|
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 7027157 |
|
27 * @summary Project Coin: javac warnings for AutoCloseable.close throwing InterruptedException |
|
28 */ |
|
29 |
|
30 import com.sun.source.util.JavacTask; |
|
31 import java.net.URI; |
|
32 import java.util.Arrays; |
|
33 import javax.tools.Diagnostic; |
|
34 import javax.tools.JavaCompiler; |
|
35 import javax.tools.JavaFileObject; |
|
36 import javax.tools.SimpleJavaFileObject; |
|
37 import javax.tools.StandardJavaFileManager; |
|
38 import javax.tools.ToolProvider; |
|
39 |
|
40 public class InterruptedExceptionTest { |
|
41 |
|
42 enum XlintOption { |
|
43 NONE("none"), |
|
44 TRY("try"); |
|
45 |
|
46 String opt; |
|
47 |
|
48 XlintOption(String opt) { |
|
49 this.opt = opt; |
|
50 } |
|
51 |
|
52 String getXlintOption() { |
|
53 return "-Xlint:" + opt; |
|
54 } |
|
55 } |
|
56 |
|
57 enum SuppressLevel { |
|
58 NONE, |
|
59 SUPPRESS; |
|
60 |
|
61 String getSuppressAnno() { |
|
62 return this == SUPPRESS ? |
|
63 "@SuppressWarnings(\"try\")" : |
|
64 ""; |
|
65 } |
|
66 } |
|
67 |
|
68 enum ClassKind { |
|
69 ABSTRACT_CLASS("abstract class", "implements", false), |
|
70 CLASS("class", "implements", true), |
|
71 INTERFACE("interface", "extends", false); |
|
72 |
|
73 String kindName; |
|
74 String extendsClause; |
|
75 boolean hasBody; |
|
76 |
|
77 private ClassKind(String kindName, String extendsClause, boolean hasBody) { |
|
78 this.kindName = kindName; |
|
79 this.extendsClause = extendsClause; |
|
80 this.hasBody = hasBody; |
|
81 } |
|
82 |
|
83 String getBody() { |
|
84 return hasBody ? "{}" : ";"; |
|
85 } |
|
86 } |
|
87 |
|
88 enum ExceptionKind { |
|
89 NONE("", false), |
|
90 EXCEPTION("Exception", true), |
|
91 INTERRUPTED_EXCEPTION("InterruptedException", true), |
|
92 ILLEGAL_ARGUMENT_EXCEPTION("IllegalArgumentException", false), |
|
93 X("X", false); |
|
94 |
|
95 String exName; |
|
96 boolean shouldWarn; |
|
97 |
|
98 private ExceptionKind(String exName, boolean shouldWarn) { |
|
99 this.exName = exName; |
|
100 this.shouldWarn = shouldWarn; |
|
101 } |
|
102 |
|
103 String getThrowsClause() { |
|
104 return this == NONE ? "" : "throws " + exName; |
|
105 } |
|
106 |
|
107 String getTypeArguments(ExceptionKind decl) { |
|
108 return (decl != X || this == NONE) ? "" : "<" + exName + ">"; |
|
109 } |
|
110 |
|
111 String getTypeParameter() { |
|
112 return this == X ? "<X extends Exception>" : ""; |
|
113 } |
|
114 } |
|
115 |
|
116 public static void main(String... args) throws Exception { |
|
117 |
|
118 //create default shared JavaCompiler - reused across multiple compilations |
|
119 JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); |
|
120 StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); |
|
121 |
|
122 for (XlintOption xlint : XlintOption.values()) { |
|
123 for (SuppressLevel suppress_decl : SuppressLevel.values()) { |
|
124 for (SuppressLevel suppress_use : SuppressLevel.values()) { |
|
125 for (ClassKind ck : ClassKind.values()) { |
|
126 for (ExceptionKind ek_decl : ExceptionKind.values()) { |
|
127 for (ExceptionKind ek_use : ExceptionKind.values()) { |
|
128 new InterruptedExceptionTest(xlint, suppress_decl, |
|
129 suppress_use, ck, ek_decl, ek_use).run(comp, fm); |
|
130 } |
|
131 } |
|
132 } |
|
133 } |
|
134 } |
|
135 } |
|
136 } |
|
137 |
|
138 XlintOption xlint; |
|
139 SuppressLevel suppress_decl; |
|
140 SuppressLevel suppress_use; |
|
141 ClassKind ck; |
|
142 ExceptionKind ek_decl; |
|
143 ExceptionKind ek_use; |
|
144 JavaSource source; |
|
145 DiagnosticChecker diagChecker; |
|
146 |
|
147 InterruptedExceptionTest(XlintOption xlint, SuppressLevel suppress_decl, SuppressLevel suppress_use, |
|
148 ClassKind ck, ExceptionKind ek_decl, ExceptionKind ek_use) { |
|
149 this.xlint = xlint; |
|
150 this.suppress_decl = suppress_decl; |
|
151 this.suppress_use = suppress_use; |
|
152 this.ck = ck; |
|
153 this.ek_decl = ek_decl; |
|
154 this.ek_use = ek_use; |
|
155 this.source = new JavaSource(); |
|
156 this.diagChecker = new DiagnosticChecker(); |
|
157 } |
|
158 |
|
159 class JavaSource extends SimpleJavaFileObject { |
|
160 |
|
161 String template = "#S1 #CK Resource#G #EC AutoCloseable {\n" + |
|
162 "public void close() #TK #BK\n" + |
|
163 "}\n" + |
|
164 "class Test {\n" + |
|
165 "#S2 <X> void test() {\n" + |
|
166 "try (Resource#PK r = null) { }\n" + |
|
167 "}\n" + |
|
168 "}\n"; |
|
169 |
|
170 String source; |
|
171 |
|
172 public JavaSource() { |
|
173 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); |
|
174 source = template.replace("#S1", suppress_decl.getSuppressAnno()) |
|
175 .replace("#S2", suppress_use.getSuppressAnno()) |
|
176 .replace("#CK", ck.kindName) |
|
177 .replace("#EC", ck.extendsClause) |
|
178 .replace("#G", ek_decl.getTypeParameter()) |
|
179 .replace("#TK", ek_decl.getThrowsClause()) |
|
180 .replace("#BK", ck.getBody()) |
|
181 .replace("#PK", ek_use.getTypeArguments(ek_decl)); |
|
182 } |
|
183 |
|
184 @Override |
|
185 public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
|
186 return source; |
|
187 } |
|
188 } |
|
189 |
|
190 void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { |
|
191 JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, |
|
192 Arrays.asList(xlint.getXlintOption()), null, Arrays.asList(source)); |
|
193 ct.analyze(); |
|
194 check(); |
|
195 } |
|
196 |
|
197 void check() { |
|
198 |
|
199 boolean shouldWarnDecl = ek_decl.shouldWarn && |
|
200 xlint == XlintOption.TRY && |
|
201 suppress_decl != SuppressLevel.SUPPRESS; |
|
202 |
|
203 boolean shouldWarnUse = (ek_decl.shouldWarn || |
|
204 ((ek_use.shouldWarn || ek_use == ExceptionKind.NONE) && ek_decl == ExceptionKind.X)) && |
|
205 xlint == XlintOption.TRY && |
|
206 suppress_use != SuppressLevel.SUPPRESS; |
|
207 |
|
208 int foundWarnings = 0; |
|
209 |
|
210 if (shouldWarnDecl) foundWarnings++; |
|
211 if (shouldWarnUse) foundWarnings++; |
|
212 |
|
213 if (foundWarnings != diagChecker.tryWarnFound) { |
|
214 throw new Error("invalid diagnostics for source:\n" + |
|
215 source.getCharContent(true) + |
|
216 "\nOptions: " + xlint.getXlintOption() + |
|
217 "\nFound warnings: " + diagChecker.tryWarnFound + |
|
218 "\nExpected decl warning: " + shouldWarnDecl + |
|
219 "\nExpected use warning: " + shouldWarnUse); |
|
220 } |
|
221 } |
|
222 |
|
223 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { |
|
224 |
|
225 int tryWarnFound; |
|
226 |
|
227 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |
|
228 if (diagnostic.getKind() == Diagnostic.Kind.WARNING && |
|
229 diagnostic.getCode().contains("try.resource.throws.interrupted.exc")) { |
|
230 tryWarnFound++; |
|
231 } |
|
232 } |
|
233 } |
|
234 } |