1 /* 2 * Copyright (c) 2011, 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 7046778 8006694 8129962 27 * @summary Project Coin: problem with diamond and member inner classes 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 * @compile -Xlint:all DiamondAndInnerClassTest.java 38 * @run main DiamondAndInnerClassTest 39 */ 40 41 import java.io.IOException; 42 import java.util.Arrays; 43 44 import combo.ComboTestHelper; 45 import combo.ComboInstance; 46 import combo.ComboParameter; 47 import combo.ComboTask.Result; 48 49 public class DiamondAndInnerClassTest extends ComboInstance<DiamondAndInnerClassTest> { 50 51 enum TypeArgumentKind implements ComboParameter { 52 NONE(""), 53 STRING("<String>"), 54 INTEGER("<Integer>"), 55 DIAMOND("<>"); 56 57 String typeargStr; 58 TypeArgumentKind(String typeargStr)59 TypeArgumentKind(String typeargStr) { 60 this.typeargStr = typeargStr; 61 } 62 compatible(TypeArgumentKind that)63 boolean compatible(TypeArgumentKind that) { 64 switch (this) { 65 case NONE: return true; 66 case STRING: return that != INTEGER; 67 case INTEGER: return that != STRING; 68 default: throw new AssertionError("Unexpected decl kind: " + this); 69 } 70 } 71 compatible(ArgumentKind that)72 boolean compatible(ArgumentKind that) { 73 switch (this) { 74 case NONE: return true; 75 case STRING: return that == ArgumentKind.STRING; 76 case INTEGER: return that == ArgumentKind.INTEGER; 77 default: throw new AssertionError("Unexpected decl kind: " + this); 78 } 79 } 80 81 @Override expand(String optParameter)82 public String expand(String optParameter) { 83 return typeargStr; 84 } 85 } 86 87 enum ArgumentKind implements ComboParameter { 88 OBJECT("(Object)null"), 89 STRING("(String)null"), 90 INTEGER("(Integer)null"); 91 92 String argStr; 93 ArgumentKind(String argStr)94 ArgumentKind(String argStr) { 95 this.argStr = argStr; 96 } 97 98 @Override expand(String optParameter)99 public String expand(String optParameter) { 100 return argStr; 101 } 102 } 103 104 enum TypeQualifierArity implements ComboParameter { 105 ONE(1, "A1#{TA#IDX[0]}"), 106 TWO(2, "A1#{TA#IDX[0]}.A2#{TA#IDX[1]}"), 107 THREE(3, "A1#{TA#IDX[0]}.A2#{TA#IDX[1]}.A3#{TA#IDX[2]}"); 108 109 int n; 110 String qualifierStr; 111 TypeQualifierArity(int n, String qualifierStr)112 TypeQualifierArity(int n, String qualifierStr) { 113 this.n = n; 114 this.qualifierStr = qualifierStr; 115 } 116 117 @Override expand(String optParameter)118 public String expand(String optParameter) { 119 return qualifierStr.replaceAll("#IDX", optParameter); 120 } 121 } 122 123 enum InnerClassDeclArity implements ComboParameter { 124 ONE(1, "class A1<X> { A1(X x1) { } #{BODY} }"), 125 TWO(2, "class A1<X1> { class A2<X2> { A2(X1 x1, X2 x2) { } #{BODY} } }"), 126 THREE(3, "class A1<X1> { class A2<X2> { class A3<X3> { A3(X1 x1, X2 x2, X3 x3) { } #{BODY} } } }"); 127 128 int n; 129 String classDeclStr; 130 InnerClassDeclArity(int n, String classDeclStr)131 InnerClassDeclArity(int n, String classDeclStr) { 132 this.n = n; 133 this.classDeclStr = classDeclStr; 134 } 135 136 @Override expand(String optParameter)137 public String expand(String optParameter) { 138 return classDeclStr; 139 } 140 } 141 142 enum ArgumentListArity implements ComboParameter { 143 ONE(1, "(#{A[0]})"), 144 TWO(2, "(#{A[0]},#{A[1]})"), 145 THREE(3, "(#{A[0]},#{A[1]},#{A[2]})"); 146 147 int n; 148 String argListStr; 149 ArgumentListArity(int n, String argListStr)150 ArgumentListArity(int n, String argListStr) { 151 this.n = n; 152 this.argListStr = argListStr; 153 } 154 155 @Override expand(String optParameter)156 public String expand(String optParameter) { 157 return argListStr.replaceAll("#IDX", optParameter); 158 } 159 } 160 main(String... args)161 public static void main(String... args) throws Exception { 162 new ComboTestHelper<DiamondAndInnerClassTest>() 163 .withFilter(DiamondAndInnerClassTest::rareTypesFilter) 164 .withFilter(DiamondAndInnerClassTest::noDiamondOnDecl) 165 .withFilter(DiamondAndInnerClassTest::noDiamondOnIntermediateTypes) 166 .withFilter(DiamondAndInnerClassTest::arityMismatch) 167 .withFilter(DiamondAndInnerClassTest::redundantFilter) 168 .withDimension("BODY", new ComboParameter.Constant<>("#{D.1} res = new #{S.2}#{AL};")) 169 .withDimension("DECL", (x, arity) -> x.innerClassDeclArity = arity, InnerClassDeclArity.values()) 170 .withDimension("D", (x, arity) -> x.declArity = arity, TypeQualifierArity.values()) 171 .withDimension("S", (x, arity) -> x.siteArity = arity, TypeQualifierArity.values()) 172 .withDimension("AL", (x, alist) -> x.argumentListArity = alist, ArgumentListArity.values()) 173 .withArrayDimension("TA1", (x, targs, idx) -> x.declTypeArgumentKinds[idx] = targs, 3, TypeArgumentKind.values()) 174 .withArrayDimension("TA2", (x, targs, idx) -> x.siteTypeArgumentKinds[idx] = targs, 3, TypeArgumentKind.values()) 175 .withArrayDimension("A", (x, argsk, idx) -> x.argumentKinds[idx] = argsk, 3, ArgumentKind.values()) 176 .run(DiamondAndInnerClassTest::new); 177 } 178 179 InnerClassDeclArity innerClassDeclArity; 180 TypeQualifierArity declArity; 181 TypeQualifierArity siteArity; 182 TypeArgumentKind[] declTypeArgumentKinds = new TypeArgumentKind[3]; 183 TypeArgumentKind[] siteTypeArgumentKinds = new TypeArgumentKind[3]; 184 ArgumentKind[] argumentKinds = new ArgumentKind[3]; 185 ArgumentListArity argumentListArity; 186 rareTypesFilter()187 boolean rareTypesFilter() { 188 for (TypeArgumentKind[] types : Arrays.asList(declTypeArgumentKinds, siteTypeArgumentKinds)) { 189 boolean isRaw = types[0] == TypeArgumentKind.NONE; 190 for (int i = 1; i < innerClassDeclArity.n; i++) { 191 if (isRaw != (types[i] == TypeArgumentKind.NONE)) { 192 return false; 193 } 194 } 195 } 196 return true; 197 } 198 noDiamondOnDecl()199 boolean noDiamondOnDecl() { 200 for (int i = 0; i < innerClassDeclArity.n; i++) { 201 if (declTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND) { 202 return false; 203 } 204 } 205 return true; 206 } 207 noDiamondOnIntermediateTypes()208 boolean noDiamondOnIntermediateTypes() { 209 for (int i = 0; i < (innerClassDeclArity.n - 1); i++) { 210 if (siteTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND) { 211 return false; 212 } 213 } 214 return true; 215 } 216 redundantFilter()217 boolean redundantFilter() { 218 for (TypeArgumentKind[] types : Arrays.asList(declTypeArgumentKinds, siteTypeArgumentKinds)) { 219 for (int i = innerClassDeclArity.n; i < types.length; i++) { 220 if (types[i].ordinal() != 0) { 221 return false; 222 } 223 } 224 } 225 for (int i = innerClassDeclArity.n; i < argumentKinds.length; i++) { 226 if (argumentKinds[i].ordinal() != 0) { 227 return false; 228 } 229 } 230 return true; 231 } 232 arityMismatch()233 boolean arityMismatch() { 234 return argumentListArity.n == innerClassDeclArity.n && 235 siteArity.n == innerClassDeclArity.n && 236 declArity.n == innerClassDeclArity.n; 237 } 238 239 @Override doWork()240 public void doWork() throws IOException { 241 newCompilationTask() 242 .withSourceFromTemplate("#{DECL}") 243 .analyze(this::check); 244 } 245 check(Result<?> res)246 void check(Result<?> res) { 247 boolean errorExpected = false; 248 249 TypeArgumentKind[] expectedArgKinds = 250 new TypeArgumentKind[innerClassDeclArity.n]; 251 252 for (int i = 0 ; i < innerClassDeclArity.n ; i++) { 253 if (!declTypeArgumentKinds[i].compatible(siteTypeArgumentKinds[i])) { 254 errorExpected = true; 255 break; 256 } 257 expectedArgKinds[i] = siteTypeArgumentKinds[i] == 258 TypeArgumentKind.DIAMOND ? 259 declTypeArgumentKinds[i] : siteTypeArgumentKinds[i]; 260 } 261 262 if (!errorExpected) { 263 for (int i = 0 ; i < innerClassDeclArity.n ; i++) { 264 if (!expectedArgKinds[i].compatible(argumentKinds[i])) { 265 errorExpected = true; 266 break; 267 } 268 } 269 } 270 271 if (errorExpected != res.hasErrors()) { 272 fail("invalid diagnostics for source:\n" + 273 res.compilationInfo() + 274 "\nFound error: " + res.hasErrors() + 275 "\nExpected error: " + errorExpected); 276 } 277 } 278 } 279