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