From 6bca4db0cd5ec25bddb71d9e34edc00672bcf110 Mon Sep 17 00:00:00 2001 From: Lucas Bullen Date: Mon, 4 Jun 2018 15:22:13 -0400 Subject: [PATCH] #79 - Prevent competion assist in comments - Check to see if the cursor is in a Rust comment or not before returning snippet completions Signed-off-by: Lucas Bullen --- .../META-INF/MANIFEST.MF | 3 +- .../org/eclipse/corrosion/tests/AllTests.java | 2 +- .../TestSnippetContentAssistProcessor.java | 97 +++++++++++++++++++ org.eclipse.corrosion/META-INF/MANIFEST.MF | 1 + .../SnippetContentAssistProcessor.java | 14 ++- 5 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 org.eclipse.corrosion.tests/src/org/eclipse/corrosion/tests/TestSnippetContentAssistProcessor.java diff --git a/org.eclipse.corrosion.tests/META-INF/MANIFEST.MF b/org.eclipse.corrosion.tests/META-INF/MANIFEST.MF index bd773c7..958c627 100644 --- a/org.eclipse.corrosion.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.corrosion.tests/META-INF/MANIFEST.MF @@ -23,6 +23,7 @@ Require-Bundle: org.eclipse.corrosion;bundle-version="0.1.0", org.eclipse.core.expressions, org.eclipse.search, org.eclipse.ui.console, - org.eclipse.debug.ui;bundle-version="3.13.0" + org.eclipse.debug.ui;bundle-version="3.13.0", + org.eclipse.jface.text;bundle-version="3.13.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy diff --git a/org.eclipse.corrosion.tests/src/org/eclipse/corrosion/tests/AllTests.java b/org.eclipse.corrosion.tests/src/org/eclipse/corrosion/tests/AllTests.java index 5c1608b..ce7d913 100644 --- a/org.eclipse.corrosion.tests/src/org/eclipse/corrosion/tests/AllTests.java +++ b/org.eclipse.corrosion.tests/src/org/eclipse/corrosion/tests/AllTests.java @@ -19,7 +19,7 @@ @RunWith(Suite.class) @SuiteClasses({ TestIDEIntegration.class, TestSyntaxHighlighting.class, TestLSPIntegration.class, TestNewCargoProjectWizard.class, TestRunConfiguration.class, TestExportCargoProjectWizard.class, - TestPerspective.class, TestLSPExtensions.class }) + TestPerspective.class, TestLSPExtensions.class, TestSnippetContentAssistProcessor.class }) public class AllTests { } diff --git a/org.eclipse.corrosion.tests/src/org/eclipse/corrosion/tests/TestSnippetContentAssistProcessor.java b/org.eclipse.corrosion.tests/src/org/eclipse/corrosion/tests/TestSnippetContentAssistProcessor.java new file mode 100644 index 0000000..010f26a --- /dev/null +++ b/org.eclipse.corrosion.tests/src/org/eclipse/corrosion/tests/TestSnippetContentAssistProcessor.java @@ -0,0 +1,97 @@ +/********************************************************************* + * Copyright (c) 2018 Red Hat Inc. and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Lucas Bullen (Red Hat Inc.) - Initial implementation + *******************************************************************************/ +package org.eclipse.corrosion.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.corrosion.snippet.SnippetContentAssistProcessor; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.lsp4e.operations.completion.LSCompletionProposal; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.texteditor.ITextEditor; +import org.junit.Test; + +@SuppressWarnings("restriction") +public class TestSnippetContentAssistProcessor extends AbstractCorrosionTest { + + @Test + public void testCompletionsPresent() throws Exception { + validateCompletionProposals("println", new String[] { "println!(\"$1\", $0)" }); + } + + @Test + public void testCompletionsLimited() throws Exception { + validateCompletionProposals("noExpectedCompletion", null); + } + + @Test + public void testSingleLineComment() throws Exception { + validateCompletionProposals("// println", null); + // With prefix + validateCompletionProposals("not a comment // println", null); + // With multiline + validateCompletionProposals("not a comment \n also not a comment // println", null); + // Comment on an above line + validateCompletionProposals("// a comment \n println", new String[] { "println!(\"$1\", $0)" }); + } + + @Test + public void testMultiLineComment() throws Exception { + validateCompletionProposals("/* println", null); + // With prefix + validateCompletionProposals("not a comment /* println", null); + // With multiline + validateCompletionProposals("not a comment \n not a comment /* println", null); + // With mulitple opens + validateCompletionProposals("not a comment \n not a comment /* in /* /* println", null); + // Previous closure + validateCompletionProposals("/* in a comment */ not a comment /* println", null); + // Previous closue no open + validateCompletionProposals("/* in a comment */ println", new String[] { "println!(\"$1\", $0)" }); + // Previous closue new line + validateCompletionProposals("/* in a comment */ \n println", new String[] { "println!(\"$1\", $0)" }); + + } + + private void validateCompletionProposals(String text, String[] expectedProposalTexts) + throws IOException, CoreException { + IProject project = getProject("basic"); + IFile file = project.getFolder("src").getFile("main.rs"); + IEditorPart editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + ((ITextEditor) editor).getDocumentProvider().getDocument(editor.getEditorInput()).set(text); + + ICompletionProposal[] proposals = (new SnippetContentAssistProcessor()).computeCompletionProposals( + (ITextViewer) editor.getAdapter(ITextOperationTarget.class), text.length() - 1); + if (expectedProposalTexts == null) { + assertTrue(proposals == null || proposals.length == 0); + return; + } + assertNotNull(proposals); + for (int i = 0; i < proposals.length; i++) { + assertEquals(((LSCompletionProposal) proposals[i]).getItem().getTextEdit().getNewText(), + expectedProposalTexts[i]); + } + } + +} \ No newline at end of file diff --git a/org.eclipse.corrosion/META-INF/MANIFEST.MF b/org.eclipse.corrosion/META-INF/MANIFEST.MF index a600543..20b7eaf 100644 --- a/org.eclipse.corrosion/META-INF/MANIFEST.MF +++ b/org.eclipse.corrosion/META-INF/MANIFEST.MF @@ -40,5 +40,6 @@ Export-Package: org.eclipse.corrosion;x-friends:="org.eclipse.corrosion.tests", org.eclipse.corrosion.edit;x-friends:="org.eclipse.corrosion.tests", org.eclipse.corrosion.extensions;x-friends:="org.eclipse.corrosion.tests", org.eclipse.corrosion.run;x-friends:="org.eclipse.corrosion.tests", + org.eclipse.corrosion.snippet;x-friends:="org.eclipse.corrosion.tests", org.eclipse.corrosion.wizards.export;x-friends:="org.eclipse.corrosion.tests", org.eclipse.corrosion.wizards.newCargo;x-friends:="org.eclipse.corrosion.tests" diff --git a/org.eclipse.corrosion/src/org/eclipse/corrosion/snippet/SnippetContentAssistProcessor.java b/org.eclipse.corrosion/src/org/eclipse/corrosion/snippet/SnippetContentAssistProcessor.java index 47aeeed..710b5f7 100644 --- a/org.eclipse.corrosion/src/org/eclipse/corrosion/snippet/SnippetContentAssistProcessor.java +++ b/org.eclipse.corrosion/src/org/eclipse/corrosion/snippet/SnippetContentAssistProcessor.java @@ -43,9 +43,12 @@ @SuppressWarnings("restriction") public class SnippetContentAssistProcessor implements IContentAssistProcessor { - + private static final String SINGLE_LINE_COMMENT = "(?s).*(\\/\\/[^\\n]*)"; //$NON-NLS-1$ + private static final String MULTI_LINE_COMMENT = "(?s).*\\/\\*(.(?!\\*\\/))*"; //$NON-NLS-1$ private static final String ENDS_WITH_WORD = "(?\\s*).*?(?\\w*)"; //$NON-NLS-1$ private static final Pattern ENDS_WITH_WORD_PATTERN = Pattern.compile(ENDS_WITH_WORD); + private static final Pattern SINGLE_LINE_COMMENT_PATTERN = Pattern.compile(SINGLE_LINE_COMMENT); + private static final Pattern MULTI_LINE_COMMENT_PATTERN = Pattern.compile(MULTI_LINE_COMMENT); private static final List snippets = new ArrayList<>(); static { JsonArray snippetArray = null; @@ -84,6 +87,9 @@ private static void addSnippet(Snippet snippet) { @Override public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { IDocument document = viewer.getDocument(); String textToOffset = document.get().substring(0, offset); + if (isOffsetInComment(textToOffset)) { + return null; + } Matcher matcher = ENDS_WITH_WORD_PATTERN.matcher(textToOffset.substring(textToOffset.lastIndexOf('\n') + 1)); matcher.matches(); @@ -101,6 +107,12 @@ private static void addSnippet(Snippet snippet) { return proposals.toArray(new ICompletionProposal[proposals.size()]); } + private boolean isOffsetInComment(String textToOffset) { + Matcher singleLineCommentMatcher = SINGLE_LINE_COMMENT_PATTERN.matcher(textToOffset); + Matcher multiLineCommentMatcher = MULTI_LINE_COMMENT_PATTERN.matcher(textToOffset); + return singleLineCommentMatcher.matches() || multiLineCommentMatcher.matches(); + } + @Override public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { return null; }