blob: 587174137e0c3f385d1e7484a75e41fb90052b60 [file] [log] [blame]
/*
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 6945418 6993978 8006694 7196160 8129962
* @summary Project Coin: Simplified Varargs Method Invocation
* temporarily workaround combo tests are causing time out in several platforms
* @library /tools/javac/lib
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.code
* jdk.compiler/com.sun.tools.javac.comp
* jdk.compiler/com.sun.tools.javac.main
* jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
* @build combo.ComboTestHelper
* @run main Warn4
*/
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileObject;
import combo.ComboInstance;
import combo.ComboParameter;
import combo.ComboTask.Result;
import combo.ComboTestHelper;
public class Warn4 extends ComboInstance<Warn4> {
final static Warning[] error = null;
final static Warning[] none = new Warning[] {};
final static Warning[] vararg = new Warning[] { Warning.VARARGS };
final static Warning[] unchecked = new Warning[] { Warning.UNCHECKED };
final static Warning[] both = new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
enum Warning {
UNCHECKED("generic.array.creation"),
VARARGS("varargs.non.reifiable.type");
String key;
Warning(String key) {
this.key = key;
}
boolean isSuppressed(TrustMe trustMe, SourceLevel source,
SuppressLevel suppressLevelClient,
SuppressLevel suppressLevelDecl,
ModifierKind modKind) {
switch(this) {
case VARARGS:
return source.compareTo(SourceLevel.JDK_7) < 0 ||
suppressLevelDecl == SuppressLevel.UNCHECKED ||
trustMe == TrustMe.TRUST;
case UNCHECKED:
return suppressLevelClient == SuppressLevel.UNCHECKED ||
(trustMe == TrustMe.TRUST &&
(((modKind == ModifierKind.FINAL || modKind == ModifierKind.STATIC) &&
source.compareTo( SourceLevel.JDK_7) >= 0 ) ||
(modKind == ModifierKind.PRIVATE && source.compareTo( SourceLevel.JDK_9) >= 0 )));
}
SuppressLevel supLev = this == VARARGS ?
suppressLevelDecl :
suppressLevelClient;
return supLev == SuppressLevel.UNCHECKED ||
(trustMe == TrustMe.TRUST && modKind != ModifierKind.NONE);
}
}
enum SourceLevel {
JDK_6("6"),
JDK_7("7"),
JDK_9("9");
String sourceKey;
SourceLevel(String sourceKey) {
this.sourceKey = sourceKey;
}
}
enum TrustMe implements ComboParameter {
DONT_TRUST(""),
TRUST("@java.lang.SafeVarargs");
String anno;
TrustMe(String anno) {
this.anno = anno;
}
@Override
public String expand(String optParameter) {
return anno;
}
}
enum ModifierKind implements ComboParameter {
NONE(" "),
FINAL("final "),
STATIC("static "),
PRIVATE("private ");
String mod;
ModifierKind(String mod) {
this.mod = mod;
}
@Override
public String expand(String optParameter) {
return mod;
}
}
enum SuppressLevel implements ComboParameter {
NONE(""),
UNCHECKED("unchecked");
String lint;
SuppressLevel(String lint) {
this.lint = lint;
}
@Override
public String expand(String optParameter) {
return "@SuppressWarnings(\"" + lint + "\")";
}
}
enum Signature implements ComboParameter {
UNBOUND("void #NAME(List<?>#ARITY arg) { #BODY }",
new Warning[][] {none, none, none, none, error}),
INVARIANT_TVAR("<Z> void #NAME(List<Z>#ARITY arg) { #BODY }",
new Warning[][] {both, both, error, both, error}),
TVAR("<Z> void #NAME(Z#ARITY arg) { #BODY }",
new Warning[][] {both, both, both, both, vararg}),
INVARIANT("void #NAME(List<String>#ARITY arg) { #BODY }",
new Warning[][] {error, error, error, both, error}),
UNPARAMETERIZED("void #NAME(String#ARITY arg) { #BODY }",
new Warning[][] {error, error, error, error, none});
String template;
Warning[][] warnings;
Signature(String template, Warning[][] warnings) {
this.template = template;
this.warnings = warnings;
}
boolean isApplicableTo(Signature other) {
return warnings[other.ordinal()] != null;
}
boolean giveUnchecked(Signature other) {
return warnings[other.ordinal()] == unchecked ||
warnings[other.ordinal()] == both;
}
boolean giveVarargs(Signature other) {
return warnings[other.ordinal()] == vararg ||
warnings[other.ordinal()] == both;
}
@Override
public String expand(String optParameter) {
if (optParameter.equals("CLIENT")) {
return template.replaceAll("#ARITY", "")
.replaceAll("#NAME", "test")
.replaceAll("#BODY", "m(arg)");
} else {
return template.replaceAll("#ARITY", "...")
.replaceAll("#NAME", "m")
.replaceAll("#BODY", "");
}
}
}
public static void main(String... args) {
new ComboTestHelper<Warn4>()
.withFilter(Warn4::badTestFilter)
.withDimension("SOURCE", (x, level) -> x.sourceLevel = level, SourceLevel.values())
.withDimension("TRUSTME", (x, trustme) -> x.trustMe = trustme, TrustMe.values())
.withArrayDimension("SUPPRESS", (x, suppress, idx) -> x.suppress[idx] = suppress, 2, SuppressLevel.values())
.withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values())
.withArrayDimension("MTH", (x, sig, idx) -> x.sigs[idx] = sig, 2, Signature.values())
.run(Warn4::new);
}
SourceLevel sourceLevel;
TrustMe trustMe;
SuppressLevel[] suppress = new SuppressLevel[2];
ModifierKind modKind;
Signature[] sigs = new Signature[2];
boolean badTestFilter() {
return sigs[0].isApplicableTo(sigs[1]);
}
final String template = "import java.util.List;\n" +
"class Test {\n" +
" #{TRUSTME} #{SUPPRESS[0]} #{MOD} #{MTH[0].VARARG}\n" +
" #{SUPPRESS[1]} #{MTH[1].CLIENT}\n" +
"}";
@Override
public void doWork() throws IOException {
newCompilationTask()
.withOption("-Xlint:unchecked")
.withOption("-source")
.withOption(sourceLevel.sourceKey)
.withSourceFromTemplate(template)
.analyze(this::check);
}
void check(Result<?> res) {
boolean[] warnArr = new boolean[] {sigs[0].giveUnchecked(sigs[1]),
sigs[0].giveVarargs(sigs[1])};
Set<Warning> warnings = new HashSet<>();
for (Diagnostic<? extends JavaFileObject> d : res.diagnosticsForKind(Kind.MANDATORY_WARNING)) {
if (d.getCode().contains(Warning.VARARGS.key)) {
warnings.add(Warning.VARARGS);
} else if(d.getCode().contains(Warning.UNCHECKED.key)) {
warnings.add(Warning.UNCHECKED);
}
}
boolean badOutput = false;
for (Warning wkind : Warning.values()) {
boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel,
suppress[1], suppress[0], modKind);
badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) !=
warnings.contains(wkind);
}
if (badOutput) {
fail("invalid diagnostics for source:\n" +
res.compilationInfo() +
"\nExpected unchecked warning: " + warnArr[0] +
"\nExpected unsafe vararg warning: " + warnArr[1] +
"\nWarnings: " + warnings +
"\nSource level: " + sourceLevel);
}
}
}