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 6945418 6993978 8006694 7196160 8129962 27 * @summary Project Coin: Simplified Varargs Method Invocation 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 Warn4 38 */ 39 40 import java.io.IOException; 41 import java.util.Set; 42 import java.util.HashSet; 43 import javax.tools.Diagnostic; 44 import javax.tools.Diagnostic.Kind; 45 import javax.tools.JavaFileObject; 46 47 import combo.ComboInstance; 48 import combo.ComboParameter; 49 import combo.ComboTask.Result; 50 import combo.ComboTestHelper; 51 52 public class Warn4 extends ComboInstance<Warn4> { 53 54 final static Warning[] error = null; 55 final static Warning[] none = new Warning[] {}; 56 final static Warning[] vararg = new Warning[] { Warning.VARARGS }; 57 final static Warning[] unchecked = new Warning[] { Warning.UNCHECKED }; 58 final static Warning[] both = new Warning[] { Warning.VARARGS, Warning.UNCHECKED }; 59 60 enum Warning { 61 UNCHECKED("generic.array.creation"), 62 VARARGS("varargs.non.reifiable.type"); 63 64 String key; 65 66 Warning(String key) { 67 this.key = key; 68 } 69 70 boolean isSuppressed(TrustMe trustMe, SourceLevel source, 71 SuppressLevel suppressLevelClient, 72 SuppressLevel suppressLevelDecl, 73 ModifierKind modKind) { 74 switch(this) { 75 case VARARGS: 76 return source.compareTo(SourceLevel.JDK_7) < 0 || 77 suppressLevelDecl == SuppressLevel.UNCHECKED || 78 trustMe == TrustMe.TRUST; 79 case UNCHECKED: 80 return suppressLevelClient == SuppressLevel.UNCHECKED || 81 (trustMe == TrustMe.TRUST && 82 (((modKind == ModifierKind.FINAL || modKind == ModifierKind.STATIC) && 83 source.compareTo( SourceLevel.JDK_7) >= 0 ) || 84 (modKind == ModifierKind.PRIVATE && source.compareTo( SourceLevel.JDK_9) >= 0 ))); 85 } 86 87 SuppressLevel supLev = this == VARARGS ? 88 suppressLevelDecl : 89 suppressLevelClient; 90 return supLev == SuppressLevel.UNCHECKED || 91 (trustMe == TrustMe.TRUST && modKind != ModifierKind.NONE); 92 } 93 } 94 95 enum SourceLevel { 96 JDK_7("7"), 97 JDK_9("9"); 98 99 String sourceKey; 100 101 SourceLevel(String sourceKey) { 102 this.sourceKey = sourceKey; 103 } 104 } 105 106 enum TrustMe implements ComboParameter { 107 DONT_TRUST(""), 108 TRUST("@java.lang.SafeVarargs"); 109 110 String anno; 111 112 TrustMe(String anno) { 113 this.anno = anno; 114 } 115 116 @Override 117 public String expand(String optParameter) { 118 return anno; 119 } 120 } 121 122 enum ModifierKind implements ComboParameter { 123 NONE(" "), 124 FINAL("final "), 125 STATIC("static "), 126 PRIVATE("private "); 127 128 String mod; 129 130 ModifierKind(String mod) { 131 this.mod = mod; 132 } 133 134 @Override 135 public String expand(String optParameter) { 136 return mod; 137 } 138 } 139 140 enum SuppressLevel implements ComboParameter { 141 NONE(""), 142 UNCHECKED("unchecked"); 143 144 String lint; 145 146 SuppressLevel(String lint) { 147 this.lint = lint; 148 } 149 150 @Override 151 public String expand(String optParameter) { 152 return "@SuppressWarnings(\"" + lint + "\")"; 153 } 154 } 155 156 enum Signature implements ComboParameter { 157 UNBOUND("void #NAME(List<?>#ARITY arg) { #BODY }", 158 new Warning[][] {none, none, none, none, error}), 159 INVARIANT_TVAR("<Z> void #NAME(List<Z>#ARITY arg) { #BODY }", 160 new Warning[][] {both, both, error, both, error}), 161 TVAR("<Z> void #NAME(Z#ARITY arg) { #BODY }", 162 new Warning[][] {both, both, both, both, vararg}), 163 INVARIANT("void #NAME(List<String>#ARITY arg) { #BODY }", 164 new Warning[][] {error, error, error, both, error}), 165 UNPARAMETERIZED("void #NAME(String#ARITY arg) { #BODY }", 166 new Warning[][] {error, error, error, error, none}); 167 168 String template; 169 Warning[][] warnings; 170 171 Signature(String template, Warning[][] warnings) { 172 this.template = template; 173 this.warnings = warnings; 174 } 175 176 boolean isApplicableTo(Signature other) { 177 return warnings[other.ordinal()] != null; 178 } 179 180 boolean giveUnchecked(Signature other) { 181 return warnings[other.ordinal()] == unchecked || 182 warnings[other.ordinal()] == both; 183 } 184 185 boolean giveVarargs(Signature other) { 186 return warnings[other.ordinal()] == vararg || 187 warnings[other.ordinal()] == both; 188 } 189 190 @Override 191 public String expand(String optParameter) { 192 if (optParameter.equals("CLIENT")) { 193 return template.replaceAll("#ARITY", "") 194 .replaceAll("#NAME", "test") 195 .replaceAll("#BODY", "m(arg)"); 196 } else { 197 return template.replaceAll("#ARITY", "...") 198 .replaceAll("#NAME", "m") 199 .replaceAll("#BODY", ""); 200 } 201 } 202 } 203 204 public static void main(String... args) { 205 new ComboTestHelper<Warn4>() 206 .withFilter(Warn4::badTestFilter) 207 .withDimension("SOURCE", (x, level) -> x.sourceLevel = level, SourceLevel.values()) 208 .withDimension("TRUSTME", (x, trustme) -> x.trustMe = trustme, TrustMe.values()) 209 .withArrayDimension("SUPPRESS", (x, suppress, idx) -> x.suppress[idx] = suppress, 2, SuppressLevel.values()) 210 .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values()) 211 .withArrayDimension("MTH", (x, sig, idx) -> x.sigs[idx] = sig, 2, Signature.values()) 212 .run(Warn4::new); 213 } 214 215 SourceLevel sourceLevel; 216 TrustMe trustMe; 217 SuppressLevel[] suppress = new SuppressLevel[2]; 218 ModifierKind modKind; 219 Signature[] sigs = new Signature[2]; 220 221 boolean badTestFilter() { 222 return sigs[0].isApplicableTo(sigs[1]); 223 } 224 225 final String template = "import java.util.List;\n" + 226 "class Test {\n" + 227 " #{TRUSTME} #{SUPPRESS[0]} #{MOD} #{MTH[0].VARARG}\n" + 228 " #{SUPPRESS[1]} #{MTH[1].CLIENT}\n" + 229 "}"; 230 231 @Override 232 public void doWork() throws IOException { 233 newCompilationTask() 234 .withOption("-Xlint:unchecked") 235 .withOption("-source") 236 .withOption(sourceLevel.sourceKey) 237 .withSourceFromTemplate(template) 238 .analyze(this::check); 239 } 240 241 void check(Result<?> res) { 242 boolean[] warnArr = new boolean[] {sigs[0].giveUnchecked(sigs[1]), 243 sigs[0].giveVarargs(sigs[1])}; 244 245 Set<Warning> warnings = new HashSet<>(); 246 for (Diagnostic<? extends JavaFileObject> d : res.diagnosticsForKind(Kind.MANDATORY_WARNING)) { 247 if (d.getCode().contains(Warning.VARARGS.key)) { 248 warnings.add(Warning.VARARGS); 249 } else if(d.getCode().contains(Warning.UNCHECKED.key)) { 250 warnings.add(Warning.UNCHECKED); 251 } 252 } 253 254 boolean badOutput = false; 255 for (Warning wkind : Warning.values()) { 256 boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel, 257 suppress[1], suppress[0], modKind); 258 badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) != 259 warnings.contains(wkind); 260 } 261 if (badOutput) { 262 fail("invalid diagnostics for source:\n" + 263 res.compilationInfo() + 264 "\nExpected unchecked warning: " + warnArr[0] + 265 "\nExpected unsafe vararg warning: " + warnArr[1] + 266 "\nWarnings: " + warnings + 267 "\nSource level: " + sourceLevel); 268 } 269 } 270 }