test/tools/javac/TryWithResources/UnusedResourcesTest.java

Mon, 26 Oct 2015 13:23:30 -0700

author
asaha
date
Mon, 26 Oct 2015 13:23:30 -0700
changeset 2999
683b3e7e05a7
parent 1073
f85d980faaf8
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Added tag jdk8u76-b00 for changeset 10ffafaf5340

     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 7023233
    27  * @summary False positive for -Xlint:try with nested try with resources blocks
    28  */
    30 import com.sun.source.util.JavacTask;
    31 import com.sun.tools.javac.api.ClientCodeWrapper;
    32 import com.sun.tools.javac.api.JavacTool;
    33 import com.sun.tools.javac.util.JCDiagnostic;
    34 import java.net.URI;
    35 import java.util.Arrays;
    36 import javax.tools.Diagnostic;
    37 import javax.tools.JavaCompiler;
    38 import javax.tools.JavaFileObject;
    39 import javax.tools.SimpleJavaFileObject;
    40 import javax.tools.StandardJavaFileManager;
    41 import javax.tools.ToolProvider;
    43 public class UnusedResourcesTest {
    45     enum XlintOption {
    46         NONE("none"),
    47         TRY("try");
    49         String opt;
    51         XlintOption(String opt) {
    52             this.opt = opt;
    53         }
    55         String getXlintOption() {
    56             return "-Xlint:" + opt;
    57         }
    58     }
    60     enum TwrStmt {
    61         TWR1("res1"),
    62         TWR2("res2"),
    63         TWR3("res3");
    65         final String resourceName;
    67         private TwrStmt(String resourceName) {
    68             this.resourceName = resourceName;
    69         }
    70     }
    72     enum SuppressLevel {
    73         NONE,
    74         SUPPRESS;
    76         String getSuppressAnno() {
    77             return this == SUPPRESS ?
    78                 "@SuppressWarnings(\"try\")" :
    79                 "";
    80         }
    81     }
    83     enum ResourceUsage {
    84         NONE(null),
    85         USE_R1(TwrStmt.TWR1),
    86         USE_R2(TwrStmt.TWR2),
    87         USE_R3(TwrStmt.TWR3);
    89         TwrStmt stmt;
    91         private ResourceUsage(TwrStmt stmt) {
    92             this.stmt = stmt;
    93         }
    95         String usedResourceName() {
    96             return stmt != null ? stmt.resourceName : null;
    97         }
    99         boolean isUsedIn(TwrStmt res, TwrStmt stmt) {
   100             return this.stmt == res &&
   101                     stmt.ordinal() >= this.stmt.ordinal();
   102         }
   104         String getUsage(TwrStmt stmt) {
   105             return this != NONE && stmt.ordinal() >= this.stmt.ordinal() ?
   106                 "use(" + usedResourceName() + ");" :
   107                 "";
   108         }
   109     }
   111     static class JavaSource extends SimpleJavaFileObject {
   113         String template = "class Resource implements AutoCloseable {\n" +
   114                               "public void close() {}\n" +
   115                           "}\n" +
   116                           "class Test {\n" +
   117                               "void use(Resource r) {}\n" +
   118                               "#S void test() {\n" +
   119                                  "try (Resource #R1 = new Resource()) {\n" +
   120                                     "#U1_R1\n" +
   121                                     "#U1_R2\n" +
   122                                     "#U1_R3\n" +
   123                                     "try (Resource #R2 = new Resource()) {\n" +
   124                                        "#U2_R1\n" +
   125                                        "#U2_R2\n" +
   126                                        "#U2_R3\n" +
   127                                        "try (Resource #R3 = new Resource()) {\n" +
   128                                            "#U3_R1\n" +
   129                                            "#U3_R2\n" +
   130                                            "#U3_R3\n" +
   131                                        "}\n" +
   132                                     "}\n" +
   133                                  "}\n" +
   134                               "}\n" +
   135                           "}\n";
   137         String source;
   139         public JavaSource(SuppressLevel suppressLevel, ResourceUsage usage1,
   140                 ResourceUsage usage2, ResourceUsage usage3) {
   141             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   142             source = template.replace("#S", suppressLevel.getSuppressAnno()).
   143                     replace("#R1", TwrStmt.TWR1.resourceName).
   144                     replace("#R2", TwrStmt.TWR2.resourceName).
   145                     replace("#R3", TwrStmt.TWR3.resourceName).
   146                     replace("#U1_R1", usage1.getUsage(TwrStmt.TWR1)).
   147                     replace("#U1_R2", usage2.getUsage(TwrStmt.TWR1)).
   148                     replace("#U1_R3", usage3.getUsage(TwrStmt.TWR1)).
   149                     replace("#U2_R1", usage1.getUsage(TwrStmt.TWR2)).
   150                     replace("#U2_R2", usage2.getUsage(TwrStmt.TWR2)).
   151                     replace("#U2_R3", usage3.getUsage(TwrStmt.TWR2)).
   152                     replace("#U3_R1", usage1.getUsage(TwrStmt.TWR3)).
   153                     replace("#U3_R2", usage2.getUsage(TwrStmt.TWR3)).
   154                     replace("#U3_R3", usage3.getUsage(TwrStmt.TWR3));
   155         }
   157         @Override
   158         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   159             return source;
   160         }
   161     }
   163     public static void main(String... args) throws Exception {
   164         for (XlintOption xlint : XlintOption.values()) {
   165             for (SuppressLevel suppressLevel : SuppressLevel.values()) {
   166                 for (ResourceUsage usage1 : ResourceUsage.values()) {
   167                     for (ResourceUsage usage2 : ResourceUsage.values()) {
   168                         for (ResourceUsage usage3 : ResourceUsage.values()) {
   169                                 test(xlint,
   170                                         suppressLevel,
   171                                         usage1,
   172                                         usage2,
   173                                         usage3);
   174                         }
   175                     }
   176                 }
   177             }
   178         }
   179     }
   181     // Create a single file manager and reuse it for each compile to save time.
   182     static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
   184     static void test(XlintOption xlint, SuppressLevel suppressLevel, ResourceUsage usage1,
   185                 ResourceUsage usage2, ResourceUsage usage3) throws Exception {
   186         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
   187         JavaSource source = new JavaSource(suppressLevel, usage1, usage2, usage3);
   188         DiagnosticChecker dc = new DiagnosticChecker();
   189         JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
   190                 Arrays.asList(xlint.getXlintOption()), null, Arrays.asList(source));
   191         ct.analyze();
   192         check(source, xlint, suppressLevel, usage1, usage2, usage3, dc);
   193     }
   195     static void check(JavaSource source, XlintOption xlint, SuppressLevel suppressLevel,
   196                 ResourceUsage usage1, ResourceUsage usage2, ResourceUsage usage3, DiagnosticChecker dc) {
   198         ResourceUsage[] usages = { usage1, usage2, usage3 };
   199         boolean[] unusedFound = { dc.unused_r1, dc.unused_r2, dc.unused_r3 };
   200         boolean[] usedResources = { false, false, false };
   202         for (TwrStmt res : TwrStmt.values()) {
   203             outer: for (TwrStmt stmt : TwrStmt.values()) {
   204                 for (ResourceUsage usage : usages) {
   205                     if (usage.isUsedIn(res, stmt)) {
   206                         usedResources[res.ordinal()] = true;
   207                         break outer;
   208                     }
   209                 }
   210             }
   211         }
   213         for (TwrStmt stmt : TwrStmt.values()) {
   214             boolean unused = !usedResources[stmt.ordinal()] &&
   215                     xlint == XlintOption.TRY &&
   216                     suppressLevel != SuppressLevel.SUPPRESS;
   217             if (unused != unusedFound[stmt.ordinal()]) {
   218                 throw new Error("invalid diagnostics for source:\n" +
   219                     source.getCharContent(true) +
   220                     "\nOptions: " + xlint.getXlintOption() +
   221                     "\nFound unused res1: " + unusedFound[0] +
   222                     "\nFound unused res2: " + unusedFound[1] +
   223                     "\nFound unused res3: " + unusedFound[2] +
   224                     "\nExpected unused res1: " + !usedResources[0] +
   225                     "\nExpected unused res2: " + !usedResources[1] +
   226                     "\nExpected unused res3: " + !usedResources[2]);
   227             }
   228         }
   229     }
   231     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   233         boolean unused_r1 = false;
   234         boolean unused_r2 = false;
   235         boolean unused_r3 = false;
   237         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   238             if (diagnostic.getKind() == Diagnostic.Kind.WARNING &&
   239                     diagnostic.getCode().contains("try.resource.not.referenced")) {
   240                 String varName = unwrap(diagnostic).getArgs()[0].toString();
   241                 if (varName.equals(TwrStmt.TWR1.resourceName)) {
   242                     unused_r1 = true;
   243                 } else if (varName.equals(TwrStmt.TWR2.resourceName)) {
   244                     unused_r2 = true;
   245                 } else if (varName.equals(TwrStmt.TWR3.resourceName)) {
   246                     unused_r3 = true;
   247                 }
   248             }
   249         }
   251         private JCDiagnostic unwrap(Diagnostic<? extends JavaFileObject> diagnostic) {
   252             if (diagnostic instanceof JCDiagnostic)
   253                 return (JCDiagnostic) diagnostic;
   254             if (diagnostic instanceof ClientCodeWrapper.DiagnosticSourceUnwrapper)
   255                 return ((ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic).d;
   256             throw new IllegalArgumentException();
   257         }
   258     }
   259 }

mercurial