diff options
author | Stephan Herrmann | 2013-12-25 21:23:58 +0000 |
---|---|---|
committer | Stephan Herrmann | 2013-12-25 21:23:58 +0000 |
commit | c8a7ab78ecfe1bc5f533155d1bcd9817c668625b (patch) | |
tree | 883e1d65139bc0458094dd2203295e8efb1a4358 | |
parent | 7d92c905003ad994c9d0795ed2a253d0f9258b7b (diff) | |
download | org.eclipse.objectteams-c8a7ab78ecfe1bc5f533155d1bcd9817c668625b.tar.gz org.eclipse.objectteams-c8a7ab78ecfe1bc5f533155d1bcd9817c668625b.tar.xz org.eclipse.objectteams-c8a7ab78ecfe1bc5f533155d1bcd9817c668625b.zip |
Update jdt.core with 654143a38aec753fd98b7be6f2d8a5edee7245f1 to
55 files changed, 7614 insertions, 3053 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java index c1a881ac8..8be878942 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java @@ -11,6 +11,8 @@ * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.parser; @@ -108,19 +110,19 @@ public class TypeAnnotationSyntaxTest extends AbstractSyntaxTreeTest { } public boolean visit(MarkerAnnotation annotation, BlockScope scope) { if (this.enclosingReference != null) { - storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null)); + storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null, 0)); } return false; } public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) { if (this.enclosingReference != null) { - storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null)); + storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null, 0)); } return false; } public boolean visit(NormalAnnotation annotation, BlockScope scope) { if (this.enclosingReference != null) { - storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null)); + storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null, 0)); } return false; } @@ -133,14 +135,28 @@ public class TypeAnnotationSyntaxTest extends AbstractSyntaxTreeTest { this.locations.put(key, null); return; } - StringBuffer buffer = new StringBuffer("{"); - for (int i = 0, max = tab.length; i < max; i++) { + + StringBuffer buffer = new StringBuffer("["); + for (int i = 0, max = tab.length; i < max; i += 2) { if (i > 0) { - buffer.append(','); + buffer.append(", "); + } + switch (tab[i]) { + case 0: + buffer.append("ARRAY"); + break; + case 1: + buffer.append("INNER_TYPE"); + break; + case 2: + buffer.append("WILDCARD"); + break; + case 3: + buffer.append("TYPE_ARGUMENT(").append(tab[i+1]).append(')'); + break; } - buffer.append(tab[i]); } - buffer.append('}'); + buffer.append(']'); this.locations.put(key, String.valueOf(buffer)); } @@ -1656,9 +1672,9 @@ public void test0068() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 4, locations.size()); assertEquals("Wrong location", null, locations.get("@E")); - assertEquals("Wrong location", "{0}", locations.get("@F")); - assertEquals("Wrong location", "{1}", locations.get("@G")); - assertEquals("Wrong location", "{2}", locations.get("@H")); + assertEquals("Wrong location", "[ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[ARRAY, ARRAY]", locations.get("@G")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY]", locations.get("@H")); } //check locations public void test0069() throws IOException { @@ -1678,8 +1694,8 @@ public void test0069() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 3, locations.size()); assertEquals("Wrong location", null, locations.get("@A")); - assertEquals("Wrong location", "{0}", locations.get("@B")); - assertEquals("Wrong location", "{1}", locations.get("@H")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1)]", locations.get("@H")); } //check locations public void test0070() throws IOException { @@ -1699,11 +1715,11 @@ public void test0070() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 6, locations.size()); assertEquals("Wrong location", null, locations.get("@A")); - assertEquals("Wrong location", "{0}", locations.get("@B")); - assertEquals("Wrong location", "{1}", locations.get("@E")); - assertEquals("Wrong location", "{1,0}", locations.get("@F")); - assertEquals("Wrong location", "{1,1}", locations.get("@G")); - assertEquals("Wrong location", "{1,2}", locations.get("@H")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1)]", locations.get("@E")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), ARRAY, ARRAY]", locations.get("@G")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), ARRAY, ARRAY, ARRAY]", locations.get("@H")); } //check locations public void test0071() throws IOException { @@ -1723,11 +1739,11 @@ public void test0071() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 6, locations.size()); assertEquals("Wrong location", null, locations.get("@A")); - assertEquals("Wrong location", "{0}", locations.get("@B")); - assertEquals("Wrong location", "{1}", locations.get("@C")); - assertEquals("Wrong location", "{1,0,2}", locations.get("@H")); - assertEquals("Wrong location", "{1,0}", locations.get("@E")); - assertEquals("Wrong location", "{1,0,1}", locations.get("@G")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1)]", locations.get("@C")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]", locations.get("@H")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), TYPE_ARGUMENT(0)]", locations.get("@E")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), TYPE_ARGUMENT(0), ARRAY, ARRAY]", locations.get("@G")); } //check locations public void test0072() throws IOException { @@ -1746,14 +1762,14 @@ public void test0072() throws IOException { checkParse(CHECK_ALL & ~CHECK_JAVAC_PARSER, source.toCharArray(), null, "test0072", expectedUnitToString, visitor); Map locations = visitor.getLocations(); assertEquals("Wrong size", 8, locations.size()); - assertEquals("Wrong location", "{0}", locations.get("@I")); - assertEquals("Wrong location", "{1}", locations.get("@J")); - assertEquals("Wrong location", "{2}", locations.get("@A")); - assertEquals("Wrong location", "{2,0}", locations.get("@B")); - assertEquals("Wrong location", "{2,1}", locations.get("@C")); - assertEquals("Wrong location", "{2,1,0,2}", locations.get("@H")); - assertEquals("Wrong location", "{2,1,0}", locations.get("@E")); - assertEquals("Wrong location", "{2,1,0,1}", locations.get("@G")); + assertEquals("Wrong location", "[ARRAY]", locations.get("@I")); + assertEquals("Wrong location", "[ARRAY, ARRAY]", locations.get("@J")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY]", locations.get("@A")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1)]", locations.get("@C")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1), TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]", locations.get("@H")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1), TYPE_ARGUMENT(0)]", locations.get("@E")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1), TYPE_ARGUMENT(0), ARRAY, ARRAY]", locations.get("@G")); } //check locations public void test0073() throws IOException { @@ -1773,13 +1789,13 @@ public void test0073() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 8, locations.size()); assertEquals("Wrong location", null, locations.get("@I")); - assertEquals("Wrong location", "{1}", locations.get("@J")); - assertEquals("Wrong location", "{2}", locations.get("@A")); - assertEquals("Wrong location", "{2,0}", locations.get("@B")); - assertEquals("Wrong location", "{2,1}", locations.get("@C")); - assertEquals("Wrong location", "{2,1,0,2}", locations.get("@H")); - assertEquals("Wrong location", "{2,1,0}", locations.get("@E")); - assertEquals("Wrong location", "{2,1,0,1}", locations.get("@G")); + assertEquals("Wrong location", "[ARRAY, ARRAY]", locations.get("@J")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY]", locations.get("@A")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1)]", locations.get("@C")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1), TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]", locations.get("@H")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1), TYPE_ARGUMENT(0)]", locations.get("@E")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1), TYPE_ARGUMENT(0), ARRAY, ARRAY]", locations.get("@G")); } //check locations public void test0074() throws IOException { @@ -1799,15 +1815,15 @@ public void test0074() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 10, locations.size()); assertEquals("Wrong location", null, locations.get("@I")); - assertEquals("Wrong location", "{0}", locations.get("@F")); - assertEquals("Wrong location", "{1}", locations.get("@J")); - assertEquals("Wrong location", "{2}", locations.get("@A")); - assertEquals("Wrong location", "{2,0}", locations.get("@C")); - assertEquals("Wrong location", "{2,0,0}", locations.get("@E")); - assertEquals("Wrong location", "{2,0,0,1}", locations.get("@G")); - assertEquals("Wrong location", "{2,0,0,2}", locations.get("@H")); - assertEquals("Wrong location", "{2,1,0}", locations.get("@D")); - assertEquals("Wrong location", "{2,1}", locations.get("@B")); + assertEquals("Wrong location", "[ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[ARRAY, ARRAY]", locations.get("@J")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY]", locations.get("@A")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0)]", locations.get("@C")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0), TYPE_ARGUMENT(0)]", locations.get("@E")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY, ARRAY]", locations.get("@G")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]", locations.get("@H")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1), ARRAY]", locations.get("@D")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1)]", locations.get("@B")); } //check locations public void test0075() throws IOException { @@ -1826,16 +1842,16 @@ public void test0075() throws IOException { checkParse(CHECK_ALL & ~CHECK_JAVAC_PARSER, source.toCharArray(), null, "test0075", expectedUnitToString, visitor); Map locations = visitor.getLocations(); assertEquals("Wrong size", 10, locations.size()); - assertEquals("Wrong location", "{0}", locations.get("@I")); - assertEquals("Wrong location", "{1}", locations.get("@F")); - assertEquals("Wrong location", "{2}", locations.get("@J")); - assertEquals("Wrong location", "{3}", locations.get("@A")); - assertEquals("Wrong location", "{3,0}", locations.get("@C")); - assertEquals("Wrong location", "{3,0,0}", locations.get("@E")); - assertEquals("Wrong location", "{3,0,0,1}", locations.get("@G")); - assertEquals("Wrong location", "{3,0,0,2}", locations.get("@H")); - assertEquals("Wrong location", "{3,1}", locations.get("@B")); - assertEquals("Wrong location", "{3,1,0,0}", locations.get("@D")); + assertEquals("Wrong location", "[ARRAY]", locations.get("@I")); + assertEquals("Wrong location", "[ARRAY, ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY]", locations.get("@J")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, ARRAY]", locations.get("@A")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0)]", locations.get("@C")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0), TYPE_ARGUMENT(0)]", locations.get("@E")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY, ARRAY]", locations.get("@G")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]", locations.get("@H")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1)]", locations.get("@B")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY, ARRAY, TYPE_ARGUMENT(1), TYPE_ARGUMENT(0), ARRAY]", locations.get("@D")); } //check locations public void test0076() throws IOException { @@ -1855,9 +1871,9 @@ public void test0076() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 4, locations.size()); assertEquals("Wrong location", null, locations.get("@A")); - assertEquals("Wrong location", "{0}", locations.get("@B")); - assertEquals("Wrong location", "{1}", locations.get("@C")); - assertEquals("Wrong location", "{1,0}", locations.get("@D")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1)]", locations.get("@C")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), TYPE_ARGUMENT(0)]", locations.get("@D")); } //check locations public void test0077() throws IOException { @@ -1877,9 +1893,9 @@ public void test0077() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 4, locations.size()); assertEquals("Wrong location", null, locations.get("@E")); - assertEquals("Wrong location", "{0}", locations.get("@F")); - assertEquals("Wrong location", "{1}", locations.get("@G")); - assertEquals("Wrong location", "{2}", locations.get("@H")); + assertEquals("Wrong location", "[ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[ARRAY, ARRAY]", locations.get("@G")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY]", locations.get("@H")); } //check locations public void test0078() throws IOException { @@ -1899,13 +1915,13 @@ public void test0078() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 8, locations.size()); assertEquals("Wrong location", null, locations.get("@A")); - assertEquals("Wrong location", "{0}", locations.get("@B")); - assertEquals("Wrong location", "{0,0,2}", locations.get("@C")); - assertEquals("Wrong location", "{0,0}", locations.get("@D")); - assertEquals("Wrong location", "{0,0,0}", locations.get("@E")); - assertEquals("Wrong location", "{0,0,1}", locations.get("@F")); - assertEquals("Wrong location", "{1}", locations.get("@G")); - assertEquals("Wrong location", "{1,0}", locations.get("@H")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]", locations.get("@C")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0), TYPE_ARGUMENT(0)]", locations.get("@D")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY]", locations.get("@E")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY, ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1)]", locations.get("@G")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), TYPE_ARGUMENT(0)]", locations.get("@H")); } //check locations public void test0079() throws IOException { @@ -1925,13 +1941,13 @@ public void test0079() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 8, locations.size()); assertEquals("Wrong location", null, locations.get("@A")); - assertEquals("Wrong location", "{0}", locations.get("@B")); - assertEquals("Wrong location", "{0,0,2}", locations.get("@C")); - assertEquals("Wrong location", "{0,0}", locations.get("@D")); - assertEquals("Wrong location", "{0,0,0}", locations.get("@E")); - assertEquals("Wrong location", "{0,0,1}", locations.get("@F")); - assertEquals("Wrong location", "{1}", locations.get("@G")); - assertEquals("Wrong location", "{1,0}", locations.get("@H")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]", locations.get("@C")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0), TYPE_ARGUMENT(0)]", locations.get("@D")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY]", locations.get("@E")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0), TYPE_ARGUMENT(0), ARRAY, ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1)]", locations.get("@G")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), TYPE_ARGUMENT(0)]", locations.get("@H")); } //check locations public void test0080() throws IOException { @@ -1951,7 +1967,7 @@ public void test0080() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 2, locations.size()); assertEquals("Wrong location", null, locations.get("@B")); - assertEquals("Wrong location", "{1}", locations.get("@A")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), WILDCARD]", locations.get("@A")); } //check locations public void test0081() throws IOException { @@ -1971,9 +1987,9 @@ public void test0081() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 4, locations.size()); assertEquals("Wrong location", null, locations.get("@E")); - assertEquals("Wrong location", "{0}", locations.get("@F")); - assertEquals("Wrong location", "{1}", locations.get("@G")); - assertEquals("Wrong location", "{2}", locations.get("@H")); + assertEquals("Wrong location", "[ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[ARRAY, ARRAY]", locations.get("@G")); + assertEquals("Wrong location", "[ARRAY, ARRAY, ARRAY]", locations.get("@H")); } //check locations public void test0082() throws IOException { @@ -1993,11 +2009,11 @@ public void test0082() throws IOException { Map locations = visitor.getLocations(); assertEquals("Wrong size", 6, locations.size()); assertEquals("Wrong location", null, locations.get("@A")); - assertEquals("Wrong location", "{0}", locations.get("@B")); - assertEquals("Wrong location", "{1}", locations.get("@E")); - assertEquals("Wrong location", "{1,0}", locations.get("@F")); - assertEquals("Wrong location", "{1,1}", locations.get("@G")); - assertEquals("Wrong location", "{1,2}", locations.get("@H")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(0)]", locations.get("@B")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1)]", locations.get("@E")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), ARRAY]", locations.get("@F")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), ARRAY, ARRAY]", locations.get("@G")); + assertEquals("Wrong location", "[TYPE_ARGUMENT(1), ARRAY, ARRAY, ARRAY]", locations.get("@H")); } public void test0083() throws IOException { String source = 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 ab9d9612c..2d9ee7fb4 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 @@ -98,27 +98,27 @@ public abstract class AbstractRegressionTest extends AbstractCompilerTest implem if (IS_JRE_8) { // TODO(stephan) accommodate future versions ... COMPARATOR_IMPL_JRE8 = // replace '*' with T, '%' with U, $ with S " public java.util.Comparator<*> reverseOrder() { return null;}\n" + - " public <% extends *> java.util.Comparator<%> thenComparing(java.util.Comparator<? super *> other) { return null;}\n" + - " public <$ extends *, % extends java.lang.Comparable<? super %>> java.util.Comparator<$> thenComparing(java.util.function.Function<? super *, ? extends %> keyExtractor) { return null;}\n" + - " public <$ extends *, %> java.util.Comparator<$> thenComparing(java.util.function.Function<? super *, ? extends %> keyExtractor, java.util.Comparator<? super %> cmp) { return null; }\n" + - " public <% extends *> java.util.Comparator<%> thenComparing(java.util.function.ToIntFunction<? super *> keyExtractor) { return null;}\n" + - " public <% extends *> java.util.Comparator<%> thenComparing(java.util.function.ToLongFunction<? super *> keyExtractor) { return null;}\n" + - " public <% extends *> java.util.Comparator<%> thenComparing(java.util.function.ToDoubleFunction<? super *> keyExtractor) { return null;}\n"; + " public java.util.Comparator<*> thenComparing(java.util.Comparator<? super *> other) { return null;}\n" + + " public <% extends java.lang.Comparable<? super %>> java.util.Comparator<*> thenComparing(java.util.function.Function<? super *, ? extends %> keyExtractor) { return null;}\n" + + " public java.util.Comparator<*> thenComparing(java.util.function.ToIntFunction<? super *> keyExtractor) { return null;}\n" + + " public java.util.Comparator<*> thenComparing(java.util.function.ToLongFunction<? super *> keyExtractor) { return null;}\n" + + " public java.util.Comparator<*> thenComparing(java.util.function.ToDoubleFunction<? super *> keyExtractor) { return null;}\n"; COMPARATOR_RAW_IMPL_JRE8 = - " public java.util.Comparator reverseOrder() { return null;}\n" + - " public java.util.Comparator thenComparing(java.util.Comparator other) { return null;}\n" + - " public java.util.Comparator thenComparing(java.util.function.Function keyExtractor) { return null;}\n" + - " public java.util.Comparator thenComparing(java.util.function.Function keyExtractor, java.util.Comparator comparator) { return null;}\n" + - " public java.util.Comparator thenComparing(java.util.function.ToIntFunction keyExtractor) { return null;}\n" + - " public java.util.Comparator thenComparing(java.util.function.ToLongFunction keyExtractor) { return null;}\n" + - " public java.util.Comparator thenComparing(java.util.function.ToDoubleFunction keyExtractor) { return null;}\n"; + " public java.util.Comparator reverseOrder() { return null;}\n" + + " public java.util.Comparator thenComparing(java.util.Comparator other) { return null;}\n" + + " public java.util.Comparator thenComparing(java.util.function.Function keyExtractor) { return null;}\n" + + " public java.util.Comparator thenComparing(java.util.function.ToIntFunction keyExtractor) { return null;}\n" + + " public java.util.Comparator thenComparing(java.util.function.ToLongFunction keyExtractor) { return null;}\n" + + " public java.util.Comparator thenComparing(java.util.function.ToDoubleFunction keyExtractor) { return null;}\n" ; COLLECTION_IMPL_JRE8 = " public boolean removeAll(java.util.function.Predicate<? super *> filter) { return false;}\n" + + " public boolean removeIf(java.util.function.Predicate<? super *> filter) { return false;}\n" + " public java.util.stream.Stream<*> stream() { return null;}\n" + " public java.util.stream.Stream<*> parallelStream() { return null;}\n" + " public java.util.Spliterator<*> spliterator() { return null; }\n"; COLLECTION_AND_LIST_IMPL_JRE8 = " public boolean removeAll(java.util.function.Predicate<? super *> filter) { return false;}\n" + + " public boolean removeIf(java.util.function.Predicate<? super *> filter) { return false;}\n" + " public java.util.stream.Stream<*> stream() { return null;}\n" + " public java.util.stream.Stream<*> parallelStream() { return null;}\n" + " public java.util.Spliterator<*> spliterator() { return null; }\n" + @@ -127,6 +127,7 @@ public abstract class AbstractRegressionTest extends AbstractCompilerTest implem " public void replaceAll(java.util.function.UnaryOperator<*> operator) {}\n"; COLLECTION_RAW_IMPL_JRE8 = " public @SuppressWarnings(\"rawtypes\") boolean removeAll(java.util.function.Predicate filter) { return false;}\n" + + " public @SuppressWarnings(\"rawtypes\") boolean removeIf(java.util.function.Predicate filter) { return false;}\n" + " public @SuppressWarnings(\"rawtypes\") java.util.stream.Stream stream() { return null;}\n" + " public @SuppressWarnings(\"rawtypes\") java.util.stream.Stream parallelStream() { return null;}\n" + " public @SuppressWarnings(\"rawtypes\") java.util.Spliterator spliterator() { return null; }\n"; @@ -142,6 +143,7 @@ public abstract class AbstractRegressionTest extends AbstractCompilerTest implem " public @SuppressWarnings(\"rawtypes\") java.util.Spliterator spliterator() { return null; }\n"; COLLECTION_AND_LIST_RAW_IMPL_JRE8 = " public @SuppressWarnings(\"rawtypes\") boolean removeAll(java.util.function.Predicate filter) { return false;}\n" + + " public @SuppressWarnings(\"rawtypes\") boolean removeIf(java.util.function.Predicate filter) { return false;}\n" + " public @SuppressWarnings(\"rawtypes\") java.util.stream.Stream stream() { return null;}\n" + " public @SuppressWarnings(\"rawtypes\") java.util.stream.Stream parallelStream() { return null;}\n" + " public @SuppressWarnings(\"rawtypes\") java.util.Spliterator spliterator() { return null; }\n" + @@ -149,17 +151,22 @@ public abstract class AbstractRegressionTest extends AbstractCompilerTest implem " public @SuppressWarnings(\"rawtypes\") void parallelSort(java.util.Comparator comparator) {}\n" + " public @SuppressWarnings(\"rawtypes\") void replaceAll(java.util.function.UnaryOperator operator) {}\n"; ITERABLE_IMPL_JRE8 = // replace '*' with your concrete type argument - " public void forEach(java.util.function.Consumer<? super *> block){}\n"; + " public void forEach(java.util.function.Consumer<? super *> block){}\n" + + " public void forEachRemaining(java.util.function.Consumer<? super *> action) {}\n"; ITERABLE_RAW_IMPL_JRE8 = - " public @SuppressWarnings(\"rawtypes\") void forEach(java.util.function.Consumer action) {}\n"; + " public @SuppressWarnings(\"rawtypes\") void forEach(java.util.function.Consumer action) {}\n" + + " public @SuppressWarnings(\"rawtypes\") void forEachRemaining(java.util.function.Consumer action) {}\n"; ITERATOR_IMPL_JRE8 = // replace '*' with your concrete type argument - "public void forEach(java.util.function.Consumer<? super *> action) {}\n"; + "public void forEach(java.util.function.Consumer<? super *> action) {}\n" + + "public void forEachRemaining(java.util.function.Consumer<? super *> action) {}\n"; ITERATOR_RAW_IMPL_JRE8 = - " public void forEach(java.util.function.Consumer block){}\n"; + " public @SuppressWarnings(\"rawtypes\") void forEach(java.util.function.Consumer block){}\n" + + " public @SuppressWarnings(\"rawtypes\") void forEachRemaining(java.util.function.Consumer action) {}\n"; MAP_IMPL_JRE8 = // '*' for 'K', '%' for 'V' " public boolean remove(Object key, Object value) { return false;}\n" + + " public % getOrDefault(Object key, % defaultValue) {return defaultValue;}\n" + " public void forEach(java.util.function.BiConsumer<? super *, ? super %> block) {}\n" + - " public void replaceAll(java.util.function.BiFunction<*, %, %> function) {}\n" + + " public void replaceAll(java.util.function.BiFunction<? super *, ? super %, ? extends %> function) {}\n" + " public % putIfAbsent(* key, % value) { return null;}\n" + " public boolean replace(* key, % oldValue, % newValue) { return false;}\n" + " public % replace(* key, % value) { return null;}\n" + @@ -169,6 +176,7 @@ public abstract class AbstractRegressionTest extends AbstractCompilerTest implem " public % merge(* key, % value, java.util.function.BiFunction<? super %, ? super %, ? extends %> remappingFunction) { return null;}\n"; MAP_RAW_IMPL_JRE8 = " public boolean remove(Object key, Object value) { return false;}\n" + + " public @SuppressWarnings(\"rawtypes\") Object getOrDefault(Object key, Object defaultValue) {return defaultValue;}\n" + " public @SuppressWarnings(\"rawtypes\") void forEach(java.util.function.BiConsumer block) {}\n" + " public @SuppressWarnings(\"rawtypes\") void replaceAll(java.util.function.BiFunction function) {}\n" + " public Object putIfAbsent(Object key, Object value) { return null;}\n" + 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 c33479251..333757963 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 @@ -24937,7 +24937,7 @@ public void test0779() throws Exception { }, "SUCCESS"); - String constantPoolIdx = IS_JRE_8 ? "70" : "36"; // depends on whether or not stubs for JRE8 default methods are included + String constantPoolIdx = IS_JRE_8 ? "73" : "36"; // depends on whether or not stubs for JRE8 default methods are included String expectedOutput = " // Method descriptor #31 (I)Ljava/lang/Object;\n" + " // Stack: 2, Locals: 2\n" + @@ -25923,27 +25923,27 @@ public void test0809() { "}\n", }, "----------\n" + - "1. WARNING in X.java (at line 22)\n" + + "1. WARNING in X.java (at line 23)\n" + " void f1(Set1 s) {\n" + " ^^^^\n" + "Set1 is a raw type. References to generic type Set1<N> should be parameterized\n" + "----------\n" + - "2. ERROR in X.java (at line 23)\n" + + "2. ERROR in X.java (at line 24)\n" + " Node n_ = s.iterator().next();\n" + " ^^^^^^^^^^^^^^^^^^^\n" + "Type mismatch: cannot convert from Object to Node\n" + "----------\n" + - "3. ERROR in X.java (at line 26)\n" + + "3. ERROR in X.java (at line 27)\n" + " for (Node n : s) {\n" + " ^\n" + "Type mismatch: cannot convert from element type Object to Node\n" + "----------\n" + - "4. WARNING in X.java (at line 36)\n" + + "4. WARNING in X.java (at line 37)\n" + " void f3(Set3 s) {\n" + " ^^^^\n" + "Set3 is a raw type. References to generic type Set3<N> should be parameterized\n" + "----------\n" + - "5. ERROR in X.java (at line 39)\n" + + "5. ERROR in X.java (at line 40)\n" + " for (Node n : s) {\n" + " ^\n" + "Type mismatch: cannot convert from element type Object to Node\n" + @@ -32588,7 +32588,7 @@ public void test0988() { " public ISheetViewer getViewer();\n" + "}", // ================= }, - "----------\n" + + "----------\n" + "1. ERROR in X.java (at line 11)\n" + " public SheetViewer getViewer() { return null; } \n" + " ^^^^^^^^^^^\n" + @@ -48376,12 +48376,6 @@ public void test1403() throws Exception { "2. ERROR in A.java (at line 3)\n" + " Class<?> c = A<?>.class; \n" + " ^^^\n" + - "Syntax error on token(s), misplaced construct(s)\n" + - "----------\n" + - "3. ERROR in A.java (at line 3)\n" + - " Class<?> c = A<?>.class; \n" + - " ^^^^^\n" + - "Syntax error, insert \")\" to complete Expression\n" + :giro */ " ^\n" + "Syntax error on token \"?\", invalid typeAnchor\n" + @@ -49784,7 +49778,7 @@ public void test1444() { " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Unnecessary cast from Iterator to Iterator<String>\n" + "----------\n" + - "6. ERROR in X.java (at line 37)\n" + + "6. ERROR in X.java (at line 38)\n" + " Zork z;\n" + " ^^^^\n" + "Zork cannot be resolved to a type\n" + diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java index d00f07a15..0b00f6203 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java @@ -6534,6 +6534,134 @@ public void test406773() { compilerOptions /* custom options */ ); } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=406859, [1.8][compiler] Bad hint that method could be declared static +public void test406859a() { + Map compilerOptions = getCompilerOptions(); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBeStatic, CompilerOptions.ERROR); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, CompilerOptions.ERROR); + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " int foo(int i);\n" + + "}\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " X x = new X();\n" + + " I i = x::foo;\n" + + " i.foo(3);\n" + + " }\n" + + " int foo(int x) {\n" + + " return x;\n" + + " } \n" + + "}\n" + }, + "", + null /* no extra class libraries */, + true /* flush output directory */, + compilerOptions /* custom options */ + ); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=406859, [1.8][compiler] Bad hint that method could be declared static +public void test406859b() { + Map compilerOptions = getCompilerOptions(); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBeStatic, CompilerOptions.ERROR); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, CompilerOptions.ERROR); + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " void doit (Y y);\n" + + "}\n" + + "\n" + + "class Y {\n" + + " void foo() {\n" + + " return;\n" + + " }\n" + + "}\n" + + "\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " I i = Y::foo; \n" + + " Y y = new Y();\n" + + " i.doit(y);\n" + + " }\n" + + "}\n" + }, + "", + null /* no extra class libraries */, + true /* flush output directory */, + compilerOptions /* custom options */ + ); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=406859, [1.8][compiler] Bad hint that method could be declared static +public void test406859c() { + Map compilerOptions = getCompilerOptions(); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBeStatic, CompilerOptions.ERROR); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, CompilerOptions.ERROR); + this.runNegativeTest( + new String[] { + "X.java", + "interface I {\n" + + " void doit ();\n" + + "}\n" + + "\n" + + "class Y {\n" + + " void foo() { \n" + + " return;\n" + + " }\n" + + "}\n" + + "\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " I i = new Y()::foo;\n" + + " i.doit();\n" + + " }\n" + + "}\n" + }, + "", + null /* no extra class libraries */, + true /* flush output directory */, + compilerOptions /* custom options */ + ); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=406859, [1.8][compiler] Bad hint that method could be declared static +// A case where we can't help but report the wrong hint due to separate compilation. +public void test406859d() { + Map compilerOptions = getCompilerOptions(); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBeStatic, CompilerOptions.ERROR); + compilerOptions.put(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, CompilerOptions.WARNING); + this.runNegativeTest( + new String[] { + "Y.java", + "public class Y {\n" + + " void foo() {\n" + + " return;\n" + + " }\n" + + "}", + "X.java", + "interface I {\n" + + " void doit ();\n" + + "}\n" + + "\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " I i = new Y()::foo;\n" + + " i.doit();\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. WARNING in Y.java (at line 2)\n" + + " void foo() {\n" + + " ^^^^^\n" + + "The method foo() from the type Y can potentially be declared as static\n" + + "----------\n", + null /* no extra class libraries */, + true /* flush output directory */, + compilerOptions /* custom options */ + ); +} public static Class testClass() { return NegativeLambdaExpressionsTest.class; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java index 9e42561fa..d963925b7 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java @@ -42,7 +42,7 @@ protected Map getCompilerOptions() { Map compilerOptions = super.getCompilerOptions(); compilerOptions.put(CompilerOptions.OPTION_ShareCommonFinallyBlocks, CompilerOptions.ENABLED); return compilerOptions; -}; +} public void test001() { this.runConformTest(new String[] { "p/X.java", 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 0443b26f0..ccb9fde6a 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2012 IBM Corporation and others. + * Copyright (c) 2011, 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,12 +11,15 @@ * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; import java.io.File; - +import java.util.Map; import org.eclipse.jdt.core.util.ClassFileBytesDisassembler; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import junit.framework.Test; @@ -34,457 +37,208 @@ public class TypeAnnotationTest extends AbstractRegressionTest { public TypeAnnotationTest(String testName){ super(testName); } -// // superclass -// public void test001() throws Exception { -// this.runConformTest( -// new String[] { -// "Marker.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@interface Marker {}", -// "X.java", -// "public class X extends @Marker Object {}", -// }, -// ""); -// String expectedOutput = -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #17 @Marker(\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = -1\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// // type parameter -// public void test002() throws Exception { -// this.runConformTest( -// new String[] { -// "Marker.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "@Target(TYPE_PARAMETER)\n" + -// "@interface Marker {}", -// "X.java", -// "public class X<@Marker T> {}", -// }, -// ""); -// String expectedOutput = -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #21 @Marker(\n" + -// " target type = 0x22 CLASS_TYPE_PARAMETER\n" + -// " type parameter index = 0\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// // superclass -// public void test003() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String id() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "C.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface C {\n" + -// " char value() default '-';\n" + -// "}\n", -// "Y.java", -// "class Y {}\n", -// "X.java", -// "public class X extends @A(id=\"Hello, World!\") @B @C('(') Y {\n" + -// "}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #19 @A(\n" + -// " #20 id=\"Hello, World!\" (constant type)\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = -1\n" + -// " )\n" + -// " #22 @C(\n" + -// " #23 value=\'(\' (constant type)\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = -1\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #17 @B(\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = -1\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// // super interfaces -// public void test004() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String id() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "C.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface C {\n" + -// " char value() default '-';\n" + -// "}\n", -// "I.java", -// "interface I {}\n", -// "J.java", -// "interface J {}\n", -// "X.java", -// "public class X implements @A(id=\"Hello, World!\") I, @B @C('(') J {}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #23 @A(\n" + -// " #24 id=\"Hello, World!\" (constant type)\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = 0\n" + -// " )\n" + -// " #26 @C(\n" + -// " #27 value=\'(\' (constant type)\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = 1\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #21 @B(\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = 1\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// // class literal -// public void test005() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "C.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface C {\n" + -// " char value() default '-';\n" + -// "}\n", -// "I.java", -// "interface I {}\n", -// "J.java", -// "interface J {}\n", -// "X.java", -// "public class X {\n" + -// " public boolean foo(String s) {\n" + -// " boolean b = (s instanceof @C('_') Object);\n" + -// " Object o = new @B(3) @A(\"new Object\") Object();\n" + -// " Class<?> c = @B(4) Object.class;\n" + -// " Class<?> c2 = @A(\"int class literal\") @B(5) int.class;\n" + -// " System.out.println(o.toString() + c.toString() + c2.toString());\n" + -// " return b;\n" + -// " }\n" + -// "}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #73 @C(\n" + -// " #68 value=\'_\' (constant type)\n" + -// " target type = 0x2 TYPE_INSTANCEOF\n" + -// " offset = 1\n" + -// " )\n" + -// " #75 @A(\n" + -// " #68 value=\"new Object\" (constant type)\n" + -// " target type = 0x4 OBJECT_CREATION\n" + -// " offset = 5\n" + -// " )\n" + -// " #75 @A(\n" + -// " #68 value=\"int class literal\" (constant type)\n" + -// " target type = 0x1e CLASS_LITERAL\n" + -// " offset = 17\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #67 @B(\n" + -// " #68 value=(int) 3 (constant type)\n" + -// " target type = 0x4 OBJECT_CREATION\n" + -// " offset = 5\n" + -// " )\n" + -// " #67 @B(\n" + -// " #68 value=(int) 4 (constant type)\n" + -// " target type = 0x1e CLASS_LITERAL\n" + -// " offset = 13\n" + -// " )\n" + -// " #67 @B(\n" + -// " #68 value=(int) 5 (constant type)\n" + -// " target type = 0x1e CLASS_LITERAL\n" + -// " offset = 17\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// // class literal generic and array -// public void test006() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "C.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface C {\n" + -// " char value() default '-';\n" + -// "}\n", -// "I.java", -// "interface I {}\n", -// "J.java", -// "interface J {}\n", -// "X.java", -// "public class X {\n" + -// " public boolean foo(Object o) {\n" + -// " boolean b = (o instanceof @C('_') Object[]);\n" + -// " Object o1 = new @B(3) @A(\"new Object\") Object[] {};\n" + -// " Class<?> c = @B(4) Object[].class;\n" + -// " Class<?> c2 = @A(\"int class literal\") @B(5) int[].class;\n" + -// " System.out.println(o1.toString() + c.toString() + c2.toString());\n" + -// " return b;\n" + -// " }\n" + -// "}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #70 @C(\n" + -// " #66 value=\'_\' (constant type)\n" + -// " target type = 0x2 TYPE_INSTANCEOF\n" + -// " offset = 1\n" + -// " )\n" + -// " #72 @A(\n" + -// " #66 value=\"int class literal\" (constant type)\n" + -// " target type = 0x1e CLASS_LITERAL\n" + -// " offset = 14\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #65 @B(\n" + -// " #66 value=(int) 4 (constant type)\n" + -// " target type = 0x1e CLASS_LITERAL\n" + -// " offset = 10\n" + -// " )\n" + -// " #65 @B(\n" + -// " #66 value=(int) 5 (constant type)\n" + -// " target type = 0x1e CLASS_LITERAL\n" + -// " offset = 14\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// // parameterized superclass -// public void test007() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "C.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface C {\n" + -// " char value() default '-';\n" + -// "}\n", -// "Y.java", -// "class Y<T> {}\n", -// "X.java", -// "public class X extends @A(\"Hello, World!\") Y<@B @C('(') String> {\n" + -// "}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #21 @A(\n" + -// " #22 value=\"Hello, World!\" (constant type)\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = -1\n" + -// " )\n" + -// " #24 @C(\n" + -// " #22 value=\'(\' (constant type)\n" + -// " target type = 0x15 CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY\n" + -// " type index = -1\n" + -// " locations = {0}\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #19 @B(\n" + -// " target type = 0x15 CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY\n" + -// " type index = -1\n" + -// " locations = {0}\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// public void test008() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "C.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface C {\n" + -// " char value() default '-';\n" + -// "}\n", -// "I.java", -// "interface I<T> {}\n", -// "J.java", -// "interface J<U,T> {}\n", -// "X.java", -// "public class X implements I<@A(\"Hello, World!\") String>, @B J<String, @C('(') Integer> {}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #25 @A(\n" + -// " #26 value=\"Hello, World!\" (constant type)\n" + -// " target type = 0x15 CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY\n" + -// " type index = 0\n" + -// " locations = {0}\n" + -// " )\n" + -// " #28 @C(\n" + -// " #26 value=\'(\' (constant type)\n" + -// " target type = 0x15 CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY\n" + -// " type index = 1\n" + -// " locations = {1}\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #23 @B(\n" + -// " target type = 0x14 CLASS_EXTENDS_IMPLEMENTS\n" + -// " type index = 1\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } - // throws - public void test009() throws Exception { + + // Enables the tests to run individually + protected Map getCompilerOptions() { + Map defaultOptions = super.getCompilerOptions(); + defaultOptions.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8); + defaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8); + defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8); + return defaultOptions; + } + + private static final String HELPER_CLASS = + "import java.lang.annotation.*;\n"+ + "import java.lang.reflect.*;\n"+ + "class Helper {\n"+ + "\n"+ + // Print type annotations on super types + " public static void printTypeAnnotations(Class<?> clazz) {\n"+ + " System.out.println(\"Annotations on superclass of \"+clazz.getName());\n"+ + " AnnotatedType superat = clazz.getAnnotatedSuperclass();\n"+ + " Helper.printAnnos(\" \", superat.getType(),superat.getAnnotations());\n"+ + " AnnotatedType[] superinterfaces = clazz.getAnnotatedInterfaces();\n"+ + " if (superinterfaces.length!=0) {\n"+ + " System.out.println(\"Annotations on superinterfaces of \"+clazz.getName());\n"+ + " for (int j=0;j<superinterfaces.length;j++) {\n"+ + " Helper.printAnnos(\" \", superinterfaces[j].getType(),superinterfaces[j].getAnnotations());\n"+ + " }\n"+ + " }\n"+ + " }\n"+ + // Print type annotations on a type + " public static void printTypeAnnotations2(Class<?> clazz) {\n"+ + " System.out.print(clazz.getName()+\"<\");\n"+ + " TypeVariable<?>[] tvs = clazz.getTypeParameters();\n"+ + " for (int t=0;t<tvs.length;t++) {\n"+ + " TypeVariable<?> tv = tvs[t];\n"+ + " Annotation[] annos = tv.getAnnotations();\n"+ + " for (int a=0;a<annos.length;a++) {\n"+ + " System.out.print(toStringAnno(annos[a])+\" \");\n"+ + " }\n"+ + " System.out.print(tv.getName());\n"+ + " if ((t+1)<tvs.length) System.out.print(\",\");\n"+ + " }\n"+ + " System.out.println(\">\");\n"+ + " }\n"+ + " public static String toStringAnno(Annotation anno) {\n"+ + " String s = anno.toString();\n"+ + " if (s.endsWith(\"()\")) return s.substring(0,s.length()-2); else return s;\n"+ + " }\n"+ + " \n"+ + " public static void printAnnos(String header, Type t, Annotation[] annos) {\n"+ + " if (annos.length==0) { System.out.println(header+t+\":no annotations\"); return;} \n"+ + " System.out.print(header+t+\":\");\n"+ + " for (int i=0;i<annos.length;i++) {\n"+ + " System.out.print(toStringAnno(annos[i])+\" \");\n"+ + " }\n"+ + " System.out.println();\n"+ + " }\n"+ + "}\n"; + + // http://types.cs.washington.edu/jsr308/specification/java-annotation-design.pdf + // type_annotation { + // // New fields in JSR 308: + // u1 target_type; // the type of the targeted program element, see Section 3.2 + // union { + // type_parameter_target; + // supertype_target; + // type_parameter_bound_target; + // empty_target; + // method_formal_parameter_target; + // throws_target; + // localvar_target; + // catch_target; + // offset_target; + // type_argument_target; + // method_reference_target; + // } target_info; // identifies the targeted program element, see Section 3.3 + // type_path target_path; // identifies targeted type in a compound type (array, generic, etc.), see Section 3.4 + // // Original fields from "annotation" structure: + // u2 type_index; + // u2 num_element_value_pairs; + // { + // u2 element_name_index; + // element_value value; + // } element_value_pairs[num_element_value_pairs]; + // } + + public void test001_classTypeParameter() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<@Marker T> {}", + + "Marker.java", + "import java.lang.annotation.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(ElementType.TYPE_PARAMETER)\n" + + "@interface Marker {}", + }, + ""); + // javac-b81: 9[0 1 0 0 0 0 13 0 0] (13=Marker annotation) + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @Marker(\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); + } + + public void test002_classTypeParameter_reflection() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<@Marker T> {\n"+ + " public static void main(String[] argv) { Helper.printTypeAnnotations2(X.class);}\n"+ + "}", + + "Helper.java",HELPER_CLASS, + "Marker.java", + "import java.lang.annotation.*;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(TYPE_PARAMETER)\n" + + "@interface Marker {}", + }, + "X<@Marker T>"); + } + + public void test003_classTypeParameter() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<@A1 T1,@A2 @A3 T2> {}", + + "A1.java", + "import java.lang.annotation.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(ElementType.TYPE_PARAMETER)\n" + + "@interface A1 {}", + + "A2.java", + "import java.lang.annotation.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(ElementType.TYPE_PARAMETER)\n" + + "@interface A2 {}", + + "A3.java", + "import java.lang.annotation.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(ElementType.TYPE_PARAMETER)\n" + + "@interface A3 {}", + + }, + ""); + // javac-b81: 9[0 1 0 0 0 0 13 0 0] (13=Marker) + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A1(\n" + + " target type = 0x0 CLASS_TYPE_PARAMETER\n" + + " type parameter index = 0\n" + + " )\n" + + " #22 @A2(\n" + + " target type = 0x0 CLASS_TYPE_PARAMETER\n" + + " type parameter index = 1\n" + + " )\n" + + " #23 @A3(\n" + + " target type = 0x0 CLASS_TYPE_PARAMETER\n" + + " type parameter index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test004_classTypeParameter_reflection() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<@A1 T1,@A2 @A3 T2> {\n"+ + " public static void main(String[] argv) { Helper.printTypeAnnotations2(X.class); }\n"+ + "}", + + "Helper.java",HELPER_CLASS, + "A1.java", + "import java.lang.annotation.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(ElementType.TYPE_PARAMETER)\n" + + "@interface A1 {}", + "A2.java", + "import java.lang.annotation.*;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(TYPE_PARAMETER)\n" + + "@interface A2 {}", + "A3.java", + "import java.lang.annotation.*;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(TYPE_PARAMETER)\n" + + "@interface A3 {}", + }, + "X<@A1 T1,@A2 @A3 T2>"); + } + + public void test005_classTypeParameter() throws Exception { this.runConformTest( new String[] { "A.java", @@ -492,7 +246,7 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + + "@Target(TYPE_PARAMETER)\n" + "@Retention(RUNTIME)\n" + "@interface A {\n" + " String value() default \"default\";\n" + @@ -502,98 +256,31 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + + "@Target(TYPE_PARAMETER)\n" + "@Retention(CLASS)\n" + "@interface B {\n" + " int value() default -1;\n" + "}", - "C.java", - "import java.lang.annotation.Target;\n" + - "import static java.lang.annotation.ElementType.*;\n" + - "import java.lang.annotation.Retention;\n" + - "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + - "@Retention(RUNTIME)\n" + - "@interface C {\n" + - " char value() default '-';\n" + - "}\n", - "E.java", - "class E extends RuntimeException {\n" + - " private static final long serialVersionUID = 1L;\n" + - "}\n", - "E1.java", - "class E1 extends RuntimeException {\n" + - " private static final long serialVersionUID = 1L;\n" + - "}\n", - "E2.java", - "class E2 extends RuntimeException {\n" + - " private static final long serialVersionUID = 1L;\n" + - "}\n", "X.java", - "public class X {\n" + - " void foo() throws @A(\"Hello, World!\") E, E1, @B @C('(') E2 {}\n" + - "}", + "public class X<@A @B(3) T> {}", }, ""); String expectedOutput = - " RuntimeVisibleTypeAnnotations: \n" + - " #25 @A(\n" + - " #26 value=\"Hello, World!\" (constant type)\n" + - " target type = 0x16 THROWS\n" + - " throws index = 0\n" + - " )\n" + - " #28 @C(\n" + - " #26 value=\'(\' (constant type)\n" + - " target type = 0x16 THROWS\n" + - " throws index = 2\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #23 @B(\n" + - " target type = 0x16 THROWS\n" + - " throws index = 2\n" + - " )\n"; + " RuntimeVisibleTypeAnnotations: \n" + + " #25 @A(\n" + + " target type = 0x0 CLASS_TYPE_PARAMETER\n" + + " type parameter index = 0\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #21 @B(\n" + + " #22 value=(int) 3 (constant type)\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); } -// // method receiver -// public void test010() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "X.java", -// "public class X {\n" + -// " void foo() @B(3) {}\n" + -// "}", -// }, -// ""); -// String expectedOutput = -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #16 @B(\n" + -// " #17 value=(int) 3 (constant type)\n" + -// " target type = 0x6 METHOD_RECEIVER\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } - // method return type - public void test011() throws Exception { + + public void test006_classTypeParameter() throws Exception { this.runConformTest( new String[] { "A.java", @@ -601,7 +288,7 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + + "@Target(TYPE_PARAMETER)\n" + "@Retention(RUNTIME)\n" + "@interface A {\n" + " String value() default \"default\";\n" + @@ -611,34 +298,31 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + + "@Target(TYPE_PARAMETER)\n" + "@Retention(CLASS)\n" + "@interface B {\n" + " int value() default -1;\n" + "}", "X.java", - "public class X {\n" + - " @B(3) @A(value=\"test\") int foo() {\n" + - " return 1;\n" + - " }\n" + - "}", + "public class X<T1,T2,@A @B(3) T3> {}", }, ""); String expectedOutput = - " RuntimeVisibleTypeAnnotations: \n" + - " #21 @A(\n" + - " #18 value=\"test\" (constant type)\n" + - " target type = 0xa METHOD_RETURN_TYPE\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #17 @B(\n" + - " #18 value=(int) 3 (constant type)\n" + - " target type = 0xa METHOD_RETURN_TYPE\n" + - " )\n"; + " RuntimeVisibleTypeAnnotations: \n" + + " #25 @A(\n" + + " target type = 0x0 CLASS_TYPE_PARAMETER\n" + + " type parameter index = 2\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #21 @B(\n" + + " #22 value=(int) 3 (constant type)\n" + + " target type = 0x0 CLASS_TYPE_PARAMETER\n" + + " type parameter index = 2\n" + + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // field type - public void test012() throws Exception { + + public void test007_methodTypeParameter() throws Exception { this.runConformTest( new String[] { "A.java", @@ -646,7 +330,7 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + + "@Target(TYPE_PARAMETER)\n" + "@Retention(RUNTIME)\n" + "@interface A {\n" + " String value() default \"default\";\n" + @@ -656,109 +340,33 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + + "@Target(TYPE_PARAMETER)\n" + "@Retention(CLASS)\n" + "@interface B {\n" + " int value() default -1;\n" + "}", "X.java", "public class X {\n" + - " @B(3) @A int field;\n" + + " <@A @B(3) T> void foo(T t) {}\n" + "}", }, ""); String expectedOutput = " RuntimeVisibleTypeAnnotations: \n" + - " #12 @A(\n" + - " target type = 0xe FIELD\n" + + " #27 @A(\n" + + " target type = 0x1 METHOD_TYPE_PARAMETER\n" + + " type parameter index = 0\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #8 @B(\n" + - " #9 value=(int) 3 (constant type)\n" + - " target type = 0xe FIELD\n" + + " #23 @B(\n" + + " #24 value=(int) 3 (constant type)\n" + + " target type = 0x1 METHOD_TYPE_PARAMETER\n" + + " type parameter index = 0\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } -// // method parameter -// public void test013() throws Exception { -// this.runConformTest( -// new String[] { -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "X.java", -// "public class X {\n" + -// " int foo(@B(3) String s) {\n" + -// " return s.length();\n" + -// " }\n" + -// "}", -// }, -// ""); -// String expectedOutput = -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #25 @B(\n" + -// " #26 value=(int) 3 (constant type)\n" + -// " target type = 0xc METHOD_PARAMETER\n" + -// " method parameter index = 0\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// // method parameter generic or array -// public void test014() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "X.java", -// "public class X {\n" + -// " int foo(String @A [] @B(3) [] s) {\n" + -// " return s.length;\n" + -// " }\n" + -// "}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #23 @A(\n" + -// " target type = 0xc METHOD_PARAMETER\n" + -// " method parameter index = 0\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #19 @B(\n" + -// " #20 value=(int) 3 (constant type)\n" + -// " target type = 0xd METHOD_PARAMETER_GENERIC_OR_ARRAY\n" + -// " method parameter index = 0\n" + -// " locations = {0}\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } - // field type generic or array - public void test015() throws Exception { + + public void test008_methodTypeParameter() throws Exception { this.runConformTest( new String[] { "A.java", @@ -766,7 +374,7 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + + "@Target(TYPE_PARAMETER)\n" + "@Retention(RUNTIME)\n" + "@interface A {\n" + " String value() default \"default\";\n" + @@ -776,75 +384,111 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + + "@Target(TYPE_PARAMETER)\n" + "@Retention(CLASS)\n" + "@interface B {\n" + " int value() default -1;\n" + "}", "X.java", "public class X {\n" + - " @A int [] @B(3) [] field;\n" + + " <T1, @A @B(3) T2> void foo(T1 t1,T2 t2) {}\n" + "}", }, ""); String expectedOutput = " RuntimeVisibleTypeAnnotations: \n" + - " #12 @A(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1}\n" + + " #29 @A(\n" + + " target type = 0x1 METHOD_TYPE_PARAMETER\n" + + " type parameter index = 1\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #8 @B(\n" + - " #9 value=(int) 3 (constant type)\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {0}\n" + + " #25 @B(\n" + + " #26 value=(int) 3 (constant type)\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); } -// // class type parameter -// public void test016() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_PARAMETER)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_PARAMETER)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "X.java", -// "public class X<@A @B(3) T> {}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #25 @A(\n" + -// " target type = 0x22 CLASS_TYPE_PARAMETER\n" + -// " type parameter index = 0\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #21 @B(\n" + -// " #22 value=(int) 3 (constant type)\n" + -// " target type = 0x22 CLASS_TYPE_PARAMETER\n" + -// " type parameter index = 0\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } - // method type parameter - public void test017() throws Exception { + + public void test009_classExtends() throws Exception { + this.runConformTest( + new String[] { + "Marker.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Target(TYPE_USE)\n" + + "@interface Marker {}", + "X.java", + "public class X extends @Marker Object {}", + }, + ""); + // javac-b81 annotation contents: len:10[0 1 16 -1 -1 0 0 17 0 0] + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #17 @Marker(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = -1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test010_classExtends() throws Exception { + this.runConformTest( + new String[] { + "Marker.java", + "import java.lang.annotation.*;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@Target(TYPE_USE)\n" + + "@interface Marker {}", + "X.java", + "public class X extends @Marker Object {}", + }, + ""); + // Bytes:10[0 1 16 -1 -1 0 0 17 0 0] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #17 @Marker(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = -1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test011_classExtends_reflection() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X extends @Marker Object {public static void main(String[] argv) {Helper.printTypeAnnotations(X.class);}}", + "Helper.java",HELPER_CLASS, + "Marker.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Target(TYPE_USE)\n" + + "@interface Marker {}" + }, + "Annotations on superclass of X\n"+ + " class java.lang.Object:no annotations"); + } + + public void test012_classExtends_reflection() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X extends @Marker Object {public static void main(String[] argv) {Helper.printTypeAnnotations(X.class);}}", + "Helper.java",HELPER_CLASS, + "Marker.java", + "import java.lang.annotation.*;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n"+ + "@interface Marker {}" + }, + "Annotations on superclass of X\n"+ + " class java.lang.Object:@Marker"); + } + + public void test013_classExtends_interfaces() throws Exception { this.runConformTest( new String[] { "A.java", @@ -852,152 +496,70 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_PARAMETER)\n" + + "@Target(TYPE_USE)\n" + "@Retention(RUNTIME)\n" + "@interface A {\n" + - " String value() default \"default\";\n" + + " String id() default \"default\";\n" + "}\n", "B.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_PARAMETER)\n" + + "@Target(TYPE_USE)\n" + "@Retention(CLASS)\n" + "@interface B {\n" + " int value() default -1;\n" + "}", + "C.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", "X.java", - "public class X {\n" + - " <@A @B(3) T> void foo(T t) {}\n" + - "}", + "public class X implements @A(id=\"Hello, World!\") I, @B @C('(') J {}", }, ""); + // Output from javac b81 lambda + // RuntimeVisibleTypeAnnotations + // Bytes:28[0 2 16 0 0 0 0 13 0 1 0 14 115 0 15 16 0 1 0 0 16 0 1 0 17 67 0 18] + // RuntimeInvisibleTypeAnnotations + // Bytes:10[0 1 16 0 1 0 0 20 0 0] String expectedOutput = - " RuntimeVisibleTypeAnnotations: \n" + - " #27 @A(\n" + - " target type = 0x20 METHOD_TYPE_PARAMETER\n" + - " type parameter index = 0\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #23 @B(\n" + - " #24 value=(int) 3 (constant type)\n" + - " target type = 0x20 METHOD_TYPE_PARAMETER\n" + - " type parameter index = 0\n" + - " )\n"; + " RuntimeVisibleTypeAnnotations: \n" + + " #23 @A(\n" + + " #24 id=\"Hello, World!\" (constant type)\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " )\n" + + " #26 @C(\n" + + " #27 value=\'(\' (constant type)\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 1\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #21 @B(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 1\n" + + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } -// // class type parameter bound -// public void test018() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "X.java", -// "public class X<T extends @A String & @B(3) Cloneable> {}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #25 @A(\n" + -// " target type = 0x10 CLASS_TYPE_PARAMETER_BOUND\n" + -// " type parameter index = 0 type parameter bound index = 0\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #21 @B(\n" + -// " #22 value=(int) 3 (constant type)\n" + -// " target type = 0x10 CLASS_TYPE_PARAMETER_BOUND\n" + -// " type parameter index = 0 type parameter bound index = 1\n" + -// " )\n" ; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } -// // class type parameter bound generic or array -// public void test019() throws Exception { -// this.runConformTest( -// new String[] { -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// "B.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(CLASS)\n" + -// "@interface B {\n" + -// " int value() default -1;\n" + -// "}", -// "C.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface C {\n" + -// " char value() default '-';\n" + -// "}\n", -// "Y.java", -// "public class Y<T> {}", -// "X.java", -// "public class X<U, T extends Y<@A String @C[][]@B[]> & @B(3) Cloneable> {}", -// }, -// ""); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #25 @A(\n" + -// " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + -// " type parameter index = 1 type parameter bound index = 0\n" + -// " locations = {0,2}\n" + -// " )\n" + -// " #26 @C(\n" + -// " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + -// " type parameter index = 1 type parameter bound index = 0\n" + -// " locations = {0}\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #21 @B(\n" + -// " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + -// " type parameter index = 1 type parameter bound index = 0\n" + -// " locations = {0,1}\n" + -// " )\n" + -// " #21 @B(\n" + -// " #22 value=(int) 3 (constant type)\n" + -// " target type = 0x10 CLASS_TYPE_PARAMETER_BOUND\n" + -// " type parameter index = 1 type parameter bound index = 1\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } - // method type parameter bound - public void test020() throws Exception { + + public void test014_classExtends_interfaces_reflection() throws Exception { this.runConformTest( new String[] { + "X.java", + "public class X implements @A I {public static void main(String[]argv) {Helper.printTypeAnnotations(X.class);}}", + "Helper.java",HELPER_CLASS, "A.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + @@ -1006,7 +568,31 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@Target(TYPE_USE)\n" + "@Retention(RUNTIME)\n" + "@interface A {\n" + - " String value() default \"default\";\n" + + "}\n", + "I.java", + "interface I {}\n" + }, + "Annotations on superclass of X\n" + + " class java.lang.Object:no annotations\n" + + "Annotations on superinterfaces of X\n" + + " interface I:@A"); + } + + public void test015_classExtends_interfaces_reflection() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X implements @A(id=\"Hello, World!\") I, @B @C('i') J {public static void main(String[] argv) { Helper.printTypeAnnotations(X.class);}}", + "Helper.java",HELPER_CLASS, + "A.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RUNTIME)\n" + + "@interface A {\n" + + " String id() default \"default\";\n" + "}\n", "B.java", "import java.lang.annotation.Target;\n" + @@ -1018,30 +604,252 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface B {\n" + " int value() default -1;\n" + "}", - "Z.java", - "public class Z {}", + "C.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", + }, + "Annotations on superclass of X\n" + + " class java.lang.Object:no annotations\n" + + "Annotations on superinterfaces of X\n" + + " interface I:@A(id=Hello, World!) \n" + + " interface J:@C(value=i)"); + } + + public void test016_classExtends() throws Exception { + this.runConformTest( + new String[] { + "B.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RUNTIME)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "Y.java", + "class Y<T> {}\n", "X.java", - "public class X {\n" + - " <T extends @A Z & @B(3) Cloneable> void foo(T t) {}\n" + + "public class X extends Y<@B String> {\n" + "}", }, ""); + // javac-b81: Bytes:12[0 1 16 -1 -1 1 3 0 0 13 0 0] // type path: 1,3,0 String expectedOutput = - " RuntimeVisibleTypeAnnotations: \n" + - " #27 @A(\n" + - " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + - " type parameter index = 0 type parameter bound index = 0\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #23 @B(\n" + - " #24 value=(int) 3 (constant type)\n" + - " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + - " type parameter index = 0 type parameter bound index = 1\n" + - " )\n"; + " RuntimeVisibleTypeAnnotations: \n" + + " #19 @B(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = -1\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test017_classExtends() throws Exception { + this.runConformTest( + new String[] { + "Marker.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface Marker { }\n", + "I.java", + "interface I<T> {}\n", + "X.java", + "public class X implements I<@Marker String> {\n" + + "}", + }, + ""); + // javac-b81: Bytes:12[0 1 16 0 0 1 3 0 0 14 0 0] // type path: 1,3,0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @Marker(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // class type parameter bound generic or array - public void test021() throws Exception { + + public void test018_classExtends() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A { }\n", + + "I.java", + "interface I<T1,T2> {}\n", + + "X.java", + "public class X implements I<Integer, @A String> {}\n" + }, + ""); + // javac-b81: Bytes:12[0 1 16 0 0 1 3 1 0 14 0 0] // type path: 1,3,1 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " location = [TYPE_ARGUMENT(1)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test019_classExtends() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A { }\n", + + "J.java", + "interface J<T> {}\n", + + "I.java", + "interface I<T> {}\n", + + "X.java", + "public class X implements I<J<@A String>> {}\n" + }, + ""); + // javac-b81: Bytes:14[0 1 16 0 0 2 3 0 3 0 0 14 0 0] // type path: 2,3,0,3,0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " location = [TYPE_ARGUMENT(0), TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test020_classExtends() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A { }\n", + + "I.java", + "interface I<T> {}\n", + + "X.java", + "public class X implements I<@A String[]> {}\n" + }, + ""); + // javac-b81: Bytes:14[0 1 16 0 0 2 3 0 0 0 0 14 0 0] // type path: 2,3,0,0,0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " location = [TYPE_ARGUMENT(0), ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test021_classExtends() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A { }\n", + + "I.java", + "interface I<T> {}\n", + + "X.java", + "public class X implements I<String @A[]> {}\n" + }, + ""); + // javac-b81: Bytes:12[0 1 16 0 0 1 3 0 0 14 0 0] // type path: 1,3,0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test022_classExtends() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A { }\n", + + "I.java", + "interface I<T> {}\n", + + "X.java", + "public class X implements I<String []@A[]> {}\n" + }, + ""); + // javac-b81: Bytes:14[0 1 16 0 0 2 3 0 0 0 0 14 0 0] // type path: 2,3,0,0,0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " location = [TYPE_ARGUMENT(0), ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test023_classExtends() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A { }\n", + + "I.java", + "interface I<T> {}\n", + + "X.java", + "public class X implements I<@A String [][][]> {}\n" + }, + ""); + // javac-b81: Bytes:10[0 1 16 0 0 0 0 12 0 0] // type path: 4,3,0,0,0,0,0,0,0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " location = [TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + + public void test024_classExtends() throws Exception { this.runConformTest( new String[] { "A.java", @@ -1074,43 +882,60 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface C {\n" + " char value() default '-';\n" + "}\n", - "Z.java", - "public class Z {}", - "Y.java", - "public class Y<T> {}", + "I.java", + "interface I<T> {}\n", + "J.java", + "interface J<U,T> {}\n", "X.java", - "public class X {\n" + - " <T extends Y<@A Z @C[][]@B[]> & @B(3) Cloneable> void foo(T t) {}\n" + - "}", + "public class X implements I<@A(\"Hello, World!\") String>, @B J<String, @C('(') Integer> {}", }, ""); String expectedOutput = - " RuntimeVisibleTypeAnnotations: \n" + - " #27 @A(\n" + - " target type = 0x13 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + - " type parameter index = 0 type parameter bound index = 0\n" + - " locations = {0,2}\n" + - " )\n" + - " #28 @C(\n" + - " target type = 0x13 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + - " type parameter index = 0 type parameter bound index = 0\n" + - " locations = {0}\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #23 @B(\n" + - " target type = 0x13 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + - " type parameter index = 0 type parameter bound index = 0\n" + - " locations = {0,1}\n" + - " )\n" + - " #23 @B(\n" + - " #24 value=(int) 3 (constant type)\n" + - " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + - " type parameter index = 0 type parameter bound index = 1\n" + - " )\n"; + " RuntimeVisibleTypeAnnotations: \n" + + " #25 @A(\n" + + " #26 value=\"Hello, World!\" (constant type)\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " #28 @C(\n" + + " #26 value=\'(\' (constant type)\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 1\n" + + " location = [TYPE_ARGUMENT(1)]\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #23 @B(\n" + + " target type = 0x10 CLASS_EXTENDS\n" + + " type index = 1\n" + + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // local variable + generic or array - public void test022() throws Exception { + + public void test025_classTypeParameterBound() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<T extends @A String> {}", + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {}\n" + }, + ""); + // javac-b81: Bytes:10[0 1 17 0 0 0 0 13 0 0] + // [17 0 0] is CLASS_PARAMETER_BOUND type_parameter_index=0 bound_index=0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A(\n" + + " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test026_classTypeParameterBound() throws Exception { this.runConformTest( new String[] { "A.java", @@ -1133,62 +958,113 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface B {\n" + " int value() default -1;\n" + "}", + "X.java", + "public class X<T extends @A String & @B(3) Cloneable> {}", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #25 @A(\n" + + " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 0\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #21 @B(\n" + + " #22 value=(int) 3 (constant type)\n" + + " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 1\n" + + " )\n" ; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test027_classTypeParameterBound_complex() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", "C.java", - "import java.lang.annotation.Target;\n" + - "import static java.lang.annotation.ElementType.*;\n" + - "import java.lang.annotation.Retention;\n" + - "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + - "@Retention(RUNTIME)\n" + + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + "@interface C {\n" + " char value() default '-';\n" + "}\n", + "Y.java", + "public class Y<T> {}", + "X.java", + "public class X<U, T extends Y<@A String @C[][]@B[]> & @B(3) Cloneable> {}", + }, + ""); + // javac-b81: + // Bytes:28[0 2 17 1 0 1 3 0 0 13 0 0 17 1 0 4 3 0 0 0 0 0 0 0 0 14 0 0] + // Bytes:29[0 2 17 1 0 3 3 0 0 0 0 0 0 16 0 0 17 1 1 0 0 16 0 1 0 17 73 0 18] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #25 @A(\n" + + " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 1 type parameter bound index = 0\n" + + " location = [TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]\n" + + " )\n" + + " #26 @C(\n" + + " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 1 type parameter bound index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #21 @B(\n" + + " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 1 type parameter bound index = 0\n" + + " location = [TYPE_ARGUMENT(0), ARRAY, ARRAY]\n" + + " )\n" + + " #21 @B(\n" + + " #22 value=(int) 3 (constant type)\n" + + " target type = 0x11 CLASS_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 1 type parameter bound index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test028_methodTypeParameterBound() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "Z.java", + "public class Z {}", "X.java", - "public class X {\n" + - " String[][] bar() {\n" + - " return new String[][] {};" + - " }\n" + - " void foo(String s) {\n" + - " @C int i;\n" + - " @A String [] @B(3)[] tab = bar();\n" + - " if (tab != null) {\n" + - " i = 0;\n" + - " System.out.println(i + tab.length);\n" + - " } else {\n" + - " System.out.println(tab.length);\n" + - " }\n" + - " i = 4;\n" + - " System.out.println(-i + tab.length);\n" + - " }\n" + + "public class X {\n" + + " <T extends @A Z> void foo(T t) {}\n" + "}", }, ""); + // javac-b81: Bytes:10[0 1 18 0 0 0 0 13 0 0] String expectedOutput = " RuntimeVisibleTypeAnnotations: \n" + - " #49 @C(\n" + - " target type = 0x8 LOCAL_VARIABLE\n" + - " local variable entries:\n" + - " [pc: 11, pc: 24] index: 2\n" + - " [pc: 34, pc: 46] index: 2\n" + - " )\n" + - " #50 @A(\n" + - " target type = 0x9 LOCAL_VARIABLE_GENERIC_OR_ARRAY\n" + - " local variable entries:\n" + - " [pc: 5, pc: 46] index: 3\n" + - " locations = {1}\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #45 @B(\n" + - " #46 value=(int) 3 (constant type)\n" + - " target type = 0x9 LOCAL_VARIABLE_GENERIC_OR_ARRAY\n" + - " local variable entries:\n" + - " [pc: 5, pc: 46] index: 3\n" + - " locations = {0}\n" + + " #23 @A(\n" + + " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 0\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // type argument constructor call - public void test023() throws Exception { + + public void test029_methodTypeParameterBound() throws Exception { this.runConformTest( new String[] { "A.java", @@ -1211,35 +1087,186 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface B {\n" + " int value() default -1;\n" + "}", + "Z.java", + "public class Z {}", "X.java", - "public class X {\n" + - " <T> X(T t) {\n" + - " }\n" + - " public Object foo() {\n" + - " X x = new <@A @B(1) String>X(null);\n" + - " return x;\n" + - " }\n" + + "public class X {\n" + + " <T extends @A Z & @B(3) Cloneable> void foo(T t) {}\n" + "}", }, ""); String expectedOutput = " RuntimeVisibleTypeAnnotations: \n" + - " #31 @A(\n" + - " target type = 0x18 TYPE_ARGUMENT_CONSTRUCTOR_CALL\n" + - " offset = 5\n" + - " type argument index = 0\n" + + " #27 @A(\n" + + " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 0\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #27 @B(\n" + - " #28 value=(int) 1 (constant type)\n" + - " target type = 0x18 TYPE_ARGUMENT_CONSTRUCTOR_CALL\n" + - " offset = 5\n" + - " type argument index = 0\n" + + " #23 @B(\n" + + " #24 value=(int) 3 (constant type)\n" + + " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 1\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // type argument constructor call generic or array - public void test024() throws Exception { + + public void test030_methodTypeParameterBound() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "Z.java", + "public class Z {}", + "Y.java", + "public class Y<T> {}", + "X.java", + "public class X {\n" + + " <T extends Y<Z [][]@B[]> & Cloneable> void foo(T t) {}\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #23 @B(\n" + + " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 0\n" + + " location = [TYPE_ARGUMENT(0), ARRAY, ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test031_methodTypeParameterBound_complex() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "Z.java", + "public class Z {}", + "Y.java", + "public class Y<T> {}", + "X.java", + "public class X {\n" + + " <T extends Y<@A Z @C[][]@B[]> & @B(3) Cloneable> void foo(T t) {}\n" + + "}", + }, + ""); + // javac-b81: + // Bytes:28[0 2 18 0 0 1 3 0 0 13 0 0 18 0 0 4 3 0 0 0 0 0 0 0 0 14 0 0] + // Bytes:29[0 2 18 0 0 3 3 0 0 0 0 0 0 16 0 0 18 0 1 0 0 16 0 1 0 17 73 0 18] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #27 @A(\n" + + " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 0\n" + + " location = [TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]\n" + + " )\n" + + " #28 @C(\n" + + " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #23 @B(\n" + + " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 0\n" + + " location = [TYPE_ARGUMENT(0), ARRAY, ARRAY]\n" + + " )\n" + + " #23 @B(\n" + + " #24 value=(int) 3 (constant type)\n" + + " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + + " type parameter index = 0 type parameter bound index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test032_field() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {}\n", + + "X.java", + "public class X {\n" + + " @A int field;\n" + + "}", + }, + ""); + // javac-b81: Bytes:8[0 1 19 0 0 7 0 0] 19 = 0x13 (FIELD) + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @A(\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test033_field() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {}\n", + + "X.java", + "public class X {\n" + + " java.util.List<@A String> field;\n" + + "}", + }, + ""); + // javac-b81: Bytes:10[0 1 19 1 3 0 0 9 0 0] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @A(\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test034_field() throws Exception { this.runConformTest( new String[] { "A.java", @@ -1262,69 +1289,127 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface B {\n" + " int value() default -1;\n" + "}", - "C.java", - "import java.lang.annotation.Target;\n" + - "import static java.lang.annotation.ElementType.*;\n" + - "import java.lang.annotation.Retention;\n" + - "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + - "@Retention(RUNTIME)\n" + - "@interface C {\n" + - " char value() default '-';\n" + - "}\n", "X.java", "public class X {\n" + - " <T, U> X(T t, U u) {\n" + - " }\n" + - " public Object foo() {\n" + - " X x = new <@A Integer, @A String @C [] @B(1)[]>X(null, null);\n" + - " return x;\n" + - " }\n" + + " @B(3) @A int field;\n" + "}", }, ""); String expectedOutput = " RuntimeVisibleTypeAnnotations: \n" + - " #33 @A(\n" + - " target type = 0x18 TYPE_ARGUMENT_CONSTRUCTOR_CALL\n" + - " offset = 6\n" + - " type argument index = 0\n" + - " )\n" + - " #33 @A(\n" + - " target type = 0x19 TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY\n" + - " offset = 6\n" + - " type argument index = 1\n" + - " locations = {1}\n" + - " )\n" + - " #34 @C(\n" + - " target type = 0x18 TYPE_ARGUMENT_CONSTRUCTOR_CALL\n" + - " offset = 6\n" + - " type argument index = 1\n" + + " #12 @A(\n" + + " target type = 0x13 FIELD\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #29 @B(\n" + - " #30 value=(int) 1 (constant type)\n" + - " target type = 0x19 TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY\n" + - " offset = 6\n" + - " type argument index = 1\n" + - " locations = {0}\n" + + " #8 @B(\n" + + " #9 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // type argument method call - public void test025() throws Exception { + + public void test035_field() throws Exception { this.runConformTest( new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {}\n", + "X.java", - "public class X {\n" + - "\n" + - " static <T, U> T foo(T t, U u) {\n" + - " return t;\n" + - " }\n" + - " public static void main(String[] args) {\n" + - " System.out.println(X.<@A @B(1) String[], @C('-') X>foo(new String[]{\"SUCCESS\"}, null)[0]);\n" + - " }\n" + + "public class X {\n" + + " java.util.Map<String, @A String> field;\n" + + "}", + }, + ""); + // javac-b81: Bytes:10[0 1 19 1 3 1 0 9 0 0] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @A(\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test036_field() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {}\n", + + "X.java", + "public class X {\n" + + " java.util.List<String[][]@A[][]> field;\n" + + "}", + }, + ""); + // javac-b81: Bytes:14[0 1 19 3 3 0 0 0 0 0 0 9 0 0] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @A(\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0), ARRAY, ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test037_field() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " java.util.List<? extends @A Number> field;\n" + + "}", + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {}\n", + }, + ""); + // javac-b81: Bytes:12[0 1 19 2 3 0 2 0 0 9 0 0] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @A(\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0), WILDCARD]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test038_field() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class AA { class BB<T> {}}" + + "class X {\n" + + " AA.@A BB field;\n" + "}\n", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A { }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @A(\n" + + " target type = 0x13 FIELD\n" + + " location = [INNER_TYPE]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test039_field() throws Exception { + this.runConformTest( + new String[] { "A.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + @@ -1345,42 +1430,28 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface B {\n" + " int value() default -1;\n" + "}", - "C.java", - "import java.lang.annotation.Target;\n" + - "import static java.lang.annotation.ElementType.*;\n" + - "import java.lang.annotation.Retention;\n" + - "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + - "@Retention(RUNTIME)\n" + - "@interface C {\n" + - " char value() default '-';\n" + - "}\n", + "X.java", + "public class X {\n" + + " @A int [] @B(3) [] field;\n" + + "}", }, - "SUCCESS"); + ""); String expectedOutput = " RuntimeVisibleTypeAnnotations: \n" + - " #52 @A(\n" + - " target type = 0x1a TYPE_ARGUMENT_METHOD_CALL\n" + - " offset = 13\n" + - " type argument index = 0\n" + - " )\n" + - " #53 @C(\n" + - " #49 value=\'-\' (constant type)\n" + - " target type = 0x1a TYPE_ARGUMENT_METHOD_CALL\n" + - " offset = 13\n" + - " type argument index = 1\n" + + " #12 @A(\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY]\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #48 @B(\n" + - " #49 value=(int) 1 (constant type)\n" + - " target type = 0x1a TYPE_ARGUMENT_METHOD_CALL\n" + - " offset = 13\n" + - " type argument index = 0\n" + + " #8 @B(\n" + + " #9 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // check locations - public void test026() throws Exception { + + public void test040_field_complex() throws Exception { this.runConformTest( new String[] { "X.java", @@ -1478,20 +1549,20 @@ public class TypeAnnotationTest extends AbstractRegressionTest { " java.lang.String[][][] field;\n" + " RuntimeVisibleTypeAnnotations: \n" + " #11 @H(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {2}\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, ARRAY]\n" + " )\n" + " #12 @F(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {0}\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + " #8 @E(\n" + - " target type = 0xe FIELD\n" + + " target type = 0x13 FIELD\n" + " )\n" + " #9 @G(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1}\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY]\n" + " )\n" + " \n" + " // Field descriptor #14 Ljava/util/Map;\n" + @@ -1499,20 +1570,20 @@ public class TypeAnnotationTest extends AbstractRegressionTest { " java.util.Map field2;\n" + " RuntimeVisibleTypeAnnotations: \n" + " #18 @A(\n" + - " target type = 0xe FIELD\n" + + " target type = 0x13 FIELD\n" + " )\n" + " #19 @C(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1}\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1)]\n" + " )\n" + " #20 @D(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1,0}\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1), TYPE_ARGUMENT(0)]\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + " #17 @B(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {0}\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0)]\n" + " )\n" + " \n" + " // Field descriptor #14 Ljava/util/Map;\n" + @@ -1520,38 +1591,38 @@ public class TypeAnnotationTest extends AbstractRegressionTest { " java.util.Map field3;\n" + " RuntimeVisibleTypeAnnotations: \n" + " #18 @A(\n" + - " target type = 0xe FIELD\n" + + " target type = 0x13 FIELD\n" + " )\n" + " #11 @H(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1,2}\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1), ARRAY, ARRAY, ARRAY]\n" + " )\n" + " #12 @F(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1,0}\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1), ARRAY]\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + " #17 @B(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {0}\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0)]\n" + " )\n" + " #8 @E(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1}\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1)]\n" + " )\n" + " #9 @G(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1,1}\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1), ARRAY, ARRAY]\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // check locations - public void test027() throws Exception { + + public void test041_field() throws Exception { this.runConformTest( new String[] { "X.java", "public class X {\n" + - " @H java.lang.String @E[] @F[] @G[] field;\n" + + " java.lang.@H String @E[] @F[] @G[] field;\n" + "}", "E.java", "import java.lang.annotation.Target;\n" + @@ -1598,25 +1669,67 @@ public class TypeAnnotationTest extends AbstractRegressionTest { String expectedOutput = " RuntimeVisibleTypeAnnotations: \n" + " #11 @H(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {2}\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, ARRAY]\n" + " )\n" + " #12 @F(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {0}\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + " #8 @E(\n" + - " target type = 0xe FIELD\n" + + " target type = 0x13 FIELD\n" + " )\n" + " #9 @G(\n" + - " target type = 0xf FIELD_GENERIC_OR_ARRAY\n" + - " locations = {1}\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY]\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // cast - public void test028() throws Exception { + + public void test042_methodReturnType() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "X.java", + "public class X {\n" + + " @B(3) @A(value=\"test\") int foo() {\n" + + " return 1;\n" + + " }\n" + + "}", + }, + ""); + // javac-b81: + // Bytes:13[0 1 20 0 0 11 0 1 0 12 115 0 13] + // Bytes:13[0 1 20 0 0 15 0 1 0 12 73 0 16] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #21 @A(\n" + + " #18 value=\"test\" (constant type)\n" + + " target type = 0x14 METHOD_RETURN\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #17 @B(\n" + + " #18 value=(int) 3 (constant type)\n" + + " target type = 0x14 METHOD_RETURN\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test043_methodReceiver() throws Exception { this.runConformTest( new String[] { "A.java", @@ -1639,56 +1752,130 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface B {\n" + " int value() default -1;\n" + "}", - "C.java", + "X.java", + "public class X {\n" + + " void foo(@B(3) X this) {}\n" + + "}", + }, + ""); + // javac-b81: Bytes:13[0 1 21 0 0 10 0 1 0 11 73 0 12] + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #16 @B(\n" + + " #17 value=(int) 3 (constant type)\n" + + " target type = 0x15 METHOD_RECEIVER\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test044_methodReceiver() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<T> {\n" + + " void foo(X<@B(3) T> this) {}\n" + + "}", + "A.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + "@Target(TYPE_USE)\n" + "@Retention(RUNTIME)\n" + - "@interface C {\n" + - " char value() default '-';\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + "}\n", - "I.java", - "interface I {}\n", - "J.java", - "interface J {}\n", + "B.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + }, + ""); + // javac-b81: Bytes:15[0 1 21 1 3 0 0 10 0 1 0 11 73 0 12] + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #18 @B(\n" + + " #19 value=(int) 3 (constant type)\n" + + " target type = 0x15 METHOD_RECEIVER\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + + public void test045_methodParameter() throws Exception { + this.runConformTest( + new String[] { "X.java", "public class X {\n" + - " public void foo(Object o) {\n" + - " if (o instanceof String[][]) {\n" + - " String[][] tab = (@C('_') @B(3) String[] @A[]) o;\n" + - " System.out.println(tab.length);\n" + - " }\n" + - " System.out.println(o);\n" + + " int foo(@B(3) String s) {\n" + + " return s.length();\n" + " }\n" + "}", + + "B.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", }, ""); + // javac-b81: Bytes:14[0 1 22 0 0 0 11 0 1 0 12 73 0 13] String expectedOutput = - " RuntimeVisibleTypeAnnotations: \n" + - " #41 @C(\n" + - " #38 value=\'_\' (constant type)\n" + - " target type = 0x1 TYPE_CAST_GENERIC_OR_ARRAY\n" + - " offset = 8\n" + - " locations = {1}\n" + - " )\n" + - " #43 @A(\n" + - " target type = 0x1 TYPE_CAST_GENERIC_OR_ARRAY\n" + - " offset = 8\n" + - " locations = {0}\n" + - " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #37 @B(\n" + - " #38 value=(int) 3 (constant type)\n" + - " target type = 0x1 TYPE_CAST_GENERIC_OR_ARRAY\n" + - " offset = 8\n" + - " locations = {1}\n" + + " #25 @B(\n" + + " #26 value=(int) 3 (constant type)\n" + + " target type = 0x16 METHOD_FORMAL_PARAMETER\n" + + " method parameter index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test046_methodParameter() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " int foo(int i, double d, @B(3) String s) {\n" + + " return s.length();\n" + + " }\n" + + "}", + + "B.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + }, + ""); + // javac-b81: Bytes:14[0 1 22 1 0 0 11 0 1 0 12 73 0 13] + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #29 @B(\n" + + " #30 value=(int) 3 (constant type)\n" + + " target type = 0x16 METHOD_FORMAL_PARAMETER\n" + + " method parameter index = 2\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // qualified allocation expression with type arguments - public void test029() throws Exception { + + public void test047_methodParameterArray() throws Exception { this.runConformTest( new String[] { "A.java", @@ -1711,62 +1898,807 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface B {\n" + " int value() default -1;\n" + "}", + "X.java", + "public class X {\n" + + " int foo(String @A [] @B(3) [] s) {\n" + + " return s.length;\n" + + " }\n" + + "}", + }, + ""); + // javac-b81: + // Bytes:9[0 1 22 0 0 0 11 0 0] + // Bytes:16[0 1 22 0 1 0 0 0 13 0 1 0 14 73 0 15] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #23 @A(\n" + + " target type = 0x16 METHOD_FORMAL_PARAMETER\n" + + " method parameter index = 0\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #19 @B(\n" + + " #20 value=(int) 3 (constant type)\n" + + " target type = 0x16 METHOD_FORMAL_PARAMETER\n" + + " method parameter index = 0\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test048_throws() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n"+ + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n"+ + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", "C.java", + "import java.lang.annotation.*;\n"+ + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "E.java", + "class E extends RuntimeException {\n" + + " private static final long serialVersionUID = 1L;\n" + + "}\n", + "E1.java", + "class E1 extends RuntimeException {\n" + + " private static final long serialVersionUID = 1L;\n" + + "}\n", + "E2.java", + "class E2 extends RuntimeException {\n" + + " private static final long serialVersionUID = 1L;\n" + + "}\n", + "X.java", + "public class X {\n" + + " void foo() throws @A(\"Hello, World!\") E, E1, @B @C('(') E2 {}\n" + + "}", + }, + ""); + // javac-b81: + // Bytes:28[0 2 23 0 0 0 0 14 0 1 0 15 115 0 16 23 0 2 0 0 17 0 1 0 15 67 0 18] + // Bytes:10[0 1 23 0 2 0 0 20 0 0] + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #25 @A(\n" + + " #26 value=\"Hello, World!\" (constant type)\n" + + " target type = 0x17 THROWS\n" + + " throws index = 0\n" + + " )\n" + + " #28 @C(\n" + + " #26 value=\'(\' (constant type)\n" + + " target type = 0x17 THROWS\n" + + " throws index = 2\n" + + " )\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #23 @B(\n" + + " target type = 0x17 THROWS\n" + + " throws index = 2\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + + public void test049_codeblocks_localVariable() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.lang.annotation.Target;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " @B int j = 9;\n" + + " try {\n" + + " System.out.print(\"SUCCESS\" + j);\n" + + " } catch(@A Exception e) {\n" + + " }\n" + + " @B int k = 3;\n" + + " System.out.println(k);\n" + + " }\n" + + "}", + "A.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + "@Target(TYPE_USE)\n" + "@Retention(RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(CLASS)\n" + + "@interface B {\n" + + " String value() default \"default\";\n" + + "}\n", + }, + "SUCCESS93"); + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #56 @B(\n" + + " target type = 0x40 LOCAL_VARIABLE\n" + + " local variable entries:\n" + + " [pc: 3, pc: 39] index: 1\n" + + " )\n" + + " #56 @B(\n" + + " target type = 0x40 LOCAL_VARIABLE\n" + + " local variable entries:\n" + + " [pc: 31, pc: 39] index: 2\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test050_codeblocks_localVariable() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + "@interface C {\n" + " char value() default '-';\n" + "}\n", - "D.java", + "X.java", + "public class X {\n" + + " String[][] bar() {\n" + + " return new String[][] {};" + + " }\n" + + " void foo(String s) {\n" + + " @C int i;\n" + + " @A String [] @B(3)[] tab = bar();\n" + + " if (tab != null) {\n" + + " i = 0;\n" + + " System.out.println(i + tab.length);\n" + + " } else {\n" + + " System.out.println(tab.length);\n" + + " }\n" + + " i = 4;\n" + + " System.out.println(-i + tab.length);\n" + + " }\n" + + "}", + }, + ""); + // javac-b81: + // Bytes:34[0 2 64 0 1 0 34 0 12 0 2 0 0 19 0 0 64 0 1 0 5 0 41 0 3 2 0 0 0 0 0 20 0 0] + // Bytes:23[0 1 64 0 1 0 5 0 41 0 3 1 0 0 0 22 0 1 0 23 73 0 24] + // ECJ data varies a little here as it is splitting the range + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #45 @B(\n" + + " #46 value=(int) 3 (constant type)\n" + + " target type = 0x40 LOCAL_VARIABLE\n" + + " local variable entries:\n" + + " [pc: 5, pc: 46] index: 3\n" + + " location = [ARRAY]\n" + + " )\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #49 @C(\n" + + " target type = 0x40 LOCAL_VARIABLE\n" + + " local variable entries:\n" + + " [pc: 11, pc: 24] index: 2\n" + + " [pc: 34, pc: 46] index: 2\n" + + " )\n" + + " #50 @A(\n" + + " target type = 0x40 LOCAL_VARIABLE\n" + + " local variable entries:\n" + + " [pc: 5, pc: 46] index: 3\n" + + " location = [ARRAY, ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test051_codeblocks_resourceVariable() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "X.java", + "import java.io.*;\n"+ + "public class X {\n" + + " public static void main(String[] argv) throws Exception {\n"+ + " try (@A BufferedReader br1 = new BufferedReader(new FileReader(\"a\"));\n"+ + " @B(99) BufferedReader br2 = new BufferedReader(new FileReader(\"b\"))) {\n"+ + " System.out.println(br1.readLine()+br2.readLine());\n" + + " }\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #81 @B(\n" + + " #82 value=(int) 99 (constant type)\n" + + " target type = 0x41 RESOURCE_VARIABLE\n" + + " local variable entries:\n" + + " [pc: 39, pc: 94] index: 4\n" + + " )\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #85 @A(\n" + + " target type = 0x41 RESOURCE_VARIABLE\n" + + " local variable entries:\n" + + " [pc: 21, pc: 135] index: 3\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void _test052_codeblocks_exceptionParameter() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.lang.annotation.*;\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " Exception test = new Exception() {\n" + + " private static final long serialVersionUID = 1L;\n" + + " @Override\n" + + " public String toString() {\n" + + " return \"SUCCESS\";\n" + + " }\n" + + " };\n" + + " try {\n" + + " System.out.println(test);\n" + + " } catch(@A Exception e) {\n" + + " e.printStackTrace();\n" + + " }\n" + + " }\n" + + "}", + + "A.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + "@Target(TYPE_USE)\n" + "@Retention(RUNTIME)\n" + - "@interface D {\n" + - " char value() default '-';\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + "}\n", + }, + "SUCCESS"); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #44 @A(\n" + + " target type = 0x42 EXCEPTION_PARAMETER\n" + + " exception table index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void _test053_codeblocks_exceptionParameter() throws Exception { + this.runConformTest( + new String[] { "X.java", + "import java.lang.annotation.Target;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + "public class X {\n" + - " class Y {\n" + - " <T, U> Y(T t, U u) {}\n" + + " public static void main(String[] args) {\n" + + " @A Exception test = new Exception() {\n" + + " private static final long serialVersionUID = 1L;\n" + + " @Override\n" + + " public String toString() {\n" + + " return \"SUCCESS\";\n" + + " }\n" + + " };\n" + + " try {\n" + + " System.out.println(test);\n" + + " } catch(@A Exception e) {\n" + + " e.printStackTrace();\n" + + " }\n" + " }\n" + + "}", + "A.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + }, + "SUCCESS"); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #44 @A(\n" + + " target type = 0x40 LOCAL_VARIABLE\n" + + " local variable entries:\n" + + " [pc: 8, pc: 24] index: 1\n" + + " )\n" + + " #44 @A(\n" + + " target type = 0x42 EXCEPTION_PARAMETER\n" + + " exception table index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void _test054_codeblocks_exceptionParameter() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.lang.annotation.Target;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "public class X {\n" + " public static void main(String[] args) {\n" + - " Y y = new X().new <@D() @A(value = \"hello\") String, @B X> Y(\"SUCCESS\", null);\n" + - " System.out.println(y);\n" + + " try {\n" + + " System.out.println(42);\n" + + " } catch(@B(1) RuntimeException e) {\n" + + " e.printStackTrace();\n" + + " } catch(@B(2) Throwable t) {\n" + + " t.printStackTrace();\n" + + " }\n" + " }\n" + "}", + "B.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RUNTIME)\n" + + "@interface B {\n" + + " int value() default 99;\n" + + "}\n", }, - ""); + "42"); String expectedOutput = " RuntimeVisibleTypeAnnotations: \n" + - " #47 @D(\n" + - " target type = 0x18 TYPE_ARGUMENT_CONSTRUCTOR_CALL\n" + - " offset = 19\n" + - " type argument index = 0\n" + + " #44 @B(\n" + + " #45 value=(int) 1 (constant type)\n" + + " target type = 0x42 EXCEPTION_PARAMETER\n" + + " exception table index = 0\n" + " )\n" + - " #48 @A(\n" + - " #49 value=\"hello\" (constant type)\n" + - " target type = 0x18 TYPE_ARGUMENT_CONSTRUCTOR_CALL\n" + - " offset = 19\n" + - " type argument index = 0\n" + + " #44 @B(\n" + + " #45 value=(int) 2 (constant type)\n" + + " target type = 0x42 EXCEPTION_PARAMETER\n" + + " exception table index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void _test055_codeblocks_exceptionParameterMultiCatch() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.lang.annotation.Target;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "class Exc1 extends RuntimeException {" + + " private static final long serialVersionUID = 1L;\n" + + "}\n"+ + "class Exc2 extends RuntimeException {" + + " private static final long serialVersionUID = 1L;\n" + + "}\n"+ + "class Exc3 extends RuntimeException {" + + " private static final long serialVersionUID = 1L;\n" + + "}\n"+ + "public class X {\n" + + " public static void main(String[] args) {\n" + + " try {\n" + + " System.out.println(42);\n" + + // @B(1) is attached to the argument, the others are attached to the type reference in the union type reference + // During Parsing the @B(1) is moved from the argument to Exc1 + " } catch(@B(1) Exc1 | Exc2 | @B(2) Exc3 t) {\n" + + " t.printStackTrace();\n" + + " }\n" + + " }\n" + + "}", + "B.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RUNTIME)\n" + + "@interface B {\n" + + " int value() default 99;\n" + + "}\n", + }, + "42"); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #45 @B(\n" + + " #46 value=(int) 1 (constant type)\n" + + " target type = 0x42 EXCEPTION_PARAMETER\n" + + " exception table index = 0\n" + " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + " #45 @B(\n" + - " target type = 0x18 TYPE_ARGUMENT_CONSTRUCTOR_CALL\n" + - " offset = 19\n" + - " type argument index = 1\n" + + " #46 value=(int) 2 (constant type)\n" + + " target type = 0x42 EXCEPTION_PARAMETER\n" + + " exception table index = 2\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test056_codeblocks_instanceof() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public void foo(Object o) {\n" + + " if (o instanceof @A String) {\n" + + " String tab = (String) o;\n" + + " System.out.println(tab);\n" + + " }\n" + + " System.out.println(o);\n" + + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #38 @A(\n" + + " target type = 0x43 INSTANCEOF\n" + + " offset = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + + expectedOutput = " 1 instanceof java.lang.String [16]\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test057_codeblocks_new() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", + "X.java", + "public class X {\n" + + " public boolean foo(String s) {\n" + + " System.out.println(\"xyz\");\n" + + " Object o = new @B(3) Object();\n" + + " return true;\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #35 @B(\n" + + " #36 value=(int) 3 (constant type)\n" + + " target type = 0x44 NEW\n" + + " offset = 8\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // local + wildcard - // qualified allocation expression with type arguments - public void test030() throws Exception { + + public void test058_codeblocks_new2() throws Exception { + this.runConformTest( + new String[] { + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + + "X.java", + "public class X {\n" + + " public void foo() {\n" + + " Outer o = new Outer();\n" + + " o.new @B(1) Inner();\n" + + " }\n" + + "}\n" + + "class Outer { class Inner {}}\n" + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #30 @B(\n" + + " #31 value=(int) 1 (constant type)\n" + + " target type = 0x44 NEW\n" + + " offset = 8\n" + + " location = [INNER_TYPE]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test059_codeblocks_new_newArray() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", + "X.java", + "public class X {\n" + + " public boolean foo(String s) {\n" + + " System.out.println(\"xyz\");\n" + + " Object o = new @A String [1];\n" + + " return true;\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #37 @A(\n" + + " target type = 0x44 NEW\n" + + " offset = 9\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test060_codeblocks_new_multiNewArray() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "X.java", + "public class X {\n" + + " public boolean foo(String s) {\n" + + " System.out.println(\"xyz\");\n" + + " Object o = new @A String [2][3];\n" + + " return true;\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #37 @A(\n" + + " target type = 0x44 NEW\n" + + " offset = 10\n" + + " location = [ARRAY, ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test061_codeblocks_new_newArrayWithInitializer() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", + "X.java", + "public class X {\n" + + " public boolean foo(String s) {\n" + + " System.out.println(\"xyz\");\n" + + " Object o = new @A String []{\"xyz\"};\n" + + " return true;\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #37 @A(\n" + + " target type = 0x44 NEW\n" + + " offset = 9\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test062_codeblocks_newArray() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", + "X.java", + "public class X {\n" + + " public boolean foo(String s) {\n" + + " System.out.println(\"xyz\");\n" + + " Object o = new String @A[1];\n" + + " return true;\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #37 @A(\n" + + " target type = 0x44 NEW\n" + + " offset = 9\n" + + // no type path expected here + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test062_codeblocks_newArrayWithInitializer() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface C {\n" + + " char value() default '-';\n" + + "}\n", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", + "X.java", + "public class X {\n" + + " public boolean foo(String s) {\n" + + " System.out.println(\"xyz\");\n" + + " Object o = new String @A[] { \"Hello\" };\n" + + " return true;\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #39 @A(\n" + + " target type = 0x44 NEW\n" + + " offset = 9\n" + + // no type path expected here + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test063_codeblocks_new_instanceof() throws Exception { this.runConformTest( new String[] { "A.java", @@ -1799,75 +2731,336 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface C {\n" + " char value() default '-';\n" + "}\n", - "D.java", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", + "X.java", + "public class X {\n" + + " public boolean foo(Object o) {\n" + + " boolean b = (o instanceof @C('_') Object[]);\n" + + " Object o1 = new @B(3) @A(\"new Object\") Object[] {};\n" + + " return b;\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #24 @B(\n" + + " #25 value=(int) 3 (constant type)\n" + + " target type = 0x44 NEW\n" + + " offset = 6\n" + + " location = [ARRAY]\n" + + " )\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #28 @C(\n" + + " #25 value=\'_\' (constant type)\n" + + " target type = 0x43 INSTANCEOF\n" + + " offset = 1\n" + + " location = [ARRAY]\n" + + " )\n" + + " #30 @A(\n" + + " #25 value=\"new Object\" (constant type)\n" + + " target type = 0x44 NEW\n" + + " offset = 6\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + + public void test064_codeblocks_constructorReference() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "interface MR { X process(String input); }\n"+ + "public class X<T> {\n" + + " public X(T t) {}\n" + + " public static <T> String foo(String bar) { return bar; }\n"+ + " public void bar() {\n" + + " System.out.println(\"abc\");\n" + + " MR ref = @A X::new;\n" + + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #48 @A(\n" + + " target type = 0x45 CONSTRUCTOR_REFERENCE\n" + + " offset = 8\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + + public void test065_codeblocks_methodReference() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "interface MR { String process(String input); }\n"+ + "public class X<T> {\n" + + " public static <T> String foo(String bar) { return bar; }\n"+ + " public void bar() {\n" + + " System.out.println(\"abc\");\n" + + " MR ref = @A X::foo;\n" + + " ref.process(\"abc\");\n" + + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #48 @A(\n" + + " target type = 0x46 METHOD_REFERENCE\n" + + " offset = 8\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test066_codeblocks_methodReference() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "interface I {\n" + + " Object copy(int [] ia);\n" + + "}\n" + + "public class X {\n" + + " public static void main(String [] args) {\n" + + " I i = @B(1) int @B(2)[]::<String>clone;\n" + + " i.copy(new int[10]); \n" + + " }\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #31 @B(\n" + + " #32 value=(int) 1 (constant type)\n" + + " target type = 0x46 METHOD_REFERENCE\n" + + " offset = 0\n" + + " location = [ARRAY]\n" + + " )\n" + + " #31 @B(\n" + + " #32 value=(int) 2 (constant type)\n" + + " target type = 0x46 METHOD_REFERENCE\n" + + " offset = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test067_codeblocks_constructorReferenceTypeArgument() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "interface MR { X process(String input); }\n" + + "public class X<T> {\n" + + " public X(T s) {};\n" + + " public static <T> String foo(String bar) { return bar; }\n"+ + " public void bar() {\n" + + " System.out.println(\"abc\");\n" + + " MR ref = X::<@A String>new;\n" + + " ref.process(\"abc\");\n" + + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #54 @A(\n" + + " target type = 0x4a CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT\n" + + " offset = 8\n" + + " type argument index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test068_codeblocks_methodReferenceTypeArgument() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "interface MR { String process(String input); }\n"+ + "public class X<T> {\n" + + " public static <T> String foo(String bar) { return bar; }\n"+ + " public void bar() {\n" + + " System.out.println(\"abc\");\n" + + " MR ref = X::<@A String>foo;\n" + + " ref.process(\"abc\");\n" + + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #48 @A(\n" + + " target type = 0x4b METHOD_REFERENCE_TYPE_ARGUMENT\n" + + " offset = 8\n" + + " type argument index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test069_codeblocks_cast() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public void foo(Object o) {\n" + + " if (o instanceof String) {\n" + + " String tab = (@A String) o;\n" + + " System.out.println(tab);\n" + + " }\n" + + " System.out.println(o);\n" + + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + // javac-b81: Bytes:11[0 1 71 0 7 0 0 0 16 0 0] + // relevant numbers '71 0 7 0' which mean 0x47 (CAST) at offset 7 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #38 @A(\n" + + " target type = 0x47 CAST\n" + + " offset = 8\n" + + " type argument index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test070_codeblocks_cast_complex() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(CLASS)\n" + + "@interface B {\n" + + " int value() default -1;\n" + + "}", + "C.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + "@Target(TYPE_USE)\n" + "@Retention(RUNTIME)\n" + - "@interface D {\n" + + "@interface C {\n" + " char value() default '-';\n" + "}\n", + "I.java", + "interface I {}\n", + "J.java", + "interface J {}\n", "X.java", - "import java.util.Map;\n" + - "import java.util.HashMap;\n" + - "@SuppressWarnings({\"unchecked\",\"rawtypes\"})\n" + "public class X {\n" + - " Object newMap(Object o) {\n" + - " Map<@A Object, ? super @C Map<@B String, @D Comparable>> map;\n" + - " if (o == null) {\n" + - " map = null;\n" + - " System.out.println(map);\n" + - " } else {\n" + - " System.out.println(\"No map yet\");\n" + + " public void foo(Object o) {\n" + + " if (o instanceof String[][]) {\n" + + " String[][] tab = (@C('_') @B(3) String[] @A[]) o;\n" + + " System.out.println(tab.length);\n" + " }\n" + - " map = new HashMap();\n" + - " return map;\n" + - " } \n" + + " System.out.println(o);\n" + + " }\n" + "}", }, ""); + // javac-b81: + // Bytes:31[0 2 71 0 7 0 1 0 0 0 16 0 0 71 0 7 0 2 0 0 0 0 0 17 0 1 0 18 67 0 19] + // Bytes:20[0 1 71 0 7 0 2 0 0 0 0 0 21 0 1 0 18 73 0 22] String expectedOutput = - " RuntimeVisibleTypeAnnotations: \n" + - " #46 @A(\n" + - " target type = 0x9 LOCAL_VARIABLE_GENERIC_OR_ARRAY\n" + - " local variable entries:\n" + - " [pc: 6, pc: 16] index: 2\n" + - " [pc: 32, pc: 34] index: 2\n" + - " locations = {0}\n" + - " )\n" + - " #47 @C(\n" + - " target type = 0x1c WILDCARD_BOUND\n" + - " wildcard location type = 0x9 LOCAL_VARIABLE_GENERIC_OR_ARRAY\n" + - " local variable entries:\n" + - " [pc: 6, pc: 16] index: 2\n" + - " [pc: 32, pc: 34] index: 2\n" + - " wildcard locations = {1}\n" + + " RuntimeInvisibleTypeAnnotations: \n" + + " #37 @B(\n" + + " #38 value=(int) 3 (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 8\n" + + " type argument index = 0\n" + + " location = [ARRAY, ARRAY]\n" + " )\n" + - " #48 @D(\n" + - " target type = 0x1d WILDCARD_BOUND_GENERIC_OR_ARRAY\n" + - " wildcard location type = 0x9 LOCAL_VARIABLE_GENERIC_OR_ARRAY\n" + - " local variable entries:\n" + - " [pc: 6, pc: 16] index: 2\n" + - " [pc: 32, pc: 34] index: 2\n" + - " wildcard locations = {1}\n" + - " locations = {1}\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #41 @C(\n" + + " #38 value=\'_\' (constant type)\n" + + " target type = 0x47 CAST\n" + + " offset = 8\n" + + " type argument index = 0\n" + + " location = [ARRAY, ARRAY]\n" + " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #44 @B(\n" + - " target type = 0x1d WILDCARD_BOUND_GENERIC_OR_ARRAY\n" + - " wildcard location type = 0x9 LOCAL_VARIABLE_GENERIC_OR_ARRAY\n" + - " local variable entries:\n" + - " [pc: 6, pc: 16] index: 2\n" + - " [pc: 32, pc: 34] index: 2\n" + - " wildcard locations = {1}\n" + - " locations = {0}\n" + + " #43 @A(\n" + + " target type = 0x47 CAST\n" + + " offset = 8\n" + + " type argument index = 0\n" + + " location = [ARRAY]\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // method type parameter bound generic or array - public void test031() throws Exception { + + public void test071_codeblocks_constructorInvocationTypeArgument() throws Exception { this.runConformTest( new String[] { "A.java", @@ -1890,65 +3083,202 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "@interface B {\n" + " int value() default -1;\n" + "}", - "C.java", + "X.java", + "public class X {\n" + + " <T> X(T t) {\n" + + " }\n" + + " public Object foo() {\n" + + " X x = new <@A @B(1) String>X(null);\n" + + " return x;\n" + + " }\n" + + "}", + }, + ""); + String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #27 @B(\n" + + " #28 value=(int) 1 (constant type)\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 5\n" + + " type argument index = 0\n" + + " )\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #31 @A(\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 5\n" + + " type argument index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test072_codeblocks_constructorInvocationTypeArgument() throws Exception { + this.runConformTest( + new String[] { + "A.java", + "import java.lang.annotation.Target;\n" + + "import static java.lang.annotation.ElementType.*;\n" + + "import java.lang.annotation.Retention;\n" + + "import static java.lang.annotation.RetentionPolicy.*;\n" + + "@Target(TYPE_USE)\n" + + "@Retention(RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + "B.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + "@Target(TYPE_USE)\n" + "@Retention(CLASS)\n" + - "@interface C {\n" + + "@interface B {\n" + " int value() default -1;\n" + "}", - "D.java", + "C.java", "import java.lang.annotation.Target;\n" + "import static java.lang.annotation.ElementType.*;\n" + "import java.lang.annotation.Retention;\n" + "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_PARAMETER)\n" + + "@Target(TYPE_USE)\n" + "@Retention(RUNTIME)\n" + - "@interface D {\n" + - " String value() default \"default\";\n" + + "@interface C {\n" + + " char value() default '-';\n" + "}\n", - "Z.java", - "public class Z<T> {}", "X.java", - "public class X {\n" + - " <@D U, T extends Z<@A String @C[][]@B[]> & @B(3) Cloneable> void foo(U u, T t) {}\n" + + "public class X {\n" + + " <T, U> X(T t, U u) {\n" + + " }\n" + + " public Object foo() {\n" + + " X x = new <@A Integer, @A String @C [] @B(1)[]>X(null, null);\n" + + " return x;\n" + + " }\n" + "}", }, ""); String expectedOutput = - " RuntimeVisibleTypeAnnotations: \n" + - " #31 @D(\n" + - " target type = 0x20 METHOD_TYPE_PARAMETER\n" + - " type parameter index = 0\n" + - " )\n" + - " #32 @A(\n" + - " target type = 0x13 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + - " type parameter index = 1 type parameter bound index = 0\n" + - " locations = {0,2}\n" + - " )\n" + " RuntimeInvisibleTypeAnnotations: \n" + - " #26 @C(\n" + - " target type = 0x13 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + - " type parameter index = 1 type parameter bound index = 0\n" + - " locations = {0}\n" + + " #29 @B(\n" + + " #30 value=(int) 1 (constant type)\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 6\n" + + " type argument index = 1\n" + + " location = [ARRAY]\n" + " )\n" + - " #27 @B(\n" + - " target type = 0x13 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY\n" + - " type parameter index = 1 type parameter bound index = 0\n" + - " locations = {0,1}\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #33 @A(\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 6\n" + + " type argument index = 0\n" + " )\n" + - " #27 @B(\n" + - " #28 value=(int) 3 (constant type)\n" + - " target type = 0x12 METHOD_TYPE_PARAMETER_BOUND\n" + - " type parameter index = 1 type parameter bound index = 1\n" + + " #33 @A(\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 6\n" + + " type argument index = 1\n" + + " location = [ARRAY, ARRAY]\n" + + " )\n" + + " #34 @C(\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 6\n" + + " type argument index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + public void test073_codeblocks_constructorInvocationTypeArgument() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<T1, T2> {\n" + + " public void bar() {\n" + + " new <String, @A T2>X();\n"+ + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + // Example bytes:11[0 1 73 0 0 0 0 0 13 0 0] this would be for offset 0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #19 @A(\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 3\n" + + " type argument index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test074_codeblocks_constructorInvocationTypeArgument() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<T1,T2> {\n" + + " public static void foo(int i) {}\n"+ + " public void bar() {\n" + + " new <java.util.List<@A String>, T2>X();\n"+ + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + // Example bytes:11[0 1 73 0 0 0 0 0 13 0 0] this would be for offset 0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #23 @A(\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 3\n" + + " type argument index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // type argument method call and generic or array - public void test032() throws Exception { + + public void test075_codeblocks_constructorInvocationTypeArgument() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<T> {\n" + + " public void bar() {\n" + + " new <@A T>X();\n"+ + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + // Example bytes:11[0 1 73 0 0 0 0 0 13 0 0] this would be for offset 0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #19 @A(\n" + + " target type = 0x48 CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 3\n" + + " type argument index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test076_codeblocks_methodInvocationTypeArgument() throws Exception { this.runConformTest( new String[] { "X.java", @@ -1957,8 +3287,8 @@ public class TypeAnnotationTest extends AbstractRegressionTest { " static <T, U> T foo(T t, U u) {\n" + " return t;\n" + " }\n" + - " public static void bar() {\n" + - " System.out.println(X.<@A String[] @B(1) [], @C('-') X>foo(new String[][]{{\"SUCCESS\"}}, null)[0]);\n" + + " public static void main(String[] args) {\n" + + " System.out.println(X.<@A @B(1) String[], @C('-') X>foo(new String[]{\"SUCCESS\"}, null)[0]);\n" + " }\n" + "}\n", "A.java", @@ -1992,203 +3322,188 @@ public class TypeAnnotationTest extends AbstractRegressionTest { " char value() default '-';\n" + "}\n", }, - ""); + "SUCCESS"); String expectedOutput = + " RuntimeInvisibleTypeAnnotations: \n" + + " #48 @B(\n" + + " #49 value=(int) 1 (constant type)\n" + + " target type = 0x49 METHOD_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 13\n" + + " type argument index = 0\n" + + " location = [ARRAY]\n" + + " )\n" + " RuntimeVisibleTypeAnnotations: \n" + " #52 @A(\n" + - " target type = 0x1b TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY\n" + - " offset = 20\n" + + " target type = 0x49 METHOD_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 13\n" + " type argument index = 0\n" + - " locations = {1}\n" + + " location = [ARRAY]\n" + " )\n" + " #53 @C(\n" + " #49 value=\'-\' (constant type)\n" + - " target type = 0x1a TYPE_ARGUMENT_METHOD_CALL\n" + - " offset = 20\n" + + " target type = 0x49 METHOD_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 13\n" + " type argument index = 1\n" + - " )\n" + - " RuntimeInvisibleTypeAnnotations: \n" + - " #48 @B(\n" + - " #49 value=(int) 1 (constant type)\n" + - " target type = 0x1b TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY\n" + - " offset = 20\n" + - " type argument index = 0\n" + - " locations = {0}\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } -// // superclass -// public void test033() throws Exception { -// this.runConformTest( -// new String[] { -// "Marker.java", -// "@interface Marker {}", -// "X.java", -// "public class X extends @Marker Object {}", -// }, -// ""); -// } - // superclass - public void test034() throws Exception { - this.runNegativeTest( + + public void test077_codeblocks_methodInvocationTypeArgument() throws Exception { + this.runConformTest( new String[] { - "Marker.java", - "import java.lang.annotation.Target;\n" + - "import static java.lang.annotation.ElementType.*;\n" + - "@Target(TYPE_PARAMETER)\n" + - "@interface Marker {}", "X.java", - "public class X extends @Marker Object {}", - }, - "----------\n" + - "1. ERROR in X.java (at line 1)\n" + - " public class X extends @Marker Object {}\n" + - " ^^^^^^^\n" + - "The annotation @Marker is disallowed for this location\n" + - "----------\n"); - } -// // annotation on catch variable -// public void test035() throws Exception { -// this.runConformTest( -// new String[] { -// "X.java", -// "import java.lang.annotation.Target;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "public class X {\n" + -// " public static void main(String[] args) {\n" + -// " @A Exception test = new Exception() {\n" + -// " private static final long serialVersionUID = 1L;\n" + -// " @Override\n" + -// " public String toString() {\n" + -// " return \"SUCCESS\";\n" + -// " }\n" + -// " };\n" + -// " try {\n" + -// " System.out.println(test);\n" + -// " } catch(@A Exception e) {\n" + -// " e.printStackTrace();\n" + -// " }\n" + -// " }\n" + -// "}", -// "A.java", -// "import java.lang.annotation.Target;\n" + -// "import static java.lang.annotation.ElementType.*;\n" + -// "import java.lang.annotation.Retention;\n" + -// "import static java.lang.annotation.RetentionPolicy.*;\n" + -// "@Target(TYPE_USE)\n" + -// "@Retention(RUNTIME)\n" + -// "@interface A {\n" + -// " String value() default \"default\";\n" + -// "}\n", -// }, -// "SUCCESS"); -// String expectedOutput = -// " RuntimeVisibleTypeAnnotations: \n" + -// " #44 @A(\n" + -// " target type = 0x8 LOCAL_VARIABLE\n" + -// " local variable entries:\n" + -// " [pc: 8, pc: 24] index: 1\n" + -// " )\n" + -// " #44 @A(\n" + -// " target type = 0x8 LOCAL_VARIABLE\n" + -// " local variable entries:\n" + -// " [pc: 19, pc: 23] index: 2\n" + -// " )\n"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } - // annotation on catch variable - public void test036() throws Exception { + "public class X<T1,T2> {\n" + + " public static void foo(int i) {}\n"+ + " public void bar() {\n" + + " X.<String, @A T2>foo(42);\n"+ + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + // Example bytes:11[0 1 73 0 0 0 0 0 13 0 0] this would be for offset 0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #24 @A(\n" + + " target type = 0x49 METHOD_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 2\n" + + " type argument index = 1\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test078_codeblocks_methodInvocationTypeArgument() throws Exception { this.runConformTest( new String[] { "X.java", - "import java.lang.annotation.Target;\n" + - "import java.lang.annotation.Retention;\n" + - "import static java.lang.annotation.ElementType.*;\n" + - "import static java.lang.annotation.RetentionPolicy.*;\n" + - "public class X {\n" + - " public static void main(String[] args) {\n" + - " @B int j = 9;\n" + - " try {\n" + - " System.out.print(\"SUCCESS\" + j);\n" + - " } catch(@A Exception e) {\n" + - " }\n" + - " @B int k = 3;\n" + - " System.out.println(k);\n" + + "public class X<T1,T2> {\n" + + " public static void foo(int i) {}\n"+ + " public void bar() {\n" + + " X.<java.util.List<@A String>, T2>foo(42);\n"+ " }\n" + "}", + "A.java", - "import java.lang.annotation.Target;\n" + - "import static java.lang.annotation.ElementType.*;\n" + - "import java.lang.annotation.Retention;\n" + - "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + - "@Retention(RUNTIME)\n" + + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface A {\n" + + " String value() default \"default\";\n" + + "}\n", + + }, + ""); + // Example bytes:11[0 1 73 0 0 0 0 0 13 0 0] this would be for offset 0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #24 @A(\n" + + " target type = 0x49 METHOD_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 2\n" + + " type argument index = 0\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test079_codeblocks_methodInvocationTypeArgument() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X<T> {\n" + + " public static void foo(int i) {}\n"+ + " public void bar() {\n" + + " X.<@A T>foo(42);\n"+ + " }\n" + + "}", + + "A.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + "@interface A {\n" + " String value() default \"default\";\n" + "}\n", + }, + ""); + // Example bytes:11[0 1 73 0 0 0 0 0 13 0 0] this would be for offset 0 + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #24 @A(\n" + + " target type = 0x49 METHOD_INVOCATION_TYPE_ARGUMENT\n" + + " offset = 2\n" + + " type argument index = 0\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + + // Annotation should appear twice in this case + public void test080_multiuseAnnotations() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " @B(1) int foo() { return 0; }\n" + + "}", "B.java", - "import java.lang.annotation.Target;\n" + - "import static java.lang.annotation.ElementType.*;\n" + - "import java.lang.annotation.Retention;\n" + - "import static java.lang.annotation.RetentionPolicy.*;\n" + - "@Target(TYPE_USE)\n" + - "@Retention(CLASS)\n" + + "import java.lang.annotation.*;\n" + + "@Target({ElementType.METHOD, ElementType.TYPE_USE})\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + "@interface B {\n" + - " String value() default \"default\";\n" + + " int value() default 99;\n" + "}\n", }, - "SUCCESS93"); + ""); String expectedOutput = - " RuntimeInvisibleTypeAnnotations: \n" + - " #56 @B(\n" + - " target type = 0x8 LOCAL_VARIABLE\n" + - " local variable entries:\n" + - " [pc: 3, pc: 39] index: 1\n" + + " RuntimeVisibleAnnotations: \n" + + " #17 @B(\n" + + " #18 value=(int) 1 (constant type)\n" + " )\n" + - " #56 @B(\n" + - " target type = 0x8 LOCAL_VARIABLE\n" + - " local variable entries:\n" + - " [pc: 31, pc: 39] index: 2\n" + + " RuntimeVisibleTypeAnnotations: \n" + + " #17 @B(\n" + + " #18 value=(int) 1 (constant type)\n" + + " target type = 0x14 METHOD_RETURN\n" + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // make sure annotation without target appears twice when set on a method declaration - public void test037() throws Exception { + + public void test081_multiuseAnnotations() throws Exception { this.runConformTest( new String[] { "X.java", - "import java.lang.annotation.Target;\r\n" + - "import static java.lang.annotation.ElementType.*;\r\n" + - "\r\n" + - "@Target(METHOD)\r\n" + - "@interface Annot {\r\n" + - " int value() default 0;\r\n" + - "}\r\n" + - "public class X {\r\n" + - " @Annot(4)\r\n" + - " public void foo() {\r\n" + - " }\r\n" + + "import java.lang.annotation.*;\n" + + "@Target({ElementType.METHOD, ElementType.TYPE_USE})\n" + + "@interface Annot {\n" + + " int value() default 0;\n" + + "}\n" + + "public class X {\n" + + " @Annot(4) public String foo() { return \"hello\"; }" + "}", }, ""); String expectedOutput = - " public void foo();\n" + - " 0 return\n" + - " Line numbers:\n" + - " [pc: 0, line: 11]\n" + - " Local variable table:\n" + - " [pc: 0, pc: 1] local: this index: 0 type: X\n" + " RuntimeInvisibleAnnotations: \n" + - " #16 @Annot(\n" + - " #17 value=(int) 4 (constant type)\n" + + " #17 @Annot(\n" + + " #18 value=(int) 4 (constant type)\n" + " )\n" + - "}"; + " RuntimeInvisibleTypeAnnotations: \n" + + " #17 @Annot(\n" + + " #18 value=(int) 4 (constant type)\n" + + " target type = 0x14 METHOD_RETURN\n" + + " )\n"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } - // make sure annotation without target appears twice when set on a method declaration - public void test038() throws Exception { + + // When not annotated with any TYPE it assumes the Java7 set (i.e. not TYPE_USE/TYPE_PARAMETER) + public void test082_multiuseAnnotations() throws Exception { this.runConformTest( new String[] { "X.java", @@ -2218,75 +3533,856 @@ public class TypeAnnotationTest extends AbstractRegressionTest { "}"; checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } -// // make sure annotation without target appears twice when set on a method declaration -// public void test039() throws Exception { -// this.runConformTest( -// new String[] { -// "X.java", -// "@interface Annot {\r\n" + -// " int value() default 0;\r\n" + -// "}\r\n" + -// "public class X {\r\n" + -// " @Annot(4)\r\n" + -// " public int foo() {\r\n" + -// " return 0;\r\n" + -// " }\r\n" + -// "}", -// }, -// ""); -// String expectedOutput = -// " public int foo();\n" + -// " 0 iconst_0\n" + -// " 1 ireturn\n" + -// " Line numbers:\n" + -// " [pc: 0, line: 7]\n" + -// " Local variable table:\n" + -// " [pc: 0, pc: 2] local: this index: 0 type: X\n" + -// " RuntimeInvisibleAnnotations: \n" + -// " #17 @Annot(\n" + -// " #18 value=(int) 4 (constant type)\n" + -// " )\n" + -// " RuntimeInvisibleTypeAnnotations: \n" + -// " #17 @Annot(\n" + -// " #18 value=(int) 4 (constant type)\n" + -// " target type = 0xa METHOD_RETURN_TYPE\n" + -// " )\n" + -// "}"; -// checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); -// } - // make sure annotation without target appears twice when set on a method declaration - public void test040() throws Exception { - this.runConformTest( - new String[] { - "X.java", - "import java.lang.annotation.Target;\r\n" + - "import static java.lang.annotation.ElementType.*;\r\n" + - "\r\n" + - "@Target(METHOD)\r\n" + - "@interface Annot {\r\n" + - " int value() default 0;\r\n" + - "}\r\n" + - "public class X {\r\n" + - " @Annot(4)\r\n" + - " public int foo() {\r\n" + - " return 0;\r\n" + - " }\r\n" + - "}", - }, - ""); - String expectedOutput = - " public int foo();\n" + - " 0 iconst_0\n" + - " 1 ireturn\n" + - " Line numbers:\n" + - " [pc: 0, line: 11]\n" + - " Local variable table:\n" + - " [pc: 0, pc: 2] local: this index: 0 type: X\n" + - " RuntimeInvisibleAnnotations: \n" + - " #17 @Annot(\n" + - " #18 value=(int) 4 (constant type)\n" + - " )\n" + - "}"; - checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + + public void test100_pqtr() throws Exception { // PQTR (ParameterizedQualifiedTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " java.util.@B(2) List<String> field2;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100a_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " java.util.@B(2) List<String>[] field3;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100b_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " java.util.List<@B(3) String>[] field3;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100c_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " java.util.List<String> @B(3)[] field3;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100d_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " java.util.@B(2) List<@B(5) String> @B(3)[]@B(4)[] field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 4 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 5 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + + public void test100e_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " java.util.Map.@B(2) Entry<String,String> field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100f_pqtr() throws Exception { + this.runConformTest( + new String[] { + "Foo.java", + "class Foo {}\n", + + "Levels.java", + "package one.two.three;\n" + + "class Level1 { static class Level2 { class Level3 { class Level4 { class Level5<T> { } } } } }\n", + + "X.java", + "package one.two.three;\n" + + "class X {\n" + + " one.two.three.Level1.Level2.@B(2) Level3.Level4.@B(3) Level5<String> instance;\n" + + "}\n", + + "B.java", + "package one.two.three;\n" + + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @one.two.three.B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [INNER_TYPE]\n" + + " )\n" + + " #10 @one.two.three.B(\n" + + " #11 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [INNER_TYPE, INNER_TYPE, INNER_TYPE]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "one" + File.separator + "two" + File.separator + "three" + File.separator + "X.class", "one.two.three.X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100g_pqtr() throws Exception { + this.runConformTest( + new String[] { + "Foo.java", + "class Foo {}\n", + + "Levels.java", + "package one.two.three;\n" + + "class Level1 { static class Level2 { class Level3 { class Level4 { class Level5<T> { } } } } }\n", + + "X.java", + "package one.two.three;\n" + + "class X {\n" + + " one.two.three.Level1.Level2.@B(2) Level3.Level4.@B(3) Level5<String>[][] instance;\n" + + "}\n", + + "B.java", + "package one.two.three;\n" + + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @one.two.three.B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE]\n" + + " )\n" + + " #10 @one.two.three.B(\n" + + " #11 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE, INNER_TYPE, INNER_TYPE]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "one" + File.separator + "two" + File.separator + "three" + File.separator + "X.class", "one.two.three.X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100h_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " Level1.Level2.@B(2) Level3.Level4.@B(3) Level5<String>[][] instance;\n" + + "}\n", + + "Levels.java", + "class Level1 { static class Level2 { class Level3 { class Level4 { class Level5<T> { } } } } }\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE, INNER_TYPE, INNER_TYPE]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100i_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " Level1.Level2.Level3.Level4.Level5<@B(1) String>[][] instance;\n" + + "}\n", + + "Levels.java", + "class Level1 { static class Level2 { class Level3 { class Level4 { class Level5<T> { } } } } }\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE, INNER_TYPE, INNER_TYPE, TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100j_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " Level1.Level2.Level3<@B(1) String>.Level4.Level5<@B(2) String>[][] instance;\n" + + "}\n", + + "Levels.java", + "class Level1 { static class Level2 { class Level3<Q> { class Level4 { class Level5<T> { } } } } }\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE, TYPE_ARGUMENT(0)]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE, INNER_TYPE, INNER_TYPE, TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test100k_pqtr() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " Level1.@B(5) Level2.Level3<@B(1) String>.Level4.Level5<@B(2) String>[][] instance;\n" + + "}\n", + + "Levels.java", + "class Level1 { static class Level2 { class Level3<Q> { class Level4 { class Level5<T> { } } } } }\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 5 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE, TYPE_ARGUMENT(0)]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, INNER_TYPE, INNER_TYPE, INNER_TYPE, TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test101a_qtr() throws Exception { // QTR (QualifiedTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " com.foo.@B(2) List field2;\n" + + "}\n", + + "List.java", + "package com.foo;\n"+ + "public class List {}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + + public void test101b_qtr() throws Exception { // QTR (QualifiedTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " java.util.Map.@B(2) Entry field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test101c_qtr() throws Exception { // QTR (QualifiedTypeReference) + this.runConformTest( + new String[] { + "Runner.java", + "public class Runner {}\n", + + "B.java", + "package one.two.three;\n" + + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + + "X.java", + "package one.two.three;\n" + + "class X {\n" + + " one.two.three.Level1.Level2.@B(2) Level3.Level4.@B(3) Level5 instance;\n" + + "}\n", + + "Level1.java", + "package one.two.three;\n" + + "public class Level1 { static class Level2 { class Level3 { class Level4 { class Level5 { } } } } }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @one.two.three.B(\n" + + " #9 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [INNER_TYPE]\n" + + " )\n" + + " #8 @one.two.three.B(\n" + + " #9 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [INNER_TYPE, INNER_TYPE, INNER_TYPE]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "one" + File.separator + "two" + File.separator + "three" + File.separator + "X.class", "one.two.three.X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test102a_str() throws Exception { // STR (SingleTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " @B(1) X field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test102b_str() throws Exception { // STR (SingleTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " @B(1) int field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test103a_atr() throws Exception { // ATR (ArrayTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " @B(1) X[] field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test103b_atr() throws Exception { // ATR (ArrayTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " X @B(2)[] field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test103c_atr() throws Exception { // ATR (ArrayTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " X []@B(3)[] field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test103d_atr() throws Exception { // ATR (ArrayTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " X []@B(3)[][] field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test103e_atr() throws Exception { // ATR (ArrayTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " @B(1) int []@B(3)[][] field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @B(\n" + + " #9 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY, ARRAY]\n" + + " )\n" + + " #8 @B(\n" + + " #9 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test104a_pstr() throws Exception { // PSTR (ParameterizedSingleTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X<T1,T2,T3> {\n" + + " @B(1) X<@B(2) String, @B(3) Integer, @B(4) Boolean> field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0)]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(1)]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 4 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(2)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test104b_pstr() throws Exception { // PSTR (ParameterizedSingleTypeReference) + this.runConformTest( + new String[] { + "X.java", + "class X<T1> {\n" + + " @B(1) X<@B(2) String> @B(3)[] field;\n" + + "}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n" + + " #10 @B(\n" + + " #11 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, TYPE_ARGUMENT(0)]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test105a_aqtr() throws Exception { // AQTR (ArrayQualifiedTypeReference) + this.runConformTest( + new String[] { + "Y.java", + "class Y {}", + + "X.java", + "package one.two.three;\n" + + "class X<T1> {\n" + + " one.two.three.@B(1) List[] field;\n" + + "}\n", + + "List.java", + "package one.two.three;\n" + + "class List {}\n", + + "B.java", + "package one.two.three;\n" + + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @one.two.three.B(\n" + + " #9 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "one" + File.separator + "two" + File.separator + "three" + File.separator +"X.class", + "one.two.three.X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test105b_aqtr() throws Exception { // AQTR (ArrayQualifiedTypeReference) + this.runConformTest( + new String[] { + "Y.java", + "class Y {}", + + "X.java", + "package one.two.three;\n" + + "class X<T1> {\n" + + " one.two.three.@B(2) List @B(3)[]@B(4)[] field;\n" + + "}\n", + + "List.java", + "package one.two.three;\n" + + "class List {}\n", + + "B.java", + "package one.two.three;\n" + + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #8 @one.two.three.B(\n" + + " #9 value=(int) 2 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY, ARRAY]\n" + + " )\n" + + " #8 @one.two.three.B(\n" + + " #9 value=(int) 3 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " )\n" + + " #8 @one.two.three.B(\n" + + " #9 value=(int) 4 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "one" + File.separator + "two" + File.separator + "three" + File.separator +"X.class", + "one.two.three.X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test106a_wtr() throws Exception { // WTR (WildcardTypeReference) + this.runConformTest( + new String[] { + "X.java", + "import java.util.List;\n" + + "class X<T1> {\n" + + " List<? extends @B(1) Number> field;\n" + + "}\n", + + "List.java", + "class List {}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0), WILDCARD]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator +"X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); + } + + public void test106b_wtr() throws Exception { // WTR (WildcardTypeReference) + this.runConformTest( + new String[] { + "X.java", + "import java.util.List;\n" + + "class X<T1> {\n" + + " List<? extends @B(1) Number[]> field;\n" + + "}\n", + + "List.java", + "class List {}\n", + + "B.java", + "import java.lang.annotation.*;\n" + + "@Target(ElementType.TYPE_USE)\n" + + "@Retention(RetentionPolicy.RUNTIME)\n" + + "@interface B { int value() default -1; }\n", + }, + ""); + String expectedOutput = + " RuntimeVisibleTypeAnnotations: \n" + + " #10 @B(\n" + + " #11 value=(int) 1 (constant type)\n" + + " target type = 0x13 FIELD\n" + + " location = [TYPE_ARGUMENT(0), WILDCARD, ARRAY]\n" + + " )\n"; + checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM); } + } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java index 347bbe60e..9a65761a5 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/VarargsTest.java @@ -2491,7 +2491,7 @@ public class VarargsTest extends AbstractComparableTest { }, this.complianceLevel < ClassFileConstants.JDK1_7 ? "----------\n" + - "1. WARNING in X.java (at line 19)\n" + + "1. WARNING in X.java (at line 20)\n" + " new IteratorChain<Number>(null, null);\n" + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Type safety: A generic array of Collection<? extends Number> is created for a varargs parameter\n" + @@ -2502,7 +2502,7 @@ public class VarargsTest extends AbstractComparableTest { " ^^^^^^^^^^^\n" + "Type safety: Potential heap pollution via varargs parameter collections\n" + "----------\n" + - "2. WARNING in X.java (at line 19)\n" + + "2. WARNING in X.java (at line 20)\n" + " new IteratorChain<Number>(null, null);\n" + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + "Type safety: A generic array of Collection<? extends Number> is created for a varargs parameter\n" + diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java index 5a3626424..c99f56652 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java @@ -1662,6 +1662,227 @@ public class ASTConverter18Test extends ConverterTestSetup { } /** + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=399794 + * ReferenceExpression Family Tests + * + * @throws JavaModelException + */ + public void test399794() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter18/src/test399794/X.java", + true/* resolve */); + String contents = "package test399794;" + + "import java.lang.annotation.*;\n " + + "interface I {\n" + + " Object copy(int [] ia);\n" + + "}\n" + + "interface J {\n" + + " void foo(int x);\n" + + "}\n" + + "class XX {\n" + + " public void foo(int x) {}\n" + + "}\n" + + "\n" + + "class Y {\n" + + " static class Z {\n" + + " public static void foo(int x) {\n" + + " System.out.print(x);\n" + + " }\n" + + " }\n" + + " public void foo(int x) {\n" + + " System.out.print(x);\n" + + " }\n" + + " public <T> void foo(T t){t.hashCode();}\n" + + "}\n" + + "\n" + + "public class X extends XX {\n" + + " @SuppressWarnings(\"unused\")\n" + + " public void bar(String [] args) {\n" + + " Y y = new Y();\n" + + " I i = @Marker int []::<String>clone;\n" + + " J j = Y.@Marker Z :: foo;\n" + + " J j1 = Y.@Marker Z :: <String> foo;\n" + + " J jdash = @Marker W<@Marker Integer> :: <String> new ;\n" + + " J jj = y :: foo;\n" + + " J jx = super :: foo;\n" + + " class Z {\n" + + " void foo() {\n" + + " J jz = X.super :: foo;\n" + + " }\n" + + " }\n" + + " }\n" + + " public static void main (String [] args) {}\n" + + "}\n" + + "class W<T> extends Y {\n" + + " public W(T x) {}\n" + + "}\n" + + "\n" + + "@Target (ElementType.TYPE_USE)\n" + + "@interface Marker {}"; + + CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy); + TypeDeclaration typeDeclaration = (TypeDeclaration) getASTNode(cu, 4); + MethodDeclaration method = typeDeclaration.getMethods()[0]; + List statements = method.getBody().statements(); + assertTrue(statements.size() == 8); + int fCount = 1; + + // type method reference with primitive type with type arguments + VariableDeclarationStatement statement = (VariableDeclarationStatement) statements.get(fCount++); + VariableDeclarationFragment fragment = (VariableDeclarationFragment) statement.fragments().get(0); + Expression expression = fragment.getInitializer(); + assertTrue(expression instanceof TypeMethodReference); + TypeMethodReference typeMethodReference = (TypeMethodReference) expression; + checkSourceRange(typeMethodReference, "@Marker int []::<String>clone", contents); + ITypeBinding typeBinding = typeMethodReference.resolveTypeBinding(); + assertNotNull(typeBinding); + IMethodBinding methodBinding = typeMethodReference.resolveMethodBinding(); + assertNotNull(methodBinding); + Type type = typeMethodReference.getType(); + checkSourceRange(type, "@Marker int []", contents); + assertTrue(type.isArrayType()); + List typeArguments = typeMethodReference.typeArguments(); + assertTrue(typeArguments.size() == 1); + type = (Type) typeArguments.get(0); + checkSourceRange(type, "String", contents); + assertTrue(type.isSimpleType()); + SimpleName name = typeMethodReference.getName(); + checkSourceRange(name, "clone", contents); + typeBinding = name.resolveTypeBinding(); + assertNotNull(typeBinding); + + // type method reference with qualified type without type arguments + statement = (VariableDeclarationStatement) statements.get(fCount++); + fragment = (VariableDeclarationFragment) statement.fragments().get(0); + expression = fragment.getInitializer(); + assertTrue(expression instanceof TypeMethodReference); + typeMethodReference = (TypeMethodReference) expression; + checkSourceRange(typeMethodReference, "Y.@Marker Z :: foo", contents); + typeBinding = typeMethodReference.resolveTypeBinding(); + assertNotNull(typeBinding); + methodBinding = typeMethodReference.resolveMethodBinding(); + assertNotNull(methodBinding); + type = typeMethodReference.getType(); + assertTrue(type.isQualifiedType()); + checkSourceRange(type, "Y.@Marker Z", contents); + typeArguments = typeMethodReference.typeArguments(); + assertTrue(typeArguments.size() == 0); + name = typeMethodReference.getName(); + checkSourceRange(name, "foo", contents); + typeBinding = name.resolveTypeBinding(); + assertNotNull(typeBinding); + + // type method reference with qualified type with type arguments + statement = (VariableDeclarationStatement) statements.get(fCount++); + fragment = (VariableDeclarationFragment) statement.fragments().get(0); + expression = fragment.getInitializer(); + assertTrue(expression instanceof TypeMethodReference); + typeMethodReference = (TypeMethodReference) expression; + checkSourceRange(typeMethodReference, "Y.@Marker Z :: <String> foo", contents); + typeBinding = typeMethodReference.resolveTypeBinding(); + assertNotNull(typeBinding); + methodBinding = typeMethodReference.resolveMethodBinding(); + assertNotNull(methodBinding); + type = typeMethodReference.getType(); + assertTrue(type.isQualifiedType()); + checkSourceRange(type, "Y.@Marker Z", contents); + typeArguments = typeMethodReference.typeArguments(); + assertTrue(typeArguments.size() == 1); + type = (Type) typeArguments.get(0); + assertTrue(type.isSimpleType()); + checkSourceRange(type, "String", contents); + name = typeMethodReference.getName(); + checkSourceRange(name, "foo", contents); + typeBinding = name.resolveTypeBinding(); + assertNotNull(typeBinding); + + // creation method reference + statement = (VariableDeclarationStatement) statements.get(fCount++); + fragment = (VariableDeclarationFragment) statement.fragments().get(0); + expression = fragment.getInitializer(); + assertTrue(expression instanceof CreationReference); + CreationReference creationReference = (CreationReference) expression; + checkSourceRange(creationReference, "@Marker W<@Marker Integer> :: <String> new ", contents); + typeBinding = creationReference.resolveTypeBinding(); + assertNotNull(typeBinding); + methodBinding = creationReference.resolveMethodBinding(); + assertNotNull(methodBinding); + type = creationReference.getType(); + checkSourceRange(type, "@Marker W<@Marker Integer>", contents); + assertTrue(type instanceof ParameterizedType); + assertASTNodeEquals("@Marker W<@Marker Integer>", type); + typeArguments = creationReference.typeArguments(); + assertTrue(typeArguments.size() == 1); + type = (Type) typeArguments.get(0); + assertTrue(type.isSimpleType()); + checkSourceRange(type, "String", contents); + + // expression method reference + statement = (VariableDeclarationStatement) statements.get(fCount++); + fragment = (VariableDeclarationFragment) statement.fragments().get(0); + expression = fragment.getInitializer(); + assertTrue(expression instanceof ExpressionMethodReference); + ExpressionMethodReference expressionMethodReference = (ExpressionMethodReference) expression; + checkSourceRange(expressionMethodReference, "y :: foo", contents); + typeBinding = expressionMethodReference.resolveTypeBinding(); + assertNotNull(typeBinding); + methodBinding = expressionMethodReference.resolveMethodBinding(); + assertNotNull(methodBinding); + Expression lhs = expressionMethodReference.getExpression(); + checkSourceRange(lhs, "y", contents); + typeArguments = expressionMethodReference.typeArguments(); + assertTrue(typeArguments.size() == 0); + name = expressionMethodReference.getName(); + checkSourceRange(name, "foo", contents); + typeBinding = name.resolveTypeBinding(); + assertNotNull(typeBinding); + + // super method reference without qualifier + statement = (VariableDeclarationStatement) statements.get(fCount++); + fragment = (VariableDeclarationFragment) statement.fragments().get(0); + expression = fragment.getInitializer(); + assertTrue(expression instanceof SuperMethodReference); + SuperMethodReference superMethodReference = (SuperMethodReference) expression; + checkSourceRange(superMethodReference, "super :: foo", contents); + typeBinding = superMethodReference.resolveTypeBinding(); + assertNotNull(typeBinding); + methodBinding = superMethodReference.resolveMethodBinding(); + assertNotNull(methodBinding); + assertNull(superMethodReference.getQualifier()); + typeArguments = superMethodReference.typeArguments(); + assertTrue(typeArguments.size() == 0); + name = superMethodReference.getName(); + checkSourceRange(name, "foo", contents); + typeBinding = name.resolveTypeBinding(); + assertNotNull(typeBinding); + + // super method reference with qualifier + TypeDeclarationStatement typeDeclarationStatement = (TypeDeclarationStatement) statements.get(fCount); + typeDeclaration = (TypeDeclaration) typeDeclarationStatement.getDeclaration(); + method = typeDeclaration.getMethods()[0]; + statements = method.getBody().statements(); + assertTrue(statements.size() == 1); + statement = (VariableDeclarationStatement) statements.get(0); + fragment = (VariableDeclarationFragment) statement.fragments().get(0); + expression = fragment.getInitializer(); + assertTrue(expression instanceof SuperMethodReference); + superMethodReference = (SuperMethodReference) expression; + checkSourceRange(superMethodReference, "X.super :: foo", contents); + typeBinding = superMethodReference.resolveTypeBinding(); + assertNotNull(typeBinding); + methodBinding = superMethodReference.resolveMethodBinding(); + assertNotNull(methodBinding); + name = (SimpleName) superMethodReference.getQualifier(); + checkSourceRange(name, "X", contents); + typeArguments = superMethodReference.typeArguments(); + assertTrue(typeArguments.size() == 0); + name = superMethodReference.getName(); + checkSourceRange(name, "foo", contents); + typeBinding = name.resolveTypeBinding(); + assertNotNull(typeBinding); + + } + + /** * https://bugs.eclipse.org/bugs/show_bug.cgi?id=399793 * * @throws JavaModelException diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java index 4ec77591d..aedf07643 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java @@ -504,6 +504,9 @@ public class ASTMatcherTest extends org.eclipse.jdt.core.tests.junit.extension.T public boolean match(SuperMethodInvocation node, Object other) { return standardBody(node, other, this.superMatch ? super.match(node, other) : false); } + public boolean match(SuperMethodReference node, Object other) { + return standardBody(node, other, this.superMatch ? super.match(node, other) : false); + } public boolean match(SwitchCase node, Object other) { return standardBody(node, other, this.superMatch ? super.match(node, other) : false); } @@ -564,6 +567,15 @@ public class ASTMatcherTest extends org.eclipse.jdt.core.tests.junit.extension.T public boolean match(LambdaExpression node, Object other) { return standardBody(node, other, this.superMatch ? super.match(node, other) : false); } + public boolean match(CreationReference node, Object other) { + return standardBody(node, other, this.superMatch ? super.match(node, other) : false); + } + public boolean match(ExpressionMethodReference node, Object other) { + return standardBody(node, other, this.superMatch ? super.match(node, other) : false); + } + public boolean match(TypeMethodReference node, Object other) { + return standardBody(node, other, this.superMatch ? super.match(node, other) : false); + } public boolean match(IntersectionType node, Object other) { return standardBody(node, other, this.superMatch ? super.match(node, other) : false); } @@ -870,6 +882,16 @@ public class ASTMatcherTest extends org.eclipse.jdt.core.tests.junit.extension.T x1.setLabel(this.N1); basicMatch(x1); } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399794 + public void testCreationReference() { + if (this.ast.apiLevel() < AST.JLS8) { + return; + } + CreationReference x1 = this.ast.newCreationReference(); + x1.setType(this.T1); + basicMatch(x1); + } + public void testDoStatement() { DoStatement x1 = this.ast.newDoStatement(); x1.setExpression(this.E1); @@ -925,6 +947,17 @@ public class ASTMatcherTest extends org.eclipse.jdt.core.tests.junit.extension.T x1.bodyDeclarations().add(this.FD2); basicMatch(x1); } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399794 + public void testExpressionMethodReference() { + if (this.ast.apiLevel() < AST.JLS8) { + return; + } + ExpressionMethodReference x1 = this.ast.newExpressionMethodReference(); + x1.setExpression(this.E1); + x1.setName(this.N1); + basicMatch(x1); + } + public void testExpressionStatement() { ExpressionStatement x1 = this.ast.newExpressionStatement(this.E1); basicMatch(x1); @@ -1157,6 +1190,15 @@ public class ASTMatcherTest extends org.eclipse.jdt.core.tests.junit.extension.T x1.arguments().add(this.E2); basicMatch(x1); } + public void testSuperMethodReference() { + if (this.ast.apiLevel() < AST.JLS8) { + return; + } + SuperMethodReference x1 = this.ast.newSuperMethodReference(); + x1.setQualifier(this.N1); + x1.setName(this.N2); + basicMatch(x1); + } public void testSwitchCase() { SwitchCase x1 = this.ast.newSwitchCase(); x1.setExpression(this.E1); @@ -1589,6 +1631,17 @@ public class ASTMatcherTest extends org.eclipse.jdt.core.tests.junit.extension.T basicMatch(x1); } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399794 + public void testTypeMethodReference() { + if (this.ast.apiLevel() < AST.JLS8) { + return; + } + TypeMethodReference x1 = this.ast.newTypeMethodReference(); + x1.setType(this.T1); + x1.setName(this.N1); + basicMatch(x1); + } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399793 public void testLambdaExpressions1() { if (this.ast.apiLevel() < AST.JLS8) { diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java index 730c9faa1..55ae39b2f 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java @@ -358,7 +358,7 @@ public class ASTStructuralPropertyTest extends org.eclipse.jdt.core.tests.junit. maxNodeType = 84; break; case AST.JLS8: - maxNodeType = 88; + maxNodeType = 92; break; default: fail(); @@ -417,9 +417,9 @@ public class ASTStructuralPropertyTest extends org.eclipse.jdt.core.tests.junit. } // {ObjectTeams: adapted for OT specific ASTNodes /* orig: - assertEquals("Wrong last known type", 88, hi); // last known one + assertEquals("Wrong last known type", 92, hi); // last known one :giro */ - assertEquals("Wrong last known type", 103, hi); // last known one + assertEquals("Wrong last known type", 107, hi); // last known one // jwl} assertEquals("Wrong number of distinct types", hi, classes.size()); // all classes are distinct } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java index ee25c3b12..c07b2c14d 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java @@ -8795,6 +8795,10 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase ASTNode.LAMBDA_EXPRESSION, ASTNode.INTERSECTION_TYPE, ASTNode.PACKAGE_QUALIFIED_TYPE, + ASTNode.CREATION_REFERENCE, + ASTNode.EXPRESSION_METHOD_REFERENCE, + ASTNode.SUPER_METHOD_REFERENCE, + ASTNode.TYPE_METHOD_REFERENCE }; // assert that nodeType values are correct: diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java index ff0db3a21..a94cb24b8 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java @@ -712,6 +712,22 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T ASTVisitorTest.this.b.append("*/)"); //$NON-NLS-1$ } + public boolean visit(CreationReference node) { + ASTVisitorTest.this.b.append("(eCR"); //$NON-NLS-1$ + return isVisitingChildren(); + } + public void endVisit(CreationReference node) { + ASTVisitorTest.this.b.append("eCR)"); //$NON-NLS-1$ + } + + public boolean visit(ExpressionMethodReference node) { + ASTVisitorTest.this.b.append("(eEMR"); //$NON-NLS-1$ + return isVisitingChildren(); + } + public void endVisit(ExpressionMethodReference node) { + ASTVisitorTest.this.b.append("eEMR)"); //$NON-NLS-1$ + } + public boolean visit(LineComment node) { ASTVisitorTest.this.b.append("(//"); //$NON-NLS-1$ return isVisitingChildren(); @@ -892,6 +908,14 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T ASTVisitorTest.this.b.append("eSM)"); //$NON-NLS-1$ } + public boolean visit(SuperMethodReference node) { + ASTVisitorTest.this.b.append("(eSMR"); //$NON-NLS-1$ + return isVisitingChildren(); + } + public void endVisit(SuperMethodReference node) { + ASTVisitorTest.this.b.append("eSMR)"); //$NON-NLS-1$ + } + public boolean visit(SwitchCase node) { ASTVisitorTest.this.b.append("(sSC"); //$NON-NLS-1$ return isVisitingChildren(); @@ -964,6 +988,14 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T ASTVisitorTest.this.b.append("eTL)"); //$NON-NLS-1$ } + public boolean visit(TypeMethodReference node) { + ASTVisitorTest.this.b.append("(eTMR"); //$NON-NLS-1$ + return isVisitingChildren(); + } + public void endVisit(TypeMethodReference node) { + ASTVisitorTest.this.b.append("eTMR)"); //$NON-NLS-1$ + } + public boolean visit(TypeParameter node) { ASTVisitorTest.this.b.append("(tTP"); //$NON-NLS-1$ return isVisitingChildren(); @@ -1416,6 +1448,19 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T String result = this.b.toString(); assertTrue(result.equals("[(sCN"+this.N1S+"sCN)]")); //$NON-NLS-1$ //$NON-NLS-2$ } + + public void testCreationReference() { + if (this.ast.apiLevel() < AST.JLS8) + return; + CreationReference x1 = this.ast.newCreationReference(); + x1.setType(this.T1); + TestVisitor v1 = new TestVisitor(); + this.b.setLength(0); + x1.accept(v1); + String result = this.b.toString(); + assertTrue(result.equals("[(eCR"+this.T1S+"eCR)]")); //$NON-NLS-1$ //$NON-NLS-2$ + } + public void testDoStatement() { DoStatement x1 = this.ast.newDoStatement(); x1.setExpression(this.E1); @@ -1476,6 +1521,19 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T String result = this.b.toString(); assertTrue(result.equals("[(ED"+this.JD1S+this.MOD1S+this.MOD2S+this.N1S+this.T1S+this.T2S+this.EC1S+this.EC2S+this.FD1S+this.FD2S+"ED)]")); //$NON-NLS-1$ //$NON-NLS-2$ } + public void testExpressionMethodReference() { + if (this.ast.apiLevel() < AST.JLS8) + return; + ExpressionMethodReference x1 = this.ast.newExpressionMethodReference(); + x1.setExpression(this.E1); + x1.setName(this.N1); + TestVisitor v1 = new TestVisitor(); + this.b.setLength(0); + x1.accept(v1); + String result = this.b.toString(); + assertTrue(result.equals("[(eEMR"+this.E1S+this.N1S+"eEMR)]")); //$NON-NLS-1$ //$NON-NLS-2$ + } + public void testExpressionStatement() { ExpressionStatement x1 = this.ast.newExpressionStatement(this.E1); TestVisitor v1 = new TestVisitor(); @@ -2009,6 +2067,19 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T assertTrue(result.equals("[(eSM"+this.N1S+this.PT1S+this.N2S+this.E1S+this.E2S+"eSM)]")); //$NON-NLS-1$ //$NON-NLS-2$ } } + public void testSuperMethodReference() { + if (this.ast.apiLevel() < AST.JLS8) { + return; + } + SuperMethodReference x1 = this.ast.newSuperMethodReference(); + x1.setQualifier(this.N1); + x1.setName(this.N2); + TestVisitor v1 = new TestVisitor(); + this.b.setLength(0); + x1.accept(v1); + String result = this.b.toString(); + assertTrue(result.equals("[(eSMR"+this.N1S+this.N2S+"eSMR)]")); //$NON-NLS-1$ //$NON-NLS-2$ + } public void testSwitchCase() { SwitchCase x1 = this.ast.newSwitchCase(); x1.setExpression(this.E1); @@ -2155,6 +2226,19 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T String result = this.b.toString(); assertTrue(result.equals("[(eTL"+this.T1S+"eTL)]")); //$NON-NLS-1$ //$NON-NLS-2$ } + public void testTypeMethodReference() { + if (this.ast.apiLevel() < AST.JLS8) + return; + TypeMethodReference x1 = this.ast.newTypeMethodReference(); + x1.setType(this.T1); + x1.setName(this.N1); + TestVisitor v1 = new TestVisitor(); + this.b.setLength(0); + x1.accept(v1); + String result = this.b.toString(); + assertTrue(result.equals("[(eTMR"+this.T1S+this.N1S+"eTMR)]")); //$NON-NLS-1$ //$NON-NLS-2$ + } + /** @deprecated using deprecated code */ public void testSingleVariableDeclaration() { SingleVariableDeclaration x1 = this.ast.newSingleVariableDeclaration(); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java index 487ae1af4..d34297e6f 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java @@ -1060,6 +1060,8 @@ public static Test suite() { suite.addTest(new CompletionTests("testBug402812c")); suite.addTest(new CompletionTests("testBug402812d")); suite.addTest(new CompletionTests("testBug370971")); + suite.addTest(new CompletionTests("testBug406468a")); + suite.addTest(new CompletionTests("testBug406468b")); return suite; } public CompletionTests(String name) { @@ -25991,6 +25993,133 @@ public void testBug385858d() throws JavaModelException { "completion token location={CONSTRUCTOR_START}", requestor.getContext()); } +// Bug 402574 - Autocomplete does not recognize all enum constants when constants override methods +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=402574 +public void testBug402574() throws JavaModelException { + Map options = COMPLETION_PROJECT.getOptions(true); + Object savedOptionCompliance = options.get(CompilerOptions.OPTION_Source); + try { + options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7); + COMPLETION_PROJECT.setOptions(options); + this.workingCopies = new ICompilationUnit[2]; + this.workingCopies[1] = getWorkingCopy( + "/Completion/src/test/ExampleEnumNoAutocomplete.java", + "public enum ExampleEnumNoAutocomplete {\n" + + " STUFF(\"a\", \"b\") {\n" + + " @Override\n" + + " public String getProperty1() {\n"+ + " return super.getProperty1().toUpperCase();\n" + + " }\n" + + " @Override\n" + + " public String getSomething() {\n" + + " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + + " }\n" + + " },\n" + + " THINGS(\"c\", \"d\") {\n" + + " @Override\n" + + " public String getProperty1() {\n" + + " return super.getProperty2();\n" + + " }\n" + + " @Override\n" + + " public String getProperty2() {\n" + + " return super.getProperty1();\n" + + " }\n" + + " @Override\n" + + " public String getSomething() {\n" + + " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + + " }\n" + + " },\n" + + " MORE_STUFF(\"e\", \"f\") {\n" + + " @Override\n" + + " public String getProperty1() {\n" + + " return getProperty2();\n" + + " }\n" + + " @Override\n" + + " public String getSomething() {\n" + + " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + + " }\n" + + " },\n" + + " OTHER(\"g\", \"h\") {\n" + + " @Override\n" + + " public String getSomething() {\n" + + " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + + " }\n" + + " },\n" + + " STILL_OTHER(\"i\", \"j\") {\n" + + " @Override\n" + + " public String getSomething() {\n" + + " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + + " }\n" + + " },\n" + + " IT_MAY_BE_DUE_TO_MIXING_PERHAPS(\"k\", \"l\") {\n" + + " @Override\n" + + " public String getProperty1() {\n" + + " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + + " }\n" + + " @Override\n" + + " public String getProperty2() {\n" + + " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + + " }\n" + + " @Override\n" + + " public String getSomething() {\n" + + " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + + " }\n" + + " };\n" + + " private final String property1;\n" + + " private final String property2;\n" + + " ExampleEnumNoAutocomplete(final String property1, final String property2) {\n" + + " this.property1 = property1;\n" + + " this.property2 = property2;\n" + + " }\n" + + " public String getProperty1() {\n" + + " return property1;\n" + + " }\n" + + " public String getProperty2() {\n" + + " return property2;\n" + + " }\n" + + " public abstract String getSomething();\n" + + " }\n"); + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/Tester.java", + "import java.util.EnumMap;\n" + + "import java.util.Map;\n" + + "public class Tester {\n" + + " public static void main(String[] args) {\n" + + " Map<ExampleEnumNoAutocomplete, Map<String, Object>> huh = new EnumMap<ExampleEnumNoAutocomplete, Map<String, Object>>(\n" + + " ExampleEnumNoAutocomplete.class);\n" + + " huh.put(ExampleEnumNoAutocomplete.STUFF, null);\n" + + " ExampleEnumNoAutocomplete. \n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, false, false, false, true); + requestor.allowAllRequiredProposals(); + requestor.setRequireExtendedContext(true); + requestor.setComputeEnclosingElement(true); + NullProgressMonitor monitor = new NullProgressMonitor(); + String str = this.workingCopies[0].getSource(); + String completeBehind = " ExampleEnumNoAutocomplete."; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, monitor); + + assertResults( + "IT_MAY_BE_DUE_TO_MIXING_PERHAPS[FIELD_REF]{IT_MAY_BE_DUE_TO_MIXING_PERHAPS, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, IT_MAY_BE_DUE_TO_MIXING_PERHAPS, null, 26}\n" + + "MORE_STUFF[FIELD_REF]{MORE_STUFF, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, MORE_STUFF, null, 26}\n" + + "OTHER[FIELD_REF]{OTHER, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, OTHER, null, 26}\n" + + "STILL_OTHER[FIELD_REF]{STILL_OTHER, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, STILL_OTHER, null, 26}\n" + + "STUFF[FIELD_REF]{STUFF, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, STUFF, null, 26}\n" + + "THINGS[FIELD_REF]{THINGS, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, THINGS, null, 26}\n" + + "class[FIELD_REF]{class, null, Ljava.lang.Class<Ltest.ExampleEnumNoAutocomplete;>;, class, null, 26}\n" + + "valueOf[METHOD_REF]{valueOf(), Ltest.ExampleEnumNoAutocomplete;, (Ljava.lang.String;)Ltest.ExampleEnumNoAutocomplete;, valueOf, (arg0), 26}\n" + + "values[METHOD_REF]{values(), Ltest.ExampleEnumNoAutocomplete;, ()[Ltest.ExampleEnumNoAutocomplete;, values, null, 26}", + requestor.getResults()); + assertEquals(false, + requestor.canUseDiamond(0)); + } finally { + // Restore compliance settings. + options.put(CompilerOptions.OPTION_Source, savedOptionCompliance); + COMPLETION_PROJECT.setOptions(options); + } +} //https://bugs.eclipse.org/bugs/show_bug.cgi?id=402812 //Bug 402812 - [1.8][completion] Code Completion problems with static/default interface methods. public void testBug402812a() throws Exception { @@ -26211,103 +26340,27 @@ public void testBug402812d() throws Exception { COMPLETION_PROJECT.setOptions(completionProjectOptions); } } -// Bug 402574 - Autocomplete does not recognize all enum constants when constants override methods -// https://bugs.eclipse.org/bugs/show_bug.cgi?id=402574 -public void testBug402574() throws JavaModelException { +//Bug 370971 - Content Assist autocomplete broken within an array of anonymous classes instances +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=370971 +public void testBug370971() throws JavaModelException { Map options = COMPLETION_PROJECT.getOptions(true); Object savedOptionCompliance = options.get(CompilerOptions.OPTION_Source); try { options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7); COMPLETION_PROJECT.setOptions(options); - this.workingCopies = new ICompilationUnit[2]; - this.workingCopies[1] = getWorkingCopy( - "/Completion/src/test/ExampleEnumNoAutocomplete.java", - "public enum ExampleEnumNoAutocomplete {\n" + - " STUFF(\"a\", \"b\") {\n" + - " @Override\n" + - " public String getProperty1() {\n"+ - " return super.getProperty1().toUpperCase();\n" + - " }\n" + - " @Override\n" + - " public String getSomething() {\n" + - " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + - " }\n" + - " },\n" + - " THINGS(\"c\", \"d\") {\n" + - " @Override\n" + - " public String getProperty1() {\n" + - " return super.getProperty2();\n" + - " }\n" + - " @Override\n" + - " public String getProperty2() {\n" + - " return super.getProperty1();\n" + - " }\n" + - " @Override\n" + - " public String getSomething() {\n" + - " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + - " }\n" + - " },\n" + - " MORE_STUFF(\"e\", \"f\") {\n" + - " @Override\n" + - " public String getProperty1() {\n" + - " return getProperty2();\n" + - " }\n" + - " @Override\n" + - " public String getSomething() {\n" + - " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + - " }\n" + - " },\n" + - " OTHER(\"g\", \"h\") {\n" + - " @Override\n" + - " public String getSomething() {\n" + - " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + - " }\n" + - " },\n" + - " STILL_OTHER(\"i\", \"j\") {\n" + - " @Override\n" + - " public String getSomething() {\n" + - " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + - " }\n" + - " },\n" + - " IT_MAY_BE_DUE_TO_MIXING_PERHAPS(\"k\", \"l\") {\n" + - " @Override\n" + - " public String getProperty1() {\n" + - " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + - " }\n" + - " @Override\n" + - " public String getProperty2() {\n" + - " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + - " }\n" + - " @Override\n" + - " public String getSomething() {\n" + - " throw new UnsupportedOperationException(\"What is this, I don't even?!\");\n" + - " }\n" + - " };\n" + - " private final String property1;\n" + - " private final String property2;\n" + - " ExampleEnumNoAutocomplete(final String property1, final String property2) {\n" + - " this.property1 = property1;\n" + - " this.property2 = property2;\n" + - " }\n" + - " public String getProperty1() {\n" + - " return property1;\n" + - " }\n" + - " public String getProperty2() {\n" + - " return property2;\n" + - " }\n" + - " public abstract String getSomething();\n" + - " }\n"); + this.workingCopies = new ICompilationUnit[1]; this.workingCopies[0] = getWorkingCopy( - "/Completion/src/test/Tester.java", - "import java.util.EnumMap;\n" + - "import java.util.Map;\n" + - "public class Tester {\n" + - " public static void main(String[] args) {\n" + - " Map<ExampleEnumNoAutocomplete, Map<String, Object>> huh = new EnumMap<ExampleEnumNoAutocomplete, Map<String, Object>>(\n" + - " ExampleEnumNoAutocomplete.class);\n" + - " huh.put(ExampleEnumNoAutocomplete.STUFF, null);\n" + - " ExampleEnumNoAutocomplete. \n" + - " }\n" + + "/Completion/src/test/ExampleEnumNoAutocomplete.java", + "public class X {\n" + + " private Object[] items = new Object[] {\n" + + " new Object() {\n" + + " @Override\n" + + " public String toString() {\n" + + " return super.toS;\n" + + " }\n" + + " },\n" + + " new Object() { }\n" + + " } ;\n" + "}\n"); CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, false, false, false, true); requestor.allowAllRequiredProposals(); @@ -26315,20 +26368,12 @@ public void testBug402574() throws JavaModelException { requestor.setComputeEnclosingElement(true); NullProgressMonitor monitor = new NullProgressMonitor(); String str = this.workingCopies[0].getSource(); - String completeBehind = " ExampleEnumNoAutocomplete."; + String completeBehind = "return super.toS"; int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, monitor); assertResults( - "IT_MAY_BE_DUE_TO_MIXING_PERHAPS[FIELD_REF]{IT_MAY_BE_DUE_TO_MIXING_PERHAPS, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, IT_MAY_BE_DUE_TO_MIXING_PERHAPS, null, 26}\n" + - "MORE_STUFF[FIELD_REF]{MORE_STUFF, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, MORE_STUFF, null, 26}\n" + - "OTHER[FIELD_REF]{OTHER, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, OTHER, null, 26}\n" + - "STILL_OTHER[FIELD_REF]{STILL_OTHER, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, STILL_OTHER, null, 26}\n" + - "STUFF[FIELD_REF]{STUFF, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, STUFF, null, 26}\n" + - "THINGS[FIELD_REF]{THINGS, Ltest.ExampleEnumNoAutocomplete;, Ltest.ExampleEnumNoAutocomplete;, THINGS, null, 26}\n" + - "class[FIELD_REF]{class, null, Ljava.lang.Class<Ltest.ExampleEnumNoAutocomplete;>;, class, null, 26}\n" + - "valueOf[METHOD_REF]{valueOf(), Ltest.ExampleEnumNoAutocomplete;, (Ljava.lang.String;)Ltest.ExampleEnumNoAutocomplete;, valueOf, (arg0), 26}\n" + - "values[METHOD_REF]{values(), Ltest.ExampleEnumNoAutocomplete;, ()[Ltest.ExampleEnumNoAutocomplete;, values, null, 26}", + "toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 65}", requestor.getResults()); assertEquals(false, requestor.canUseDiamond(0)); @@ -26338,4 +26383,91 @@ public void testBug402574() throws JavaModelException { COMPLETION_PROJECT.setOptions(options); } } +// Bug 406468 - [1.8][code assist] No completion proposals after the use of a constructor reference +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=406468 +public void testBug406468a() throws JavaModelException { + Map options = COMPLETION_PROJECT.getOptions(true); + Object savedOptionCompliance = options.get(CompilerOptions.OPTION_Compliance); + Object savedOptionSource = options.get(CompilerOptions.OPTION_Source); + try { + options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8); + options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8); + COMPLETION_PROJECT.setOptions(options); + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/X.java", + "interface I {\n" + + " X [][][] copy (int x);\n" + + "}\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " I i = X[][][]::new;\n" + + " X[][][] x = i.copy(136);\n" + + " System.out.println(x.length);\n" + + " \n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + String str = this.workingCopies[0].getSource(); + String completeBehind = "System.out.println(x.length);"; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + assertResults( + "I[TYPE_REF]{I, test, Ltest.I;, null, null, 27}\n" + + "X[TYPE_REF]{X, test, Ltest.X;, null, null, 27}\n" + + "args[LOCAL_VARIABLE_REF]{args, null, [Ljava.lang.String;, args, null, 27}\n" + + "i[LOCAL_VARIABLE_REF]{i, null, Ltest.I;, i, null, 27}\n" + + "main[METHOD_REF]{main(), Ltest.X;, ([Ljava.lang.String;)V, main, (args), 27}\n" + + "x[LOCAL_VARIABLE_REF]{x, null, [[[Ltest.X;, x, null, 27}", + requestor.getResults()); + } finally { + // Restore compliance settings. + options.put(CompilerOptions.OPTION_Compliance, savedOptionCompliance); + options.put(CompilerOptions.OPTION_Source, savedOptionSource); + COMPLETION_PROJECT.setOptions(options); + } +} +public void testBug406468b() throws JavaModelException { + Map options = COMPLETION_PROJECT.getOptions(true); + Object savedOptionCompliance = options.get(CompilerOptions.OPTION_Compliance); + Object savedOptionSource = options.get(CompilerOptions.OPTION_Source); + try { + options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8); + options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8); + COMPLETION_PROJECT.setOptions(options); + this.workingCopies = new ICompilationUnit[1]; + this.workingCopies[0] = getWorkingCopy( + "/Completion/src/test/X.java", + "interface I {\n" + + " X<java.lang.String> copy ();\n" + + "}\n" + + "public class X<S> {\n" + + " public static void main(String[] args) {\n" + + " I i = X<java.lang.String>::new;\n" + + " X x = i.copy();\n" + + " System.out.println(x);\n" + + " \n" + + " }\n" + + "}\n"); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true); + String str = this.workingCopies[0].getSource(); + String completeBehind = "System.out.println(x);"; + int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); + this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner); + assertResults( + "I[TYPE_REF]{I, test, Ltest.I;, null, null, 27}\n" + + "S[TYPE_REF]{S, null, TS;, null, null, 27}\n" + + "X<S>[TYPE_REF]{X, test, Ltest.X<TS;>;, null, null, 27}\n" + + "args[LOCAL_VARIABLE_REF]{args, null, [Ljava.lang.String;, args, null, 27}\n" + + "i[LOCAL_VARIABLE_REF]{i, null, Ltest.I;, i, null, 27}\n" + + "main[METHOD_REF]{main(), Ltest.X<TS;>;, ([Ljava.lang.String;)V, main, (args), 27}\n" + + "x[LOCAL_VARIABLE_REF]{x, null, Ltest.X;, x, null, 27}", + requestor.getResults()); + } finally { + // Restore compliance settings. + options.put(CompilerOptions.OPTION_Compliance, savedOptionCompliance); + options.put(CompilerOptions.OPTION_Source, savedOptionSource); + COMPLETION_PROJECT.setOptions(options); + } +} } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeAnnotationsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeAnnotationsTest.java index 56d7886ba..cea9d59c8 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeAnnotationsTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingTypeAnnotationsTest.java @@ -947,7 +947,7 @@ public class ASTRewritingTypeAnnotationsTest extends ASTRewritingTest { " * @param arg \n" + " */\n" + " test406469.bug.@Marker IOException foo(\n" + - " FileNotFoundException arg)\n" + + " test406469.bug.FileNotFoundException arg)\n" + " throws test406469.bug.@NonNull @Marker EOFException {\n" + " try {\n" + " test406469.bug.@NonNull IOError e = new test406469.bug.@Marker IOError();\n" + @@ -972,4 +972,103 @@ public class ASTRewritingTypeAnnotationsTest extends ASTRewritingTest { assertEqualString(preview, contentsmodified); } + /** + * ASTRewriterTests for QualifiedType + * @throws Exception + * + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=407364 + */ + public void testQualifiedTypeAnnotations() throws Exception { + IPackageFragment pack1= this.sourceFolder.createPackageFragment("test407364.bug", false, null); + String contents = "package test0002;\n" + + "import java.lang.annotation.Target;\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " Outer outer = new Outer();\n" + + " Outer.@Marker1 Inner first = outer.new Inner();\n" + + " Outer.@Marker2 Inner second = outer.new Inner() ;\n" + + " Outer.Inner.@Marker1 Deeper deeper = second.new Deeper();\n" + + " Outer.Inner.Deeper deeper2 = second.new Deeper();\n" + + " }\n" + "}\n" + "class Outer {\n" + + " public class Inner {\n" + + " public class Deeper {\n" + + " }\n" + + " }\n" + + "}\n" + + "@Target (java.lang.annotation.ElementType.TYPE_USE)\n" + + "@interface Marker {}\n" + + "@Target (java.lang.annotation.ElementType.TYPE_USE)\n" + + "@interface Marker1 {}\n" + + "@Target (java.lang.annotation.ElementType.TYPE_USE)\n" + + "@interface Marker2 {}\n"; + + StringBuffer buf = new StringBuffer(contents); + ICompilationUnit cu= pack1.createCompilationUnit("X.java", buf.toString(), false, null); + CompilationUnit astRoot= createAST(cu, /* resolve */ true, false); + ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST()); + AST ast= astRoot.getAST(); + TypeDeclaration typeDeclaration= findTypeDeclaration(astRoot, "X"); + MethodDeclaration methodDeclaration= findMethodDeclaration(typeDeclaration, "main"); + List statements = methodDeclaration.getBody().statements(); + int sCount = 1; + + { //replace an annotation. + VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) statements.get(sCount++); + QualifiedType qualifiedType = (QualifiedType) variableDeclarationStatement.getType(); + MarkerAnnotation markerAnnotation= ast.newMarkerAnnotation(); + markerAnnotation.setTypeName(ast.newSimpleName("NewMarker")); + rewrite.replace((ASTNode) qualifiedType.annotations().get(0), markerAnnotation, null); + + // remove an annotation + variableDeclarationStatement = (VariableDeclarationStatement) statements.get(sCount++); + qualifiedType = (QualifiedType) variableDeclarationStatement.getType(); + rewrite.remove((ASTNode) qualifiedType.annotations().get(0), null); + + // insert an annotation after an existing annotation + variableDeclarationStatement = (VariableDeclarationStatement) statements.get(sCount++); + qualifiedType = (QualifiedType) variableDeclarationStatement.getType(); + markerAnnotation= ast.newMarkerAnnotation(); + markerAnnotation.setTypeName(ast.newSimpleName("NewMarker")); + rewrite.getListRewrite(qualifiedType, QualifiedType.ANNOTATIONS_PROPERTY).insertLast(markerAnnotation, null); + + /* insert an annotation in a type not converted as QualifiedType. This would involve + * creation of a QualifiedType from fields of the existing type. + */ + variableDeclarationStatement = (VariableDeclarationStatement) statements.get(sCount++); + SimpleType simpleType = (SimpleType) variableDeclarationStatement.getType(); + QualifiedName qualifiedName = (QualifiedName) simpleType.getName(); + SimpleName simpleName = ast.newSimpleName(qualifiedName.getName().getIdentifier()); + qualifiedName = (QualifiedName) qualifiedName.getQualifier(); + qualifiedName = ast.newQualifiedName(ast.newName(qualifiedName.getQualifier().toString()), ast.newSimpleName(qualifiedName.getName().toString())); + qualifiedType = ast.newQualifiedType(ast.newSimpleType(qualifiedName), simpleName); + + markerAnnotation= ast.newMarkerAnnotation(); + markerAnnotation.setTypeName(ast.newSimpleName("NewMarker")); + rewrite.getListRewrite(qualifiedType, QualifiedType.ANNOTATIONS_PROPERTY).insertLast(markerAnnotation, null); + rewrite.replace(variableDeclarationStatement.getType(), qualifiedType, null); + } + String preview= evaluateRewrite(cu, rewrite); + String contentsmodified = "package test0002;\n" + + "import java.lang.annotation.Target;\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " Outer outer = new Outer();\n" + + " Outer.@NewMarker Inner first = outer.new Inner();\n" + + " Outer.Inner second = outer.new Inner() ;\n" + + " Outer.Inner.@Marker1 @NewMarker Deeper deeper = second.new Deeper();\n" + + " Outer. Inner.@NewMarker Deeper deeper2 = second.new Deeper();\n" + + " }\n" + "}\n" + "class Outer {\n" + + " public class Inner {\n" + + " public class Deeper {\n" + + " }\n" + + " }\n" + + "}\n" + + "@Target (java.lang.annotation.ElementType.TYPE_USE)\n" + + "@interface Marker {}\n" + + "@Target (java.lang.annotation.ElementType.TYPE_USE)\n" + + "@interface Marker1 {}\n" + + "@Target (java.lang.annotation.ElementType.TYPE_USE)\n" + + "@interface Marker2 {}\n"; + assertEqualString(preview, contentsmodified); + } }
\ No newline at end of file diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java index bb9a271a1..2e06bda94 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java @@ -196,6 +196,7 @@ public class CompletionParser extends AssistParser { private boolean storeSourceEnds; public HashtableOfObjectToInt sourceEnds; + private boolean inReferenceExpression; public CompletionParser(ProblemReporter problemReporter, boolean storeExtraSourceEnds) { super(problemReporter); @@ -3902,7 +3903,12 @@ protected void consumeToken(int token) { break; } break; + case TokenNameCOLON_COLON: + this.inReferenceExpression = true; + break; case TokenNameIdentifier: + if (this.inReferenceExpression) + break; if (previous == TokenNameDOT) { // e.g. foo().[fred]() if (this.invocationType != SUPER_RECEIVER // e.g. not super.[fred]() //{ObjectTeams: base: @@ -3931,6 +3937,8 @@ protected void consumeToken(int token) { } break; case TokenNamenew: + if (this.inReferenceExpression) + break; pushOnElementStack(K_BETWEEN_NEW_AND_LEFT_BRACKET); this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed if (previous == TokenNameDOT) { // e.g. fred().[new] X() @@ -4374,6 +4382,10 @@ protected void consumeToken(int token) { } } } +protected void consumeIdentifierOrNew(boolean newForm) { + this.inReferenceExpression = false; + super.consumeIdentifierOrNew(newForm); +} protected void consumeOnlySynchronized() { super.consumeOnlySynchronized(); this.hasUnusedModifiers = false; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java index ab883e0d0..b1e59181e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java @@ -15,6 +15,8 @@ * Technical University Berlin - extended API and implementation * Jesper S Moller - Contributions for * Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335 + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.compiler; @@ -28,7 +30,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.Stack; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; @@ -48,15 +49,13 @@ import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; -import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; +import org.eclipse.jdt.internal.compiler.ast.Receiver; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeParameter; import org.eclipse.jdt.internal.compiler.ast.TypeReference; -import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.AnnotationContext; import org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants; @@ -64,19 +63,19 @@ import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel; +import org.eclipse.jdt.internal.compiler.codegen.MultiCatchExceptionLabel; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrame; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream; import org.eclipse.jdt.internal.compiler.codegen.TypeAnnotationCodeStream; -import org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.ExceptionMarker; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackDepthMarker; import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackMarker; +import org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.impl.StringConstant; import org.eclipse.jdt.internal.compiler.lookup.Binding; -import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; @@ -287,75 +286,6 @@ public class ClassFile implements TypeConstants, TypeIds { LookupEnvironment env = typeBinding.scope.environment(); return env.classFilePool.acquire(typeBinding); } - - /** - * Return the location for the corresponding annotation inside the type reference, <code>null</code> if none. - */ - private static int[] getWildcardLocations(TypeReference reference, Wildcard wildcard) { - class LocationCollector extends ASTVisitor { - Stack currentIndexes; - boolean search = true; - Wildcard currentWildcard; - - public LocationCollector(Wildcard currentWildcard) { - this.currentIndexes = new Stack(); - this.currentWildcard = currentWildcard; - } - public boolean visit(ParameterizedSingleTypeReference typeReference, BlockScope scope) { - if (!this.search) return false; - TypeReference[] typeReferences = typeReference.typeArguments; - this.currentIndexes.push(new Integer(0)); - for (int i = 0, max = typeReferences.length; i < max; i++) { - typeReferences[i].traverse(this, scope); - if (!this.search) return false; - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); - } - this.currentIndexes.pop(); - return true; - } - public boolean visit(ParameterizedQualifiedTypeReference typeReference, BlockScope scope) { - if (!this.search) return false; - TypeReference[] typeReferences = typeReference.typeArguments[typeReference.typeArguments.length - 1]; - this.currentIndexes.push(new Integer(0)); - for (int i = 0, max = typeReferences.length; i < max; i++) { - typeReferences[i].traverse(this, scope); - if (!this.search) return false; - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); - } - this.currentIndexes.pop(); - return true; - } - public boolean visit(Wildcard typeReference, BlockScope scope) { - if (!this.search) return false; - if (typeReference.equals(this.currentWildcard)) { - this.search = false; - } - return true; - } - public String toString() { - StringBuffer buffer = new StringBuffer(); - buffer - .append("search location for ") //$NON-NLS-1$ - .append(this.currentWildcard) - .append("\ncurrent indexes : ") //$NON-NLS-1$ - .append(this.currentIndexes); - return String.valueOf(buffer); - } - } - if (reference == null) return null; - LocationCollector collector = new LocationCollector(wildcard); - reference.traverse(collector, (BlockScope) null); - if (collector.currentIndexes.isEmpty()) { - return null; - } - int size = collector.currentIndexes.size(); - int[] result = new int[size]; - for (int i = 0; i < size; i++) { - result[size - i - 1] = ((Integer) collector.currentIndexes.pop()).intValue(); - } - return result; - } - /** * INTERNAL USE-ONLY * This methods creates a new instance of the receiver. @@ -374,7 +304,7 @@ public class ClassFile implements TypeConstants, TypeIds { this.isNestedType = typeBinding.isNestedType(); if (this.targetJDK >= ClassFileConstants.JDK1_6) { this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; - if (this.targetJDK >= ClassFileConstants.JDK1_7) { + if (this.targetJDK >= ClassFileConstants.JDK1_8) { this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION; this.codeStream = new TypeAnnotationCodeStream(this); } else { @@ -525,6 +455,7 @@ public class ClassFile implements TypeConstants, TypeIds { } attributesNumber += generateTypeAnnotationAttributeForTypeDeclaration(); + // update the number of attributes if (attributeOffset + 2 >= this.contents.length) { resizeContents(2); @@ -579,41 +510,40 @@ public class ClassFile implements TypeConstants, TypeIds { FieldDeclaration fieldDeclaration = fieldBinding.sourceField(); if (fieldDeclaration != null) { Annotation[] annotations = fieldDeclaration.annotations; - List allTypeAnnotationContexts = new ArrayList(); - int invisibleTypeAnnotationsCounter = 0; - int visibleTypeAnnotationsCounter = 0; if (annotations != null) { attributesNumber += generateRuntimeAnnotations(annotations); - if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { - if ((fieldDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) { - fieldDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts); - } - } } - TypeReference fieldType = fieldDeclaration.type; - if (fieldType != null - && ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) - && ((fieldType.bits & ASTNode.HasTypeAnnotations) != 0)) { - fieldType.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts); - } - int size = allTypeAnnotationContexts.size(); - if (size != 0) { - AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size]; - allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray); - for (int i = 0, max = allTypeAnnotationContextsArray.length; i < max; i++) { - AnnotationContext annotationContext = allTypeAnnotationContextsArray[i]; - if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { - invisibleTypeAnnotationsCounter++; - allTypeAnnotationContexts.add(annotationContext); - } else { - visibleTypeAnnotationsCounter++; - allTypeAnnotationContexts.add(annotationContext); + + if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { + List allTypeAnnotationContexts = new ArrayList(); + if (annotations != null && (fieldDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) { + fieldDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts); + } + int invisibleTypeAnnotationsCounter = 0; + int visibleTypeAnnotationsCounter = 0; + TypeReference fieldType = fieldDeclaration.type; + if (fieldType != null && ((fieldType.bits & ASTNode.HasTypeAnnotations) != 0)) { + fieldType.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts); + } + int size = allTypeAnnotationContexts.size(); + if (size != 0) { + AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size]; + allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray); + for (int i = 0, max = allTypeAnnotationContextsArray.length; i < max; i++) { + AnnotationContext annotationContext = allTypeAnnotationContextsArray[i]; + if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { + invisibleTypeAnnotationsCounter++; + allTypeAnnotationContexts.add(annotationContext); + } else { + visibleTypeAnnotationsCounter++; + allTypeAnnotationContexts.add(annotationContext); + } } + attributesNumber += generateRuntimeTypeAnnotations( + allTypeAnnotationContextsArray, + visibleTypeAnnotationsCounter, + invisibleTypeAnnotationsCounter); } - attributesNumber += generateRuntimeTypeAnnotations( - allTypeAnnotationContextsArray, - visibleTypeAnnotationsCounter, - invisibleTypeAnnotationsCounter); } } } @@ -1523,6 +1453,10 @@ public class ClassFile implements TypeConstants, TypeIds { max_locals, false); } + + if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { + attributesNumber += generateTypeAnnotationsOnCodeAttribute(); + } this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; @@ -1534,6 +1468,62 @@ public class ClassFile implements TypeConstants, TypeIds { this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8); this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength; } + + public int generateTypeAnnotationsOnCodeAttribute() { + int attributesNumber = 0; + + List allTypeAnnotationContexts = ((TypeAnnotationCodeStream) this.codeStream).allTypeAnnotationContexts; + int invisibleTypeAnnotationsCounter = 0; + int visibleTypeAnnotationsCounter = 0; + + for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { + LocalVariableBinding localVariable = this.codeStream.locals[i]; + if (localVariable.isCatchParameter()) continue; + LocalDeclaration declaration = localVariable.declaration; + if (declaration == null + || (declaration.isArgument() && ((declaration.bits & ASTNode.IsUnionType) == 0)) + || (localVariable.initializationCount == 0) + || ((declaration.bits & ASTNode.HasTypeAnnotations) == 0)) { + continue; + } + int targetType = ((localVariable.tagBits & TagBits.IsResource) == 0) ? AnnotationTargetTypeConstants.LOCAL_VARIABLE : AnnotationTargetTypeConstants.RESOURCE_VARIABLE; + declaration.getAllAnnotationContexts(targetType, localVariable, allTypeAnnotationContexts); + } + + ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels; + int tableIndex = 0; + for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { + ExceptionLabel exceptionLabel = exceptionLabels[i]; + if (exceptionLabel instanceof MultiCatchExceptionLabel) { + MultiCatchExceptionLabel multiCatchExceptionLabel = (MultiCatchExceptionLabel)exceptionLabel; + tableIndex += multiCatchExceptionLabel.getAllAnnotationContexts(tableIndex, allTypeAnnotationContexts); + } else { + if (exceptionLabel.exceptionTypeReference != null) { // ignore those which cannot be annotated + exceptionLabel.exceptionTypeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.EXCEPTION_PARAMETER, tableIndex, allTypeAnnotationContexts); + } + tableIndex++; + } + } + + int size = allTypeAnnotationContexts.size(); + if (size != 0) { + AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size]; + allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray); + for (int j = 0, max2 = allTypeAnnotationContextsArray.length; j < max2; j++) { + AnnotationContext annotationContext = allTypeAnnotationContextsArray[j]; + if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { + invisibleTypeAnnotationsCounter++; + } else { + visibleTypeAnnotationsCounter++; + } + } + attributesNumber += generateRuntimeTypeAnnotations( + allTypeAnnotationContextsArray, + visibleTypeAnnotationsCounter, + invisibleTypeAnnotationsCounter); + } + return attributesNumber; + } /** * INTERNAL USE-ONLY @@ -2168,22 +2158,11 @@ public class ClassFile implements TypeConstants, TypeIds { MethodBinding binding, int methodAttributeOffset, int attributesNumber) { - + if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { - List allTypeAnnotationContexts = ((TypeAnnotationCodeStream) this.codeStream).allTypeAnnotationContexts; + List allTypeAnnotationContexts = new ArrayList(); int invisibleTypeAnnotationsCounter = 0; int visibleTypeAnnotationsCounter = 0; - for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { - LocalVariableBinding localVariable = this.codeStream.locals[i]; - LocalDeclaration declaration = localVariable.declaration; - if (declaration == null - || (declaration.isArgument() && ((declaration.bits & ASTNode.IsUnionType) == 0)) - || (localVariable.initializationCount == 0) - || ((declaration.bits & ASTNode.HasTypeAnnotations) == 0)) { - continue; - } - declaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.LOCAL_VARIABLE, localVariable, allTypeAnnotationContexts); - } AbstractMethodDeclaration methodDeclaration = binding.sourceMethod(); if (methodDeclaration != null) { if ((methodDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) { @@ -2192,37 +2171,24 @@ public class ClassFile implements TypeConstants, TypeIds { for (int i = 0, max = arguments.length; i < max; i++) { Argument argument = arguments[i]; if ((argument.bits & ASTNode.HasTypeAnnotations) != 0) { - argument.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_PARAMETER, i, allTypeAnnotationContexts); + argument.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER, i, allTypeAnnotationContexts); } } } - Annotation[] annotations = (methodDeclaration.receiver==null?null:methodDeclaration.receiver.annotations); - if (annotations != null) { - for (int i = 0, max = annotations.length; i < max; i++) { - Annotation annotation = annotations[i]; - AnnotationContext annotationContext = null; - if (annotation.isRuntimeTypeInvisible()) { - annotationContext = new AnnotationContext(annotation, null, AnnotationTargetTypeConstants.METHOD_RECEIVER, null, AnnotationContext.INVISIBLE, null); - invisibleTypeAnnotationsCounter++; - } else if (annotation.isRuntimeTypeVisible()) { - annotationContext = new AnnotationContext(annotation, null, AnnotationTargetTypeConstants.METHOD_RECEIVER, null, AnnotationContext.VISIBLE, null); - visibleTypeAnnotationsCounter++; - } - if (annotationContext != null) { - allTypeAnnotationContexts.add(annotationContext); - } - } + Receiver receiver = methodDeclaration.receiver; + if (receiver != null && (receiver.type.bits & ASTNode.HasTypeAnnotations) != 0) { + receiver.type.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RECEIVER, allTypeAnnotationContexts); } } Annotation[] annotations = methodDeclaration.annotations; if (annotations != null && binding.returnType.id != T_void) { - methodDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN_TYPE, allTypeAnnotationContexts); + methodDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN, allTypeAnnotationContexts); } if (!methodDeclaration.isConstructor() && !methodDeclaration.isClinit() && binding.returnType.id != T_void) { MethodDeclaration declaration = (MethodDeclaration) methodDeclaration; TypeReference typeReference = declaration.returnType; if ((typeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - typeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN_TYPE, allTypeAnnotationContexts); + typeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN, allTypeAnnotationContexts); } } TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions; @@ -2260,21 +2226,24 @@ public class ClassFile implements TypeConstants, TypeIds { invisibleTypeAnnotationsCounter); } } - // update the number of attributes this.contents[methodAttributeOffset++] = (byte) (attributesNumber >> 8); this.contents[methodAttributeOffset] = (byte) attributesNumber; } - + private void dumpLocations(int[] locations) { - if (locations != null) { + if (locations == null) { + // no type path + if (this.contentsOffset + 1 >= this.contents.length) { + resizeContents(1); + } + this.contents[this.contentsOffset++] = (byte) 0; + } else { int length = locations.length; - int actualSize = 2 + length; - if (this.contentsOffset + actualSize >= this.contents.length) { - resizeContents(actualSize); + if (this.contentsOffset + length >= this.contents.length) { + resizeContents(length + 1); } - this.contents[this.contentsOffset++] = (byte) (length >> 8); - this.contents[this.contentsOffset++] = (byte) length; + this.contents[this.contentsOffset++] = (byte) (locations.length / 2); for (int i = 0; i < length; i++) { this.contents[this.contentsOffset++] = (byte) locations[i]; } @@ -2282,22 +2251,67 @@ public class ClassFile implements TypeConstants, TypeIds { } private void dumpTargetTypeContents(int targetType, AnnotationContext annotationContext) { switch(targetType) { - case AnnotationTargetTypeConstants.THROWS : - case AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS : - case AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY : - case AnnotationTargetTypeConstants.OBJECT_CREATION : - case AnnotationTargetTypeConstants.OBJECT_CREATION_GENERIC_OR_ARRAY : - case AnnotationTargetTypeConstants.CLASS_LITERAL : - case AnnotationTargetTypeConstants.CLASS_LITERAL_GENERIC_OR_ARRAY : - case AnnotationTargetTypeConstants.TYPE_INSTANCEOF : - case AnnotationTargetTypeConstants.TYPE_INSTANCEOF_GENERIC_OR_ARRAY : - case AnnotationTargetTypeConstants.TYPE_CAST : - case AnnotationTargetTypeConstants.TYPE_CAST_GENERIC_OR_ARRAY : + case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER : + case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER : + // parameter index + this.contents[this.contentsOffset++] = (byte) annotationContext.info; + break; + + case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : + // type_parameter_index + this.contents[this.contentsOffset++] = (byte) annotationContext.info; + // bound_index + this.contents[this.contentsOffset++] = (byte) annotationContext.info2; + break; + case AnnotationTargetTypeConstants.FIELD : + case AnnotationTargetTypeConstants.METHOD_RECEIVER : + case AnnotationTargetTypeConstants.METHOD_RETURN : + // target_info is empty_target + break; + case AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER : + // target_info is parameter index + this.contents[this.contentsOffset++] = (byte) annotationContext.info; + break; + + case AnnotationTargetTypeConstants.INSTANCEOF : + case AnnotationTargetTypeConstants.NEW : + case AnnotationTargetTypeConstants.EXCEPTION_PARAMETER : + case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE : + case AnnotationTargetTypeConstants.METHOD_REFERENCE : + // bytecode offset for new/instanceof/method_reference + // exception table entry index for exception_parameter + this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); + this.contents[this.contentsOffset++] = (byte) annotationContext.info; + break; + case AnnotationTargetTypeConstants.CAST : + // bytecode offset + this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); + this.contents[this.contentsOffset++] = (byte) annotationContext.info; + // type_argument_index not set for cast + this.contents[this.contentsOffset++] = (byte)0; + break; + + case AnnotationTargetTypeConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : + case AnnotationTargetTypeConstants.METHOD_INVOCATION_TYPE_ARGUMENT : + case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : + case AnnotationTargetTypeConstants.METHOD_REFERENCE_TYPE_ARGUMENT : + // bytecode offset + this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); + this.contents[this.contentsOffset++] = (byte) annotationContext.info; + // type_argument_index + this.contents[this.contentsOffset++] = (byte) annotationContext.info2; + break; + + case AnnotationTargetTypeConstants.CLASS_EXTENDS : + case AnnotationTargetTypeConstants.THROWS : + // For CLASS_EXTENDS - info is supertype index (-1 = superclass) + // For THROWS - info is exception table index this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); this.contents[this.contentsOffset++] = (byte) annotationContext.info; break; + case AnnotationTargetTypeConstants.LOCAL_VARIABLE : - case AnnotationTargetTypeConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY : + case AnnotationTargetTypeConstants.RESOURCE_VARIABLE : int localVariableTableOffset = this.contentsOffset; LocalVariableBinding localVariable = annotationContext.variableBinding; int actualSize = 0; @@ -2328,40 +2342,15 @@ public class ClassFile implements TypeConstants, TypeIds { this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8); this.contents[localVariableTableOffset] = (byte) numberOfEntries; break; - case AnnotationTargetTypeConstants.METHOD_PARAMETER : - case AnnotationTargetTypeConstants.METHOD_PARAMETER_GENERIC_OR_ARRAY : - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - break; - // nothing to do - // case AnnotationTargetTypeConstants.METHOD_RECEIVER : - // case AnnotationTargetTypeConstants.METHOD_RECEIVER_GENERIC_OR_ARRAY : - // break; - // case AnnotationTargetTypeConstants.FIELD : - // case AnnotationTargetTypeConstants.FIELD_GENERIC_OR_ARRAY : - // break; - case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER : - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER : - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - break; case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND : - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : - case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY : - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY : this.contents[this.contentsOffset++] = (byte) annotationContext.info; this.contents[this.contentsOffset++] = (byte) annotationContext.info2; break; - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL : - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY : - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL : - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY : - // offset - this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - // type index - this.contents[this.contentsOffset++] = (byte) annotationContext.info2; } } + + /** * INTERNAL USE-ONLY * This methods returns a char[] representing the file name of the receiver @@ -3762,13 +3751,17 @@ public class ClassFile implements TypeConstants, TypeIds { } return attributesNumber; } + /** * @param annotationContexts the given annotation contexts * @param visibleTypeAnnotationsNumber the given number of visible type annotations * @param invisibleTypeAnnotationsNumber the given number of invisible type annotations * @return the number of attributes created while dumping the annotations in the .class file */ - private int generateRuntimeTypeAnnotations(final AnnotationContext[] annotationContexts, int visibleTypeAnnotationsNumber, int invisibleTypeAnnotationsNumber) { + private int generateRuntimeTypeAnnotations( + final AnnotationContext[] annotationContexts, + int visibleTypeAnnotationsNumber, + int invisibleTypeAnnotationsNumber) { int attributesNumber = 0; final int length = annotationContexts.length; @@ -4467,175 +4460,52 @@ public class ClassFile implements TypeConstants, TypeIds { this.contentsOffset = localContentsOffset; return 1; } - + private void generateTypeAnnotation(AnnotationContext annotationContext, int currentOffset) { - int targetType = annotationContext.targetType; if (annotationContext.wildcard != null) { - generateWilcardTypeAnnotation(annotationContext, currentOffset); - return; - } - // common part between type annotation and annotation - generateAnnotation(annotationContext.annotation, currentOffset); - if (this.contentsOffset == currentOffset) { - // error occurred while generating the annotation + generateWildcardTypeAnnotation(annotationContext, currentOffset); return; } + + int targetType = annotationContext.targetType; + int[] locations = Annotation.getLocations( annotationContext.typeReference, annotationContext.primaryAnnotations, annotationContext.annotation, - annotationContext.annotationsOnDimensions); - if (locations != null) { - // convert to GENERIC_OR_ARRAY type - switch(targetType) { - case AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS : - targetType = AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.LOCAL_VARIABLE : - targetType = AnnotationTargetTypeConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.METHOD_PARAMETER : - targetType = AnnotationTargetTypeConstants.METHOD_PARAMETER_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.FIELD : - targetType = AnnotationTargetTypeConstants.FIELD_GENERIC_OR_ARRAY; - break; -// case AnnotationTargetTypeConstants.METHOD_RECEIVER : -// // should not happen - possible extension -// targetType = AnnotationTargetTypeConstants.METHOD_RECEIVER_GENERIC_OR_ARRAY; -// break; -// case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER : -// // should not happen - possible extension -// targetType = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY; -// break; - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : - // should not happen - possible extension - targetType = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY; - break; -// case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER : -// // should not happen - possible extension -// targetType = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY; -// break; - case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND : - // should not happen - possible extension - targetType = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY; - break; -// case AnnotationTargetTypeConstants.THROWS : -// targetType = AnnotationTargetTypeConstants.THROWS_GENERIC_OR_ARRAY; - case AnnotationTargetTypeConstants.TYPE_INSTANCEOF: - targetType = AnnotationTargetTypeConstants.TYPE_INSTANCEOF_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.CLASS_LITERAL: - targetType = AnnotationTargetTypeConstants.CLASS_LITERAL_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.OBJECT_CREATION: - targetType = AnnotationTargetTypeConstants.OBJECT_CREATION_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.TYPE_CAST: - targetType = AnnotationTargetTypeConstants.TYPE_CAST_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL : - targetType = AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL : - targetType = AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.METHOD_RETURN_TYPE : - targetType = AnnotationTargetTypeConstants.METHOD_RETURN_TYPE_GENERIC_OR_ARRAY; - } - } - // reserve enough space + annotationContext.annotationsOnDimensions, + annotationContext.dimensions); + if (this.contentsOffset + 5 >= this.contents.length) { resizeContents(5); } this.contents[this.contentsOffset++] = (byte) targetType; dumpTargetTypeContents(targetType, annotationContext); dumpLocations(locations); - } - - private void generateWilcardTypeAnnotation(AnnotationContext annotationContext, int currentOffset) { + // common part between type annotation and annotation generateAnnotation(annotationContext.annotation, currentOffset); - if (this.contentsOffset == currentOffset) { - // error occurred while generating the annotation - return; - } - int[] wildcardLocations = getWildcardLocations(annotationContext.typeReference, annotationContext.wildcard); + } + + private void generateWildcardTypeAnnotation(AnnotationContext annotationContext, int currentOffset) { int targetType = annotationContext.targetType; - switch(targetType) { - case AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS : - targetType = AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.LOCAL_VARIABLE : - targetType = AnnotationTargetTypeConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.METHOD_PARAMETER : - targetType = AnnotationTargetTypeConstants.METHOD_PARAMETER_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.FIELD : - targetType = AnnotationTargetTypeConstants.FIELD_GENERIC_OR_ARRAY; - break; -// case AnnotationTargetTypeConstants.METHOD_RECEIVER : -// // should not happen - possible extension -// targetType = AnnotationTargetTypeConstants.METHOD_RECEIVER_GENERIC_OR_ARRAY; -// break; -// case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER : -// // should not happen - possible extension -// targetType = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY; -// break; -// case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : -// // should not happen - possible extension -// targetType = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY; -// break; -// case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER : -// // should not happen - possible extension -// targetType = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY; -// break; -// case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND : -// // should not happen - possible extension -// targetType = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY; -// break; -// case AnnotationTargetTypeConstants.THROWS : -// targetType = AnnotationTargetTypeConstants.THROWS_GENERIC_OR_ARRAY; - case AnnotationTargetTypeConstants.TYPE_INSTANCEOF: - targetType = AnnotationTargetTypeConstants.TYPE_INSTANCEOF_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.CLASS_LITERAL: - targetType = AnnotationTargetTypeConstants.CLASS_LITERAL_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.OBJECT_CREATION: - targetType = AnnotationTargetTypeConstants.OBJECT_CREATION_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.TYPE_CAST: - targetType = AnnotationTargetTypeConstants.TYPE_CAST_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL : - targetType = AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL : - targetType = AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY; - break; - case AnnotationTargetTypeConstants.METHOD_RETURN_TYPE : - targetType = AnnotationTargetTypeConstants.METHOD_RETURN_TYPE_GENERIC_OR_ARRAY; - } + int[] locations = Annotation.getLocations( - annotationContext.wildcard.bound, + annotationContext.typeReference, null, annotationContext.annotation, - null); + null, + 0); // reserve enough space if (this.contentsOffset + 5 >= this.contents.length) { resizeContents(5); } - this.contents[this.contentsOffset++] = - (byte) (locations != null ? - AnnotationTargetTypeConstants.WILDCARD_BOUND_GENERIC_OR_ARRAY : - AnnotationTargetTypeConstants.WILDCARD_BOUND); this.contents[this.contentsOffset++] = (byte) targetType; dumpTargetTypeContents(targetType, annotationContext); - dumpLocations(wildcardLocations); dumpLocations(locations); + generateAnnotation(annotationContext.annotation, currentOffset); } + private int generateTypeAnnotationAttributeForTypeDeclaration() { TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext; if ((typeDeclaration.bits & ASTNode.HasTypeAnnotations) == 0) { @@ -4647,7 +4517,7 @@ public class ClassFile implements TypeConstants, TypeIds { TypeReference superclass = typeDeclaration.superclass; List allTypeAnnotationContexts = new ArrayList(); if (superclass != null && (superclass.bits & ASTNode.HasTypeAnnotations) != 0) { - superclass.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS, -1, allTypeAnnotationContexts); + superclass.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_EXTENDS, -1, allTypeAnnotationContexts); } TypeReference[] superInterfaces = typeDeclaration.superInterfaces; if (superInterfaces != null) { @@ -4656,7 +4526,7 @@ public class ClassFile implements TypeConstants, TypeIds { if ((superInterface.bits & ASTNode.HasTypeAnnotations) == 0) { continue; } - superInterface.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS, i, allTypeAnnotationContexts); + superInterface.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_EXTENDS, i, allTypeAnnotationContexts); } } TypeParameter[] typeParameters = typeDeclaration.typeParameters; @@ -4690,6 +4560,9 @@ public class ClassFile implements TypeConstants, TypeIds { return attributesNumber; } + + + private int generateVarargsAttribute() { int localContentsOffset = this.contentsOffset; /* @@ -5148,7 +5021,7 @@ public class ClassFile implements TypeConstants, TypeIds { this.produceAttributes = options.produceDebugAttributes; if (this.targetJDK >= ClassFileConstants.JDK1_6) { this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; - if (this.targetJDK >= ClassFileConstants.JDK1_7) { + if (this.targetJDK >= ClassFileConstants.JDK1_8) { this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION; } } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) { 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 64709c909..538c3ee7d 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 @@ -17,6 +17,8 @@ * bug 186342 - [compiler][null] Using annotations for null checking * bug 365662 - [compiler][null] warn on contradictory and redundant null annotations * bug 331649 - [compiler][null] consider null annotations for fields + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -47,47 +49,44 @@ public abstract class Annotation extends Expression { final TypeReference reference, final Annotation[] primaryAnnotation, final Annotation annotation, - final Annotation[][] annotationsOnDimensionsOnExpression) { + final Annotation[][] annotationsOnDimensionsOnExpression, + final int dimensions) { + class LocationCollector extends ASTVisitor { - Stack currentIndexes; + Stack typePathEntries; Annotation currentAnnotation; boolean search = true; public LocationCollector(Annotation currentAnnotation) { - this.currentIndexes = new Stack(); + this.typePathEntries = new Stack(); this.currentAnnotation = currentAnnotation; } - public boolean visit(ArrayTypeReference typeReference, BlockScope scope) { + + public boolean visit(ParameterizedSingleTypeReference typeReference, BlockScope scope) { if (!this.search) return false; + Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions; if (annotationsOnDimensions != null) { - // check if the annotation is located on the first dimension - Annotation[] annotations = annotationsOnDimensions[0]; - if (annotations != null) { - for (int j = 0, max2 = annotations.length; j < max2; j++) { - Annotation current = annotations[j]; - if (current == this.currentAnnotation) { - this.search = false; - return false; - } - } - } - - this.currentIndexes.push(new Integer(0)); - for (int i = 1, max = annotationsOnDimensions.length; i < max; i++) { - annotations = annotationsOnDimensions[i]; + for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) { + Annotation[] annotations = annotationsOnDimensions[i]; if (annotations != null) { for (int j = 0, max2 = annotations.length; j < max2; j++) { Annotation current = annotations[j]; if (current == this.currentAnnotation) { + // found it, push any relevant type path entries + for (int k = 0; k < i; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } this.search = false; return false; } } } - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); + } } + + // Example cases handled here: @B(1) List<String>[] Annotation[][] annotations = typeReference.annotations; if (annotations == null) { annotations = new Annotation[][] { primaryAnnotation }; @@ -99,91 +98,99 @@ public abstract class Annotation extends Expression { for (int j = 0; j < annotationsLength; j++) { if (current[j] == this.currentAnnotation) { this.search = false; + // Found it, insert any necessary type path elements + for (int k = 0; k < typeReference.dimensions; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } return false; } } } - this.currentIndexes.pop(); + + // If a type argument is annotated it is necessary jump past the array elements + if (typeReference.dimensions != 0) { + for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } + } + TypeReference[] typeReferences = typeReference.typeArguments; + for (int i = 0, max = typeReferences.length; i < max; i++) { + this.typePathEntries.add(new int[]{3,i}); + typeReferences[i].traverse(this, scope); + if (!this.search) { + return false; + } else { + this.typePathEntries.pop(); + } + } + if (typeReference.dimensions != 0) { + for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) { + this.typePathEntries.pop(); + } + } return true; } - public boolean visit(ArrayQualifiedTypeReference typeReference, BlockScope scope) { + + public boolean visit(SingleTypeReference typeReference, BlockScope scope) { if (!this.search) return false; - Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions; - if (annotationsOnDimensions != null) { - // check if the annotation is located on the first dimension - Annotation[] annotations = annotationsOnDimensions[0]; - if (annotations != null) { - for (int j = 0, max2 = annotations.length; j < max2; j++) { - Annotation current = annotations[j]; - if (current == this.currentAnnotation) { - this.search = false; - return false; - } - } - } - this.currentIndexes.push(new Integer(0)); - for (int i = 1, max = annotationsOnDimensions.length; i < max; i++) { - annotations = annotationsOnDimensions[i]; - if (annotations != null) { - for (int j = 0, max2 = annotations.length; j < max2; j++) { - Annotation current = annotations[j]; - if (current == this.currentAnnotation) { - this.search = false; - return false; - } - } - } - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); + // depth allows for the syntax "outerInstance.new @A InnerType();" + int depth = 0; + if (typeReference.resolvedType instanceof ReferenceBinding) { + depth = getInnerDepth((ReferenceBinding)typeReference.resolvedType); + } + + if (dimensions != 0) { + for (int k = 0; k < dimensions; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); } } Annotation[][] annotations = typeReference.annotations; - if (annotations == null) { - annotations = new Annotation[][] { primaryAnnotation }; - } - int annotationsLevels = annotations.length; + int annotationsLevels = annotations == null ? 0 : 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) { + // Found this.search = false; + if (depth != 0) { + for (int k = 0; k<depth; k++) { + this.typePathEntries.add(TYPE_PATH_INNER_TYPE); + } + } return false; } } } - this.currentIndexes.pop(); - return true; + if (dimensions != 0) { + for (int k = 0; k < dimensions; k++) { + this.typePathEntries.pop(); + } + } + return false; } - public boolean visit(ParameterizedSingleTypeReference typeReference, BlockScope scope) { + + public boolean visit(ArrayTypeReference typeReference, BlockScope scope) { if (!this.search) return false; + Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions; if (annotationsOnDimensions != null) { - // check if the annotation is located on the first dimension - Annotation[] annotations = annotationsOnDimensions[0]; - if (annotations != null) { - for (int j = 0, max2 = annotations.length; j < max2; j++) { - Annotation current = annotations[j]; - if (current == this.currentAnnotation) { - this.search = false; - return false; - } - } - } - - this.currentIndexes.push(new Integer(0)); - for (int i = 1, max = annotationsOnDimensions.length; i < max; i++) { - annotations = annotationsOnDimensions[i]; + for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) { + Annotation[] annotations = annotationsOnDimensions[i]; if (annotations != null) { for (int j = 0, max2 = annotations.length; j < max2; j++) { Annotation current = annotations[j]; if (current == this.currentAnnotation) { + for (int k = 0; k < i; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } this.search = false; return false; } } } - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); + } } Annotation[][] annotations = typeReference.annotations; @@ -196,50 +203,36 @@ public abstract class Annotation extends Expression { int annotationsLength = current == null ? 0 : current.length; for (int j = 0; j < annotationsLength; j++) { if (current[j] == this.currentAnnotation) { + for (int k = 0, maxk=typeReference.dimensions; k < maxk; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } this.search = false; return false; } } } - TypeReference[] typeReferences = typeReference.typeArguments; - this.currentIndexes.push(new Integer(0)); - for (int i = 0, max = typeReferences.length; i < max; i++) { - typeReferences[i].traverse(this, scope); - if (!this.search) return false; - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); - } - this.currentIndexes.pop(); return true; } - public boolean visit(ParameterizedQualifiedTypeReference typeReference, BlockScope scope) { + + public boolean visit(ArrayQualifiedTypeReference typeReference, BlockScope scope) { if (!this.search) return false; Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions; if (annotationsOnDimensions != null) { - // check if the annotation is located on the first dimension - Annotation[] annotations = annotationsOnDimensions[0]; - if (annotations != null) { - for (int j = 0, max2 = annotations.length; j < max2; j++) { - Annotation current = annotations[j]; - if (current == this.currentAnnotation) { - this.search = false; - return false; - } - } - } - - this.currentIndexes.push(new Integer(0)); - for (int i = 1, max = annotationsOnDimensions.length; i < max; i++) { - annotations = annotationsOnDimensions[i]; + for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) { + Annotation[] annotations = annotationsOnDimensions[i]; if (annotations != null) { for (int j = 0, max2 = annotations.length; j < max2; j++) { Annotation current = annotations[j]; if (current == this.currentAnnotation) { this.search = false; + // Found it, insert relevant type path elements + for (int k = 0, maxk = i; k < maxk; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } return false; } } } - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); } } Annotation[][] annotations = typeReference.annotations; @@ -253,130 +246,230 @@ public abstract class Annotation extends Expression { for (int j = 0; j < annotationsLength; j++) { if (current[j] == this.currentAnnotation) { this.search = false; + for (int k = 0, maxk=typeReference.dimensions; k < maxk; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } return false; } } } - //TODO it is unclear how to manage annotations located in the first type arguments - TypeReference[] typeReferences = typeReference.typeArguments[typeReference.typeArguments.length - 1]; - this.currentIndexes.push(new Integer(0)); - for (int i = 0, max = typeReferences.length; i < max; i++) { - typeReferences[i].traverse(this, scope); - if (!this.search) return false; - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); - } - this.currentIndexes.pop(); return true; } - public boolean visit(SingleTypeReference typeReference, BlockScope scope) { + + public boolean visit(ParameterizedQualifiedTypeReference typeReference, BlockScope scope) { if (!this.search) return false; - Annotation[][] annotationsOnDimensions = annotationsOnDimensionsOnExpression; + + // Example case handled by this block: java.util.List<String>[]@A[] + Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions; if (annotationsOnDimensions != null) { - // check if the annotation is located on the first dimension - Annotation[] annotations = annotationsOnDimensions[0]; - if (annotations != null) { - for (int j = 0, max2 = annotations.length; j < max2; j++) { - Annotation current = annotations[j]; - if (current == this.currentAnnotation) { - this.search = false; - return false; - } - } - } - - this.currentIndexes.push(new Integer(0)); - for (int i = 1, max = annotationsOnDimensions.length; i < max; i++) { - annotations = annotationsOnDimensions[i]; + for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) { + Annotation[] annotations = annotationsOnDimensions[i]; if (annotations != null) { for (int j = 0, max2 = annotations.length; j < max2; j++) { Annotation current = annotations[j]; if (current == this.currentAnnotation) { this.search = false; + // Found it, insert relevant type path elements + for (int k = 0, maxk = i; k < maxk; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } return false; } } } - this.currentIndexes.push(new Integer(((Integer) this.currentIndexes.pop()).intValue() + 1)); } } + + boolean[] needsInnerEntryInfo = computeInnerEntryInfo(typeReference); + + // Example cases handled by this block: + // java.util.@A List<String>[][], com.demo.@A Outer.@B Inner<String>, java.util.Map.@A Entry<String,String> Annotation[][] annotations = typeReference.annotations; - int annotationsLevels = annotations == null ? 0 : annotations.length; + 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; + // Found, insert any relevant type path elements + for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } + // Found, insert any relevant type path elements + if (needsInnerEntryInfo != null) { + for (int k = 0; k <= i; k++) { + if (needsInnerEntryInfo[k]) { + this.typePathEntries.push(TYPE_PATH_INNER_TYPE); + } + } + } return false; } } } - return false; + + // Example cases handled by this block: + // java.util.List<@A String> + if (typeReference.dimensions != 0) { + for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) { + this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY); + } + } + int toPop = 0; + for (int i = 0, max = typeReference.typeArguments.length; i < max; i++) { + TypeReference[] typeArgumentsForComponent = typeReference.typeArguments[i]; + if (needsInnerEntryInfo != null && needsInnerEntryInfo[i]) { + this.typePathEntries.push(TYPE_PATH_INNER_TYPE); + toPop++; + } + if (typeArgumentsForComponent != null) { + for (int j = 0, max2 = typeArgumentsForComponent.length; j < max2; j++) { + this.typePathEntries.push(new int[]{3,j}); + typeArgumentsForComponent[j].traverse(this,scope); + if (!this.search) return false; + this.typePathEntries.pop(); + } + } + } + toPop += typeReference.dimensions; + for (int k = 0, maxk = toPop; k < maxk; k++) { + this.typePathEntries.pop(); + } + return true; } + public boolean visit(Wildcard typeReference, BlockScope scope) { if (!this.search) return false; TypeReference bound = typeReference.bound; + this.typePathEntries.push(TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND); bound.traverse(this, scope); + if (!this.search) { + return false; + } + this.typePathEntries.pop(); return true; } + + private boolean[] computeInnerEntryInfo(QualifiedTypeReference typeReference) { + ReferenceBinding resolvedType = (ReferenceBinding) + (typeReference.resolvedType instanceof ArrayBinding ? typeReference.resolvedType.leafComponentType() : typeReference.resolvedType); + boolean[] needsInnerEntryInfo = null; + if (resolvedType != null && resolvedType.isNestedType()) { + // Work backwards computing whether a INNER_TYPE entry is required for each level + needsInnerEntryInfo = new boolean[typeReference.tokens.length]; + int counter = needsInnerEntryInfo.length - 1; + ReferenceBinding type = resolvedType;//resolvedType.enclosingType(); + while (type != null) { + needsInnerEntryInfo[counter--] = !type.isStatic(); + type = type.enclosingType(); + } + } + return needsInnerEntryInfo; + } + + private int getInnerDepth(ReferenceBinding resolvedType) { + int depth = 0; + ReferenceBinding type = resolvedType; + while (type != null) { + depth += (type.isStatic())?0:1; + type = type.enclosingType(); + } + return depth; + } + public boolean visit(QualifiedTypeReference typeReference, BlockScope scope) { if (!this.search) return false; + boolean[] needsInnerEntryInfo = computeInnerEntryInfo(typeReference); + + // Example cases handled by this block: + // java.util.@A List, com.demo.@A Outer.@B Inner, java.util.Map.@A Entry Annotation[][] annotations = typeReference.annotations; - int annotationsLevels = annotations == null ? 0 : annotations.length; + 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; + // Found, insert any relevant type path elements + if (needsInnerEntryInfo != null) { + for (int k = 0; k <= i; k++) { + if (needsInnerEntryInfo[k]) { + this.typePathEntries.push(TYPE_PATH_INNER_TYPE); + } + } + } return false; } } } return true; } + public String toString() { StringBuffer buffer = new StringBuffer(); buffer .append("search location for ") //$NON-NLS-1$ .append(this.currentAnnotation) - .append("\ncurrent indexes : ") //$NON-NLS-1$ - .append(this.currentIndexes); + .append("\ncurrent type_path entries : "); //$NON-NLS-1$ + for (int i = 0, maxi = this.typePathEntries.size(); i < maxi; i++) { + int[] typePathEntry = (int[]) this.typePathEntries.get(i); + buffer + .append('(') + .append(typePathEntry[0]) + .append(',') + .append(typePathEntry[1]) + .append(')'); + } return String.valueOf(buffer); } } if (reference == null) return null; LocationCollector collector = new LocationCollector(annotation); reference.traverse(collector, (BlockScope) null); - if (collector.currentIndexes.isEmpty()) { + if (collector.typePathEntries.isEmpty()) { return null; } - int size = collector.currentIndexes.size(); - int[] result = new int[size]; + int size = collector.typePathEntries.size(); + int[] result = new int[size*2]; + int offset=0; for (int i = 0; i < size; i++) { - result[size - i - 1] = ((Integer) collector.currentIndexes.pop()).intValue(); + int[] pathElement = (int[])collector.typePathEntries.get(i); + result[offset++] = pathElement[0]; + result[offset++] = pathElement[1]; } return result; } - - // jsr 308 - public static class TypeUseBinding extends ReferenceBinding { - private int kind; - public TypeUseBinding(int kind) { - this.tagBits = 0L; - this.kind = kind; - } - public int kind() { - return this.kind; - } - public boolean hasTypeBit(int bit) { - return false; - } + + // jsr 308 + public static class TypeUseBinding extends ReferenceBinding { + private int kind; + public TypeUseBinding(int kind) { + this.tagBits = 0L; + this.kind = kind; + } + public int kind() { + return this.kind; } + public boolean hasTypeBit(int bit) { + return false; + } + } final static MemberValuePair[] NoValuePairs = new MemberValuePair[0]; private static final long TAGBITS_NULLABLE_OR_NONNULL = TagBits.AnnotationNullable|TagBits.AnnotationNonNull; + static final int[] TYPE_PATH_ELEMENT_ARRAY = new int[]{0,0}; + static final int[] TYPE_PATH_INNER_TYPE = new int[]{1,0}; + static final int[] TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND = new int[]{2,0}; + public int declarationSourceEnd; public Binding recipient; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java index 41abbac3d..5f9853175 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java @@ -17,6 +17,9 @@ * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking + * 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) + * *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -68,7 +71,7 @@ public class ArrayAllocationExpression extends Expression { int pc = codeStream.position; if (this.initializer != null) { - this.initializer.generateCode(currentScope, codeStream, valueRequired); + this.initializer.generateCode(this.type, this.annotationsOnDimensions, currentScope, codeStream, valueRequired); return; } @@ -83,10 +86,10 @@ public class ArrayAllocationExpression extends Expression { // array allocation if (explicitDimCount == 1) { // Mono-dimensional array - codeStream.newArray((ArrayBinding)this.resolvedType); + codeStream.newArray(this.type, this.annotationsOnDimensions, (ArrayBinding)this.resolvedType); } else { // Multi-dimensional array - codeStream.multianewarray(this.resolvedType, explicitDimCount); + codeStream.multianewarray(this.type, this.resolvedType, this.dimensions.length, this.annotationsOnDimensions); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java index 0a4d71b17..d39eeef47 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java @@ -15,6 +15,8 @@ * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK * bug 370639 - [compiler][resource] restore the default for resource leak warnings * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -52,16 +54,20 @@ public class ArrayInitializer extends Expression { return flowInfo; } + public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { + generateCode(null, null, currentScope, codeStream, valueRequired); + } + /** * Code generation for a array initializer */ - public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { + public void generateCode(TypeReference typeReference, Annotation[][] annotationsOnDimensions, BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { // Flatten the values and compute the dimensions, by iterating in depth into nested array initializers int pc = codeStream.position; int expressionLength = (this.expressions == null) ? 0: this.expressions.length; codeStream.generateInlinedValue(expressionLength); - codeStream.newArray(null, this.binding); + codeStream.newArray(typeReference, annotationsOnDimensions, this.binding); if (this.expressions != null) { // binding is an ArrayType, so I can just deal with the dimension int elementsTypeID = this.binding.dimensions > 1 ? -1 : this.binding.leafComponentType.id; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java index 4a4a314a2..ee461e693 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java @@ -17,6 +17,8 @@ * Stephan Herrmann - Contribution for * bug 402028 - [1.8][compiler] null analysis for reference expressions * bug 404649 - [1.8][compiler] detect illegal reference to indirect or redundant super via I.super.m() syntax + * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contribution for + * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -144,7 +146,8 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat buffer.append(this.resolvedType.constantPoolName()); buffer.append(';'); int invokeDynamicNumber = codeStream.classFile.recordBootstrapMethod(this); - codeStream.invokeDynamic(invokeDynamicNumber, argumentsSize, 1, LAMBDA, buffer.toString().toCharArray()); + codeStream.invokeDynamic(invokeDynamicNumber, argumentsSize, 1, LAMBDA, buffer.toString().toCharArray(), + this.isConstructorReference(), (this.lhs instanceof TypeReference? (TypeReference) this.lhs : null), this.typeArguments); codeStream.recordPositionsFrom(pc, this.sourceStart); } @@ -399,9 +402,15 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat if (this.binding.isAbstract() && this.lhs.isSuper()) scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding); - if (this.binding.isStatic() && this.binding.declaringClass != this.receiverType) - scope.problemReporter().indirectAccessToStaticMethod(this, this.binding); - + if (this.binding.isStatic()) { + if (this.binding.declaringClass != this.receiverType) + scope.problemReporter().indirectAccessToStaticMethod(this, this.binding); + } else { + AbstractMethodDeclaration srcMethod = this.binding.sourceMethod(); + if (srcMethod != null && srcMethod.isMethod()) + srcMethod.bits &= ~ASTNode.CanBeStatic; + } + if (isMethodUseDeprecated(this.binding, scope, true)) scope.problemReporter().deprecatedMethod(this.binding, this); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java index 6c6bc5cf5..07aad10b3 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java @@ -27,6 +27,9 @@ * bug 384380 - False positive on a ?? Potential null pointer access ?? after a continue * Jesper Steen Moller - Contributions for * bug 404146 - [1.7][compiler] nested try-catch-finally-blocks leads to unrunnable Java byte code + * 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) + * *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -524,7 +527,7 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) { multiCatchExceptionLabel.initialize((UnionTypeReference) argument.type); exceptionLabel = multiCatchExceptionLabel; } else { - exceptionLabel = new ExceptionLabel(codeStream, argument.binding.type); + exceptionLabel = new ExceptionLabel(codeStream, argument.binding.type, argument.type); } exceptionLabel.placeStart(); exceptionLabels[i] = exceptionLabel; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java index a8ac20a75..32c906102 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java @@ -16,6 +16,8 @@ * Stephan Herrmann - Contribution for * bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis * bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -54,207 +56,226 @@ import org.eclipse.objectteams.otdt.internal.core.compiler.util.TSuperHelper; * @version $Id: TypeReference.java 23404 2010-02-03 14:10:22Z stephan $ */ public abstract class TypeReference extends Expression { - public static final TypeReference[] NO_TYPE_ARGUMENTS = new TypeReference[0]; - static class AnnotationCollector extends ASTVisitor { - List annotationContexts; - TypeReference typeReference; - int targetType; - Annotation[] primaryAnnotations; - int info = -1; - int info2 = -1; - LocalVariableBinding localVariable; - Annotation[][] annotationsOnDimensions; - Wildcard currentWildcard; - - public AnnotationCollector( - TypeParameter typeParameter, - int targetType, - int typeParameterIndex, - List annotationContexts) { - this.annotationContexts = annotationContexts; - this.typeReference = typeParameter.type; - this.targetType = targetType; - this.primaryAnnotations = typeParameter.annotations; - this.info = typeParameterIndex; - } +static class AnnotationCollector extends ASTVisitor { + List annotationContexts; + TypeReference typeReference; + int targetType; + Annotation[] primaryAnnotations; + int info = -1; + int info2 = -1; + LocalVariableBinding localVariable; + Annotation[][] annotationsOnDimensions; + int dimensions; + Wildcard currentWildcard; + + public AnnotationCollector( + TypeParameter typeParameter, + int targetType, + int typeParameterIndex, + List annotationContexts) { + this.annotationContexts = annotationContexts; + this.typeReference = typeParameter.type; + this.targetType = targetType; + this.primaryAnnotations = typeParameter.annotations; + this.info = typeParameterIndex; + } - public AnnotationCollector( - LocalDeclaration localDeclaration, - int targetType, - LocalVariableBinding localVariable, - List annotationContexts) { - this.annotationContexts = annotationContexts; - this.typeReference = localDeclaration.type; - this.targetType = targetType; - this.primaryAnnotations = localDeclaration.annotations; - this.localVariable = localVariable; - } + public AnnotationCollector( + LocalDeclaration localDeclaration, + int targetType, + LocalVariableBinding localVariable, + List annotationContexts) { + this.annotationContexts = annotationContexts; + this.typeReference = localDeclaration.type; + this.targetType = targetType; + this.primaryAnnotations = localDeclaration.annotations; + this.localVariable = localVariable; + } - public AnnotationCollector( - LocalDeclaration localDeclaration, - int targetType, - int parameterIndex, - List annotationContexts) { - this.annotationContexts = annotationContexts; - this.typeReference = localDeclaration.type; - this.targetType = targetType; - this.primaryAnnotations = localDeclaration.annotations; - this.info = parameterIndex; - } + public AnnotationCollector( + LocalDeclaration localDeclaration, + int targetType, + int parameterIndex, + List annotationContexts) { + this.annotationContexts = annotationContexts; + this.typeReference = localDeclaration.type; + this.targetType = targetType; + this.primaryAnnotations = localDeclaration.annotations; + this.info = parameterIndex; + } - public AnnotationCollector( - MethodDeclaration methodDeclaration, - int targetType, - List annotationContexts) { - this.annotationContexts = annotationContexts; - this.typeReference = methodDeclaration.returnType; - this.targetType = targetType; - this.primaryAnnotations = methodDeclaration.annotations; - } + public AnnotationCollector( + MethodDeclaration methodDeclaration, + int targetType, + List annotationContexts) { + this.annotationContexts = annotationContexts; + this.typeReference = methodDeclaration.returnType; + this.targetType = targetType; + this.primaryAnnotations = methodDeclaration.annotations; + } - public AnnotationCollector( - FieldDeclaration fieldDeclaration, - int targetType, - List annotationContexts) { - this.annotationContexts = annotationContexts; - this.typeReference = fieldDeclaration.type; - this.targetType = targetType; - this.primaryAnnotations = fieldDeclaration.annotations; - } - public AnnotationCollector( - TypeReference typeReference, - int targetType, - List annotationContexts) { - this.annotationContexts = annotationContexts; - this.typeReference = typeReference; - this.targetType = targetType; - } - public AnnotationCollector( - TypeReference typeReference, - int targetType, - int info, - List annotationContexts) { - this.annotationContexts = annotationContexts; - this.typeReference = typeReference; - this.info = info; - this.targetType = targetType; - } - public AnnotationCollector( - TypeReference typeReference, - int targetType, - int info, - int typeIndex, - List annotationContexts) { - this.annotationContexts = annotationContexts; - this.typeReference = typeReference; - this.info = info; - this.targetType = targetType; - this.info2 = typeIndex; - } - public AnnotationCollector( - TypeReference typeReference, - int targetType, - int info, - List annotationContexts, - Annotation[][] annotationsOnDimensions) { - this.annotationContexts = annotationContexts; - this.typeReference = typeReference; - this.info = info; - this.targetType = targetType; - this.annotationsOnDimensions = annotationsOnDimensions; + public AnnotationCollector( + FieldDeclaration fieldDeclaration, + int targetType, + List annotationContexts) { + this.annotationContexts = annotationContexts; + this.typeReference = fieldDeclaration.type; + this.targetType = targetType; + this.primaryAnnotations = fieldDeclaration.annotations; + } + public AnnotationCollector( + TypeReference typeReference, + int targetType, + List annotationContexts) { + this.annotationContexts = annotationContexts; + this.typeReference = typeReference; + this.targetType = targetType; + } + public AnnotationCollector( + TypeReference typeReference, + int targetType, + int info, + List annotationContexts) { + this.annotationContexts = annotationContexts; + this.typeReference = typeReference; + this.info = info; + this.targetType = targetType; + } + public AnnotationCollector( + TypeReference typeReference, + int targetType, + int info, + int typeIndex, + List annotationContexts) { + this.annotationContexts = annotationContexts; + this.typeReference = typeReference; + this.info = info; + this.targetType = targetType; + this.info2 = typeIndex; + } + public AnnotationCollector( + TypeReference typeReference, + int targetType, + int info, + List annotationContexts, + Annotation[][] annotationsOnDimensions, + int dimensions) { + this.annotationContexts = annotationContexts; + this.typeReference = typeReference; + this.info = info; + this.targetType = targetType; + this.annotationsOnDimensions = annotationsOnDimensions; + // Array references like 'new String[]' manifest as an ArrayAllocationExpression + // with a 'type' of String. When the type is not carrying the dimensions count + // it is passed in via the dimensions parameter. It is not possible to use + // annotationsOnDimensions as it will be null if there are no annotations on any + // of the dimensions. + this.dimensions = dimensions; + } + + private boolean internalVisit(Annotation annotation) { + AnnotationContext annotationContext = null; + if (annotation.isRuntimeTypeInvisible()) { + annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, this.primaryAnnotations, AnnotationContext.INVISIBLE, this.annotationsOnDimensions, this.dimensions); + } else if (annotation.isRuntimeTypeVisible()) { + annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, this.primaryAnnotations, AnnotationContext.VISIBLE, this.annotationsOnDimensions, this.dimensions); } - private boolean internalVisit(Annotation annotation) { - AnnotationContext annotationContext = null; - if (annotation.isRuntimeTypeInvisible()) { - annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, this.primaryAnnotations, AnnotationContext.INVISIBLE, this.annotationsOnDimensions); - } else if (annotation.isRuntimeTypeVisible()) { - annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, this.primaryAnnotations, AnnotationContext.VISIBLE, this.annotationsOnDimensions); + if (annotationContext != null) { + annotationContext.wildcard = this.currentWildcard; + switch(this.targetType) { + case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER : + case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER : + case AnnotationTargetTypeConstants.CLASS_EXTENDS: + case AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER : + case AnnotationTargetTypeConstants.THROWS : + case AnnotationTargetTypeConstants.EXCEPTION_PARAMETER : + case AnnotationTargetTypeConstants.INSTANCEOF: + case AnnotationTargetTypeConstants.NEW : + case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE : + case AnnotationTargetTypeConstants.METHOD_REFERENCE : + case AnnotationTargetTypeConstants.CAST: + annotationContext.info = this.info; + break; + case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : + case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND : + annotationContext.info2 = this.info2; + annotationContext.info = this.info; + break; + case AnnotationTargetTypeConstants.LOCAL_VARIABLE : + case AnnotationTargetTypeConstants.RESOURCE_VARIABLE : + annotationContext.variableBinding = this.localVariable; + break; + case AnnotationTargetTypeConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : + case AnnotationTargetTypeConstants.METHOD_INVOCATION_TYPE_ARGUMENT : + case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : + case AnnotationTargetTypeConstants.METHOD_REFERENCE_TYPE_ARGUMENT : + annotationContext.info2 = this.info2; + annotationContext.info = this.info; + break; + case AnnotationTargetTypeConstants.FIELD : + case AnnotationTargetTypeConstants.METHOD_RETURN : + case AnnotationTargetTypeConstants.METHOD_RECEIVER : + break; + } - if (annotationContext != null) { - annotationContext.wildcard = this.currentWildcard; - switch(this.targetType) { - case AnnotationTargetTypeConstants.THROWS : - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER : - case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER : - case AnnotationTargetTypeConstants.METHOD_PARAMETER : - case AnnotationTargetTypeConstants.TYPE_CAST : - case AnnotationTargetTypeConstants.TYPE_INSTANCEOF : - case AnnotationTargetTypeConstants.OBJECT_CREATION : - case AnnotationTargetTypeConstants.CLASS_LITERAL : - case AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS: - annotationContext.info = this.info; - break; - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : - case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND : - annotationContext.info2 = this.info2; - annotationContext.info = this.info; - break; - case AnnotationTargetTypeConstants.LOCAL_VARIABLE : - annotationContext.variableBinding = this.localVariable; - break; - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL : - case AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL : - annotationContext.info2 = this.info2; - annotationContext.info = this.info; - } - this.annotationContexts.add(annotationContext); - } - return true; - } - public boolean visit(MarkerAnnotation annotation, BlockScope scope) { - return internalVisit(annotation); + this.annotationContexts.add(annotationContext); } - public boolean visit(NormalAnnotation annotation, BlockScope scope) { - return internalVisit(annotation); - } - public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) { - return internalVisit(annotation); - } - public boolean visit(Wildcard wildcard, BlockScope scope) { - this.currentWildcard = wildcard; + return true; + } + public boolean visit(MarkerAnnotation annotation, BlockScope scope) { + return internalVisit(annotation); + } + public boolean visit(NormalAnnotation annotation, BlockScope scope) { + return internalVisit(annotation); + } + public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) { + return internalVisit(annotation); + } + public boolean visit(Wildcard wildcard, BlockScope scope) { + this.currentWildcard = wildcard; + return true; + } + public boolean visit(Argument argument, BlockScope scope) { + if ((argument.bits & ASTNode.IsUnionType) == 0) { return true; } - public boolean visit(Argument argument, BlockScope scope) { - if ((argument.bits & ASTNode.IsUnionType) == 0) { + for (int i = 0, max = this.localVariable.initializationCount; i < max; i++) { + int startPC = this.localVariable.initializationPCs[i << 1]; + int endPC = this.localVariable.initializationPCs[(i << 1) + 1]; + if (startPC != endPC) { // only entries for non zero length return true; } - for (int i = 0, max = this.localVariable.initializationCount; i < max; i++) { - int startPC = this.localVariable.initializationPCs[i << 1]; - int endPC = this.localVariable.initializationPCs[(i << 1) + 1]; - if (startPC != endPC) { // only entries for non zero length - return true; - } - } - return false; } - public boolean visit(Argument argument, ClassScope scope) { - if ((argument.bits & ASTNode.IsUnionType) == 0) { + return false; + } + public boolean visit(Argument argument, ClassScope scope) { + if ((argument.bits & ASTNode.IsUnionType) == 0) { + return true; + } + for (int i = 0, max = this.localVariable.initializationCount; i < max; i++) { + int startPC = this.localVariable.initializationPCs[i << 1]; + int endPC = this.localVariable.initializationPCs[(i << 1) + 1]; + if (startPC != endPC) { // only entries for non zero length return true; } - for (int i = 0, max = this.localVariable.initializationCount; i < max; i++) { - int startPC = this.localVariable.initializationPCs[i << 1]; - int endPC = this.localVariable.initializationPCs[(i << 1) + 1]; - if (startPC != endPC) { // only entries for non zero length - return true; - } - } - return false; } - public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { - for (int i = 0, max = this.localVariable.initializationCount; i < max; i++) { - int startPC = this.localVariable.initializationPCs[i << 1]; - int endPC = this.localVariable.initializationPCs[(i << 1) + 1]; - if (startPC != endPC) { // only entries for non zero length - return true; - } + return false; + } + public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { + for (int i = 0, max = this.localVariable.initializationCount; i < max; i++) { + int startPC = this.localVariable.initializationPCs[i << 1]; + int endPC = this.localVariable.initializationPCs[(i << 1) + 1]; + if (startPC != endPC) { // only entries for non zero length + return true; } - return false; - } - public void endVisit(Wildcard wildcard, BlockScope scope) { - this.currentWildcard = null; } + return false; } + public void endVisit(Wildcard wildcard, BlockScope scope) { + this.currentWildcard = null; + } +} //{ObjectTeams: for baseclass decapsulation (implement interface from Expression): private DecapsulationState baseclassDecapsulation = DecapsulationState.NONE; @@ -275,7 +296,7 @@ public int deprecationProblemId = IProblem.UsingDeprecatedType; /* * Answer a base type reference (can be an array of base type). */ -public static final TypeReference baseTypeReference(int baseType, int dim, Annotation[][] dimAnnotations) { +public static final TypeReference baseTypeReference(int baseType, int dim, Annotation [][] dimAnnotations) { if (dim == 0) { switch (baseType) { @@ -363,12 +384,9 @@ public void getAllAnnotationContexts(int targetType, int info, List allAnnotatio } /** * info can be either a type index (superclass/superinterfaces) or a pc into the bytecode - * @param targetType - * @param info - * @param allAnnotationContexts */ -public void getAllAnnotationContexts(int targetType, int info, List allAnnotationContexts, Annotation[][] annotationsOnDimensions) { - AnnotationCollector collector = new AnnotationCollector(this, targetType, info, allAnnotationContexts, annotationsOnDimensions); +public void getAllAnnotationContexts(int targetType, int info, List allAnnotationContexts, Annotation[][] annotationsOnDimensions, int dimensions) { + AnnotationCollector collector = new AnnotationCollector(this, targetType, info, allAnnotationContexts, annotationsOnDimensions, dimensions); this.traverse(collector, (BlockScope) null); if (annotationsOnDimensions != null) { for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) { @@ -593,7 +611,6 @@ public boolean isWildcard() { public boolean isParameterizedTypeReference() { return false; } - protected void reportDeprecatedType(TypeBinding type, Scope scope, int index) { scope.problemReporter().deprecatedType(type, this, index); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java index 75de873ef..c743d436f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. + * Copyright (c) 2012, 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 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; @@ -32,6 +34,9 @@ public class AnnotationContext { public LocalVariableBinding variableBinding; public Annotation[][] annotationsOnDimensions; public Wildcard wildcard; + // annotationsOnDimensions might be null but the dimensions may still be important. In some + // cases they are not on the reference. + public int dimensions; public AnnotationContext( Annotation annotation, @@ -39,13 +44,15 @@ public class AnnotationContext { int targetType, Annotation[] primaryAnnotations, int visibility, - Annotation[][] annotationsOnDimensions) { + Annotation[][] annotationsOnDimensions, + int dimensions) { this.annotation = annotation; this.typeReference = typeReference; this.targetType = targetType; this.primaryAnnotations = primaryAnnotations; this.visibility = visibility; this.annotationsOnDimensions = annotationsOnDimensions; + this.dimensions = dimensions; } public String toString() { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java index ad66617ce..919247a9e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationTargetTypeConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. + * Copyright (c) 2012, 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,44 +11,39 @@ * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; public interface AnnotationTargetTypeConstants { - int METHOD_RECEIVER = 0x06; - int METHOD_RECEIVER_GENERIC_OR_ARRAY = 0x07; - int METHOD_RETURN_TYPE = 0x0A; - int METHOD_RETURN_TYPE_GENERIC_OR_ARRAY = 0x0B; - int METHOD_PARAMETER = 0x0C; - int METHOD_PARAMETER_GENERIC_OR_ARRAY = 0x0D; - int FIELD = 0x0E; - int FIELD_GENERIC_OR_ARRAY = 0x0F; - int CLASS_TYPE_PARAMETER_BOUND = 0x10; - int CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY = 0x11; - int METHOD_TYPE_PARAMETER_BOUND = 0x12; - int METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY = 0x13; - int CLASS_EXTENDS_IMPLEMENTS = 0x14; - int CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY = 0x15; - int THROWS = 0x16; - int THROWS_GENERIC_OR_ARRAY = 0x17; - int WILDCARD_BOUND = 0x1C; - int WILDCARD_BOUND_GENERIC_OR_ARRAY = 0x1D; - int METHOD_TYPE_PARAMETER = 0x20; - int METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY = 0x21; - int CLASS_TYPE_PARAMETER = 0x22; - int CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY = 0x23; - int TYPE_CAST = 0x00; - int TYPE_CAST_GENERIC_OR_ARRAY = 0x01; - int TYPE_INSTANCEOF = 0x02; - int TYPE_INSTANCEOF_GENERIC_OR_ARRAY = 0x03; - int OBJECT_CREATION = 0x04; - int OBJECT_CREATION_GENERIC_OR_ARRAY = 0x05; - int LOCAL_VARIABLE = 0x08; - int LOCAL_VARIABLE_GENERIC_OR_ARRAY = 0x09; - int TYPE_ARGUMENT_CONSTRUCTOR_CALL = 0x18; - int TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY = 0x19; - int TYPE_ARGUMENT_METHOD_CALL = 0x1A; - int TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY = 0x1B; - int CLASS_LITERAL = 0x1E; - int CLASS_LITERAL_GENERIC_OR_ARRAY = 0x1F; + + // Targets for type parameter declarations + int CLASS_TYPE_PARAMETER = 0x00; + int METHOD_TYPE_PARAMETER = 0x01; + + // Targets that may be externally visible in classes and members + int CLASS_EXTENDS = 0x10; + int CLASS_TYPE_PARAMETER_BOUND = 0x11; + int METHOD_TYPE_PARAMETER_BOUND = 0x12; + int FIELD = 0x13; + int METHOD_RETURN = 0x14; + int METHOD_RECEIVER = 0x15; + int METHOD_FORMAL_PARAMETER = 0x16; + int THROWS = 0x17; + + // Targets for type uses that occur only within code blocks + int LOCAL_VARIABLE = 0x40; + int RESOURCE_VARIABLE = 0x41; + int EXCEPTION_PARAMETER = 0x42; + int INSTANCEOF = 0x43; + int NEW = 0x44; + int CONSTRUCTOR_REFERENCE = 0x45; + int METHOD_REFERENCE = 0x46; + int CAST = 0x47; + int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; + int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; + int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; + int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; + } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java index 48f2e7a4b..6558a942e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java @@ -22,6 +22,8 @@ * bug 391376 - [1.8] check interaction of default methods with bridge methods and generics * Jesper S Moller - Contributions for * Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335 + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; @@ -692,9 +694,11 @@ public void checkcast(int baseId) { writeUnsignedShort(this.constantPool.literalIndexForType(ConstantPool.JavaLangBooleanConstantPoolName)); } } + public void checkcast(TypeBinding typeBinding) { this.checkcast(null, typeBinding); } + public void checkcast(TypeReference typeReference, TypeBinding typeBinding) { /* We use a slightly sub-optimal generation for intersection casts by resorting to a runtime cast for every intersecting type, but in reality this should not matter. In its intended use form such as (I & Serializable) () -> {}, no cast is emitted at all @@ -710,6 +714,7 @@ public void checkcast(TypeReference typeReference, TypeBinding typeBinding) { writeUnsignedShort(this.constantPool.literalIndexForType(types[i])); } } + public void d2f() { this.countLabels = 0; this.stackDepth--; @@ -1774,13 +1779,11 @@ public void generateBoxingConversion(int unboxedTypeID) { } } } -public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBinding syntheticFieldBinding) { - this.generateClassLiteralAccessForType(null, accessedType, syntheticFieldBinding); -} + /** * Macro for building a class descriptor object */ -public void generateClassLiteralAccessForType(TypeReference typeReference, TypeBinding accessedType, FieldBinding syntheticFieldBinding) { +public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBinding syntheticFieldBinding) { if (accessedType.isBaseType() && accessedType != TypeBinding.NULL) { getTYPE(accessedType.id); return; @@ -2570,7 +2573,7 @@ public void generateSyntheticBodyForFactoryMethod(SyntheticMethodBinding methodB public void generateSyntheticBodyForEnumValueOf(SyntheticMethodBinding methodBinding) { initializeMaxLocals(methodBinding); final ReferenceBinding declaringClass = methodBinding.declaringClass; - generateClassLiteralAccessForType(null, declaringClass, null); + generateClassLiteralAccessForType(declaringClass, null); aload_0(); invokeJavaLangEnumvalueOf(declaringClass); this.checkcast(declaringClass); @@ -4052,11 +4055,17 @@ public boolean inlineForwardReferencesFromLabelsTargeting(BranchLabel targetLabe } return (chaining & (L_OPTIMIZABLE|L_CANNOT_OPTIMIZE)) == L_OPTIMIZABLE; // check was some standards, and no case/recursive } + +/** + * We didn't call it instanceof because there is a conflict with the + * instanceof keyword + */ public void instance_of(TypeBinding typeBinding) { this.instance_of(null, typeBinding); } + /** - * We didn't call it instanceof because there is a conflit with the + * We didn't call it instanceof because there is a conflict with the * instanceof keyword */ public void instance_of(TypeReference typeReference, TypeBinding typeBinding) { @@ -4102,7 +4111,12 @@ protected void invoke(byte opcode, int receiverAndArgsSize, int returnTypeSize, this.stackMax = this.stackDepth; } } + public void invokeDynamic(int bootStrapIndex, int argsSize, int returnTypeSize, char[] selector, char[] signature) { + this.invokeDynamic(bootStrapIndex, argsSize, returnTypeSize, selector, signature, false, null, null); +} + +public void invokeDynamic(int bootStrapIndex, int argsSize, int returnTypeSize, char[] selector, char[] signature, boolean isConstructorReference, TypeReference lhsTypeReference, TypeReference [] typeArguments) { if (this.classFileOffset + 4 >= this.bCodeStream.length) { resizeByteArray(); } @@ -4117,6 +4131,11 @@ public void invokeDynamic(int bootStrapIndex, int argsSize, int returnTypeSize, this.stackMax = this.stackDepth; } } + +public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass) { + this.invoke(opcode, methodBinding, declaringClass, null); +} + public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass, TypeReference[] typeArguments) { if (declaringClass == null) declaringClass = methodBinding.declaringClass; if ((declaringClass.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { @@ -4163,7 +4182,7 @@ public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declari default: receiverAndArgsSize++; break; - } + } } } } @@ -4265,10 +4284,6 @@ public void invokeGetTeam(ReferenceBinding roleIfc) { } // SH} -public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass) { - this.invoke(opcode, methodBinding, declaringClass, null); -} - protected void invokeAccessibleObjectSetAccessible() { // invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V; invoke( @@ -5907,9 +5922,11 @@ public void monitorexit() { this.position++; this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_monitorexit; } + public void multianewarray(TypeBinding typeBinding, int dimensions) { this.multianewarray(null, typeBinding, dimensions, null); } + public void multianewarray( TypeReference typeReference, TypeBinding typeBinding, @@ -5930,9 +5947,11 @@ public void multianewarray( // SH} this.bCodeStream[this.classFileOffset++] = (byte) dimensions; } +// We didn't call it new, because there is a conflit with the new keyword public void new_(TypeBinding typeBinding) { this.new_(null, typeBinding); } + // We didn't call it new, because there is a conflit with the new keyword public void new_(TypeReference typeReference, TypeBinding typeBinding) { this.countLabels = 0; @@ -5961,10 +5980,16 @@ public void newarray(int array_Type) { this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_newarray; this.bCodeStream[this.classFileOffset++] = (byte) array_Type; } + public void newArray(ArrayBinding arrayBinding) { this.newArray(null, arrayBinding); } + public void newArray(TypeReference typeReference, ArrayBinding arrayBinding) { + this.newArray(null, null, arrayBinding); +} + +public void newArray(TypeReference typeReference, Annotation[][] annotationsOnDimensions, ArrayBinding arrayBinding) { TypeBinding component = arrayBinding.elementsType(); switch (component.id) { case TypeIds.T_int : diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java index 7c2639725..e6e619d1f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java @@ -1,16 +1,23 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 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 * http://www.eclipse.org/legal/epl-v10.html * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; public class ExceptionLabel extends Label { @@ -18,6 +25,13 @@ public class ExceptionLabel extends Label { public int ranges[] = {POS_NOT_SET,POS_NOT_SET}; private int count = 0; // incremented each time placeStart or placeEnd is called public TypeBinding exceptionType; + public TypeReference exceptionTypeReference; + +public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType, TypeReference exceptionTypeReference) { + super(codeStream); + this.exceptionType = exceptionType; + this.exceptionTypeReference = exceptionTypeReference; +} public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType) { super(codeStream); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java index 2d0fc549e..21fc79f2b 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java @@ -1,15 +1,23 @@ /******************************************************************************* - * Copyright (c) 2011 IBM Corporation and others. + * Copyright (c) 2011, 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 * http://www.eclipse.org/legal/epl-v10.html * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; +import java.util.List; + import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; @@ -27,7 +35,7 @@ public class MultiCatchExceptionLabel extends ExceptionLabel { int length = typeReferences.length; this.exceptionLabels = new ExceptionLabel[length]; for (int i = 0; i < length; i++) { - this.exceptionLabels[i] = new ExceptionLabel(this.codeStream, typeReferences[i].resolvedType); + this.exceptionLabels[i] = new ExceptionLabel(this.codeStream, typeReferences[i].resolvedType, typeReferences[i]); } } public void place() { @@ -52,4 +60,16 @@ public class MultiCatchExceptionLabel extends ExceptionLabel { } return temp; } + + public int getAllAnnotationContexts(int tableIndex, List allTypeAnnotationContexts) { + int localCount = 0; + for (int i = 0, max = this.exceptionLabels.length; i < max; i++) { + ExceptionLabel exceptionLabel = this.exceptionLabels[i]; + if (exceptionLabel.exceptionTypeReference != null) { // ignore those which cannot be annotated + exceptionLabel.exceptionTypeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.EXCEPTION_PARAMETER, tableIndex + localCount, allTypeAnnotationContexts); + } + tableIndex++; + } + return localCount; + } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java index aab6d3a31..e1fb841c2 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. + * Copyright (c) 2012, 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 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; @@ -23,7 +25,6 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; -import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; @@ -35,82 +36,104 @@ public class TypeAnnotationCodeStream extends StackMapFrameCodeStream { this.generateAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION; this.allTypeAnnotationContexts = new ArrayList(); } - private void addAnnotationContext(TypeReference typeReference, int info, int targetType, Annotation[][] annotationsOnDimensions) { -// if (this.allTypeAnnotationContexts == null) { -// this.allTypeAnnotationContexts = new ArrayList(); -// } - typeReference.getAllAnnotationContexts(targetType, info, this.allTypeAnnotationContexts, annotationsOnDimensions); + + private void addAnnotationContext(TypeReference typeReference, int info, int targetType, Annotation[][] annotationsOnDimensions, int dimensions) { + typeReference.getAllAnnotationContexts(targetType, info, this.allTypeAnnotationContexts, annotationsOnDimensions, dimensions); } + private void addAnnotationContext(TypeReference typeReference, int info, int targetType) { -// if (this.allTypeAnnotationContexts == null) { -// this.allTypeAnnotationContexts = new ArrayList(); -// } typeReference.getAllAnnotationContexts(targetType, info, this.allTypeAnnotationContexts); } + private void addAnnotationContext(TypeReference typeReference, int info, int typeIndex, int targetType) { -// if (this.allTypeAnnotationContexts == null) { -// this.allTypeAnnotationContexts = new ArrayList(); -// } typeReference.getAllAnnotationContexts(targetType, info, typeIndex, this.allTypeAnnotationContexts); } + public void instance_of(TypeReference typeReference, TypeBinding typeBinding) { if (typeReference != null && (typeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.TYPE_INSTANCEOF); + addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.INSTANCEOF); } super.instance_of(typeReference, typeBinding); } + public void multianewarray( TypeReference typeReference, TypeBinding typeBinding, int dimensions, Annotation [][] annotationsOnDimensions) { if (typeReference != null && (typeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.OBJECT_CREATION, annotationsOnDimensions); + addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.NEW, annotationsOnDimensions, dimensions); } super.multianewarray(typeReference, typeBinding, dimensions, annotationsOnDimensions); } + public void new_(TypeReference typeReference, TypeBinding typeBinding) { if (typeReference != null && (typeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.OBJECT_CREATION); + addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.NEW); } super.new_(typeReference, typeBinding); } - public void newArray(TypeReference typeReference, ArrayBinding arrayBinding) { - if (typeReference != null && (typeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.OBJECT_CREATION); - } - super.newArray(typeReference, arrayBinding); - } - public void generateClassLiteralAccessForType(TypeReference typeReference, TypeBinding accessedType, FieldBinding syntheticFieldBinding) { + + public void newArray(TypeReference typeReference, Annotation[][] annotationsOnDimensions, ArrayBinding arrayBinding) { if (typeReference != null && (typeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.CLASS_LITERAL); + addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.NEW, annotationsOnDimensions, 1); } - super.generateClassLiteralAccessForType(typeReference, accessedType, syntheticFieldBinding); + super.newArray(typeReference, annotationsOnDimensions, arrayBinding); } + public void checkcast(TypeReference typeReference, TypeBinding typeBinding) { if (typeReference != null && (typeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.TYPE_CAST); + addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.CAST); } super.checkcast(typeReference, typeBinding); } - public void reset(ClassFile givenClassFile) { - super.reset(givenClassFile); - this.allTypeAnnotationContexts = new ArrayList(); - } - public void init(ClassFile targetClassFile) { - super.init(targetClassFile); - this.allTypeAnnotationContexts = new ArrayList(); - } + public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass, TypeReference[] typeArguments) { if (typeArguments != null) { int targetType = methodBinding.isConstructor() - ? AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL - : AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL; + ? AnnotationTargetTypeConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + : AnnotationTargetTypeConstants.METHOD_INVOCATION_TYPE_ARGUMENT; for (int i = 0, max = typeArguments.length; i < max; i++) { TypeReference typeArgument = typeArguments[i]; - addAnnotationContext(typeArgument, this.position, i, targetType); + if ((typeArgument.bits & ASTNode.HasTypeAnnotations) != 0) { // TODO can check this at a higher level? + addAnnotationContext(typeArgument, this.position, i, targetType); + } } } super.invoke(opcode, methodBinding, declaringClass, typeArguments); } + + public void invokeDynamic(int bootStrapIndex, int argsSize, int returnTypeSize, char[] selector, char[] signature, + boolean isConstructorReference, TypeReference lhsTypeReference, TypeReference [] typeArguments) { + if (lhsTypeReference != null && (lhsTypeReference.bits & ASTNode.HasTypeAnnotations) != 0) { + if (isConstructorReference) { + addAnnotationContext(lhsTypeReference, this.position, 0, AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE); + } else { + addAnnotationContext(lhsTypeReference, this.position, 0, AnnotationTargetTypeConstants.METHOD_REFERENCE); + } + } + if (typeArguments != null) { + int targetType = + isConstructorReference + ? AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + : AnnotationTargetTypeConstants.METHOD_REFERENCE_TYPE_ARGUMENT; + for (int i = 0, max = typeArguments.length; i < max; i++) { + TypeReference typeArgument = typeArguments[i]; + if ((typeArgument.bits & ASTNode.HasTypeAnnotations) != 0) { + addAnnotationContext(typeArgument, this.position, i, targetType); + } + } + } + super.invokeDynamic(bootStrapIndex, argsSize, returnTypeSize, selector, signature, isConstructorReference, lhsTypeReference, typeArguments); + } + + public void reset(ClassFile givenClassFile) { + super.reset(givenClassFile); + this.allTypeAnnotationContexts = new ArrayList(); + } + + public void init(ClassFile targetClassFile) { + super.init(targetClassFile); + this.allTypeAnnotationContexts = new ArrayList(); + } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java index 6b822c45f..97db2c9d7 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java @@ -37,7 +37,6 @@ import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.objectteams.otdt.core.compiler.IOTConstants; import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AnchorListAttribute; -import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates; import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleBridgeMethodBinding; import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel; import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel; @@ -1703,14 +1702,7 @@ public AbstractMethodDeclaration sourceMethod() { return null; } -//{ObjectTeams: more robust this way!?! -/* orig: - AbstractMethodDeclaration[] methods = sourceType.scope.referenceContext.methods; - :giro */ - if (sourceType.model.getState() == ITranslationStates.STATE_FINAL) - return null; // no source available any more - AbstractMethodDeclaration[] methods = sourceType.model.getAst().methods; -// SH} + AbstractMethodDeclaration[] methods = sourceType.scope != null ? sourceType.scope.referenceContext.methods : null; if (methods != null) { for (int i = methods.length; --i >= 0;) if (this == methods[i].binding) diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java index a23a7dd9f..276a9b7a3 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java @@ -1441,6 +1441,19 @@ public final class AST { // km(merge) } /** + * Creates an unparented creation reference node owned by this AST. + * By default, the type is unspecified (but legal), and there are no type arguments. + * + * @return a new unparented creation reference expression node + * @exception UnsupportedOperationException if this operation is used in a JLS2, JLS3 or JLS4 AST + * @since 3.9 BETA_JAVA8 + */ + public CreationReference newCreationReference() { + CreationReference result = new CreationReference(this); + return result; + } + + /** * Creates a new unparented do statement node owned by this AST. * By default, the expression is unspecified (but legal), and * the body statement is an empty block. @@ -1508,6 +1521,20 @@ public final class AST { } /** + * Creates an unparented expression method reference node owned by this AST. + * By default, the expression and method name are unspecified (but legal), + * and there are no type arguments. + * + * @return a new unparented expression method reference expression node + * @exception UnsupportedOperationException if this operation is used in a JLS2, JLS3 or JLS4 AST + * @since 3.9 BETA_JAVA8 + */ + public ExpressionMethodReference newExpressionMethodReference() { + ExpressionMethodReference result = new ExpressionMethodReference(this); + return result; + } + + /** * Creates a new unparented expression statement node owned by this AST, * for the given expression. * <p> @@ -2424,7 +2451,7 @@ public final class AST { /** * Creates an unparented "super" method invocation expression node owned by - * this AST. By default, the name of the method is unspecified (but legal) + * this AST. By default, the name of the method is unspecified (but legal), * there is no qualifier, no type arguments, and the list of arguments is empty. * * @return a new unparented "super" method invocation @@ -2436,6 +2463,19 @@ public final class AST { } /** + * Creates and returns a new unparented super method reference node owned by + * this AST. By default, the name of the method is unspecified (but legal), + * and there is no qualifier and no type arguments. + * + * @return a new unparented super method reference node + * @since 3.9 BETA_JAVA8 + */ + public SuperMethodReference newSuperMethodReference() { + SuperMethodReference result = new SuperMethodReference(this); + return result; + } + + /** * Creates a new unparented switch case statement node owned by * this AST. By default, the expression is unspecified, but legal. * @@ -2643,6 +2683,20 @@ public final class AST { } /** + * Creates an unparented type method reference node owned by this AST. + * By default, the type and method name are unspecified (but legal), + * and there are no type arguments. + * + * @return a new unparented type method reference node + * @exception UnsupportedOperationException if this operation is used in a JLS2, JLS3 or JLS4 AST + * @since 3.9 BETA_JAVA8 + */ + public TypeMethodReference newTypeMethodReference() { + TypeMethodReference result = new TypeMethodReference(this); + return result; + } + + /** * Creates and returns a new unparented type parameter type node with an * unspecified type variable name and an empty list of type bounds. * diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java index fda33cd2f..d10a185f9 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java @@ -53,11 +53,13 @@ import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; +import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.Receiver; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation; +import org.eclipse.jdt.internal.compiler.ast.SuperReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; import org.eclipse.jdt.internal.compiler.ast.Wildcard; @@ -1955,6 +1957,9 @@ class ASTConverter { if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LambdaExpression) { return convert((org.eclipse.jdt.internal.compiler.ast.LambdaExpression) expression); } + if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) { + return convert((org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) expression); + } //{ObjectTeams: more expressions: if (expression instanceof org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallMessageSend) { @@ -2448,13 +2453,7 @@ class ASTConverter { public Expression convert(org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambda) { if (this.ast.apiLevel < AST.JLS8) { - if (this.referenceContext != null) { - this.referenceContext.setFlags(this.referenceContext.getFlags() | ASTNode.MALFORMED); - } - NullLiteral nullLiteral = new NullLiteral(this.ast); - nullLiteral.setFlags(nullLiteral.getFlags() | ASTNode.MALFORMED); - nullLiteral.setSourceRange(lambda.sourceStart, lambda.sourceEnd - lambda.sourceStart + 1); - return nullLiteral; + return createFakeNullLiteral(lambda); } final LambdaExpression lambdaExpression = new LambdaExpression(this.ast); if (this.resolveBindings) { @@ -2813,6 +2812,79 @@ class ASTConverter { return null; // cannot be reached } + public Expression convert(org.eclipse.jdt.internal.compiler.ast.ReferenceExpression reference) { + if (this.ast.apiLevel < AST.JLS8) { + return createFakeNullLiteral(reference); + } + Expression result = null; + org.eclipse.jdt.internal.compiler.ast.Expression lhs = reference.lhs; + org.eclipse.jdt.internal.compiler.ast.TypeReference[] arguments = reference.typeArguments; + int start = arguments != null && arguments.length > 0 ? arguments[arguments.length - 1].sourceEnd + 1 : reference.lhs.sourceEnd + 1; + final SimpleName name = new SimpleName(this.ast); + retrieveIdentifierAndSetPositions(start, reference.sourceEnd, name); + name.internalSetIdentifier(new String(reference.selector)); + if (this.resolveBindings) { + recordNodes(name, reference); + } + List typeArguments = null; + if (name.getStartPosition() == -1 && name.getIdentifier().equals("<init>")) { // check for "new" //$NON-NLS-1$ + retrieveInitAndSetPositions(start, reference.sourceEnd, name); + Type type = null; + if (lhs instanceof TypeReference) { + type = convertType((TypeReference) lhs); + } else if (lhs instanceof NameReference) { + Name typeName = convert((NameReference) lhs); + SimpleType simpleType = new SimpleType(this.ast); + simpleType.setName(typeName); + if (this.resolveBindings) { + recordNodes(simpleType, lhs); + } + simpleType.setSourceRange(lhs.sourceStart, lhs.sourceEnd - lhs.sourceStart + 1); + type = simpleType; + } + CreationReference creationReference = new CreationReference(this.ast); + creationReference.setType(type); + typeArguments = creationReference.typeArguments(); + result = creationReference; + } else if (lhs instanceof TypeReference) { + TypeMethodReference typeMethodReference = new TypeMethodReference(this.ast); + typeMethodReference.setType(convertType((TypeReference) lhs)); + typeMethodReference.setName(name); + typeArguments = typeMethodReference.typeArguments(); + result = typeMethodReference; + } else if (lhs instanceof SuperReference) { + SuperMethodReference superMethodReference = new SuperMethodReference(this.ast); + superMethodReference.setName(name); + typeArguments = superMethodReference.typeArguments(); + result = superMethodReference; + } else if (lhs instanceof QualifiedSuperReference) { + SuperMethodReference superMethodReference = new SuperMethodReference(this.ast); + superMethodReference.setQualifier(convert((QualifiedSuperReference)lhs)); + superMethodReference.setName(name); + typeArguments = superMethodReference.typeArguments(); + result = superMethodReference; + } else { + ExpressionMethodReference expressionMethodReference = new ExpressionMethodReference(this.ast); + expressionMethodReference.setExpression(convert(lhs)); + typeArguments = expressionMethodReference.typeArguments(); + expressionMethodReference.setName(name); + result = expressionMethodReference; + } + if (typeArguments != null && arguments != null) { + int argumentsLength = arguments.length; + for (int i = 0; i < argumentsLength; i++) { + org.eclipse.jdt.internal.compiler.ast.TypeReference argument = arguments[i]; + typeArguments.add(convertType(argument)); + } + } + if (this.resolveBindings) { + recordNodes(result, reference); + } + int sourceStart = reference.sourceStart; + result.setSourceRange(sourceStart, reference.sourceEnd - sourceStart + 1); + return result; + } + public ReturnStatement convert(org.eclipse.jdt.internal.compiler.ast.ReturnStatement statement) { final ReturnStatement returnStatement = new ReturnStatement(this.ast); returnStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1); @@ -4274,6 +4346,21 @@ class ASTConverter { emptyStatement.setSourceRange(start, end - start + 1); return emptyStatement; } + + /** + * Warning: Callers of this method must ensure that the fake literal node is not recorded in + * {@link #recordNodes(ASTNode, org.eclipse.jdt.internal.compiler.ast.ASTNode)}, see bug 403444! + */ + protected Expression createFakeNullLiteral(org.eclipse.jdt.internal.compiler.ast.FunctionalExpression expression) { + if (this.referenceContext != null) { + this.referenceContext.setFlags(this.referenceContext.getFlags() | ASTNode.MALFORMED); + } + NullLiteral nullLiteral = new NullLiteral(this.ast); + nullLiteral.setFlags(nullLiteral.getFlags() | ASTNode.MALFORMED); + nullLiteral.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1); + return nullLiteral; + } + /** * @return a new modifier */ @@ -4564,8 +4651,8 @@ class ASTConverter { } protected void recordNodes(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) { - // Do not record the fake literal node created in lieu of LambdaExpressions at JLS levels < 8, as it would lead to CCE down the road. - if (oldASTNode instanceof org.eclipse.jdt.internal.compiler.ast.LambdaExpression && node instanceof NullLiteral) { + // Do not record the fake literal node created in lieu of functional expressions at JLS levels < 8, as it would lead to CCE down the road. + if (oldASTNode instanceof org.eclipse.jdt.internal.compiler.ast.FunctionalExpression && node instanceof NullLiteral) { return; } this.ast.getBindingResolver().store(node, oldASTNode); @@ -4924,7 +5011,7 @@ class ASTConverter { } /** - * This method is used to retrieve the start and end position of a name. + * This method is used to retrieve the start and end position of a name or primitive type token. * * @return int[] a single dimensional array, with two elements, for the start and end positions of the name respectively */ @@ -5100,6 +5187,29 @@ class ASTConverter { } /** + * retrieves the start and and of new and set the positions of the name + * @param start position to start search + * @param end position to end search + * @param name object where these positions will be updated. + */ + protected void retrieveInitAndSetPositions(int start, int end, Name name) { + this.scanner.resetTo(start, end); + int token; + try { + while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) { + if (token == TerminalTokens.TokenNamenew) { + int startName = this.scanner.startPosition; + int endName = this.scanner.currentPosition; + name.setSourceRange(startName, endName - startName); + return; + } + } + } catch(InvalidInputException e) { + // ignore + } + } + + /** * This method is used to retrieve position before the next comma or semi-colon. * @param initializerEnd the given initializer end exclusive * @return int the position found. diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java index 939a76827..23ca2f33c 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java @@ -703,6 +703,31 @@ public class ASTMatcher { * @return <code>true</code> if the subtree matches, or * <code>false</code> if they do not match or the other object has a * different node type or is <code>null</code> + * @since 3.9 BETA_JAVA8 + */ + public boolean match(CreationReference node, Object other) { + if (!(other instanceof CreationReference)) { + return false; + } + CreationReference o = (CreationReference) other; + return ( + safeSubtreeMatch(node.getType(), o.getType()) + && safeSubtreeListMatch(node.typeArguments(), o.typeArguments())); + } + + /** + * Returns whether the given node and the other object match. + * <p> + * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + * </p> + * + * @param node the node + * @param other the other object, or <code>null</code> + * @return <code>true</code> if the subtree matches, or + * <code>false</code> if they do not match or the other object has a + * different node type or is <code>null</code> */ public boolean match(DoStatement node, Object other) { if (!(other instanceof DoStatement)) { @@ -835,6 +860,32 @@ public class ASTMatcher { * @return <code>true</code> if the subtree matches, or * <code>false</code> if they do not match or the other object has a * different node type or is <code>null</code> + * @since 3.9 BETA_JAVA8 + */ + public boolean match(ExpressionMethodReference node, Object other) { + if (!(other instanceof ExpressionMethodReference)) { + return false; + } + ExpressionMethodReference o = (ExpressionMethodReference) other; + return ( + safeSubtreeMatch(node.getExpression(), o.getExpression()) + && safeSubtreeListMatch(node.typeArguments(), o.typeArguments()) + && safeSubtreeMatch(node.getName(), o.getName())); + } + + /** + * Returns whether the given node and the other object match. + * <p> + * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + * </p> + * + * @param node the node + * @param other the other object, or <code>null</code> + * @return <code>true</code> if the subtree matches, or + * <code>false</code> if they do not match or the other object has a + * different node type or is <code>null</code> */ public boolean match(ExpressionStatement node, Object other) { if (!(other instanceof ExpressionStatement)) { @@ -2028,6 +2079,32 @@ public class ASTMatcher { * @return <code>true</code> if the subtree matches, or * <code>false</code> if they do not match or the other object has a * different node type or is <code>null</code> + * + * @since 3.9 BETA_JAVA8 + */ + public boolean match(SuperMethodReference node, Object other) { + if (!(other instanceof SuperMethodReference)) { + return false; + } + SuperMethodReference o = (SuperMethodReference) other; + return (safeSubtreeMatch(node.getQualifier(), o.getQualifier()) + && safeSubtreeListMatch(node.typeArguments(), o.typeArguments()) + && safeSubtreeMatch(node.getName(), o.getName())); + } + + /** + * Returns whether the given node and the other object match. + * <p> + * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + * </p> + * + * @param node the node + * @param other the other object, or <code>null</code> + * @return <code>true</code> if the subtree matches, or + * <code>false</code> if they do not match or the other object has a + * different node type or is <code>null</code> */ public boolean match(SwitchCase node, Object other) { if (!(other instanceof SwitchCase)) { @@ -2320,6 +2397,32 @@ public class ASTMatcher { * @return <code>true</code> if the subtree matches, or * <code>false</code> if they do not match or the other object has a * different node type or is <code>null</code> + * @since 3.9 BETA_JAVA8 + */ + public boolean match(TypeMethodReference node, Object other) { + if (!(other instanceof TypeMethodReference)) { + return false; + } + TypeMethodReference o = (TypeMethodReference) other; + return ( + safeSubtreeMatch(node.getType(), o.getType()) + && safeSubtreeListMatch(node.typeArguments(), o.typeArguments()) + && safeSubtreeMatch(node.getName(), o.getName())); + } + + /** + * Returns whether the given node and the other object match. + * <p> + * The default implementation provided by this class tests whether the + * other object is a node of the same type with structurally isomorphic + * child subtrees. Subclasses may override this method as needed. + * </p> + * + * @param node the node + * @param other the other object, or <code>null</code> + * @return <code>true</code> if the subtree matches, or + * <code>false</code> if they do not match or the other object has a + * different node type or is <code>null</code> * @since 3.1 */ public boolean match(TypeParameter node, Object other) { diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java index c206fd6b3..5b264d788 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java @@ -869,6 +869,38 @@ public abstract class ASTNode { */ public static final int PACKAGE_QUALIFIED_TYPE = 88; + /** + * Node type constant indicating a node of type + * <code>CreationReference</code>. + * @see CreationReference + * @since 3.9 BETA_JAV8 + */ + public static final int CREATION_REFERENCE = 89; + + /** + * Node type constant indicating a node of type + * <code>ExpressionMethodReference</code>. + * @see ExpressionMethodReference + * @since 3.9 BETA_JAV8 + */ + public static final int EXPRESSION_METHOD_REFERENCE = 90; + + /** + * Node type constant indicating a node of type + * <code>SuperMethhodReference</code>. + * @see SuperMethodReference + * @since 3.9 BETA_JAV8 + */ + public static final int SUPER_METHOD_REFERENCE = 91; + + /** + * Node type constant indicating a node of type + * <code>TypeMethodReference</code>. + * @see TypeMethodReference + * @since 3.9 BETA_JAV8 + */ + public static final int TYPE_METHOD_REFERENCE = 92; + //{ObjectTeams: required OT specific node type constants added /** @@ -876,93 +908,93 @@ public abstract class ASTNode { * <code>MethodSpec</code>. * @see MethodSpec */ - public static final int METHOD_SPEC = 89; + public static final int METHOD_SPEC = 93; /** * Node type constant indicating a node of type * <code>CallinMappingDeclaration</code>. * @see CallinMappingDeclaration */ - public static final int CALLIN_MAPPING_DECLARATION = 90; + public static final int CALLIN_MAPPING_DECLARATION = 94; /** * Node type constant indicating a node of type * <code>CalloutMappingDeclaration</code>. * @see CalloutMappingDeclaration */ - public static final int CALLOUT_MAPPING_DECLARATION = 91; + public static final int CALLOUT_MAPPING_DECLARATION = 95; /** * Node type constant indicating a node of type * <code>LiftingType</code>. * @see LiftingType */ - public static final int LIFTING_TYPE = 92; + public static final int LIFTING_TYPE = 96; /** * Node type constant indicating a node of type * <code>WithinStatement</code>. * @see WithinStatement */ - public static final int WITHIN_STATEMENT = 93; + public static final int WITHIN_STATEMENT = 97; /** * Node type constant indicating a node of type * <code>BaseConstructorMessageSend</code>. * @see BaseConstructorInvocation */ - public static final int BASE_CONSTRUCTOR_INVOCATION = 94; + public static final int BASE_CONSTRUCTOR_INVOCATION = 98; /** * Node type constant indicating a node of type * <code>ParameterMapping</code>. * @see ParameterMapping */ - public static final int PARAMETER_MAPPING = 95; + public static final int PARAMETER_MAPPING = 99; /** * Node type constant indicating a node of type * <code>BaseCallMessageSend</code>. * @see BaseCallMessageSend */ - public static final int BASE_CALL_MESSAGE_SEND = 96; + public static final int BASE_CALL_MESSAGE_SEND = 100; /** * Node type constant indicating a node of type * <code>FieldAccessSpec</code>. * @see FieldAccessSpec */ - public static final int FIELD_ACCESS_SPEC = 97; + public static final int FIELD_ACCESS_SPEC = 101; /** * Node type constant indicating a node of type * <code>RoleTypeDelaration</code>. * @see RoleTypeDeclaration */ - public static final int ROLE_TYPE_DECLARATION = 98; + public static final int ROLE_TYPE_DECLARATION = 102; /** * Node type constant indicating a node of type * <code>TSuperMessageSend</code>. * @see TSuperMessageSend */ - public static final int TSUPER_MESSAGE_SEND = 99; + public static final int TSUPER_MESSAGE_SEND = 103; /** * Node type constant indicating a node of type * <code>TSuperCallMessageSend</code>. * @see TSuperMessageSend */ - public static final int TSUPER_CONSTRUCTOR_INVOCATION = 100; + public static final int TSUPER_CONSTRUCTOR_INVOCATION = 104; - public static final int TYPE_ANCHOR = 101; + public static final int TYPE_ANCHOR = 105; - public static final int PRECEDENCE_DECLARATION = 102; + public static final int PRECEDENCE_DECLARATION = 106; - public static final int GUARD_PREDICATE_DECLARATION = 103; + public static final int GUARD_PREDICATE_DECLARATION = 107; /** @since 1.3.1 */ - public static final int METHOD_BINDING_OPERATOR = 104; + public static final int METHOD_BINDING_OPERATOR = 108; //gbr} /** @@ -1019,6 +1051,8 @@ public abstract class ASTNode { return ConstructorInvocation.class; case CONTINUE_STATEMENT : return ContinueStatement.class; + case CREATION_REFERENCE : + return CreationReference.class; case UNION_TYPE : return UnionType.class; case DO_STATEMENT : @@ -1031,6 +1065,8 @@ public abstract class ASTNode { return EnumConstantDeclaration.class; case ENUM_DECLARATION : return EnumDeclaration.class; + case EXPRESSION_METHOD_REFERENCE : + return ExpressionMethodReference.class; case EXPRESSION_STATEMENT : return ExpressionStatement.class; case EXTRA_DIMENSION: @@ -1119,6 +1155,8 @@ public abstract class ASTNode { return SuperFieldAccess.class; case SUPER_METHOD_INVOCATION : return SuperMethodInvocation.class; + case SUPER_METHOD_REFERENCE : + return SuperMethodReference.class; case SWITCH_CASE: return SwitchCase.class; case SWITCH_STATEMENT : @@ -1139,6 +1177,8 @@ public abstract class ASTNode { return TypeDeclaration.class; case TYPE_DECLARATION_STATEMENT : return TypeDeclarationStatement.class; + case TYPE_METHOD_REFERENCE : + return TypeMethodReference.class; case TYPE_LITERAL : return TypeLiteral.class; case TYPE_PARAMETER : diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java index 2272844b7..bb229f5ce 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java @@ -521,6 +521,23 @@ public abstract class ASTVisitor { * Visits the given type-specific AST node. * <p> * The default implementation does nothing and return true. + * Subclasses may re-implement. + * </p> + * + * @param node the node to visit + * @return <code>true</code> if the children of this node should be + * visited, and <code>false</code> if the children of this node should + * be skipped + * @since 3.9 BETA_JAVA8 + */ + public boolean visit(CreationReference node) { + return true; + } + + /** + * Visits the given type-specific AST node. + * <p> + * The default implementation does nothing and return true. * Subclasses may reimplement. * </p> * @@ -603,6 +620,23 @@ public abstract class ASTVisitor { * Visits the given type-specific AST node. * <p> * The default implementation does nothing and return true. + * Subclasses may re-implement. + * </p> + * + * @param node the node to visit + * @return <code>true</code> if the children of this node should be + * visited, and <code>false</code> if the children of this node should + * be skipped + * @since 3.9 BETA_JAVA8 + */ + public boolean visit(ExpressionMethodReference node) { + return true; + } + + /** + * Visits the given type-specific AST node. + * <p> + * The default implementation does nothing and return true. * Subclasses may reimplement. * </p> * @@ -1369,6 +1403,23 @@ public abstract class ASTVisitor { * @return <code>true</code> if the children of this node should be * visited, and <code>false</code> if the children of this node should * be skipped + * @since 3.9 BETA_JAVA8 + */ + public boolean visit(SuperMethodReference node) { + return true; + } + + /** + * Visits the given type-specific AST node. + * <p> + * The default implementation does nothing and return true. + * Subclasses may reimplement. + * </p> + * + * @param node the node to visit + * @return <code>true</code> if the children of this node should be + * visited, and <code>false</code> if the children of this node should + * be skipped */ public boolean visit(SwitchCase node) { return true; @@ -1549,6 +1600,24 @@ public abstract class ASTVisitor { * @return <code>true</code> if the children of this node should be * visited, and <code>false</code> if the children of this node should * be skipped + * + * @since 3.9 BETA_JAVA8 + */ + public boolean visit(TypeMethodReference node) { + return true; + } + + /** + * Visits the given type-specific AST node. + * <p> + * The default implementation does nothing and return true. + * Subclasses may reimplement. + * </p> + * + * @param node the node to visit + * @return <code>true</code> if the children of this node should be + * visited, and <code>false</code> if the children of this node should + * be skipped * @since 3.1 */ public boolean visit(TypeParameter node) { @@ -2182,6 +2251,19 @@ public abstract class ASTVisitor { * </p> * * @param node the node to visit + * @since 3.9 BETA_JAVA8 + */ + public void endVisit(CreationReference node) { + // default implementation: do nothing + } + + /** + * End of visit the given type-specific AST node. + * <p> + * The default implementation does nothing. Subclasses may reimplement. + * </p> + * + * @param node the node to visit */ public void endVisit(DoStatement node) { // default implementation: do nothing @@ -2245,6 +2327,19 @@ public abstract class ASTVisitor { * </p> * * @param node the node to visit + * @since 3.9 BETA_JAVA8 + */ + public void endVisit(ExpressionMethodReference node) { + // default implementation: do nothing + } + + /** + * End of visit the given type-specific AST node. + * <p> + * The default implementation does nothing. Subclasses may reimplement. + * </p> + * + * @param node the node to visit */ public void endVisit(ExpressionStatement node) { // default implementation: do nothing @@ -2780,6 +2875,19 @@ public abstract class ASTVisitor { * </p> * * @param node the node to visit + * @since 3.9 BETA_JAVA8 + */ + public void endVisit(SuperMethodReference node) { + // default implementation: do nothing + } + + /** + * End of visit the given type-specific AST node. + * <p> + * The default implementation does nothing. Subclasses may reimplement. + * </p> + * + * @param node the node to visit */ public void endVisit(SwitchCase node) { // default implementation: do nothing @@ -2913,6 +3021,20 @@ public abstract class ASTVisitor { * </p> * * @param node the node to visit + * + * @since 3.9 BETA_JAVA8 + */ + public void endVisit(TypeMethodReference node) { + // default implementation: do nothing + } + + /** + * End of visit the given type-specific AST node. + * <p> + * The default implementation does nothing. Subclasses may reimplement. + * </p> + * + * @param node the node to visit * @since 3.1 */ public void endVisit(TypeParameter node) { diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java index c62d5104c..8b2c16dbe 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotatableType.java @@ -17,7 +17,7 @@ package org.eclipse.jdt.core.dom; import java.util.List; /** - * Type node for an annotatable type (added in JLS8 API). + * Abstract base class of AST nodes that represent an annotatable type (added in JLS8 API). * <p> * Introduced in JLS8, type references that can be annotated are represented by * AnnotatableType. For the list of types extending AnnotatableType, see {@link Type}.</p> diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java index 19ffcc045..585dcda3b 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java @@ -589,6 +589,28 @@ class BindingResolver { } /** + * Resolves the given method reference and returns the binding for it. + * <p> + * The implementation of <code>MethodReference.resolveMethodBinding</code> + * forwards to this method. How the method resolves is often a function of + * the context in which the method reference node is embedded as well as + * the method reference subtree itself. + * </p> + * <p> + * The default implementation of this method returns <code>null</code>. + * Subclasses may reimplement. + * </p> + * + * @param methodReference the method reference of interest + * @return the binding for the given method reference, or + * <code>null</code> if no binding is available + * @since 3.9 BETA_JAVA8 + */ + IMethodBinding resolveMethod(MethodReference methodReference) { + return null; + } + + /** * Resolves the given Lambda Expression and returns the binding for it. * <p> * The implementation of <code>LambdaExpression.resolveMethodBinding</code> diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CreationReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CreationReference.java new file mode 100644 index 000000000..13602f0dd --- /dev/null +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CreationReference.java @@ -0,0 +1,241 @@ +/******************************************************************************* + * Copyright (c) 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Creation reference expression AST node type (added in JLS8 API). + * + * <pre> + * CreationReference: + * Type <b>::</b> + * [ <b><</b> Type { <b>,</b> Type } <b>></b> ] + * <b>new</b> + * </pre> + * + * @since 3.9 BETA_JAVA8 + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class CreationReference extends MethodReference { + + /** + * The "type" structural property of this node type (child type: {@link Type}). + */ + public static final ChildPropertyDescriptor TYPE_PROPERTY = + new ChildPropertyDescriptor(CreationReference.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "typeArguments" structural property of this node type (element type: {@link Type}) + */ + public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = + internalTypeArgumentsFactory(CreationReference.class); + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_8_0; + + static { + List propertyList = new ArrayList(3); + createPropertyList(CreationReference.class, propertyList); + addProperty(TYPE_PROPERTY, propertyList); + addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the AST.JLS* constants + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_8_0; + } + + /** + * The type; lazily initialized; defaults to an unspecified type. + */ + private Type type = null; + + /** + * Creates a new AST node for an CreationReference declaration owned + * by the given AST. + * <p> + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + * </p> + * + * @param ast the AST that is to own this node + */ + CreationReference(AST ast) { + super(ast); + unsupportedIn2_3_4(); + } + + /* (omit javadoc for this method) + * Method declared on MethodReference. + */ + final ChildListPropertyDescriptor internalTypeArgumentsProperty() { + return TYPE_ARGUMENTS_PROPERTY; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == TYPE_PROPERTY) { + if (get) { + return getType(); + } else { + setType((Type) child); + return null; + } + } + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == TYPE_ARGUMENTS_PROPERTY) { + return typeArguments(); + } + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final int getNodeType0() { + return CREATION_REFERENCE; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + ASTNode clone0(AST target) { + CreationReference result = new CreationReference(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setType((Type) ASTNode.copySubtree(target, getType())); + result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments())); + return result; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + // visit children in normal left to right reading order + acceptChild(visitor, getType()); + acceptChildren(visitor, this.typeArguments); + } + visitor.endVisit(this); + } + + /** + * Returns the type of this creation reference expression. + * + * @return the type node + */ + public Type getType() { + if (this.type == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.type == null) { + preLazyInit(); + this.type = new SimpleType(this.ast); + postLazyInit(this.type, TYPE_PROPERTY); + } + } + } + return this.type; + } + + /** + * Sets the type of this creation reference expression. + * + * @param type the new type node + * @exception IllegalArgumentException if: + * <ul> + * <li>the node belongs to a different AST</li> + * <li>the node already has a parent</li> + * </ul> + */ + public void setType(Type type) { + if (type == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.type; + preReplaceChild(oldChild, type, TYPE_PROPERTY); + this.type = type; + postReplaceChild(oldChild, type, TYPE_PROPERTY); + } + + /** + * Returns the live ordered list of type arguments of this creation reference expression. + * + * @return the live list of type arguments + * (element type: {@link Type}) + */ + public List typeArguments() { + return this.typeArguments; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int memSize() { + // treat Code as free + return BASE_NODE_SIZE + 2 * 4; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int treeSize() { + return + memSize() + + (this.type == null ? 0 : getType().treeSize()) + + (this.typeArguments == null ? 0 : this.typeArguments.listSize()); + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java index 029f3ccd0..c8bffe5a7 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java @@ -92,6 +92,9 @@ class DefaultASTVisitor extends ASTVisitor { public void endVisit(ContinueStatement node) { endVisitNode(node); } + public void endVisit(CreationReference node) { + endVisitNode(node); + } public void endVisit(DoStatement node) { endVisitNode(node); } @@ -107,6 +110,9 @@ class DefaultASTVisitor extends ASTVisitor { public void endVisit(EnumDeclaration node) { endVisitNode(node); } + public void endVisit(ExpressionMethodReference node) { + endVisitNode(node); + } public void endVisit(ExpressionStatement node) { endVisitNode(node); } @@ -239,7 +245,9 @@ class DefaultASTVisitor extends ASTVisitor { public void endVisit(SuperMethodInvocation node) { endVisitNode(node); } - + public void endVisit(SuperMethodReference node) { + endVisitNode(node); + } public void endVisit(SwitchCase node) { endVisitNode(node); } @@ -274,6 +282,9 @@ class DefaultASTVisitor extends ASTVisitor { public void endVisit(TypeLiteral node) { endVisitNode(node); } + public void endVisit(TypeMethodReference node) { + endVisitNode(node); + } public void endVisit(TypeParameter node) { endVisitNode(node); } @@ -363,6 +374,9 @@ class DefaultASTVisitor extends ASTVisitor { public boolean visit(ContinueStatement node) { return visitNode(node); } + public boolean visit(CreationReference node) { + return visitNode(node); + } public boolean visit(DoStatement node) { return visitNode(node); } @@ -378,6 +392,9 @@ class DefaultASTVisitor extends ASTVisitor { public boolean visit(EnumDeclaration node) { return visitNode(node); } + public boolean visit(ExpressionMethodReference node) { + return visitNode(node); + } public boolean visit(ExpressionStatement node) { return visitNode(node); } @@ -520,6 +537,10 @@ class DefaultASTVisitor extends ASTVisitor { return visitNode(node); } + public boolean visit(SuperMethodReference node) { + return visitNode(node); + } + public boolean visit(SwitchCase node) { return visitNode(node); } @@ -564,6 +585,10 @@ class DefaultASTVisitor extends ASTVisitor { return visitNode(node); } + public boolean visit(TypeMethodReference node) { + return visitNode(node); + } + public boolean visit(TypeParameter node) { return visitNode(node); } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java index 7f53c4331..bb707a632 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java @@ -156,12 +156,12 @@ class DefaultBindingResolver extends BindingResolver { * Toggle controlling whether DOM bindings should be created when missing internal compiler bindings.. */ boolean isRecoveringBindings; - + /** * Set to <code>true</code> if initialized from a java project */ boolean fromJavaProject; - + /** * Constructor for DefaultBindingResolver. */ @@ -743,6 +743,10 @@ class DefaultBindingResolver extends BindingResolver { case ASTNode.INFIX_EXPRESSION : case ASTNode.INSTANCEOF_EXPRESSION : case ASTNode.LAMBDA_EXPRESSION: + case ASTNode.CREATION_REFERENCE: + case ASTNode.EXPRESSION_METHOD_REFERENCE: + case ASTNode.TYPE_METHOD_REFERENCE: + case ASTNode.SUPER_METHOD_REFERENCE : case ASTNode.FIELD_ACCESS : case ASTNode.SUPER_FIELD_ACCESS : case ASTNode.ARRAY_ACCESS : @@ -918,15 +922,15 @@ class DefaultBindingResolver extends BindingResolver { /* * Method declared on BindingResolver. */ - synchronized IMethodBinding resolveMethod(MethodDeclaration method) { - Object oldNode = this.newAstToOldAst.get(method); - if (oldNode instanceof AbstractMethodDeclaration) { - AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode; - IMethodBinding methodBinding = getMethodBinding(methodDeclaration.binding); + synchronized IMethodBinding resolveMethod(LambdaExpression lambda) { + Object oldNode = this.newAstToOldAst.get(lambda); + if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.LambdaExpression) { + org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression = (org.eclipse.jdt.internal.compiler.ast.LambdaExpression) oldNode; + IMethodBinding methodBinding = getMethodBinding(lambdaExpression.binding); if (methodBinding == null) { return null; } - this.bindingsToAstNodes.put(methodBinding, method); + this.bindingsToAstNodes.put(methodBinding, lambda); String key = methodBinding.getKey(); if (key != null) { this.bindingTables.bindingKeysToBindings.put(key, methodBinding); @@ -938,15 +942,15 @@ class DefaultBindingResolver extends BindingResolver { /* * Method declared on BindingResolver. */ - synchronized IMethodBinding resolveMethod(LambdaExpression lambda) { - Object oldNode = this.newAstToOldAst.get(lambda); - if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.LambdaExpression) { - org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression = (org.eclipse.jdt.internal.compiler.ast.LambdaExpression) oldNode; - IMethodBinding methodBinding = getMethodBinding(lambdaExpression.binding); + synchronized IMethodBinding resolveMethod(MethodDeclaration method) { + Object oldNode = this.newAstToOldAst.get(method); + if (oldNode instanceof AbstractMethodDeclaration) { + AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode; + IMethodBinding methodBinding = getMethodBinding(methodDeclaration.binding); if (methodBinding == null) { return null; } - this.bindingsToAstNodes.put(methodBinding, lambda); + this.bindingsToAstNodes.put(methodBinding, method); String key = methodBinding.getKey(); if (key != null) { this.bindingTables.bindingKeysToBindings.put(key, methodBinding); @@ -969,6 +973,26 @@ class DefaultBindingResolver extends BindingResolver { /* * Method declared on BindingResolver. */ + synchronized IMethodBinding resolveMethod(MethodReference methodReference) { + Object oldNode = this.newAstToOldAst.get(methodReference); + if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) { + org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) oldNode; + IMethodBinding methodBinding = getMethodBinding(referenceExpression.binding); + if (methodBinding == null) { + return null; + } + this.bindingsToAstNodes.put(methodBinding, methodReference); + String key = methodBinding.getKey(); + if (key != null) { + this.bindingTables.bindingKeysToBindings.put(key, methodBinding); + } + return methodBinding; + } + return null; + } + /* + * Method declared on BindingResolver. + */ synchronized IMethodBinding resolveMethod(SuperMethodInvocation method) { Object oldNode = this.newAstToOldAst.get(method); if (oldNode instanceof MessageSend) { @@ -1289,6 +1313,11 @@ class DefaultBindingResolver extends BindingResolver { IMethodBinding method = getMethodBinding(memberValuePair.binding); if (method == null) return null; return method.getReturnType(); + } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) { + org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) node; + IMethodBinding method = getMethodBinding(referenceExpression.binding); + if (method == null) return null; + return method.getReturnType(); //{ObjectTeams: Resolve bindings for OT-specific elements } else if (node instanceof MethodSpec) { if (node instanceof FieldAccessSpec) { @@ -1307,7 +1336,6 @@ class DefaultBindingResolver extends BindingResolver { return getTypeBinding(liftingTypeRef.resolvedType); // SH} } - return null; } @@ -1577,6 +1605,9 @@ class DefaultBindingResolver extends BindingResolver { } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.MemberValuePair) { org.eclipse.jdt.internal.compiler.ast.MemberValuePair memberValuePair = (org.eclipse.jdt.internal.compiler.ast.MemberValuePair) node; return getMethodBinding(memberValuePair.binding); + } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) { + org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) node; + return getMethodBinding(referenceExpression.binding); } //{ObjectTeams: Resolve bindings for OT-specific elements else if (node instanceof MethodSpec) diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Expression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Expression.java index 6fd76fa9c..a5b6dabb3 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Expression.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Expression.java @@ -31,11 +31,14 @@ package org.eclipse.jdt.core.dom; * {@link CharacterLiteral}, * {@link ClassInstanceCreation}, * {@link ConditionalExpression}, + * {@link CreationReference}, + * {@link ExpressionMethodReference}, * {@link FieldAccess}, * {@link InfixExpression}, * {@link InstanceofExpression}, * {@link LambdaExpression}, * {@link MethodInvocation}, + * {@link MethodReference}, * {@link Name}, * {@link NullLiteral}, * {@link NumberLiteral}, @@ -45,8 +48,10 @@ package org.eclipse.jdt.core.dom; * {@link StringLiteral}, * {@link SuperFieldAccess}, * {@link SuperMethodInvocation}, + * {@link SuperMethodReference}, * {@link ThisExpression}, * {@link TypeLiteral}, + * {@link TypeMethodReference}, * {@link VariableDeclarationExpression} * </pre> * </p> diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionMethodReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionMethodReference.java new file mode 100644 index 000000000..b98eba8e8 --- /dev/null +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionMethodReference.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Expression method reference AST node type (added in JLS8 API). + * <pre> + * ExpressionMethodReference: + * Expression <b>::</b> + * [ <b><</b> Type { <b>,</b> Type } <b>></b> ] + * Identifier + * </pre> + * + * @since 3.9 BETA_JAVA8 + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class ExpressionMethodReference extends MethodReference { + + /** + * The "expression" structural property of this node type (child type: {@link Expression}). + */ + public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = + new ChildPropertyDescriptor(ExpressionMethodReference.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "typeArguments" structural property of this node type (element type: {@link Type}) + */ + public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = + internalTypeArgumentsFactory(ExpressionMethodReference.class); + + /** + * The "name" structural property of this node type (child type: {@link SimpleName}. + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + new ChildPropertyDescriptor(ExpressionMethodReference.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_8_0; + + static { + List propertyList = new ArrayList(4); + createPropertyList(ExpressionMethodReference.class, propertyList); + addProperty(EXPRESSION_PROPERTY, propertyList); + addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList); + addProperty(NAME_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the AST.JLS* constants + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_8_0; + } + + /** + * The expression; lazily initialized; defaults to an unspecified, + * legal expression. + */ + private Expression expression = null; + + /** + * The method name; lazily initialized; defaults to an unspecified, + * legal Java method name. + */ + private SimpleName methodName = null; + + /** + * Creates a new AST node for an ExpressionMethodReference declaration owned + * by the given AST. + * <p> + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + * </p> + * + * @param ast the AST that is to own this node + */ + ExpressionMethodReference(AST ast) { + super(ast); + unsupportedIn2_3_4(); + } + + /* (omit javadoc for this method) + * Method declared on MethodReference. + */ + final ChildListPropertyDescriptor internalTypeArgumentsProperty() { + return TYPE_ARGUMENTS_PROPERTY; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == NAME_PROPERTY) { + if (get) { + return getName(); + } else { + setName((SimpleName) child); + return null; + } + } + if (property == EXPRESSION_PROPERTY) { + if (get) { + return getExpression(); + } else { + setExpression((Expression) child); + return null; + } + } + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == TYPE_ARGUMENTS_PROPERTY) { + return typeArguments(); + } + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final int getNodeType0() { + return EXPRESSION_METHOD_REFERENCE; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + ASTNode clone0(AST target) { + ExpressionMethodReference result = new ExpressionMethodReference(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setExpression( + (Expression) ASTNode.copySubtree(target, getExpression())); + result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments())); + result.setName((SimpleName) getName().clone(target)); + return result; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + // visit children in normal left to right reading order + acceptChild(visitor, getExpression()); + acceptChildren(visitor, this.typeArguments); + acceptChild(visitor, getName()); + } + visitor.endVisit(this); + } + + /** + * Returns the expression of this expression method reference expression + * + * @return the expression node + */ + public Expression getExpression() { + if (this.expression == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.expression == null) { + preLazyInit(); + this.expression = new SimpleName(this.ast); + postLazyInit(this.expression, EXPRESSION_PROPERTY); + } + } + } + return this.expression; + } + + /** + * Sets the expression of this expression method reference. + * + * @param expression the expression node + * @exception IllegalArgumentException if: + * <ul> + * <li>the node belongs to a different AST</li> + * <li>the node already has a parent</li> + * <li>a cycle in would be created</li> + * </ul> + */ + public void setExpression(Expression expression) { + if (expression == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.expression; + preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY); + this.expression = expression; + postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY); + } + + /** + * Returns the live ordered list of type arguments of this expression method reference + * + * @return the live list of type arguments + * (element type: {@link Type}) + */ + public List typeArguments() { + return this.typeArguments; + } + + /** + * Returns the name of the method referenced in this expression. + * + * @return the method name node + */ + public SimpleName getName() { + if (this.methodName == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.methodName == null) { + preLazyInit(); + this.methodName = new SimpleName(this.ast); + postLazyInit(this.methodName, NAME_PROPERTY); + } + } + } + return this.methodName; + } + + /** + * Sets the name of the method referenced in this expression to the + * given name. + * + * @param name the new method name + * @exception IllegalArgumentException if: + * <ul> + * <li>the node belongs to a different AST</li> + * <li>the node already has a parent</li> + * </ul> + */ + public void setName(SimpleName name) { + if (name == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.methodName; + preReplaceChild(oldChild, name, NAME_PROPERTY); + this.methodName = name; + postReplaceChild(oldChild, name, NAME_PROPERTY); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int memSize() { + // treat Code as free + return BASE_NODE_SIZE + 3 * 4; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int treeSize() { + return + memSize() + + (this.expression == null ? 0 : getExpression().treeSize()) + + (this.typeArguments == null ? 0 : this.typeArguments.listSize()) + + (this.methodName == null ? 0 : getName().treeSize()); + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LambdaExpression.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LambdaExpression.java index fd541a51e..35fa5b522 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LambdaExpression.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LambdaExpression.java @@ -18,7 +18,7 @@ import java.util.ArrayList; import java.util.List; /** - * Lambda expression AST node type. + * Lambda expression AST node type (added in JLS8 API). * <pre> * LambdaExpression: * Identifier <b>-></b> Body @@ -130,7 +130,7 @@ public class LambdaExpression extends Expression { /* (omit javadoc for this method) * Method declared on ASTNode. */ - List internalStructuralPropertiesForType(int apiLevel) { + final List internalStructuralPropertiesForType(int apiLevel) { return propertyDescriptors(apiLevel); } @@ -180,7 +180,7 @@ public class LambdaExpression extends Expression { /* (omit javadoc for this method) * Method declared on ASTNode. */ - int getNodeType0() { + final int getNodeType0() { return LAMBDA_EXPRESSION; } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodReference.java new file mode 100644 index 000000000..b7cfe3042 --- /dev/null +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodReference.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.List; + +/** + * Abstract base class of all AST node types that represent a method reference + * expression (added in JLS8 API). + * + * <pre> + * MethodReference: + * CreationReference + * ExpressionMethodReference + * SuperMethodReference + * TypeMethodReference + * </pre> + * <p> + * A method reference that is represented by a simple or qualified name, + * followed by <code>::</code>, followed by a simple name can be represented + * as {@link ExpressionMethodReference} or as {@link TypeMethodReference}. + * The ASTParser currently prefers the first form. + * </p> + * + * @see CreationReference + * @see ExpressionMethodReference + * @see SuperMethodReference + * @see TypeMethodReference + * @since 3.9 BETA_JAVA8 + */ +public abstract class MethodReference extends Expression { + + /** + * The type arguments (element type: {@link Type}). + * Defaults to an empty list (see constructor). + */ + ASTNode.NodeList typeArguments; + + /** + * Creates and returns a structural property descriptor for the "typeArguments" + * property declared on the given concrete node type (element type: {@link Type}). + * + * @return the property descriptor + */ + static final ChildListPropertyDescriptor internalTypeArgumentsFactory(Class nodeClass) { + return new ChildListPropertyDescriptor(nodeClass, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$ + } + + /** + * Returns the structural property descriptor for the "typeArguments" property + * of this node (element type: {@link Type}). + * + * @return the property descriptor + */ + abstract ChildListPropertyDescriptor internalTypeArgumentsProperty(); + + /** + * Returns the structural property descriptor for the "typeArguments" property + * of this node (element type: {@link Type}). + * + * @return the property descriptor + */ + public final ChildListPropertyDescriptor getTypeArgumentsProperty() { + return internalTypeArgumentsProperty(); + } + + /** + * Creates a new AST node for a method reference owned by the given AST. + * <p> + * N.B. This constructor is package-private. + * </p> + * + * @param ast the AST that is to own this node + */ + MethodReference(AST ast) { + super(ast); + this.typeArguments = new ASTNode.NodeList(getTypeArgumentsProperty()); + } + + /** + * Returns the live ordered list of type arguments of this method reference. + * + * @return the live list of type arguments + * (element type: {@link Type}) + */ + public List typeArguments() { + return this.typeArguments; + } + + /** + * Resolves and returns the binding for the method referenced by this + * method reference expression. + * <p> + * Note that bindings are generally unavailable unless requested when the + * AST is being built. + * </p> + * + * @return the method binding, or <code>null</code> if the binding cannot + * be resolved + */ + public IMethodBinding resolveMethodBinding() { + return this.ast.getBindingResolver().resolveMethod(this); + } +} diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageQualifiedType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageQualifiedType.java index 7a9cabe79..b3154b430 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageQualifiedType.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageQualifiedType.java @@ -162,11 +162,11 @@ public class PackageQualifiedType extends AnnotatableType { return super.internalGetSetChildProperty(property, get, child); } - int getNodeType0() { + final int getNodeType0() { return PACKAGE_QUALIFIED_TYPE; } - boolean subtreeMatch0(ASTMatcher matcher, Object other) { + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { // dispatch to correct overloaded match method return matcher.match(this, other); } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodReference.java new file mode 100644 index 000000000..0dfbc2e2e --- /dev/null +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodReference.java @@ -0,0 +1,294 @@ +/******************************************************************************* + * Copyright (c) 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Super method reference AST node type (added in JLS8 API). + * + * <pre> + * SuperMethodReference: + * [ ClassName <b>.</b> ] <b>super</b> <b>::</b> + * [ <b><</b> Type { <b>,</b> Type } <b>></b> ] + * Identifier + * </pre> + * + * @since 3.9 BETA_JAVA8 + * @noinstantiate This class is not intended to be instantiated by clients + */ +public class SuperMethodReference extends MethodReference { + + /** + * The "qualifier" structural property of this node type (child type: {@link Name}). + */ + public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = + new ChildPropertyDescriptor(SuperMethodReference.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "typeArguments" structural property of this node type (element type: {@link Type}) + */ + public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = + internalTypeArgumentsFactory(SuperMethodReference.class); + + /** + * The "name" structural property of this node type (child type: {@link SimpleName}). + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + new ChildPropertyDescriptor(SuperMethodReference.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_8_0; + + static { + List propertyList = new ArrayList(4); + createPropertyList(SuperMethodReference.class, propertyList); + addProperty(QUALIFIER_PROPERTY, propertyList); + addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList); + addProperty(NAME_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the + * <code>AST.JLS*</code> constants + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_8_0; + } + + /** + * The optional qualifier; <code>null</code> for none; defaults to none. + */ + private Name optionalQualifier = null; + + /** + * The method name; lazily initialized; defaults to a unspecified, + * legal Java method name. + */ + private SimpleName methodName = null; + /** + * Creates a new AST node for a super method reference owned + * by the given AST. By default, there is no qualifier. + * <p> + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + * </p> + * + * @param ast the AST that is to own this node + */ + SuperMethodReference(AST ast) { + super(ast); + unsupportedIn2_3_4(); + } + + /* (omit javadoc for this method) + * Method declared on MethodReference. + */ + final ChildListPropertyDescriptor internalTypeArgumentsProperty() { + return TYPE_ARGUMENTS_PROPERTY; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == QUALIFIER_PROPERTY) { + if (get) { + return getQualifier(); + } else { + setQualifier((Name) child); + return null; + } + } + if (property == NAME_PROPERTY) { + if (get) { + return getName(); + } else { + setName((SimpleName) child); + return null; + } + } + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == TYPE_ARGUMENTS_PROPERTY) { + return typeArguments(); + } + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final int getNodeType0() { + return SUPER_METHOD_REFERENCE; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + ASTNode clone0(AST target) { + SuperMethodReference result = new SuperMethodReference(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setName((SimpleName) getName().clone(target)); + result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier())); + result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments())); + return result; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + // visit children in normal left to right reading order + acceptChild(visitor, getQualifier()); + acceptChildren(visitor, this.typeArguments); + acceptChild(visitor, getName()); + } + visitor.endVisit(this); + } + + /** + * Returns the qualifier of this "super" method reference, or + * <code>null</code> if there is none. + * + * @return the qualifier name node, or <code>null</code> if there is none + */ + public Name getQualifier() { + return this.optionalQualifier; + } + + /** + * Sets the qualifier of this "super" method reference expression. + * + * @param name the qualifier name node, or <code>null</code> if + * there is none + * @exception IllegalArgumentException if: + * <ul> + * <li>the node belongs to a different AST</li> + * <li>the node already has a parent</li> + * </ul> + */ + public void setQualifier(Name name) { + ASTNode oldChild = this.optionalQualifier; + preReplaceChild(oldChild, name, QUALIFIER_PROPERTY); + this.optionalQualifier = name; + postReplaceChild(oldChild, name, QUALIFIER_PROPERTY); + } + + /** + * Returns the live ordered list of type arguments of this super method reference. + * + * @return the live list of type arguments + * (element type: {@link Type}) + */ + public List typeArguments() { + return this.typeArguments; + } + + /** + * Returns the name of the method referenced in this expression. + * + * @return the method name node + */ + public SimpleName getName() { + if (this.methodName == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.methodName == null) { + preLazyInit(); + this.methodName = new SimpleName(this.ast); + postLazyInit(this.methodName, NAME_PROPERTY); + } + } + } + return this.methodName; + } + + /** + * Sets the name of the method referenced in this expression to the + * given name. + * + * @param name the new method name + * @exception IllegalArgumentException if: + * <ul> + * <li>the node belongs to a different AST</li> + * <li>the node already has a parent</li> + * </ul> + */ + public void setName(SimpleName name) { + if (name == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.methodName; + preReplaceChild(oldChild, name, NAME_PROPERTY); + this.methodName = name; + postReplaceChild(oldChild, name, NAME_PROPERTY); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int memSize() { + // treat Code as free + return BASE_NODE_SIZE + 3 * 4; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int treeSize() { + return + memSize() + + (this.optionalQualifier == null ? 0 : getQualifier().treeSize()) + + (this.typeArguments == null ? 0 : this.typeArguments.listSize()) + + (this.methodName == null ? 0 : getName().treeSize()); + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeMethodReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeMethodReference.java new file mode 100644 index 000000000..1cebbe493 --- /dev/null +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeMethodReference.java @@ -0,0 +1,304 @@ +/******************************************************************************* + * Copyright (c) 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; +import java.util.List; + +/** + * Type method reference expression AST node type (added in JLS8 API). + * <pre> + * TypeMethodReference: + * Type <b>::</b> + * [ <b><</b> Type { <b>,</b> Type } <b>></b> ] + * Identifier + * </pre> + * + * @since 3.9 BETA_JAVA8 + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class TypeMethodReference extends MethodReference { + + /** + * The "type" structural property of this node type (child type: {@link Type}). + */ + public static final ChildPropertyDescriptor TYPE_PROPERTY = + new ChildPropertyDescriptor(TypeMethodReference.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * The "typeArguments" structural property of this node type (element type: {@link Type}) + */ + public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = + internalTypeArgumentsFactory(TypeMethodReference.class); + + /** + * The "name" structural property of this node type (child type: {@link SimpleName}. + */ + public static final ChildPropertyDescriptor NAME_PROPERTY = + new ChildPropertyDescriptor(TypeMethodReference.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ + + /** + * A list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}), + * or null if uninitialized. + */ + private static final List PROPERTY_DESCRIPTORS_8_0; + + static { + List propertyList = new ArrayList(4); + createPropertyList(TypeMethodReference.class, propertyList); + addProperty(TYPE_PROPERTY, propertyList); + addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList); + addProperty(NAME_PROPERTY, propertyList); + PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList); + } + + /** + * Returns a list of structural property descriptors for this node type. + * Clients must not modify the result. + * + * @param apiLevel the API level; one of the AST.JLS* constants + * @return a list of property descriptors (element type: + * {@link StructuralPropertyDescriptor}) + */ + public static List propertyDescriptors(int apiLevel) { + return PROPERTY_DESCRIPTORS_8_0; + } + + /** + * The type; lazily initialized; defaults to an unspecified type. + */ + private Type type = null; + + /** + * The method name; lazily initialized; defaults to an unspecified, + * legal Java method name. + */ + private SimpleName methodName = null; + + /** + * Creates a new AST node for an TypeMethodReference declaration owned + * by the given AST. + * <p> + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + * </p> + * + * @param ast the AST that is to own this node + */ + TypeMethodReference(AST ast) { + super(ast); + unsupportedIn2_3_4(); + } + + /* (omit javadoc for this method) + * Method declared on MethodReference. + */ + final ChildListPropertyDescriptor internalTypeArgumentsProperty() { + return TYPE_ARGUMENTS_PROPERTY; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalStructuralPropertiesForType(int apiLevel) { + return propertyDescriptors(apiLevel); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { + if (property == NAME_PROPERTY) { + if (get) { + return getName(); + } else { + setName((SimpleName) child); + return null; + } + } + if (property == TYPE_PROPERTY) { + if (get) { + return getType(); + } else { + setType((Type) child); + return null; + } + } + // allow default implementation to flag the error + return super.internalGetSetChildProperty(property, get, child); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final List internalGetChildListProperty(ChildListPropertyDescriptor property) { + if (property == TYPE_ARGUMENTS_PROPERTY) { + return typeArguments(); + } + // allow default implementation to flag the error + return super.internalGetChildListProperty(property); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final int getNodeType0() { + return TYPE_METHOD_REFERENCE; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + ASTNode clone0(AST target) { + TypeMethodReference result = new TypeMethodReference(target); + result.setSourceRange(getStartPosition(), getLength()); + result.setType((Type) ASTNode.copySubtree(target, getType())); + result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments())); + result.setName((SimpleName) getName().clone(target)); + return result; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + final boolean subtreeMatch0(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + void accept0(ASTVisitor visitor) { + boolean visitChildren = visitor.visit(this); + if (visitChildren) { + // visit children in normal left to right reading order + acceptChild(visitor, getType()); + acceptChildren(visitor, this.typeArguments); + acceptChild(visitor, getName()); + } + visitor.endVisit(this); + } + + /** + * Returns the type of this type method reference expression. + * + * @return the type node + */ + public Type getType() { + if (this.type == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.type == null) { + preLazyInit(); + this.type = new SimpleType(this.ast); + postLazyInit(this.type, TYPE_PROPERTY); + } + } + } + return this.type; + } + + /** + * Sets the type of this type method reference expression. + * + * @param type the new type node + * @exception IllegalArgumentException if: + * <ul> + * <li>the node belongs to a different AST</li> + * <li>the node already has a parent</li> + * </ul> + */ + public void setType(Type type) { + if (type == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.type; + preReplaceChild(oldChild, type, TYPE_PROPERTY); + this.type = type; + postReplaceChild(oldChild, type, TYPE_PROPERTY); + } + + /** + * Returns the live ordered list of type arguments of this type method reference expression. + * + * @return the live list of type arguments + * (element type: {@link Type}) + */ + public List typeArguments() { + return this.typeArguments; + } + + /** + * Returns the name of the method referenced in this expression. + * + * @return the method name node + */ + public SimpleName getName() { + if (this.methodName == null) { + // lazy init must be thread-safe for readers + synchronized (this) { + if (this.methodName == null) { + preLazyInit(); + this.methodName = new SimpleName(this.ast); + postLazyInit(this.methodName, NAME_PROPERTY); + } + } + } + return this.methodName; + } + + /** + * Sets the name of the method referenced in this expression to the + * given name. + * + * @param name the new method name + * @exception IllegalArgumentException if: + * <ul> + * <li>the node belongs to a different AST</li> + * <li>the node already has a parent</li> + * </ul> + */ + public void setName(SimpleName name) { + if (name == null) { + throw new IllegalArgumentException(); + } + ASTNode oldChild = this.methodName; + preReplaceChild(oldChild, name, NAME_PROPERTY); + this.methodName = name; + postReplaceChild(oldChild, name, NAME_PROPERTY); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int memSize() { + // treat Code as free + return BASE_NODE_SIZE + 3 * 4; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int treeSize() { + return + memSize() + + (this.type == null ? 0 : getType().treeSize()) + + (this.typeArguments == null ? 0 : this.typeArguments.listSize()) + + (this.methodName == null ? 0 : getName().treeSize()); + } +}
\ No newline at end of file diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java index 7de4a7e3f..3a1f4b5a3 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java @@ -204,6 +204,27 @@ public class NaiveASTFlattener extends ASTVisitor { } } + /** + * reference node helper function that is common to all + * the difference reference nodes. + * + * @param typeArguments list of type arguments + */ + private void visitReferenceTypeArguments(List typeArguments) { + this.buffer.append("::");//$NON-NLS-1$ + if (!typeArguments.isEmpty()) { + this.buffer.append('<'); + for (Iterator it = typeArguments.iterator(); it.hasNext(); ) { + Type t = (Type) it.next(); + t.accept(this); + if (it.hasNext()) { + this.buffer.append(','); + } + } + this.buffer.append('>'); + } + } + private void visitTypeAnnotations(AnnotatableType node) { if (node.getAST().apiLevel() >= AST.JLS8) { visitAnnotationsList(node.annotations()); @@ -580,6 +601,18 @@ public class NaiveASTFlattener extends ASTVisitor { } /* + * @see ASTVisitor#visit(CreationReference) + * + * @since 3.9 BETA_JAVA8 + */ + public boolean visit(CreationReference node) { + node.getType().accept(this); + visitReferenceTypeArguments(node.typeArguments()); + this.buffer.append("new");//$NON-NLS-1$ + return false; + } + + /* * @see ASTVisitor#visit(DoStatement) */ public boolean visit(DoStatement node) { @@ -691,6 +724,18 @@ public class NaiveASTFlattener extends ASTVisitor { } /* + * @see ASTVisitor#visit(ExpressionMethodReference) + * + * @since 3.9 BETA_JAVA8 + */ + public boolean visit(ExpressionMethodReference node) { + node.getExpression().accept(this); + visitReferenceTypeArguments(node.typeArguments()); + node.getName().accept(this); + return false; + } + + /* * @see ASTVisitor#visit(ExpressionStatement) */ public boolean visit(ExpressionStatement node) { @@ -1493,6 +1538,22 @@ public class NaiveASTFlattener extends ASTVisitor { } /* + * @see ASTVisitor#visit(SuperMethodReference) + * + * @since 3.9 BETA_JAVA8 + */ + public boolean visit(SuperMethodReference node) { + if (node.getQualifier() != null) { + node.getQualifier().accept(this); + this.buffer.append('.'); + } + this.buffer.append("super");//$NON-NLS-1$ + visitReferenceTypeArguments(node.typeArguments()); + node.getName().accept(this); + return false; + } + + /* * @see ASTVisitor#visit(SwitchCase) */ public boolean visit(SwitchCase node) { @@ -1749,6 +1810,18 @@ public class NaiveASTFlattener extends ASTVisitor { } /* + * @see ASTVisitor#visit(TypeMethodReference) + * + * @since 3.9 BETA_JAVA8 + */ + public boolean visit(TypeMethodReference node) { + node.getType().accept(this); + visitReferenceTypeArguments(node.typeArguments()); + node.getName().accept(this); + return false; + } + + /* * @see ASTVisitor#visit(TypeParameter) * @since 3.1 */ diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java index 3072772d6..0542c2f06 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java @@ -4007,9 +4007,12 @@ public final class ASTRewriteAnalyzer extends ASTVisitor { if (!hasChildrenChanges(node)) { return doVisitUnchangedChildren(node); } - rewriteRequiredNode(node, PackageQualifiedType.QUALIFIER_PROPERTY); - if (node.getAST().apiLevel() >= AST.JLS8) { - rewriteTypeAnnotations(node, PackageQualifiedType.ANNOTATIONS_PROPERTY, node.getStartPosition()); + int pos = rewriteRequiredNode(node, PackageQualifiedType.QUALIFIER_PROPERTY); + try { + pos = getScanner().getTokenEndOffset(TerminalTokens.TokenNameDOT, pos); + rewriteTypeAnnotations(node, PackageQualifiedType.ANNOTATIONS_PROPERTY, pos); + } catch (CoreException e) { + handleException(e); } rewriteRequiredNode(node, PackageQualifiedType.NAME_PROPERTY); return false; @@ -4042,9 +4045,14 @@ public final class ASTRewriteAnalyzer extends ASTVisitor { if (!hasChildrenChanges(node)) { return doVisitUnchangedChildren(node); } - rewriteRequiredNode(node, QualifiedType.QUALIFIER_PROPERTY); + int pos = rewriteRequiredNode(node, QualifiedType.QUALIFIER_PROPERTY); if (node.getAST().apiLevel() >= AST.JLS8) { - rewriteTypeAnnotations(node, QualifiedType.ANNOTATIONS_PROPERTY, node.getStartPosition()); + try { + pos = getScanner().getTokenEndOffset(TerminalTokens.TokenNameDOT, pos); + rewriteTypeAnnotations(node, QualifiedType.ANNOTATIONS_PROPERTY, pos); + } catch (CoreException e) { + handleException(e); + } } rewriteRequiredNode(node, QualifiedType.NAME_PROPERTY); return false; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExtendedAnnotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExtendedAnnotation.java index a143b4cc6..d6eb7df14 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExtendedAnnotation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExtendedAnnotation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. + * Copyright (c) 2012, 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,16 +11,18 @@ * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.core.util; /** * Description of an extended annotation structure as described in the JVM specifications - * (added in JavaSE-1.7). + * (added in JavaSE-1.8). * * This interface may be implemented by clients. * - * @since 3.9 + * @since 3.9 BETA_JAVA8 */ public interface IExtendedAnnotation extends IAnnotation { /** @@ -40,18 +42,18 @@ public interface IExtendedAnnotation extends IAnnotation { * <th>offset description</th> * </tr> * <tr> - * <td>0x00, 0x02, 0x04, 0x1E</td> - * <td>The offset within the bytecodes of the containing method of the <code>checkcast</code> - * bytecode emitted for a typecast, the <code>instanceof</code> bytecode for the type tests, - * the <code>new</code> bytecode emitted for the object creation expression, the <code>ldc(_w)</code> - * bytecode emitted for class literal, or the <code>getstatic</code> bytecode emitted for primitive - * class literals.</td> + * <td>0x43 (INSTANCE_OF), 0x44 (NEW), 0x45 (CONSTRUCTOR_REFERENCE), 0x46 (METHOD_REFERENCE)</td> + * <td>The offset within the bytecodes of the <code>instanceof</code> bytecode for INSTANCE_OF, + * the <code>new</code> bytecode for NEW and the implementing instruction for either a + * CONSTRUCTOR_REFERENCE or METHOD_REFERENCE.</td> * </tr> * <tr> - * <td>0x18, 0x1A</td> - * <td>The offset within the bytecodes of the containing method of the <code>new</code> - * bytecode emitted for a constructor call, or the <code>invoke{interface|special|static|virtual}</code> - * bytecode emitted for a method invocation.</td> + * <td>0x47 (CAST), 0x48 (CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT), 0x49 (METHOD_INVOCATION_TYPE_ARGUMENT), + * 0x4A (CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT), 0x4B (METHOD_REFERENCE_TYPE_ARGUMENT)</td> + * <td>The offset within the bytecodes of the <code>new</code> bytecode for constructor call, or the + * relevant bytecode for method invocation or method reference. For CAST the offset may + * point to the <code>checkcast</code> or another instruction as it is possible the cast + * may have been discarded by the compiler if it were a no-op.</td> * </tr> * </table> * @@ -61,6 +63,13 @@ public interface IExtendedAnnotation extends IAnnotation { int getOffset(); /** + * Answer back the exception table index when the target_type is EXCEPTION_PARAMETER. + * + * @return the exception table index + */ + int getExceptionTableIndex(); + + /** * Answer back the local variable reference info table length of this entry as specified in * the JVM specifications. * @@ -92,20 +101,20 @@ public interface IExtendedAnnotation extends IAnnotation { int getParameterIndex(); /** - * Answer back the method type parameter index. + * Answer back the index of the type parameter of the class or method * * <p>The index is 0-based.</p> * - * @return the method type parameter index + * @return the index of the type parameter of the class or method */ int getTypeParameterIndex(); /** - * Answer back the method type parameter bound index. + * Answer back the index of the bound of the type parameter of the method or class * * <p>The index is 0-based.</p> * - * @return the method type parameter bound index + * @return the index of the bound of the type parameter of the method or class */ int getTypeParameterBoundIndex(); @@ -120,45 +129,33 @@ public interface IExtendedAnnotation extends IAnnotation { * <th>offset description</th> * </tr> * <tr> - * <td>0x18, 0x1A</td> - * <td>the type argument index in the expression</td> - * </tr> - * <tr> - * <td>0x14</td> - * <td>the index of the type in the clause: <code>-1 (255)</code> is used if the annotation is on + * <td>0x10 (CLASS_EXTENDS)</td> + * <td>the index of the type in the clause: <code>-1 (65535)</code> is used if the annotation is on * the superclass type, and the value <code>i</code> is used if the annotation is on the <code>i</code>th * superinterface type (counting from zero).</td> * </tr> * <tr> - * <td>0x16</td> + * <td>0x17 (THROWS)</td> * <td>the index of the exception type in the clause: the value <code>i</code> denotes an annotation of the * <code>i</code>th exception type (counting from zero).</td> * </tr> + * <tr> + * <td>0x47 (CAST), 0x48 (CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT), 0x49 (METHOD_INVOCATION_TYPE_ARGUMENT), + * 0x4A (CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT), 0x4B (METHOD_REFERENCE_TYPE_ARGUMENT)</td> + * <td>the type argument index in the expression</td> + * </tr> * </table> * @return the index in the given different situations */ int getAnnotationTypeIndex(); /** - * Answer back the target type of the location of the wildcard as described in the JVM specifications. - * - * @return the target type of the location of the wildcard - */ - int getWildcardLocationType(); - - /** - * Answer back the locations of the wildcard type as described in the JVM specifications. - * - * @return the locations of the wildcard type - */ - int[] getWildcardLocations(); - - /** * Answer back the locations of the annotated type as described in the JVM specifications. * * <p>This is used for parameterized and array types.</p> * * @return the locations of the annotated type */ - int[] getLocations(); + int[][] getTypePath(); + } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExtendedAnnotationConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExtendedAnnotationConstants.java index 15d26470d..c849076fd 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExtendedAnnotationConstants.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExtendedAnnotationConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. + * Copyright (c) 2012, 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 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ package org.eclipse.jdt.core.util; @@ -18,47 +20,42 @@ import org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants; /** * Description of an extended annotation target types constants as described in the JVM specifications - * (added in JavaSE-1.7). + * (added in JavaSE-1.8). * - * @since 3.9 + * @since 3.9 BETA_JAVA8 * @noimplement This interface is not intended to be implemented by clients. * @noextend This interface is not intended to be extended by clients. */ public interface IExtendedAnnotationConstants { - int METHOD_RECEIVER = AnnotationTargetTypeConstants.METHOD_RECEIVER; - int METHOD_RECEIVER_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.METHOD_RECEIVER_GENERIC_OR_ARRAY; - int METHOD_RETURN_TYPE = AnnotationTargetTypeConstants.METHOD_RETURN_TYPE; - int METHOD_RETURN_TYPE_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.METHOD_RETURN_TYPE_GENERIC_OR_ARRAY; - int METHOD_PARAMETER = AnnotationTargetTypeConstants.METHOD_PARAMETER; - int METHOD_PARAMETER_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.METHOD_PARAMETER_GENERIC_OR_ARRAY; - int FIELD = AnnotationTargetTypeConstants.FIELD; - int FIELD_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.FIELD_GENERIC_OR_ARRAY; + + int CLASS_TYPE_PARAMETER = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER; + int METHOD_TYPE_PARAMETER = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER; + + int CLASS_EXTENDS = AnnotationTargetTypeConstants.CLASS_EXTENDS; int CLASS_TYPE_PARAMETER_BOUND = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND; - int CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY; int METHOD_TYPE_PARAMETER_BOUND = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND; - int METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY; - int CLASS_EXTENDS_IMPLEMENTS = AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS; - int CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY; + int FIELD = AnnotationTargetTypeConstants.FIELD; + int METHOD_RETURN = AnnotationTargetTypeConstants.METHOD_RETURN; + int METHOD_RECEIVER = AnnotationTargetTypeConstants.METHOD_RECEIVER; + int METHOD_FORMAL_PARAMETER = AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER; int THROWS = AnnotationTargetTypeConstants.THROWS; - int THROWS_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.THROWS_GENERIC_OR_ARRAY; - int WILDCARD_BOUND = AnnotationTargetTypeConstants.WILDCARD_BOUND; - int WILDCARD_BOUND_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.WILDCARD_BOUND_GENERIC_OR_ARRAY; - int METHOD_TYPE_PARAMETER = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER; - int METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY; - int CLASS_TYPE_PARAMETER = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER; - int CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY; - int TYPE_CAST = AnnotationTargetTypeConstants.TYPE_CAST; - int TYPE_CAST_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.TYPE_CAST_GENERIC_OR_ARRAY; - int TYPE_INSTANCEOF = AnnotationTargetTypeConstants.TYPE_INSTANCEOF; - int TYPE_INSTANCEOF_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.TYPE_INSTANCEOF_GENERIC_OR_ARRAY; - int OBJECT_CREATION = AnnotationTargetTypeConstants.OBJECT_CREATION; - int OBJECT_CREATION_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.OBJECT_CREATION_GENERIC_OR_ARRAY; + int LOCAL_VARIABLE = AnnotationTargetTypeConstants.LOCAL_VARIABLE; - int LOCAL_VARIABLE_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY; - int TYPE_ARGUMENT_CONSTRUCTOR_CALL = AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL; - int TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY; - int TYPE_ARGUMENT_METHOD_CALL = AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL; - int TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY; - int CLASS_LITERAL = AnnotationTargetTypeConstants.CLASS_LITERAL; - int CLASS_LITERAL_GENERIC_OR_ARRAY = AnnotationTargetTypeConstants.CLASS_LITERAL_GENERIC_OR_ARRAY; + int RESOURCE_VARIABLE = AnnotationTargetTypeConstants.RESOURCE_VARIABLE; + int EXCEPTION_PARAMETER = AnnotationTargetTypeConstants.EXCEPTION_PARAMETER; + int INSTANCEOF = AnnotationTargetTypeConstants.INSTANCEOF; + int NEW = AnnotationTargetTypeConstants.NEW; + int CONSTRUCTOR_REFERENCE = AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE; + int METHOD_REFERENCE = AnnotationTargetTypeConstants.METHOD_REFERENCE; + int CAST = AnnotationTargetTypeConstants.CAST; + int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = AnnotationTargetTypeConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT; + int METHOD_INVOCATION_TYPE_ARGUMENT = AnnotationTargetTypeConstants.METHOD_INVOCATION_TYPE_ARGUMENT; + int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT; + int METHOD_REFERENCE_TYPE_ARGUMENT = AnnotationTargetTypeConstants.METHOD_REFERENCE_TYPE_ARGUMENT; + + // Type path entry kinds + int TYPE_PATH_DEEPER_IN_ARRAY = 0; + int TYPE_PATH_DEEPER_IN_INNER_TYPE = 1; + int TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND = 2; + int TYPE_PATH_TYPE_ARGUMENT_INDEX = 3; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java index a281ab0df..43393752f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java @@ -1,12 +1,18 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 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 * http://www.eclipse.org/legal/epl-v10.html * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.core.util; @@ -86,6 +92,10 @@ public class CodeAttribute extends ClassFileAttribute implements ICodeAttribute this.attributes[attributesIndex++] = new StackMapTableAttribute(classFileBytes, constantPool, offset + readOffset); } else if (equals(attributeName, IAttributeNamesConstants.STACK_MAP)) { this.attributes[attributesIndex++] = new StackMapAttribute(classFileBytes, constantPool, offset + readOffset); + } else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS)) { + this.attributes[attributesIndex++] = new RuntimeVisibleTypeAnnotationsAttribute(classFileBytes, constantPool, offset + readOffset); + } else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS)) { + this.attributes[attributesIndex++] = new RuntimeInvisibleTypeAnnotationsAttribute(classFileBytes, constantPool, offset + readOffset); } else { this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, constantPool, offset + readOffset); } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java index 32f5c01fb..c7960b433 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java @@ -8,9 +8,11 @@ * This is an implementation of an early-draft specification developed under the Java * Community Process (JCP) and is made available for testing and evaluation purposes * only. The code is not compatible with any specification of the JCP. - * + * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.core.util; @@ -262,7 +264,7 @@ public class Disassembler extends ClassFileBytesDisassembler { writeNewLine(buffer, lineSeparator, tabNumber + 1); buffer.append(Messages.disassembler_annotationentryend); } - + private void disassemble(IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { writeNewLine(buffer, lineSeparator, tabNumber + 1); final int typeIndex = extendedAnnotation.getTypeIndex(); @@ -285,102 +287,30 @@ public class Disassembler extends ClassFileBytesDisassembler { })); switch(targetType) { case IExtendedAnnotationConstants.METHOD_RECEIVER : - case IExtendedAnnotationConstants.METHOD_RETURN_TYPE : + case IExtendedAnnotationConstants.METHOD_RETURN: case IExtendedAnnotationConstants.FIELD : break; default: writeNewLine(buffer, lineSeparator, tabNumber + 2); - } - - switch(targetType) { - case IExtendedAnnotationConstants.WILDCARD_BOUND : - int wildcardLocationType = extendedAnnotation.getWildcardLocationType(); - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocationtype, new String[] { - Integer.toString(wildcardLocationType), - getTargetType(wildcardLocationType), - })); - writeNewLine(buffer, lineSeparator, tabNumber + 3); - disassembleTargetTypeContents(true, wildcardLocationType, extendedAnnotation, buffer, lineSeparator, tabNumber + 3, mode); - break; - case IExtendedAnnotationConstants.WILDCARD_BOUND_GENERIC_OR_ARRAY : - wildcardLocationType = extendedAnnotation.getWildcardLocationType(); - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocationtype, new String[] { - Integer.toString(wildcardLocationType), - getTargetType(wildcardLocationType), - })); - writeNewLine(buffer, lineSeparator, tabNumber + 3); - disassembleTargetTypeContents(true, wildcardLocationType, extendedAnnotation, buffer, lineSeparator, tabNumber + 3, mode); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - break; - default: disassembleTargetTypeContents(false, targetType, extendedAnnotation, buffer, lineSeparator, tabNumber, mode); } + disassembleTypePathContents(targetType, extendedAnnotation, buffer, lineSeparator, tabNumber, mode); writeNewLine(buffer, lineSeparator, tabNumber + 1); buffer.append(Messages.disassembler_extendedannotationentryend); } + private void disassembleTypePathContents(int targetType, IExtendedAnnotation extendedAnnotation,StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { + int[][] typepath = extendedAnnotation.getTypePath(); + if (typepath.length != 0) { + writeNewLine(buffer, lineSeparator, tabNumber + 2); + buffer.append( + Messages.bind(Messages.disassembler_extendedannotation_typepath, new String[] { + toTypePathString(typepath), + })); + } + } private void disassembleTargetTypeContents(boolean insideWildcard, int targetType, IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { switch(targetType) { - case IExtendedAnnotationConstants.CLASS_EXTENDS_IMPLEMENTS : - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_classextendsimplements, new String[] { - Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), - })); - break; - case IExtendedAnnotationConstants.CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY : - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_classextendsimplements, new String[] { - Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), - })); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } - break; - case IExtendedAnnotationConstants.TYPE_CAST : - case IExtendedAnnotationConstants.TYPE_INSTANCEOF : - case IExtendedAnnotationConstants.OBJECT_CREATION : - case IExtendedAnnotationConstants.CLASS_LITERAL : - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_offset, new String[] { - Integer.toString(extendedAnnotation.getOffset()), - })); - break; - case IExtendedAnnotationConstants.TYPE_CAST_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.TYPE_INSTANCEOF_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.OBJECT_CREATION_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.CLASS_LITERAL_GENERIC_OR_ARRAY : - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_offset, new String[] { - Integer.toString(extendedAnnotation.getOffset()), - })); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } - break; case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER : case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER : buffer.append( @@ -388,54 +318,40 @@ public class Disassembler extends ClassFileBytesDisassembler { Integer.toString(extendedAnnotation.getTypeParameterIndex()), })); break; - case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY : + case IExtendedAnnotationConstants.CLASS_EXTENDS : buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_type_parameter, new String[] { - Integer.toString(extendedAnnotation.getTypeParameterIndex()), - })); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } + Messages.bind(Messages.disassembler_extendedannotation_classextendsimplements, new String[] { + Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), + })); break; - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND : + case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND : + case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND : buffer.append( Messages.bind(Messages.disassembler_extendedannotation_type_parameter_with_bound, new String[] { Integer.toString(extendedAnnotation.getTypeParameterIndex()), Integer.toString(extendedAnnotation.getTypeParameterBoundIndex()), })); + break; + case IExtendedAnnotationConstants.FIELD : + case IExtendedAnnotationConstants.METHOD_RETURN : + case IExtendedAnnotationConstants.METHOD_RECEIVER : break; - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY : + case IExtendedAnnotationConstants.METHOD_FORMAL_PARAMETER : buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_type_parameter_with_bound, new String[] { - Integer.toString(extendedAnnotation.getTypeParameterIndex()), - Integer.toString(extendedAnnotation.getTypeParameterBoundIndex()), + Messages.bind(Messages.disassembler_extendedannotation_method_parameter, new String[] { + Integer.toString(extendedAnnotation.getParameterIndex()), })); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } break; + case IExtendedAnnotationConstants.THROWS : + buffer.append( + Messages.bind(Messages.disassembler_extendedannotation_throws, new String[] { + Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), + })); + break; + case IExtendedAnnotationConstants.LOCAL_VARIABLE : + case IExtendedAnnotationConstants.RESOURCE_VARIABLE : buffer.append(Messages.disassembler_localvariabletargetheader); writeNewLine(buffer, lineSeparator, tabNumber + 3); int localVariableTableSize = extendedAnnotation.getLocalVariableRefenceInfoLength(); @@ -456,92 +372,27 @@ public class Disassembler extends ClassFileBytesDisassembler { })); } break; - case IExtendedAnnotationConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY : - buffer.append(Messages.disassembler_localvariabletargetheader); - writeNewLine(buffer, lineSeparator, tabNumber + 3); - localVariableTableSize = extendedAnnotation.getLocalVariableRefenceInfoLength(); - localVariableTable = extendedAnnotation.getLocalVariableTable(); - for (int i = 0; i < localVariableTableSize; i++) { - if (i != 0) { - writeNewLine(buffer, lineSeparator, tabNumber + 3); - } - ILocalVariableReferenceInfo info = localVariableTable[i]; - int index= info.getIndex(); - int startPC = info.getStartPC(); - int length = info.getLength(); - buffer.append(Messages.bind(Messages.classfileformat_localvariablereferenceinfoentry, - new String[] { - Integer.toString(startPC), - Integer.toString(startPC + length), - Integer.toString(index), - })); - } - writeNewLine(buffer, lineSeparator, tabNumber + 2); - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } - break; - case IExtendedAnnotationConstants.METHOD_PARAMETER : + case IExtendedAnnotationConstants.EXCEPTION_PARAMETER : buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_method_parameter, new String[] { - Integer.toString(extendedAnnotation.getTypeParameterIndex()), + Messages.bind(Messages.disassembler_extendedannotation_exception_table_index, new String[] { + Integer.toString(extendedAnnotation.getExceptionTableIndex()), })); break; - case IExtendedAnnotationConstants.METHOD_PARAMETER_GENERIC_OR_ARRAY : - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_method_parameter, new String[] { - Integer.toString(extendedAnnotation.getTypeParameterIndex()), - })); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } - break; - case IExtendedAnnotationConstants.METHOD_RECEIVER_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.METHOD_RETURN_TYPE_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.FIELD_GENERIC_OR_ARRAY : - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } - break; - case IExtendedAnnotationConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL : - case IExtendedAnnotationConstants.TYPE_ARGUMENT_METHOD_CALL : + + case IExtendedAnnotationConstants.INSTANCEOF : + case IExtendedAnnotationConstants.NEW : + case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE : + case IExtendedAnnotationConstants.METHOD_REFERENCE : buffer.append( Messages.bind(Messages.disassembler_extendedannotation_offset, new String[] { Integer.toString(extendedAnnotation.getOffset()), })); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_type_argument, new String[] { - Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), - })); break; - case IExtendedAnnotationConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY : + case IExtendedAnnotationConstants.CAST : + case IExtendedAnnotationConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : + case IExtendedAnnotationConstants.METHOD_INVOCATION_TYPE_ARGUMENT : + case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : + case IExtendedAnnotationConstants.METHOD_REFERENCE_TYPE_ARGUMENT : buffer.append( Messages.bind(Messages.disassembler_extendedannotation_offset, new String[] { Integer.toString(extendedAnnotation.getOffset()), @@ -551,124 +402,63 @@ public class Disassembler extends ClassFileBytesDisassembler { Messages.bind(Messages.disassembler_extendedannotation_type_argument, new String[] { Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), })); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } - break; - case IExtendedAnnotationConstants.THROWS : - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_throws, new String[] { - Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), - })); - break; - case IExtendedAnnotationConstants.THROWS_GENERIC_OR_ARRAY : - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_throws, new String[] { - Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), - })); - writeNewLine(buffer, lineSeparator, tabNumber + 2); - if (insideWildcard) { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_wildcardlocations, new String[] { - toString(extendedAnnotation.getWildcardLocations()), - })); - } else { - buffer.append( - Messages.bind(Messages.disassembler_extendedannotation_locations, new String[] { - toString(extendedAnnotation.getLocations()), - })); - } break; } } private String getTargetType(int targetType) { switch(targetType) { - case IExtendedAnnotationConstants.CLASS_EXTENDS_IMPLEMENTS : - return "CLASS_EXTENDS_IMPLEMENTS"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY : - return "CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.TYPE_CAST : - return "TYPE_CAST"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.TYPE_INSTANCEOF : - return "TYPE_INSTANCEOF"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.OBJECT_CREATION : - return "OBJECT_CREATION"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.CLASS_LITERAL : - return "CLASS_LITERAL"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.TYPE_CAST_GENERIC_OR_ARRAY : - return "TYPE_CAST_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.TYPE_INSTANCEOF_GENERIC_OR_ARRAY : - return "TYPE_INSTANCEOF_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.OBJECT_CREATION_GENERIC_OR_ARRAY : - return "OBJECT_CREATION_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.CLASS_LITERAL_GENERIC_OR_ARRAY : - return "CLASS_LITERAL_GENERIC_OR_ARRAY"; //$NON-NLS-1$ case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER : return "CLASS_TYPE_PARAMETER"; //$NON-NLS-1$ case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER : return "METHOD_TYPE_PARAMETER"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY : - return "CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY : - return "METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND : - return "METHOD_TYPE_PARAMETER_BOUND"; //$NON-NLS-1$ + + case IExtendedAnnotationConstants.CLASS_EXTENDS : + return "CLASS_EXTENDS"; //$NON-NLS-1$ case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND : return "CLASS_TYPE_PARAMETER_BOUND"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY : - return "METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY : - return "CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.LOCAL_VARIABLE : - return "LOCAL_VARIABLE"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY : - return "LOCAL_VARIABLE_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_PARAMETER : - return "METHOD_PARAMETER"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_PARAMETER_GENERIC_OR_ARRAY : - return "METHOD_PARAMETER_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_RECEIVER_GENERIC_OR_ARRAY : - return "METHOD_RECEIVER_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_RETURN_TYPE_GENERIC_OR_ARRAY : - return "METHOD_RETURN_TYPE_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_RECEIVER : - return "METHOD_RECEIVER"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.METHOD_RETURN_TYPE : - return "METHOD_RETURN_TYPE"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND : + return "METHOD_TYPE_PARAMETER_BOUND"; //$NON-NLS-1$ case IExtendedAnnotationConstants.FIELD : return "FIELD"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.FIELD_GENERIC_OR_ARRAY : - return "FIELD_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL : - return "TYPE_ARGUMENT_CONSTRUCTOR_CALL"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.TYPE_ARGUMENT_METHOD_CALL : - return "TYPE_ARGUMENT_METHOD_CALL"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY : - return "TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY : - return "TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.METHOD_RETURN : + return "METHOD_RETURN"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.METHOD_RECEIVER : + return "METHOD_RECEIVER"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.METHOD_FORMAL_PARAMETER : + return "METHOD_FORMAL_PARAMETER"; //$NON-NLS-1$ case IExtendedAnnotationConstants.THROWS : return "THROWS"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.THROWS_GENERIC_OR_ARRAY : - return "THROWS_GENERIC_OR_ARRAY"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.WILDCARD_BOUND : - return "WILDCARD_BOUND"; //$NON-NLS-1$ - case IExtendedAnnotationConstants.WILDCARD_BOUND_GENERIC_OR_ARRAY : - return "WILDCARD_BOUND_GENERIC_OR_ARRAY"; //$NON-NLS-1$ + + case IExtendedAnnotationConstants.LOCAL_VARIABLE : + return "LOCAL_VARIABLE"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.RESOURCE_VARIABLE : + return "RESOURCE_VARIABLE"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.EXCEPTION_PARAMETER : + return "EXCEPTION_PARAMETER"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.INSTANCEOF : + return "INSTANCEOF"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.NEW : + return "NEW"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE : + return "CONSTRUCTOR_REFERENCE"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.METHOD_REFERENCE : + return "METHOD_REFERENCE"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.CAST : + return "CAST"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : + return "CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.METHOD_INVOCATION_TYPE_ARGUMENT : + return "METHOD_INVOCATION_TYPE_ARGUMENT"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : + return "CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT"; //$NON-NLS-1$ + case IExtendedAnnotationConstants.METHOD_REFERENCE_TYPE_ARGUMENT : + return "METHOD_REFERENCE_TYPE_ARGUMENT"; //$NON-NLS-1$ default: return "UNKNOWN"; //$NON-NLS-1$ } } + private void disassemble(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { writeNewLine(buffer, lineSeparator, tabNumber + 1); buffer.append( @@ -1128,7 +918,7 @@ public class Disassembler extends ClassFileBytesDisassembler { } if (runtimeInvisibleTypeAnnotationsAttribute != null) { disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); - } + } } } @@ -1222,7 +1012,9 @@ public class Disassembler extends ClassFileBytesDisassembler { IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute(); IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); - + IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); + IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); + IClassFileAttribute bootstrapMethods = Util.getAttribute(classFileReader, IAttributeNamesConstants.BOOTSTRAP_METHODS); if (checkMode(mode, DETAILED)) { @@ -1369,6 +1161,12 @@ public class Disassembler extends ClassFileBytesDisassembler { if (runtimeInvisibleAnnotationsAttribute != null) { disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode); } + if (runtimeVisibleTypeAnnotationsAttribute != null) { + disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, 0, mode); + } + if (runtimeInvisibleTypeAnnotationsAttribute != null) { + disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, 0, mode); + } if (length != 0) { for (int i = 0; i < length; i++) { IClassFileAttribute attribute = attributes[i]; @@ -1378,6 +1176,8 @@ public class Disassembler extends ClassFileBytesDisassembler { && attribute != enclosingMethodAttribute && attribute != runtimeInvisibleAnnotationsAttribute && attribute != runtimeVisibleAnnotationsAttribute + && attribute != runtimeInvisibleTypeAnnotationsAttribute + && attribute != runtimeVisibleTypeAnnotationsAttribute && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED) && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC) && attribute != bootstrapMethods) { @@ -1602,6 +1402,10 @@ public class Disassembler extends ClassFileBytesDisassembler { if (numberOfEntries != 0) { disassemble(stackMapAttribute, buffer, lineSeparator, tabNumber, mode); } + } else if (CharOperation.equals(attribute.getAttributeName(),IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS)) { + disassemble((IRuntimeVisibleTypeAnnotationsAttribute) attribute, buffer, lineSeparator, tabNumber, mode); + } else if (CharOperation.equals(attribute.getAttributeName(),IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS)) { + disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) attribute, buffer, lineSeparator, tabNumber, mode); } else if (attribute != lineNumberAttribute && attribute != localVariableAttribute && attribute != localVariableTypeAttribute) { @@ -2113,7 +1917,7 @@ public class Disassembler extends ClassFileBytesDisassembler { } if (runtimeInvisibleTypeAnnotationsAttribute != null) { disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); - } + } } } @@ -2247,16 +2051,7 @@ public class Disassembler extends ClassFileBytesDisassembler { disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); } } - - private void disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { - writeNewLine(buffer, lineSeparator, tabNumber + 1); - buffer.append(Messages.disassembler_runtimevisibleannotationsattributeheader); - IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations(); - for (int i = 0, max = annotations.length; i < max; i++) { - disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); - } - } - + private void disassemble(IRuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { writeNewLine(buffer, lineSeparator, tabNumber + 1); buffer.append(Messages.disassembler_runtimeinvisibletypeannotationsattributeheader); @@ -2265,13 +2060,13 @@ public class Disassembler extends ClassFileBytesDisassembler { disassemble(extendedAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); } } - - private void disassemble(IRuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { + + private void disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { writeNewLine(buffer, lineSeparator, tabNumber + 1); - buffer.append(Messages.disassembler_runtimevisibletypeannotationsattributeheader); - IExtendedAnnotation[] extendedAnnotations = runtimeVisibleTypeAnnotationsAttribute.getExtendedAnnotations(); - for (int i = 0, max = extendedAnnotations.length; i < max; i++) { - disassemble(extendedAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); + buffer.append(Messages.disassembler_runtimevisibleannotationsattributeheader); + IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations(); + for (int i = 0, max = annotations.length; i < max; i++) { + disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); } } @@ -2283,6 +2078,15 @@ public class Disassembler extends ClassFileBytesDisassembler { disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); } } + + private void disassemble(IRuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { + writeNewLine(buffer, lineSeparator, tabNumber + 1); + buffer.append(Messages.disassembler_runtimevisibletypeannotationsattributeheader); + IExtendedAnnotation[] extendedAnnotations = runtimeVisibleTypeAnnotationsAttribute.getExtendedAnnotations(); + for (int i = 0, max = extendedAnnotations.length; i < max; i++) { + disassemble(extendedAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); + } + } private String disassemble(IVerificationTypeInfo[] infos, int mode) { StringBuffer buffer = new StringBuffer(); @@ -2718,16 +2522,37 @@ public class Disassembler extends ClassFileBytesDisassembler { dumpTab(tabNumber, buffer); } - private String toString(int[] tab) { + private String toTypePathString(int[][] typepath) { StringBuffer buffer = new StringBuffer(); - buffer.append('{'); - for (int i = 0, max = tab.length; i < max; i++) { + buffer.append('['); + for (int i = 0, max = typepath.length; i < max; i++) { + int[] typepathElement = typepath[i]; if (i > 0) { - buffer.append(','); + buffer.append(',').append(' '); + } + switch (typepathElement[0]) { + case IExtendedAnnotationConstants.TYPE_PATH_DEEPER_IN_ARRAY: + buffer.append(Messages.disassembler_extendedannotation_typepath_array); + break; + case IExtendedAnnotationConstants.TYPE_PATH_DEEPER_IN_INNER_TYPE: + buffer.append(Messages.disassembler_extendedannotation_typepath_innertype); + break; + case IExtendedAnnotationConstants.TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND: + buffer.append(Messages.disassembler_extendedannotation_typepath_wildcard); + break; + case IExtendedAnnotationConstants.TYPE_PATH_TYPE_ARGUMENT_INDEX: + buffer.append( + Messages.bind(Messages.disassembler_extendedannotation_typepath_typeargument, + new String[] { + Integer.toString(typepathElement[1]) + })); + break; + default: + throw new IllegalStateException("Unrecognized type_path_kind: "+typepathElement[0]); //$NON-NLS-1$ } - buffer.append(tab[i]); } - buffer.append('}'); - return String.valueOf(buffer); + buffer.append(']'); + return String.valueOf(buffer); } + } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExtendedAnnotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExtendedAnnotation.java index aa429774f..902b32967 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExtendedAnnotation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExtendedAnnotation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 IBM Corporation and others. + * Copyright (c) 2012, 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 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ package org.eclipse.jdt.internal.core.util; @@ -23,30 +25,58 @@ import org.eclipse.jdt.core.util.IExtendedAnnotation; import org.eclipse.jdt.core.util.IExtendedAnnotationConstants; import org.eclipse.jdt.core.util.ILocalVariableReferenceInfo; +/* http://types.cs.washington.edu/jsr308/specification/java-annotation-design.pdf + type_annotation { + // New fields in JSR 308: + u1 target_type; // the type of the targeted program element, see Section 3.2 + union { + type_parameter_target; + supertype_target; + type_parameter_bound_target; + empty_target; + method_formal_parameter_target; + throws_target; + localvar_target; + catch_target; + offset_target; + type_argument_target; + method_reference_target; + } target_info; // identifies the targeted program element, see Section 3.3 + type_path target_path; // identifies targeted type in a compound type (array, generic, etc.), see Section 3.4 + // Original fields from "annotation" structure: + u2 type_index; + u2 num_element_value_pairs; + { + u2 element_name_index; + element_value value; + } element_value_pairs[num_element_value_pairs]; +*/ /** - * Default implementation of IAnnotation + * @since 3.9 BETA_JAVA8 */ public class ExtendedAnnotation extends ClassFileStruct implements IExtendedAnnotation { private static final IAnnotationComponent[] NO_ENTRIES = new IAnnotationComponent[0]; + private final static int[][] NO_TYPEPATH = new int[0][0]; + + private int targetType; + private int annotationTypeIndex; + private int[][] typePath; private int typeIndex; private char[] typeName; private int componentsNumber; private IAnnotationComponent[] components; private int readOffset; - private int targetType; - private int annotationTypeIndex; private int offset; private int typeParameterIndex; private int typeParameterBoundIndex; private int parameterIndex; - private int wildcardLocationType; + private int exceptionTableIndex; private ILocalVariableReferenceInfo[] localVariableTable; - private int[] locations; - private int[] wildcardLocations; + /** - * Constructor for Annotation. + * Constructor for ExtendedAnnotation, builds an annotation from the supplied bytestream. * * @param classFileBytes * @param constantPool @@ -58,8 +88,32 @@ public class ExtendedAnnotation extends ClassFileStruct implements IExtendedAnno IConstantPool constantPool, int offset) throws ClassFormatException { - int index = u2At(classFileBytes, 0, offset); + // Read target_type + int index = u1At(classFileBytes,0,offset); + this.targetType = index; + this.readOffset = 1; + + readTargetInfo(index, classFileBytes, constantPool, offset); + + // Read type_path + index = u1At(classFileBytes, this.readOffset, offset); + this.readOffset++; + int typePathEntryCount = index; + if (typePathEntryCount == 0) { + this.typePath = NO_TYPEPATH; + } else { + this.typePath = new int[typePathEntryCount][]; + for (int i = 0; i < typePathEntryCount; i++) { + int[] typePathEntry = (this.typePath[i] = new int[2]); + typePathEntry[0] = u1At(classFileBytes, this.readOffset++, offset); + typePathEntry[1] = u1At(classFileBytes, this.readOffset++, offset); + } + } + + // Read annotation + index = u2At(classFileBytes, this.readOffset, offset); this.typeIndex = index; + this.readOffset+=2; if (index != 0) { IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(index); if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Utf8) { @@ -69,9 +123,9 @@ public class ExtendedAnnotation extends ClassFileStruct implements IExtendedAnno } else { throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY); } - final int length = u2At(classFileBytes, 2, offset); + final int length = u2At(classFileBytes, this.readOffset, offset); this.componentsNumber = length; - this.readOffset = 4; + this.readOffset+=2; if (length != 0) { this.components = new IAnnotationComponent[length]; for (int i = 0; i < length; i++) { @@ -82,122 +136,55 @@ public class ExtendedAnnotation extends ClassFileStruct implements IExtendedAnno } else { this.components = NO_ENTRIES; } - index = u1At(classFileBytes, this.readOffset, offset); - this.readOffset++; - this.targetType = index; - switch(index) { - case IExtendedAnnotationConstants.WILDCARD_BOUND : - this.wildcardLocationType = u1At(classFileBytes, this.readOffset, offset); - this.readOffset++; - internalDecoding(this.wildcardLocationType, classFileBytes, constantPool, offset); - // copy the location back into the wildcard location - int size = this.locations.length; - System.arraycopy(this.locations, 0, (this.wildcardLocations = new int[size]), 0, size); - this.locations = null; - break; - case IExtendedAnnotationConstants.WILDCARD_BOUND_GENERIC_OR_ARRAY : - this.wildcardLocationType = u1At(classFileBytes, this.readOffset, offset); - this.readOffset++; - internalDecoding(this.wildcardLocationType, classFileBytes, constantPool, offset); - size = this.locations.length; - System.arraycopy(this.locations, 0, (this.wildcardLocations = new int[size]), 0, size); - int locationLength = u2At(classFileBytes, this.readOffset, offset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, offset); - this.readOffset++; - } - break; - default: - internalDecoding(index, classFileBytes, constantPool, offset); - } if (this.annotationTypeIndex == 0xFFFF) { this.annotationTypeIndex = -1; } } - private void internalDecoding( + private void readTargetInfo( int localTargetType, byte[] classFileBytes, IConstantPool constantPool, int localOffset) throws ClassFormatException { switch(localTargetType) { - case IExtendedAnnotationConstants.CLASS_EXTENDS_IMPLEMENTS : - this.annotationTypeIndex = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset+=2; - break; - case IExtendedAnnotationConstants.CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY : - this.annotationTypeIndex = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset+=2; - int locationLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } - break; - case IExtendedAnnotationConstants.TYPE_CAST : - case IExtendedAnnotationConstants.TYPE_INSTANCEOF : - case IExtendedAnnotationConstants.OBJECT_CREATION : - case IExtendedAnnotationConstants.CLASS_LITERAL : - this.offset = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - break; - case IExtendedAnnotationConstants.TYPE_CAST_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.TYPE_INSTANCEOF_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.OBJECT_CREATION_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.CLASS_LITERAL_GENERIC_OR_ARRAY : - this.offset = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - locationLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } - break; case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER : case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER : this.typeParameterIndex = u1At(classFileBytes, this.readOffset, localOffset); this.readOffset++; break; - case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY : - this.typeParameterIndex = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - locationLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } + + case IExtendedAnnotationConstants.CLASS_EXTENDS : + this.annotationTypeIndex = u2At(classFileBytes, this.readOffset, localOffset); + this.readOffset+=2; break; - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND : + case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND : + case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND : this.typeParameterIndex = u1At(classFileBytes, this.readOffset, localOffset); this.readOffset++; this.typeParameterBoundIndex = u1At(classFileBytes, this.readOffset, localOffset); this.readOffset++; break; - case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY : - this.typeParameterIndex = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - this.typeParameterBoundIndex = u1At(classFileBytes, this.readOffset, localOffset); + + case IExtendedAnnotationConstants.FIELD : + case IExtendedAnnotationConstants.METHOD_RETURN : + case IExtendedAnnotationConstants.METHOD_RECEIVER : + // nothing to do, target_info is empty_target + break; + + case IExtendedAnnotationConstants.METHOD_FORMAL_PARAMETER : + this.parameterIndex = u1At(classFileBytes, this.readOffset, localOffset); this.readOffset++; - locationLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } break; + + case IExtendedAnnotationConstants.THROWS : + this.annotationTypeIndex = u2At(classFileBytes, this.readOffset, localOffset); + this.readOffset+=2; + break; + + case IExtendedAnnotationConstants.LOCAL_VARIABLE : + case IExtendedAnnotationConstants.RESOURCE_VARIABLE : int tableLength = u2At(classFileBytes, this.readOffset, localOffset); this.readOffset += 2; this.localVariableTable = new LocalVariableReferenceInfo[tableLength]; @@ -206,83 +193,34 @@ public class ExtendedAnnotation extends ClassFileStruct implements IExtendedAnno this.readOffset += 6; } break; - case IExtendedAnnotationConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY : - tableLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.localVariableTable = new LocalVariableReferenceInfo[tableLength]; - for (int i = 0; i < tableLength; i++) { - this.localVariableTable[i] = new LocalVariableReferenceInfo(classFileBytes, constantPool, this.readOffset + localOffset); - this.readOffset += 6; - } - locationLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } - break; - case IExtendedAnnotationConstants.METHOD_PARAMETER : - this.parameterIndex = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - break; - case IExtendedAnnotationConstants.METHOD_PARAMETER_GENERIC_OR_ARRAY : - this.parameterIndex = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - locationLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } - break; - case IExtendedAnnotationConstants.METHOD_RECEIVER_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.METHOD_RETURN_TYPE_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.FIELD_GENERIC_OR_ARRAY : - locationLength = u2At(classFileBytes, this.readOffset, localOffset); + + case IExtendedAnnotationConstants.EXCEPTION_PARAMETER : + this.exceptionTableIndex = u2At(classFileBytes, this.readOffset, localOffset); this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } break; - case IExtendedAnnotationConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL : - case IExtendedAnnotationConstants.TYPE_ARGUMENT_METHOD_CALL : + + case IExtendedAnnotationConstants.NEW : + case IExtendedAnnotationConstants.INSTANCEOF : + case IExtendedAnnotationConstants.METHOD_REFERENCE : + case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE : this.offset = u2At(classFileBytes, this.readOffset, localOffset); this.readOffset += 2; - this.annotationTypeIndex = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; + break; + + case IExtendedAnnotationConstants.CAST : + this.offset = u2At(classFileBytes, this.readOffset, localOffset); + this.readOffset += 3; // skipping the 3rd byte which will be 0 for CAST break; - case IExtendedAnnotationConstants.TYPE_ARGUMENT_CONSTRUCTOR_CALL_GENERIC_OR_ARRAY : - case IExtendedAnnotationConstants.TYPE_ARGUMENT_METHOD_CALL_GENERIC_OR_ARRAY : + + case IExtendedAnnotationConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : + case IExtendedAnnotationConstants.METHOD_INVOCATION_TYPE_ARGUMENT : + case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : + case IExtendedAnnotationConstants.METHOD_REFERENCE_TYPE_ARGUMENT : this.offset = u2At(classFileBytes, this.readOffset, localOffset); this.readOffset += 2; + // read type_argument_index this.annotationTypeIndex = u1At(classFileBytes, this.readOffset, localOffset); this.readOffset++; - locationLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } - break; - case IExtendedAnnotationConstants.THROWS : - this.annotationTypeIndex = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset+=2; - break; - case IExtendedAnnotationConstants.THROWS_GENERIC_OR_ARRAY : - this.annotationTypeIndex = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset+=2; - locationLength = u2At(classFileBytes, this.readOffset, localOffset); - this.readOffset += 2; - this.locations = new int[locationLength]; - for (int i = 0; i < locationLength; i++) { - this.locations[i] = u1At(classFileBytes, this.readOffset, localOffset); - this.readOffset++; - } break; } } @@ -319,6 +257,10 @@ public class ExtendedAnnotation extends ClassFileStruct implements IExtendedAnno public int getTargetType() { return this.targetType; } + + public int getExceptionTableIndex() { + return this.exceptionTableIndex; + } public int getOffset() { return this.offset; @@ -344,16 +286,8 @@ public class ExtendedAnnotation extends ClassFileStruct implements IExtendedAnno return this.typeParameterBoundIndex; } - public int getWildcardLocationType() { - return this.wildcardLocationType; - } - - public int[] getWildcardLocations() { - return this.wildcardLocations; - } - - public int[] getLocations() { - return this.locations; + public int[][] getTypePath() { + return this.typePath; } public int getAnnotationTypeIndex() { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java index 1edfa5f1d..2de336260 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 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 @@ -8,9 +8,11 @@ * This is an implementation of an early-draft specification developed under the Java * Community Process (JCP) and is made available for testing and evaluation purposes * only. The code is not compatible with any specification of the JCP. - * + * * Contributors: * IBM Corporation - initial API and implementation + * 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) *******************************************************************************/ package org.eclipse.jdt.internal.core.util; @@ -304,7 +306,7 @@ public final class Messages extends NLS { public static String disassembler_runtimevisibletypeannotationsattributeheader; public static String disassembler_runtimeinvisibletypeannotationsattributeheader; public static String disassembler_extendedannotation_classextendsimplements; - public static String disassembler_extendedannotation_locations; + public static String disassembler_extendedannotation_typepath; public static String disassembler_extendedannotation_method_parameter; public static String disassembler_extendedannotation_offset; public static String disassembler_extendedannotation_throws; @@ -314,8 +316,12 @@ public final class Messages extends NLS { public static String disassembler_extendedannotation_wildcardlocationtype; public static String disassembler_extendedannotation_targetType; public static String disassembler_extendedannotation_wildcardlocations; + public static String disassembler_extendedannotation_exception_table_index; + public static String disassembler_extendedannotation_typepath_array; + public static String disassembler_extendedannotation_typepath_wildcard; + public static String disassembler_extendedannotation_typepath_typeargument; + public static String disassembler_extendedannotation_typepath_innertype; public static String disassembler_localvariabletargetheader; - public static String classfileformat_localvariablereferenceinfoentry; public static String disassembler_runtimevisibleannotationsattributeheader; public static String disassembler_runtimeinvisibleannotationsattributeheader; @@ -331,6 +337,9 @@ public final class Messages extends NLS { public static String classfileformat_superflagisnotset; public static String classfileformat_superflagisset; public static String classfileformat_clinitname; + // jsr308 + public static String classfileformat_localvariablereferenceinfoentry; + public static String classformat_classformatexception; public static String classformat_anewarray; public static String classformat_checkcast; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties index 748f5c1b3..30fad38c9 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2011 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 @@ -8,9 +8,11 @@ # This is an implementation of an early-draft specification developed under the Java # Community Process (JCP) and is made available for testing and evaluation purposes # only. The code is not compatible with any specification of the JCP. -# +# # Contributors: # IBM Corporation - initial API and implementation +# 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) ############################################################################### ### JavaModel messages. @@ -323,12 +325,13 @@ disassembler_annotationarrayvaluestart = [ disassembler_annotationarrayvalueend = ] disassembler_annotationentrystart = #{0} @{1}( disassembler_annotationentryend = ) -# jsr308 +# jsr308 (next two) disassembler_extendedannotationentrystart=#{0} @{1}( disassembler_extendedannotationentryend= ) disassembler_annotationcomponent = #{0} {1}= disassembler_runtimevisibleannotationsattributeheader= RuntimeVisibleAnnotations:\ disassembler_runtimeinvisibleannotationsattributeheader= RuntimeInvisibleAnnotations:\ +# jsr308 (next two) disassembler_runtimevisibletypeannotationsattributeheader= RuntimeVisibleTypeAnnotations:\ disassembler_runtimeinvisibletypeannotationsattributeheader= RuntimeInvisibleTypeAnnotations:\ disassembler_runtimevisibleparameterannotationsattributeheader= RuntimeVisibleParameterAnnotations:\ @@ -356,11 +359,10 @@ disassembler_method_type_ref_newinvokespecial = newinvokespecial ({0}) disassembler_frame_full_frame=[pc: {0}, full, stack: {4}, locals: {2}] disassembler_frame_same_frame=[pc: {0}, same] disassembler_frame_same_locals_1_stack_item=[pc: {0}, same_locals_1_stack_item, stack: {1}] - -# jsr 308 +# jsr308 disassembler_extendedannotation_targetType=target type = 0x{0} {1} disassembler_extendedannotation_classextendsimplements=type index = {0} -disassembler_extendedannotation_locations=locations = {0} +disassembler_extendedannotation_typepath=location = {0} disassembler_extendedannotation_method_parameter=method parameter index = {0} disassembler_extendedannotation_offset=offset = {0} disassembler_extendedannotation_throws=throws index = {0} @@ -369,7 +371,12 @@ disassembler_extendedannotation_type_parameter=type parameter index = {0} disassembler_extendedannotation_type_parameter_with_bound=type parameter index = {0} type parameter bound index = {1} disassembler_extendedannotation_wildcardlocationtype=wildcard location type = 0x{0} {1} disassembler_extendedannotation_wildcardlocations=wildcard locations = {0} +disassembler_extendedannotation_exception_table_index=exception table index = {0} disassembler_localvariabletargetheader=local variable entries: +disassembler_extendedannotation_typepath_array=ARRAY +disassembler_extendedannotation_typepath_innertype=INNER_TYPE +disassembler_extendedannotation_typepath_wildcard=WILDCARD +disassembler_extendedannotation_typepath_typeargument=TYPE_ARGUMENT({0}) ### classfileformat decoding classfileformat_versiondetails =\ (version {0} : {1}.{2}, {3}) |