test/tools/javac/varargs/warning/Warn5.java

changeset 0
959103a6100f
child 2525
2eb010b6cb22
equal deleted inserted replaced
-1:000000000000 0:959103a6100f
1 /*
2 * Copyright (c) 2010, 2013, 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 6993978 7097436 8006694
27 * @summary Project Coin: Annotation to reduce varargs warnings
28 * temporarily workaround combo tests are causing time out in several platforms
29 * @author mcimadamore
30 * @library ../../lib
31 * @build JavacTestingAbstractThreadedTest
32 * @run main/othervm Warn5
33 */
34
35 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
36 // see JDK-8006746
37
38 import java.net.URI;
39 import java.util.Arrays;
40 import java.util.EnumSet;
41 import javax.tools.Diagnostic;
42 import javax.tools.JavaCompiler;
43 import javax.tools.JavaFileObject;
44 import javax.tools.SimpleJavaFileObject;
45 import javax.tools.ToolProvider;
46 import com.sun.source.util.JavacTask;
47
48 public class Warn5
49 extends JavacTestingAbstractThreadedTest
50 implements Runnable {
51
52 enum XlintOption {
53 NONE("none"),
54 ALL("all");
55
56 String opt;
57
58 XlintOption(String opt) {
59 this.opt = opt;
60 }
61
62 String getXlintOption() {
63 return "-Xlint:" + opt;
64 }
65 }
66
67 enum TrustMe {
68 DONT_TRUST(""),
69 TRUST("@java.lang.SafeVarargs");
70
71 String anno;
72
73 TrustMe(String anno) {
74 this.anno = anno;
75 }
76 }
77
78 enum SuppressLevel {
79 NONE,
80 VARARGS;
81
82 String getSuppressAnno() {
83 return this == VARARGS ?
84 "@SuppressWarnings(\"varargs\")" :
85 "";
86 }
87 }
88
89 enum ModifierKind {
90 NONE(""),
91 FINAL("final"),
92 STATIC("static");
93
94 String mod;
95
96 ModifierKind(String mod) {
97 this.mod = mod;
98 }
99 }
100
101 enum MethodKind {
102 METHOD("void m"),
103 CONSTRUCTOR("Test");
104
105 String name;
106
107 MethodKind(String name) {
108 this.name = name;
109 }
110 }
111
112 enum SourceLevel {
113 JDK_6("6"),
114 JDK_7("7");
115
116 String sourceKey;
117
118 SourceLevel(String sourceKey) {
119 this.sourceKey = sourceKey;
120 }
121 }
122
123 enum SignatureKind {
124 VARARGS_X("#K <X>#N(X... x)", false, true),
125 VARARGS_STRING("#K #N(String... x)", true, true),
126 ARRAY_X("#K <X>#N(X[] x)", false, false),
127 ARRAY_STRING("#K #N(String[] x)", true, false);
128
129 String stub;
130 boolean isReifiableArg;
131 boolean isVarargs;
132
133 SignatureKind(String stub, boolean isReifiableArg, boolean isVarargs) {
134 this.stub = stub;
135 this.isReifiableArg = isReifiableArg;
136 this.isVarargs = isVarargs;
137 }
138
139 String getSignature(ModifierKind modKind, MethodKind methKind) {
140 return methKind != MethodKind.CONSTRUCTOR ?
141 stub.replace("#K", modKind.mod).replace("#N", methKind.name) :
142 stub.replace("#K", "").replace("#N", methKind.name);
143 }
144 }
145
146 enum BodyKind {
147 ASSIGN("Object o = x;", true),
148 CAST("Object o = (Object)x;", true),
149 METH("test(x);", true),
150 PRINT("System.out.println(x.toString());", false),
151 ARRAY_ASSIGN("Object[] o = x;", true),
152 ARRAY_CAST("Object[] o = (Object[])x;", true),
153 ARRAY_METH("testArr(x);", true);
154
155 String body;
156 boolean hasAliasing;
157
158 BodyKind(String body, boolean hasAliasing) {
159 this.body = body;
160 this.hasAliasing = hasAliasing;
161 }
162 }
163
164 enum WarningKind {
165 UNSAFE_BODY,
166 UNSAFE_DECL,
167 MALFORMED_SAFEVARARGS,
168 REDUNDANT_SAFEVARARGS;
169 }
170
171 public static void main(String... args) throws Exception {
172 for (SourceLevel sourceLevel : SourceLevel.values()) {
173 for (XlintOption xlint : XlintOption.values()) {
174 for (TrustMe trustMe : TrustMe.values()) {
175 for (SuppressLevel suppressLevel : SuppressLevel.values()) {
176 for (ModifierKind modKind : ModifierKind.values()) {
177 for (MethodKind methKind : MethodKind.values()) {
178 for (SignatureKind sig : SignatureKind.values()) {
179 for (BodyKind body : BodyKind.values()) {
180 pool.execute(new Warn5(sourceLevel,
181 xlint, trustMe, suppressLevel,
182 modKind, methKind, sig, body));
183 }
184 }
185 }
186 }
187 }
188 }
189 }
190 }
191
192 checkAfterExec(false);
193 }
194
195 final SourceLevel sourceLevel;
196 final XlintOption xlint;
197 final TrustMe trustMe;
198 final SuppressLevel suppressLevel;
199 final ModifierKind modKind;
200 final MethodKind methKind;
201 final SignatureKind sig;
202 final BodyKind body;
203 final JavaSource source;
204 final DiagnosticChecker dc;
205
206 public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe,
207 SuppressLevel suppressLevel, ModifierKind modKind,
208 MethodKind methKind, SignatureKind sig, BodyKind body) {
209 this.sourceLevel = sourceLevel;
210 this.xlint = xlint;
211 this.trustMe = trustMe;
212 this.suppressLevel = suppressLevel;
213 this.modKind = modKind;
214 this.methKind = methKind;
215 this.sig = sig;
216 this.body = body;
217 this.source = new JavaSource();
218 this.dc = new DiagnosticChecker();
219 }
220
221 @Override
222 public void run() {
223 final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
224 JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc,
225 Arrays.asList(xlint.getXlintOption(),
226 "-source", sourceLevel.sourceKey),
227 null, Arrays.asList(source));
228 try {
229 ct.analyze();
230 } catch (Throwable t) {
231 processException(t);
232 }
233 check();
234 }
235
236 void check() {
237
238 EnumSet<WarningKind> expectedWarnings =
239 EnumSet.noneOf(WarningKind.class);
240
241 if (sourceLevel == SourceLevel.JDK_7 &&
242 trustMe == TrustMe.TRUST &&
243 suppressLevel != SuppressLevel.VARARGS &&
244 xlint != XlintOption.NONE &&
245 sig.isVarargs &&
246 !sig.isReifiableArg &&
247 body.hasAliasing &&
248 (methKind == MethodKind.CONSTRUCTOR ||
249 (methKind == MethodKind.METHOD &&
250 modKind != ModifierKind.NONE))) {
251 expectedWarnings.add(WarningKind.UNSAFE_BODY);
252 }
253
254 if (sourceLevel == SourceLevel.JDK_7 &&
255 trustMe == TrustMe.DONT_TRUST &&
256 sig.isVarargs &&
257 !sig.isReifiableArg &&
258 xlint == XlintOption.ALL) {
259 expectedWarnings.add(WarningKind.UNSAFE_DECL);
260 }
261
262 if (sourceLevel == SourceLevel.JDK_7 &&
263 trustMe == TrustMe.TRUST &&
264 (!sig.isVarargs ||
265 (modKind == ModifierKind.NONE &&
266 methKind == MethodKind.METHOD))) {
267 expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS);
268 }
269
270 if (sourceLevel == SourceLevel.JDK_7 &&
271 trustMe == TrustMe.TRUST &&
272 xlint != XlintOption.NONE &&
273 suppressLevel != SuppressLevel.VARARGS &&
274 (modKind != ModifierKind.NONE ||
275 methKind == MethodKind.CONSTRUCTOR) &&
276 sig.isVarargs &&
277 sig.isReifiableArg) {
278 expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS);
279 }
280
281 if (!expectedWarnings.containsAll(dc.warnings) ||
282 !dc.warnings.containsAll(expectedWarnings)) {
283 throw new Error("invalid diagnostics for source:\n" +
284 source.getCharContent(true) +
285 "\nOptions: " + xlint.getXlintOption() +
286 "\nExpected warnings: " + expectedWarnings +
287 "\nFound warnings: " + dc.warnings);
288 }
289 }
290
291 class JavaSource extends SimpleJavaFileObject {
292
293 String template = "import com.sun.tools.javac.api.*;\n" +
294 "import java.util.List;\n" +
295 "class Test {\n" +
296 " static void test(Object o) {}\n" +
297 " static void testArr(Object[] o) {}\n" +
298 " #T \n #S #M { #B }\n" +
299 "}\n";
300
301 String source;
302
303 public JavaSource() {
304 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
305 source = template.replace("#T", trustMe.anno).
306 replace("#S", suppressLevel.getSuppressAnno()).
307 replace("#M", sig.getSignature(modKind, methKind)).
308 replace("#B", body.body);
309 }
310
311 @Override
312 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
313 return source;
314 }
315 }
316
317 class DiagnosticChecker
318 implements javax.tools.DiagnosticListener<JavaFileObject> {
319
320 EnumSet<WarningKind> warnings = EnumSet.noneOf(WarningKind.class);
321
322 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
323 if (diagnostic.getKind() == Diagnostic.Kind.WARNING) {
324 if (diagnostic.getCode().
325 contains("unsafe.use.varargs.param")) {
326 setWarning(WarningKind.UNSAFE_BODY);
327 } else if (diagnostic.getCode().
328 contains("redundant.trustme")) {
329 setWarning(WarningKind.REDUNDANT_SAFEVARARGS);
330 }
331 } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING &&
332 diagnostic.getCode().
333 contains("varargs.non.reifiable.type")) {
334 setWarning(WarningKind.UNSAFE_DECL);
335 } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
336 diagnostic.getCode().contains("invalid.trustme")) {
337 setWarning(WarningKind.MALFORMED_SAFEVARARGS);
338 }
339 }
340
341 void setWarning(WarningKind wk) {
342 if (!warnings.add(wk)) {
343 throw new AssertionError("Duplicate warning of kind " +
344 wk + " in source:\n" + source);
345 }
346 }
347
348 boolean hasWarning(WarningKind wk) {
349 return warnings.contains(wk);
350 }
351 }
352
353 }

mercurial