mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 438549 - Fixed a regression for parameterless functions and
re-enabled parameter guessing. Change-Id: I4b6347999d675335c8e88f4bffed37fcef2e0bc3 Signed-off-by: mazab <mohamed_azab@mentor.com>
This commit is contained in:
parent
01589f6297
commit
c6dc02c94d
3 changed files with 132 additions and 8 deletions
|
@ -15,6 +15,7 @@
|
|||
* Nathan Ridge
|
||||
* Thomas Corbat (IFS)
|
||||
* Michael Woski
|
||||
* Mohamed Azab (Mentor Graphics) - Bug 438549. Add mechanism for parameter guessing.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.ui.tests.text.contentassist2;
|
||||
|
||||
|
@ -855,7 +856,7 @@ public class CompletionTests extends AbstractContentAssistTest {
|
|||
// Printer::/*cursor*/
|
||||
public void testPrivateStaticMember_109480() throws Exception {
|
||||
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=109480
|
||||
final String[] expected= { "InitPrinter()", "port" };
|
||||
final String[] expected= { "InitPrinter(port)", "port" };
|
||||
assertCompletionResults(fCursorOffset, expected, REPLACEMENT);
|
||||
}
|
||||
|
||||
|
@ -1261,7 +1262,7 @@ public class CompletionTests extends AbstractContentAssistTest {
|
|||
// }
|
||||
//};
|
||||
public void testContentAssistInDeferredClassInstance_194592() throws Exception {
|
||||
final String[] expected= { "add()" };
|
||||
final String[] expected= { "add(tOther)" };
|
||||
assertCompletionResults(fCursorOffset, expected, REPLACEMENT);
|
||||
}
|
||||
|
||||
|
@ -1428,7 +1429,7 @@ public class CompletionTests extends AbstractContentAssistTest {
|
|||
// }
|
||||
// using N::f/*cursor*/
|
||||
public void testUsingDeclaration_379631() throws Exception {
|
||||
final String[] expected= { "foo;" };
|
||||
final String[] expected= { "foo()" };
|
||||
assertCompletionResults(fCursorOffset, expected, REPLACEMENT);
|
||||
}
|
||||
|
||||
|
@ -1575,7 +1576,7 @@ public class CompletionTests extends AbstractContentAssistTest {
|
|||
// }
|
||||
// using N::fo/*cursor*/;
|
||||
public void testUsingCompletionWithFollowingSemicolon() throws Exception {
|
||||
final String[] expected = { "foo" };
|
||||
final String[] expected = { "foo()" };
|
||||
assertContentAssistResults(fCursorOffset, expected, true, REPLACEMENT);
|
||||
final String[] expectedInformation = { "null" };
|
||||
assertContentAssistResults(fCursorOffset, expectedInformation, true, CONTEXT);
|
||||
|
@ -1613,7 +1614,7 @@ public class CompletionTests extends AbstractContentAssistTest {
|
|||
setDisplayDefaultArguments(true);
|
||||
final String[] expectedDisplay = { "default_argument(int i = 23) : void" };
|
||||
assertContentAssistResults(fCursorOffset, expectedDisplay, true, DISPLAY);
|
||||
final String[] expectedReplacement = { "default_argument()" };
|
||||
final String[] expectedReplacement = { "default_argument(i)" };
|
||||
assertContentAssistResults(fCursorOffset, expectedReplacement, true, REPLACEMENT);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ public class ContentAssist2TestSuite extends TestSuite {
|
|||
addTest(CompletionTests.suite());
|
||||
addTest(CompletionTests_PlainC.suite());
|
||||
addTest(ParameterHintTests.suite());
|
||||
// addTest(CPPParameterGuessingTests.suite());
|
||||
// addTest(CParameterGuessingTests.suite());
|
||||
addTest(CPPParameterGuessingTests.suite());
|
||||
addTest(CParameterGuessingTests.suite());
|
||||
|
||||
addTest(ShowCamelCasePreferenceTest.suite());
|
||||
|
||||
|
|
|
@ -13,12 +13,15 @@
|
|||
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
|
||||
* Nathan Ridge
|
||||
* Thomas Corbat (IFS)
|
||||
* Mohamed Azab (Mentor Graphics) - Bug 438549. Add mechanism for parameter guessing.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.text.contentassist;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jface.preference.IPreferenceStore;
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
|
@ -107,17 +110,22 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
|
|||
private static final String TEMPLATE_PARAMETER_PATTERN = "template<{0}> class"; //$NON-NLS-1$;
|
||||
private static final String TYPENAME = "typename"; //$NON-NLS-1$;
|
||||
private static final String ELLIPSIS = "..."; //$NON-NLS-1$;
|
||||
private String fPrefix;
|
||||
private ArrayList<IBinding> fAvailableElements;
|
||||
|
||||
/**
|
||||
* Default constructor is required (executable extension).
|
||||
*/
|
||||
public DOMCompletionProposalComputer() {
|
||||
fPrefix = ""; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ICompletionProposal> computeCompletionProposals(
|
||||
CContentAssistInvocationContext context,
|
||||
IASTCompletionNode completionNode, String prefix) {
|
||||
fPrefix = prefix;
|
||||
initializeDefinedElements(context);
|
||||
List<ICompletionProposal> proposals = new ArrayList<>();
|
||||
|
||||
if (inPreprocessorDirective(context)) {
|
||||
|
@ -587,7 +595,122 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
|
|||
proposal.setContextInformation(info);
|
||||
}
|
||||
|
||||
proposals.add(proposal);
|
||||
/*
|
||||
* The ParameterGuessingProposal will be active if the function accepts parameters and the content assist is
|
||||
* invoked before typing any parameters. Otherwise, the normal Parameter Hint Proposal will be added.
|
||||
*/
|
||||
if (function.getParameters() != null && function.getParameters().length > 0 && isBeforeParameters(context)) {
|
||||
proposals.add(ParameterGuessingProposal.createProposal(context, fAvailableElements, proposal, function, fPrefix));
|
||||
} else {
|
||||
proposals.add(proposal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the invocation is at the function name or before typing any parameters
|
||||
*/
|
||||
private boolean isBeforeParameters(CContentAssistInvocationContext context) {
|
||||
/*
|
||||
* Invocation offset and parse offset are the same if content assist is invoked while in the function
|
||||
* name (i.e. before the '('). After that, the parse offset will indicate the end of the name part. If
|
||||
* the diff. between them is zero, then we're still inside the function name part.
|
||||
*/
|
||||
int relativeOffset = context.getInvocationOffset() - context.getParseOffset();
|
||||
if (relativeOffset == 0)
|
||||
return true;
|
||||
int startOffset = context.getParseOffset();
|
||||
String completePrefix = context.getDocument().get().substring(startOffset,
|
||||
context.getInvocationOffset());
|
||||
int lastChar = getLastNonWhitespaceChar(completePrefix);
|
||||
if (lastChar != -1 && completePrefix.charAt(lastChar) == '(')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int getLastNonWhitespaceChar(String str) {
|
||||
char[] chars = str.toCharArray();
|
||||
for (int i = chars.length - 1; i >= 0; i--) {
|
||||
if (!Character.isWhitespace(chars[i]))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the list of defined elements at the start of the current statement.
|
||||
*/
|
||||
private void initializeDefinedElements(CContentAssistInvocationContext context) {
|
||||
/*
|
||||
* Get all defined elements before the start of the statement.
|
||||
* ex1: int a = foo(
|
||||
* ^ --> We don't want 'a' as a suggestion.
|
||||
* ex2: char* foo(int a, int b) {return NULL;}
|
||||
* void bar(char* name) {}
|
||||
* ...
|
||||
* bar( foo(
|
||||
* ^ --> If this offset is used, the only defined name will be "bar(char*)".
|
||||
*/
|
||||
int startOffset = getStatementStartOffset(context.getDocument(),
|
||||
context.getParseOffset() - fPrefix.length());
|
||||
Map<String, IBinding> elementsMap = new HashMap<>();
|
||||
IASTCompletionNode node = null;
|
||||
// Create a content assist context that points to the start of the statement.
|
||||
CContentAssistInvocationContext newContext = new CContentAssistInvocationContext(
|
||||
context.getViewer(), startOffset, context.getEditor(), true, false);
|
||||
try {
|
||||
node = newContext.getCompletionNode();
|
||||
if (node != null) {
|
||||
IASTTranslationUnit tu = node.getTranslationUnit();
|
||||
IASTName[] names = node.getNames();
|
||||
for (IASTName name : names) {
|
||||
IASTCompletionContext astContext = name.getCompletionContext();
|
||||
if (astContext != null) {
|
||||
IBinding[] bindings = astContext.findBindings(name, true);
|
||||
if (bindings != null) {
|
||||
AccessContext accessibilityContext = new AccessContext(name);
|
||||
for (IBinding binding : bindings) {
|
||||
// Consider only variables that are part of the current translation unit and fields.
|
||||
if (binding instanceof IVariable
|
||||
&& accessibilityContext.isAccessible(binding)
|
||||
&& !elementsMap.containsKey(binding.getName())) {
|
||||
if (binding instanceof ICPPField) {
|
||||
elementsMap.put(binding.getName(), binding);
|
||||
} else {
|
||||
IASTName[] declarations = tu.getDeclarationsInAST(binding);
|
||||
if (declarations.length != 0)
|
||||
elementsMap.put(binding.getName(), binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
fAvailableElements = new ArrayList<>(elementsMap.values());
|
||||
newContext.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position after last semicolon or opening or closing brace before the given offset.
|
||||
*/
|
||||
private static int getStatementStartOffset(IDocument doc, int offset) {
|
||||
if (offset != 0) {
|
||||
String docPart;
|
||||
try {
|
||||
docPart = doc.get(0, offset);
|
||||
int index = docPart.lastIndexOf(';');
|
||||
int tmpIndex = docPart.lastIndexOf('{');
|
||||
index = (index < tmpIndex) ? tmpIndex : index;
|
||||
tmpIndex = docPart.lastIndexOf('}');
|
||||
index = (index < tmpIndex) ? tmpIndex : index;
|
||||
return index + 1;
|
||||
} catch (BadLocationException e) {
|
||||
CUIPlugin.log(e);
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
private boolean skipDefaultedParameter(IParameter param) {
|
||||
|
|
Loading…
Add table
Reference in a new issue