|
1 /* |
|
2 * Copyright (c) 2011, 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 6550655 |
|
27 * @summary javac crashes when compiling against an annotated class |
|
28 */ |
|
29 |
|
30 import java.io.File; |
|
31 import java.net.URI; |
|
32 import java.util.Arrays; |
|
33 |
|
34 import javax.tools.Diagnostic; |
|
35 import javax.tools.DiagnosticListener; |
|
36 import javax.tools.JavaCompiler; |
|
37 import javax.tools.JavaCompiler.CompilationTask; |
|
38 import javax.tools.JavaFileObject; |
|
39 import javax.tools.SimpleJavaFileObject; |
|
40 import javax.tools.ToolProvider; |
|
41 |
|
42 public class T6550655 { |
|
43 |
|
44 JavaCompiler javacTool; |
|
45 File testDir; |
|
46 TestKind testKind; |
|
47 EnumActionKind actionKind; |
|
48 |
|
49 String testSource = "enum E { NORTH, SOUTH, WEST, EAST; }\n" + |
|
50 "@I(val = E.NORTH)class A {}\n" + |
|
51 "@interface I { E val(); }"; |
|
52 |
|
53 T6550655(JavaCompiler javacTool, File testDir, TestKind testKind, EnumActionKind actionKind) { |
|
54 this.javacTool = javacTool; |
|
55 this.testDir = testDir; |
|
56 this.testKind = testKind; |
|
57 this.actionKind = actionKind; |
|
58 } |
|
59 |
|
60 void test() { |
|
61 testDir.mkdirs(); |
|
62 compile(null, new JavaSource("Test.java", testSource)); |
|
63 actionKind.doAction(this); |
|
64 compile(new DiagnosticChecker(), testKind.source); |
|
65 } |
|
66 |
|
67 void compile(DiagnosticChecker dc, JavaSource... sources) { |
|
68 try { |
|
69 CompilationTask ct = javacTool.getTask(null, null, dc, |
|
70 Arrays.asList("-d", testDir.getAbsolutePath(), "-cp", testDir.getAbsolutePath()), |
|
71 null, Arrays.asList(sources)); |
|
72 ct.call(); |
|
73 } |
|
74 catch (Exception e) { |
|
75 error("Internal compilation error"); |
|
76 } |
|
77 } |
|
78 |
|
79 void replaceEnum(String newSource) { |
|
80 compile(null, new JavaSource("Replace.java", newSource)); |
|
81 }; |
|
82 |
|
83 void removeEnum() { |
|
84 File enumClass = new File(testDir, "E.class"); |
|
85 if (!enumClass.exists()) { |
|
86 error("Expected file E.class does not exists in folder " + testDir); |
|
87 } |
|
88 enumClass.delete(); |
|
89 }; |
|
90 |
|
91 void error(String msg) { |
|
92 System.err.println(msg); |
|
93 nerrors++; |
|
94 } |
|
95 |
|
96 class DiagnosticChecker implements DiagnosticListener<JavaFileObject> { |
|
97 |
|
98 String[][] expectedKeys = new String[][] { |
|
99 // DIRECT, INDIRECT |
|
100 {/*REPLACE1*/ "compiler.err.cant.resolve.location" , "compiler.warn.unknown.enum.constant" }, |
|
101 {/*REPLACE2*/ "compiler.err.cant.resolve.location.args", "compiler.warn.annotation.method.not.found" }, |
|
102 {/*REMOVE*/ "compiler.err.cant.resolve" , "compiler.warn.unknown.enum.constant.reason" } }; |
|
103 |
|
104 String keyToIgnore = "compiler.err.attribute.value.must.be.constant"; |
|
105 |
|
106 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |
|
107 String expectedCode = expectedKeys[actionKind.ordinal()][testKind.ordinal()]; |
|
108 if (!diagnostic.getCode().equals(keyToIgnore) && |
|
109 !diagnostic.getCode().equals(expectedCode)) { |
|
110 error("Unexpected diagnostic" + |
|
111 "\nfound " + diagnostic.getCode() + |
|
112 "\nexpected " + expectedCode + |
|
113 "\ntestKind " + testKind + |
|
114 "\nactionKind " + actionKind); |
|
115 } |
|
116 } |
|
117 } |
|
118 |
|
119 //global declarations |
|
120 |
|
121 enum EnumActionKind { |
|
122 REPLACE1("enum E { SOUTH, WEST, EAST; }") { |
|
123 @Override |
|
124 void doAction(T6550655 test) { |
|
125 test.replaceEnum(optionalSource); |
|
126 } |
|
127 }, |
|
128 REPLACE2("@interface I { E valNew() default E.EAST; }") { |
|
129 @Override |
|
130 void doAction(T6550655 test) { |
|
131 test.replaceEnum(optionalSource); |
|
132 } |
|
133 }, |
|
134 REMOVE(null) { |
|
135 @Override |
|
136 void doAction(T6550655 test) { test.removeEnum(); } |
|
137 }; |
|
138 |
|
139 String optionalSource; |
|
140 |
|
141 private EnumActionKind(String optionalSource) { |
|
142 this.optionalSource = optionalSource; |
|
143 } |
|
144 |
|
145 abstract void doAction(T6550655 test); |
|
146 } |
|
147 |
|
148 enum TestKind { |
|
149 DIRECT("@I(val = E.NORTH)class C1 {}"), |
|
150 INDIRECT("class C2 { A a; }"); |
|
151 |
|
152 JavaSource source; |
|
153 |
|
154 private TestKind(final String code) { |
|
155 this.source = new JavaSource("Test.java", code); |
|
156 } |
|
157 } |
|
158 |
|
159 public static void main(String[] args) throws Exception { |
|
160 String SCRATCH_DIR = System.getProperty("user.dir"); |
|
161 JavaCompiler javacTool = ToolProvider.getSystemJavaCompiler(); |
|
162 int n = 0; |
|
163 for (TestKind testKind : TestKind.values()) { |
|
164 for (EnumActionKind actionKind : EnumActionKind.values()) { |
|
165 File testDir = new File(SCRATCH_DIR, "test"+n); |
|
166 new T6550655(javacTool, testDir, testKind, actionKind).test(); |
|
167 n++; |
|
168 } |
|
169 } |
|
170 if (nerrors > 0) { |
|
171 throw new AssertionError("Some errors have been detected"); |
|
172 } |
|
173 } |
|
174 |
|
175 static class JavaSource extends SimpleJavaFileObject { |
|
176 |
|
177 String source; |
|
178 |
|
179 public JavaSource(String filename, String source) { |
|
180 super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE); |
|
181 this.source = source; |
|
182 } |
|
183 |
|
184 @Override |
|
185 public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
|
186 return source; |
|
187 } |
|
188 } |
|
189 |
|
190 static int nerrors = 0; |
|
191 } |