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 09b6af99549..0a8e7b7c24c 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 @@ -719,6 +719,16 @@ public class CompletionTests extends CompletionTestBase { final String[] expected = { "method", "datamem" }; assertMinimumCompletionResults(fCursorOffset, expected, REPLACEMENT); } + + // struct Waldo { + // void find(); + // }; + // void Waldo::f/*cursor*/ + public void testRegression_395562() throws Exception { + // Should include parentheses in replacement string when completing + // out-of-line method definition. + assertCompletionResults(new String[] { "find()" }); + } // typedef struct { // int sx; @@ -1236,10 +1246,10 @@ public class CompletionTests extends CompletionTestBase { public void testDestructorDefinition_456293() throws Exception { final String[] expectedDisplay = { "~Waldo(void)" }; assertCompletionResults(fCursorOffset, expectedDisplay, DISPLAY); - final String[] expectedReplacement = { "Waldo" }; + final String[] expectedReplacement = { "Waldo()" }; assertCompletionResults(fCursorOffset, expectedReplacement, REPLACEMENT); } - + // template struct vector { // typedef T value_type; // void push_back(const value_type& value) {} 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 bdf4c766438..b4b55fad94c 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 @@ -529,7 +529,7 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer return relevance; } - // Returns whether a function name being completed could be a call that function. + // Returns whether a function name being completed could be a call to that function. private boolean canBeCall(IFunction function, IASTCompletionContext astContext, CContentAssistInvocationContext cContext) { // Can't have a call in a using-directive. @@ -548,6 +548,23 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer return true; } + // Returns whether a function name being completed could be a definition of that function. + private boolean canBeDefinition(IFunction function, IASTCompletionContext astContext) { + if (!(astContext instanceof IASTName)) { + return true; + } + // If content assist is invoked while completing the destructor name in an + // out-of-line destructor definition, the parser doesn't have enough information + // to recognize that this is a function definition, and so getRoleOfName() will + // incorrectly return r_reference. Since destructors are rarely referred to + // explicitly, just assume destructor name is a definition. + if (function instanceof ICPPMethod && ((ICPPMethod) function).isDestructor()) { + return true; + } + IASTName name = (IASTName) astContext; + return name.getRoleOfName(false) == IASTNameOwner.r_definition; + } + private String getFunctionNameForReplacement(IFunction function, IASTCompletionContext astContext) { // If we are completiong a destructor name ... if (function instanceof ICPPMethod && ((ICPPMethod) function).isDestructor()) { @@ -574,6 +591,8 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer repStringBuff.append(getFunctionNameForReplacement(function, astContext)); boolean canBeCall = canBeCall(function, astContext, cContext); + boolean canBeDefinition = canBeDefinition(function, astContext); + boolean wantParens = canBeCall || canBeDefinition; StringBuilder dispArgs = new StringBuilder(); // For the dispArgString StringBuilder idArgs = new StringBuilder(); // For the idArgString @@ -652,8 +671,8 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer boolean inUsingDeclaration = cContext.isInUsingDirective(); - if (canBeCall && !cContext.isFollowedByOpeningParen()) { - // If we might be calling the function in this context, assume we are + if (wantParens && !cContext.isFollowedByOpeningParen()) { + // If we might be calling or defining the function in this context, assume we are // (since that's the most common case) and emit parentheses. repStringBuff.append('('); repStringBuff.append(')');