| /* |
| * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * @test |
| * @bug 7027157 |
| * @summary Project Coin: javac warnings for AutoCloseable.close throwing InterruptedException |
| */ |
| |
| import com.sun.source.util.JavacTask; |
| import java.net.URI; |
| import java.util.Arrays; |
| import javax.tools.Diagnostic; |
| import javax.tools.JavaCompiler; |
| import javax.tools.JavaFileObject; |
| import javax.tools.SimpleJavaFileObject; |
| import javax.tools.StandardJavaFileManager; |
| import javax.tools.ToolProvider; |
| |
| public class InterruptedExceptionTest { |
| |
| enum XlintOption { |
| NONE("none"), |
| TRY("try"); |
| |
| String opt; |
| |
| XlintOption(String opt) { |
| this.opt = opt; |
| } |
| |
| String getXlintOption() { |
| return "-Xlint:" + opt; |
| } |
| } |
| |
| enum SuppressLevel { |
| NONE, |
| SUPPRESS; |
| |
| String getSuppressAnno() { |
| return this == SUPPRESS ? |
| "@SuppressWarnings(\"try\")" : |
| ""; |
| } |
| } |
| |
| enum ClassKind { |
| ABSTRACT_CLASS("abstract class", "implements", false), |
| CLASS("class", "implements", true), |
| INTERFACE("interface", "extends", false); |
| |
| String kindName; |
| String extendsClause; |
| boolean hasBody; |
| |
| private ClassKind(String kindName, String extendsClause, boolean hasBody) { |
| this.kindName = kindName; |
| this.extendsClause = extendsClause; |
| this.hasBody = hasBody; |
| } |
| |
| String getBody() { |
| return hasBody ? "{}" : ";"; |
| } |
| } |
| |
| enum ExceptionKind { |
| NONE("", false), |
| EXCEPTION("Exception", true), |
| INTERRUPTED_EXCEPTION("InterruptedException", true), |
| ILLEGAL_ARGUMENT_EXCEPTION("IllegalArgumentException", false), |
| X("X", false); |
| |
| String exName; |
| boolean shouldWarn; |
| |
| private ExceptionKind(String exName, boolean shouldWarn) { |
| this.exName = exName; |
| this.shouldWarn = shouldWarn; |
| } |
| |
| String getThrowsClause() { |
| return this == NONE ? "" : "throws " + exName; |
| } |
| |
| String getTypeArguments(ExceptionKind decl) { |
| return (decl != X || this == NONE) ? "" : "<" + exName + ">"; |
| } |
| |
| String getTypeParameter() { |
| return this == X ? "<X extends Exception>" : ""; |
| } |
| } |
| |
| public static void main(String... args) throws Exception { |
| |
| //create default shared JavaCompiler - reused across multiple compilations |
| JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); |
| StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); |
| |
| for (XlintOption xlint : XlintOption.values()) { |
| for (SuppressLevel suppress_decl : SuppressLevel.values()) { |
| for (SuppressLevel suppress_use : SuppressLevel.values()) { |
| for (ClassKind ck : ClassKind.values()) { |
| for (ExceptionKind ek_decl : ExceptionKind.values()) { |
| for (ExceptionKind ek_use : ExceptionKind.values()) { |
| new InterruptedExceptionTest(xlint, suppress_decl, |
| suppress_use, ck, ek_decl, ek_use).run(comp, fm); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| XlintOption xlint; |
| SuppressLevel suppress_decl; |
| SuppressLevel suppress_use; |
| ClassKind ck; |
| ExceptionKind ek_decl; |
| ExceptionKind ek_use; |
| JavaSource source; |
| DiagnosticChecker diagChecker; |
| |
| InterruptedExceptionTest(XlintOption xlint, SuppressLevel suppress_decl, SuppressLevel suppress_use, |
| ClassKind ck, ExceptionKind ek_decl, ExceptionKind ek_use) { |
| this.xlint = xlint; |
| this.suppress_decl = suppress_decl; |
| this.suppress_use = suppress_use; |
| this.ck = ck; |
| this.ek_decl = ek_decl; |
| this.ek_use = ek_use; |
| this.source = new JavaSource(); |
| this.diagChecker = new DiagnosticChecker(); |
| } |
| |
| class JavaSource extends SimpleJavaFileObject { |
| |
| String template = "#S1 #CK Resource#G #EC AutoCloseable {\n" + |
| "public void close() #TK #BK\n" + |
| "}\n" + |
| "class Test {\n" + |
| "#S2 <X> void test() {\n" + |
| "try (Resource#PK r = null) { }\n" + |
| "}\n" + |
| "}\n"; |
| |
| String source; |
| |
| public JavaSource() { |
| super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); |
| source = template.replace("#S1", suppress_decl.getSuppressAnno()) |
| .replace("#S2", suppress_use.getSuppressAnno()) |
| .replace("#CK", ck.kindName) |
| .replace("#EC", ck.extendsClause) |
| .replace("#G", ek_decl.getTypeParameter()) |
| .replace("#TK", ek_decl.getThrowsClause()) |
| .replace("#BK", ck.getBody()) |
| .replace("#PK", ek_use.getTypeArguments(ek_decl)); |
| } |
| |
| @Override |
| public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
| return source; |
| } |
| } |
| |
| void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { |
| JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, |
| Arrays.asList(xlint.getXlintOption()), null, Arrays.asList(source)); |
| ct.analyze(); |
| check(); |
| } |
| |
| void check() { |
| |
| boolean shouldWarnDecl = ek_decl.shouldWarn && |
| xlint == XlintOption.TRY && |
| suppress_decl != SuppressLevel.SUPPRESS; |
| |
| boolean shouldWarnUse = (ek_decl.shouldWarn || |
| ((ek_use.shouldWarn || ek_use == ExceptionKind.NONE) && ek_decl == ExceptionKind.X)) && |
| xlint == XlintOption.TRY && |
| suppress_use != SuppressLevel.SUPPRESS; |
| |
| int foundWarnings = 0; |
| |
| if (shouldWarnDecl) foundWarnings++; |
| if (shouldWarnUse) foundWarnings++; |
| |
| if (foundWarnings != diagChecker.tryWarnFound) { |
| throw new Error("invalid diagnostics for source:\n" + |
| source.getCharContent(true) + |
| "\nOptions: " + xlint.getXlintOption() + |
| "\nFound warnings: " + diagChecker.tryWarnFound + |
| "\nExpected decl warning: " + shouldWarnDecl + |
| "\nExpected use warning: " + shouldWarnUse); |
| } |
| } |
| |
| static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { |
| |
| int tryWarnFound; |
| |
| public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |
| if (diagnostic.getKind() == Diagnostic.Kind.WARNING && |
| diagnostic.getCode().contains("try.resource.throws.interrupted.exc")) { |
| tryWarnFound++; |
| } |
| } |
| } |
| } |