Fri, 24 Apr 2020 03:58:51 +0100
Merge
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 */
24 /*
25 * @test
26 * @bug 7027157
27 * @summary Project Coin: javac warnings for AutoCloseable.close throwing InterruptedException
28 */
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;
40 public class InterruptedExceptionTest {
42 enum XlintOption {
43 NONE("none"),
44 TRY("try");
46 String opt;
48 XlintOption(String opt) {
49 this.opt = opt;
50 }
52 String getXlintOption() {
53 return "-Xlint:" + opt;
54 }
55 }
57 enum SuppressLevel {
58 NONE,
59 SUPPRESS;
61 String getSuppressAnno() {
62 return this == SUPPRESS ?
63 "@SuppressWarnings(\"try\")" :
64 "";
65 }
66 }
68 enum ClassKind {
69 ABSTRACT_CLASS("abstract class", "implements", false),
70 CLASS("class", "implements", true),
71 INTERFACE("interface", "extends", false);
73 String kindName;
74 String extendsClause;
75 boolean hasBody;
77 private ClassKind(String kindName, String extendsClause, boolean hasBody) {
78 this.kindName = kindName;
79 this.extendsClause = extendsClause;
80 this.hasBody = hasBody;
81 }
83 String getBody() {
84 return hasBody ? "{}" : ";";
85 }
86 }
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);
95 String exName;
96 boolean shouldWarn;
98 private ExceptionKind(String exName, boolean shouldWarn) {
99 this.exName = exName;
100 this.shouldWarn = shouldWarn;
101 }
103 String getThrowsClause() {
104 return this == NONE ? "" : "throws " + exName;
105 }
107 String getTypeArguments(ExceptionKind decl) {
108 return (decl != X || this == NONE) ? "" : "<" + exName + ">";
109 }
111 String getTypeParameter() {
112 return this == X ? "<X extends Exception>" : "";
113 }
114 }
116 public static void main(String... args) throws Exception {
118 //create default shared JavaCompiler - reused across multiple compilations
119 JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
120 StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
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 }
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;
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 }
159 class JavaSource extends SimpleJavaFileObject {
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";
170 String source;
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 }
184 @Override
185 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
186 return source;
187 }
188 }
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 }
197 void check() {
199 boolean shouldWarnDecl = ek_decl.shouldWarn &&
200 xlint == XlintOption.TRY &&
201 suppress_decl != SuppressLevel.SUPPRESS;
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;
208 int foundWarnings = 0;
210 if (shouldWarnDecl) foundWarnings++;
211 if (shouldWarnUse) foundWarnings++;
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 }
223 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
225 int tryWarnFound;
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 }