summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2012-12-06 23:23:59 (EST)
committerSergey Prigogin2012-12-07 15:12:40 (EST)
commitf9e5116c6974dce9709e1c1cebd23e39036183e2 (patch)
treed0e1ecdab7774abf9386dbd59a4274ab1934da29
parent9475bffdeaaf09d297ebc945b0e9fb1bb4ad5d73 (diff)
downloadorg.eclipse.cdt-f9e5116c6974dce9709e1c1cebd23e39036183e2.zip
org.eclipse.cdt-f9e5116c6974dce9709e1c1cebd23e39036183e2.tar.gz
org.eclipse.cdt-f9e5116c6974dce9709e1c1cebd23e39036183e2.tar.bz2
Bug 379631 - code-completion of functions in using-declarations
Change-Id: Ifae9e0e790629e03c1ad93988ea535e42373d448 Reviewed-on: https://git.eclipse.org/r/9066 Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com> IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com> Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java15
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java30
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java65
3 files changed, 97 insertions, 13 deletions
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java
index 49b0c3e..da4abfe 100644
--- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java
@@ -12,10 +12,9 @@
* IBM Corporation
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
+ * Nathan Ridge
*******************************************************************************/
-package org.eclipse.cdt.ui.tests.text.contentassist2;
-
-import java.io.File;
+package org.eclipse.cdt.ui.tests.text.contentassist2;import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
@@ -28,6 +27,7 @@ import org.eclipse.jface.text.IDocument;
import org.eclipse.cdt.core.testplugin.TestScannerProvider;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
+;
/**
* A collection of code completion tests.
@@ -1365,4 +1365,13 @@ public class CompletionTests extends AbstractContentAssistTest {
final String[] expected= { "__builtin_va_arg(ap, type)" };
assertCompletionResults(fCursorOffset, expected, COMPARE_ID_STRINGS);
}
+
+ // namespace N {
+ // void foo(int);
+ // }
+ // using N::f/*cursor*/
+ public void testUsingDeclaration_Bug379631() throws Exception {
+ final String[] expected= { "foo;" };
+ assertCompletionResults(fCursorOffset, expected, COMPARE_REP_STRINGS);
+ }
} \ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java
index 4a8a10c..db8e3f3 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Sergey Prigogin, Google
* Anton Leherbauer (Wind River Systems)
+ * Nathan Ridge
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
@@ -1202,4 +1203,31 @@ public final class CHeuristicScanner implements Symbols {
}
}
+ /**
+ * A simplified interface to CHeuristicScanner's
+ * nextToken() and previousToken() methods.
+ */
+ public static class TokenStream {
+ private CHeuristicScanner fScanner;
+ private int fPos;
+ private final int fDocumentLength;
+
+ public TokenStream(IDocument document, int startPos) {
+ fScanner = new CHeuristicScanner(document);
+ fPos = startPos;
+ fDocumentLength = document.getLength();
+ }
+
+ public int nextToken() {
+ int result = fScanner.nextToken(fPos, fDocumentLength);
+ fPos = fScanner.getPosition();
+ return result;
+ }
+
+ public int previousToken() {
+ int result = fScanner.previousToken(fPos, 0);
+ fPos = fScanner.getPosition();
+ return result;
+ }
+ }
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java
index 1fdb266..54dacc3 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 QNX Software Systems and others.
+ * Copyright (c) 2007, 2012 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
+ * Nathan Ridge
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
@@ -83,6 +84,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.AccessContext;
import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory;
+import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
+import org.eclipse.cdt.internal.ui.text.Symbols;
import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
/**
@@ -91,7 +94,6 @@ import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
* @author Bryan Wilkinson
*/
public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer {
-
/**
* Default constructor is required (executable extension).
*/
@@ -153,6 +155,40 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
}
/**
+ * Checks whether the invocation offset is inside a using-declaration.
+ *
+ * @param context the invocation context
+ * @return {@code true} if the invocation offset is inside a using-declaration
+ */
+ private boolean inUsingDeclaration(CContentAssistInvocationContext context) {
+ IDocument doc = context.getDocument();
+ int offset = context.getInvocationOffset();
+
+ // Look at the tokens preceding the invocation offset.
+ CHeuristicScanner.TokenStream tokenStream = new CHeuristicScanner.TokenStream(doc, offset);
+ int token = tokenStream.previousToken();
+
+ // There may be a partially typed identifier which is being completed.
+ if (token == Symbols.TokenIDENT)
+ token = tokenStream.previousToken();
+
+ // Before that, there may be any number of "namespace::" token pairs.
+ while (token == Symbols.TokenDOUBLECOLON) {
+ token = tokenStream.previousToken();
+ if (token == Symbols.TokenUSING) { // there could also be a leading "::" for global namespace
+ return true;
+ } else if (token != Symbols.TokenIDENT) {
+ return false;
+ } else {
+ token = tokenStream.previousToken();
+ }
+ }
+
+ // Before that, there must be a "using" token.
+ return token == Symbols.TokenUSING;
+ }
+
+ /**
* Test whether the invocation offset is inside or before the preprocessor directive keyword.
*
* @param context the invocation context
@@ -377,10 +413,11 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
StringBuilder repStringBuff = new StringBuilder();
repStringBuff.append(function.getName());
+
repStringBuff.append('(');
StringBuilder dispargs = new StringBuilder(); // for the dispargString
- StringBuilder idargs = new StringBuilder(); // for the idargString
+ StringBuilder idargs = new StringBuilder(); // for the idargString
boolean hasArgs = true;
String returnTypeStr = null;
IParameter[] params = function.getParameters();
@@ -388,12 +425,12 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
for (int i = 0; i < params.length; ++i) {
IType paramType = params[i].getType();
if (i > 0) {
- dispargs.append(',');
- idargs.append(',');
- }
+ dispargs.append(',');
+ idargs.append(',');
+ }
dispargs.append(ASTTypeUtil.getType(paramType, false));
- idargs.append(ASTTypeUtil.getType(paramType, false));
+ idargs.append(ASTTypeUtil.getType(paramType, false));
String paramName = params[i].getName();
if (paramName != null && paramName.length() > 0) {
dispargs.append(' ');
@@ -439,7 +476,17 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
idStringBuff.append(')');
String idString = idStringBuff.toString();
- repStringBuff.append(')');
+ // In a using declaration, emitting parentheses after the function
+ // name is useless, since the user will just have to delete them.
+ // Instead, emitting a semicolon is useful.
+ boolean inUsingDeclaration = inUsingDeclaration(context);
+ if (inUsingDeclaration) {
+ repStringBuff.setLength(repStringBuff.length() - 1); // Remove opening parenthesis
+ repStringBuff.append(';');
+ } else {
+ repStringBuff.append(')');
+ }
+
String repString = repStringBuff.toString();
final int relevance = function instanceof ICPPMethod ?
@@ -447,7 +494,7 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
CCompletionProposal proposal = createProposal(repString, dispString, idString,
context.getCompletionNode().getLength(), image, baseRelevance + relevance, context);
if (!context.isContextInformationStyle()) {
- int cursorPosition = hasArgs ? (repString.length() - 1) : repString.length();
+ int cursorPosition = (!inUsingDeclaration && hasArgs) ? (repString.length() - 1) : repString.length();
proposal.setCursorPosition(cursorPosition);
}