23 |
23 |
24 /** |
24 /** |
25 * @test |
25 * @test |
26 * @bug 8003280 |
26 * @bug 8003280 |
27 * @summary Add lambda tests |
27 * @summary Add lambda tests |
28 * perform automated checks in type inference in lambda expressions in different contexts |
28 * perform automated checks in type inference in lambda expressions |
|
29 * in different contexts |
|
30 * @library ../../../lib |
|
31 * @build JavacTestingAbstractThreadedTest |
29 * @compile TypeInferenceComboTest.java |
32 * @compile TypeInferenceComboTest.java |
30 * @run main/timeout=360 TypeInferenceComboTest |
33 * @run main/timeout=360 TypeInferenceComboTest |
31 */ |
34 */ |
32 |
35 |
33 import com.sun.source.util.JavacTask; |
|
34 import java.net.URI; |
36 import java.net.URI; |
35 import java.util.Arrays; |
37 import java.util.Arrays; |
36 import javax.tools.Diagnostic; |
38 import javax.tools.Diagnostic; |
37 import javax.tools.JavaCompiler; |
|
38 import javax.tools.JavaFileObject; |
39 import javax.tools.JavaFileObject; |
39 import javax.tools.SimpleJavaFileObject; |
40 import javax.tools.SimpleJavaFileObject; |
40 import javax.tools.ToolProvider; |
41 import com.sun.source.util.JavacTask; |
41 import javax.tools.StandardJavaFileManager; |
42 |
42 |
43 public class TypeInferenceComboTest |
43 public class TypeInferenceComboTest { |
44 extends JavacTestingAbstractThreadedTest |
|
45 implements Runnable { |
44 enum Context { |
46 enum Context { |
45 ASSIGNMENT("SAM#Type s = #LBody;"), |
47 ASSIGNMENT("SAM#Type s = #LBody;"), |
46 METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" + |
48 METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" + |
47 "void method2() {\n" + |
49 "void method2() {\n" + |
48 " method1(#LBody);\n" + |
50 " method1(#LBody);\n" + |
57 |
59 |
58 Context(String context) { |
60 Context(String context) { |
59 this.context = context; |
61 this.context = context; |
60 } |
62 } |
61 |
63 |
62 String getContext(SamKind sk, TypeKind samTargetT, Keyword kw, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) { |
64 String getContext(SamKind sk, TypeKind samTargetT, Keyword kw, |
|
65 TypeKind parameterT, TypeKind returnT, LambdaKind lk, |
|
66 ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) { |
63 String result = context; |
67 String result = context; |
64 if (sk == SamKind.GENERIC) { |
68 if (sk == SamKind.GENERIC) { |
65 if(this == Context.METHOD_CALL) { |
69 if(this == Context.METHOD_CALL) { |
66 result = result.replaceAll("#GenericDeclKind", gdk.getGenericDeclKind(samTargetT)); |
70 result = result.replaceAll("#GenericDeclKind", |
|
71 gdk.getGenericDeclKind(samTargetT)); |
67 if(gdk == GenericDeclKind.NON_GENERIC) |
72 if(gdk == GenericDeclKind.NON_GENERIC) |
68 result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">"); |
73 result = result.replaceAll("#Type", "<" + |
|
74 samTargetT.typeStr + ">"); |
69 else //#GenericDeclKind is <T> or <T extends xxx> |
75 else //#GenericDeclKind is <T> or <T extends xxx> |
70 result = result.replaceAll("#Type", "<T>"); |
76 result = result.replaceAll("#Type", "<T>"); |
71 } |
77 } |
72 else { |
78 else { |
73 if(kw == Keyword.VOID) |
79 if(kw == Keyword.VOID) |
74 result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">"); |
80 result = result.replaceAll("#Type", "<" + |
|
81 samTargetT.typeStr + ">"); |
75 else |
82 else |
76 result = result.replaceAll("#Type", "<? " + kw.keyStr + " " + samTargetT.typeStr + ">"); |
83 result = result.replaceAll("#Type", "<? " + kw.keyStr + |
|
84 " " + samTargetT.typeStr + ">"); |
77 } |
85 } |
78 } |
86 } |
79 else |
87 else |
80 result = result.replaceAll("#Type", "").replaceAll("#GenericDeclKind", ""); |
88 result = result.replaceAll("#Type", ""). |
81 |
89 replaceAll("#GenericDeclKind", ""); |
82 return result.replaceAll("#LBody", lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk)); |
90 |
|
91 return result.replaceAll("#LBody", |
|
92 lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk)); |
83 } |
93 } |
84 } |
94 } |
85 |
95 |
86 enum SamKind { |
96 enum SamKind { |
87 GENERIC("interface SAM<T> { #R m(#ARG); }"), |
97 GENERIC("interface SAM<T> { #R m(#ARG); }"), |
92 SamKind(String sam_str) { |
102 SamKind(String sam_str) { |
93 this.sam_str = sam_str; |
103 this.sam_str = sam_str; |
94 } |
104 } |
95 |
105 |
96 String getSam(TypeKind parameterT, TypeKind returnT) { |
106 String getSam(TypeKind parameterT, TypeKind returnT) { |
97 return sam_str.replaceAll("#ARG", parameterT == TypeKind.VOID ? "" : parameterT.typeStr + " arg") |
107 return sam_str.replaceAll("#ARG", |
98 .replaceAll("#R", returnT.typeStr); |
108 parameterT == TypeKind.VOID ? |
|
109 "" : parameterT.typeStr + " arg") |
|
110 .replaceAll("#R", returnT.typeStr); |
99 } |
111 } |
100 } |
112 } |
101 |
113 |
102 enum TypeKind { |
114 enum TypeKind { |
103 VOID("void", ""), |
115 VOID("void", ""), |
104 STRING("String", "\"hello\""), |
116 STRING("String", "\"hello\""), |
105 INTEGER("Integer", "1"), |
117 INTEGER("Integer", "1"), |
106 INT("int", "0"), |
118 INT("int", "0"), |
107 COMPARATOR("java.util.Comparator<String>", "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"), |
119 COMPARATOR("java.util.Comparator<String>", |
|
120 "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"), |
108 SAM("SAM2", "null"), |
121 SAM("SAM2", "null"), |
109 GENERIC("T", null); |
122 GENERIC("T", null); |
110 |
123 |
111 String typeStr; |
124 String typeStr; |
112 String valStr; |
125 String valStr; |
150 this.keyStr = keyStr; |
163 this.keyStr = keyStr; |
151 } |
164 } |
152 } |
165 } |
153 |
166 |
154 enum LambdaBody { |
167 enum LambdaBody { |
155 RETURN_VOID("() -> #RET"),//no parameters, return type is one of the TypeKind |
168 //no parameters, return type is one of the TypeKind |
156 RETURN_ARG("(#PK arg) -> #RET");//has parameters, return type is one of the TypeKind |
169 RETURN_VOID("() -> #RET"), |
|
170 //has parameters, return type is one of the TypeKind |
|
171 RETURN_ARG("(#PK arg) -> #RET"); |
157 |
172 |
158 String bodyStr; |
173 String bodyStr; |
159 |
174 |
160 LambdaBody(String bodyStr) { |
175 LambdaBody(String bodyStr) { |
161 this.bodyStr = bodyStr; |
176 this.bodyStr = bodyStr; |
162 } |
177 } |
163 |
178 |
164 String getLambdaBody(TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk) { |
179 String getLambdaBody(TypeKind samTargetT, TypeKind parameterT, |
|
180 TypeKind returnT, LambdaKind lk, ParameterKind pk) { |
165 String result = bodyStr.replaceAll("#PK", pk.paramTemplate); |
181 String result = bodyStr.replaceAll("#PK", pk.paramTemplate); |
166 |
182 |
167 if(result.contains("#TYPE")) { |
183 if(result.contains("#TYPE")) { |
168 if (parameterT == TypeKind.GENERIC && this != RETURN_VOID) |
184 if (parameterT == TypeKind.GENERIC && this != RETURN_VOID) |
169 result = result.replaceAll("#TYPE", samTargetT == null? "": samTargetT.typeStr); |
185 result = result.replaceAll("#TYPE", |
|
186 samTargetT == null? "": samTargetT.typeStr); |
170 else |
187 else |
171 result = result.replaceAll("#TYPE", parameterT.typeStr); |
188 result = result.replaceAll("#TYPE", parameterT.typeStr); |
172 } |
189 } |
173 if (this == RETURN_ARG && parameterT == returnT) |
190 if (this == RETURN_ARG && parameterT == returnT) |
174 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg")); |
191 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg")); |
175 else { |
192 else { |
176 if(returnT != TypeKind.GENERIC) |
193 if(returnT != TypeKind.GENERIC) |
177 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", (returnT==TypeKind.VOID && lk==LambdaKind.EXPRESSION)? "{}" : returnT.valStr)); |
194 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", |
|
195 (returnT==TypeKind.VOID && |
|
196 lk==LambdaKind.EXPRESSION) ? "{}" : returnT.valStr)); |
178 else |
197 else |
179 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", samTargetT.valStr)); |
198 return result.replaceAll("#RET", |
|
199 lk.stmt.replaceAll("#VAL", samTargetT.valStr)); |
180 } |
200 } |
181 } |
201 } |
182 } |
202 } |
183 |
203 |
184 enum GenericDeclKind { |
204 enum GenericDeclKind { |
214 "interface SAM2 {\n" + |
236 "interface SAM2 {\n" + |
215 " SAM m();\n" + |
237 " SAM m();\n" + |
216 "}\n"; |
238 "}\n"; |
217 SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) { |
239 SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) { |
218 public String toString() { |
240 public String toString() { |
219 return template.replaceAll("#C", samKind.getSam(parameterType, returnType)); |
241 return template.replaceAll("#C", |
|
242 samKind.getSam(parameterType, returnType)); |
220 } |
243 } |
221 }; |
244 }; |
222 |
245 |
223 SourceFile clientSourceFile = new SourceFile("Client.java", |
246 SourceFile clientSourceFile = new SourceFile("Client.java", |
224 "class Client { \n" + |
247 "class Client { \n" + |
225 " #Context\n" + |
248 " #Context\n" + |
226 "}") { |
249 "}") { |
227 public String toString() { |
250 public String toString() { |
228 return template.replaceAll("#Context", context.getContext(samKind, samTargetType, keyword, parameterType, returnType, lambdaKind, parameterKind, genericDeclKind, lambdaBodyType)); |
251 return template.replaceAll("#Context", |
|
252 context.getContext(samKind, samTargetType, keyword, |
|
253 parameterType, returnType, lambdaKind, parameterKind, |
|
254 genericDeclKind, lambdaBodyType)); |
229 } |
255 } |
230 }; |
256 }; |
231 |
257 |
232 void test() throws Exception { |
258 public void run() { |
233 System.out.println("kk:"); |
259 outWriter.println("kk:"); |
234 StringBuilder sb = new StringBuilder("SamKind:"); |
260 StringBuilder sb = new StringBuilder("SamKind:"); |
235 sb.append(samKind).append(" SamTargetType:").append(samTargetType).append(" ParameterType:").append(parameterType) |
261 sb.append(samKind).append(" SamTargetType:") |
236 .append(" ReturnType:").append(returnType).append(" Context:").append(context).append(" LambdaKind:").append(lambdaKind) |
262 .append(samTargetType).append(" ParameterType:").append(parameterType) |
237 .append(" LambdaBodyType:").append(lambdaBodyType).append(" ParameterKind:").append(parameterKind).append(" Keyword:").append(keyword); |
263 .append(" ReturnType:").append(returnType).append(" Context:") |
238 System.out.println(sb); |
264 .append(context).append(" LambdaKind:").append(lambdaKind) |
|
265 .append(" LambdaBodyType:").append(lambdaBodyType) |
|
266 .append(" ParameterKind:").append(parameterKind).append(" Keyword:") |
|
267 .append(keyword); |
|
268 outWriter.println(sb); |
239 DiagnosticChecker dc = new DiagnosticChecker(); |
269 DiagnosticChecker dc = new DiagnosticChecker(); |
240 JavacTask ct = (JavacTask)comp.getTask(null, fm, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile)); |
270 JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc, |
241 ct.analyze(); |
271 null, null, Arrays.asList(samSourceFile, clientSourceFile)); |
|
272 try { |
|
273 ct.analyze(); |
|
274 } catch (Throwable t) { |
|
275 processException(t); |
|
276 } |
242 if (dc.errorFound == checkTypeInference()) { |
277 if (dc.errorFound == checkTypeInference()) { |
243 throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile + "\n" + parameterType + " " + returnType); |
278 throw new AssertionError(samSourceFile + "\n\n" + |
|
279 clientSourceFile + "\n" + parameterType + " " + returnType); |
244 } |
280 } |
245 } |
281 } |
246 |
282 |
247 abstract class SourceFile extends SimpleJavaFileObject { |
283 abstract class SourceFile extends SimpleJavaFileObject { |
248 |
284 |
281 LambdaKind lambdaKind; |
318 LambdaKind lambdaKind; |
282 ParameterKind parameterKind; |
319 ParameterKind parameterKind; |
283 Keyword keyword; |
320 Keyword keyword; |
284 GenericDeclKind genericDeclKind; |
321 GenericDeclKind genericDeclKind; |
285 |
322 |
286 static JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); |
323 TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT, |
287 static StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); |
324 TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk, |
288 |
325 ParameterKind pk, Keyword kw, GenericDeclKind gdk) { |
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; |
326 samKind = sk; |
291 samTargetType = samTargetT; |
327 samTargetType = samTargetT; |
292 parameterType = parameterT; |
328 parameterType = parameterT; |
293 returnType = returnT; |
329 returnType = returnT; |
294 context = c; |
330 context = c; |
306 for(LambdaBody lb : LambdaBody.values()) { |
342 for(LambdaBody lb : LambdaBody.values()) { |
307 for (ParameterKind parameterK : ParameterKind.values()) { |
343 for (ParameterKind parameterK : ParameterKind.values()) { |
308 for(LambdaKind lambdaK : LambdaKind.values()) { |
344 for(LambdaKind lambdaK : LambdaKind.values()) { |
309 for (SamKind sk : SamKind.values()) { |
345 for (SamKind sk : SamKind.values()) { |
310 if (sk == SamKind.NON_GENERIC) { |
346 if (sk == SamKind.NON_GENERIC) { |
311 if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) |
347 generateNonGenericSAM(ct, returnT, |
312 new TypeInferenceComboTest(sk, null, parameterT, returnT, lb, ct, lambdaK, parameterK, null, null).test(); |
348 parameterT, lb, parameterK, |
|
349 lambdaK, sk); |
313 } |
350 } |
314 else if (sk == SamKind.GENERIC) { |
351 else if (sk == SamKind.GENERIC) { |
315 for (Keyword kw : Keyword.values()) { |
352 generateGenericSAM(ct, returnT, |
316 for (TypeKind samTargetT : TypeKind.values()) { |
353 parameterT, lb, parameterK, |
317 if(samTargetT != TypeKind.VOID && samTargetT != TypeKind.INT && samTargetT != TypeKind.GENERIC |
354 lambdaK, sk); |
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 } |
355 } |
330 } |
356 } |
331 } |
357 } |
332 } |
358 } |
333 } |
359 } |
334 } |
360 } |
335 } |
361 } |
336 } |
362 } |
337 } |
363 |
|
364 checkAfterExec(false); |
|
365 } |
|
366 |
|
367 static void generateNonGenericSAM(Context ct, TypeKind returnT, |
|
368 TypeKind parameterT, LambdaBody lb, ParameterKind parameterK, |
|
369 LambdaKind lambdaK, SamKind sk) { |
|
370 if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) { |
|
371 pool.execute(new TypeInferenceComboTest(sk, null, parameterT, |
|
372 returnT, lb, ct, lambdaK, parameterK, null, null)); |
|
373 } |
|
374 } |
|
375 |
|
376 static void generateGenericSAM(Context ct, TypeKind returnT, |
|
377 TypeKind parameterT, LambdaBody lb, ParameterKind parameterK, |
|
378 LambdaKind lambdaK, SamKind sk) { |
|
379 for (Keyword kw : Keyword.values()) { |
|
380 for (TypeKind samTargetT : TypeKind.values()) { |
|
381 if(samTargetT != TypeKind.VOID && |
|
382 samTargetT != TypeKind.INT && |
|
383 samTargetT != TypeKind.GENERIC && |
|
384 (parameterT == TypeKind.GENERIC || |
|
385 returnT == TypeKind.GENERIC)) { |
|
386 if(ct != Context.METHOD_CALL) { |
|
387 pool.execute( |
|
388 new TypeInferenceComboTest(sk, samTargetT, parameterT, |
|
389 returnT, lb, ct, lambdaK, parameterK, kw, null)); |
|
390 } else {//Context.METHOD_CALL |
|
391 for (GenericDeclKind gdk : |
|
392 GenericDeclKind.values()) |
|
393 pool.execute( |
|
394 new TypeInferenceComboTest(sk, samTargetT, |
|
395 parameterT, returnT, lb, ct, lambdaK, |
|
396 parameterK, kw, gdk)); |
|
397 } |
|
398 } |
|
399 } |
|
400 } |
|
401 } |
|
402 |
338 } |
403 } |