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