Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGayan Perera2021-02-07 20:09:28 +0000
committerVikas Chandra2021-02-11 12:54:24 +0000
commitd890922f01a874dd5cafce5db8dfb5bae47b2f3c (patch)
tree1567e24a493e52db624cce2bad1f2279c7f4e80d
parent4c1496dfbd11b3ad81e483bf468882e56f00e870 (diff)
downloadeclipse.jdt.core-d890922f01a874dd5cafce5db8dfb5bae47b2f3c.tar.gz
eclipse.jdt.core-d890922f01a874dd5cafce5db8dfb5bae47b2f3c.tar.xz
eclipse.jdt.core-d890922f01a874dd5cafce5db8dfb5bae47b2f3c.zip
Bug570593 : Fix completions on nested parameterized type definitions
When invoking on nested parameterized type definitions like Map<Long, Map<K,V>> completions were not provided to nested parameterized type indexes other than the last. This issue fix that problem by properly returning the correct parent node from CompletionNodeDetector Change-Id: I6bf59ba4e5d2af82f71486cc6d30ec4880bde080 Signed-off-by: Gayan Perera <gayanper@gmail.com>
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java287
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java14
2 files changed, 301 insertions, 0 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
index f38b48b005..bb6c03f1e4 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
@@ -3760,4 +3760,291 @@ public void testCompletionConstructorRelevance() throws JavaModelException {
"LinkedBlockingQueue[CONSTRUCTOR_INVOCATION]{(), Ljava.util.concurrent.LinkedBlockingQueue;, (Ljava.util.Collection<+TE;>;)V, LinkedBlockingQueue, (arg0), " + expectedConstructorRelevance + "}",
requestor.getResults());
}
+
+public void testBug570593_SingleTypeParam() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.List;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private List<XBug570593>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_MultipleTypeParams_OnFirstTP() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private Map<XBug570593,V>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_MultipleTypeParams_OnSecondTP() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private Map<Long,XBug570593>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_SingleTypeParam_NestedSingleParam() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.List;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private List<List<XBug570593>>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_SingleTypeParam_NestedMultiParams_OnFirst() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.List;\n" +
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private List<Map<XBug570593,V>>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_SingleTypeParam_NestedMultiParams_OnSecond() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.List;\n" +
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private List<Map<Long,XBug570593>>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_MultiTypeParam_OnFirst_NestedSingleParam() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.List;\n" +
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private Map<List<XBug570593>,V>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_MultiTypeParam_OnSecond_NestedSingleParam() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.List;\n" +
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private Map<Long,List<XBug570593>>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_MultiTypeParam_NestedMultiParam_OnFirst() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.List;\n" +
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private Map<Long,Map<XBug570593,R>>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
+public void testBug570593_MultiTypeParam_NestedMultiParam_OnSecond() throws JavaModelException {
+ this.workingCopies = new ICompilationUnit[2];
+ this.workingCopies[0] = getWorkingCopy(
+ "/Completion/src/Bug570593.java",
+ "import java.util.List;\n" +
+ "import java.util.Map;\n" +
+ "\n" +
+ "public class Bug570593 {\n" +
+ " private Map<Long,Map<String,XBug570593>>\n" +
+ "}");
+ this.workingCopies[1] = getWorkingCopy(
+ "/Completion/src/XBug570593Type.java",
+ "\n" +
+ "public class XBug570593Type {\n" +
+ "}");
+
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+ requestor.allowAllRequiredProposals();
+
+ String str = this.workingCopies[0].getSource();
+ String completeBehind = "XBug570593";
+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, new NullProgressMonitor());
+
+ assertResults(
+ "XBug570593Type[TYPE_REF]{XBug570593Type, , LXBug570593Type;, null, null, 72}",
+ requestor.getResults());
+}
+
}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
index a8f214a300..04befdd0e7 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
@@ -13,6 +13,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.codeassist.complete;
+import java.util.stream.Stream;
+
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -381,8 +383,20 @@ public class CompletionNodeDetector extends ASTVisitor {
&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfTrue == this.searchedNode)
&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfFalse == this.searchedNode)) {
this.parent = astNode;
+ return;
}
}
+
+ // when we have recovering node like private Map<String, Function<I,R>> the visitor actually endVisit on I and
+ // R when completions are requested at I. The above logic actually identify R as a parent since the R is visited
+ // and endVisited after founding that I was the searched node. This happens for all type parameters which are at
+ // index where index < n.
+ // Therefore we need to following check to fix the parent by setting the parent to the node which represents
+ // Map<String, Function<Long,$>> when we are invoking endVisit.
+ if(this.result && astNode instanceof ParameterizedSingleTypeReference &&
+ Stream.of(((ParameterizedSingleTypeReference) astNode).typeArguments).anyMatch(n -> n == this.searchedNode)) {
+ this.parent = astNode;
+ }
}
private boolean visit(ASTNode astNode) {
if(astNode == this.searchedNode) {

Back to the top