From 55e280e07d9cb79138719ed1fac2ebad49bb1617 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Fri, 7 Jun 2024 22:56:38 +0200 Subject: [PATCH 01/16] WIP: Looks into indirect types during compilation fixes #543 + tolerate missing types during BTB.resolveTypesFor(MethodBinding) + new parameterCompatibilityLevel NEED_MISSING_TYPE + when NEED_MISSING_TYPE is encountered during resolution answer ProblemMethodBinding(ProblemReason.MissingTypeInSignature) + for varargs invocation try to discern if a missing type is relevant Tests: + adjust expected secondary errors (neither is better than the other) TODO: + check all call paths into parameterCompatibilityLevel() + fields --- .../internal/compiler/ast/MessageSend.java | 17 +- .../compiler/lookup/BinaryTypeBinding.java | 50 +++-- .../compiler/lookup/InferenceContext18.java | 1 + .../ParameterizedGenericMethodBinding.java | 2 +- .../compiler/lookup/ProblemReasons.java | 1 + .../jdt/internal/compiler/lookup/Scope.java | 20 +- .../compiler/problem/ProblemReporter.java | 8 + .../regression/ProblemTypeAndMethodTest.java | 203 ++++++++++++++++-- .../compiler/regression/SealedTypesTests.java | 24 +-- 9 files changed, 269 insertions(+), 57 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index 9bc7180ee50..250e816928a 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -995,7 +995,7 @@ public TypeBinding resolveType(BlockScope scope) { this.binding = scope.environment().updatePolymorphicMethodReturnType((PolymorphicMethodBinding) this.binding, TypeBinding.VOID); } } - if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { + if ((this.binding.tagBits & TagBits.HasMissingType) != 0 && isMissingTypeRelevant()) { scope.problemReporter().missingTypeInMethod(this, this.binding); } if (!this.binding.isStatic()) { @@ -1112,6 +1112,21 @@ protected boolean isUnnecessaryReceiverCast(BlockScope scope, TypeBinding uncast || MethodVerifier.doesMethodOverride(otherMethod, this.binding, scope.environment()); } +protected boolean isMissingTypeRelevant() { + if ((this.binding.returnType.tagBits & TagBits.HasMissingType) == 0 + && this.binding.isVarargs()) { + if (this.arguments.length < this.binding.parameters.length) { + // are all but the irrelevant varargs type present? + for (int i = 0; i < this.arguments.length; i++) { + if ((this.binding.parameters[i].tagBits & TagBits.HasMissingType) != 0) + return true; // this one *is* relevant + } + return false; + } + } + return true; +} + protected TypeBinding handleNullnessCodePatterns(BlockScope scope, TypeBinding returnType) { // j.u.s.Stream.filter() may modify nullness of stream elements: if (this.binding.isWellknownMethod(TypeConstants.JAVA_UTIL_STREAM__STREAM, TypeConstants.FILTER) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index d2c917ee2c7..c8cb9f00ca8 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -1951,33 +1951,39 @@ MethodBinding resolveTypesFor(MethodBinding method) { if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return method; + boolean tolerateSave = this.environment.mayTolerateMissingType; + this.environment.mayTolerateMissingType = true; + try { - if (!method.isConstructor()) { - TypeBinding resolvedType = resolveType(method.returnType, this.environment, true /* raw conversion */); - method.returnType = resolvedType; - if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { - method.tagBits |= TagBits.HasMissingType; + if (!method.isConstructor()) { + TypeBinding resolvedType = resolveType(method.returnType, this.environment, true /* raw conversion */); + method.returnType = resolvedType; + if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { + method.tagBits |= TagBits.HasMissingType; + } } - } - for (int i = method.parameters.length; --i >= 0;) { - TypeBinding resolvedType = resolveType(method.parameters[i], this.environment, true /* raw conversion */); - method.parameters[i] = resolvedType; - if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { - method.tagBits |= TagBits.HasMissingType; + for (int i = method.parameters.length; --i >= 0;) { + TypeBinding resolvedType = resolveType(method.parameters[i], this.environment, true /* raw conversion */); + method.parameters[i] = resolvedType; + if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { + method.tagBits |= TagBits.HasMissingType; + } } - } - for (int i = method.thrownExceptions.length; --i >= 0;) { - ReferenceBinding resolvedType = (ReferenceBinding) resolveType(method.thrownExceptions[i], this.environment, true /* raw conversion */); - method.thrownExceptions[i] = resolvedType; - if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { - method.tagBits |= TagBits.HasMissingType; + for (int i = method.thrownExceptions.length; --i >= 0;) { + ReferenceBinding resolvedType = (ReferenceBinding) resolveType(method.thrownExceptions[i], this.environment, true /* raw conversion */); + method.thrownExceptions[i] = resolvedType; + if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) { + method.tagBits |= TagBits.HasMissingType; + } } + for (int i = method.typeVariables.length; --i >= 0;) { + method.typeVariables[i].resolve(); + } + method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; + return method; + } finally { + this.environment.mayTolerateMissingType = tolerateSave; } - for (int i = method.typeVariables.length; --i >= 0;) { - method.typeVariables[i].resolve(); - } - method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; - return method; } @Override AnnotationBinding[] retrieveAnnotations(Binding binding) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java index 8eef8e72500..26ad94323ad 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java @@ -754,6 +754,7 @@ private boolean addConstraintsToC_OneExpr(Expression expri, Set Scope.NOT_COMPATIBLE) { + if ((scope.parameterCompatibilityLevel(substitute, arguments, false)) > Scope.NOT_COMPATIBLE) { // don't worry about NEEDS_MISSING_TYPE in 1.7 context methodSubstitute = substitute; } else { inferenceContext = oldContext; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java index 5c550bf6247..fff08aa31cb 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java @@ -52,4 +52,5 @@ public interface ProblemReasons { final int InterfaceMethodInvocationNotBelow18 = 29; final int NotAccessible = 30; // JLS 6.6.1 - module aspects final int ErrorAlreadyReported = 31; + final int MissingTypeInSignature = 32; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java index ce12830d0be..531049fc509 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -108,6 +108,7 @@ public char[] readableName() { public final static int COMPATIBLE = 0; public final static int AUTOBOX_COMPATIBLE = 1; public final static int VARARGS_COMPATIBLE = 2; + public final static int NEEDS_MISSING_TYPE = -2; /* Type Compatibilities */ public static final int EQUAL_OR_MORE_SPECIFIC = -1; @@ -871,13 +872,16 @@ protected final MethodBinding computeCompatibleMethod(MethodBinding method, Type } - if ((parameterCompatibilityLevel(method, arguments, tiebreakingVarargsMethods)) > NOT_COMPATIBLE) { + int level = parameterCompatibilityLevel(method, arguments, tiebreakingVarargsMethods); + if (level > NOT_COMPATIBLE) { if (method.hasPolymorphicSignature(this)) { // generate polymorphic method and set polymorphic tagbits as well method.tagBits |= TagBits.AnnotationPolymorphicSignature; return this.environment().createPolymorphicMethod(method, arguments, this); } return method; + } else if (level == NEEDS_MISSING_TYPE) { + return new ProblemMethodBinding(method, method.selector, method.parameters, ProblemReasons.MissingTypeInSignature); } // if method is generic and type arguments have been supplied, only then answer a problem // of ParameterizedMethodTypeMismatch, else a non-generic method was invoked using type arguments @@ -1764,6 +1768,8 @@ public MethodBinding findMethod0(ReferenceBinding receiverType, char[] selector, if (candidatesCount == 0) candidates = new MethodBinding[foundSize]; candidates[candidatesCount++] = compatibleMethod; + } else if (compatibleMethod.problemId() == ProblemReasons.MissingTypeInSignature) { + return compatibleMethod; // use this method for error message to give a hint about the missing type } else if (problemMethod == null) { problemMethod = compatibleMethod; } @@ -2495,6 +2501,8 @@ public MethodBinding getConstructor0(ReferenceBinding receiverType, TypeBinding[ if (compatibleMethod != null) { if (compatibleMethod.isValidBinding()) compatible[compatibleIndex++] = compatibleMethod; + else if (compatibleMethod.problemId() == ProblemReasons.MissingTypeInSignature) + return compatibleMethod; // use this method for error message to give a hint about the missing type else if (problemMethod == null) problemMethod = compatibleMethod; } @@ -4648,6 +4656,10 @@ protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int compatibleCount = 0; for (int i = 0; i < visibleSize; i++) if ((compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes, invocationSite)) != NOT_COMPATIBLE) { + if (compatibilityLevels[i] == NEEDS_MISSING_TYPE) { + // cannot conclusively select any candidate, use the method with missing types in the error message + return new ProblemMethodBinding(visible[i], visible[i].selector, visible[i].parameters, ProblemReasons.Ambiguous); + } if (i != compatibleCount) { visible[compatibleCount] = visible[i]; compatibilityLevels[compatibleCount] = compatibilityLevels[i]; @@ -5161,8 +5173,8 @@ public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] argum TypeBinding arg = (tiebreakingVarargsMethods && (i == (argLength - 1))) ? ((ArrayBinding)arguments[i]).elementsType() : arguments[i]; if (TypeBinding.notEquals(arg,param)) { int newLevel = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method); - if (newLevel == NOT_COMPATIBLE) - return NOT_COMPATIBLE; + if (newLevel < COMPATIBLE) + return newLevel; if (newLevel > level) level = newLevel; } @@ -5193,6 +5205,8 @@ private int parameterCompatibilityLevel(TypeBinding arg, TypeBinding param, Look // only called if env.options.sourceLevel >= ClassFileConstants.JDK1_5 if (arg == null || param == null) return NOT_COMPATIBLE; + if ((param.tagBits & TagBits.HasMissingType) != 0) + return NEEDS_MISSING_TYPE; if (arg instanceof PolyTypeBinding && !((PolyTypeBinding) arg).expression.isPertinentToApplicability(param, method)) { if (arg.isPotentiallyCompatibleWith(param, this)) return COMPATIBLE; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 84265a3f95c..063986d6e98 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -4164,6 +4164,10 @@ public void invalidConstructor(Statement statement, MethodBinding targetConstruc problemConstructor = (ProblemMethodBinding) targetConstructor; contradictoryNullAnnotationsInferred(problemConstructor.closestMatch, statement); return; + case ProblemReasons.MissingTypeInSignature: + problemConstructor = (ProblemMethodBinding) targetConstructor; + missingTypeInConstructor(statement, problemConstructor.closestMatch); + return; case ProblemReasons.NoError : // 0 default : needImplementation(statement); // want to fail to see why we were here... @@ -4785,6 +4789,10 @@ public void invalidMethod(MessageSend messageSend, MethodBinding method, Scope s problemMethod = (ProblemMethodBinding) method; contradictoryNullAnnotationsInferred(problemMethod.closestMatch, messageSend); return; + case ProblemReasons.MissingTypeInSignature: + problemMethod = (ProblemMethodBinding) method; + missingTypeInMethod(messageSend, problemMethod.closestMatch); + return; case ProblemReasons.NoError : // 0 default : needImplementation(messageSend); // want to fail to see why we were here... diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index 5af1988a49f..2377fdbcf2c 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -497,15 +497,10 @@ public void test005() { "----------\n" + /* expected compiler log */ "1. ERROR in X.java (at line 4)\n" + " ofoo.bar();\n" + - " ^^^^^^^^^^\n" + - "The type q1.q2.Zork cannot be resolved. It is indirectly referenced from required type p.OtherFoo\n" + - "----------\n" + - "2. ERROR in X.java (at line 4)\n" + - " ofoo.bar();\n" + " ^^^\n" + "The method bar() from the type OtherFoo refers to the missing type Zork\n" + "----------\n" + - "3. ERROR in X.java (at line 5)\n" + + "2. ERROR in X.java (at line 5)\n" + " q1.q2.Zork z;\n" + " ^^^^^^^^^^\n" + "q1.q2.Zork cannot be resolved to a type\n" + @@ -564,15 +559,10 @@ public void test006() { "----------\n" + "2. ERROR in X.java (at line 5)\n" + " ofoo.bar();\n" + - " ^^^^^^^^^^\n" + - "The type q1.q2.Zork cannot be resolved. It is indirectly referenced from required type p.OtherFoo\n" + - "----------\n" + - "3. ERROR in X.java (at line 5)\n" + - " ofoo.bar();\n" + " ^^^\n" + "The method bar() from the type OtherFoo refers to the missing type Zork\n" + "----------\n" + - "4. ERROR in X.java (at line 6)\n" + + "3. ERROR in X.java (at line 6)\n" + " Zork z;\n" + " ^^^^\n" + "Zork cannot be resolved to a type\n" + @@ -631,15 +621,10 @@ public void test007() { "----------\n" + "2. ERROR in X.java (at line 5)\n" + " ofoo.bar();\n" + - " ^^^^^^^^^^\n" + - "The type q1.q2.Zork cannot be resolved. It is indirectly referenced from required type p.OtherFoo\n" + - "----------\n" + - "3. ERROR in X.java (at line 5)\n" + - " ofoo.bar();\n" + " ^^^\n" + "The method bar() from the type OtherFoo refers to the missing type Zork\n" + "----------\n" + - "4. ERROR in X.java (at line 6)\n" + + "3. ERROR in X.java (at line 6)\n" + " Zork z;\n" + " ^^^^\n" + "Zork cannot be resolved to a type\n" + @@ -8828,4 +8813,186 @@ public void testBug576735() { "----------\n"; runner.runNegativeTest(); } +public void testMissingClassNeededForOverloadResolution() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + public class B { + public void m(A a) {} + public void m(Object s) {} + public void m(Object s1, String s2) {} + public void other() {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + runner.shouldFlushOutputDirectory = false; + + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + b.other(); // no need to see A for other() + b.m(this, ""); // overload selected by arity + } + } + """ + }; + runner.runConformTest(); + + runner.testFiles = new String[] { + "p2/D.java", + """ + package p2; + import p1.B; + public class D { + void test(B b) { + b.m(this); // cannot select without seeing class A + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\D.java (at line 5) + b.m(this); // cannot select without seeing class A + ^ + The method m(A) from the type B refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClassNeededForOverloadResolution_varargs1() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses varargs + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + public class B { + public void m(Object o1, String s, A... a) {} + public void m(Object o1) {} + public void n(Object o1, A... a) {} + public void n(Object o1) {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + b.m(this, ""); // overload selected by arity, trailing A[] is irrelevant + b.m(this); // overload selected by arity, no reference to A + } + } + """ + }; + runner.runConformTest(); + + runner.testFiles = new String[] { + "p2/D.java", + """ + package p2; + import p1.B; + public class D { + void test(B b) { + b.n(this, null); // passing null into A[] is not OK + b.n(this, null, null); // passing null into A is not OK (could potentially be accepted) + b.n(this); // resolvable in strict mode, ignore the varargs method + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\D.java (at line 5) + b.n(this, null); // passing null into A[] is not OK + ^ + The method n(Object, A...) from the type B refers to the missing type A + ---------- + 2. ERROR in p2\\D.java (at line 6) + b.n(this, null, null); // passing null into A is not OK (could potentially be accepted) + ^ + The method n(Object, A...) from the type B refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClassNeededForOverloadResolution_varargs2() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses varargs + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + public class B { + public void m(A a, String... args) {} + public void m(Object s, Number... args) {} + public void m(Object s1, String s2) {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + runner.shouldFlushOutputDirectory = false; + + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + b.m(this, ""); // two overloads could apply (not knowing A) + b.m(this, 3); // overload effectively selected by 2nd arg + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + b.m(this, ""); // two overloads could apply (not knowing A) + ^ + The method m(A, String...) from the type B refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java index dc26c3ecc47..0e054e5469e 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SealedTypesTests.java @@ -2836,7 +2836,7 @@ public void testBug564638_041() { "2. ERROR in X.java (at line 5)\n" + " this(t);\n" + " ^^^^^^^^\n" + - "The parameterized constructor X(permits) of type X is not applicable for the arguments (Integer)\n" + + "The constructor X(permits) refers to the missing type permits\n" + "----------\n"); } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -2863,7 +2863,7 @@ public void testBug564638_042() { "3. ERROR in X.java (at line 5)\n" + " this(t);\n" + " ^^^^^^^^\n" + - "The parameterized constructor X(permits) of type X is not applicable for the arguments (Integer)\n" + + "The constructor X(permits) refers to the missing type permits\n" + "----------\n", null, true, @@ -2887,7 +2887,7 @@ public void testBug564638_043() { "1. ERROR in X.java (at line 5)\n" + " new X(t).foo();\n" + " ^^^^^^^^^^^^^^^^^\n" + - "The parameterized constructor X(permits) of type X is not applicable for the arguments (Integer)\n" + + "The constructor X(permits) refers to the missing type permits\n" + "----------\n" + "2. ERROR in X.java (at line 5)\n" + " new X(t).foo();\n" + @@ -2915,7 +2915,7 @@ public void testBug564638_044() { "1. ERROR in X.java (at line 5)\n" + " new X(t).foo();\n" + " ^^^^^^^^^^^^^^^^^\n" + - "The parameterized constructor X(permits) of type X is not applicable for the arguments (Integer)\n" + + "The constructor X(permits) refers to the missing type permits\n" + "----------\n" + "2. ERROR in X.java (at line 5)\n" + " new X(t).foo();\n" + @@ -2949,7 +2949,7 @@ public void testBug564638_045() { "2. ERROR in X.java (at line 6)\n" + " x.foo(0);\n" + " ^^^\n" + - "The parameterized method foo(permits) of type X is not applicable for the arguments (Integer)\n" + + "The method foo(permits) from the type X refers to the missing type permits\n" + "----------\n"); } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -2977,7 +2977,7 @@ public void testBug564638_046() { "3. ERROR in X.java (at line 6)\n" + " x.foo(0);\n" + " ^^^\n" + - "The parameterized method foo(permits) of type X is not applicable for the arguments (Integer)\n" + + "The method foo(permits) from the type X refers to the missing type permits\n" + "----------\n", null, true, @@ -4459,7 +4459,7 @@ public void testBug564638b_041() { "2. ERROR in X.java (at line 5)\n" + " this(t);\n" + " ^^^^^^^^\n" + - "The parameterized constructor X(sealed) of type X is not applicable for the arguments (Integer)\n" + + "The constructor X(sealed) refers to the missing type sealed\n" + "----------\n"); } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -4486,7 +4486,7 @@ public void testBug564638b_042() { "3. ERROR in X.java (at line 5)\n" + " this(t);\n" + " ^^^^^^^^\n" + - "The parameterized constructor X(sealed) of type X is not applicable for the arguments (Integer)\n" + + "The constructor X(sealed) refers to the missing type sealed\n" + "----------\n", null, true, @@ -4510,7 +4510,7 @@ public void testBug564638b_043() { "1. ERROR in X.java (at line 5)\n" + " new X(t).foo();\n" + " ^^^^^^^^^^^^^^^^\n" + - "The parameterized constructor X(sealed) of type X is not applicable for the arguments (Integer)\n" + + "The constructor X(sealed) refers to the missing type sealed\n" + "----------\n" + "2. ERROR in X.java (at line 5)\n" + " new X(t).foo();\n" + @@ -4538,7 +4538,7 @@ public void testBug564638b_044() { "1. ERROR in X.java (at line 5)\n" + " new X(t).foo();\n" + " ^^^^^^^^^^^^^^^^\n" + - "The parameterized constructor X(sealed) of type X is not applicable for the arguments (Integer)\n" + + "The constructor X(sealed) refers to the missing type sealed\n" + "----------\n" + "2. ERROR in X.java (at line 5)\n" + " new X(t).foo();\n" + @@ -4572,7 +4572,7 @@ public void testBug564638b_045() { "2. ERROR in X.java (at line 6)\n" + " x.foo(0);\n" + " ^^^\n" + - "The parameterized method foo(sealed) of type X is not applicable for the arguments (Integer)\n" + + "The method foo(sealed) from the type X refers to the missing type sealed\n" + "----------\n"); } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -4600,7 +4600,7 @@ public void testBug564638b_046() { "3. ERROR in X.java (at line 6)\n" + " x.foo(0);\n" + " ^^^\n" + - "The parameterized method foo(sealed) of type X is not applicable for the arguments (Integer)\n" + + "The method foo(sealed) from the type X refers to the missing type sealed\n" + "----------\n", null, true, From 0ee51820678cfe6de4b7026c912b9b959d80aca4 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Sun, 9 Jun 2024 16:09:53 +0200 Subject: [PATCH 02/16] Fixing regressions: + Java50Tests pointed to incomplete impl. at compliance below 1.8 => restrict new policy to 1.8+ + DependencyTests.testMissingClassFile() + bump test to 1.8 and let it include positive & negative cases + MultiProjectTests.test461074_error() split to 1.5 and 1.8 variants: + no change at 1.5 + no longer an error at 1.8+ --- .../compiler/lookup/BinaryTypeBinding.java | 2 +- .../core/tests/builder/DependencyTests.java | 18 +++-- .../core/tests/builder/MultiProjectTests.java | 76 +++++++++++++++++++ .../regression/ProblemTypeAndMethodTest.java | 8 +- 4 files changed, 94 insertions(+), 10 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index c8cb9f00ca8..bc7d37f03e0 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -1952,7 +1952,7 @@ MethodBinding resolveTypesFor(MethodBinding method) { if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return method; boolean tolerateSave = this.environment.mayTolerateMissingType; - this.environment.mayTolerateMissingType = true; + this.environment.mayTolerateMissingType = this.environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_8; // tolerance only implemented for 1.8+ try { if (!method.isConstructor()) { diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/DependencyTests.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/DependencyTests.java index 8c5354ee834..8656c4b146c 100644 --- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/DependencyTests.java +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/DependencyTests.java @@ -25,6 +25,9 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public class DependencyTests extends BuilderTests { + static { +// TESTS_NAMES = new String[] {"testMissingClassFile"}; + } public DependencyTests(String name) { super(name); } @@ -857,7 +860,7 @@ public void testMethodVisibility() throws JavaModelException { } public void testMissingClassFile() throws JavaModelException { - IPath project1Path = env.addProject("Project1"); //$NON-NLS-1$ + IPath project1Path = env.addProject("Project1", "1.8"); // tolerance of missing types not fully implemented below 1.8 env.addExternalJars(project1Path, Util.getJavaClassLibs()); // remove old package fragment root so that names don't collide @@ -871,7 +874,7 @@ public void testMissingClassFile() throws JavaModelException { "public class MissingClass {}" //$NON-NLS-1$ ); - IPath project2Path = env.addProject("Project2"); //$NON-NLS-1$ + IPath project2Path = env.addProject("Project2", "1.8"); // tolerance of missing types not fully implemented below 1.8 env.addExternalJars(project2Path, Util.getJavaClassLibs()); env.addRequiredProject(project2Path, project1Path); @@ -890,7 +893,7 @@ public void testMissingClassFile() throws JavaModelException { "}\n" //$NON-NLS-1$ ); - IPath project3Path = env.addProject("Project3"); //$NON-NLS-1$ + IPath project3Path = env.addProject("Project3", "1.8"); // tolerance of missing types not fully implemented below 1.8 env.addExternalJars(project3Path, Util.getJavaClassLibs()); env.addRequiredProject(project3Path, project2Path); // missing required Project1 so MissingClass cannot be found @@ -906,19 +909,20 @@ public void testMissingClassFile() throws JavaModelException { "import p2.A;\n" + "public class B {\n"+ //$NON-NLS-1$ " public static void main(String[] args) {\n" + //$NON-NLS-1$ - " new A().foo(new String());\n" + //$NON-NLS-1$ + " new A().foo(new Object());\n" + // potentially ambiguous + " new A().foo(new String());\n" + // exact match to fully resolved method " }\n" + //$NON-NLS-1$ "}\n" //$NON-NLS-1$ ); fullBuild(); - expectingOnlyProblemsFor(new IPath[] {project3Path, bPath}); - expectingSpecificProblemFor(project3Path, new Problem("Project3", "The project was not built since its build path is incomplete. Cannot find the class file for p1.MissingClass. Fix the build path then try building this project", project3Path, -1, -1, CategorizedProblem.CAT_BUILDPATH, IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ //$NON-NLS-2$ - expectingSpecificProblemFor(bPath, new Problem("B", "The type p1.MissingClass cannot be resolved. It is indirectly referenced from required type p2.A", bPath, 86, 111, CategorizedProblem.CAT_BUILDPATH, IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ //$NON-NLS-2$ + expectingOnlyProblemsFor(new IPath[] {bPath}); + expectingSpecificProblemFor(bPath, new Problem("B", "The method foo(MissingClass) from the type A refers to the missing type MissingClass", bPath, 94, 97, CategorizedProblem.CAT_MEMBER, IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ //$NON-NLS-2$ env.addClass(root2, "p2", "A", //$NON-NLS-1$ //$NON-NLS-2$ "package p2;\n"+ //$NON-NLS-1$ "public class A {\n"+ //$NON-NLS-1$ + " public void foo(Object data) {}\n"+ //$NON-NLS-1$ " public void foo(String data) {}\n"+ //$NON-NLS-1$ "}\n" //$NON-NLS-1$ ); diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java index 8babfccacaf..087637dc9dd 100644 --- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java @@ -33,6 +33,10 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public class MultiProjectTests extends BuilderTests { + static { + TESTS_NAMES = new String[] { "test461074_error_1_8" }; + } + public MultiProjectTests(String name) { super(name); } @@ -2221,4 +2225,76 @@ public void test461074_error() throws JavaModelException { env.removeProject(p2); env.removeProject(p3); } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=461074, "indirectly referenced from required .class files" error for unreachable reference of type in overriding method declaration in a library on classpath +public void test461074_error_1_8() throws JavaModelException { + // as of https://github.com/eclipse-jdt/eclipse.jdt.core/pull/2543 and at 1.8+ we tolerate the missing type + //---------------------------- + // Project1 + //---------------------------- + IPath p1 = env.addProject("SampleMissing", "1.8"); //$NON-NLS-1$ + env.addExternalJars(p1, Util.getJavaClassLibs()); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p1, ""); //$NON-NLS-1$ + IPath root1 = env.addPackageFragmentRoot(p1, "src"); //$NON-NLS-1$ + env.setOutputFolder(p1, "bin"); //$NON-NLS-1$ + + env.addClass(root1, "pack.missing", "MissingType", //$NON-NLS-1$ //$NON-NLS-2$ + "package pack.missing;\n" + + "public class MissingType {\n" + + "}\n" + ); + + //---------------------------- + // Project2 + //---------------------------- + IPath p2 = env.addProject("SampleLib", "1.8"); //$NON-NLS-1$ + env.addExternalJars(p2, Util.getJavaClassLibs()); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p2, ""); //$NON-NLS-1$ + IPath root2 = env.addPackageFragmentRoot(p2, "src"); //$NON-NLS-1$ + env.setOutputFolder(p2, "bin"); //$NON-NLS-1$ + + env.addClass(root2, "pack.lib", "TopClass", //$NON-NLS-1$ //$NON-NLS-2$ + "package pack.lib;\n" + + "public abstract class TopClass {\n" + + " abstract Object get();\n" + + "}\n" + ); + env.addClass(root2, "pack.lib", "SuperClass", //$NON-NLS-1$ //$NON-NLS-2$ + "package pack.lib;\n" + + "import pack.missing.MissingType;\n" + + "public class SuperClass extends TopClass {\n" + + " @Override\n" + + " MissingType get() { return null; }\n" + + "}\n" + ); + + //---------------------------- + // Project3 + //---------------------------- + IPath p3 = env.addProject("SampleTest", "1.8"); //$NON-NLS-1$ + env.addExternalJars(p3, Util.getJavaClassLibs()); + // remove old package fragment root so that names don't collide + env.removePackageFragmentRoot(p3, ""); //$NON-NLS-1$ + IPath root3 = env.addPackageFragmentRoot(p3, "src"); //$NON-NLS-1$ + env.setOutputFolder(p3, "bin"); //$NON-NLS-1$ + + env.addClass(root3, "pack.test", "Test", //$NON-NLS-1$ //$NON-NLS-2$ + "package pack.test;\n" + + "import pack.lib.SuperClass;\n" + + "public class Test extends SuperClass {/*empty*/}\n" + ); + + // for Project1 + env.addRequiredProject(p2, p1); + env.addRequiredProject(p3, p2); + env.waitForManualRefresh(); + fullBuild(); + env.waitForAutoBuild(); + expectingNoProblemsFor(p3); + env.setBuildOrder(null); + env.removeProject(p1); + env.removeProject(p2); + env.removeProject(p3); +} } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index 2377fdbcf2c..886175f5b6c 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -454,6 +454,7 @@ public void test004() { } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=196200 - variation public void test005() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 this.runConformTest( new String[] { "p/OtherFoo.java", //----------------------------------------------------------------------- @@ -510,6 +511,7 @@ public void test005() { } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=196200 - variation public void test006() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 this.runConformTest( new String[] { "p/OtherFoo.java", //----------------------------------------------------------------------- @@ -572,6 +574,7 @@ public void test006() { } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=196200 - variation public void test007() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 this.runConformTest( new String[] { "p/OtherFoo.java", //----------------------------------------------------------------------- @@ -8814,6 +8817,7 @@ public void testBug576735() { runner.runNegativeTest(); } public void testMissingClassNeededForOverloadResolution() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); runner.testFiles = new String[] { "p1/A.java", @@ -8876,7 +8880,7 @@ The method m(A) from the type B refers to the missing type A runner.runNegativeTest(); } public void testMissingClassNeededForOverloadResolution_varargs1() { - if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses varargs + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); runner.customOptions = getCompilerOptions(); runner.testFiles = new String[] { @@ -8948,7 +8952,7 @@ The method n(Object, A...) from the type B refers to the missing type A runner.runNegativeTest(); } public void testMissingClassNeededForOverloadResolution_varargs2() { - if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses varargs + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); runner.testFiles = new String[] { "p1/A.java", From 2fcd3fefeecf12c69235d4bfacdfbf738aed970b Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Thu, 13 Jun 2024 22:12:25 +0200 Subject: [PATCH 03/16] regression fix: don't overwrite existing mayTolerateMissingType=true --- .../eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index bc7d37f03e0..43d1afd2b5f 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -1952,7 +1952,7 @@ MethodBinding resolveTypesFor(MethodBinding method) { if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) return method; boolean tolerateSave = this.environment.mayTolerateMissingType; - this.environment.mayTolerateMissingType = this.environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_8; // tolerance only implemented for 1.8+ + this.environment.mayTolerateMissingType |= this.environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_8; // tolerance only implemented for 1.8+ try { if (!method.isConstructor()) { From f474a320b09e08ddd07f315b23c00394b79e792e Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Sun, 16 Jun 2024 14:01:47 +0200 Subject: [PATCH 04/16] more complete coverage of varargs methods/invocations - if in doubt signal "missing type" rather than plain "ambiguous" --- .../jdt/internal/compiler/lookup/Scope.java | 12 +- .../regression/ProblemTypeAndMethodTest.java | 324 +++++++++++++++++- 2 files changed, 330 insertions(+), 6 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java index 531049fc509..1b84b7c5bf8 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -5156,13 +5156,17 @@ public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] argum TypeBinding param = ((ArrayBinding) parameters[lastIndex]).elementsType(); for (int i = lastIndex; i < argLength; i++) { TypeBinding arg = (tiebreakingVarargsMethods && (i == (argLength - 1))) ? ((ArrayBinding)arguments[i]).elementsType() : arguments[i]; - if (TypeBinding.notEquals(param, arg) && parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method) == NOT_COMPATIBLE) - return NOT_COMPATIBLE; + if (TypeBinding.notEquals(param, arg)) { + level = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method); + if (level == NOT_COMPATIBLE) + return NOT_COMPATIBLE; + } } } else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo(); return NOT_COMPATIBLE; } - level = VARARGS_COMPATIBLE; // varargs support needed + if (level != NEEDS_MISSING_TYPE) // preserve any NEEDS_MISSING_TYPE + level = VARARGS_COMPATIBLE; // varargs support needed } } else if (paramLength != argLength) { return NOT_COMPATIBLE; @@ -5175,7 +5179,7 @@ public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] argum int newLevel = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method); if (newLevel < COMPATIBLE) return newLevel; - if (newLevel > level) + if (newLevel > level && level != NEEDS_MISSING_TYPE) // preserve any NEEDS_MISSING_TYPE level = newLevel; } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index 886175f5b6c..613085f3399 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -8879,7 +8879,326 @@ The method m(A) from the type B refers to the missing type A """; runner.runNegativeTest(); } -public void testMissingClassNeededForOverloadResolution_varargs1() { +public void testMissingClassNeededForOverloadResolution_varargs1a() { + // varargs arg: B vs Missing + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A1.java", + """ + package p1; + public class A1 {} + """, + "p1/A2.java", + """ + package p1; + public class A2 {} + """, + "p1/B.java", + """ + package p1; + public class B { + public void m(Object o1, B... s) {} + public void m(Object o1, A1... a) {} + public void m(Object o1, A2... a) {} + } + """ + }; + runner.runConformTest(); + + // delete binary files A1, A2 (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A1.class")); + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A2.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + b.m(this); // simply ambiguous as we don't even look at A1 or A2 + b.m(this, null); + b.m(this, b); + b.m(this, b, b); + b.m(this, new B[0]); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + b.m(this); // simply ambiguous as we don't even look at A1 or A2 + ^ + The method m(Object, B[]) is ambiguous for the type B + ---------- + 2. ERROR in p2\\C.java (at line 6) + b.m(this, null); + ^ + The method m(Object, A1...) from the type B refers to the missing type A1 + ---------- + 3. ERROR in p2\\C.java (at line 7) + b.m(this, b); + ^ + The method m(Object, A1...) from the type B refers to the missing type A1 + ---------- + 4. ERROR in p2\\C.java (at line 8) + b.m(this, b, b); + ^ + The method m(Object, A1...) from the type B refers to the missing type A1 + ---------- + 5. ERROR in p2\\C.java (at line 9) + b.m(this, new B[0]); + ^ + The method m(Object, A1...) from the type B refers to the missing type A1 + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClassNeededForOverloadResolution_varargs1b() { + // like testMissingClassNeededForOverloadResolution_varargs1a, but no preceding regular parameter + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A1.java", + """ + package p1; + public class A1 {} + """, + "p1/A2.java", + """ + package p1; + public class A2 {} + """, + "p1/B.java", + """ + package p1; + public class B { + public void m(String... s) {} + public void m(A1... a) {} + public void m(A2... a) {} + } + """ + }; + runner.runConformTest(); + + // delete binary files A1, A1 (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A1.class")); + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A2.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + b.m(); // simply ambiguous as we don't even look at A1 or A2 + b.m(null); + b.m(b); + b.m(b, b); + b.m(new B[0]); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + b.m(); // simply ambiguous as we don't even look at A1 or A2 + ^ + The method m(String[]) is ambiguous for the type B + ---------- + 2. ERROR in p2\\C.java (at line 6) + b.m(null); + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + 3. ERROR in p2\\C.java (at line 7) + b.m(b); + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + 4. ERROR in p2\\C.java (at line 8) + b.m(b, b); + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + 5. ERROR in p2\\C.java (at line 9) + b.m(new B[0]); + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClassNeededForOverloadResolution_varargs1c() { + // varargs arg: only missing types competing + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A1.java", + """ + package p1; + public class A1 {} + """, + "p1/A2.java", + """ + package p1; + public class A2 {} + """, + "p1/B.java", + """ + package p1; + public class B { + public void m(Object o1, A1... a) {} + public void m(Object o1, A2... a) {} + } + """ + }; + runner.runConformTest(); + + // delete binary files A1, A1 (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A1.class")); + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A2.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + b.m(this); // simply ambiguous as we don't even look at A1 or A2 + b.m(this, null); + b.m(this, b); + b.m(this, b, b); + b.m(this, new B[0]); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + b.m(this); // simply ambiguous as we don't even look at A1 or A2 + ^ + The method m(Object, A1[]) is ambiguous for the type B + ---------- + 2. ERROR in p2\\C.java (at line 6) + b.m(this, null); + ^ + The method m(Object, A1...) from the type B refers to the missing type A1 + ---------- + 3. ERROR in p2\\C.java (at line 7) + b.m(this, b); + ^ + The method m(Object, A1...) from the type B refers to the missing type A1 + ---------- + 4. ERROR in p2\\C.java (at line 8) + b.m(this, b, b); + ^ + The method m(Object, A1...) from the type B refers to the missing type A1 + ---------- + 5. ERROR in p2\\C.java (at line 9) + b.m(this, new B[0]); + ^ + The method m(Object, A1...) from the type B refers to the missing type A1 + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClassNeededForOverloadResolution_varargs1d() { + // like testMissingClassNeededForOverloadResolution_varargs1c, but no preceding regular parameter + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A1.java", + """ + package p1; + public class A1 {} + """, + "p1/A2.java", + """ + package p1; + public class A2 {} + """, + "p1/B.java", + """ + package p1; + public class B { + public void m(A1... a) {} + public void m(A2... a) {} + } + """ + }; + runner.runConformTest(); + + // delete binary files A1, A1 (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A1.class")); + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A2.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + b.m(); // simply ambiguous as we don't even look at A1 or A2 + b.m(null); + b.m(b); + b.m(b, b); + b.m(new B[0]); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + b.m(); // simply ambiguous as we don't even look at A1 or A2 + ^ + The method m(A1[]) is ambiguous for the type B + ---------- + 2. ERROR in p2\\C.java (at line 6) + b.m(null); + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + 3. ERROR in p2\\C.java (at line 7) + b.m(b); + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + 4. ERROR in p2\\C.java (at line 8) + b.m(b, b); + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + 5. ERROR in p2\\C.java (at line 9) + b.m(new B[0]); + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClassNeededForOverloadResolution_varargs2() { + // different arities if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); runner.customOptions = getCompilerOptions(); @@ -8951,7 +9270,8 @@ The method n(Object, A...) from the type B refers to the missing type A """; runner.runNegativeTest(); } -public void testMissingClassNeededForOverloadResolution_varargs2() { +public void testMissingClassNeededForOverloadResolution_varargs3() { + // missing type in non-varargs position if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); runner.testFiles = new String[] { From 23a695396f645f75ffe3cdf7bbd03b812bacb1fe Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Sat, 22 Jun 2024 14:34:06 +0200 Subject: [PATCH 05/16] tests for missing method return type (positive / negative) + ignore missing return type if not needed for further resolving - distinguish by expression context (vanilla -> not needed) - but for send in receiver position report despite vanilla context + avoid resolving MemberValuePair.value in expressionContext VANILLA --- .../jdt/internal/compiler/ClassFile.java | 4 +- .../internal/compiler/ast/ArrayReference.java | 5 +- .../internal/compiler/ast/FieldReference.java | 5 +- .../compiler/ast/MemberValuePair.java | 4 +- .../internal/compiler/ast/MessageSend.java | 8 + .../compiler/lookup/MethodBinding.java | 6 +- .../compiler/problem/ProblemReporter.java | 6 +- .../tests/compiler/regression/LookupTest.java | 12 +- .../regression/ProblemTypeAndMethodTest.java | 156 ++++++++++++++++-- 9 files changed, 175 insertions(+), 31 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ClassFile.java index 76a6b1841a2..41d8f3518ca 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ClassFile.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ClassFile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2023 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -4485,7 +4485,7 @@ public int generateMethodInfoAttributes(MethodBinding methodBinding) { } } if ((methodBinding.tagBits & TagBits.HasMissingType) != 0) { - this.missingTypes = methodBinding.collectMissingTypes(this.missingTypes); + this.missingTypes = methodBinding.collectMissingTypes(this.missingTypes, true); } return attributesNumber; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java index a5470eb9e64..fd5d586538b 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -208,6 +208,9 @@ public TypeBinding resolveType(BlockScope scope) { && ((CastExpression)this.receiver).innermostCastedExpression() instanceof NullLiteral) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on } + if (this.receiver instanceof MessageSend) { + ((MessageSend) this.receiver).isReceiver = true; + } TypeBinding arrayType = this.receiver.resolveType(scope); if (arrayType != null) { this.receiver.computeConversion(scope, arrayType, arrayType); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java index 811b8587ef7..8d2f5333138 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -661,6 +661,9 @@ public TypeBinding resolveType(BlockScope scope) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on receiverCast = true; } + if (this.receiver instanceof MessageSend) { + ((MessageSend) this.receiver).isReceiver = true; + } this.actualReceiverType = this.receiver.resolveType(scope); if (this.actualReceiverType == null) { this.constant = Constant.NotAConstant; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java index 7511228540b..a4405319bc5 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -69,6 +69,8 @@ public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) { this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding); return; } + // the following is not really useful, but let's humor the resolution even if value is not a constant + this.value.setExpressionContext(ExpressionContext.ASSIGNMENT_CONTEXT); if (requiredType == null) { // fault tolerance: keep resolving if (this.value instanceof ArrayInitializer) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index 250e816928a..f8863661f47 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -136,6 +136,7 @@ public class MessageSend extends Expression implements IPolyExpression, Invocati public TypeReference[] typeArguments; public TypeBinding[] genericTypeArguments; public ExpressionContext expressionContext = VANILLA_CONTEXT; + public boolean isReceiver = false; // hold on to this context from invocation applicability inference until invocation type inference (per method candidate): private SimpleLookupTable/**/ inferenceContexts; @@ -811,6 +812,9 @@ public TypeBinding resolveType(BlockScope scope) { if (this.receiver instanceof CastExpression) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on } + if (this.receiver instanceof MessageSend) { + ((MessageSend) this.receiver).isReceiver = true; + } this.actualReceiverType = this.receiver.resolveType(scope); if (this.actualReceiverType instanceof InferenceVariable) { return null; // not yet ready for resolving @@ -1113,6 +1117,10 @@ protected boolean isUnnecessaryReceiverCast(BlockScope scope, TypeBinding uncast } protected boolean isMissingTypeRelevant() { + if (this.expressionContext == ExpressionContext.VANILLA_CONTEXT && !this.isReceiver) { + if (this.binding.collectMissingTypes(null, false) == null) + return false; // only irrelevant return type is missing + } if ((this.binding.returnType.tagBits & TagBits.HasMissingType) == 0 && this.binding.isVarargs()) { if (this.arguments.length < this.binding.parameters.length) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java index fa74db4f09f..be5c7ac183d 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java @@ -413,9 +413,11 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca return false; } -public List collectMissingTypes(List missingTypes) { +public List collectMissingTypes(List missingTypes, boolean considerReturnType) { if ((this.tagBits & TagBits.HasMissingType) != 0) { - missingTypes = this.returnType.collectMissingTypes(missingTypes); + if (considerReturnType) { + missingTypes = this.returnType.collectMissingTypes(missingTypes); + } for (TypeBinding parameter : this.parameters) { missingTypes = parameter.collectMissingTypes(missingTypes); } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 063986d6e98..cae43ed23bb 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -6951,7 +6951,7 @@ public void missingSynchronizedOnInheritedMethod(MethodBinding currentMethod, Me currentMethod.sourceEnd()); } public void missingTypeInConstructor(ASTNode location, MethodBinding constructor) { - List missingTypes = constructor.collectMissingTypes(null); + List missingTypes = constructor.collectMissingTypes(null, true); if (missingTypes == null) { System.err.println("The constructor " + constructor + " is wrongly tagged as containing missing types"); //$NON-NLS-1$ //$NON-NLS-2$ return; @@ -6984,7 +6984,7 @@ public void missingTypeInConstructor(ASTNode location, MethodBinding constructor public void missingTypeInLambda(LambdaExpression lambda, MethodBinding method) { int nameSourceStart = lambda.sourceStart(); int nameSourceEnd = lambda.diagnosticsSourceEnd(); - List missingTypes = method.collectMissingTypes(null); + List missingTypes = method.collectMissingTypes(null, true); if (missingTypes == null) { System.err.println("The lambda expression " + method + " is wrongly tagged as containing missing types"); //$NON-NLS-1$ //$NON-NLS-2$ return; @@ -7011,7 +7011,7 @@ public void missingTypeInMethod(ASTNode astNode, MethodBinding method) { nameSourceStart = astNode.sourceStart; nameSourceEnd = astNode.sourceEnd; } - List missingTypes = method.collectMissingTypes(null); + List missingTypes = method.collectMissingTypes(null, true); if (missingTypes == null) { System.err.println("The method " + method + " is wrongly tagged as containing missing types"); //$NON-NLS-1$ //$NON-NLS-2$ return; diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LookupTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LookupTest.java index 9ab267f7327..a011541d5e1 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LookupTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LookupTest.java @@ -1907,7 +1907,7 @@ public void test059() { " Zork bb() {\n" + " }\n" + " void cc() {\n" + - " this.bb();\n" + + " Object o = this.bb();\n" + " }\n" + " public static void main(String[] args) {\n" + " System.out.println(\"SUCCESS\");\n" + @@ -1921,8 +1921,8 @@ public void test059() { "Zork cannot be resolved to a type\n" + "----------\n" + "2. ERROR in X.java (at line 10)\n" + - " this.bb();\n" + - " ^^\n" + + " Object o = this.bb();\n" + + " ^^\n" + "The method bb() from the type X refers to the missing type Zork\n" + "----------\n"); } @@ -1940,7 +1940,7 @@ public void test060() { " Zork bb() {\n" + " }\n" + " void cc() {\n" + - " this.bb();\n" + + " Object o = this.bb();\n" + " }\n" + " public static void main(String[] args) {\n" + " System.out.println(\"SUCCESS\");\n" + @@ -1959,8 +1959,8 @@ public void test060() { "Zork cannot be resolved to a type\n" + "----------\n" + "3. ERROR in X.java (at line 10)\n" + - " this.bb();\n" + - " ^^\n" + + " Object o = this.bb();\n" + + " ^^\n" + "The method bb() from the type X refers to the missing type Zork\n" + "----------\n"); } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index 613085f3399..583dde889ef 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -486,8 +486,9 @@ public void test005() { "public class X {\n" + " void foo() {\n" + " p.OtherFoo ofoo = new p.OtherFoo();\n" + - " ofoo.bar();\n" + + " Object o = ofoo.bar();\n" + " q1.q2.Zork z;\n" + + " ofoo.bar();\n" + // not a problem " }\n" + "} \n", }, @@ -497,8 +498,8 @@ public void test005() { // compiler results "----------\n" + /* expected compiler log */ "1. ERROR in X.java (at line 4)\n" + - " ofoo.bar();\n" + - " ^^^\n" + + " Object o = ofoo.bar();\n" + + " ^^^\n" + "The method bar() from the type OtherFoo refers to the missing type Zork\n" + "----------\n" + "2. ERROR in X.java (at line 5)\n" + @@ -559,12 +560,7 @@ public void test006() { " ^^\n" + "The import q1 cannot be resolved\n" + "----------\n" + - "2. ERROR in X.java (at line 5)\n" + - " ofoo.bar();\n" + - " ^^^\n" + - "The method bar() from the type OtherFoo refers to the missing type Zork\n" + - "----------\n" + - "3. ERROR in X.java (at line 6)\n" + + "2. ERROR in X.java (at line 6)\n" + " Zork z;\n" + " ^^^^\n" + "Zork cannot be resolved to a type\n" + @@ -607,7 +603,7 @@ public void test007() { "public class X {\n" + " void foo() {\n" + " p.OtherFoo ofoo = new p.OtherFoo();\n" + - " ofoo.bar();\n" + + " Object o = ofoo.bar();\n" + " Zork z;\n" + " }\n" + "} \n", @@ -623,8 +619,8 @@ public void test007() { "The import q1 cannot be resolved\n" + "----------\n" + "2. ERROR in X.java (at line 5)\n" + - " ofoo.bar();\n" + - " ^^^\n" + + " Object o = ofoo.bar();\n" + + " ^^^\n" + "The method bar() from the type OtherFoo refers to the missing type Zork\n" + "----------\n" + "3. ERROR in X.java (at line 6)\n" + @@ -3439,8 +3435,8 @@ public void test074() { "The method bar1() from the type X refers to the missing type Zork\n" + "----------\n" + "2. ERROR in X.java (at line 5)\n" + - " bar2();\n" + - " ^^^^\n" + + " Object o = bar2();\n" + + " ^^^^\n" + "The method bar2() from the type X refers to the missing type Zork\n" + "----------\n" + "3. ERROR in X.java (at line 6)\n" + @@ -3481,7 +3477,7 @@ public void test074() { "public class X {\n" + " void foo() {\n" + " bar1().foo();\n" + - " bar2();\n" + + " Object o = bar2();\n" + " bar3(null);\n" + " bar4(null,null);\n" + " }\n" + @@ -9319,4 +9315,134 @@ The method m(A, String...) from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClass_returnType_OK() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A { + public A() { System.out.print("new A()"); } + } + """, + "p1/B.java", + """ + package p1; + public class B { + public A m(Object o) { + System.out.print("B.m()"); + return new A(); + } + } + """ + }; + runner.runConformTest(); + + // temporarily move A.class to A.moved (i.e. simulate removing it from classpath for the next compile) + File classFileA = new File(OUTPUT_DIR, "p1" + File.separator + "A.class"); + File movedFileA = new File(OUTPUT_DIR, "p1" + File.separator + "A.moved"); + classFileA.renameTo(movedFileA); + runner.shouldFlushOutputDirectory = false; + + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C extends B { + void test(B b) { + b.m(this); + } + } + """ + }; + runner.expectedErrorString = "java.lang.NoClassDefFoundError: p1/A\n"; + runner.runConformTest(); + + runner.testFiles = new String[] { + "p2/Main.java", + """ + package p2; + import p1.B; + public class Main { + public static void main(String... args) { + new C().test(new B()); + System.out.print("SUCCESS"); + } + } + """ + }; + // restore A.class and expect execution of Main to succeed + movedFileA.renameTo(classFileA); + runner.expectedOutputString = "B.m()new A()SUCCESS"; + runner.shouldFlushOutputDirectory = false; + runner.expectedErrorString = null; + runner.runConformTest(); +} +public void testMissingClass_returnType_NOK() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + public class B { + public A m(Object o) { return new A(); } + public void n(A a) {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C extends B { + void test(B b) { + B b2 = b.m(this); + b.n(b.m(this)); + } + @Override + public B m(Object o) { return super.m(o); } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + B b2 = b.m(this); + ^ + The method m(Object) from the type B refers to the missing type A + ---------- + 2. ERROR in p2\\C.java (at line 6) + b.n(b.m(this)); + ^ + The method m(Object) from the type B refers to the missing type A + ---------- + 3. ERROR in p2\\C.java (at line 9) + public B m(Object o) { return super.m(o); } + ^ + The return type is incompatible with B.m(Object) + ---------- + 4. ERROR in p2\\C.java (at line 9) + public B m(Object o) { return super.m(o); } + ^ + The method m(Object) from the type B refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} } From 2ed31bef17681282ee6040236b229c24ab809bdc Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Sat, 22 Jun 2024 18:21:29 +0200 Subject: [PATCH 06/16] expect fewer errors --- .../core/tests/dom/ASTConverterAST3Test.java | 97 +++++++++++++++-- .../core/tests/dom/ASTConverterAST4Test.java | 97 +++++++++++++++-- .../core/tests/dom/ASTConverterAST8Test.java | 97 +++++++++++++++-- .../jdt/core/tests/dom/ASTConverterTest.java | 100 ++++++++++++++++-- 4 files changed, 359 insertions(+), 32 deletions(-) diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java index ba8f5097e98..cdd9376ec26 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java @@ -14,15 +14,96 @@ package org.eclipse.jdt.core.tests.dom; -import java.util.*; +import java.util.Enumeration; +import java.util.List; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTMatcher; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; +import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; +import org.eclipse.jdt.core.dom.ArrayCreation; +import org.eclipse.jdt.core.dom.ArrayInitializer; +import org.eclipse.jdt.core.dom.ArrayType; +import org.eclipse.jdt.core.dom.Assignment; +import org.eclipse.jdt.core.dom.Block; +import org.eclipse.jdt.core.dom.BodyDeclaration; +import org.eclipse.jdt.core.dom.BooleanLiteral; +import org.eclipse.jdt.core.dom.BreakStatement; +import org.eclipse.jdt.core.dom.CastExpression; +import org.eclipse.jdt.core.dom.CatchClause; +import org.eclipse.jdt.core.dom.CharacterLiteral; +import org.eclipse.jdt.core.dom.ClassInstanceCreation; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ConditionalExpression; +import org.eclipse.jdt.core.dom.ContinueStatement; +import org.eclipse.jdt.core.dom.DoStatement; +import org.eclipse.jdt.core.dom.EmptyStatement; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ExpressionStatement; +import org.eclipse.jdt.core.dom.FieldAccess; +import org.eclipse.jdt.core.dom.FieldDeclaration; +import org.eclipse.jdt.core.dom.ForStatement; +import org.eclipse.jdt.core.dom.IBinding; +import org.eclipse.jdt.core.dom.IMethodBinding; +import org.eclipse.jdt.core.dom.IPackageBinding; +import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.IVariableBinding; +import org.eclipse.jdt.core.dom.IfStatement; +import org.eclipse.jdt.core.dom.ImportDeclaration; +import org.eclipse.jdt.core.dom.InfixExpression; +import org.eclipse.jdt.core.dom.Initializer; +import org.eclipse.jdt.core.dom.InstanceofExpression; +import org.eclipse.jdt.core.dom.Javadoc; +import org.eclipse.jdt.core.dom.LabeledStatement; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.Modifier; +import org.eclipse.jdt.core.dom.Name; +import org.eclipse.jdt.core.dom.NullLiteral; +import org.eclipse.jdt.core.dom.NumberLiteral; +import org.eclipse.jdt.core.dom.PackageDeclaration; +import org.eclipse.jdt.core.dom.ParenthesizedExpression; +import org.eclipse.jdt.core.dom.PostfixExpression; +import org.eclipse.jdt.core.dom.PrefixExpression; +import org.eclipse.jdt.core.dom.PrimitiveType; +import org.eclipse.jdt.core.dom.QualifiedName; +import org.eclipse.jdt.core.dom.ReturnStatement; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SimpleType; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; +import org.eclipse.jdt.core.dom.Statement; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.SuperConstructorInvocation; +import org.eclipse.jdt.core.dom.SuperFieldAccess; +import org.eclipse.jdt.core.dom.SuperMethodInvocation; +import org.eclipse.jdt.core.dom.SwitchCase; +import org.eclipse.jdt.core.dom.SwitchStatement; +import org.eclipse.jdt.core.dom.SynchronizedStatement; +import org.eclipse.jdt.core.dom.ThisExpression; +import org.eclipse.jdt.core.dom.ThrowStatement; +import org.eclipse.jdt.core.dom.TryStatement; +import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.TypeDeclarationStatement; +import org.eclipse.jdt.core.dom.TypeLiteral; +import org.eclipse.jdt.core.dom.VariableDeclarationExpression; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; +import org.eclipse.jdt.core.dom.VariableDeclarationStatement; +import org.eclipse.jdt.core.dom.WhileStatement; +import org.eclipse.jdt.core.jdom.DOMFactory; +import org.eclipse.jdt.core.jdom.IDOMCompilationUnit; +import org.eclipse.jdt.core.jdom.IDOMMethod; +import org.eclipse.jdt.core.jdom.IDOMNode; +import org.eclipse.jdt.core.jdom.IDOMType; +import org.eclipse.jdt.core.util.IModifierConstants; import junit.framework.Test; -import org.eclipse.jdt.core.*; -import org.eclipse.jdt.core.dom.*; -import org.eclipse.jdt.core.jdom.*; -import org.eclipse.jdt.core.util.IModifierConstants; - @SuppressWarnings({"rawtypes"}) public class ASTConverterAST3Test extends ConverterTestSetup { @@ -6995,8 +7076,8 @@ public void test0295() throws JavaModelException { assertNotNull("No compilation unit", result); //$NON-NLS-1$ assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$ CompilationUnit compilationUnit = (CompilationUnit) result; - assertEquals("Wrong size", 2, compilationUnit.getMessages().length); //$NON-NLS-1$ - assertEquals("Wrong size", 2, compilationUnit.getProblems().length); //$NON-NLS-1$ + assertEquals("Wrong size", 1, compilationUnit.getMessages().length); //$NON-NLS-1$ + assertEquals("Wrong size", 1, compilationUnit.getProblems().length); //$NON-NLS-1$ ASTNode node = getASTNode(compilationUnit, 0, 1, 0); assertTrue("Not an ExpressionStatement", node instanceof ExpressionStatement); //$NON-NLS-1$ ExpressionStatement expressionStatement = (ExpressionStatement) node; diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java index 936cff67fcc..3db9d82ed29 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java @@ -14,15 +14,96 @@ package org.eclipse.jdt.core.tests.dom; -import java.util.*; +import java.util.Enumeration; +import java.util.List; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTMatcher; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; +import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; +import org.eclipse.jdt.core.dom.ArrayCreation; +import org.eclipse.jdt.core.dom.ArrayInitializer; +import org.eclipse.jdt.core.dom.ArrayType; +import org.eclipse.jdt.core.dom.Assignment; +import org.eclipse.jdt.core.dom.Block; +import org.eclipse.jdt.core.dom.BodyDeclaration; +import org.eclipse.jdt.core.dom.BooleanLiteral; +import org.eclipse.jdt.core.dom.BreakStatement; +import org.eclipse.jdt.core.dom.CastExpression; +import org.eclipse.jdt.core.dom.CatchClause; +import org.eclipse.jdt.core.dom.CharacterLiteral; +import org.eclipse.jdt.core.dom.ClassInstanceCreation; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ConditionalExpression; +import org.eclipse.jdt.core.dom.ContinueStatement; +import org.eclipse.jdt.core.dom.DoStatement; +import org.eclipse.jdt.core.dom.EmptyStatement; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ExpressionStatement; +import org.eclipse.jdt.core.dom.FieldAccess; +import org.eclipse.jdt.core.dom.FieldDeclaration; +import org.eclipse.jdt.core.dom.ForStatement; +import org.eclipse.jdt.core.dom.IBinding; +import org.eclipse.jdt.core.dom.IMethodBinding; +import org.eclipse.jdt.core.dom.IPackageBinding; +import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.IVariableBinding; +import org.eclipse.jdt.core.dom.IfStatement; +import org.eclipse.jdt.core.dom.ImportDeclaration; +import org.eclipse.jdt.core.dom.InfixExpression; +import org.eclipse.jdt.core.dom.Initializer; +import org.eclipse.jdt.core.dom.InstanceofExpression; +import org.eclipse.jdt.core.dom.Javadoc; +import org.eclipse.jdt.core.dom.LabeledStatement; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.Modifier; +import org.eclipse.jdt.core.dom.Name; +import org.eclipse.jdt.core.dom.NullLiteral; +import org.eclipse.jdt.core.dom.NumberLiteral; +import org.eclipse.jdt.core.dom.PackageDeclaration; +import org.eclipse.jdt.core.dom.ParenthesizedExpression; +import org.eclipse.jdt.core.dom.PostfixExpression; +import org.eclipse.jdt.core.dom.PrefixExpression; +import org.eclipse.jdt.core.dom.PrimitiveType; +import org.eclipse.jdt.core.dom.QualifiedName; +import org.eclipse.jdt.core.dom.ReturnStatement; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SimpleType; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; +import org.eclipse.jdt.core.dom.Statement; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.SuperConstructorInvocation; +import org.eclipse.jdt.core.dom.SuperFieldAccess; +import org.eclipse.jdt.core.dom.SuperMethodInvocation; +import org.eclipse.jdt.core.dom.SwitchCase; +import org.eclipse.jdt.core.dom.SwitchStatement; +import org.eclipse.jdt.core.dom.SynchronizedStatement; +import org.eclipse.jdt.core.dom.ThisExpression; +import org.eclipse.jdt.core.dom.ThrowStatement; +import org.eclipse.jdt.core.dom.TryStatement; +import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.TypeDeclarationStatement; +import org.eclipse.jdt.core.dom.TypeLiteral; +import org.eclipse.jdt.core.dom.VariableDeclarationExpression; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; +import org.eclipse.jdt.core.dom.VariableDeclarationStatement; +import org.eclipse.jdt.core.dom.WhileStatement; +import org.eclipse.jdt.core.jdom.DOMFactory; +import org.eclipse.jdt.core.jdom.IDOMCompilationUnit; +import org.eclipse.jdt.core.jdom.IDOMMethod; +import org.eclipse.jdt.core.jdom.IDOMNode; +import org.eclipse.jdt.core.jdom.IDOMType; +import org.eclipse.jdt.core.util.IModifierConstants; import junit.framework.Test; -import org.eclipse.jdt.core.*; -import org.eclipse.jdt.core.dom.*; -import org.eclipse.jdt.core.jdom.*; -import org.eclipse.jdt.core.util.IModifierConstants; - @SuppressWarnings({"rawtypes"}) public class ASTConverterAST4Test extends ConverterTestSetup { @@ -6995,8 +7076,8 @@ public void test0295() throws JavaModelException { assertNotNull("No compilation unit", result); //$NON-NLS-1$ assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$ CompilationUnit compilationUnit = (CompilationUnit) result; - assertEquals("Wrong size", 2, compilationUnit.getMessages().length); //$NON-NLS-1$ - assertEquals("Wrong size", 2, compilationUnit.getProblems().length); //$NON-NLS-1$ + assertEquals("Wrong size", 1, compilationUnit.getMessages().length); //$NON-NLS-1$ + assertEquals("Wrong size", 1, compilationUnit.getProblems().length); //$NON-NLS-1$ ASTNode node = getASTNode(compilationUnit, 0, 1, 0); assertTrue("Not an ExpressionStatement", node instanceof ExpressionStatement); //$NON-NLS-1$ ExpressionStatement expressionStatement = (ExpressionStatement) node; diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java index 4e1bc1df2f6..cb09972890d 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java @@ -14,15 +14,96 @@ package org.eclipse.jdt.core.tests.dom; -import java.util.*; +import java.util.Enumeration; +import java.util.List; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTMatcher; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; +import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; +import org.eclipse.jdt.core.dom.ArrayCreation; +import org.eclipse.jdt.core.dom.ArrayInitializer; +import org.eclipse.jdt.core.dom.ArrayType; +import org.eclipse.jdt.core.dom.Assignment; +import org.eclipse.jdt.core.dom.Block; +import org.eclipse.jdt.core.dom.BodyDeclaration; +import org.eclipse.jdt.core.dom.BooleanLiteral; +import org.eclipse.jdt.core.dom.BreakStatement; +import org.eclipse.jdt.core.dom.CastExpression; +import org.eclipse.jdt.core.dom.CatchClause; +import org.eclipse.jdt.core.dom.CharacterLiteral; +import org.eclipse.jdt.core.dom.ClassInstanceCreation; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ConditionalExpression; +import org.eclipse.jdt.core.dom.ContinueStatement; +import org.eclipse.jdt.core.dom.DoStatement; +import org.eclipse.jdt.core.dom.EmptyStatement; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ExpressionStatement; +import org.eclipse.jdt.core.dom.FieldAccess; +import org.eclipse.jdt.core.dom.FieldDeclaration; +import org.eclipse.jdt.core.dom.ForStatement; +import org.eclipse.jdt.core.dom.IBinding; +import org.eclipse.jdt.core.dom.IMethodBinding; +import org.eclipse.jdt.core.dom.IPackageBinding; +import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.IVariableBinding; +import org.eclipse.jdt.core.dom.IfStatement; +import org.eclipse.jdt.core.dom.ImportDeclaration; +import org.eclipse.jdt.core.dom.InfixExpression; +import org.eclipse.jdt.core.dom.Initializer; +import org.eclipse.jdt.core.dom.InstanceofExpression; +import org.eclipse.jdt.core.dom.Javadoc; +import org.eclipse.jdt.core.dom.LabeledStatement; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.Modifier; +import org.eclipse.jdt.core.dom.Name; +import org.eclipse.jdt.core.dom.NullLiteral; +import org.eclipse.jdt.core.dom.NumberLiteral; +import org.eclipse.jdt.core.dom.PackageDeclaration; +import org.eclipse.jdt.core.dom.ParenthesizedExpression; +import org.eclipse.jdt.core.dom.PostfixExpression; +import org.eclipse.jdt.core.dom.PrefixExpression; +import org.eclipse.jdt.core.dom.PrimitiveType; +import org.eclipse.jdt.core.dom.QualifiedName; +import org.eclipse.jdt.core.dom.ReturnStatement; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SimpleType; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; +import org.eclipse.jdt.core.dom.Statement; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.SuperConstructorInvocation; +import org.eclipse.jdt.core.dom.SuperFieldAccess; +import org.eclipse.jdt.core.dom.SuperMethodInvocation; +import org.eclipse.jdt.core.dom.SwitchCase; +import org.eclipse.jdt.core.dom.SwitchStatement; +import org.eclipse.jdt.core.dom.SynchronizedStatement; +import org.eclipse.jdt.core.dom.ThisExpression; +import org.eclipse.jdt.core.dom.ThrowStatement; +import org.eclipse.jdt.core.dom.TryStatement; +import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.TypeDeclarationStatement; +import org.eclipse.jdt.core.dom.TypeLiteral; +import org.eclipse.jdt.core.dom.VariableDeclarationExpression; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; +import org.eclipse.jdt.core.dom.VariableDeclarationStatement; +import org.eclipse.jdt.core.dom.WhileStatement; +import org.eclipse.jdt.core.jdom.DOMFactory; +import org.eclipse.jdt.core.jdom.IDOMCompilationUnit; +import org.eclipse.jdt.core.jdom.IDOMMethod; +import org.eclipse.jdt.core.jdom.IDOMNode; +import org.eclipse.jdt.core.jdom.IDOMType; +import org.eclipse.jdt.core.util.IModifierConstants; import junit.framework.Test; -import org.eclipse.jdt.core.*; -import org.eclipse.jdt.core.dom.*; -import org.eclipse.jdt.core.jdom.*; -import org.eclipse.jdt.core.util.IModifierConstants; - @SuppressWarnings({"rawtypes"}) public class ASTConverterAST8Test extends ConverterTestSetup { @@ -6993,8 +7074,8 @@ public void test0295() throws JavaModelException { assertNotNull("No compilation unit", result); //$NON-NLS-1$ assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$ CompilationUnit compilationUnit = (CompilationUnit) result; - assertEquals("Wrong size", 2, compilationUnit.getMessages().length); //$NON-NLS-1$ - assertEquals("Wrong size", 2, compilationUnit.getProblems().length); //$NON-NLS-1$ + assertEquals("Wrong size", 1, compilationUnit.getMessages().length); //$NON-NLS-1$ + assertEquals("Wrong size", 1, compilationUnit.getProblems().length); //$NON-NLS-1$ ASTNode node = getASTNode(compilationUnit, 0, 1, 0); assertTrue("Not an ExpressionStatement", node instanceof ExpressionStatement); //$NON-NLS-1$ ExpressionStatement expressionStatement = (ExpressionStatement) node; diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java index 84291dfa06c..0a704c4ccfc 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java @@ -14,17 +14,101 @@ package org.eclipse.jdt.core.tests.dom; -import java.util.*; - -import junit.framework.Test; +import java.util.Enumeration; +import java.util.List; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; -import org.eclipse.jdt.core.*; -import org.eclipse.jdt.core.dom.*; -import org.eclipse.jdt.core.jdom.*; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTMatcher; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; +import org.eclipse.jdt.core.dom.ArrayCreation; +import org.eclipse.jdt.core.dom.ArrayInitializer; +import org.eclipse.jdt.core.dom.ArrayType; +import org.eclipse.jdt.core.dom.Assignment; +import org.eclipse.jdt.core.dom.Block; +import org.eclipse.jdt.core.dom.BodyDeclaration; +import org.eclipse.jdt.core.dom.BooleanLiteral; +import org.eclipse.jdt.core.dom.BreakStatement; +import org.eclipse.jdt.core.dom.CastExpression; +import org.eclipse.jdt.core.dom.CatchClause; +import org.eclipse.jdt.core.dom.CharacterLiteral; +import org.eclipse.jdt.core.dom.ClassInstanceCreation; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ConditionalExpression; +import org.eclipse.jdt.core.dom.ContinueStatement; +import org.eclipse.jdt.core.dom.DoStatement; +import org.eclipse.jdt.core.dom.EmptyStatement; +import org.eclipse.jdt.core.dom.EnumConstantDeclaration; +import org.eclipse.jdt.core.dom.EnumDeclaration; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ExpressionStatement; +import org.eclipse.jdt.core.dom.FieldAccess; +import org.eclipse.jdt.core.dom.FieldDeclaration; +import org.eclipse.jdt.core.dom.ForStatement; +import org.eclipse.jdt.core.dom.IBinding; +import org.eclipse.jdt.core.dom.IMethodBinding; +import org.eclipse.jdt.core.dom.IPackageBinding; +import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.IVariableBinding; +import org.eclipse.jdt.core.dom.IfStatement; +import org.eclipse.jdt.core.dom.ImportDeclaration; +import org.eclipse.jdt.core.dom.InfixExpression; +import org.eclipse.jdt.core.dom.Initializer; +import org.eclipse.jdt.core.dom.InstanceofExpression; +import org.eclipse.jdt.core.dom.Javadoc; +import org.eclipse.jdt.core.dom.LabeledStatement; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.Modifier; +import org.eclipse.jdt.core.dom.Name; +import org.eclipse.jdt.core.dom.NullLiteral; +import org.eclipse.jdt.core.dom.NumberLiteral; +import org.eclipse.jdt.core.dom.PackageDeclaration; +import org.eclipse.jdt.core.dom.ParenthesizedExpression; +import org.eclipse.jdt.core.dom.PostfixExpression; +import org.eclipse.jdt.core.dom.PrefixExpression; +import org.eclipse.jdt.core.dom.PrimitiveType; +import org.eclipse.jdt.core.dom.QualifiedName; +import org.eclipse.jdt.core.dom.ReturnStatement; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SimpleType; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; +import org.eclipse.jdt.core.dom.Statement; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.SuperConstructorInvocation; +import org.eclipse.jdt.core.dom.SuperFieldAccess; +import org.eclipse.jdt.core.dom.SuperMethodInvocation; +import org.eclipse.jdt.core.dom.SwitchCase; +import org.eclipse.jdt.core.dom.SwitchStatement; +import org.eclipse.jdt.core.dom.SynchronizedStatement; +import org.eclipse.jdt.core.dom.ThisExpression; +import org.eclipse.jdt.core.dom.ThrowStatement; +import org.eclipse.jdt.core.dom.TryStatement; +import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.TypeDeclarationStatement; +import org.eclipse.jdt.core.dom.TypeLiteral; +import org.eclipse.jdt.core.dom.VariableDeclarationExpression; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; +import org.eclipse.jdt.core.dom.VariableDeclarationStatement; +import org.eclipse.jdt.core.dom.WhileStatement; +import org.eclipse.jdt.core.jdom.DOMFactory; +import org.eclipse.jdt.core.jdom.IDOMCompilationUnit; +import org.eclipse.jdt.core.jdom.IDOMMethod; +import org.eclipse.jdt.core.jdom.IDOMNode; +import org.eclipse.jdt.core.jdom.IDOMType; import org.eclipse.jdt.core.util.IModifierConstants; +import junit.framework.Test; + @SuppressWarnings("rawtypes") public class ASTConverterTest extends ConverterTestSetup { @@ -7160,8 +7244,8 @@ public void test0295() throws JavaModelException { assertNotNull("No compilation unit", result); //$NON-NLS-1$ assertTrue("result is not a compilation unit", result instanceof CompilationUnit); //$NON-NLS-1$ CompilationUnit compilationUnit = (CompilationUnit) result; - assertEquals("Wrong size", 2, compilationUnit.getMessages().length); //$NON-NLS-1$ - assertEquals("Wrong size", 2, compilationUnit.getProblems().length); //$NON-NLS-1$ + assertEquals("Wrong size", 1, compilationUnit.getMessages().length); //$NON-NLS-1$ + assertEquals("Wrong size", 1, compilationUnit.getProblems().length); //$NON-NLS-1$ ASTNode node = getASTNode(compilationUnit, 0, 1, 0); assertTrue("Not an ExpressionStatement", node instanceof ExpressionStatement); //$NON-NLS-1$ ExpressionStatement expressionStatement = (ExpressionStatement) node; From 4c96803f8f28560cf73483078f97b5b257981e80 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Sat, 22 Jun 2024 19:54:06 +0200 Subject: [PATCH 07/16] restore original, warning-free imports --- .../core/tests/dom/ASTConverterAST3Test.java | 93 ++---------------- .../core/tests/dom/ASTConverterAST4Test.java | 93 ++---------------- .../core/tests/dom/ASTConverterAST8Test.java | 93 ++---------------- .../jdt/core/tests/dom/ASTConverterTest.java | 96 ++----------------- 4 files changed, 24 insertions(+), 351 deletions(-) diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java index cdd9376ec26..0f86b176244 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java @@ -14,96 +14,15 @@ package org.eclipse.jdt.core.tests.dom; -import java.util.Enumeration; -import java.util.List; - -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTMatcher; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; -import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; -import org.eclipse.jdt.core.dom.ArrayCreation; -import org.eclipse.jdt.core.dom.ArrayInitializer; -import org.eclipse.jdt.core.dom.ArrayType; -import org.eclipse.jdt.core.dom.Assignment; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.BodyDeclaration; -import org.eclipse.jdt.core.dom.BooleanLiteral; -import org.eclipse.jdt.core.dom.BreakStatement; -import org.eclipse.jdt.core.dom.CastExpression; -import org.eclipse.jdt.core.dom.CatchClause; -import org.eclipse.jdt.core.dom.CharacterLiteral; -import org.eclipse.jdt.core.dom.ClassInstanceCreation; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ConditionalExpression; -import org.eclipse.jdt.core.dom.ContinueStatement; -import org.eclipse.jdt.core.dom.DoStatement; -import org.eclipse.jdt.core.dom.EmptyStatement; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.ExpressionStatement; -import org.eclipse.jdt.core.dom.FieldAccess; -import org.eclipse.jdt.core.dom.FieldDeclaration; -import org.eclipse.jdt.core.dom.ForStatement; -import org.eclipse.jdt.core.dom.IBinding; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.IPackageBinding; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.IVariableBinding; -import org.eclipse.jdt.core.dom.IfStatement; -import org.eclipse.jdt.core.dom.ImportDeclaration; -import org.eclipse.jdt.core.dom.InfixExpression; -import org.eclipse.jdt.core.dom.Initializer; -import org.eclipse.jdt.core.dom.InstanceofExpression; -import org.eclipse.jdt.core.dom.Javadoc; -import org.eclipse.jdt.core.dom.LabeledStatement; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.Modifier; -import org.eclipse.jdt.core.dom.Name; -import org.eclipse.jdt.core.dom.NullLiteral; -import org.eclipse.jdt.core.dom.NumberLiteral; -import org.eclipse.jdt.core.dom.PackageDeclaration; -import org.eclipse.jdt.core.dom.ParenthesizedExpression; -import org.eclipse.jdt.core.dom.PostfixExpression; -import org.eclipse.jdt.core.dom.PrefixExpression; -import org.eclipse.jdt.core.dom.PrimitiveType; -import org.eclipse.jdt.core.dom.QualifiedName; -import org.eclipse.jdt.core.dom.ReturnStatement; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SimpleType; -import org.eclipse.jdt.core.dom.SingleVariableDeclaration; -import org.eclipse.jdt.core.dom.Statement; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.SuperConstructorInvocation; -import org.eclipse.jdt.core.dom.SuperFieldAccess; -import org.eclipse.jdt.core.dom.SuperMethodInvocation; -import org.eclipse.jdt.core.dom.SwitchCase; -import org.eclipse.jdt.core.dom.SwitchStatement; -import org.eclipse.jdt.core.dom.SynchronizedStatement; -import org.eclipse.jdt.core.dom.ThisExpression; -import org.eclipse.jdt.core.dom.ThrowStatement; -import org.eclipse.jdt.core.dom.TryStatement; -import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.core.dom.TypeDeclarationStatement; -import org.eclipse.jdt.core.dom.TypeLiteral; -import org.eclipse.jdt.core.dom.VariableDeclarationExpression; -import org.eclipse.jdt.core.dom.VariableDeclarationFragment; -import org.eclipse.jdt.core.dom.VariableDeclarationStatement; -import org.eclipse.jdt.core.dom.WhileStatement; -import org.eclipse.jdt.core.jdom.DOMFactory; -import org.eclipse.jdt.core.jdom.IDOMCompilationUnit; -import org.eclipse.jdt.core.jdom.IDOMMethod; -import org.eclipse.jdt.core.jdom.IDOMNode; -import org.eclipse.jdt.core.jdom.IDOMType; -import org.eclipse.jdt.core.util.IModifierConstants; +import java.util.*; import junit.framework.Test; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.dom.*; +import org.eclipse.jdt.core.jdom.*; +import org.eclipse.jdt.core.util.IModifierConstants; + @SuppressWarnings({"rawtypes"}) public class ASTConverterAST3Test extends ConverterTestSetup { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java index 3db9d82ed29..5118af8d577 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java @@ -14,96 +14,15 @@ package org.eclipse.jdt.core.tests.dom; -import java.util.Enumeration; -import java.util.List; - -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTMatcher; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; -import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; -import org.eclipse.jdt.core.dom.ArrayCreation; -import org.eclipse.jdt.core.dom.ArrayInitializer; -import org.eclipse.jdt.core.dom.ArrayType; -import org.eclipse.jdt.core.dom.Assignment; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.BodyDeclaration; -import org.eclipse.jdt.core.dom.BooleanLiteral; -import org.eclipse.jdt.core.dom.BreakStatement; -import org.eclipse.jdt.core.dom.CastExpression; -import org.eclipse.jdt.core.dom.CatchClause; -import org.eclipse.jdt.core.dom.CharacterLiteral; -import org.eclipse.jdt.core.dom.ClassInstanceCreation; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ConditionalExpression; -import org.eclipse.jdt.core.dom.ContinueStatement; -import org.eclipse.jdt.core.dom.DoStatement; -import org.eclipse.jdt.core.dom.EmptyStatement; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.ExpressionStatement; -import org.eclipse.jdt.core.dom.FieldAccess; -import org.eclipse.jdt.core.dom.FieldDeclaration; -import org.eclipse.jdt.core.dom.ForStatement; -import org.eclipse.jdt.core.dom.IBinding; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.IPackageBinding; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.IVariableBinding; -import org.eclipse.jdt.core.dom.IfStatement; -import org.eclipse.jdt.core.dom.ImportDeclaration; -import org.eclipse.jdt.core.dom.InfixExpression; -import org.eclipse.jdt.core.dom.Initializer; -import org.eclipse.jdt.core.dom.InstanceofExpression; -import org.eclipse.jdt.core.dom.Javadoc; -import org.eclipse.jdt.core.dom.LabeledStatement; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.Modifier; -import org.eclipse.jdt.core.dom.Name; -import org.eclipse.jdt.core.dom.NullLiteral; -import org.eclipse.jdt.core.dom.NumberLiteral; -import org.eclipse.jdt.core.dom.PackageDeclaration; -import org.eclipse.jdt.core.dom.ParenthesizedExpression; -import org.eclipse.jdt.core.dom.PostfixExpression; -import org.eclipse.jdt.core.dom.PrefixExpression; -import org.eclipse.jdt.core.dom.PrimitiveType; -import org.eclipse.jdt.core.dom.QualifiedName; -import org.eclipse.jdt.core.dom.ReturnStatement; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SimpleType; -import org.eclipse.jdt.core.dom.SingleVariableDeclaration; -import org.eclipse.jdt.core.dom.Statement; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.SuperConstructorInvocation; -import org.eclipse.jdt.core.dom.SuperFieldAccess; -import org.eclipse.jdt.core.dom.SuperMethodInvocation; -import org.eclipse.jdt.core.dom.SwitchCase; -import org.eclipse.jdt.core.dom.SwitchStatement; -import org.eclipse.jdt.core.dom.SynchronizedStatement; -import org.eclipse.jdt.core.dom.ThisExpression; -import org.eclipse.jdt.core.dom.ThrowStatement; -import org.eclipse.jdt.core.dom.TryStatement; -import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.core.dom.TypeDeclarationStatement; -import org.eclipse.jdt.core.dom.TypeLiteral; -import org.eclipse.jdt.core.dom.VariableDeclarationExpression; -import org.eclipse.jdt.core.dom.VariableDeclarationFragment; -import org.eclipse.jdt.core.dom.VariableDeclarationStatement; -import org.eclipse.jdt.core.dom.WhileStatement; -import org.eclipse.jdt.core.jdom.DOMFactory; -import org.eclipse.jdt.core.jdom.IDOMCompilationUnit; -import org.eclipse.jdt.core.jdom.IDOMMethod; -import org.eclipse.jdt.core.jdom.IDOMNode; -import org.eclipse.jdt.core.jdom.IDOMType; -import org.eclipse.jdt.core.util.IModifierConstants; +import java.util.*; import junit.framework.Test; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.dom.*; +import org.eclipse.jdt.core.jdom.*; +import org.eclipse.jdt.core.util.IModifierConstants; + @SuppressWarnings({"rawtypes"}) public class ASTConverterAST4Test extends ConverterTestSetup { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java index cb09972890d..431e6334cdb 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java @@ -14,96 +14,15 @@ package org.eclipse.jdt.core.tests.dom; -import java.util.Enumeration; -import java.util.List; - -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTMatcher; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; -import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; -import org.eclipse.jdt.core.dom.ArrayCreation; -import org.eclipse.jdt.core.dom.ArrayInitializer; -import org.eclipse.jdt.core.dom.ArrayType; -import org.eclipse.jdt.core.dom.Assignment; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.BodyDeclaration; -import org.eclipse.jdt.core.dom.BooleanLiteral; -import org.eclipse.jdt.core.dom.BreakStatement; -import org.eclipse.jdt.core.dom.CastExpression; -import org.eclipse.jdt.core.dom.CatchClause; -import org.eclipse.jdt.core.dom.CharacterLiteral; -import org.eclipse.jdt.core.dom.ClassInstanceCreation; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ConditionalExpression; -import org.eclipse.jdt.core.dom.ContinueStatement; -import org.eclipse.jdt.core.dom.DoStatement; -import org.eclipse.jdt.core.dom.EmptyStatement; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.ExpressionStatement; -import org.eclipse.jdt.core.dom.FieldAccess; -import org.eclipse.jdt.core.dom.FieldDeclaration; -import org.eclipse.jdt.core.dom.ForStatement; -import org.eclipse.jdt.core.dom.IBinding; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.IPackageBinding; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.IVariableBinding; -import org.eclipse.jdt.core.dom.IfStatement; -import org.eclipse.jdt.core.dom.ImportDeclaration; -import org.eclipse.jdt.core.dom.InfixExpression; -import org.eclipse.jdt.core.dom.Initializer; -import org.eclipse.jdt.core.dom.InstanceofExpression; -import org.eclipse.jdt.core.dom.Javadoc; -import org.eclipse.jdt.core.dom.LabeledStatement; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.Modifier; -import org.eclipse.jdt.core.dom.Name; -import org.eclipse.jdt.core.dom.NullLiteral; -import org.eclipse.jdt.core.dom.NumberLiteral; -import org.eclipse.jdt.core.dom.PackageDeclaration; -import org.eclipse.jdt.core.dom.ParenthesizedExpression; -import org.eclipse.jdt.core.dom.PostfixExpression; -import org.eclipse.jdt.core.dom.PrefixExpression; -import org.eclipse.jdt.core.dom.PrimitiveType; -import org.eclipse.jdt.core.dom.QualifiedName; -import org.eclipse.jdt.core.dom.ReturnStatement; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SimpleType; -import org.eclipse.jdt.core.dom.SingleVariableDeclaration; -import org.eclipse.jdt.core.dom.Statement; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.SuperConstructorInvocation; -import org.eclipse.jdt.core.dom.SuperFieldAccess; -import org.eclipse.jdt.core.dom.SuperMethodInvocation; -import org.eclipse.jdt.core.dom.SwitchCase; -import org.eclipse.jdt.core.dom.SwitchStatement; -import org.eclipse.jdt.core.dom.SynchronizedStatement; -import org.eclipse.jdt.core.dom.ThisExpression; -import org.eclipse.jdt.core.dom.ThrowStatement; -import org.eclipse.jdt.core.dom.TryStatement; -import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.core.dom.TypeDeclarationStatement; -import org.eclipse.jdt.core.dom.TypeLiteral; -import org.eclipse.jdt.core.dom.VariableDeclarationExpression; -import org.eclipse.jdt.core.dom.VariableDeclarationFragment; -import org.eclipse.jdt.core.dom.VariableDeclarationStatement; -import org.eclipse.jdt.core.dom.WhileStatement; -import org.eclipse.jdt.core.jdom.DOMFactory; -import org.eclipse.jdt.core.jdom.IDOMCompilationUnit; -import org.eclipse.jdt.core.jdom.IDOMMethod; -import org.eclipse.jdt.core.jdom.IDOMNode; -import org.eclipse.jdt.core.jdom.IDOMType; -import org.eclipse.jdt.core.util.IModifierConstants; +import java.util.*; import junit.framework.Test; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.dom.*; +import org.eclipse.jdt.core.jdom.*; +import org.eclipse.jdt.core.util.IModifierConstants; + @SuppressWarnings({"rawtypes"}) public class ASTConverterAST8Test extends ConverterTestSetup { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java index 0a704c4ccfc..ac7ffe183c6 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java @@ -14,101 +14,17 @@ package org.eclipse.jdt.core.tests.dom; -import java.util.Enumeration; -import java.util.List; +import java.util.*; + +import junit.framework.Test; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IField; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTMatcher; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; -import org.eclipse.jdt.core.dom.ArrayCreation; -import org.eclipse.jdt.core.dom.ArrayInitializer; -import org.eclipse.jdt.core.dom.ArrayType; -import org.eclipse.jdt.core.dom.Assignment; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.BodyDeclaration; -import org.eclipse.jdt.core.dom.BooleanLiteral; -import org.eclipse.jdt.core.dom.BreakStatement; -import org.eclipse.jdt.core.dom.CastExpression; -import org.eclipse.jdt.core.dom.CatchClause; -import org.eclipse.jdt.core.dom.CharacterLiteral; -import org.eclipse.jdt.core.dom.ClassInstanceCreation; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ConditionalExpression; -import org.eclipse.jdt.core.dom.ContinueStatement; -import org.eclipse.jdt.core.dom.DoStatement; -import org.eclipse.jdt.core.dom.EmptyStatement; -import org.eclipse.jdt.core.dom.EnumConstantDeclaration; -import org.eclipse.jdt.core.dom.EnumDeclaration; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.ExpressionStatement; -import org.eclipse.jdt.core.dom.FieldAccess; -import org.eclipse.jdt.core.dom.FieldDeclaration; -import org.eclipse.jdt.core.dom.ForStatement; -import org.eclipse.jdt.core.dom.IBinding; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.IPackageBinding; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.IVariableBinding; -import org.eclipse.jdt.core.dom.IfStatement; -import org.eclipse.jdt.core.dom.ImportDeclaration; -import org.eclipse.jdt.core.dom.InfixExpression; -import org.eclipse.jdt.core.dom.Initializer; -import org.eclipse.jdt.core.dom.InstanceofExpression; -import org.eclipse.jdt.core.dom.Javadoc; -import org.eclipse.jdt.core.dom.LabeledStatement; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.Modifier; -import org.eclipse.jdt.core.dom.Name; -import org.eclipse.jdt.core.dom.NullLiteral; -import org.eclipse.jdt.core.dom.NumberLiteral; -import org.eclipse.jdt.core.dom.PackageDeclaration; -import org.eclipse.jdt.core.dom.ParenthesizedExpression; -import org.eclipse.jdt.core.dom.PostfixExpression; -import org.eclipse.jdt.core.dom.PrefixExpression; -import org.eclipse.jdt.core.dom.PrimitiveType; -import org.eclipse.jdt.core.dom.QualifiedName; -import org.eclipse.jdt.core.dom.ReturnStatement; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SimpleType; -import org.eclipse.jdt.core.dom.SingleVariableDeclaration; -import org.eclipse.jdt.core.dom.Statement; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.SuperConstructorInvocation; -import org.eclipse.jdt.core.dom.SuperFieldAccess; -import org.eclipse.jdt.core.dom.SuperMethodInvocation; -import org.eclipse.jdt.core.dom.SwitchCase; -import org.eclipse.jdt.core.dom.SwitchStatement; -import org.eclipse.jdt.core.dom.SynchronizedStatement; -import org.eclipse.jdt.core.dom.ThisExpression; -import org.eclipse.jdt.core.dom.ThrowStatement; -import org.eclipse.jdt.core.dom.TryStatement; -import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.core.dom.TypeDeclarationStatement; -import org.eclipse.jdt.core.dom.TypeLiteral; -import org.eclipse.jdt.core.dom.VariableDeclarationExpression; -import org.eclipse.jdt.core.dom.VariableDeclarationFragment; -import org.eclipse.jdt.core.dom.VariableDeclarationStatement; -import org.eclipse.jdt.core.dom.WhileStatement; -import org.eclipse.jdt.core.jdom.DOMFactory; -import org.eclipse.jdt.core.jdom.IDOMCompilationUnit; -import org.eclipse.jdt.core.jdom.IDOMMethod; -import org.eclipse.jdt.core.jdom.IDOMNode; -import org.eclipse.jdt.core.jdom.IDOMType; +import org.eclipse.jdt.core.*; +import org.eclipse.jdt.core.dom.*; +import org.eclipse.jdt.core.jdom.*; import org.eclipse.jdt.core.util.IModifierConstants; -import junit.framework.Test; - @SuppressWarnings("rawtypes") public class ASTConverterTest extends ConverterTestSetup { From 2ff64f29b94eed2b29faca3ab587a4f18103f333 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Mon, 1 Jul 2024 19:44:41 +0200 Subject: [PATCH 08/16] better strategy to detect when method return type can be ignored --- .../internal/compiler/ast/ArrayReference.java | 5 +- .../internal/compiler/ast/FieldReference.java | 5 +- .../compiler/ast/MemberValuePair.java | 4 +- .../internal/compiler/ast/MessageSend.java | 6 +- .../regression/ProblemTypeAndMethodTest.java | 80 ++++++++++++++++++- 5 files changed, 80 insertions(+), 20 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java index fd5d586538b..a5470eb9e64 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -208,9 +208,6 @@ public TypeBinding resolveType(BlockScope scope) { && ((CastExpression)this.receiver).innermostCastedExpression() instanceof NullLiteral) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on } - if (this.receiver instanceof MessageSend) { - ((MessageSend) this.receiver).isReceiver = true; - } TypeBinding arrayType = this.receiver.resolveType(scope); if (arrayType != null) { this.receiver.computeConversion(scope, arrayType, arrayType); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java index 8d2f5333138..811b8587ef7 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2018 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -661,9 +661,6 @@ public TypeBinding resolveType(BlockScope scope) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on receiverCast = true; } - if (this.receiver instanceof MessageSend) { - ((MessageSend) this.receiver).isReceiver = true; - } this.actualReceiverType = this.receiver.resolveType(scope); if (this.actualReceiverType == null) { this.constant = Constant.NotAConstant; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java index a4405319bc5..7511228540b 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -69,8 +69,6 @@ public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) { this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding); return; } - // the following is not really useful, but let's humor the resolution even if value is not a constant - this.value.setExpressionContext(ExpressionContext.ASSIGNMENT_CONTEXT); if (requiredType == null) { // fault tolerance: keep resolving if (this.value instanceof ArrayInitializer) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index f8863661f47..023f40184fb 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -136,7 +136,6 @@ public class MessageSend extends Expression implements IPolyExpression, Invocati public TypeReference[] typeArguments; public TypeBinding[] genericTypeArguments; public ExpressionContext expressionContext = VANILLA_CONTEXT; - public boolean isReceiver = false; // hold on to this context from invocation applicability inference until invocation type inference (per method candidate): private SimpleLookupTable/**/ inferenceContexts; @@ -812,9 +811,6 @@ public TypeBinding resolveType(BlockScope scope) { if (this.receiver instanceof CastExpression) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on } - if (this.receiver instanceof MessageSend) { - ((MessageSend) this.receiver).isReceiver = true; - } this.actualReceiverType = this.receiver.resolveType(scope); if (this.actualReceiverType instanceof InferenceVariable) { return null; // not yet ready for resolving @@ -1117,7 +1113,7 @@ protected boolean isUnnecessaryReceiverCast(BlockScope scope, TypeBinding uncast } protected boolean isMissingTypeRelevant() { - if (this.expressionContext == ExpressionContext.VANILLA_CONTEXT && !this.isReceiver) { + if ((this.bits & ASTNode.InsideExpressionStatement) != 0) { if (this.binding.collectMissingTypes(null, false) == null) return false; // only irrelevant return type is missing } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index 583dde889ef..af4e3c0f2b1 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -9410,34 +9410,60 @@ public void n(A a) {} """ package p2; import p1.B; + import java.util.function.Function; public class C extends B { void test(B b) { B b2 = b.m(this); b.n(b.m(this)); + boolean f = b.m(this) == b; + f = b.m(this) instanceof B; + Function fun = b.m(this)::foo; + Object o = b.m(this).new Inner(); } @Override public B m(Object o) { return super.m(o); } + class Inner {} } """ }; runner.expectedCompilerLog = """ ---------- - 1. ERROR in p2\\C.java (at line 5) + 1. ERROR in p2\\C.java (at line 6) B b2 = b.m(this); ^ The method m(Object) from the type B refers to the missing type A ---------- - 2. ERROR in p2\\C.java (at line 6) + 2. ERROR in p2\\C.java (at line 7) b.n(b.m(this)); ^ The method m(Object) from the type B refers to the missing type A ---------- - 3. ERROR in p2\\C.java (at line 9) + 3. ERROR in p2\\C.java (at line 8) + boolean f = b.m(this) == b; + ^ + The method m(Object) from the type B refers to the missing type A + ---------- + 4. ERROR in p2\\C.java (at line 9) + f = b.m(this) instanceof B; + ^ + The method m(Object) from the type B refers to the missing type A + ---------- + 5. ERROR in p2\\C.java (at line 10) + Function fun = b.m(this)::foo; + ^ + The method m(Object) from the type B refers to the missing type A + ---------- + 7. ERROR in p2\\C.java (at line 11) + Object o = b.m(this).new Inner(); + ^ + The method m(Object) from the type B refers to the missing type A + ---------- + 8. ERROR in p2\\C.java (at line 14) public B m(Object o) { return super.m(o); } ^ The return type is incompatible with B.m(Object) ---------- - 4. ERROR in p2\\C.java (at line 9) + 9. ERROR in p2\\C.java (at line 14) public B m(Object o) { return super.m(o); } ^ The method m(Object) from the type B refers to the missing type A @@ -9445,4 +9471,50 @@ The method m(Object) from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClass_exception() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A extends Exception {} + """, + "p1/B.java", + """ + package p1; + import p1.A; + public class B { + public void m() throws A {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + class C { + void test(B b) { + b.m(); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + b.m(); + ^ + The method m() from the type B refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} } From 404720fde90dfaf291fed1aa8491da8ccb71719f Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Mon, 1 Jul 2024 21:56:46 +0200 Subject: [PATCH 09/16] detect missing types during type inference + don't let constraint with missing type fail type inference + prefer that candidate during overload resolution additional bug fix: + fix tagging of TypeVariableBinding with HasMissingType - no magic for class level type parameters with missing type + improved errors in GenericsRegressionTest_1_8.testBug525580*() et al --- .../lookup/ConstraintExceptionFormula.java | 4 + .../lookup/ConstraintExpressionFormula.java | 4 + .../lookup/ConstraintTypeFormula.java | 4 + .../compiler/lookup/InferenceContext18.java | 2 + .../ParameterizedGenericMethodBinding.java | 3 + .../jdt/internal/compiler/lookup/Scope.java | 4 +- .../compiler/lookup/TypeVariableBinding.java | 21 +++- .../core/tests/builder/MultiProjectTests.java | 2 +- .../compiler/regression/AnnotationTest.java | 4 +- .../compiler/regression/GenericTypeTest.java | 5 + .../GenericsRegressionTest_1_8.java | 31 +++--- .../regression/ProblemTypeAndMethodTest.java | 98 +++++++++++++++++++ 12 files changed, 156 insertions(+), 26 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java index 37cb04ee363..d7d0c3e3272 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java @@ -44,6 +44,10 @@ public ConstraintExceptionFormula(FunctionalExpression left, TypeBinding type) { @Override public Object reduce(InferenceContext18 inferenceContext) { + if ((this.right.tagBits & TagBits.HasMissingType) != 0) { + inferenceContext.hasIgnoredMissingType = true; + return TRUE; + } // JLS 18.2.5 Scope scope = inferenceContext.scope; if (!this.right.isFunctionalInterface(scope)) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java index 29094d54ba7..2bce82c25e1 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java @@ -59,6 +59,10 @@ class ConstraintExpressionFormula extends ConstraintFormula { @Override public Object reduce(InferenceContext18 inferenceContext) throws InferenceFailureException { + if ((this.right.tagBits & TagBits.HasMissingType) != 0) { + inferenceContext.hasIgnoredMissingType = true; + return TRUE; + } if (this.relation == POTENTIALLY_COMPATIBLE) { /* 15.12.2.1: ... The definition of potential applicability goes beyond a basic arity check to also take into account the presence and "shape" of functional interface diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java index 3149d02f0d1..7b7346deacf 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java @@ -63,6 +63,10 @@ private ConstraintTypeFormula(TypeBinding exprType, TypeBinding right, int relat // return: ReductionResult or ConstraintFormula[] @Override public Object reduce(InferenceContext18 inferenceContext) { + if ((this.left.tagBits & TagBits.HasMissingType) != 0 || (this.right.tagBits & TagBits.HasMissingType) != 0) { + inferenceContext.hasIgnoredMissingType = true; + return TRUE; + } switch (this.relation) { case COMPATIBLE: // 18.2.2: diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java index 26ad94323ad..a478ba29180 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java @@ -180,6 +180,8 @@ public class InferenceContext18 { // the following two flags control to what degree we continue with incomplete information: private boolean isInexactVarargsInference = false; boolean prematureOverloadResolution = false; + // during reduction we ignore missing types but record that fact here: + boolean hasIgnoredMissingType; public static boolean isSameSite(InvocationSite site1, InvocationSite site2) { if (site1 == site2) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java index 350fb1b1f51..60c0e7ff4e1 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java @@ -307,6 +307,9 @@ public static MethodBinding computeCompatibleMethod18(MethodBinding originalMeth if (invocationSite instanceof Invocation && allArgumentsAreProper && (expectedType == null || expectedType.isProperType(true))) infCtx18.forwardResults(result, (Invocation) invocationSite, methodSubstitute, expectedType); try { + if (infCtx18.hasIgnoredMissingType) { + return new ProblemMethodBinding(originalMethod, originalMethod.selector, parameters, ProblemReasons.MissingTypeInSignature); + } if (hasReturnProblem) { // illegally working from the provisional result? MethodBinding problemMethod = infCtx18.getReturnProblemMethodIfNeeded(expectedType, methodSubstitute); if (problemMethod instanceof ProblemMethodBinding) { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java index 1b84b7c5bf8..1bfb0f75f3e 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -982,7 +982,7 @@ protected boolean connectTypeVariables(TypeParameter[] typeParameters, boolean c } else { typeVariable.setSuperInterfaces(new ReferenceBinding[] {superRefType}); } - typeVariable.tagBits |= superType.tagBits & TagBits.ContainsNestedTypeReferences; + typeVariable.tagBits |= superType.tagBits & (TagBits.ContainsNestedTypeReferences | TagBits.HasMissingType); typeVariable.setFirstBound(superRefType); // first bound used to compute erasure } } @@ -997,7 +997,7 @@ protected boolean connectTypeVariables(TypeParameter[] typeParameters, boolean c typeVariable.tagBits |= TagBits.HierarchyHasProblems; continue nextBound; } else { - typeVariable.tagBits |= superType.tagBits & TagBits.ContainsNestedTypeReferences; + typeVariable.tagBits |= superType.tagBits & (TagBits.ContainsNestedTypeReferences | TagBits.HasMissingType); boolean didAlreadyComplain = !typeRef.resolvedType.isValidBinding(); if (isFirstBoundTypeVariable && j == 0) { problemReporter().noAdditionalBoundAfterTypeVariable(typeRef); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java index f7ef22e0f74..2d4cc0a1834 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2020 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -43,6 +43,7 @@ package org.eclipse.jdt.internal.compiler.lookup; import java.util.Arrays; +import java.util.List; import java.util.Set; import java.util.function.Consumer; @@ -344,6 +345,20 @@ public int boundsCount() { public boolean canBeInstantiated() { return false; } + + @Override + public List collectMissingTypes(List missingTypes) { + if ((this.tagBits & TagBits.HasMissingType) != 0) { + if (this.superclass != null) { + missingTypes = this.superclass.collectMissingTypes(missingTypes); + } + for (ReferenceBinding superIfc : this.superInterfaces) { + missingTypes = superIfc.collectMissingTypes(missingTypes); + } + } + return missingTypes; + } + /** * Collect the substitutes into a map for certain type variables inside the receiver type * e.g. {@code Collection.collectSubstitutes(Collection>, Map)} will populate Map with: {@code T --> List} @@ -805,7 +820,7 @@ ReferenceBinding resolve() { TypeBinding oldSuperclass = this.superclass, oldFirstInterface = null; if (this.superclass != null) { ReferenceBinding resolveType = (ReferenceBinding) BinaryTypeBinding.resolveType(this.superclass, this.environment, true /* raw conversion */); - this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences; + this.tagBits |= resolveType.tagBits & (TagBits.ContainsNestedTypeReferences | TagBits.HasMissingType); long superNullTagBits = resolveType.tagBits & TagBits.AnnotationNullMASK; if (superNullTagBits != 0L) { if (nullTagBits == 0L) { @@ -824,7 +839,7 @@ ReferenceBinding resolve() { oldFirstInterface = interfaces[0]; for (int i = length; --i >= 0;) { ReferenceBinding resolveType = (ReferenceBinding) BinaryTypeBinding.resolveType(interfaces[i], this.environment, true /* raw conversion */); - this.tagBits |= resolveType.tagBits & TagBits.ContainsNestedTypeReferences; + this.tagBits |= resolveType.tagBits & (TagBits.ContainsNestedTypeReferences | TagBits.HasMissingType); long superNullTagBits = resolveType.tagBits & TagBits.AnnotationNullMASK; if (superNullTagBits != 0L) { if (nullTagBits == 0L) { diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java index 087637dc9dd..2e8d7c58d7a 100644 --- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/MultiProjectTests.java @@ -34,7 +34,7 @@ public class MultiProjectTests extends BuilderTests { static { - TESTS_NAMES = new String[] { "test461074_error_1_8" }; +// TESTS_NAMES = new String[] { "test461074_error_1_8" }; } public MultiProjectTests(String name) { diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java index 466557801e5..ffe8ed0767d 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java @@ -7973,8 +7973,8 @@ public void test237() { "----------\n" + "2. ERROR in X.java (at line 6)\n" + " List ls = get();\n" + - " ^^^^^\n" + - "Type mismatch: cannot convert from B to List\n" + + " ^^^\n" + + "The method get() from the type X refers to the missing type ArrayList\n" + "----------\n"); } public void test238() { diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java index 2b0f686803c..f2cf8999f6b 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java @@ -43243,6 +43243,11 @@ public void test1222() { " public class X {\n" + " ^^^^\n" + "Zork cannot be resolved to a type\n" + + "----------\n" + + "2. ERROR in X.java (at line 4)\n" + + " Runnable r = x2.get();\n" + + " ^^^\n" + + "The method get() from the type X refers to the missing type Zork\n" + "----------\n"); } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=211718 diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java index 1386fe9ad27..1c3fe0eb91f 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java @@ -9173,45 +9173,40 @@ public void testBug525580() { "----------\n" + "2. ERROR in org\\a\\a\\g\\d.java (at line 6)\n" + " T t = (e) cls.newInstance();\n" + - " ^^^^^^^^^^^^^^^^^^^^^\n" + - "e cannot be resolved to a type\n" + - "----------\n" + - "3. ERROR in org\\a\\a\\g\\d.java (at line 6)\n" + - " T t = (e) cls.newInstance();\n" + " ^\n" + "e cannot be resolved to a type\n" + "----------\n" + - "4. ERROR in org\\a\\a\\g\\d.java (at line 7)\n" + + "3. ERROR in org\\a\\a\\g\\d.java (at line 7)\n" + " while (size >= 0) {\n" + " ^^^^\n" + "size cannot be resolved to a variable\n" + "----------\n" + - "5. ERROR in org\\a\\a\\g\\d.java (at line 8)\n" + - " T a = ((b) this.e.m.get(size)).a();\n" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + - "Type mismatch: cannot convert from e to T\n" + - "----------\n" + - "6. ERROR in org\\a\\a\\g\\d.java (at line 8)\n" + + "4. ERROR in org\\a\\a\\g\\d.java (at line 8)\n" + " T a = ((b) this.e.m.get(size)).a();\n" + " ^\n" + "e cannot be resolved or is not a field\n" + "----------\n" + - "7. ERROR in org\\a\\a\\g\\d.java (at line 8)\n" + + "5. ERROR in org\\a\\a\\g\\d.java (at line 8)\n" + " T a = ((b) this.e.m.get(size)).a();\n" + " ^^^^\n" + "size cannot be resolved to a variable\n" + "----------\n" + - "8. ERROR in org\\a\\a\\g\\d.java (at line 15)\n" + + "6. ERROR in org\\a\\a\\g\\d.java (at line 8)\n" + + " T a = ((b) this.e.m.get(size)).a();\n" + + " ^\n" + + "The method a() from the type d.b refers to the missing type e\n" + + "----------\n" + + "7. ERROR in org\\a\\a\\g\\d.java (at line 15)\n" + " T a();\n" + " ^\n" + "e cannot be resolved to a type\n" + "----------\n" + - "9. ERROR in org\\a\\a\\g\\d.java (at line 17)\n" + + "8. ERROR in org\\a\\a\\g\\d.java (at line 17)\n" + " T b();\n" + " ^\n" + "j cannot be resolved to a type\n" + "----------\n" + - "10. WARNING in org\\a\\a\\g\\d.java (at line 17)\n" + + "9. WARNING in org\\a\\a\\g\\d.java (at line 17)\n" + " T b();\n" + " ^^^\n" + "This method has a constructor name\n" + @@ -9292,8 +9287,8 @@ public void testBug525580_comment28() { "----------\n" + "3. ERROR in xxxxxx\\iiibii.java (at line 9)\n" + " return b041D041D041D041DН041DН(new xxxxxx.jjajaa(b, b2));\n" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + - "Type mismatch: cannot convert from jajaja to jajaja\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^\n" + + "The method b041D041D041D041DН041DН(jjajaa) from the type iiibii refers to the missing type jajaja\n" + "----------\n" + "----------\n" + "1. ERROR in xxxxxx\\jjajaa.java (at line 3)\n" + diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index af4e3c0f2b1..48364bd027f 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -9517,4 +9517,102 @@ The method m() from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClass_typeVariableBound() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + import p1.A; + public class B { + public void m(Number n) {} // would match, but ... + public void m(T t) {} // ... don't rule out method with missing type + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + class C { + void test(B b) { + b.m(Integer.valueOf(13)); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + b.m(Integer.valueOf(13)); + ^ + The method m(T) from the type B refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClass_typeVariableBound2() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + import p1.A; + public class B { + public void m(T t) {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + class C { + void test(B b) { + b.m(this); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 1) + package p2; + ^ + The type p1.A cannot be resolved. It is indirectly referenced from required type p1.B + ---------- + 2. ERROR in p2\\C.java (at line 4) + void test(B b) { + ^ + Bound mismatch: The type C is not a valid substitute for the bounded parameter of the type B + ---------- + """; + runner.runNegativeTest(); +} } From f0309004ffab54e35846743dac36770921b37d94 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Tue, 2 Jul 2024 10:50:05 +0200 Subject: [PATCH 10/16] Regression fixes: + avoid j.l.Number which is absent from jclMin! + fix JCL_LIB -> JCL18_LIB in ImportRewrite18Test + propagate HasMissingType through substitution + protect collectMissingTypes() against infinite recursion --- .../lookup/ParameterizedMethodBinding.java | 2 +- .../compiler/lookup/TypeVariableBinding.java | 17 ++++++++++------ .../core/tests/dom/ASTModelBridgeTests.java | 20 +++++++++++++++++++ .../describing/ImportRewrite18Test.java | 3 ++- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java index 0e392932587..5c0569e0359 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java @@ -66,7 +66,7 @@ public ParameterizedMethodBinding(final ParameterizedTypeBinding parameterizedDe for (int i = 0; i < length; i++) { // copy original type variable to relocate TypeVariableBinding originalVariable = originalVariables[i]; substitutedVariables[i] = new TypeVariableBinding(originalVariable.sourceName, this, originalVariable.rank, parameterizedDeclaringClass.environment); - substitutedVariables[i].tagBits |= (originalVariable.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation)); + substitutedVariables[i].tagBits |= (originalVariable.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation|TagBits.HasMissingType)); } this.typeVariables = substitutedVariables; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java index 2d4cc0a1834..864c756b131 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java @@ -348,12 +348,17 @@ public boolean canBeInstantiated() { @Override public List collectMissingTypes(List missingTypes) { - if ((this.tagBits & TagBits.HasMissingType) != 0) { - if (this.superclass != null) { - missingTypes = this.superclass.collectMissingTypes(missingTypes); - } - for (ReferenceBinding superIfc : this.superInterfaces) { - missingTypes = superIfc.collectMissingTypes(missingTypes); + if ((this.tagBits & TagBits.HasMissingType) != 0 && !this.inRecursiveFunction) { + this.inRecursiveFunction = true; + try { + if (this.superclass != null) { + missingTypes = this.superclass.collectMissingTypes(missingTypes); + } + for (ReferenceBinding superIfc : this.superInterfaces) { + missingTypes = superIfc.collectMissingTypes(missingTypes); + } + } finally { + this.inRecursiveFunction = false; } } return missingTypes; diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java index 2db09a5979b..2d17b43bb7c 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTModelBridgeTests.java @@ -160,10 +160,14 @@ private String buildBindingKey(String contents) throws JavaModelException { } private IBinding[] createBindings(String contents, IJavaElement element) throws JavaModelException { + return createBindings(contents, element, false); + } + private IBinding[] createBindings(String contents, IJavaElement element, boolean recoverBindings) throws JavaModelException { this.workingCopy.getBuffer().setContents(contents); this.workingCopy.makeConsistent(null); ASTParser parser = ASTParser.newParser(JLS3_INTERNAL); parser.setProject(getJavaProject("P")); + parser.setBindingsRecovery(recoverBindings); IJavaElement[] elements = new IJavaElement[] {element}; return parser.createBindings(elements, null); } @@ -1175,6 +1179,22 @@ public void testCreateBindings14a() throws JavaModelException { IBinding[] bindings = createBindings( "public class X {\n" + "}", + this.workingCopy.getType("X").getTypeParameter("T"), + true // recover bindings, java.lang.Number is missing from jclMin! + ); + assertBindingsEqual( + "LX;:TT;", + bindings); + } + + /* + * Ensures that the correct IBindings are created for a given set of IJavaElement + * (type parameter with bound) + */ + public void testCreateBindings14a2() throws JavaModelException { + IBinding[] bindings = createBindings( + "public class X {\n" + // j.l.Exception is present + "}", this.workingCopy.getType("X").getTypeParameter("T") ); assertBindingsEqual( diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java index 632e7e6fafd..a1f0f895cd7 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewrite18Test.java @@ -75,7 +75,7 @@ public static Test suite() { protected void setUp() throws Exception { super.setUp(); - IJavaProject proj= createJavaProject(PROJECT, new String[] {"src"}, new String[] {"JCL_LIB"}, "bin", "1.8"); + IJavaProject proj= createJavaProject(PROJECT, new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "1.8"); proj.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE); proj.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4"); proj.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8); @@ -794,6 +794,7 @@ public void testBug474270_since_8() throws Exception { parser.setSource(cu); parser.setResolveBindings(true); parser.setStatementsRecovery(true); + parser.setBindingsRecovery(true); CompilationUnit astRoot = (CompilationUnit) parser.createAST(null); TypeDeclaration type= (TypeDeclaration) astRoot.types().get(1); MethodDeclaration [] methods = type.getMethods(); From ee19f7ae6ba0ab5fa661319b4ca9898e4e8af2f4 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Tue, 2 Jul 2024 20:18:16 +0200 Subject: [PATCH 11/16] renamed constant --- .../internal/compiler/lookup/InferenceContext18.java | 2 +- .../eclipse/jdt/internal/compiler/lookup/Scope.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java index a478ba29180..96595c5f56b 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java @@ -756,7 +756,7 @@ private boolean addConstraintsToC_OneExpr(Expression expri, Set level && level != NEEDS_MISSING_TYPE) // preserve any NEEDS_MISSING_TYPE + if (newLevel > level && level != COMPATIBLE_IGNORING_MISSING_TYPE) // preserve any NEEDS_MISSING_TYPE level = newLevel; } } @@ -5210,7 +5210,7 @@ private int parameterCompatibilityLevel(TypeBinding arg, TypeBinding param, Look if (arg == null || param == null) return NOT_COMPATIBLE; if ((param.tagBits & TagBits.HasMissingType) != 0) - return NEEDS_MISSING_TYPE; + return COMPATIBLE_IGNORING_MISSING_TYPE; if (arg instanceof PolyTypeBinding && !((PolyTypeBinding) arg).expression.isPertinentToApplicability(param, method)) { if (arg.isPotentiallyCompatibleWith(param, this)) return COMPATIBLE; From f87c44a8902da72c6461188d9f673f017e3f1af7 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Tue, 2 Jul 2024 22:21:48 +0200 Subject: [PATCH 12/16] include (Qualified)AllocationExpression + tests --- .../compiler/ast/AllocationExpression.java | 18 +- .../internal/compiler/ast/MessageSend.java | 2 +- .../ast/QualifiedAllocationExpression.java | 2 +- .../regression/ProblemTypeAndMethodTest.java | 623 ++++++++++++++++++ 4 files changed, 641 insertions(+), 4 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java index ac94a2af8eb..4822ee81283 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -505,7 +505,7 @@ public TypeBinding resolveType(BlockScope scope) { scope.problemReporter().invalidConstructor(this, this.binding); return this.resolvedType; } - if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { + if ((this.binding.tagBits & TagBits.HasMissingType) != 0 && isMissingTypeRelevant()) { scope.problemReporter().missingTypeInConstructor(this, this.binding); } if (isMethodUseDeprecated(this.binding, scope, true, this)) { @@ -539,6 +539,20 @@ public TypeBinding resolveType(BlockScope scope) { return this.resolvedType; } +protected boolean isMissingTypeRelevant() { + if (this.binding != null && this.binding.isVarargs()) { + if (this.arguments.length < this.binding.parameters.length) { + // are all but the irrelevant varargs type present? + for (int i = 0; i < this.arguments.length; i++) { + if ((this.binding.parameters[i].tagBits & TagBits.HasMissingType) != 0) + return true; // this one *is* relevant - actually this case is already detected during findConstructorBinding() + } + return false; + } + } + return true; +} + protected void checkPreConstructorContext(BlockScope scope) { if (this.inPreConstructorContext && this.type != null && this.type.resolvedType instanceof ReferenceBinding currentType diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index 023f40184fb..ce2c97d35a9 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -1123,7 +1123,7 @@ protected boolean isMissingTypeRelevant() { // are all but the irrelevant varargs type present? for (int i = 0; i < this.arguments.length; i++) { if ((this.binding.parameters[i].tagBits & TagBits.HasMissingType) != 0) - return true; // this one *is* relevant + return true; // this one *is* relevant - actually this case is already detected during findMethodBinding() } return false; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java index 2aae1b181d1..0a32307c3d6 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java @@ -586,7 +586,7 @@ private TypeBinding resolveTypeForQualifiedAllocationExpression(BlockScope scope scope.problemReporter().invalidConstructor(this, constructorBinding); return this.resolvedType; } - if ((constructorBinding.tagBits & TagBits.HasMissingType) != 0) { + if ((constructorBinding.tagBits & TagBits.HasMissingType) != 0 && isMissingTypeRelevant()) { scope.problemReporter().missingTypeInConstructor(this, constructorBinding); } if (this.enclosingInstance != null) { diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index 48364bd027f..fbb4f2566c9 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -8875,6 +8875,69 @@ The method m(A) from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClassNeededForOverloadResolution_ctor() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + public class B { + public B(A a) {} + public B(Object s) {} + public B(Object s1, String s2) {} + public B() {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + runner.shouldFlushOutputDirectory = false; + + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + new B(); // no need to see A for B() + new B(this, ""); // overload selected by arity + } + } + """ + }; + runner.runConformTest(); + + runner.testFiles = new String[] { + "p2/D.java", + """ + package p2; + import p1.B; + public class D { + void test(B b) { + new B(this); // cannot select without seeing class A + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\D.java (at line 5) + new B(this); // cannot select without seeing class A + ^^^^^^^^^^^ + The constructor B(A) refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} public void testMissingClassNeededForOverloadResolution_varargs1a() { // varargs arg: B vs Missing if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 @@ -8955,6 +9018,86 @@ The method m(Object, A1...) from the type B refers to the missing type A1 """; runner.runNegativeTest(); } +public void testMissingClassNeededForOverloadResolution_varargs1a_ctor() { + // varargs arg: B vs Missing + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A1.java", + """ + package p1; + public class A1 {} + """, + "p1/A2.java", + """ + package p1; + public class A2 {} + """, + "p1/B.java", + """ + package p1; + public class B { + public B(Object o1, B... s) {} + public B(Object o1, A1... a) {} + public B(Object o1, A2... a) {} + } + """ + }; + runner.runConformTest(); + + // delete binary files A1, A2 (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A1.class")); + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A2.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + new B(this); // simply ambiguous as we don't even look at A1 or A2 + new B(this, null); + new B(this, b); + new B(this, b, b); + new B(this, new B[0]); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + new B(this); // simply ambiguous as we don't even look at A1 or A2 + ^^^^^^^^^^^ + The constructor B(Object, B[]) is ambiguous + ---------- + 2. ERROR in p2\\C.java (at line 6) + new B(this, null); + ^^^^^^^^^^^^^^^^^ + The constructor B(Object, A1...) refers to the missing type A1 + ---------- + 3. ERROR in p2\\C.java (at line 7) + new B(this, b); + ^^^^^^^^^^^^^^ + The constructor B(Object, A1...) refers to the missing type A1 + ---------- + 4. ERROR in p2\\C.java (at line 8) + new B(this, b, b); + ^^^^^^^^^^^^^^^^^ + The constructor B(Object, A1...) refers to the missing type A1 + ---------- + 5. ERROR in p2\\C.java (at line 9) + new B(this, new B[0]); + ^^^^^^^^^^^^^^^^^^^^^ + The constructor B(Object, A1...) refers to the missing type A1 + ---------- + """; + runner.runNegativeTest(); +} public void testMissingClassNeededForOverloadResolution_varargs1b() { // like testMissingClassNeededForOverloadResolution_varargs1a, but no preceding regular parameter if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 @@ -9266,6 +9409,149 @@ The method n(Object, A...) from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClassNeededForOverloadResolution_varargs2_ctorOK() { + // different arities + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + public class B { + public B(Object o1, String s, A... a) {} + public B(Object o1) {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test() { + new B(this, ""); // overload selected by arity, trailing A[] is irrelevant + new B(this); // overload selected by arity, no reference to A + } + } + """ + }; + runner.runConformTest(); +} +public void testMissingClassNeededForOverloadResolution_varargs2_qualCtorOK() { + // different arities + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/Outer.java", + """ + package p1; + public class Outer { + public class B { + public B(Object o1, String s, A... a) {} + public B(Object o1) {} + } + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.Outer; + public class C { + void test(Outer outer) { + outer.new B(this, ""); // overload selected by arity, trailing A[] is irrelevant + outer.new B(this); // overload selected by arity, no reference to A + } + } + """ + }; + runner.runConformTest(); +} +public void testMissingClassNeededForOverloadResolution_varargs2_ctorNOK() { + // different arities + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.customOptions = getCompilerOptions(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + public class B { + public B(Object o1, A... a) {} + public B(Object o1) {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + runner.shouldFlushOutputDirectory = false; + + runner.customOptions.put(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, CompilerOptions.IGNORE); + + runner.testFiles = new String[] { + "p2/D.java", + """ + package p2; + import p1.B; + public class D { + void test(B b) { + new B(this, null); // passing null into A[] is not OK + new B(this, null, null); // passing null into A is not OK (could potentially be accepted) + new B(this); // resolvable in strict mode, ignore the varargs method + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\D.java (at line 5) + new B(this, null); // passing null into A[] is not OK + ^^^^^^^^^^^^^^^^^ + The constructor B(Object, A...) refers to the missing type A + ---------- + 2. ERROR in p2\\D.java (at line 6) + new B(this, null, null); // passing null into A is not OK (could potentially be accepted) + ^^^^^^^^^^^^^^^^^^^^^^^ + The constructor B(Object, A...) refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} public void testMissingClassNeededForOverloadResolution_varargs3() { // missing type in non-varargs position if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 @@ -9315,6 +9601,55 @@ The method m(A, String...) from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClassNeededForOverloadResolution_varargs3_ctor() { + // missing type in non-varargs position + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + public class B { + public B(A a, String... args) {} + public B(Object s, Number... args) {} + public B(Object s1, String s2) {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + runner.shouldFlushOutputDirectory = false; + + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + new B(this, ""); // two overloads could apply (not knowing A) + new B(this, 3); // overload effectively selected by 2nd arg + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + new B(this, ""); // two overloads could apply (not knowing A) + ^^^^^^^^^^^^^^^ + The constructor B(A, String...) refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} public void testMissingClass_returnType_OK() { if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); @@ -9517,6 +9852,52 @@ The method m() from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClass_exception_ctor() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A extends Exception {} + """, + "p1/B.java", + """ + package p1; + import p1.A; + public class B { + public B() throws A {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + class C { + void test() { + new B(); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + new B(); + ^^^^^^^ + The constructor B() refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} public void testMissingClass_typeVariableBound() { if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); @@ -9564,6 +9945,53 @@ The method m(T) from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClass_typeVariableBound_OK() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + import p1.A; + public class B { + public B(Number n) {} // would match, but ... + public B(T t) {} // ... don't rule out method with missing type + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + class C { + void test(B b) { + new B(Integer.valueOf(13)); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + new B(Integer.valueOf(13)); + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + The constructor B(T) refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} public void testMissingClass_typeVariableBound2() { if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); @@ -9615,4 +10043,199 @@ void test(B b) { """; runner.runNegativeTest(); } +public void testMissingClass_typeVariableBound2_ctor() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/B.java", + """ + package p1; + import p1.A; + public class B { + public B(T t) {} + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + class C { + B test() { + new B<>(this); + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 1) + package p2; + ^ + The type p1.A cannot be resolved. It is indirectly referenced from required type p1.B + ---------- + 2. ERROR in p2\\C.java (at line 4) + B test() { + ^ + Bound mismatch: The type C is not a valid substitute for the bounded parameter of the type B + ---------- + 3. ERROR in p2\\C.java (at line 5) + new B<>(this); + ^^^^^^^^^^^^^ + Cannot infer type arguments for B<> + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClass_samMissingParameterType_OK() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/F.java", + """ + package p1; + import p1.A; + public interface F { + public void m(A a); + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.F; + class C { + F test() { + return a -> {}; + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + return a -> {}; + ^^^^ + This lambda expression refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClass_samMissingParameterType_NOK() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/F.java", + """ + package p1; + import p1.A; + public interface F { + public void m(A a); + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.F; + class C { + F test() { + return a -> bar(a); + } + void bar(C c) {} + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + return a -> bar(a); + ^^^^^^^^^^^ + This lambda expression refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} +public void testMissingClass_samMissingReturnType() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/A.java", + """ + package p1; + public class A {} + """, + "p1/F.java", + """ + package p1; + import p1.A; + public interface F { + public A m(); + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "A.class")); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.F; + class C { + F test() { + return () -> null; + } + } + """ + }; + runner.expectedCompilerLog = """ + ---------- + 1. ERROR in p2\\C.java (at line 5) + return () -> null; + ^^^^^^^^^^ + This lambda expression refers to the missing type A + ---------- + """; + runner.runNegativeTest(); +} } From b69426b3de383aa67fe29f9055eebc92a3f33e4c Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Tue, 2 Jul 2024 22:29:08 +0200 Subject: [PATCH 13/16] rename constant also in comments --- .../compiler/lookup/ParameterizedGenericMethodBinding.java | 2 +- .../src/org/eclipse/jdt/internal/compiler/lookup/Scope.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java index 60c0e7ff4e1..83f5fe5f450 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java @@ -135,7 +135,7 @@ public static MethodBinding computeCompatibleMethod(MethodBinding originalMethod ParameterizedGenericMethodBinding substitute = inferFromArgumentTypes(scope, originalMethod, arguments, parameters, inferenceContext); if (substitute != null && substitute.returnType.isCompatibleWith(expectedType)) { // Do not use the new solution if it results in incompatibilities in parameter types - if ((scope.parameterCompatibilityLevel(substitute, arguments, false)) > Scope.NOT_COMPATIBLE) { // don't worry about NEEDS_MISSING_TYPE in 1.7 context + if ((scope.parameterCompatibilityLevel(substitute, arguments, false)) > Scope.NOT_COMPATIBLE) { // don't worry about COMPATIBLE_IGNORING_MISSING_TYPE in 1.7 context methodSubstitute = substitute; } else { inferenceContext = oldContext; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java index 5a7178ac6d5..2801b85d124 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -5165,7 +5165,7 @@ public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] argum } else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo(); return NOT_COMPATIBLE; } - if (level != COMPATIBLE_IGNORING_MISSING_TYPE) // preserve any NEEDS_MISSING_TYPE + if (level != COMPATIBLE_IGNORING_MISSING_TYPE) // preserve any COMPATIBLE_IGNORING_MISSING_TYPE level = VARARGS_COMPATIBLE; // varargs support needed } } else if (paramLength != argLength) { @@ -5179,7 +5179,7 @@ public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] argum int newLevel = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method); if (newLevel < COMPATIBLE) return newLevel; - if (newLevel > level && level != COMPATIBLE_IGNORING_MISSING_TYPE) // preserve any NEEDS_MISSING_TYPE + if (newLevel > level && level != COMPATIBLE_IGNORING_MISSING_TYPE) // preserve any COMPATIBLE_IGNORING_MISSING_TYPE level = newLevel; } } From 285eee1ba99d6e7159ffbe3ea8f8f7eeb6eeae30 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Wed, 10 Jul 2024 22:40:49 +0200 Subject: [PATCH 14/16] from review comments: + improve comment in DependencyTests + add more invocations in PTAMT.testMissingClassNeededForOverloadResolution_varargs1b + reject candidate meth by mismatching arg beyond a missing type param --- .../jdt/internal/compiler/lookup/Scope.java | 9 ++-- .../core/tests/builder/DependencyTests.java | 2 +- .../regression/ProblemTypeAndMethodTest.java | 52 +++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java index 2801b85d124..244c093b1e9 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -5177,10 +5177,13 @@ public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] argum TypeBinding arg = (tiebreakingVarargsMethods && (i == (argLength - 1))) ? ((ArrayBinding)arguments[i]).elementsType() : arguments[i]; if (TypeBinding.notEquals(arg,param)) { int newLevel = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method); - if (newLevel < COMPATIBLE) - return newLevel; - if (newLevel > level && level != COMPATIBLE_IGNORING_MISSING_TYPE) // preserve any COMPATIBLE_IGNORING_MISSING_TYPE + if (newLevel == NOT_COMPATIBLE) { + return NOT_COMPATIBLE; + } else if (newLevel == COMPATIBLE_IGNORING_MISSING_TYPE) { + level = newLevel; + } else if (newLevel > level && level != COMPATIBLE_IGNORING_MISSING_TYPE) { level = newLevel; + } } } return level; diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/DependencyTests.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/DependencyTests.java index 8656c4b146c..07de7950983 100644 --- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/DependencyTests.java +++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/DependencyTests.java @@ -909,7 +909,7 @@ public void testMissingClassFile() throws JavaModelException { "import p2.A;\n" + "public class B {\n"+ //$NON-NLS-1$ " public static void main(String[] args) {\n" + //$NON-NLS-1$ - " new A().foo(new Object());\n" + // potentially ambiguous + " new A().foo(new B());\n" + // applicability test would like to see MissingClass " new A().foo(new String());\n" + // exact match to fully resolved method " }\n" + //$NON-NLS-1$ "}\n" //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java index fbb4f2566c9..d0205b01945 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java @@ -8875,6 +8875,45 @@ The method m(A) from the type B refers to the missing type A """; runner.runNegativeTest(); } +public void testMissingClassNeededForOverloadResolution_pickByLateArg() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 + Runner runner = new Runner(); + runner.testFiles = new String[] { + "p1/MissingType.java", + """ + package p1; + public class MissingType {} + """, + "p1/B.java", + """ + package p1; + import java.util.Date; + public interface B { + public void m(String s, MissingType m, Date d); + public void m(String s, Object o, Integer i); + } + """ + }; + runner.runConformTest(); + + // delete binary file A (i.e. simulate removing it from classpath for subsequent compile) + Util.delete(new File(OUTPUT_DIR, "p1" + File.separator + "MissingType.class")); + runner.shouldFlushOutputDirectory = false; + + runner.testFiles = new String[] { + "p2/C.java", + """ + package p2; + import p1.B; + public class C { + void test(B b) { + b.m("Hello", new Object(), 42); // last arg rules out the overload with MissingType + } + } + """ + }; + runner.runConformTest(); +} public void testMissingClassNeededForOverloadResolution_ctor() { if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // ignore different outcome below 1.8 since PR 2543 Runner runner = new Runner(); @@ -9144,6 +9183,9 @@ void test(B b) { b.m(b); b.m(b, b); b.m(new B[0]); + b.m(""); // would like to check against A1 / A2 + b.m("", ""); // would like to check against A1 / A2 + b.m(new String[0]); // exact match } } """ @@ -9175,6 +9217,16 @@ The method m(A1...) from the type B refers to the missing type A1 ^ The method m(A1...) from the type B refers to the missing type A1 ---------- + 6. ERROR in p2\\C.java (at line 10) + b.m(""); // would like to check against A1 / A2 + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- + 7. ERROR in p2\\C.java (at line 11) + b.m("", ""); // would like to check against A1 / A2 + ^ + The method m(A1...) from the type B refers to the missing type A1 + ---------- """; runner.runNegativeTest(); } From 1b4526ab2d7407410d4fbdd77acac6a483422b25 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Thu, 11 Jul 2024 11:58:04 +0200 Subject: [PATCH 15/16] left-over from review + more locations to propagate HasMissingType along w/ other tagBits --- .../jdt/internal/compiler/lookup/CaptureBinding.java | 9 +++------ .../internal/compiler/lookup/InferenceSubstitution.java | 3 +-- .../compiler/lookup/ParameterizedMethodBinding.java | 2 +- .../compiler/lookup/ParameterizedTypeBinding.java | 7 +++---- .../internal/compiler/lookup/TypeVariableBinding.java | 4 ++-- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java index 9dea4749782..c7723579ac1 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2021 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -63,13 +63,10 @@ public CaptureBinding(WildcardBinding wildcard, ReferenceBinding sourceType, int this.environment.typeSystem.cacheDerivedType(this, unannotated, this); // propagate from wildcard to capture - use super version, because our own method propagates type annotations in the opposite direction: super.setTypeAnnotations(wildcard.getTypeAnnotations(), wildcard.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled); - if (wildcard.hasNullTypeAnnotations()) - this.tagBits |= TagBits.HasNullTypeAnnotation; + this.tagBits |= wildcard.tagBits & (TagBits.HasNullTypeAnnotation|TagBits.HasMissingType); } else { computeId(this.environment); - if(wildcard.hasNullTypeAnnotations()) { - this.tagBits |= (wildcard.tagBits & TagBits.AnnotationNullMASK) | TagBits.HasNullTypeAnnotation; - } + this.tagBits |= wildcard.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation|TagBits.HasMissingType); } } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java index c6cb99b9ffb..d9509d37de1 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java @@ -144,8 +144,7 @@ public TypeBinding substitute(TypeVariableBinding typeVariable) { typeVariable.superclass = superclass; typeVariable.superInterfaces = superInterfaces; typeVariable.firstBound = superclass != null ? superclass : superInterfaces[0]; - if (typeVariable.firstBound.hasNullTypeAnnotations()) - typeVariable.tagBits |= TagBits.HasNullTypeAnnotation; + typeVariable.tagBits |= typeVariable.firstBound.tagBits & (TagBits.HasNullTypeAnnotation|TagBits.HasMissingType); } return typeVariable; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java index 5c0569e0359..b4576ac2880 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java @@ -209,7 +209,7 @@ public ParameterizedMethodBinding(final ReferenceBinding declaringClass, MethodB this, originalVariable.rank, environment); - substitutedVariables[i].tagBits |= (originalVariable.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation)); + substitutedVariables[i].tagBits |= (originalVariable.tagBits & (TagBits.AnnotationNullMASK|TagBits.HasNullTypeAnnotation|TagBits.HasMissingType)); } this.typeVariables = substitutedVariables; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java index 32df901927e..158154973c4 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java @@ -91,12 +91,11 @@ public ParameterizedTypeBinding(ReferenceBinding type, TypeBinding[] arguments, for (TypeBinding argument : arguments) { if (argument instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) argument).addWrapper(this, environment); - if (argument.hasNullTypeAnnotations()) - this.tagBits |= TagBits.HasNullTypeAnnotation; + this.tagBits |= argument.tagBits & (TagBits.HasNullTypeAnnotation | TagBits.HasMissingType); } } - if (enclosingType != null && enclosingType.hasNullTypeAnnotations()) - this.tagBits |= TagBits.HasNullTypeAnnotation; + if (enclosingType != null) + this.tagBits |= enclosingType.tagBits & (TagBits.HasNullTypeAnnotation | TagBits.HasMissingType); this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve() this.typeBits = type.typeBits; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java index 864c756b131..df64ebf3a43 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java @@ -1094,8 +1094,8 @@ public TypeBinding setFirstBound(TypeBinding firstBound) { annotatedType.firstBound = firstBound; } } - if (firstBound != null && firstBound.hasNullTypeAnnotations()) - this.tagBits |= TagBits.HasNullTypeAnnotation; + if (firstBound != null) + this.tagBits |= firstBound.tagBits & (TagBits.HasNullTypeAnnotation|TagBits.HasMissingType); return firstBound; } /* An annotated type variable use differs from its declaration exactly in its annotations and in nothing else. From 82ee42da9ff7141d74be705507cd177aa401b6cd Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Thu, 11 Jul 2024 14:53:12 +0200 Subject: [PATCH 16/16] clean-up and fix regression: + revert duplicate tagging with HasMissingType (already in initialize()) + fix tests by adding required import + create one test variant with missing import and POTENTIAL_MATCH --- .../lookup/ParameterizedTypeBinding.java | 7 ++-- .../tests/model/JavaSearchBugsTests2.java | 40 ++++++++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java index 158154973c4..32df901927e 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java @@ -91,11 +91,12 @@ public ParameterizedTypeBinding(ReferenceBinding type, TypeBinding[] arguments, for (TypeBinding argument : arguments) { if (argument instanceof UnresolvedReferenceBinding) ((UnresolvedReferenceBinding) argument).addWrapper(this, environment); - this.tagBits |= argument.tagBits & (TagBits.HasNullTypeAnnotation | TagBits.HasMissingType); + if (argument.hasNullTypeAnnotations()) + this.tagBits |= TagBits.HasNullTypeAnnotation; } } - if (enclosingType != null) - this.tagBits |= enclosingType.tagBits & (TagBits.HasNullTypeAnnotation | TagBits.HasMissingType); + if (enclosingType != null && enclosingType.hasNullTypeAnnotations()) + this.tagBits |= TagBits.HasNullTypeAnnotation; this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve() this.typeBits = type.typeBits; } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java index 355c86465d9..cb991bf3b25 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2016 IBM Corporation and others. + * Copyright (c) 2014, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -210,6 +210,7 @@ public void testBug123836c() throws CoreException { // create the common project and create an interface project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); createFile("/P/Test.java", + "import java.io.Serializable;\n" + "class Test {\n"+ " void calc(Property prop, Property p2) {\n"+ " prop.compute(null);\n"+ @@ -232,6 +233,36 @@ public void testBug123836c() throws CoreException { deleteProject(project); } } + public void testBug123836c_missingImport() throws CoreException { + // original version with missing import, will now give POTENTIAL_MATCH + IJavaProject project = null; + try + { + // create the common project and create an interface + project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); + createFile("/P/Test.java", + "class Test {\n"+ + " void calc(Property prop, Property p2) {\n"+ + " prop.compute(null);\n"+ + " p2.compute(null);\n"+ + " }\n"+ + "}\n"+ + "abstract class Property {\n"+ + " public abstract void compute(E e);\n"+ + "}\n"+ + "class StringProperty extends Property {\n"+ + " @Override public void compute(String e) {\n"+ + " System.out.println(e);\n"+ + " }"); + IType type = getCompilationUnit("/P/Test.java").getType("StringProperty"); + IMethod method = type.getMethod("compute", new String[]{"QString;"}); + search(method, REFERENCES, EXACT_RULE, SearchEngine.createWorkspaceScope(), this.resultCollector); + assertSearchResults("Test.java void Test.calc(Property, Property) [compute(null)] EXACT_MATCH\n" + + "Test.java void Test.calc(Property, Property) [compute(null)] POTENTIAL_MATCH"); + } finally { + deleteProject(project); + } + } // Test inner class public void testBug123836d() throws CoreException { IJavaProject project = null; @@ -240,6 +271,7 @@ public void testBug123836d() throws CoreException { // create the common project and create an interface project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); createFile("/P/Test.java", + "import java.io.Serializable;\n" + "class Test {\n"+ " void calc(Property prop, Property p2) {\n"+ " prop.compute(null);\n"+ @@ -271,6 +303,7 @@ public void testBug123836e() throws CoreException { // create the common project and create an interface project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); createFile("/P/Test.java", + "import java.io.Serializable;\n" + "class Test {\n"+ " void calc(Property prop, Property p2) {\n"+ " prop.compute(null);\n"+ @@ -301,6 +334,7 @@ public void testBug123836f() throws CoreException { // create the common project and create an interface project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); createFile("/P/Test.java", + "import java.io.Serializable;\n" + "class Test {\n"+ " void calc(Property prop, Property p2) {\n"+ " prop.compute(null);\n"+ @@ -331,6 +365,7 @@ public void testBug123836g() throws CoreException { // create the common project and create an interface project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); createFile("/P/Test.java", + "import java.io.Serializable;\n" + "class Test {\n"+ " {\n" + " new Property() {\n" + @@ -361,6 +396,7 @@ public void testBug123836h() throws CoreException { // create the common project and create an interface project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); createFile("/P/Test.java", + "import java.io.Serializable;\n" + "class Test {\n"+ " static {\n" + " new Property() {\n" + @@ -391,6 +427,7 @@ public void testBug123836i() throws CoreException { // create the common project and create an interface project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); createFile("/P/Test.java", + "import java.io.Serializable;\n" + "class Test {\n"+ " Property p = new Property() {\n" + " @Override public void compute(String e) {}\n" + @@ -418,6 +455,7 @@ public void testBug123836j() throws CoreException { // create the common project and create an interface project = createJavaProject("P", new String[] {""}, new String[] {"JCL15_LIB"}, "","1.5"); createFile("/P/Test.java", + "import java.io.Serializable;\n" + "class Test {\n"+ " void calc(Property prop, Property p2) {\n"+ " prop.compute(null);\n"+