1 /* 2 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 8038788 27 * @summary Verify proper handling of annotations after method's type parameters. 28 * @modules jdk.compiler 29 * @build AfterMethodTypeParams 30 * @run main AfterMethodTypeParams 31 */ 32 33 import java.io.IOException; 34 import java.io.StringWriter; 35 import java.net.URI; 36 import java.util.*; 37 38 import javax.lang.model.element.Name; 39 import javax.tools.*; 40 41 import com.sun.source.tree.*; 42 import com.sun.source.util.*; 43 44 public class AfterMethodTypeParams { 45 main(String... args)46 public static void main(String... args) throws IOException { 47 new AfterMethodTypeParams().run(); 48 } 49 run()50 void run() throws IOException { 51 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 52 53 for (TestCase tc : testCases) { 54 String test = TEMPLATE.replace("CONTENT", tc.snippet); 55 List<JavaFileObject> files = Arrays.asList(new MyFileObject(test)); 56 StringWriter out = new StringWriter(); 57 List<String> options = Arrays.asList("-XDrawDiagnostics", "--should-stop=at=FLOW"); 58 JavacTask task = (JavacTask) compiler.getTask(out, null, null, options, null, files); 59 60 new TreePathScanner<Void, Void>() { 61 boolean seenAnnotation; 62 @Override 63 public Void visitAnnotation(AnnotationTree node, Void p) { 64 Name name = ((IdentifierTree) node.getAnnotationType()).getName(); 65 seenAnnotation |= name.contentEquals("TA") || name.contentEquals("DA"); 66 return null; 67 } 68 @Override 69 public Void visitCompilationUnit(CompilationUnitTree node, Void p) { 70 super.visitCompilationUnit(node, p); 71 if (!seenAnnotation) 72 error(test, "Annotation was missing"); 73 return null; 74 } 75 }.scan(task.parse(), null); 76 77 task.analyze(); 78 79 if (!tc.error.equals(out.toString().trim())) { 80 error(test, "Incorrect errors: " + out.toString()); 81 } 82 } 83 84 if (errors > 0) { 85 throw new IllegalStateException("Errors found"); 86 } 87 } 88 89 int errors; 90 error(String code, String error)91 void error(String code, String error) { 92 System.out.println("Error detected: " + error); 93 System.out.println("Code:"); 94 System.out.println(code); 95 errors++; 96 } 97 98 static String TEMPLATE = 99 "import java.lang.annotation.*;\n" + 100 "public class Test {\n" + 101 " CONTENT\n" + 102 "}\n" + 103 "@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})\n" + 104 "@interface DA { }\n" + 105 "@Target(ElementType.TYPE_USE)\n" + 106 "@interface TA { }\n"; 107 108 static class MyFileObject extends SimpleJavaFileObject { 109 final String text; MyFileObject(String text)110 public MyFileObject(String text) { 111 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 112 this.text = text; 113 } 114 @Override getCharContent(boolean ignoreEncodingErrors)115 public CharSequence getCharContent(boolean ignoreEncodingErrors) { 116 return text; 117 } 118 } 119 120 static TestCase[] testCases = new TestCase[] { 121 new TestCase("<T> @DA int foo1() { return 0;}", ""), 122 new TestCase("<T> @DA void foo2() { }", ""), 123 new TestCase("<T> @TA int foo3() { return 0;}", ""), 124 new TestCase("<T> @TA void foo4() { }", 125 "Test.java:3:9: compiler.err.annotation.type.not.applicable"), 126 new TestCase("<T> @DA Test() { }", "Test.java:3:9: compiler.err.illegal.start.of.type"), 127 new TestCase("<T> @TA Test() { }", "Test.java:3:9: compiler.err.illegal.start.of.type"), 128 }; 129 130 static class TestCase { 131 final String snippet; 132 final String error; TestCase(String snippet, String error)133 public TestCase(String snippet, String error) { 134 this.snippet = snippet; 135 this.error = error; 136 } 137 } 138 } 139 140