test/tools/javac/TryWithResources/UnusedResourcesTest.java

Thu, 03 Mar 2011 09:43:24 +0000

author
mcimadamore
date
Thu, 03 Mar 2011 09:43:24 +0000
changeset 905
e9b8fbb30f5a
child 1073
f85d980faaf8
permissions
-rw-r--r--

7023233: False positive for -Xlint:try with nested try with resources blocks
Summary: Wrong lint warning issued about unused resource when nested try-with-resource blocks are found
Reviewed-by: jjg

mcimadamore@905 1 /*
mcimadamore@905 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
mcimadamore@905 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@905 4 *
mcimadamore@905 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@905 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@905 7 * published by the Free Software Foundation.
mcimadamore@905 8 *
mcimadamore@905 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@905 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@905 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@905 12 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@905 13 * accompanied this code).
mcimadamore@905 14 *
mcimadamore@905 15 * You should have received a copy of the GNU General Public License version
mcimadamore@905 16 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@905 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@905 18 *
mcimadamore@905 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@905 20 * or visit www.oracle.com if you need additional information or have any
mcimadamore@905 21 * questions.
mcimadamore@905 22 */
mcimadamore@905 23
mcimadamore@905 24 /*
mcimadamore@905 25 * @test
mcimadamore@905 26 * @bug 7023233
mcimadamore@905 27 * @summary False positive for -Xlint:try with nested try with resources blocks
mcimadamore@905 28 */
mcimadamore@905 29
mcimadamore@905 30 import com.sun.source.util.JavacTask;
mcimadamore@905 31 import com.sun.tools.javac.api.JavacTool;
mcimadamore@905 32 import com.sun.tools.javac.util.JCDiagnostic;
mcimadamore@905 33 import java.net.URI;
mcimadamore@905 34 import java.util.Arrays;
mcimadamore@905 35 import javax.tools.Diagnostic;
mcimadamore@905 36 import javax.tools.JavaCompiler;
mcimadamore@905 37 import javax.tools.JavaFileObject;
mcimadamore@905 38 import javax.tools.SimpleJavaFileObject;
mcimadamore@905 39 import javax.tools.StandardJavaFileManager;
mcimadamore@905 40 import javax.tools.ToolProvider;
mcimadamore@905 41
mcimadamore@905 42 public class UnusedResourcesTest {
mcimadamore@905 43
mcimadamore@905 44 enum XlintOption {
mcimadamore@905 45 NONE("none"),
mcimadamore@905 46 TRY("try");
mcimadamore@905 47
mcimadamore@905 48 String opt;
mcimadamore@905 49
mcimadamore@905 50 XlintOption(String opt) {
mcimadamore@905 51 this.opt = opt;
mcimadamore@905 52 }
mcimadamore@905 53
mcimadamore@905 54 String getXlintOption() {
mcimadamore@905 55 return "-Xlint:" + opt;
mcimadamore@905 56 }
mcimadamore@905 57 }
mcimadamore@905 58
mcimadamore@905 59 enum TwrStmt {
mcimadamore@905 60 TWR1("res1"),
mcimadamore@905 61 TWR2("res2"),
mcimadamore@905 62 TWR3("res3");
mcimadamore@905 63
mcimadamore@905 64 final String resourceName;
mcimadamore@905 65
mcimadamore@905 66 private TwrStmt(String resourceName) {
mcimadamore@905 67 this.resourceName = resourceName;
mcimadamore@905 68 }
mcimadamore@905 69 }
mcimadamore@905 70
mcimadamore@905 71 enum SuppressLevel {
mcimadamore@905 72 NONE,
mcimadamore@905 73 SUPPRESS;
mcimadamore@905 74
mcimadamore@905 75 String getSuppressAnno() {
mcimadamore@905 76 return this == SUPPRESS ?
mcimadamore@905 77 "@SuppressWarnings(\"try\")" :
mcimadamore@905 78 "";
mcimadamore@905 79 }
mcimadamore@905 80 }
mcimadamore@905 81
mcimadamore@905 82 enum ResourceUsage {
mcimadamore@905 83 NONE(null),
mcimadamore@905 84 USE_R1(TwrStmt.TWR1),
mcimadamore@905 85 USE_R2(TwrStmt.TWR2),
mcimadamore@905 86 USE_R3(TwrStmt.TWR3);
mcimadamore@905 87
mcimadamore@905 88 TwrStmt stmt;
mcimadamore@905 89
mcimadamore@905 90 private ResourceUsage(TwrStmt stmt) {
mcimadamore@905 91 this.stmt = stmt;
mcimadamore@905 92 }
mcimadamore@905 93
mcimadamore@905 94 String usedResourceName() {
mcimadamore@905 95 return stmt != null ? stmt.resourceName : null;
mcimadamore@905 96 }
mcimadamore@905 97
mcimadamore@905 98 boolean isUsedIn(TwrStmt res, TwrStmt stmt) {
mcimadamore@905 99 return this.stmt == res &&
mcimadamore@905 100 stmt.ordinal() >= this.stmt.ordinal();
mcimadamore@905 101 }
mcimadamore@905 102
mcimadamore@905 103 String getUsage(TwrStmt stmt) {
mcimadamore@905 104 return this != NONE && stmt.ordinal() >= this.stmt.ordinal() ?
mcimadamore@905 105 "use(" + usedResourceName() + ");" :
mcimadamore@905 106 "";
mcimadamore@905 107 }
mcimadamore@905 108 }
mcimadamore@905 109
mcimadamore@905 110 static class JavaSource extends SimpleJavaFileObject {
mcimadamore@905 111
mcimadamore@905 112 String template = "class Resource implements AutoCloseable {\n" +
mcimadamore@905 113 "public void close() {}\n" +
mcimadamore@905 114 "}\n" +
mcimadamore@905 115 "class Test {\n" +
mcimadamore@905 116 "void use(Resource r) {}\n" +
mcimadamore@905 117 "#S void test() {\n" +
mcimadamore@905 118 "try (Resource #R1 = new Resource()) {\n" +
mcimadamore@905 119 "#U1_R1\n" +
mcimadamore@905 120 "#U1_R2\n" +
mcimadamore@905 121 "#U1_R3\n" +
mcimadamore@905 122 "try (Resource #R2 = new Resource()) {\n" +
mcimadamore@905 123 "#U2_R1\n" +
mcimadamore@905 124 "#U2_R2\n" +
mcimadamore@905 125 "#U2_R3\n" +
mcimadamore@905 126 "try (Resource #R3 = new Resource()) {\n" +
mcimadamore@905 127 "#U3_R1\n" +
mcimadamore@905 128 "#U3_R2\n" +
mcimadamore@905 129 "#U3_R3\n" +
mcimadamore@905 130 "}\n" +
mcimadamore@905 131 "}\n" +
mcimadamore@905 132 "}\n" +
mcimadamore@905 133 "}\n" +
mcimadamore@905 134 "}\n";
mcimadamore@905 135
mcimadamore@905 136 String source;
mcimadamore@905 137
mcimadamore@905 138 public JavaSource(SuppressLevel suppressLevel, ResourceUsage usage1,
mcimadamore@905 139 ResourceUsage usage2, ResourceUsage usage3) {
mcimadamore@905 140 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
mcimadamore@905 141 source = template.replace("#S", suppressLevel.getSuppressAnno()).
mcimadamore@905 142 replace("#R1", TwrStmt.TWR1.resourceName).
mcimadamore@905 143 replace("#R2", TwrStmt.TWR2.resourceName).
mcimadamore@905 144 replace("#R3", TwrStmt.TWR3.resourceName).
mcimadamore@905 145 replace("#U1_R1", usage1.getUsage(TwrStmt.TWR1)).
mcimadamore@905 146 replace("#U1_R2", usage2.getUsage(TwrStmt.TWR1)).
mcimadamore@905 147 replace("#U1_R3", usage3.getUsage(TwrStmt.TWR1)).
mcimadamore@905 148 replace("#U2_R1", usage1.getUsage(TwrStmt.TWR2)).
mcimadamore@905 149 replace("#U2_R2", usage2.getUsage(TwrStmt.TWR2)).
mcimadamore@905 150 replace("#U2_R3", usage3.getUsage(TwrStmt.TWR2)).
mcimadamore@905 151 replace("#U3_R1", usage1.getUsage(TwrStmt.TWR3)).
mcimadamore@905 152 replace("#U3_R2", usage2.getUsage(TwrStmt.TWR3)).
mcimadamore@905 153 replace("#U3_R3", usage3.getUsage(TwrStmt.TWR3));
mcimadamore@905 154 }
mcimadamore@905 155
mcimadamore@905 156 @Override
mcimadamore@905 157 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@905 158 return source;
mcimadamore@905 159 }
mcimadamore@905 160 }
mcimadamore@905 161
mcimadamore@905 162 public static void main(String... args) throws Exception {
mcimadamore@905 163 for (XlintOption xlint : XlintOption.values()) {
mcimadamore@905 164 for (SuppressLevel suppressLevel : SuppressLevel.values()) {
mcimadamore@905 165 for (ResourceUsage usage1 : ResourceUsage.values()) {
mcimadamore@905 166 for (ResourceUsage usage2 : ResourceUsage.values()) {
mcimadamore@905 167 for (ResourceUsage usage3 : ResourceUsage.values()) {
mcimadamore@905 168 test(xlint,
mcimadamore@905 169 suppressLevel,
mcimadamore@905 170 usage1,
mcimadamore@905 171 usage2,
mcimadamore@905 172 usage3);
mcimadamore@905 173 }
mcimadamore@905 174 }
mcimadamore@905 175 }
mcimadamore@905 176 }
mcimadamore@905 177 }
mcimadamore@905 178 }
mcimadamore@905 179
mcimadamore@905 180 // Create a single file manager and reuse it for each compile to save time.
mcimadamore@905 181 static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
mcimadamore@905 182
mcimadamore@905 183 static void test(XlintOption xlint, SuppressLevel suppressLevel, ResourceUsage usage1,
mcimadamore@905 184 ResourceUsage usage2, ResourceUsage usage3) throws Exception {
mcimadamore@905 185 final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
mcimadamore@905 186 JavaSource source = new JavaSource(suppressLevel, usage1, usage2, usage3);
mcimadamore@905 187 DiagnosticChecker dc = new DiagnosticChecker();
mcimadamore@905 188 JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
mcimadamore@905 189 Arrays.asList(xlint.getXlintOption()), null, Arrays.asList(source));
mcimadamore@905 190 ct.analyze();
mcimadamore@905 191 check(source, xlint, suppressLevel, usage1, usage2, usage3, dc);
mcimadamore@905 192 }
mcimadamore@905 193
mcimadamore@905 194 static void check(JavaSource source, XlintOption xlint, SuppressLevel suppressLevel,
mcimadamore@905 195 ResourceUsage usage1, ResourceUsage usage2, ResourceUsage usage3, DiagnosticChecker dc) {
mcimadamore@905 196
mcimadamore@905 197 ResourceUsage[] usages = { usage1, usage2, usage3 };
mcimadamore@905 198 boolean[] unusedFound = { dc.unused_r1, dc.unused_r2, dc.unused_r3 };
mcimadamore@905 199 boolean[] usedResources = { false, false, false };
mcimadamore@905 200
mcimadamore@905 201 for (TwrStmt res : TwrStmt.values()) {
mcimadamore@905 202 outer: for (TwrStmt stmt : TwrStmt.values()) {
mcimadamore@905 203 for (ResourceUsage usage : usages) {
mcimadamore@905 204 if (usage.isUsedIn(res, stmt)) {
mcimadamore@905 205 usedResources[res.ordinal()] = true;
mcimadamore@905 206 break outer;
mcimadamore@905 207 }
mcimadamore@905 208 }
mcimadamore@905 209 }
mcimadamore@905 210 }
mcimadamore@905 211
mcimadamore@905 212 for (TwrStmt stmt : TwrStmt.values()) {
mcimadamore@905 213 boolean unused = !usedResources[stmt.ordinal()] &&
mcimadamore@905 214 xlint == XlintOption.TRY &&
mcimadamore@905 215 suppressLevel != SuppressLevel.SUPPRESS;
mcimadamore@905 216 if (unused != unusedFound[stmt.ordinal()]) {
mcimadamore@905 217 throw new Error("invalid diagnostics for source:\n" +
mcimadamore@905 218 source.getCharContent(true) +
mcimadamore@905 219 "\nOptions: " + xlint.getXlintOption() +
mcimadamore@905 220 "\nFound unused res1: " + unusedFound[0] +
mcimadamore@905 221 "\nFound unused res2: " + unusedFound[1] +
mcimadamore@905 222 "\nFound unused res3: " + unusedFound[2] +
mcimadamore@905 223 "\nExpected unused res1: " + !usedResources[0] +
mcimadamore@905 224 "\nExpected unused res2: " + !usedResources[1] +
mcimadamore@905 225 "\nExpected unused res3: " + !usedResources[2]);
mcimadamore@905 226 }
mcimadamore@905 227 }
mcimadamore@905 228 }
mcimadamore@905 229
mcimadamore@905 230 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@905 231
mcimadamore@905 232 boolean unused_r1 = false;
mcimadamore@905 233 boolean unused_r2 = false;
mcimadamore@905 234 boolean unused_r3 = false;
mcimadamore@905 235
mcimadamore@905 236 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@905 237 if (diagnostic.getKind() == Diagnostic.Kind.WARNING &&
mcimadamore@905 238 diagnostic.getCode().contains("try.resource.not.referenced")) {
mcimadamore@905 239 String varName = ((JCDiagnostic)diagnostic).getArgs()[0].toString();
mcimadamore@905 240 if (varName.equals(TwrStmt.TWR1.resourceName)) {
mcimadamore@905 241 unused_r1 = true;
mcimadamore@905 242 } else if (varName.equals(TwrStmt.TWR2.resourceName)) {
mcimadamore@905 243 unused_r2 = true;
mcimadamore@905 244 } else if (varName.equals(TwrStmt.TWR3.resourceName)) {
mcimadamore@905 245 unused_r3 = true;
mcimadamore@905 246 }
mcimadamore@905 247 }
mcimadamore@905 248 }
mcimadamore@905 249 }
mcimadamore@905 250 }

mercurial