test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java

changeset 1415
01c9d4161882
child 1482
954541f13717
equal deleted inserted replaced
1414:843d3b191773 1415:01c9d4161882
1 /*
2 * Copyright (c) 2011, 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 8003280
27 * @summary Add lambda tests
28 * perform automated checks in type inference in lambda expressions in different contexts
29 * @compile TypeInferenceComboTest.java
30 * @run main/timeout=360 TypeInferenceComboTest
31 */
32
33 import com.sun.source.util.JavacTask;
34 import java.net.URI;
35 import java.util.Arrays;
36 import javax.tools.Diagnostic;
37 import javax.tools.JavaCompiler;
38 import javax.tools.JavaFileObject;
39 import javax.tools.SimpleJavaFileObject;
40 import javax.tools.ToolProvider;
41 import javax.tools.StandardJavaFileManager;
42
43 public class TypeInferenceComboTest {
44 enum Context {
45 ASSIGNMENT("SAM#Type s = #LBody;"),
46 METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" +
47 "void method2() {\n" +
48 " method1(#LBody);\n" +
49 "}"),
50 RETURN_OF_METHOD("SAM#Type method1() {\n" +
51 " return #LBody;\n" +
52 "}"),
53 LAMBDA_RETURN_EXPRESSION("SAM2 s2 = () -> {return (SAM#Type)#LBody;};\n"),
54 ARRAY_INITIALIZER("Object[] oarray = {\"a\", 1, (SAM#Type)#LBody};");
55
56 String context;
57
58 Context(String context) {
59 this.context = context;
60 }
61
62 String getContext(SamKind sk, TypeKind samTargetT, Keyword kw, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) {
63 String result = context;
64 if (sk == SamKind.GENERIC) {
65 if(this == Context.METHOD_CALL) {
66 result = result.replaceAll("#GenericDeclKind", gdk.getGenericDeclKind(samTargetT));
67 if(gdk == GenericDeclKind.NON_GENERIC)
68 result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">");
69 else //#GenericDeclKind is <T> or <T extends xxx>
70 result = result.replaceAll("#Type", "<T>");
71 }
72 else {
73 if(kw == Keyword.VOID)
74 result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">");
75 else
76 result = result.replaceAll("#Type", "<? " + kw.keyStr + " " + samTargetT.typeStr + ">");
77 }
78 }
79 else
80 result = result.replaceAll("#Type", "").replaceAll("#GenericDeclKind", "");
81
82 return result.replaceAll("#LBody", lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk));
83 }
84 }
85
86 enum SamKind {
87 GENERIC("interface SAM<T> { #R m(#ARG); }"),
88 NON_GENERIC("interface SAM { #R m(#ARG); }");
89
90 String sam_str;
91
92 SamKind(String sam_str) {
93 this.sam_str = sam_str;
94 }
95
96 String getSam(TypeKind parameterT, TypeKind returnT) {
97 return sam_str.replaceAll("#ARG", parameterT == TypeKind.VOID ? "" : parameterT.typeStr + " arg")
98 .replaceAll("#R", returnT.typeStr);
99 }
100 }
101
102 enum TypeKind {
103 VOID("void", ""),
104 STRING("String", "\"hello\""),
105 INTEGER("Integer", "1"),
106 INT("int", "0"),
107 COMPARATOR("java.util.Comparator<String>", "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"),
108 SAM("SAM2", "null"),
109 GENERIC("T", null);
110
111 String typeStr;
112 String valStr;
113
114 TypeKind(String typeStr, String valStr) {
115 this.typeStr = typeStr;
116 this.valStr = valStr;
117 }
118 }
119
120 enum LambdaKind {
121 EXPRESSION("#VAL"),
122 STATEMENT("{return #VAL;}");
123
124 String stmt;
125
126 LambdaKind(String stmt) {
127 this.stmt = stmt;
128 }
129 }
130
131 enum ParameterKind {
132 EXPLICIT("#TYPE"),
133 IMPLICIT("");
134
135 String paramTemplate;
136
137 ParameterKind(String paramTemplate) {
138 this.paramTemplate = paramTemplate;
139 }
140 }
141
142 enum Keyword {
143 SUPER("super"),
144 EXTENDS("extends"),
145 VOID("");
146
147 String keyStr;
148
149 Keyword(String keyStr) {
150 this.keyStr = keyStr;
151 }
152 }
153
154 enum LambdaBody {
155 RETURN_VOID("() -> #RET"),//no parameters, return type is one of the TypeKind
156 RETURN_ARG("(#PK arg) -> #RET");//has parameters, return type is one of the TypeKind
157
158 String bodyStr;
159
160 LambdaBody(String bodyStr) {
161 this.bodyStr = bodyStr;
162 }
163
164 String getLambdaBody(TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk) {
165 String result = bodyStr.replaceAll("#PK", pk.paramTemplate);
166
167 if(result.contains("#TYPE")) {
168 if (parameterT == TypeKind.GENERIC && this != RETURN_VOID)
169 result = result.replaceAll("#TYPE", samTargetT == null? "": samTargetT.typeStr);
170 else
171 result = result.replaceAll("#TYPE", parameterT.typeStr);
172 }
173 if (this == RETURN_ARG && parameterT == returnT)
174 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg"));
175 else {
176 if(returnT != TypeKind.GENERIC)
177 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", (returnT==TypeKind.VOID && lk==LambdaKind.EXPRESSION)? "{}" : returnT.valStr));
178 else
179 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", samTargetT.valStr));
180 }
181 }
182 }
183
184 enum GenericDeclKind {
185 NON_GENERIC(""),
186 GENERIC_NOBOUND("<T>"),
187 GENERIC_BOUND("<T extends #ExtendedType>");
188 String typeStr;
189
190 GenericDeclKind(String typeStr) {
191 this.typeStr = typeStr;
192 }
193
194 String getGenericDeclKind(TypeKind et) {
195 return typeStr.replaceAll("#ExtendedType", et==null? "":et.typeStr);
196 }
197 }
198
199 boolean checkTypeInference() {
200 if (parameterType == TypeKind.VOID) {
201 if (lambdaBodyType != LambdaBody.RETURN_VOID)
202 return false;
203 }
204 else if (lambdaBodyType != LambdaBody.RETURN_ARG)
205 return false;
206 if ( genericDeclKind == GenericDeclKind.GENERIC_NOBOUND || genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
207 if ( parameterType == TypeKind.GENERIC && parameterKind == ParameterKind.IMPLICIT) //cyclic inference
208 return false;
209 }
210 return true;
211 }
212
213 String templateStr = "#C\n" +
214 "interface SAM2 {\n" +
215 " SAM m();\n" +
216 "}\n";
217 SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) {
218 public String toString() {
219 return template.replaceAll("#C", samKind.getSam(parameterType, returnType));
220 }
221 };
222
223 SourceFile clientSourceFile = new SourceFile("Client.java",
224 "class Client { \n" +
225 " #Context\n" +
226 "}") {
227 public String toString() {
228 return template.replaceAll("#Context", context.getContext(samKind, samTargetType, keyword, parameterType, returnType, lambdaKind, parameterKind, genericDeclKind, lambdaBodyType));
229 }
230 };
231
232 void test() throws Exception {
233 System.out.println("kk:");
234 StringBuilder sb = new StringBuilder("SamKind:");
235 sb.append(samKind).append(" SamTargetType:").append(samTargetType).append(" ParameterType:").append(parameterType)
236 .append(" ReturnType:").append(returnType).append(" Context:").append(context).append(" LambdaKind:").append(lambdaKind)
237 .append(" LambdaBodyType:").append(lambdaBodyType).append(" ParameterKind:").append(parameterKind).append(" Keyword:").append(keyword);
238 System.out.println(sb);
239 DiagnosticChecker dc = new DiagnosticChecker();
240 JavacTask ct = (JavacTask)comp.getTask(null, fm, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile));
241 ct.analyze();
242 if (dc.errorFound == checkTypeInference()) {
243 throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile + "\n" + parameterType + " " + returnType);
244 }
245 }
246
247 abstract class SourceFile extends SimpleJavaFileObject {
248
249 protected String template;
250
251 public SourceFile(String filename, String template) {
252 super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
253 this.template = template;
254 }
255
256 @Override
257 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
258 return toString();
259 }
260
261 public abstract String toString();
262 }
263
264 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
265
266 boolean errorFound = false;
267
268 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
269 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
270 errorFound = true;
271 }
272 }
273 }
274
275 SamKind samKind;
276 TypeKind samTargetType;
277 TypeKind parameterType;
278 TypeKind returnType;
279 Context context;
280 LambdaBody lambdaBodyType;
281 LambdaKind lambdaKind;
282 ParameterKind parameterKind;
283 Keyword keyword;
284 GenericDeclKind genericDeclKind;
285
286 static JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
287 static StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
288
289 TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk, ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
290 samKind = sk;
291 samTargetType = samTargetT;
292 parameterType = parameterT;
293 returnType = returnT;
294 context = c;
295 lambdaKind = lk;
296 parameterKind = pk;
297 keyword = kw;
298 lambdaBodyType = lb;
299 genericDeclKind = gdk;
300 }
301
302 public static void main(String[] args) throws Exception {
303 for(Context ct : Context.values()) {
304 for (TypeKind returnT : TypeKind.values()) {
305 for (TypeKind parameterT : TypeKind.values()) {
306 for(LambdaBody lb : LambdaBody.values()) {
307 for (ParameterKind parameterK : ParameterKind.values()) {
308 for(LambdaKind lambdaK : LambdaKind.values()) {
309 for (SamKind sk : SamKind.values()) {
310 if (sk == SamKind.NON_GENERIC) {
311 if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC )
312 new TypeInferenceComboTest(sk, null, parameterT, returnT, lb, ct, lambdaK, parameterK, null, null).test();
313 }
314 else if (sk == SamKind.GENERIC) {
315 for (Keyword kw : Keyword.values()) {
316 for (TypeKind samTargetT : TypeKind.values()) {
317 if(samTargetT != TypeKind.VOID && samTargetT != TypeKind.INT && samTargetT != TypeKind.GENERIC
318 && (parameterT == TypeKind.GENERIC || returnT == TypeKind.GENERIC)) {
319 if(ct != Context.METHOD_CALL) {
320 new TypeInferenceComboTest(sk, samTargetT, parameterT, returnT, lb, ct, lambdaK, parameterK, kw, null).test();
321 }
322 else {//Context.METHOD_CALL
323 for (GenericDeclKind gdk : GenericDeclKind.values())
324 new TypeInferenceComboTest(sk, samTargetT, parameterT, returnT, lb, ct, lambdaK, parameterK, kw, gdk).test();
325 }
326 }
327 }
328 }
329 }
330 }
331 }
332 }
333 }
334 }
335 }
336 }
337 }
338 }

mercurial