diff options
author | Andrew Clement | 2013-08-22 07:36:56 +0000 |
---|---|---|
committer | ssankaran | 2013-08-22 07:36:56 +0000 |
commit | ef77db37669242a4bac152127ea8ae67d10be39c (patch) | |
tree | 06c71d1903c666d355214fc6b5ec0edc18f1a51a | |
parent | 7089fcfd703b096f125599a900905c00e15535fa (diff) | |
download | eclipse.jdt.core-ef77db37669242a4bac152127ea8ae67d10be39c.tar.gz eclipse.jdt.core-ef77db37669242a4bac152127ea8ae67d10be39c.tar.xz eclipse.jdt.core-ef77db37669242a4bac152127ea8ae67d10be39c.zip |
Fixed Bug 415397 - [1.8][compiler] Type Annotations on wildcard type
argument dropped.
Signed-off-by: Andrew Clement <aclement@gopivotal.com>
3 files changed, 253 insertions, 26 deletions
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 a2c0156f2f..5a8630581d 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 @@ -14,6 +14,7 @@ * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 415541 - [1.8][compiler] Type annotations in the body of static initializer get dropped * Bug 415543 - [1.8][compiler] Incorrect bound index in RuntimeInvisibleTypeAnnotations attribute + * Bug 415397 - [1.8][compiler] Type Annotations on wildcard type argument dropped *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -440,55 +441,137 @@ public class JSR308SpecSnippetTests extends AbstractRegressionTest { " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - public void test011() throws Exception { // WILL FAIL WHEN https://bugs.eclipse.org/bugs/show_bug.cgi?id=415397 IS FIXED. + + public void test011() throws Exception { this.runConformTest( new String[] { "X.java", "import java.lang.annotation.*;\n" + - "import java.util.List;\n" + + "import java.util.*;\n" + + "import java.io.*;\n" + "import static java.lang.annotation.ElementType.*; \n" + "@Target(TYPE_USE)\n" + - "@interface Immutable {}\n" + + "@interface Immutable { int value() default 0; }\n" + "class X {\n" + - " List<@Immutable ? extends Comparable<X>> x;\n" + + " List<@Immutable ? extends Comparable<X>> a;\n" + + " List<? extends @Immutable Comparable<X>> b;\n" + + " List<@Immutable(1) ? extends @Immutable(2) Comparable<X>> c;\n" + + " Map<@Immutable(1) ? extends Comparable<X>,@Immutable(2) ? extends @Immutable(3) Serializable> d;\n" + "}\n", }, ""); + // javac b100 + // Field a: + // RuntimeInvisibleTypeAnnotations: + // 0: #9(): FIELD, location=[TYPE_ARGUMENT(0)] + // Field b: + // RuntimeInvisibleTypeAnnotations: + // 0: #9(): FIELD, location=[TYPE_ARGUMENT(0), WILDCARD] + // Field c: + // RuntimeInvisibleTypeAnnotations: + // 0: #9(#12=I#13): FIELD, location=[TYPE_ARGUMENT(0)] + // 1: #9(#12=I#14): FIELD, location=[TYPE_ARGUMENT(0), WILDCARD] + // Field d: + // RuntimeInvisibleTypeAnnotations: + // 0: #9(#12=I#13): FIELD, location=[TYPE_ARGUMENT(0)] + // 1: #9(#12=I#14): FIELD, location=[TYPE_ARGUMENT(1)] + // 2: #9(#12=I#18): FIELD, location=[TYPE_ARGUMENT(1), WILDCARD] String expectedOutput = + "// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + "class X {\n" + " Constant pool:\n" + " constant #1 class: #2 X\n" + " constant #2 utf8: \"X\"\n" + " constant #3 class: #4 java/lang/Object\n" + " constant #4 utf8: \"java/lang/Object\"\n" + - " constant #5 utf8: \"x\"\n" + + " constant #5 utf8: \"a\"\n" + " constant #6 utf8: \"Ljava/util/List;\"\n" + " constant #7 utf8: \"Signature\"\n" + " constant #8 utf8: \"Ljava/util/List<+Ljava/lang/Comparable<LX;>;>;\"\n" + - " constant #9 utf8: \"<init>\"\n" + - " constant #10 utf8: \"()V\"\n" + - " constant #11 utf8: \"Code\"\n" + - " constant #12 method_ref: #3.#13 java/lang/Object.<init> ()V\n" + - " constant #13 name_and_type: #9.#10 <init> ()V\n" + - " constant #14 utf8: \"LineNumberTable\"\n" + - " constant #15 utf8: \"LocalVariableTable\"\n" + - " constant #16 utf8: \"this\"\n" + - " constant #17 utf8: \"LX;\"\n" + - " constant #18 utf8: \"SourceFile\"\n" + - " constant #19 utf8: \"X.java\"\n" + + " constant #9 utf8: \"RuntimeInvisibleTypeAnnotations\"\n" + + " constant #10 utf8: \"LImmutable;\"\n" + + " constant #11 utf8: \"b\"\n" + + " constant #12 utf8: \"c\"\n" + + " constant #13 utf8: \"value\"\n" + + " constant #14 integer: 1\n" + + " constant #15 integer: 2\n" + + " constant #16 utf8: \"d\"\n" + + " constant #17 utf8: \"Ljava/util/Map;\"\n" + + " constant #18 utf8: \"Ljava/util/Map<+Ljava/lang/Comparable<LX;>;+Ljava/io/Serializable;>;\"\n" + + " constant #19 integer: 3\n" + + " constant #20 utf8: \"<init>\"\n" + + " constant #21 utf8: \"()V\"\n" + + " constant #22 utf8: \"Code\"\n" + + " constant #23 method_ref: #3.#24 java/lang/Object.<init> ()V\n" + + " constant #24 name_and_type: #20.#21 <init> ()V\n" + + " constant #25 utf8: \"LineNumberTable\"\n" + + " constant #26 utf8: \"LocalVariableTable\"\n" + + " constant #27 utf8: \"this\"\n" + + " constant #28 utf8: \"LX;\"\n" + + " constant #29 utf8: \"SourceFile\"\n" + + " constant #30 utf8: \"X.java\"\n" + + " \n" + + " // Field descriptor #6 Ljava/util/List;\n" + + " // Signature: Ljava/util/List<+Ljava/lang/Comparable<LX;>;>;\n" + + " java.util.List a;\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #10 @Immutable(\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " \n" + + " // Field descriptor #6 Ljava/util/List;\n" + + " // Signature: Ljava/util/List<+Ljava/lang/Comparable<LX;>;>;\n" + + " java.util.List b;\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #10 @Immutable(\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0), WILDCARD]\n" + + " )\n" + " \n" + " // Field descriptor #6 Ljava/util/List;\n" + " // Signature: Ljava/util/List<+Ljava/lang/Comparable<LX;>;>;\n" + - " java.util.List x;\n" + + " java.util.List c;\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #10 @Immutable(\n" + + " #13 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " #10 @Immutable(\n" + + " #13 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0), WILDCARD]\n" + + " )\n" + + " \n" + + " // Field descriptor #17 Ljava/util/Map;\n" + + " // Signature: Ljava/util/Map<+Ljava/lang/Comparable<LX;>;+Ljava/io/Serializable;>;\n" + + " java.util.Map d;\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #10 @Immutable(\n" + + " #13 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " #10 @Immutable(\n" + + " #13 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1)]\n" + + " )\n" + + " #10 @Immutable(\n" + + " #13 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1), WILDCARD]\n" + + " )\n" + " \n" + - " // Method descriptor #10 ()V\n" + + " // Method descriptor #21 ()V\n" + " // Stack: 1, Locals: 1\n" + " X();\n" + " 0 aload_0 [this]\n" + - " 1 invokespecial java.lang.Object() [12]\n" + + " 1 invokespecial java.lang.Object() [23]\n" + " 4 return\n" + " Line numbers:\n" + - " [pc: 0, line: 6]\n" + + " [pc: 0, line: 7]\n" + " Local variable table:\n" + " [pc: 0, pc: 5] local: this index: 0 type: X\n" + "}"; @@ -1164,7 +1247,7 @@ public class JSR308SpecSnippetTests extends AbstractRegressionTest { " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - public void test028() throws Exception { // // WILL FAIL WHEN https://bugs.eclipse.org/bugs/show_bug.cgi?id=415397 IS FIXED. + public void test028() throws Exception { this.runConformTest( new String[] { "X.java", @@ -1179,15 +1262,89 @@ public class JSR308SpecSnippetTests extends AbstractRegressionTest { "}\n", }, ""); + // javac b100 + // On the type declaration: + // RuntimeInvisibleTypeAnnotations: + // 0: #9(): CLASS_TYPE_PARAMETER, param_index=0 + // On the method: + // RuntimeInvisibleTypeAnnotations: + // 0: #9(): METHOD_TYPE_PARAMETER, param_index=0 + // On the field: + // RuntimeInvisibleTypeAnnotations: + // 0: #9(): FIELD, location=[TYPE_ARGUMENT(0)] String expectedOutput = + "// Compiled from X.java (version 1.8 : 52.0, super bit)\n" + + "// Signature: <T:Ljava/lang/Object;>Ljava/lang/Object;\n" + + "class X {\n" + + " Constant pool:\n" + + " constant #1 class: #2 X\n" + + " constant #2 utf8: \"X\"\n" + + " constant #3 class: #4 java/lang/Object\n" + + " constant #4 utf8: \"java/lang/Object\"\n" + + " constant #5 utf8: \"l\"\n" + + " constant #6 utf8: \"Ljava/util/List;\"\n" + + " constant #7 utf8: \"Signature\"\n" + + " constant #8 utf8: \"Ljava/util/List<*>;\"\n" + + " constant #9 utf8: \"RuntimeInvisibleTypeAnnotations\"\n" + + " constant #10 utf8: \"LNonNull;\"\n" + + " constant #11 utf8: \"<init>\"\n" + + " constant #12 utf8: \"()V\"\n" + + " constant #13 utf8: \"Code\"\n" + + " constant #14 method_ref: #3.#15 java/lang/Object.<init> ()V\n" + + " constant #15 name_and_type: #11.#12 <init> ()V\n" + + " constant #16 utf8: \"LineNumberTable\"\n" + + " constant #17 utf8: \"LocalVariableTable\"\n" + + " constant #18 utf8: \"this\"\n" + + " constant #19 utf8: \"LX;\"\n" + + " constant #20 utf8: \"LocalVariableTypeTable\"\n" + + " constant #21 utf8: \"LX<TT;>;\"\n" + + " constant #22 utf8: \"foo\"\n" + + " constant #23 utf8: \"<K:Ljava/lang/Object;>()V\"\n" + + " constant #24 utf8: \"SourceFile\"\n" + + " constant #25 utf8: \"X.java\"\n" + + " constant #26 utf8: \"<T:Ljava/lang/Object;>Ljava/lang/Object;\"\n" + + " \n" + + " // Field descriptor #6 Ljava/util/List;\n" + + " // Signature: Ljava/util/List<*>;\n" + + " java.util.List l;\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #23 @NonNull(\n" + + " #10 @NonNull(\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " \n" + + " // Method descriptor #12 ()V\n" + + " // Stack: 1, Locals: 1\n" + + " X();\n" + + " 0 aload_0 [this]\n" + + " 1 invokespecial java.lang.Object() [14]\n" + + " 4 return\n" + + " Line numbers:\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" + + " [pc: 0, pc: 5] local: this index: 0 type: X<T>\n" + + " \n" + + " // Method descriptor #12 ()V\n" + + " // Signature: <K:Ljava/lang/Object;>()V\n" + + " // Stack: 0, Locals: 1\n" + + " void foo();\n" + + " 0 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 7]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 1] local: this index: 0 type: X\n" + + " Local variable type table:\n" + + " [pc: 0, pc: 1] local: this index: 0 type: X<T>\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #10 @NonNull(\n" + " target type = 0x1 METHOD_TYPE_PARAMETER\n" + " type parameter index = 0\n" + " )\n" + "\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #23 @NonNull(\n" + + " #10 @NonNull(\n" + " target type = 0x0 CLASS_TYPE_PARAMETER\n" + " type parameter index = 0\n" + " )\n" + @@ -1913,4 +2070,40 @@ public class JSR308SpecSnippetTests extends AbstractRegressionTest { " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } + public void test039() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.lang.annotation.*;\n" + + "import java.util.List;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface Readonly {\n" + + " String value() default \"default\";\n" + + "}\n" + + "public class X { \n" + + " void foo(List<@Readonly ?> l) {\n" + + " }\n" + + "}\n", + }, + ""); + String expectedOutput = + " void foo(java.util.List l);\n" + + " 0 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 10]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 1] local: this index: 0 type: X\n" + + " [pc: 0, pc: 1] local: l index: 1 type: java.util.List\n" + + " Local variable type table:\n" + + " [pc: 0, pc: 1] local: l index: 1 type: java.util.List<?>\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #23 @Readonly(\n" + + " target type = 0x16 METHOD_FORMAL_PARAMETER\n" + + " method parameter index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + "}"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } }
\ No newline at end of file diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java index 9d58a6b188..097d966c74 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java @@ -20,6 +20,7 @@ * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) * Bug 409517 - [1.8][compiler] Type annotation problems on more elaborate array references + * Bug 415397 - [1.8][compiler] Type Annotations on wildcard type argument dropped *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -249,8 +250,9 @@ public abstract class Annotation extends Expression { if (primaryAnnotation != null) { for (int i = 0, max = primaryAnnotation.length; i < max; i++) { - if (primaryAnnotation[i] == this.currentAnnotation) { this.search = false; - for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) { + if (primaryAnnotation[i] == this.currentAnnotation) { + this.search = false; + for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) { this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); } return false; @@ -374,6 +376,24 @@ public abstract class Annotation extends Expression { public boolean visit(Wildcard typeReference, BlockScope scope) { if (!this.search) return false; + + // This block handles List<@Foo ? extends Serializable> + Annotation[][] annotations = typeReference.annotations; + if (annotations == null) { + annotations = new Annotation[][] { primaryAnnotation }; + } + int annotationsLevels = annotations.length; + for (int i = 0; i < annotationsLevels; i++) { + Annotation [] current = annotations[i]; + int annotationsLength = current == null ? 0 : current.length; + for (int j = 0; j < annotationsLength; j++) { + if (current[j] == this.currentAnnotation) { + this.search = false; + return false; + } + } + } + TypeReference bound = typeReference.bound; this.typePathEntries.push(TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND); bound.traverse(this, scope); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java index 1a0f7db242..57ce6874b0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,6 +11,8 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for + * Bug 415397 - [1.8][compiler] Type Annotations on wildcard type argument dropped *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -120,6 +122,12 @@ public class Wildcard extends SingleTypeReference { public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { + if (this.annotations != null) { + Annotation [] typeAnnotations = this.annotations[0]; + for (int i = 0, length = typeAnnotations == null ? 0 : typeAnnotations.length; i < length; i++) { + typeAnnotations[i].traverse(visitor, scope); + } + } if (this.bound != null) { this.bound.traverse(visitor, scope); } @@ -129,6 +137,12 @@ public class Wildcard extends SingleTypeReference { public void traverse(ASTVisitor visitor, ClassScope scope) { if (visitor.visit(this, scope)) { + if (this.annotations != null) { + Annotation [] typeAnnotations = this.annotations[0]; + for (int i = 0, length = typeAnnotations == null ? 0 : typeAnnotations.length; i < length; i++) { + typeAnnotations[i].traverse(visitor, scope); + } + } if (this.bound != null) { this.bound.traverse(visitor, scope); } |