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