1/* 2 * Copyright (c) 2010, 2015, 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 */ 23 24/** 25 * @test 26 * @bug 6993978 7097436 8006694 7196160 27 * @summary Project Coin: Annotation to reduce varargs warnings 28 * temporarily workaround combo tests are causing time out in several platforms 29 * @library /tools/javac/lib 30 * @modules jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.code 32 * jdk.compiler/com.sun.tools.javac.comp 33 * jdk.compiler/com.sun.tools.javac.main 34 * jdk.compiler/com.sun.tools.javac.tree 35 * jdk.compiler/com.sun.tools.javac.util 36 * @build combo.ComboTestHelper 37 * @run main/othervm Warn5 38 */ 39 40import java.io.IOException; 41import java.util.EnumSet; 42import javax.tools.Diagnostic; 43import javax.tools.Diagnostic.Kind; 44import javax.tools.JavaFileObject; 45 46import combo.ComboInstance; 47import combo.ComboParameter; 48import combo.ComboTask.Result; 49import combo.ComboTestHelper; 50 51 52public class Warn5 extends ComboInstance<Warn5> { 53 54 enum XlintOption { 55 NONE("none"), 56 ALL("all"); 57 58 String opt; 59 60 XlintOption(String opt) { 61 this.opt = opt; 62 } 63 64 String getXlintOption() { 65 return "-Xlint:" + opt; 66 } 67 } 68 69 enum TrustMe implements ComboParameter { 70 DONT_TRUST(""), 71 TRUST("@java.lang.SafeVarargs"); 72 73 String anno; 74 75 TrustMe(String anno) { 76 this.anno = anno; 77 } 78 79 @Override 80 public String expand(String optParameter) { 81 return anno; 82 } 83 } 84 85 enum SuppressLevel implements ComboParameter { 86 NONE, 87 VARARGS; 88 89 @Override 90 public String expand(String optParameter) { 91 return this == VARARGS ? 92 "@SuppressWarnings(\"varargs\")" : 93 ""; 94 } 95 } 96 97 enum ModifierKind implements ComboParameter { 98 NONE(""), 99 FINAL("final"), 100 STATIC("static"), 101 PRIVATE("private"); 102 103 String mod; 104 105 ModifierKind(String mod) { 106 this.mod = mod; 107 } 108 109 @Override 110 public String expand(String optParameter) { 111 return mod; 112 } 113 } 114 115 enum MethodKind implements ComboParameter { 116 METHOD("void m"), 117 CONSTRUCTOR("Test"); 118 119 String name; 120 121 MethodKind(String name) { 122 this.name = name; 123 } 124 125 @Override 126 public String expand(String optParameter) { 127 return name; 128 } 129 } 130 131 enum SourceLevel { 132 JDK_6("6"), 133 JDK_7("7"), 134 JDK_9("9"); 135 136 String sourceKey; 137 138 SourceLevel(String sourceKey) { 139 this.sourceKey = sourceKey; 140 } 141 } 142 143 enum SignatureKind implements ComboParameter { 144 VARARGS_X("<X>#{NAME}(X... x)", false, true), 145 VARARGS_STRING("#{NAME}(String... x)", true, true), 146 ARRAY_X("<X>#{NAME}(X[] x)", false, false), 147 ARRAY_STRING("#{NAME}(String[] x)", true, false); 148 149 String stub; 150 boolean isReifiableArg; 151 boolean isVarargs; 152 153 SignatureKind(String stub, boolean isReifiableArg, boolean isVarargs) { 154 this.stub = stub; 155 this.isReifiableArg = isReifiableArg; 156 this.isVarargs = isVarargs; 157 } 158 159 @Override 160 public String expand(String optParameter) { 161 return stub; 162 } 163 } 164 165 enum BodyKind implements ComboParameter { 166 ASSIGN("Object o = x;", true), 167 CAST("Object o = (Object)x;", true), 168 METH("test(x);", true), 169 PRINT("System.out.println(x.toString());", false), 170 ARRAY_ASSIGN("Object[] o = x;", true), 171 ARRAY_CAST("Object[] o = (Object[])x;", true), 172 ARRAY_METH("testArr(x);", true); 173 174 String body; 175 boolean hasAliasing; 176 177 BodyKind(String body, boolean hasAliasing) { 178 this.body = body; 179 this.hasAliasing = hasAliasing; 180 } 181 182 @Override 183 public String expand(String optParameter) { 184 return body; 185 } 186 } 187 188 enum WarningKind { 189 UNSAFE_BODY("compiler.warn.varargs.unsafe.use.varargs.param"), 190 UNSAFE_DECL("compiler.warn.unchecked.varargs.non.reifiable.type"), 191 MALFORMED_SAFEVARARGS("compiler.err.varargs.invalid.trustme.anno"), 192 REDUNDANT_SAFEVARARGS("compiler.warn.varargs.redundant.trustme.anno"); 193 194 String code; 195 196 WarningKind(String code) { 197 this.code = code; 198 } 199 } 200 201 public static void main(String[] args) { 202 new ComboTestHelper<Warn5>() 203 .withFilter(Warn5::badTestFilter) 204 .withDimension("SOURCE", (x, level) -> x.sourceLevel = level, SourceLevel.values()) 205 .withDimension("LINT", (x, lint) -> x.xlint = lint, XlintOption.values()) 206 .withDimension("TRUSTME", (x, trustme) -> x.trustMe = trustme, TrustMe.values()) 207 .withDimension("SUPPRESS", (x, suppress) -> x.suppressLevel = suppress, SuppressLevel.values()) 208 .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values()) 209 .withDimension("NAME", (x, name) -> x.methKind = name, MethodKind.values()) 210 .withDimension("SIG", (x, sig) -> x.sig = sig, SignatureKind.values()) 211 .withDimension("BODY", (x, body) -> x.body = body, BodyKind.values()) 212 .run(Warn5::new); 213 } 214 215 SourceLevel sourceLevel; 216 XlintOption xlint; 217 TrustMe trustMe; 218 SuppressLevel suppressLevel; 219 ModifierKind modKind; 220 MethodKind methKind; 221 SignatureKind sig; 222 BodyKind body; 223 224 boolean badTestFilter() { 225 return (methKind != MethodKind.CONSTRUCTOR || modKind == ModifierKind.NONE); 226 } 227 228 String template = "import com.sun.tools.javac.api.*;\n" + 229 "import java.util.List;\n" + 230 "class Test {\n" + 231 " static void test(Object o) {}\n" + 232 " static void testArr(Object[] o) {}\n" + 233 " #{TRUSTME} #{SUPPRESS} #{MOD} #{SIG} { #{BODY} }\n" + 234 "}\n"; 235 236 @Override 237 public void doWork() throws IOException { 238 check(newCompilationTask() 239 .withOption(xlint.getXlintOption()) 240 .withOption("-source") 241 .withOption(sourceLevel.sourceKey) 242 .withSourceFromTemplate(template) 243 .analyze()); 244 } 245 246 void check(Result<?> res) { 247 248 EnumSet<WarningKind> foundWarnings = EnumSet.noneOf(WarningKind.class); 249 for (Diagnostic.Kind kind : new Kind[] { Kind.ERROR, Kind.MANDATORY_WARNING, Kind.WARNING}) { 250 for (Diagnostic<? extends JavaFileObject> diag : res.diagnosticsForKind(kind)) { 251 for (WarningKind wk : WarningKind.values()) { 252 if (wk.code.equals(diag.getCode())) { 253 foundWarnings.add(wk); 254 } 255 } 256 } 257 } 258 259 EnumSet<WarningKind> expectedWarnings = 260 EnumSet.noneOf(WarningKind.class); 261 262 if (sourceLevel.compareTo(SourceLevel.JDK_7) >= 0 && 263 trustMe == TrustMe.TRUST && 264 suppressLevel != SuppressLevel.VARARGS && 265 xlint != XlintOption.NONE && 266 sig.isVarargs && 267 !sig.isReifiableArg && 268 body.hasAliasing && 269 (methKind == MethodKind.CONSTRUCTOR || 270 (methKind == MethodKind.METHOD && 271 modKind == ModifierKind.FINAL || modKind == ModifierKind.STATIC || 272 (modKind == ModifierKind.PRIVATE && sourceLevel.compareTo(SourceLevel.JDK_9) >= 0)))) { 273 expectedWarnings.add(WarningKind.UNSAFE_BODY); 274 } 275 276 if (sourceLevel.compareTo(SourceLevel.JDK_7) >= 0 && 277 trustMe == TrustMe.DONT_TRUST && 278 sig.isVarargs && 279 !sig.isReifiableArg && 280 xlint == XlintOption.ALL) { 281 expectedWarnings.add(WarningKind.UNSAFE_DECL); 282 } 283 284 if (sourceLevel.compareTo(SourceLevel.JDK_7) >= 0 && 285 trustMe == TrustMe.TRUST && 286 (!sig.isVarargs || 287 ((modKind == ModifierKind.NONE || 288 modKind == ModifierKind.PRIVATE && sourceLevel.compareTo(SourceLevel.JDK_9) < 0 ) && 289 methKind == MethodKind.METHOD))) { 290 expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS); 291 } 292 293 if (sourceLevel.compareTo(SourceLevel.JDK_7) >= 0 && 294 trustMe == TrustMe.TRUST && 295 xlint != XlintOption.NONE && 296 suppressLevel != SuppressLevel.VARARGS && 297 (modKind == ModifierKind.FINAL || modKind == ModifierKind.STATIC || 298 (modKind == ModifierKind.PRIVATE && sourceLevel.compareTo(SourceLevel.JDK_9) >= 0) || 299 methKind == MethodKind.CONSTRUCTOR) && 300 sig.isVarargs && 301 sig.isReifiableArg) { 302 expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS); 303 } 304 305 if (!expectedWarnings.containsAll(foundWarnings) || 306 !foundWarnings.containsAll(expectedWarnings)) { 307 fail("invalid diagnostics for source:\n" + 308 res.compilationInfo() + 309 "\nOptions: " + xlint.getXlintOption() + 310 "\nSource Level: " + sourceLevel + 311 "\nExpected warnings: " + expectedWarnings + 312 "\nFound warnings: " + foundWarnings); 313 } 314 } 315} 316