/* * Copyright (c) 2011, 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 7046778 8006694 8129962 * @summary Project Coin: problem with diamond and member inner classes * 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 * @compile -Xlint:all DiamondAndInnerClassTest.java * @run main DiamondAndInnerClassTest */ import java.io.IOException; import java.util.Arrays; import combo.ComboTestHelper; import combo.ComboInstance; import combo.ComboParameter; import combo.ComboTask.Result; public class DiamondAndInnerClassTest extends ComboInstance<DiamondAndInnerClassTest> { enum TypeArgumentKind implements ComboParameter { NONE(""), STRING("<String>"), INTEGER("<Integer>"), DIAMOND("<>"); String typeargStr; TypeArgumentKind(String typeargStr) { this.typeargStr = typeargStr; } boolean compatible(TypeArgumentKind that) { switch (this) { case NONE: return true; case STRING: return that != INTEGER; case INTEGER: return that != STRING; default: throw new AssertionError("Unexpected decl kind: " + this); } } boolean compatible(ArgumentKind that) { switch (this) { case NONE: return true; case STRING: return that == ArgumentKind.STRING; case INTEGER: return that == ArgumentKind.INTEGER; default: throw new AssertionError("Unexpected decl kind: " + this); } } @Override public String expand(String optParameter) { return typeargStr; } } enum ArgumentKind implements ComboParameter { OBJECT("(Object)null"), STRING("(String)null"), INTEGER("(Integer)null"); String argStr; ArgumentKind(String argStr) { this.argStr = argStr; } @Override public String expand(String optParameter) { return argStr; } } enum TypeQualifierArity implements ComboParameter { ONE(1, "A1#{TA#IDX[0]}"), TWO(2, "A1#{TA#IDX[0]}.A2#{TA#IDX[1]}"), THREE(3, "A1#{TA#IDX[0]}.A2#{TA#IDX[1]}.A3#{TA#IDX[2]}"); int n; String qualifierStr; TypeQualifierArity(int n, String qualifierStr) { this.n = n; this.qualifierStr = qualifierStr; } @Override public String expand(String optParameter) { return qualifierStr.replaceAll("#IDX", optParameter); } } enum InnerClassDeclArity implements ComboParameter { ONE(1, "class A1<X> { A1(X x1) { } #{BODY} }"), TWO(2, "class A1<X1> { class A2<X2> { A2(X1 x1, X2 x2) { } #{BODY} } }"), THREE(3, "class A1<X1> { class A2<X2> { class A3<X3> { A3(X1 x1, X2 x2, X3 x3) { } #{BODY} } } }"); int n; String classDeclStr; InnerClassDeclArity(int n, String classDeclStr) { this.n = n; this.classDeclStr = classDeclStr; } @Override public String expand(String optParameter) { return classDeclStr; } } enum ArgumentListArity implements ComboParameter { ONE(1, "(#{A[0]})"), TWO(2, "(#{A[0]},#{A[1]})"), THREE(3, "(#{A[0]},#{A[1]},#{A[2]})"); int n; String argListStr; ArgumentListArity(int n, String argListStr) { this.n = n; this.argListStr = argListStr; } @Override public String expand(String optParameter) { return argListStr.replaceAll("#IDX", optParameter); } } public static void main(String... args) throws Exception { new ComboTestHelper<DiamondAndInnerClassTest>() .withFilter(DiamondAndInnerClassTest::rareTypesFilter) .withFilter(DiamondAndInnerClassTest::noDiamondOnDecl) .withFilter(DiamondAndInnerClassTest::noDiamondOnIntermediateTypes) .withFilter(DiamondAndInnerClassTest::arityMismatch) .withFilter(DiamondAndInnerClassTest::redundantFilter) .withDimension("BODY", new ComboParameter.Constant<>("#{D.1} res = new #{S.2}#{AL};")) .withDimension("DECL", (x, arity) -> x.innerClassDeclArity = arity, InnerClassDeclArity.values()) .withDimension("D", (x, arity) -> x.declArity = arity, TypeQualifierArity.values()) .withDimension("S", (x, arity) -> x.siteArity = arity, TypeQualifierArity.values()) .withDimension("AL", (x, alist) -> x.argumentListArity = alist, ArgumentListArity.values()) .withArrayDimension("TA1", (x, targs, idx) -> x.declTypeArgumentKinds[idx] = targs, 3, TypeArgumentKind.values()) .withArrayDimension("TA2", (x, targs, idx) -> x.siteTypeArgumentKinds[idx] = targs, 3, TypeArgumentKind.values()) .withArrayDimension("A", (x, argsk, idx) -> x.argumentKinds[idx] = argsk, 3, ArgumentKind.values()) .run(DiamondAndInnerClassTest::new); } InnerClassDeclArity innerClassDeclArity; TypeQualifierArity declArity; TypeQualifierArity siteArity; TypeArgumentKind[] declTypeArgumentKinds = new TypeArgumentKind[3]; TypeArgumentKind[] siteTypeArgumentKinds = new TypeArgumentKind[3]; ArgumentKind[] argumentKinds = new ArgumentKind[3]; ArgumentListArity argumentListArity; boolean rareTypesFilter() { for (TypeArgumentKind[] types : Arrays.asList(declTypeArgumentKinds, siteTypeArgumentKinds)) { boolean isRaw = types[0] == TypeArgumentKind.NONE; for (int i = 1; i < innerClassDeclArity.n; i++) { if (isRaw != (types[i] == TypeArgumentKind.NONE)) { return false; } } } return true; } boolean noDiamondOnDecl() { for (int i = 0; i < innerClassDeclArity.n; i++) { if (declTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND) { return false; } } return true; } boolean noDiamondOnIntermediateTypes() { for (int i = 0; i < (innerClassDeclArity.n - 1); i++) { if (siteTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND) { return false; } } return true; } boolean redundantFilter() { for (TypeArgumentKind[] types : Arrays.asList(declTypeArgumentKinds, siteTypeArgumentKinds)) { for (int i = innerClassDeclArity.n; i < types.length; i++) { if (types[i].ordinal() != 0) { return false; } } } for (int i = innerClassDeclArity.n; i < argumentKinds.length; i++) { if (argumentKinds[i].ordinal() != 0) { return false; } } return true; } boolean arityMismatch() { return argumentListArity.n == innerClassDeclArity.n && siteArity.n == innerClassDeclArity.n && declArity.n == innerClassDeclArity.n; } @Override public void doWork() throws IOException { check(newCompilationTask() .withSourceFromTemplate("#{DECL}") .analyze()); } void check(Result<?> res) { boolean errorExpected = false; TypeArgumentKind[] expectedArgKinds = new TypeArgumentKind[innerClassDeclArity.n]; for (int i = 0 ; i < innerClassDeclArity.n ; i++) { if (!declTypeArgumentKinds[i].compatible(siteTypeArgumentKinds[i])) { errorExpected = true; break; } expectedArgKinds[i] = siteTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND ? declTypeArgumentKinds[i] : siteTypeArgumentKinds[i]; } if (!errorExpected) { for (int i = 0 ; i < innerClassDeclArity.n ; i++) { if (!expectedArgKinds[i].compatible(argumentKinds[i])) { errorExpected = true; break; } } } if (errorExpected != res.hasErrors()) { fail("invalid diagnostics for source:\n" + res.compilationInfo() + "\nFound error: " + res.hasErrors() + "\nExpected error: " + errorExpected); } } }