8023515: import type-annotations updates
Reviewed-by: jjg
Contributed-by: wdietl@gmail.com
--- a/langtools/src/share/classes/com/sun/source/tree/MethodTree.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/source/tree/MethodTree.java Wed Aug 21 16:13:50 2013 -0700
@@ -53,7 +53,15 @@
Tree getReturnType();
List<? extends TypeParameterTree> getTypeParameters();
List<? extends VariableTree> getParameters();
+
+ /**
+ * Return an explicit receiver parameter ("this" parameter).
+ *
+ * @return an explicit receiver parameter ("this" parameter)
+ * @since 1.8
+ */
VariableTree getReceiverParameter();
+
List<? extends ExpressionTree> getThrows();
BlockTree getBody();
Tree getDefaultValue(); // for annotation types
--- a/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java Wed Aug 21 16:13:50 2013 -0700
@@ -36,6 +36,8 @@
* <em>name</em>
*
* <em>name</em> extends <em>bounds</em>
+ *
+ * <em>annotations</em> <em>name</em>
* </pre>
*
* @jls section 4.4
@@ -48,5 +50,17 @@
public interface TypeParameterTree extends Tree {
Name getName();
List<? extends Tree> getBounds();
+
+ /**
+ * Return annotations on the type parameter declaration.
+ *
+ * Annotations need Target meta-annotations of
+ * {@link java.lang.annotation.ElementType#TYPE_PARAMETER} or
+ * {@link java.lang.annotation.ElementType#TYPE_USE}
+ * to appear in this position.
+ *
+ * @return annotations on the type parameter declaration
+ * @since 1.8
+ */
List<? extends AnnotationTree> getAnnotations();
}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java Wed Aug 21 16:13:50 2013 -0700
@@ -27,8 +27,6 @@
import java.util.Locale;
-import javax.lang.model.type.TypeKind;
-
import com.sun.tools.javac.api.Messages;
import com.sun.tools.javac.code.Type.AnnotatedType;
import com.sun.tools.javac.code.Type.ArrayType;
@@ -191,7 +189,7 @@
void printBaseElementType(Type t, StringBuilder sb, Locale locale) {
Type arrel = t;
- while (arrel.getKind() == TypeKind.ARRAY) {
+ while (arrel.hasTag(TypeTag.ARRAY)) {
arrel = arrel.unannotatedType();
arrel = ((ArrayType) arrel).elemtype;
}
@@ -200,7 +198,7 @@
void printBrackets(Type t, StringBuilder sb, Locale locale) {
Type arrel = t;
- while (arrel.getKind() == TypeKind.ARRAY) {
+ while (arrel.hasTag(TypeTag.ARRAY)) {
if (arrel.isAnnotated()) {
sb.append(' ');
sb.append(arrel.getAnnotationMirrors());
@@ -264,12 +262,12 @@
public String visitAnnotatedType(AnnotatedType t, Locale locale) {
if (t.typeAnnotations != null &&
t.typeAnnotations.nonEmpty()) {
- if (t.underlyingType.getKind() == TypeKind.ARRAY) {
+ if (t.underlyingType.hasTag(TypeTag.ARRAY)) {
StringBuilder res = new StringBuilder();
printBaseElementType(t, res, locale);
printBrackets(t, res, locale);
return res.toString();
- } else if (t.underlyingType.getKind() == TypeKind.DECLARED &&
+ } else if (t.underlyingType.hasTag(TypeTag.CLASS) &&
t.underlyingType.getEnclosingType() != Type.noType) {
return visit(t.underlyingType.getEnclosingType(), locale) +
". " +
@@ -348,7 +346,7 @@
args = args.tail;
buf.append(',');
}
- if (args.head.unannotatedType().getKind() == TypeKind.ARRAY) {
+ if (args.head.unannotatedType().hasTag(TypeTag.ARRAY)) {
buf.append(visit(((ArrayType) args.head.unannotatedType()).elemtype, locale));
if (args.head.getAnnotationMirrors().nonEmpty()) {
buf.append(' ');
--- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Wed Aug 21 16:13:50 2013 -0700
@@ -29,6 +29,8 @@
import javax.lang.model.element.ElementKind;
import javax.lang.model.type.TypeKind;
+import javax.tools.JavaFileObject;
+
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Attribute.TypeCompound;
import com.sun.tools.javac.code.Flags;
@@ -52,12 +54,16 @@
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.comp.Annotate;
import com.sun.tools.javac.comp.Annotate.Annotator;
+import com.sun.tools.javac.comp.AttrContext;
+import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCLambda;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCNewClass;
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
@@ -90,11 +96,17 @@
* later processing.
*/
public static void organizeTypeAnnotationsSignatures(final Symtab syms, final Names names,
- final Log log, final JCClassDecl tree, Annotate annotate) {
+ final Log log, final Env<AttrContext> env, final JCClassDecl tree, final Annotate annotate) {
annotate.afterRepeated( new Annotator() {
@Override
public void enterAnnotation() {
- new TypeAnnotationPositions(syms, names, log, true).scan(tree);
+ JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
+
+ try {
+ new TypeAnnotationPositions(syms, names, log, true).scan(tree);
+ } finally {
+ log.useSource(oldSource);
+ }
}
} );
}
@@ -906,7 +918,14 @@
if (!invocation.typeargs.contains(tree)) {
Assert.error("{" + tree + "} is not an argument in the invocation: " + invocation);
}
- p.type = TargetType.METHOD_INVOCATION_TYPE_ARGUMENT;
+ MethodSymbol exsym = (MethodSymbol) TreeInfo.symbol(invocation.getMethodSelect());
+ if (exsym == null) {
+ Assert.error("could not determine symbol for {" + invocation + "}");
+ } else if (exsym.isConstructor()) {
+ p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
+ } else {
+ p.type = TargetType.METHOD_INVOCATION_TYPE_ARGUMENT;
+ }
p.pos = invocation.pos;
p.type_index = invocation.typeargs.indexOf(tree);
return;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Aug 21 16:13:50 2013 -0700
@@ -249,7 +249,7 @@
MethodType lambdaType = (MethodType) sym.type;
{
- MethodSymbol owner = (MethodSymbol) localContext.owner;
+ Symbol owner = localContext.owner;
ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Wed Aug 21 16:13:50 2013 -0700
@@ -1089,7 +1089,7 @@
}
}
if (allowTypeAnnos) {
- TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, tree, annotate);
+ TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, env, tree, annotate);
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Wed Aug 21 16:13:50 2013 -0700
@@ -89,7 +89,7 @@
* deletion without notice.</b>
*/
public class JavacProcessingEnvironment implements ProcessingEnvironment, Closeable {
- Options options;
+ private final Options options;
private final boolean printProcessorInfo;
private final boolean printRounds;
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Aug 21 16:13:50 2013 -0700
@@ -2248,7 +2248,7 @@
# TODO 308: make a better error message
# 0: unused
compiler.err.cant.annotate.nested.type=\
- nested type cannot be annotated
+ scoping construct for static nested type cannot be annotated
# 0: type, 1: type
compiler.err.incorrect.receiver.name=\
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java Wed Aug 21 16:13:50 2013 -0700
@@ -944,10 +944,17 @@
try {
if (tree.elemtype != null) {
print("new ");
- printTypeAnnotations(tree.annotations);
JCTree elem = tree.elemtype;
printBaseElementType(elem);
- boolean isElemAnnoType = elem instanceof JCAnnotatedType;
+
+ if (!tree.annotations.isEmpty()) {
+ print(' ');
+ printTypeAnnotations(tree.annotations);
+ }
+ if (tree.elems != null) {
+ print("[]");
+ }
+
int i = 0;
List<List<JCAnnotation>> da = tree.dimAnnotations;
for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
@@ -960,17 +967,7 @@
printExpr(l.head);
print("]");
}
- if (tree.elems != null) {
- if (isElemAnnoType) {
- print(' ');
- printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations);
- }
- print("[]");
- }
- if (isElemAnnoType)
- elem = ((JCAnnotatedType)elem).underlyingType;
- if (elem instanceof JCArrayTypeTree)
- printBrackets((JCArrayTypeTree) elem);
+ printBrackets(elem);
}
if (tree.elems != null) {
print("{");
@@ -1260,20 +1257,24 @@
}
// prints the brackets of a nested array in reverse order
- private void printBrackets(JCArrayTypeTree tree) throws IOException {
- JCTree elem;
+ // tree is either JCArrayTypeTree or JCAnnotatedTypeTree
+ private void printBrackets(JCTree tree) throws IOException {
+ JCTree elem = tree;
while (true) {
- elem = tree.elemtype;
if (elem.hasTag(ANNOTATED_TYPE)) {
JCAnnotatedType atype = (JCAnnotatedType) elem;
elem = atype.underlyingType;
- if (!elem.hasTag(TYPEARRAY)) break;
- print(' ');
- printTypeAnnotations(atype.annotations);
+ if (elem.hasTag(TYPEARRAY)) {
+ print(' ');
+ printTypeAnnotations(atype.annotations);
+ }
}
- print("[]");
- if (!elem.hasTag(TYPEARRAY)) break;
- tree = (JCArrayTypeTree) elem;
+ if (elem.hasTag(TYPEARRAY)) {
+ print("[]");
+ elem = ((JCArrayTypeTree)elem).elemtype;
+ } else {
+ break;
+ }
}
}
@@ -1378,22 +1379,15 @@
public void visitAnnotatedType(JCAnnotatedType tree) {
try {
- if (tree.underlyingType.getKind() == JCTree.Kind.MEMBER_SELECT) {
+ if (tree.underlyingType.hasTag(SELECT)) {
JCFieldAccess access = (JCFieldAccess) tree.underlyingType;
printExpr(access.selected, TreeInfo.postfixPrec);
print(".");
printTypeAnnotations(tree.annotations);
print(access.name);
- } else if (tree.underlyingType.getKind() == JCTree.Kind.ARRAY_TYPE) {
- JCArrayTypeTree array = (JCArrayTypeTree) tree.underlyingType;
+ } else if (tree.underlyingType.hasTag(TYPEARRAY)) {
printBaseElementType(tree);
- print(' ');
- printTypeAnnotations(tree.annotations);
- print("[]");
- JCExpression elem = array.elemtype;
- if (elem.hasTag(TYPEARRAY)) {
- printBrackets((JCArrayTypeTree) elem);
- }
+ printBrackets(tree);
} else {
printTypeAnnotations(tree.annotations);
printExpr(tree.underlyingType);
--- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java Wed Aug 21 16:13:50 2013 -0700
@@ -35,13 +35,16 @@
// Test count helps identify test case in event of failure.
int testcount = 0;
- // Base test case template descriptions
+ // Base test case template descriptions;true==annotations in code attribute.
enum srce {
src1("(repeating) type annotations on on field in method body",true),
src2("(repeating) type annotations on type parameters, bounds and type arguments", true),
src3("(repeating) type annotations on type parameters of class, method return value in method", true),
src4("(repeating) type annotations on field in anonymous class", false),
- src5("(repeating) type annotations on field in anonymous class", false);
+ src5("(repeating) type annotations on field in anonymous class", false),
+ src6("(repeating) type annotations on void method declaration", false),
+ src7("(repeating) type annotations in use of instanceof", true),
+ src8("(repeating) type annotations in use of instanceof in method", true);
String description;
Boolean local;
@@ -84,6 +87,12 @@
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
test( 2, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src5);
test( 0, 2, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src5);
+ test( 0, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src6);
+ test( 0, 0, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src6);
+ test( 2, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src7);
+ test( 0, 2, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src7);
+ test( 4, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src8);
+ test( 0, 4, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src8);
break;
case "FIELD":
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src1);
@@ -121,18 +130,6 @@
", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " +
et2 + ", src=" + source + "\n " + source.description;
- if(
-// 8005681 - src1,2,3 - skip cases with repeated annotations on new, array, cast.
- (( source.equals(srce.src1) || source.equals(srce.src2) ||
- source.equals(srce.src3)) && (ABmix || (Arepeats && BDrepeats)))
- // 8008928 - src4,5 - this change cause crash with t-a on anon class)
- || (source.equals(srce.src4) || source.equals(srce.src5))
- ) {
- System.out.println(testDef +
- "\n 8005681-skip repeated annotations on new,array,cast");
- return;
- }
-
println(testDef);
// Create test source and File.
String sourceString = sourceString(tname, rtn, et2, Arepeats,
@@ -178,9 +175,7 @@
println("Pass");
}
- //
// Source for test cases
- //
String sourceString(String testname, String retentn, String annot2,
Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
srce src) {
@@ -359,6 +354,63 @@
hasInnerClass=true;
innerClassname="$1";
break;
+ case src6: // (repeating)annotations on void method declaration
+ /*
+ * class Test95{
+ * @A @A @B @B public void test() { };
+ * }
+ */
+ source = new String( source +
+ "// " + src.description + "\n" +
+ "class "+ testname + "{\n" +
+ " _As_ _Bs_ public void test() { }\n" +
+ "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
+ "\n\n";
+ hasInnerClass=false;
+ break;
+ case src7: // (repeating) type annotations in use of instanceof
+ /*
+ * class Test10{
+ * String data = "test";
+ * boolean dataIsString = ( data instanceof @A @B @A @B String);
+ * }
+ */
+ source = new String( source +
+ "// " + src.description + "\n" +
+ "class "+ testname + "{\n" +
+ " String data = \"test\";\n" +
+ " boolean dataIsString = ( data instanceof _As_ _Bs_ String);\n" +
+ "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
+ "\n\n";
+ hasInnerClass=false;
+ break;
+ case src8: // (repeating) type annotations in use of instanceof
+ /*
+ * class Test20{
+ * String data = "test";
+ * Boolean isString() {
+ * if( data instanceof @A @B @A @B String )
+ * return true;
+ * else
+ * return( data instanceof @A @B @A @B String );
+ * }
+ * }
+ */
+ source = new String( source +
+ "// " + src.description + "\n" +
+ "class "+ testname + "{\n" +
+ " String data = \"test\";\n" +
+ " Boolean isString() { \n" +
+ " if( data instanceof _As_ _Bs_ String )\n" +
+ " return true;\n" +
+ " else\n" +
+ " return( data instanceof _As_ _Bs_ String );\n" +
+ " }\n" +
+ "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
+ "\n\n";
+ hasInnerClass=false;
+ break;
+
}
return imports + source;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/DummyProcessor.java Wed Aug 21 16:13:50 2013 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+import java.util.Set;
+
+/* A simple annotation processor. */
+@SupportedAnnotationTypes("*")
+public class DummyProcessor extends AbstractProcessor {
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ @Override
+ public final boolean process(Set<? extends TypeElement> annotations,
+ RoundEnvironment roundEnv) {
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/T8020715.java Wed Aug 21 16:13:50 2013 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Regression: compiling program with lambda crashed compiler
+ * @bug 8020715
+ * @compile T8020715.java
+ */
+class T8020715 {
+ // This crashed.
+ private static void makeTask1() {
+ class LocalClass {
+ private Runnable r = () -> {};
+ }
+ }
+
+ // This crashed, too.
+ private void makeTask2() {
+ class LocalClass {
+ private Runnable r = () -> {};
+ }
+ }
+
+ // This is fine.
+ private class InnerClass {
+ private Runnable r = () -> {};
+ }
+}
--- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Tue Aug 20 15:12:16 2013 -0700
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Wed Aug 21 16:13:50 2013 -0700
@@ -85,4 +85,24 @@
" } } }";
}
+ @TADescriptions({
+ @TADescription(annotation = "TA", type = CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT,
+ typeIndex = 0, offset = 4),
+ @TADescription(annotation = "TB", type = CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT,
+ typeIndex = 0, offset = 0)
+ })
+ public String generic1() {
+ return "class Test { <T> Test(int i) { new <@TA T>Test(); }" +
+ " <T> Test() { <@TB String>this(0); } }";
+ }
+
+ @TADescriptions({
+ @TADescription(annotation = "TA", type = CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT,
+ typeIndex = 0, offset = 0)
+ })
+ public String generic2() {
+ return "class Super { <T> Super(int i) { } } " +
+ "class Test extends Super { <T> Test() { <@TA String>super(0); } }";
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/tree/TypeAnnotationsPretty.java Wed Aug 21 16:13:50 2013 -0700
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 1234567
+ * @summary test Pretty print of type annotations
+ * @author wmdietl
+ */
+
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.tree.JCTree;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.LinkedList;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+public class TypeAnnotationsPretty {
+ private final JavaCompiler tool;
+
+ TypeAnnotationsPretty() {
+ tool = ToolProvider.getSystemJavaCompiler();
+ }
+
+ private List<String> matches = new LinkedList<String>();
+ private List<String> mismatches = new LinkedList<String>();
+
+ public static void main(String... args) throws Exception {
+ TypeAnnotationsPretty tap = new TypeAnnotationsPretty();
+
+ tap.runField("@TA()\nObject cls = null");
+ tap.runField("@TA()\nObject cls = new @TA() Object()");
+
+ tap.runField("@TA()\nList<@TB() Object> cls = null");
+ tap.runField("@TA()\nList<@TB() Object> cls = new @TA() LinkedList<@TB() Object>()");
+
+ tap.runField("Class[] cls = null");
+ tap.runField("@TA()\nClass[] cls = null");
+ tap.runField("Class @TA() [] cls = null");
+ tap.runField("@TA()\nClass @TB() [] cls = null");
+
+ tap.runField("Class[] cls = new Class[]{Object.class}");
+ tap.runField("@TA()\nClass[] cls = new @TA() Class[]{Object.class}");
+ tap.runField("Class @TB() [] cls = new Class @TB() []{Object.class}");
+ tap.runField("@TA()\nClass @TB() [] cls = new @TA() Class @TB() []{Object.class}");
+ tap.runField("@TA()\nClass @TB() [] @TC() [] cls = new @TA() Class @TB() [10] @TC() []");
+ tap.runField("Class @TB() [] @TC() [] cls = new Class @TB() [10] @TC() []");
+ tap.runField("@TA()\nClass @TB() [] @TC() [] @TD() [] cls = new @TA() Class @TB() [10] @TC() [] @TD() []");
+
+ tap.runMethod("\n@TA()\nObject test(@TB()\nList<@TC() String> p) {\n" +
+ " return null;\n" +
+ "}");
+
+
+ if (!tap.matches.isEmpty()) {
+ for (String m : tap.matches)
+ System.out.println(m);
+ }
+ if (!tap.mismatches.isEmpty()) {
+ for (String mm : tap.mismatches)
+ System.err.println(mm + "\n");
+ throw new RuntimeException("Tests failed!");
+ }
+ }
+
+ private static final String prefix =
+ "import java.lang.annotation.*;" +
+ "import java.util.*;" +
+ "public class Test {";
+
+ private static final String postfix =
+ "@Target(ElementType.TYPE_USE)" +
+ "@interface TA {}" +
+ "@Target(ElementType.TYPE_USE)" +
+ "@interface TB {}" +
+ "@Target(ElementType.TYPE_USE)" +
+ "@interface TC {}" +
+ "@Target(ElementType.TYPE_USE)" +
+ "@interface TD {}";
+
+
+ private void runField(String code) throws IOException {
+ String src = prefix +
+ code + "; }" +
+ postfix;
+
+ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null,
+ null, Arrays.asList(new MyFileObject(src)));
+
+
+ for (CompilationUnitTree cut : ct.parse()) {
+ JCTree.JCVariableDecl var =
+ (JCTree.JCVariableDecl) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0);
+
+ if (!code.equals(var.toString())) {
+ mismatches.add("Expected: " + code +
+ "\nObtained: " + var.toString());
+ } else {
+ matches.add("Passed: " + code);
+ }
+ }
+ }
+
+ private void runMethod(String code) throws IOException {
+ String src = prefix +
+ code + "}" +
+ postfix;
+
+ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null,
+ null, Arrays.asList(new MyFileObject(src)));
+
+
+ for (CompilationUnitTree cut : ct.parse()) {
+ JCTree.JCMethodDecl var =
+ (JCTree.JCMethodDecl) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0);
+
+ if (!code.equals(var.toString())) {
+ mismatches.add("Expected: " + code +
+ "\nObtained: " + var.toString());
+ } else {
+ matches.add("Passed: " + code);
+ }
+ }
+ }
+}
+
+
+class MyFileObject extends SimpleJavaFileObject {
+
+ private String text;
+
+ public MyFileObject(String text) {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ this.text = text;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return text;
+ }
+}