1.1 --- a/test/tools/javac/varargs/warning/Warn5.java Thu Oct 06 18:39:31 2011 +0100 1.2 +++ b/test/tools/javac/varargs/warning/Warn5.java Mon Oct 17 12:54:33 2011 +0100 1.3 @@ -23,7 +23,7 @@ 1.4 1.5 /** 1.6 * @test 1.7 - * @bug 6993978 1.8 + * @bug 6993978 7097436 1.9 * @summary Project Coin: Annotation to reduce varargs warnings 1.10 * @author mcimadamore 1.11 * @run main Warn5 1.12 @@ -31,8 +31,8 @@ 1.13 import com.sun.source.util.JavacTask; 1.14 import com.sun.tools.javac.api.JavacTool; 1.15 import java.net.URI; 1.16 -import java.util.ArrayList; 1.17 import java.util.Arrays; 1.18 +import java.util.EnumSet; 1.19 import javax.tools.Diagnostic; 1.20 import javax.tools.JavaCompiler; 1.21 import javax.tools.JavaFileObject; 1.22 @@ -95,7 +95,6 @@ 1.23 METHOD("void m"), 1.24 CONSTRUCTOR("Test"); 1.25 1.26 - 1.27 String name; 1.28 1.29 MethodKind(String name) { 1.30 @@ -155,7 +154,124 @@ 1.31 } 1.32 } 1.33 1.34 - static class JavaSource extends SimpleJavaFileObject { 1.35 + enum WarningKind { 1.36 + UNSAFE_BODY, 1.37 + UNSAFE_DECL, 1.38 + MALFORMED_SAFEVARARGS, 1.39 + REDUNDANT_SAFEVARARGS; 1.40 + } 1.41 + 1.42 + // Create a single file manager and reuse it for each compile to save time. 1.43 + static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); 1.44 + 1.45 + public static void main(String... args) throws Exception { 1.46 + for (SourceLevel sourceLevel : SourceLevel.values()) { 1.47 + for (XlintOption xlint : XlintOption.values()) { 1.48 + for (TrustMe trustMe : TrustMe.values()) { 1.49 + for (SuppressLevel suppressLevel : SuppressLevel.values()) { 1.50 + for (ModifierKind modKind : ModifierKind.values()) { 1.51 + for (MethodKind methKind : MethodKind.values()) { 1.52 + for (SignatureKind sig : SignatureKind.values()) { 1.53 + for (BodyKind body : BodyKind.values()) { 1.54 + new Warn5(sourceLevel, 1.55 + xlint, 1.56 + trustMe, 1.57 + suppressLevel, 1.58 + modKind, 1.59 + methKind, 1.60 + sig, 1.61 + body).test(); 1.62 + } 1.63 + } 1.64 + } 1.65 + } 1.66 + } 1.67 + } 1.68 + } 1.69 + } 1.70 + } 1.71 + 1.72 + final SourceLevel sourceLevel; 1.73 + final XlintOption xlint; 1.74 + final TrustMe trustMe; 1.75 + final SuppressLevel suppressLevel; 1.76 + final ModifierKind modKind; 1.77 + final MethodKind methKind; 1.78 + final SignatureKind sig; 1.79 + final BodyKind body; 1.80 + final JavaSource source; 1.81 + final DiagnosticChecker dc; 1.82 + 1.83 + public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) { 1.84 + this.sourceLevel = sourceLevel; 1.85 + this.xlint = xlint; 1.86 + this.trustMe = trustMe; 1.87 + this.suppressLevel = suppressLevel; 1.88 + this.modKind = modKind; 1.89 + this.methKind = methKind; 1.90 + this.sig = sig; 1.91 + this.body = body; 1.92 + this.source = new JavaSource(); 1.93 + this.dc = new DiagnosticChecker(); 1.94 + } 1.95 + 1.96 + void test() throws Exception { 1.97 + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 1.98 + JavacTask ct = (JavacTask)tool.getTask(null, fm, dc, 1.99 + Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source)); 1.100 + ct.analyze(); 1.101 + check(); 1.102 + } 1.103 + 1.104 + void check() { 1.105 + 1.106 + EnumSet<WarningKind> expectedWarnings = EnumSet.noneOf(WarningKind.class); 1.107 + 1.108 + if (sourceLevel == SourceLevel.JDK_7 && 1.109 + trustMe == TrustMe.TRUST && 1.110 + suppressLevel != SuppressLevel.VARARGS && 1.111 + xlint != XlintOption.NONE && 1.112 + sig.isVarargs && !sig.isReifiableArg && body.hasAliasing && 1.113 + (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE))) { 1.114 + expectedWarnings.add(WarningKind.UNSAFE_BODY); 1.115 + } 1.116 + 1.117 + if (sourceLevel == SourceLevel.JDK_7 && 1.118 + trustMe == TrustMe.DONT_TRUST && 1.119 + sig.isVarargs && 1.120 + !sig.isReifiableArg && 1.121 + xlint == XlintOption.ALL) { 1.122 + expectedWarnings.add(WarningKind.UNSAFE_DECL); 1.123 + } 1.124 + 1.125 + if (sourceLevel == SourceLevel.JDK_7 && 1.126 + trustMe == TrustMe.TRUST && 1.127 + (!sig.isVarargs || 1.128 + (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD))) { 1.129 + expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS); 1.130 + } 1.131 + 1.132 + if (sourceLevel == SourceLevel.JDK_7 && 1.133 + trustMe == TrustMe.TRUST && 1.134 + xlint != XlintOption.NONE && 1.135 + suppressLevel != SuppressLevel.VARARGS && 1.136 + (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) && 1.137 + sig.isVarargs && 1.138 + sig.isReifiableArg) { 1.139 + expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS); 1.140 + } 1.141 + 1.142 + if (!expectedWarnings.containsAll(dc.warnings) || 1.143 + !dc.warnings.containsAll(expectedWarnings)) { 1.144 + throw new Error("invalid diagnostics for source:\n" + 1.145 + source.getCharContent(true) + 1.146 + "\nOptions: " + xlint.getXlintOption() + 1.147 + "\nExpected warnings: " + expectedWarnings + 1.148 + "\nFound warnings: " + dc.warnings); 1.149 + } 1.150 + } 1.151 + 1.152 + class JavaSource extends SimpleJavaFileObject { 1.153 1.154 String template = "import com.sun.tools.javac.api.*;\n" + 1.155 "import java.util.List;\n" + 1.156 @@ -167,12 +283,11 @@ 1.157 1.158 String source; 1.159 1.160 - public JavaSource(TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, 1.161 - MethodKind methKind, SignatureKind meth, BodyKind body) { 1.162 + public JavaSource() { 1.163 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 1.164 source = template.replace("#T", trustMe.anno). 1.165 replace("#S", suppressLevel.getSuppressAnno()). 1.166 - replace("#M", meth.getSignature(modKind, methKind)). 1.167 + replace("#M", sig.getSignature(modKind, methKind)). 1.168 replace("#B", body.body); 1.169 } 1.170 1.171 @@ -182,117 +297,34 @@ 1.172 } 1.173 } 1.174 1.175 - public static void main(String... args) throws Exception { 1.176 - for (SourceLevel sourceLevel : SourceLevel.values()) { 1.177 - for (XlintOption xlint : XlintOption.values()) { 1.178 - for (TrustMe trustMe : TrustMe.values()) { 1.179 - for (SuppressLevel suppressLevel : SuppressLevel.values()) { 1.180 - for (ModifierKind modKind : ModifierKind.values()) { 1.181 - for (MethodKind methKind : MethodKind.values()) { 1.182 - for (SignatureKind sig : SignatureKind.values()) { 1.183 - for (BodyKind body : BodyKind.values()) { 1.184 - test(sourceLevel, 1.185 - xlint, 1.186 - trustMe, 1.187 - suppressLevel, 1.188 - modKind, 1.189 - methKind, 1.190 - sig, 1.191 - body); 1.192 - } 1.193 - } 1.194 - } 1.195 - } 1.196 - } 1.197 - } 1.198 - } 1.199 - } 1.200 - } 1.201 + class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { 1.202 1.203 - // Create a single file manager and reuse it for each compile to save time. 1.204 - static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); 1.205 - 1.206 - static void test(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, 1.207 - ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) throws Exception { 1.208 - final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 1.209 - JavaSource source = new JavaSource(trustMe, suppressLevel, modKind, methKind, sig, body); 1.210 - DiagnosticChecker dc = new DiagnosticChecker(); 1.211 - JavacTask ct = (JavacTask)tool.getTask(null, fm, dc, 1.212 - Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source)); 1.213 - ct.analyze(); 1.214 - check(sourceLevel, dc, source, xlint, trustMe, 1.215 - suppressLevel, modKind, methKind, sig, body); 1.216 - } 1.217 - 1.218 - static void check(SourceLevel sourceLevel, DiagnosticChecker dc, JavaSource source, 1.219 - XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, 1.220 - MethodKind methKind, SignatureKind meth, BodyKind body) { 1.221 - 1.222 - boolean hasPotentiallyUnsafeBody = sourceLevel == SourceLevel.JDK_7 && 1.223 - trustMe == TrustMe.TRUST && 1.224 - suppressLevel != SuppressLevel.VARARGS && 1.225 - xlint != XlintOption.NONE && 1.226 - meth.isVarargs && !meth.isReifiableArg && body.hasAliasing && 1.227 - (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE)); 1.228 - 1.229 - boolean hasPotentiallyPollutingDecl = sourceLevel == SourceLevel.JDK_7 && 1.230 - trustMe == TrustMe.DONT_TRUST && 1.231 - meth.isVarargs && 1.232 - !meth.isReifiableArg && 1.233 - xlint == XlintOption.ALL; 1.234 - 1.235 - boolean hasMalformedAnnoInDecl = sourceLevel == SourceLevel.JDK_7 && 1.236 - trustMe == TrustMe.TRUST && 1.237 - (!meth.isVarargs || 1.238 - (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD)); 1.239 - 1.240 - boolean hasRedundantAnnoInDecl = sourceLevel == SourceLevel.JDK_7 && 1.241 - trustMe == TrustMe.TRUST && 1.242 - xlint != XlintOption.NONE && 1.243 - suppressLevel != SuppressLevel.VARARGS && 1.244 - (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) && 1.245 - meth.isVarargs && 1.246 - meth.isReifiableArg; 1.247 - 1.248 - if (hasPotentiallyUnsafeBody != dc.hasPotentiallyUnsafeBody || 1.249 - hasPotentiallyPollutingDecl != dc.hasPotentiallyPollutingDecl || 1.250 - hasMalformedAnnoInDecl != dc.hasMalformedAnnoInDecl || 1.251 - hasRedundantAnnoInDecl != dc.hasRedundantAnnoInDecl) { 1.252 - throw new Error("invalid diagnostics for source:\n" + 1.253 - source.getCharContent(true) + 1.254 - "\nOptions: " + xlint.getXlintOption() + 1.255 - "\nExpected potentially unsafe body warning: " + hasPotentiallyUnsafeBody + 1.256 - "\nExpected potentially polluting decl warning: " + hasPotentiallyPollutingDecl + 1.257 - "\nExpected malformed anno error: " + hasMalformedAnnoInDecl + 1.258 - "\nExpected redundant anno warning: " + hasRedundantAnnoInDecl + 1.259 - "\nFound potentially unsafe body warning: " + dc.hasPotentiallyUnsafeBody + 1.260 - "\nFound potentially polluting decl warning: " + dc.hasPotentiallyPollutingDecl + 1.261 - "\nFound malformed anno error: " + dc.hasMalformedAnnoInDecl + 1.262 - "\nFound redundant anno warning: " + dc.hasRedundantAnnoInDecl); 1.263 - } 1.264 - } 1.265 - 1.266 - static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { 1.267 - 1.268 - boolean hasPotentiallyUnsafeBody = false; 1.269 - boolean hasPotentiallyPollutingDecl = false; 1.270 - boolean hasMalformedAnnoInDecl = false; 1.271 - boolean hasRedundantAnnoInDecl = false; 1.272 + EnumSet<WarningKind> warnings = EnumSet.noneOf(WarningKind.class); 1.273 1.274 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 1.275 if (diagnostic.getKind() == Diagnostic.Kind.WARNING) { 1.276 if (diagnostic.getCode().contains("unsafe.use.varargs.param")) { 1.277 - hasPotentiallyUnsafeBody = true; 1.278 + setWarning(WarningKind.UNSAFE_BODY); 1.279 } else if (diagnostic.getCode().contains("redundant.trustme")) { 1.280 - hasRedundantAnnoInDecl = true; 1.281 + setWarning(WarningKind.REDUNDANT_SAFEVARARGS); 1.282 } 1.283 } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING && 1.284 diagnostic.getCode().contains("varargs.non.reifiable.type")) { 1.285 - hasPotentiallyPollutingDecl = true; 1.286 + setWarning(WarningKind.UNSAFE_DECL); 1.287 } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR && 1.288 diagnostic.getCode().contains("invalid.trustme")) { 1.289 - hasMalformedAnnoInDecl = true; 1.290 + setWarning(WarningKind.MALFORMED_SAFEVARARGS); 1.291 } 1.292 } 1.293 + 1.294 + void setWarning(WarningKind wk) { 1.295 + if (!warnings.add(wk)) { 1.296 + throw new AssertionError("Duplicate warning of kind " + wk + " in source:\n" + source); 1.297 + } 1.298 + } 1.299 + 1.300 + boolean hasWarning(WarningKind wk) { 1.301 + return warnings.contains(wk); 1.302 + } 1.303 } 1.304 }