diff options
| author | Stephan Herrmann | 2018-10-05 22:00:35 +0000 |
|---|---|---|
| committer | Stephan Herrmann | 2021-04-24 22:24:08 +0000 |
| commit | f19d20e6a917016c9405829df3732ebb1d810478 (patch) | |
| tree | b0201ee70eddc5979077ecd4c5cbb8ad728946a5 | |
| parent | e9a317e2800418a41c182dccb7408f45ac4aaecf (diff) | |
| download | eclipse.jdt.core-f19d20e6a917016c9405829df3732ebb1d810478.tar.gz eclipse.jdt.core-f19d20e6a917016c9405829df3732ebb1d810478.tar.xz eclipse.jdt.core-f19d20e6a917016c9405829df3732ebb1d810478.zip | |
Bug 539617 - Content assist not working for constructors in lamdaI20210425-1800
expressions
Change-Id: Ib34293ac03315f47788b3a3ff50be0376d562913
Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/130512
Tested-by: JDT Bot <jdt-bot@eclipse.org>
Reviewed-by: Stephan Herrmann <stephan.herrmann@berlin.de>
7 files changed, 98 insertions, 50 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest.java index 53972ce457..2d4b852317 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest.java @@ -8917,9 +8917,9 @@ public void testBug346454b(){ String testName = "<complete after diamond type>"; String completeBehind = "new Test<>().new T2<>("; - String expectedCompletionNodeToString = "<CompleteOnName:>"; + String expectedCompletionNodeToString = "<CompleteOnQualifiedAllocationExpression:new Test<>().new T2<>(<CompleteOnName:>)>"; String completionIdentifier = ""; - String expectedReplacedSource = ""; + String expectedReplacedSource = "new Test<>().new T2<>()"; String expectedUnitDisplayString = "public class Test<T> {\n" + " public class T2<Z> {\n" + @@ -8929,7 +8929,7 @@ public void testBug346454b(){ " public Test() {\n" + " }\n" + " public void foo() {\n" + - " Test<String>.T2<String> t = new Test<>().new T2<>(<CompleteOnName:>);\n" + // outer allocation is illegal to begin with + " Test<String>.T2<String> t = <CompleteOnQualifiedAllocationExpression:new Test<>().new T2<>(<CompleteOnName:>)>;\n" + " }\n" + "}\n"; diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java index d61c57df00..ec723935d3 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java @@ -23519,7 +23519,8 @@ public void testBug346454f() throws JavaModelException { int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "", // nothing useful can be proposed since type inference will inevitably fail on "new Test<>()." + "T2[METHOD_REF<CONSTRUCTOR>]{, Lpack.Test<Ljava.lang.Object;>.T2<>;, (TZ;)V, T2, (z), " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED) + "}\n" + + "Test<java.lang.Object>.T2<>[ANONYMOUS_CLASS_DECLARATION]{, Lpack.Test<Ljava.lang.Object;>.T2<>;, (TZ;)V, null, (z), " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED) + "}", requestor.getResults()); } finally { // Restore compliance settings. @@ -23565,7 +23566,8 @@ public void testBug346454g() throws JavaModelException { int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "", // nothing useful can be proposed since type inference will inevitably fail on "new pack.Test<>()." + "T2[METHOD_REF<CONSTRUCTOR>]{, Lpack.Test<>.T2<>;, (TZ;)V, T2, (z), " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED) + "}\n" + + "Test<>.T2<>[ANONYMOUS_CLASS_DECLARATION]{, Lpack.Test<>.T2<>;, (TZ;)V, null, (z), " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED) + "}", requestor.getResults()); } finally { // Restore compliance settings. @@ -23660,7 +23662,8 @@ public void testBug346454i() throws JavaModelException { int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - "", // nothing useful can be proposed since enclosing instance "new <String> Test<>()' is illegal (and thus can never be type infered) + "T2[METHOD_REF<CONSTRUCTOR>]{, Lpack.Test<>.T2<>;, (TU;)V, T2, (u), " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED) + "}\n" + + "Test<>.T2<>[ANONYMOUS_CLASS_DECLARATION]{, Lpack.Test<>.T2<>;, (TU;)V, null, (u), " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED) + "}", requestor.getResults()); } finally { // Restore compliance settings. @@ -23705,22 +23708,8 @@ public void testBug346454j() throws JavaModelException { int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - // TODO: it would be great if type inference could narrow this down to only proposals of type String - "finalize[METHOD_REF]{finalize(), Ljava.lang.Object;, ()V, finalize, null, 47}\n" + - "foo[METHOD_REF]{foo(), Ltest.X;, (Ljava.lang.String;)V, foo, (str), 47}\n" + - "notify[METHOD_REF]{notify(), Ljava.lang.Object;, ()V, notify, null, 47}\n" + - "notifyAll[METHOD_REF]{notifyAll(), Ljava.lang.Object;, ()V, notifyAll, null, 47}\n" + - "wait[METHOD_REF]{wait(), Ljava.lang.Object;, ()V, wait, null, 47}\n" + - "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (J)V, wait, (millis), 47}\n" + - "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (JI)V, wait, (millis, nanos), 47}\n" + - "equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), 52}\n" + - "hashCode[METHOD_REF]{hashCode(), Ljava.lang.Object;, ()I, hashCode, null, 52}\n" + - "X[TYPE_REF]{X, test, Ltest.X;, null, null, 72}\n" + - "clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, 72}\n" + - "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class;, getClass, null, 72}\n" + - "str[LOCAL_VARIABLE_REF]{str, null, Ljava.lang.String;, str, null, 72}\n" + - "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 72}\n" + - "Z[TYPE_REF]{pack.Z, pack, TZ;, null, null, 79}", + "T2[METHOD_REF<CONSTRUCTOR>]{, Lpack.Test<Ljava.lang.String;>.T2<>;, (TZ;)V, T2, (z), 39}\n" + + "Test<java.lang.String>.T2<>[ANONYMOUS_CLASS_DECLARATION]{, Lpack.Test<Ljava.lang.String;>.T2<>;, (TZ;)V, null, (z), 39}", requestor.getResults()); } finally { // Restore compliance settings. @@ -23766,22 +23755,8 @@ public void testBug346454k() throws JavaModelException { int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); assertResults( - // TODO: it would be great if type inference could narrow this down to only proposals of type String - "finalize[METHOD_REF]{finalize(), Ljava.lang.Object;, ()V, finalize, null, 47}\n" + - "foo[METHOD_REF]{foo(), Ltest.X;, (Ljava.lang.String;)V, foo, (str), 47}\n" + - "notify[METHOD_REF]{notify(), Ljava.lang.Object;, ()V, notify, null, 47}\n" + - "notifyAll[METHOD_REF]{notifyAll(), Ljava.lang.Object;, ()V, notifyAll, null, 47}\n" + - "wait[METHOD_REF]{wait(), Ljava.lang.Object;, ()V, wait, null, 47}\n" + - "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (J)V, wait, (millis), 47}\n" + - "wait[METHOD_REF]{wait(), Ljava.lang.Object;, (JI)V, wait, (millis, nanos), 47}\n" + - "equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), 52}\n" + - "hashCode[METHOD_REF]{hashCode(), Ljava.lang.Object;, ()I, hashCode, null, 52}\n" + - "X[TYPE_REF]{X, test, Ltest.X;, null, null, 72}\n" + - "clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, 72}\n" + - "getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class;, getClass, null, 72}\n" + - "str[LOCAL_VARIABLE_REF]{str, null, Ljava.lang.String;, str, null, 72}\n" + - "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 72}\n" + - "Z[TYPE_REF]{pack.Z, pack, TZ;, null, null, 79}", + "T2[METHOD_REF<CONSTRUCTOR>]{, Lpack.Test<Ljava.lang.String;>.T2<>;, (TZ;)V, T2, (z), 39}\n" + + "Test<java.lang.String>.T2<>[ANONYMOUS_CLASS_DECLARATION]{, Lpack.Test<Ljava.lang.String;>.T2<>;, (TZ;)V, null, (z), 39}", requestor.getResults()); } finally { // Restore compliance settings. 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 57dc6760c0..0bcf7b9882 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 @@ -188,8 +188,9 @@ public void test005() throws JavaModelException { String completeBehind = "arg"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_EXACT_EXPECTED_TYPE + R_NON_RESTRICTED + R_UNQUALIFIED; assertResults( - "argument[LOCAL_VARIABLE_REF]{argument, null, I, argument, null, " + (R_DEFAULT + 52) + "}", + "argument[LOCAL_VARIABLE_REF]{argument, null, I, argument, null, " + relevance + "}", requestor.getResults()); } public void test006() throws JavaModelException { @@ -528,8 +529,9 @@ public void test014() throws JavaModelException { // ensure higher relevance for String completeBehind = "arrayO"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_NON_RESTRICTED + R_EXACT_EXPECTED_TYPE + R_UNQUALIFIED; assertResults("arrayOfStrings[LOCAL_VARIABLE_REF]{arrayOfStrings, null, [Ljava.lang.String;, null, null, arrayOfStrings, null, [168, 174], " + (R_DEFAULT + 22) + "}\n" + - "arrayOfInts[LOCAL_VARIABLE_REF]{arrayOfInts, null, [I, null, null, arrayOfInts, null, [168, 174], " + (R_DEFAULT + 52) + "}", requestor.getResults()); + "arrayOfInts[LOCAL_VARIABLE_REF]{arrayOfInts, null, [I, null, null, arrayOfInts, null, [168, 174], " + relevance + "}", requestor.getResults()); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=422901, [1.8][code assist] Code assistant sensitive to scope.referenceContext type identity. public void test015() throws JavaModelException { // ensure higher relevance for matching return type. @@ -3112,8 +3114,9 @@ public void test485492b() throws JavaModelException { String completeBehind = "return zil"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_EXACT_EXPECTED_TYPE + R_UNQUALIFIED + R_NON_RESTRICTED; assertResults( - "zilch[LOCAL_VARIABLE_REF]{zilch, null, Ljava.lang.String;, null, null, zilch, null, [81, 84], "+(R_EXACT_EXPECTED_TYPE+52)+"}", + "zilch[LOCAL_VARIABLE_REF]{zilch, null, Ljava.lang.String;, null, null, zilch, null, [81, 84], " + relevance + "}", requestor.getResults()); } public void test485492c() throws JavaModelException { @@ -4693,4 +4696,49 @@ public void testBug543617() throws JavaModelException { "load[METHOD_REF]{load(), Ltest.TestApp;, (Ljava.util.List<Ljava.lang.Long;>;)Ljava.util.List<Ljava.lang.String;>;, load, (ids), "+expectedTypeRelevance+"}", requestor.getResults()); } +public void testBug539617_alloc() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy("/Completion/src/CodeCompletion.java", + "public class CodeCompletion {\n" + + " public static void main(String[] args) {\n" + + " new Thread( () -> {\n" + + " Double d = new Double(\n" + + " });\n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + String str = this.workingCopies[0].getSource(); + String completeBehind = "new Double("; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED; + assertResults( + "Double[METHOD_REF<CONSTRUCTOR>]{, Ljava.lang.Double;, (D)V, Double, (arg0), "+relevance+"}\n" + + "Double[METHOD_REF<CONSTRUCTOR>]{, Ljava.lang.Double;, (Ljava.lang.String;)V, Double, (arg0), "+relevance+"}", + requestor.getResults()); +} +public void testBug539617_msg() throws JavaModelException { + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy("/Completion/src/CodeCompletion.java", + "public class CodeCompletion {\n" + + " public static void main(String[] args) {\n" + + " new Thread( () -> {\n" + + " Double d = meth(\n" + + " });\n" + + " }\n" + + " static Double meth(String arg) { return null; }\n" + + " static Number meth(String arg, boolean flag) { return null; }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + String str = this.workingCopies[0].getSource(); + String completeBehind = "meth("; + int cursorLocation = str.indexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_EXACT_NAME + R_UNQUALIFIED + R_NON_RESTRICTED; + int relevanceExpectedType = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_EXACT_NAME + R_UNQUALIFIED + R_NON_RESTRICTED + R_EXACT_EXPECTED_TYPE; + assertResults( + "meth[METHOD_REF]{, LCodeCompletion;, (Ljava.lang.String;Z)Ljava.lang.Number;, meth, (arg, flag), "+relevance+"}\n" + + "meth[METHOD_REF]{, LCodeCompletion;, (Ljava.lang.String;)Ljava.lang.Double;, meth, (arg), "+relevanceExpectedType+"}", + requestor.getResults()); +} } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java index 18548cac73..21c67eb7d3 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java @@ -46,8 +46,13 @@ public class CompletionOnMessageSend extends MessageSend { this.constant = Constant.NotAConstant; if (this.arguments != null) { int argsLength = this.arguments.length; - for (int a = argsLength; --a >= 0;) - this.arguments[a].resolveType(scope); + for (int a = argsLength; --a >= 0;) { + try { + this.arguments[a].resolveType(scope); + } catch (CompletionNodeFound cnf) { + // ignore nested completion node + } + } } if (this.receiver.isImplicitThis()) diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java index 3e49ede588..de28ee46ec 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java @@ -44,12 +44,18 @@ public class CompletionOnQualifiedAllocationExpression extends QualifiedAllocati @Override public TypeBinding resolveType(BlockScope scope) { this.argumentTypes = Binding.NO_PARAMETERS; + boolean hasMissingType = false; if (this.arguments != null) { int argsLength = this.arguments.length; int length = this.arguments.length; this.argumentTypes = new TypeBinding[length]; for (int a = argsLength; --a >= 0;) { - this.argumentTypes[a] = this.arguments[a].resolveType(scope); + try { + this.argumentTypes[a] = this.arguments[a].resolveType(scope); + } catch (CompletionNodeFound cnf) { + // ignore nested completion node + hasMissingType = true; + } } } final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0; @@ -69,7 +75,7 @@ public TypeBinding resolveType(BlockScope scope) { throw new CompletionNodeFound(); } this.resolvedType = ((SingleTypeReference) this.type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingType); - if (isDiamond && (this.resolvedType instanceof ParameterizedTypeBinding)) { + if (isDiamond && (this.resolvedType instanceof ParameterizedTypeBinding) && !hasMissingType) { TypeBinding [] inferredTypes = inferElidedTypes(scope); if (inferredTypes != null) { this.resolvedType = this.type.resolvedType = scope.environment().createParameterizedType(((ParameterizedTypeBinding) this.resolvedType).genericType(), inferredTypes, this.resolvedType.enclosingType()); diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java index 6d55724ed6..c96e227508 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java @@ -5618,6 +5618,15 @@ private MessageSend internalNewMessageSend() { } return null; } +@Override +protected AllocationExpression newAllocationExpression(boolean isQualified) { + if (this.assistNode != null && this.lParenPos == this.assistNode.sourceEnd) { + CompletionOnQualifiedAllocationExpression allocation = new CompletionOnQualifiedAllocationExpression(); + this.assistNode = allocation; + return allocation; + } + return super.newAllocationExpression(isQualified); +} public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) { this.cursorLocation = cursorLoc; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java index 3d1df93cb1..e0afaee7d0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java @@ -1295,11 +1295,7 @@ protected void classInstanceCreation(boolean isQualified) { && (this.astStack[this.astPtr] == null)) { //NO ClassBody this.astPtr--; - if (isQualified) { - alloc = new QualifiedAllocationExpression(); - } else { - alloc = new AllocationExpression(); - } + alloc = newAllocationExpression(isQualified); alloc.sourceEnd = this.endPosition; //the position has been stored explicitly if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { @@ -1334,6 +1330,15 @@ protected void classInstanceCreation(boolean isQualified) { this.astLengthPtr--; } } +protected AllocationExpression newAllocationExpression(boolean isQualified) { + AllocationExpression alloc; + if (isQualified) { + alloc = new QualifiedAllocationExpression(); + } else { + alloc = new AllocationExpression(); + } + return alloc; +} protected void checkForDiamond(TypeReference allocType) { if (allocType instanceof ParameterizedSingleTypeReference) { ParameterizedSingleTypeReference type = (ParameterizedSingleTypeReference) allocType; |
