Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2017-11-06 02:06:42 +0000
committerNathan Ridge2017-11-13 18:22:26 +0000
commit301de3d40ea15dfc84a90c227db62514cd2dc578 (patch)
tree5f01ce1f4ffcee2282133ebf81f376f6afed36fc
parentb090f32e646527db07ab1b1b4f2374256ec43af9 (diff)
downloadorg.eclipse.cdt-301de3d40ea15dfc84a90c227db62514cd2dc578.tar.gz
org.eclipse.cdt-301de3d40ea15dfc84a90c227db62514cd2dc578.tar.xz
org.eclipse.cdt-301de3d40ea15dfc84a90c227db62514cd2dc578.zip
Bug 522010 - Completion of non-type template parameter in ambiguous template argument
This works around the fact that the optimization introduced in bug 316704 inteferes with the mechanism for offering completions for both alternatives in an ambiguous context. Change-Id: Ibe14c1b4f2f9c9b3394d4635c87424a25fbd7a53
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTCompletionNode.java25
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTCompletionNode.java37
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java9
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java8
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java16
-rw-r--r--lrparser/org.eclipse.cdt.core.lrparser/src/org/eclipse/cdt/core/dom/lrparser/action/ASTCompletionNode.java27
6 files changed, 111 insertions, 11 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTCompletionNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTCompletionNode.java
index 607379e3d8f..733ecf946bc 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTCompletionNode.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTCompletionNode.java
@@ -20,7 +20,7 @@ import org.eclipse.cdt.core.parser.IToken;
*/
public class ASTCompletionNode implements IASTCompletionNode {
private final IToken completionToken;
- private final List<IASTName> names = new ArrayList<>();
+ private final List<CompletionNameEntry> entries = new ArrayList<>();
private final IASTTranslationUnit translationUnit;
public ASTCompletionNode(IToken completionToken, IASTTranslationUnit translationUnit) {
@@ -29,7 +29,7 @@ public class ASTCompletionNode implements IASTCompletionNode {
}
public void addName(IASTName name) {
- names.add(name);
+ entries.add(new CompletionNameEntry(name, name.getParent()));
}
@Override
@@ -43,8 +43,27 @@ public class ASTCompletionNode implements IASTCompletionNode {
}
@Override
+ public boolean containsName(IASTName name) {
+ for (CompletionNameEntry entry : entries) {
+ if (entry.fName == name) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
public IASTName[] getNames() {
- return names.toArray(new IASTName[names.size()]);
+ IASTName[] names = new IASTName[entries.size()];
+ for (int i = 0; i < entries.size(); ++i) {
+ names[i] = entries.get(i).fName;
+ }
+ return names;
+ }
+
+ @Override
+ public CompletionNameEntry[] getEntries() {
+ return entries.toArray(new CompletionNameEntry[entries.size()]);
}
@Override
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTCompletionNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTCompletionNode.java
index 237b49d38ee..8c9d983ae32 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTCompletionNode.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTCompletionNode.java
@@ -26,6 +26,25 @@ package org.eclipse.cdt.core.dom.ast;
*/
public interface IASTCompletionNode {
/**
+ * Represents a name that fits in this context, and its parent.
+ * The parent is stored separately because two entries can have
+ * the same name but different parents. (This is due to the
+ * parser sometimes re-using nodes between alternatives in an
+ * ambiguous node.)
+ *
+ * @since 6.4
+ */
+ public class CompletionNameEntry {
+ public CompletionNameEntry(IASTName name, IASTNode parent) {
+ fName = name;
+ fParent = parent;
+ }
+
+ public IASTName fName;
+ public IASTNode fParent;
+ }
+
+ /**
* If the point of completion was at the end of a potential identifier, this
* string contains the text of that identifier.
*
@@ -39,9 +58,27 @@ public interface IASTCompletionNode {
public int getLength();
/**
+ * Returns true if this completion node contains a {@link CompletionNameEntry}
+ * with the given name.
+ *
+ * @since 6.4
+ */
+ public boolean containsName(IASTName name);
+
+ /**
* Returns a list of names that fit in this context.
+ * If doing computations based on the name's parent, prefer calling getEntries() instead
+ * and obtaining the parent from there.
*/
public IASTName[] getNames();
+
+ /**
+ * Returns a list of names that fir in this context, along with their parents.
+ * See {@link CompletionNameEntry} for more details.
+ *
+ * @since 6.4
+ */
+ public CompletionNameEntry[] getEntries();
/**
* Returns the translation unit for this completion.
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
index a2b01fec885..2fc22a307cb 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
@@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier;
@@ -785,6 +786,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
name = namedTypeSpec.getName();
if (name.contains(typeId)) {
idExpression = setRange(getNodeFactory().newIdExpression(name), name);
+
+ // If the name was one of the completion names, add it to the completion
+ // node again now that it has a new parent. This ensures that completion
+ // proposals are offered for both contexts that the name appears in.
+ ASTCompletionNode completionNode = (ASTCompletionNode) getCompletionNode();
+ if (completionNode != null && completionNode.containsName(name)) {
+ completionNode.addName(name);
+ }
}
}
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 ebe55719a8f..59cf69b2312 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
@@ -2032,4 +2032,12 @@ public class CompletionTests extends CompletionTestBase {
public void testPartialSpecializationWithDeferredClassInstance_456224b() throws Exception {
assertCompletionResults(new String[] { "Result" });
}
+
+ // template<int TestParam>
+ // struct A {
+ // using type_t = A<Te/*cursor*/>
+ // };
+ public void testNonTypeTemplateParameterCompletion_522010() throws Exception {
+ assertCompletionResults(new String[] { "TestParam" });
+ }
}
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 71f17585c8d..8016c3db7a7 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
@@ -36,11 +36,13 @@ import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.swt.graphics.Image;
import org.eclipse.cdt.core.dom.ILinkage;
+import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
import org.eclipse.cdt.core.dom.ast.IASTCompletionNode;
+import org.eclipse.cdt.core.dom.ast.IASTCompletionNode.CompletionNameEntry;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionStyleMacroParameter;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
@@ -160,9 +162,10 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
}
} else {
boolean handleMacros= false;
- IASTName[] names = completionNode.getNames();
+ CompletionNameEntry[] entries = ((ASTCompletionNode) completionNode).getEntries();
- for (IASTName name : names) {
+ for (CompletionNameEntry entry : entries) {
+ IASTName name = entry.fName;
if (name.getTranslationUnit() == null && !(name instanceof IASTInactiveCompletionName)) {
// The node isn't properly hooked up, must have backtracked out of this node.
// Inactive completion names are special in that they are not hooked up
@@ -171,7 +174,7 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
continue;
}
- IASTCompletionContext astContext = name.getCompletionContext();
+ IASTCompletionContext astContext = getCompletionContext(name, entry.fParent);
if (astContext == null) {
continue;
} else if (astContext instanceof IASTIdExpression
@@ -203,6 +206,13 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
return proposals;
}
+ private static IASTCompletionContext getCompletionContext(IASTName name, IASTNode parent) {
+ if (parent instanceof IASTCompletionContext) {
+ return (IASTCompletionContext) parent;
+ }
+ return name.getCompletionContext();
+ }
+
/**
* Checks whether the invocation offset is inside or before the preprocessor directive keyword.
*
diff --git a/lrparser/org.eclipse.cdt.core.lrparser/src/org/eclipse/cdt/core/dom/lrparser/action/ASTCompletionNode.java b/lrparser/org.eclipse.cdt.core.lrparser/src/org/eclipse/cdt/core/dom/lrparser/action/ASTCompletionNode.java
index 6ac50613317..b021de30609 100644
--- a/lrparser/org.eclipse.cdt.core.lrparser/src/org/eclipse/cdt/core/dom/lrparser/action/ASTCompletionNode.java
+++ b/lrparser/org.eclipse.cdt.core.lrparser/src/org/eclipse/cdt/core/dom/lrparser/action/ASTCompletionNode.java
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.core.dom.lrparser.action;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.IASTCompletionNode;
@@ -38,7 +38,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
*/
public class ASTCompletionNode implements IASTCompletionNode {
- private final List<IASTName> names = new LinkedList<IASTName>();
+ private final List<CompletionNameEntry> entries = new ArrayList<>();
private final String prefix;
private IASTTranslationUnit tu;
@@ -62,7 +62,7 @@ public class ASTCompletionNode implements IASTCompletionNode {
public void addName(IASTName name) {
- names.add(name);
+ entries.add(new CompletionNameEntry(name, name.getParent()));
}
@@ -77,7 +77,11 @@ public class ASTCompletionNode implements IASTCompletionNode {
@Override
public IASTName[] getNames() {
- return names.toArray(new IASTName[names.size()]);
+ IASTName[] names = new IASTName[entries.size()];
+ for (int i = 0; i < entries.size(); ++i) {
+ names[i] = entries.get(i).fName;
+ }
+ return names;
}
@@ -100,6 +104,19 @@ public class ASTCompletionNode implements IASTCompletionNode {
public IASTTranslationUnit getTranslationUnit() {
return tu;
}
-
+ @Override
+ public boolean containsName(IASTName name) {
+ for (CompletionNameEntry entry : entries) {
+ if (entry.fName == name) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public CompletionNameEntry[] getEntries() {
+ return entries.toArray(new CompletionNameEntry[entries.size()]);
+ }
}

Back to the top