From 03658fd4ac29c267869c3ad9cf20788feb200e6e Mon Sep 17 00:00:00 2001 From: Srikanth Sankaran <131454720+srikanth-sankaran@users.noreply.github.com> Date: Thu, 8 Jun 2023 11:54:36 +0530 Subject: [PATCH] ECJ out of sync with JLS 9.6.4.1 (#1097) * Reverse the changes made for https://bugs.eclipse.org/bugs/show_bug.cgi?id=552082 * Tweak for test failures in Jenkins * Implement the recent changes to JLS 9.6.4.1 * Incorporate review comment https://github.com/eclipse-jdt/eclipse.jdt.core/pull/1097#discussion_r1210427778 * Additional test case for https://bugs.eclipse.org/bugs/show_bug.cgi?id=568240 * Additional regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=566803 * Review follow up: Get rid of the head-scratch producing enumerator NonJVMS4_7_20_TargetLocation. --- .../eclipse/jdt/core/compiler/IProblem.java | 6 +- .../jdt/internal/compiler/ClassFile.java | 8 +- .../jdt/internal/compiler/ast/Annotation.java | 51 +++--- .../internal/compiler/ast/TypeReference.java | 8 +- .../compiler/problem/ProblemReporter.java | 7 + .../regression/AbstractRegressionTest.java | 4 - .../regression/JSR308SpecSnippetTests.java | 20 ++- .../NegativeTypeAnnotationTest.java | 149 ++++++++++++---- .../RecordsRestrictedClassTest.java | 30 +--- .../regression/RepeatableAnnotationTest.java | 61 +++++-- .../regression/TypeAnnotationTest.java | 162 +++++++++++++++++- 11 files changed, 386 insertions(+), 120 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java index be959304dbe..f8258575b81 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/core/compiler/IProblem.java @@ -1511,11 +1511,7 @@ public interface IProblem { int ConstructorReferenceNotBelow18 = Internal + Syntax + 647; /** @since 3.10 */ int ExplicitThisParameterNotInLambda = Internal + Syntax + 648; - /** - * @since 3.10 - * @deprecated Per https://bugs.openjdk.java.net/browse/JDK-8231435 this problem is no longer raised - */ - @Deprecated + /** @since 3.10 */ int ExplicitAnnotationTargetRequired = TypeRelated + 649; /** @since 3.10 */ int IllegalTypeForExplicitThis = Internal + Syntax + 650; 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 e13166f9bc0..d23872557b0 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 @@ -4578,9 +4578,9 @@ private int generateRuntimeAnnotations(final Annotation[] annotations, final lon if (annotationMask != 0 && (annotationMask & targetMask) == 0) { if (!jdk16packageInfoAnnotation(annotationMask, targetMask)) continue; } - if (annotation.isRuntimeInvisible() || annotation.isRuntimeTypeInvisible()) { + if (annotation.isRuntimeInvisible() || annotation.isRuntimeTypeInvisible(false)) { invisibleAnnotationsCounter++; - } else if (annotation.isRuntimeVisible() || annotation.isRuntimeTypeVisible()) { + } else if (annotation.isRuntimeVisible() || annotation.isRuntimeTypeVisible(false)) { visibleAnnotationsCounter++; } } @@ -4609,7 +4609,7 @@ private int generateRuntimeAnnotations(final Annotation[] annotations, final lon if (annotationMask != 0 && (annotationMask & targetMask) == 0) { if (!jdk16packageInfoAnnotation(annotationMask, targetMask)) continue; } - if (annotation.isRuntimeInvisible() || annotation.isRuntimeTypeInvisible()) { + if (annotation.isRuntimeInvisible() || annotation.isRuntimeTypeInvisible(false)) { int currentAnnotationOffset = this.contentsOffset; generateAnnotation(annotation, currentAnnotationOffset); invisibleAnnotationsCounter--; @@ -4657,7 +4657,7 @@ private int generateRuntimeAnnotations(final Annotation[] annotations, final lon if (annotationMask != 0 && (annotationMask & targetMask) == 0) { if (!jdk16packageInfoAnnotation(annotationMask, targetMask)) continue; } - if (annotation.isRuntimeVisible() || annotation.isRuntimeTypeVisible()) { + if (annotation.isRuntimeVisible() || annotation.isRuntimeTypeVisible(false)) { visibleAnnotationsCounter--; int currentAnnotationOffset = this.contentsOffset; generateAnnotation(annotation, currentAnnotationOffset); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java index bb29cb6d5af..df0f18ce06b 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java @@ -768,18 +768,19 @@ public boolean isRuntimeInvisible() { return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention; } - public boolean isRuntimeTypeInvisible() { + public boolean isRuntimeTypeInvisible(boolean targetingTypeParameter) { final TypeBinding annotationBinding = this.resolvedType; if (annotationBinding == null) { return false; } long metaTagBits = annotationBinding.getAnnotationTagBits(); // could be forward reference - if ((metaTagBits & (TagBits.AnnotationTargetMASK)) != 0) { - if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) == 0) { + if ((metaTagBits & (TagBits.AnnotationTargetMASK)) == 0) { // In the absence of explicit target, applicable only to declaration sites + if (!targetingTypeParameter) return false; - } - } // else: no-@Target always applicable + } else if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) == 0) { + return false; + } if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0) return true; // by default the retention is CLASS @@ -787,18 +788,19 @@ public boolean isRuntimeTypeInvisible() { return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention; } - public boolean isRuntimeTypeVisible() { + public boolean isRuntimeTypeVisible(boolean targetingTypeParameter) { final TypeBinding annotationBinding = this.resolvedType; if (annotationBinding == null) { return false; } long metaTagBits = annotationBinding.getAnnotationTagBits(); - if ((metaTagBits & (TagBits.AnnotationTargetMASK)) != 0) { - if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) == 0) { + if ((metaTagBits & (TagBits.AnnotationTargetMASK)) == 0) { // In the absence of explicit target, applicable only to declaration sites + if (!targetingTypeParameter) return false; - } - } // else: no-@Target always applicable + } else if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) == 0) { + return false; + } if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0) return false; // by default the retention is CLASS @@ -1162,7 +1164,7 @@ public long handleNonNullByDefault(BlockScope scope) { } public enum AnnotationTargetAllowed { - YES, TYPE_ANNOTATION_ON_QUALIFIED_NAME, NO; + YES, NO_DUE_TO_LACKING_TARGET, TYPE_ANNOTATION_ON_QUALIFIED_NAME, NO/*_DUE_TO_MISMATCHED_TARGET*/; } private static AnnotationTargetAllowed isAnnotationTargetAllowed(Binding recipient, BlockScope scope, TypeBinding annotationType, int kind, long metaTagBits) { @@ -1274,6 +1276,9 @@ else if (scope.compilerOptions().sourceLevel <= ClassFileConstants.JDK1_6) { } break; case Binding.TYPE_PARAMETER : // jsr308 + if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) { + return AnnotationTargetAllowed.YES; + } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391196 if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) != 0) { return AnnotationTargetAllowed.YES; @@ -1300,8 +1305,11 @@ static AnnotationTargetAllowed isAnnotationTargetAllowed(Annotation annotation, long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) { - // does not specify any target restriction - all locations are possible - return AnnotationTargetAllowed.YES; + /* JLS 9.6.4.1: If an annotation of type java.lang.annotation.Target is not present on the + declaration of an annotation interface A, then A is applicable in all declaration + contexts and in no type contexts. + */ + return kind == Binding.TYPE_USE ? AnnotationTargetAllowed.NO_DUE_TO_LACKING_TARGET : AnnotationTargetAllowed.YES; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391201 @@ -1329,13 +1337,16 @@ static void checkAnnotationTarget(Annotation annotation, BlockScope scope, Refer // no need to check annotation usage if missing return; } - AnnotationTargetAllowed annotationTargetAllowed = isAnnotationTargetAllowed(annotation, scope, annotationType, kind); - if (annotationTargetAllowed != AnnotationTargetAllowed.YES) { - if(annotationTargetAllowed == AnnotationTargetAllowed.TYPE_ANNOTATION_ON_QUALIFIED_NAME) { - scope.problemReporter().typeAnnotationAtQualifiedName(annotation); - } else { - scope.problemReporter().disallowedTargetForAnnotation(annotation); - } + + AnnotationTargetAllowed annotationTargetAllowed = isAnnotationTargetAllowed(annotation, scope, annotationType, kind); + if (annotationTargetAllowed != AnnotationTargetAllowed.YES) { + if(annotationTargetAllowed == AnnotationTargetAllowed.TYPE_ANNOTATION_ON_QUALIFIED_NAME) { + scope.problemReporter().typeAnnotationAtQualifiedName(annotation); + } else if (annotationTargetAllowed == AnnotationTargetAllowed.NO_DUE_TO_LACKING_TARGET) { + scope.problemReporter().explitAnnotationTargetRequired(annotation); + } else { + scope.problemReporter().disallowedTargetForAnnotation(annotation); + } if (recipient instanceof TypeBinding) ((TypeBinding)recipient).tagBits &= ~tagBitsToRevert; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java index eef36b31d76..13632d25cc5 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java @@ -189,11 +189,15 @@ public AnnotationCollector(RecordComponent recordComponent, int targetType, List this.targetType = targetType; } + private boolean targetingTypeParameter() { + return this.targetType == AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER || this.targetType == AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER; + } + private boolean internalVisit(Annotation annotation) { AnnotationContext annotationContext = null; - if (annotation.isRuntimeTypeInvisible()) { + if (annotation.isRuntimeTypeInvisible(targetingTypeParameter())) { annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, AnnotationContext.INVISIBLE); - } else if (annotation.isRuntimeTypeVisible()) { + } else if (annotation.isRuntimeTypeVisible(targetingTypeParameter())) { annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, AnnotationContext.VISIBLE); } if (annotationContext != null) { 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 45d7928f48f..82d666f0796 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 @@ -2025,6 +2025,13 @@ public void disallowedTargetForAnnotation(Annotation annotation) { annotation.sourceStart, annotation.sourceEnd); } +public void explitAnnotationTargetRequired(Annotation annotation) { + this.handle(IProblem.ExplicitAnnotationTargetRequired, + NoArgument, + NoArgument, + annotation.sourceStart, + annotation.sourceEnd); +} public void polymorphicMethodNotBelow17(ASTNode node) { this.handle( IProblem.PolymorphicMethodNotBelow17, diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java index 60704ef4ac3..ba453a9a1fc 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java @@ -1134,10 +1134,6 @@ Excuse excuseFor(JavacCompiler compiler) { new JavacBug8221413(" --release 12 --enable-preview -Xlint:-preview") : null, JavacBug8226510_switchExpression = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8226510 new JavacBug8226510(" --release 12 --enable-preview -Xlint:-preview") : null, - JavacBug8231436 = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8231436 to implement https://bugs.openjdk.java.net/browse/JDK-8231435 - new JavacHasABug(MismatchType.JavacErrorsEclipseNone) : null, - JavacBug8231436_EclipseWarns = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8231436 to implement https://bugs.openjdk.java.net/browse/JDK-8231435 - new JavacHasABug(MismatchType.JavacErrorsEclipseWarnings) : null, JavacBug8299416 = RUN_JAVAC ? // https://bugs.openjdk.java.net/browse/JDK-8299416 new JavacBugExtraJavacOptionsPlusMismatch(" --release 20 --enable-preview -Xlint:-preview", MismatchType.EclipseErrorsJavacNone| MismatchType.EclipseErrorsJavacWarnings) : null; diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR308SpecSnippetTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR308SpecSnippetTests.java index 62e23d7697b..ca302f1d58f 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR308SpecSnippetTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR308SpecSnippetTests.java @@ -889,10 +889,11 @@ public void test017() throws Exception { checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X$Y.class", "Y", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } public void test018() throws Exception { - Runner runner = new Runner(); - runner.testFiles = + this.runNegativeTest( new String[] { "X.java", + "import java.lang.annotation.*;\n" + + "import static java.lang.annotation.ElementType.*; \n" + "@interface Receiver {}\n" + "class Document {}\n" + "interface I {\n" + @@ -904,9 +905,18 @@ public void test018() throws Exception { " Y(@Receiver X X.this, boolean b) { }\n" + " }\n" + "}\n", - }; - runner.javacTestOptions = JavacTestOptions.JavacHasABug.JavacBug8231436; - runner.runConformTest(); + }, + "----------\n" + + "1. ERROR in X.java (at line 9)\n" + + " void foo(@Receiver X this) {}\n" + + " ^^^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n" + + "2. ERROR in X.java (at line 11)\n" + + " Y(@Receiver X X.this, boolean b) { }\n" + + " ^^^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); } public void test019() throws Exception { this.runConformTest( diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java index dee08ac9693..5ffa032af6d 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java @@ -686,20 +686,18 @@ public void test031() throws Exception { "----------\n"); } public void test032() throws Exception { - Runner runner = new Runner(); - runner.testFiles = + this.runConformTest( new String[] { "Marker.java", "@interface Marker {}", "X.java", "public class X<@Marker T> {}", - }; - runner.javacTestOptions = JavacTestOptions.JavacHasABug.JavacBug8231436; - runner.runConformTest(); + }, + ""); + } public void test033() throws Exception { - Runner runner = new Runner(); - runner.testFiles = + this.runNegativeTest( new String[] { "Marker.java", "@interface Marker {}", @@ -707,9 +705,13 @@ public void test033() throws Exception { "public class Y {}", "X.java", "public class X extends @Marker Y {}", - }; - runner.javacTestOptions = JavacTestOptions.JavacHasABug.JavacBug8231436; - runner.runConformTest(); + }, + "----------\n" + + "1. ERROR in X.java (at line 1)\n" + + " public class X extends @Marker Y {}\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); } // check locations public void test034() throws Exception { @@ -880,20 +882,23 @@ public void test036() throws Exception { "----------\n"); } public void test037() { - Runner runner = new Runner(); - runner.testFiles = + this.runNegativeTest( new String[] { "X.java", "@interface Marker {}\n" + "@Marker // line 2: Don't complain \n" + - "public class X<@Marker T> extends @Marker Object{ // 3: Complain \n" + + "public class X<@Marker T> extends @Marker Object{ // 3: Complain only on super type and not on class type parameter\n" + " public @Marker Object foo(@Marker Object obj) { // 4: Don't complain on both\n" + " return null;\n" + " }\n" + "}\n", - }; - runner.javacTestOptions = JavacTestOptions.JavacHasABug.JavacBug8231436; - runner.runConformTest(); + }, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " public class X<@Marker T> extends @Marker Object{ // 3: Complain only on super type and not on class type parameter\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=383950 // [1.8][compiler] Type annotations must have target type meta annotation TYPE_USE @@ -2099,8 +2104,7 @@ public void test061() throws Exception { "----------\n"); } public void test062() throws Exception { - // was negative prior to https://bugs.openjdk.java.net/browse/JDK-8231435 - this.runConformTest( + this.runNegativeTest( new String[] { "X.java", "public class X {\n" + @@ -2111,7 +2115,12 @@ public void test062() throws Exception { "@interface Marker {\n" + "}\n" }, - ""); + "----------\n" + + "1. ERROR in X.java (at line 2)\n" + + " public @Marker Object foo() {\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); } public void test063() throws Exception { this.runNegativeTest( @@ -2153,8 +2162,7 @@ public void test064() throws Exception { "----------\n"); } public void test065() throws Exception { - Runner runner = new Runner(); - runner.testFiles = + this.runNegativeTest( new String[] { "X.java", "public class X {\n" + @@ -2162,9 +2170,18 @@ public void test065() throws Exception { "}\n" + "@interface Marker {\n" + "}\n" - }; - runner.javacTestOptions = JavacTestOptions.JavacHasABug.JavacBug8231436; - runner.runConformTest(); + }, + "----------\n" + + "1. WARNING in X.java (at line 2)\n" + + " Object o = new @Marker X();\n" + + " ^^^^^^\n" + + "Unused type arguments for the non generic constructor X() of type X; it should not be parameterized with arguments \n" + + "----------\n" + + "2. ERROR in X.java (at line 2)\n" + + " Object o = new @Marker X();\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); } public void test066() throws Exception { this.runNegativeTest( @@ -2176,10 +2193,14 @@ public void test066() throws Exception { "@interface Marker {\n" + "}\n" }, - // one error removed after https://bugs.openjdk.java.net/browse/JDK-8231435 "----------\n" + "1. ERROR in X.java (at line 2)\n" + " Object o = new X().new @Marker X();\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n" + + "2. ERROR in X.java (at line 2)\n" + + " Object o = new X().new @Marker X();\n" + " ^^^^^^^^^\n" + "X.X cannot be resolved to a type\n" + "----------\n"); @@ -2202,8 +2223,7 @@ public void test067() throws Exception { "----------\n"); } public void test068() throws Exception { - Runner runner = new Runner(); - runner.testFiles = + this.runNegativeTest( new String[] { "X.java", "public class X {\n" + @@ -2211,9 +2231,18 @@ public void test068() throws Exception { "}\n" + "@interface Marker {\n" + "}\n" - }; - runner.javacTestOptions = JavacTestOptions.JavacHasABug.JavacBug8231436; - runner.runConformTest(); + }, + "----------\n" + + "1. WARNING in X.java (at line 2)\n" + + " Object o = new @Marker X() {};\n" + + " ^^^^^^\n" + + "Unused type arguments for the non generic constructor X() of type X; it should not be parameterized with arguments \n" + + "----------\n" + + "2. ERROR in X.java (at line 2)\n" + + " Object o = new @Marker X() {};\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=385293 public void test069() throws Exception { @@ -2280,6 +2309,8 @@ public void test0388085() { public void test0388085a() { this.runNegativeTest( new String[] {"X.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + "class X {\n" + " public void main() {\n" + " final One<@Marker ? extends Two<@Marker ? super Three>>> one = null;" + @@ -2291,13 +2322,26 @@ public void test0388085a() { "class Three {}\n" + "class Four {}\n" + "@interface Marker {}"}, - // some errors no longer raised since https://bugs.openjdk.java.net/browse/JDK-8231435 "----------\n" + - "1. ERROR in X.java (at line 3)\n" + + "1. ERROR in X.java (at line 5)\n" + " final One<@Marker ? extends Two<@Marker ? super Three>>> one = null; one = null;\n" + - " ^^^\n" + - "The final local variable one cannot be assigned. It must be blank and not using a compound assignment\n" + - "----------\n"); + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n" + + "2. ERROR in X.java (at line 5)\n" + + " final One<@Marker ? extends Two<@Marker ? super Three>>> one = null; one = null;\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n" + + "3. ERROR in X.java (at line 5)\n" + + " final One<@Marker ? extends Two<@Marker ? super Three>>> one = null; one = null;\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n" + + "4. ERROR in X.java (at line 5)\n" + + " final One<@Marker ? extends Two<@Marker ? super Three>>> one = null; one = null;\n" + + " ^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n"); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=390882 public void test0390882() { @@ -2672,12 +2716,16 @@ public void testBug391315() { " TYPE_PARAMETER,\n" + " TYPE_USE\n" + "}\n"}, - // one error removed after https://bugs.openjdk.java.net/browse/JDK-8231435 "----------\n" + "1. ERROR in X.java (at line 2)\n" + " X<@Marker ?> l;\n" + " ^^^^^^^\n" + "The annotation @Marker is disallowed for this location\n" + + "----------\n" + + "2. ERROR in X.java (at line 4)\n" + + " X<@Marker3 ?> l3;\n" + + " ^^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + "----------\n"); } public void testBug391315a() { @@ -4416,4 +4464,33 @@ public void test419827b() { "", true); } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=552082 + public void test552082_comment_0() throws Exception { + this.runNegativeTest( + new String[] { + "EclipseReturnValueAnnotationTest.java", + "class EclipseReturnValueAnnotationTest {\n" + + " \n" + + " @interface SomeAnnotation {}\n" + + "\n" + + " public @SomeAnnotation String foo(Object anything) {\n" + + " return \"foo\";\n" + + " }\n" + + "\n" + + " public @SomeAnnotation String bar(T anything) { // Error - type annotation position\n" + + " return \"bar\";\n" + + " }\n" + + "\n" + + " public @SomeAnnotation String baz(T anything) { // OK - declaration annotation on method \n" + + " return \"baz\";\n" + + " }\n" + + "}\n", + }, + "----------\n" + + "1. ERROR in EclipseReturnValueAnnotationTest.java (at line 9)\n" + + " public @SomeAnnotation String bar(T anything) { // Error - type annotation position\n" + + " ^^^^^^^^^^^^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); + } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java index 22e82ea7302..2ed6c891d3b 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java @@ -3746,22 +3746,18 @@ public void testBug562439_019() throws IOException, ClassFormatException { " RuntimeInvisibleAnnotations: \n" + " #8 @Annot(\n" + " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #8 @Annot(\n" + - " target type = 0x13 FIELD\n" + - " )\n" + " \n"; RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM); expectedOutput = " Point(int myInt, char myChar);\n" + " 0 aload_0 [this]\n" + - " 1 invokespecial java.lang.Record() [16]\n" + + " 1 invokespecial java.lang.Record() [15]\n" + " 4 aload_0 [this]\n" + " 5 iload_1 [myInt]\n" + - " 6 putfield Point.myInt : int [19]\n" + + " 6 putfield Point.myInt : int [18]\n" + " 9 aload_0 [this]\n" + " 10 iload_2 [myChar]\n" + - " 11 putfield Point.myChar : char [21]\n" + + " 11 putfield Point.myChar : char [20]\n" + " 14 return\n" + " Line numbers:\n" + " [pc: 0, line: 11]\n" + @@ -3777,28 +3773,19 @@ public void testBug562439_019() throws IOException, ClassFormatException { " #8 @Annot(\n" + " )\n" + " Number of annotations for parameter 1: 0\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #8 @Annot(\n" + - " target type = 0x16 METHOD_FORMAL_PARAMETER\n" + - " method parameter index = 0\n" + - " )\n" + " \n"; RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM); expectedOutput = - " // Method descriptor #28 ()I\n" + + " // Method descriptor #27 ()I\n" + " // Stack: 1, Locals: 1\n" + " public int myInt();\n" + " 0 aload_0 [this]\n" + - " 1 getfield Point.myInt : int [19]\n" + + " 1 getfield Point.myInt : int [18]\n" + " 4 ireturn\n" + " Line numbers:\n" + " [pc: 0, line: 11]\n" + " RuntimeInvisibleAnnotations: \n" + " #8 @Annot(\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #8 @Annot(\n" + - " target type = 0x14 METHOD_RETURN\n" + " )\n"; RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM); expectedOutput = @@ -3809,10 +3796,6 @@ public void testBug562439_019() throws IOException, ClassFormatException { "int myInt;\n" + " RuntimeInvisibleAnnotations: \n" + " #8 @Annot(\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #8 @Annot(\n" + - " target type = 0x13 FIELD\n" + " )\n"; RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Point.class", ClassFileBytesDisassembler.SYSTEM); } @@ -8403,7 +8386,7 @@ public void testBug571038_3() throws Exception { + "@interface MyAnnot {}\n" }, "hello"); - String expectedOutput = " // Method descriptor #30 ()[LMyIntf;\n" + String expectedOutput = " // Method descriptor #29 ()[LMyIntf;\n" + " // Signature: ()[LMyIntf;\n" + " // Stack: 1, Locals: 1\n" + " public MyIntf[] t();\n"; @@ -8427,6 +8410,7 @@ public void testBug571038_4() throws Exception { + "}\n" + "interface MyIntf {}\n" + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@java.lang.annotation.Target(ElementType.TYPE_USE)\n" + "@interface MyAnnot {}\n" }, "hello"); diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java index da3d15acb5d..d013620ecbd 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java @@ -22,7 +22,6 @@ import junit.framework.Test; -import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest.JavacTestOptions.JavacHasABug; import org.eclipse.jdt.core.util.ClassFileBytesDisassembler; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -1427,8 +1426,7 @@ public void testUnspecifiedTarget2() { "----------\n"); } public void testDeprecation() { - Runner runner = new Runner(); - runner.testFiles = + this.runNegativeTest( new String[] { "TC.java", "@Deprecated\n" + @@ -1442,8 +1440,7 @@ public void testDeprecation() { "}\n" + "interface I<@T(1) @T(2) K> {\n" + "}\n" - }; - runner.expectedCompilerLog = + }, "----------\n" + "1. WARNING in T.java (at line 1)\n" + " @java.lang.annotation.Repeatable(TC.class)\n" + @@ -1453,15 +1450,10 @@ public void testDeprecation() { "2. WARNING in T.java (at line 5)\n" + " interface I<@T(1) @T(2) K> {\n" + " ^^\n" + - "The type TC is deprecated\n" + - "----------\n"; - runner.javacTestOptions = JavacHasABug.JavacBug8231436_EclipseWarns; - runner.runWarningTest(); + "The type TC is deprecated\n"); } public void testDeprecation2() { // verify that deprecation warning does not show up when the deprecated element is used in the same file defining it. - // was negative prior to https://bugs.openjdk.java.net/browse/JDK-8231435 - Runner runner = new Runner(); - runner.testFiles = + this.runNegativeTest( new String[] { "T.java", "@Deprecated\n" + @@ -1472,12 +1464,15 @@ public void testDeprecation2() { // verify that deprecation warning does not sho "@interface T {\n" + " public int value() default -1;\n" + "}\n" + - "interface I<@T(1) @T(2) K> {\n" + + "interface I extends @T(1) Runnable {\n" + "}\n" - }; - runner.expectedCompilerLog = ""; - runner.javacTestOptions = JavacHasABug.JavacBug8231436; - runner.runConformTest(); + }, + "----------\n" + + "1. ERROR in T.java (at line 9)\n" + + " interface I extends @T(1) Runnable {\n" + + " ^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); } // 419209: [1.8] Repeating container annotations should be rejected in the presence of annotation it contains @@ -1561,4 +1556,36 @@ public void testRepeatableWithContaining3() { "The repeatable annotation @Foo may not be present where its container annotation type @FooContainer is repeated\n" + "----------\n"); } + // check repeated occurrence of annotation where annotation container is not valid for the target + public void testRepeatingAnnotationsWithoutTarget() { + this.runNegativeTest( + new String[] { + "FooContainer.java", + "public @interface FooContainer {\n" + + " Foo[] value();\n" + + "}\n", + "Foo.java", + "@java.lang.annotation.Repeatable(FooContainer.class) public @interface Foo {\n" + + "}\n", + "X.java", + "public class X<@Foo @Foo T> extends @Foo @Foo Object {\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 1)\n" + + " public class X<@Foo @Foo T> extends @Foo @Foo Object {\n" + + " ^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n" + + "2. ERROR in X.java (at line 1)\n" + + " public class X<@Foo @Foo T> extends @Foo @Foo Object {\n" + + " ^^^^\n" + + "The annotation @Foo cannot be repeated at this location since its container annotation type @FooContainer is disallowed at this location\n" + + "----------\n" + + "3. ERROR in X.java (at line 1)\n" + + " public class X<@Foo @Foo T> extends @Foo @Foo Object {\n" + + " ^^^^\n" + + "Annotation types that do not specify explicit target element types cannot be applied here\n" + + "----------\n"); + } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java index 29b91a95107..c2524dd3c44 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java @@ -4225,6 +4225,8 @@ public void test082_multiuseAnnotations() throws Exception { this.runConformTest( new String[] { "X.java", + "import java.lang.annotation.*;\n" + + "@Target({ElementType.METHOD, ElementType.TYPE_USE})\n" + "@interface Annot {\r\n" + " int value() default 0;\r\n" + "}\r\n" + @@ -4241,7 +4243,7 @@ public void test082_multiuseAnnotations() throws Exception { " public void foo();\n" + " 0 return\n" + " Line numbers:\n" + - " [pc: 0, line: 7]\n" + + " [pc: 0, line: 9]\n" + " Local variable table:\n" + " [pc: 0, pc: 1] local: this index: 0 type: X\n" + " RuntimeInvisibleAnnotations: \n" + @@ -4258,6 +4260,8 @@ public void test083_multiuseAnnotations() throws Exception { runner.testFiles = new String[] { "X.java", + "import java.lang.annotation.*;\n" + + "@Target({ElementType.METHOD, ElementType.TYPE_USE})\n" + "@interface Annot {\n" + " int value() default 0;\n" + "}\n" + @@ -4268,7 +4272,6 @@ public void test083_multiuseAnnotations() throws Exception { "}\n", }; runner.expectedCompilerLog = ""; - runner.javacTestOptions = JavacTestOptions.JavacHasABug.JavacBug8231436; runner.runConformTest(); String expectedOutput = @@ -4287,7 +4290,7 @@ public void test083_multiuseAnnotations() throws Exception { " 1 invokespecial java.lang.Object() [14]\n" + " 4 return\n" + " Line numbers:\n" + - " [pc: 0, line: 4]\n" + + " [pc: 0, line: 6]\n" + " Local variable table:\n" + " [pc: 0, pc: 5] local: this index: 0 type: X\n" + " Local variable type table:\n" + @@ -4298,7 +4301,7 @@ public void test083_multiuseAnnotations() throws Exception { " public void foo(java.lang.String[] args);\n" + " 0 return\n" + " Line numbers:\n" + - " [pc: 0, line: 7]\n" + + " [pc: 0, line: 9]\n" + " Local variable table:\n" + " [pc: 0, pc: 1] local: this index: 0 type: X\n" + " [pc: 0, pc: 1] local: args index: 1 type: java.lang.String[]\n" + @@ -6964,4 +6967,155 @@ public void testBug594561_ParameterizedTypeAnnotations() { assertEquals(1, annos.length); assertEquals("java.lang.Deprecated", annos[0].getAnnotationType().debugName()); } + + // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/1096 + // ECJ out of sync with JLS 9.6.4.1 + public void testGH1096() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.lang.annotation.*;\n" + + "@interface MTPA {}\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@interface CTPA {}\n" + + "public class X<@CTPA K, T> {\n" + + " void m(U arg1) {}\n" + + "}\n", + }, + ""); + String expectedOutput = + "RuntimeInvisibleTypeAnnotations: \n" + + " #24 @MTPA(\n" + + " target type = 0x1 METHOD_TYPE_PARAMETER\n" + + " type parameter index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + + expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #29 @CTPA(\n" + + " target type = 0x0 CLASS_TYPE_PARAMETER\n" + + " type parameter index = 0\n" + + " )\n" + + "}"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=568240 + // Method's annotation attribute is compiled as annotation on return type + public void testBug568240() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.lang.annotation.ElementType;\n" + + "import java.lang.annotation.Retention;\n" + + "import java.lang.annotation.RetentionPolicy;\n" + + "import java.lang.annotation.Target;\n" + + "import java.lang.reflect.AnnotatedType;\n" + + "import java.util.Arrays;\n" + + "\n" + + "public class X {\n" + + "\n" + + " public void test() {\n" + + "\n" + + " AnnotatedType annotatedReturnType = Foo.class.getMethods()[0].getAnnotatedReturnType();\n" + + "\n" + + " // @Child is an attribute of the @Ann annotation. Not a TYPE_USE annotation on the return type.\n" + + " if (!Arrays.asList(annotatedReturnType.getAnnotations()).isEmpty()) {\n" + + " throw new Error(\"Broken\");\n" + + " }\n" + + "\n" + + " }\n" + + " \n" + + " public static void main(String[] args) {\n" + + " new X().test();\n" + + " }\n" + + "\n" + + " public static interface Foo {\n" + + "\n" + + " @Ann(value = @Ann.Child(value = \"foo\"))\n" + + " String get();\n" + + "\n" + + " }\n" + + "\n" + + " @Target(ElementType.METHOD)\n" + + " @Retention(RetentionPolicy.RUNTIME)\n" + + " public static @interface Ann {\n" + + "\n" + + " Child value();\n" + + "\n" + + " @Retention(RetentionPolicy.RUNTIME)\n" + + " public static @interface Child {\n" + + " String value();\n" + + " }\n" + + " }\n" + + "}\n", + }, + ""); + } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=566803 + // field.getAnnotatedType().getAnnotations() broken in the latest ECJ version + public void testBug566803() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.lang.annotation.*;\n" + + "import java.lang.reflect.AnnotatedType;\n" + + "import java.lang.reflect.Field;\n" + + "\n" + + "public class X {\n" + + "\n" + + " @TestAnn1(\"1-1\")\n" + + " @TestAnn1(\"1-2\")\n" + + " public static final @TestAnnFirst long aaa = 1;\n" + + "\n" + + " public void broken() {\n" + + " throw new Error(\"Broken\");\n" + + " }\n" + + " \n" + + " public static void main(String[] args) throws NoSuchFieldException, SecurityException {\n" + + " new X().test();\n" + + "}\n" + + " public void test() throws NoSuchFieldException, SecurityException {\n" + + " Field f = X.class.getDeclaredField(\"aaa\");\n" + + " AnnotatedType s = f.getAnnotatedType();\n" + + "\n" + + " if (long.class != s.getType()) {\n" + + " broken();\n" + + " }\n" + + "\n" + + " Annotation[] as = s.getAnnotations();\n" + + " for (int i = 0; i < as.length; i++) {\n" + + " System.out.println(i + \" \" + as[i]);\n" + + " }\n" + + "\n" + + " if (1 != as.length) {\n" + + " broken();\n" + + " }\n" + + " as = s.getAnnotationsByType(TestAnnFirst.class);\n" + + " if (1 != as.length) {\n" + + " broken();\n" + + " }\n" + + " }\n" + + "\n" + + " @Retention(RetentionPolicy.RUNTIME)\n" + + " @java.lang.annotation.Target(ElementType.TYPE_USE)\n" + + " public @interface TestAnnFirst {\n" + + " }\n" + + "\n" + + " @Retention(value = RetentionPolicy.RUNTIME)\n" + + " @Inherited\n" + + " @Repeatable(TestAnn1s.class)\n" + + " public @interface TestAnn1 {\n" + + " String value() default \"1\";\n" + + " }\n" + + "\n" + + " @Retention(value = RetentionPolicy.RUNTIME)\n" + + " @Inherited\n" + + " public @interface TestAnn1s {\n" + + " TestAnn1[] value();\n" + + " }\n" + + "}\n", + }, + "0 @X.TestAnnFirst()"); + } }