1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 06:32:10 +02:00

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>
This commit is contained in:
Nathan Ridge 2012-12-06 23:23:59 -05:00 committed by Sergey Prigogin
parent 032c010a82
commit d159cd9545
3 changed files with 97 additions and 13 deletions

View file

@ -12,10 +12,9 @@
* IBM Corporation * IBM Corporation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion) * Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.ui.tests.text.contentassist2; package org.eclipse.cdt.ui.tests.text.contentassist2;import java.io.File;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; 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.TestScannerProvider;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
;
/** /**
* A collection of code completion tests. * A collection of code completion tests.
@ -1365,4 +1365,13 @@ public class CompletionTests extends AbstractContentAssistTest {
final String[] expected= { "__builtin_va_arg(ap, type)" }; final String[] expected= { "__builtin_va_arg(ap, type)" };
assertCompletionResults(fCursorOffset, expected, COMPARE_ID_STRINGS); 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);
}
} }

View file

@ -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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation * IBM Corporation - initial API and implementation
* Sergey Prigogin, Google * Sergey Prigogin, Google
* Anton Leherbauer (Wind River Systems) * Anton Leherbauer (Wind River Systems)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.ui.text; 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;
}
}
} }

View file

@ -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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -11,6 +11,7 @@
* Anton Leherbauer (Wind River Systems) * Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion) * Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist; 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.dom.parser.cpp.semantics.AccessContext;
import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory; 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; import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
/** /**
@ -91,7 +94,6 @@ import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
* @author Bryan Wilkinson * @author Bryan Wilkinson
*/ */
public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer { public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer {
/** /**
* Default constructor is required (executable extension). * Default constructor is required (executable extension).
*/ */
@ -152,6 +154,40 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
return proposals; return proposals;
} }
/**
* 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. * Test whether the invocation offset is inside or before the preprocessor directive keyword.
* *
@ -377,10 +413,11 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
StringBuilder repStringBuff = new StringBuilder(); StringBuilder repStringBuff = new StringBuilder();
repStringBuff.append(function.getName()); repStringBuff.append(function.getName());
repStringBuff.append('('); repStringBuff.append('(');
StringBuilder dispargs = new StringBuilder(); // for the dispargString StringBuilder dispargs = new StringBuilder(); // for the dispargString
StringBuilder idargs = new StringBuilder(); // for the idargString StringBuilder idargs = new StringBuilder(); // for the idargString
boolean hasArgs = true; boolean hasArgs = true;
String returnTypeStr = null; String returnTypeStr = null;
IParameter[] params = function.getParameters(); IParameter[] params = function.getParameters();
@ -388,12 +425,12 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
for (int i = 0; i < params.length; ++i) { for (int i = 0; i < params.length; ++i) {
IType paramType = params[i].getType(); IType paramType = params[i].getType();
if (i > 0) { if (i > 0) {
dispargs.append(','); dispargs.append(',');
idargs.append(','); idargs.append(',');
} }
dispargs.append(ASTTypeUtil.getType(paramType, false)); dispargs.append(ASTTypeUtil.getType(paramType, false));
idargs.append(ASTTypeUtil.getType(paramType, false)); idargs.append(ASTTypeUtil.getType(paramType, false));
String paramName = params[i].getName(); String paramName = params[i].getName();
if (paramName != null && paramName.length() > 0) { if (paramName != null && paramName.length() > 0) {
dispargs.append(' '); dispargs.append(' ');
@ -439,7 +476,17 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
idStringBuff.append(')'); idStringBuff.append(')');
String idString = idStringBuff.toString(); 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(); String repString = repStringBuff.toString();
final int relevance = function instanceof ICPPMethod ? final int relevance = function instanceof ICPPMethod ?
@ -447,7 +494,7 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
CCompletionProposal proposal = createProposal(repString, dispString, idString, CCompletionProposal proposal = createProposal(repString, dispString, idString,
context.getCompletionNode().getLength(), image, baseRelevance + relevance, context); context.getCompletionNode().getLength(), image, baseRelevance + relevance, context);
if (!context.isContextInformationStyle()) { if (!context.isContextInformationStyle()) {
int cursorPosition = hasArgs ? (repString.length() - 1) : repString.length(); int cursorPosition = (!inUsingDeclaration && hasArgs) ? (repString.length() - 1) : repString.length();
proposal.setCursorPosition(cursorPosition); proposal.setCursorPosition(cursorPosition);
} }