test/tools/javac/TryWithResources/UnusedResourcesTest.java

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 1073
f85d980faaf8
parent 0
959103a6100f
permissions
-rw-r--r--

merge

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

mercurial