TypeInferenceComboTest.java revision 1519:5c956be64b9e
1264391Snwhitehorn/* 2264391Snwhitehorn * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3264391Snwhitehorn * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4264391Snwhitehorn * 5264391Snwhitehorn * This code is free software; you can redistribute it and/or modify it 6264404Snwhitehorn * under the terms of the GNU General Public License version 2 only, as 7264404Snwhitehorn * published by the Free Software Foundation. 8294060Ssmh * 9294060Ssmh * This code is distributed in the hope that it will be useful, but WITHOUT 10264391Snwhitehorn * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11264391Snwhitehorn * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12264391Snwhitehorn * version 2 for more details (a copy is included in the LICENSE file that 13264391Snwhitehorn * accompanied this code). 14264391Snwhitehorn * 15264391Snwhitehorn * You should have received a copy of the GNU General Public License version 16264391Snwhitehorn * 2 along with this work; if not, write to the Free Software Foundation, 17264391Snwhitehorn * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18264391Snwhitehorn * 19264391Snwhitehorn * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20264391Snwhitehorn * or visit www.oracle.com if you need additional information or have any 21264391Snwhitehorn * questions. 22264391Snwhitehorn */ 23264391Snwhitehorn 24264391Snwhitehorn/** 25264391Snwhitehorn * @test 26264391Snwhitehorn * @bug 8003280 8006694 27264391Snwhitehorn * @summary Add lambda tests 28293460Ssmh * perform automated checks in type inference in lambda expressions 29264391Snwhitehorn * in different contexts 30264391Snwhitehorn * temporarily workaround combo tests are causing time out in several platforms 31271762Semaste * @library ../../../lib 32264391Snwhitehorn * @build JavacTestingAbstractThreadedTest 33294060Ssmh * @compile TypeInferenceComboTest.java 34294765Simp * @run main/othervm/timeout=360 TypeInferenceComboTest 35294060Ssmh */ 36294060Ssmh 37294060Ssmh// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) 38294068Ssmh// see JDK-8006746 39294068Ssmh 40294068Ssmhimport java.net.URI; 41294060Ssmhimport java.util.Arrays; 42294060Ssmhimport javax.tools.Diagnostic; 43294060Ssmhimport javax.tools.JavaFileObject; 44294060Ssmhimport javax.tools.SimpleJavaFileObject; 45264391Snwhitehornimport com.sun.source.util.JavacTask; 46294060Ssmh 47294060Ssmhpublic class TypeInferenceComboTest 48294060Ssmh extends JavacTestingAbstractThreadedTest 49294060Ssmh implements Runnable { 50293460Ssmh enum Context { 51293724Ssmh ASSIGNMENT("SAM#Type s = #LBody;"), 52264391Snwhitehorn METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" + 53294060Ssmh "void method2() {\n" + 54294060Ssmh " method1(#LBody);\n" + 55264391Snwhitehorn "}"), 56294060Ssmh RETURN_OF_METHOD("SAM#Type method1() {\n" + 57294060Ssmh " return #LBody;\n" + 58281169Sandrew "}"), 59264391Snwhitehorn LAMBDA_RETURN_EXPRESSION("SAM2 s2 = () -> {return (SAM#Type)#LBody;};\n"), 60264391Snwhitehorn ARRAY_INITIALIZER("Object[] oarray = {\"a\", 1, (SAM#Type)#LBody};"); 61264391Snwhitehorn 62264391Snwhitehorn String context; 63271762Semaste 64264391Snwhitehorn Context(String context) { 65294060Ssmh this.context = context; 66294060Ssmh } 67294060Ssmh 68294060Ssmh String getContext(SamKind sk, TypeKind samTargetT, Keyword kw, 69294060Ssmh TypeKind parameterT, TypeKind returnT, LambdaKind lk, 70294060Ssmh ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) { 71294060Ssmh String result = context; 72294060Ssmh if (sk == SamKind.GENERIC) { 73294060Ssmh if(this == Context.METHOD_CALL) { 74264391Snwhitehorn result = result.replaceAll("#GenericDeclKind", 75294060Ssmh gdk.getGenericDeclKind(samTargetT)); 76294060Ssmh if(gdk == GenericDeclKind.NON_GENERIC) 77294060Ssmh result = result.replaceAll("#Type", "<" + 78294060Ssmh samTargetT.typeStr + ">"); 79294060Ssmh else //#GenericDeclKind is <T> or <T extends xxx> 80294060Ssmh result = result.replaceAll("#Type", "<T>"); 81294060Ssmh } 82294060Ssmh else { 83264391Snwhitehorn if(kw == Keyword.VOID) 84294060Ssmh result = result.replaceAll("#Type", "<" + 85294060Ssmh samTargetT.typeStr + ">"); 86294060Ssmh else 87294060Ssmh result = result.replaceAll("#Type", "<? " + kw.keyStr + 88294060Ssmh " " + samTargetT.typeStr + ">"); 89294060Ssmh } 90294060Ssmh } 91294060Ssmh else 92294060Ssmh result = result.replaceAll("#Type", ""). 93294060Ssmh replaceAll("#GenericDeclKind", ""); 94294768Simp 95294060Ssmh return result.replaceAll("#LBody", 96294768Simp lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk)); 97294060Ssmh } 98294060Ssmh } 99294060Ssmh 100264391Snwhitehorn enum SamKind { 101294060Ssmh GENERIC("interface SAM<T> { #R m(#ARG); }"), 102294768Simp NON_GENERIC("interface SAM { #R m(#ARG); }"); 103294768Simp 104294768Simp String sam_str; 105294768Simp 106294768Simp SamKind(String sam_str) { 107294768Simp this.sam_str = sam_str; 108294768Simp } 109294768Simp 110294768Simp String getSam(TypeKind parameterT, TypeKind returnT) { 111294768Simp return sam_str.replaceAll("#ARG", 112294768Simp parameterT == TypeKind.VOID ? 113294768Simp "" : parameterT.typeStr + " arg") 114294768Simp .replaceAll("#R", returnT.typeStr); 115294768Simp } 116294768Simp } 117294768Simp 118294768Simp enum TypeKind { 119294768Simp VOID("void", ""), 120294768Simp STRING("String", "\"hello\""), 121294768Simp INTEGER("Integer", "1"), 122294768Simp INT("int", "0"), 123294768Simp COMPARATOR("java.util.Comparator<String>", 124294768Simp "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"), 125294768Simp SAM("SAM2", "null"), 126294768Simp GENERIC("T", null); 127294768Simp 128294768Simp String typeStr; 129294765Simp String valStr; 130294060Ssmh 131294060Ssmh TypeKind(String typeStr, String valStr) { 132294060Ssmh this.typeStr = typeStr; 133294060Ssmh this.valStr = valStr; 134294765Simp } 135294765Simp } 136294060Ssmh 137294060Ssmh enum LambdaKind { 138294060Ssmh EXPRESSION("#VAL"), 139294060Ssmh STATEMENT("{return #VAL;}"); 140294060Ssmh 141294060Ssmh String stmt; 142294060Ssmh 143294060Ssmh LambdaKind(String stmt) { 144294060Ssmh this.stmt = stmt; 145294060Ssmh } 146294768Simp } 147294768Simp 148294768Simp enum ParameterKind { 149294060Ssmh EXPLICIT("#TYPE"), 150294060Ssmh IMPLICIT(""); 151294060Ssmh 152294060Ssmh String paramTemplate; 153294060Ssmh 154294060Ssmh ParameterKind(String paramTemplate) { 155294060Ssmh this.paramTemplate = paramTemplate; 156294060Ssmh } 157294768Simp } 158294768Simp 159294060Ssmh enum Keyword { 160294060Ssmh SUPER("super"), 161294060Ssmh EXTENDS("extends"), 162294284Semaste VOID(""); 163294284Semaste 164294768Simp String keyStr; 165294768Simp 166294768Simp Keyword(String keyStr) { 167294060Ssmh this.keyStr = keyStr; 168294060Ssmh } 169294060Ssmh } 170294060Ssmh 171294060Ssmh enum LambdaBody { 172294060Ssmh //no parameters, return type is one of the TypeKind 173294060Ssmh RETURN_VOID("() -> #RET"), 174294060Ssmh //has parameters, return type is one of the TypeKind 175294060Ssmh RETURN_ARG("(#PK arg) -> #RET"); 176271762Semaste 177281059Srpaulo String bodyStr; 178294060Ssmh 179264391Snwhitehorn LambdaBody(String bodyStr) { 180294060Ssmh this.bodyStr = bodyStr; 181264391Snwhitehorn } 182264391Snwhitehorn 183294060Ssmh String getLambdaBody(TypeKind samTargetT, TypeKind parameterT, 184264391Snwhitehorn TypeKind returnT, LambdaKind lk, ParameterKind pk) { 185294060Ssmh String result = bodyStr.replaceAll("#PK", pk.paramTemplate); 186294060Ssmh 187271762Semaste if(result.contains("#TYPE")) { 188271762Semaste if (parameterT == TypeKind.GENERIC && this != RETURN_VOID) 189271762Semaste result = result.replaceAll("#TYPE", 190271762Semaste samTargetT == null? "": samTargetT.typeStr); 191281059Srpaulo else 192281059Srpaulo result = result.replaceAll("#TYPE", parameterT.typeStr); 193281059Srpaulo } 194281059Srpaulo if (this == RETURN_ARG && parameterT == returnT) 195281059Srpaulo return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg")); 196281059Srpaulo else { 197281059Srpaulo if(returnT != TypeKind.GENERIC) 198293274Ssmh return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", 199281059Srpaulo (returnT==TypeKind.VOID && 200281059Srpaulo lk==LambdaKind.EXPRESSION) ? "{}" : returnT.valStr)); 201281059Srpaulo else 202281059Srpaulo return result.replaceAll("#RET", 203281059Srpaulo lk.stmt.replaceAll("#VAL", samTargetT.valStr)); 204281059Srpaulo } 205281059Srpaulo } 206281059Srpaulo } 207281059Srpaulo 208281059Srpaulo enum GenericDeclKind { 209281059Srpaulo NON_GENERIC(""), 210271762Semaste GENERIC_NOBOUND("<T>"), 211294060Ssmh GENERIC_BOUND("<T extends #ExtendedType>"); 212294765Simp String typeStr; 213294060Ssmh 214294060Ssmh GenericDeclKind(String typeStr) { 215294060Ssmh this.typeStr = typeStr; 216264391Snwhitehorn } 217264391Snwhitehorn 218294060Ssmh String getGenericDeclKind(TypeKind et) { 219294060Ssmh return typeStr.replaceAll("#ExtendedType", et==null? "":et.typeStr); 220294060Ssmh } 221294060Ssmh } 222294060Ssmh 223264391Snwhitehorn boolean checkTypeInference() { 224294060Ssmh if (parameterType == TypeKind.VOID) { 225294060Ssmh if (lambdaBodyType != LambdaBody.RETURN_VOID) 226294060Ssmh return false; 227294060Ssmh } 228294060Ssmh else if (lambdaBodyType != LambdaBody.RETURN_ARG) 229294060Ssmh return false; 230264391Snwhitehorn if ( genericDeclKind == GenericDeclKind.GENERIC_NOBOUND || 231294060Ssmh genericDeclKind == GenericDeclKind.GENERIC_BOUND ) { 232294060Ssmh if ( parameterType == TypeKind.GENERIC && 233294060Ssmh parameterKind == ParameterKind.IMPLICIT) //cyclic inference 234294060Ssmh return false; 235294060Ssmh } 236294060Ssmh return true; 237294060Ssmh } 238294060Ssmh 239294060Ssmh String templateStr = "#C\n" + 240294060Ssmh "interface SAM2 {\n" + 241294060Ssmh " SAM m();\n" + 242294060Ssmh "}\n"; 243294060Ssmh SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) { 244294060Ssmh public String toString() { 245294060Ssmh return template.replaceAll("#C", 246294060Ssmh samKind.getSam(parameterType, returnType)); 247294060Ssmh } 248294060Ssmh }; 249294060Ssmh 250294060Ssmh SourceFile clientSourceFile = new SourceFile("Client.java", 251294060Ssmh "class Client { \n" + 252294060Ssmh " #Context\n" + 253264391Snwhitehorn "}") { 254294060Ssmh public String toString() { 255294060Ssmh return template.replaceAll("#Context", 256294060Ssmh context.getContext(samKind, samTargetType, keyword, 257294060Ssmh parameterType, returnType, lambdaKind, parameterKind, 258294060Ssmh genericDeclKind, lambdaBodyType)); 259294060Ssmh } 260294060Ssmh }; 261294060Ssmh 262264391Snwhitehorn public void run() { 263294060Ssmh DiagnosticChecker dc = new DiagnosticChecker(); 264294060Ssmh JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc, 265294060Ssmh null, null, Arrays.asList(samSourceFile, clientSourceFile)); 266294060Ssmh try { 267294060Ssmh ct.analyze(); 268294060Ssmh } catch (Throwable t) { 269294060Ssmh processException(t); 270264391Snwhitehorn } 271294060Ssmh if (dc.errorFound == checkTypeInference()) { 272264391Snwhitehorn throw new AssertionError(samSourceFile + "\n\n" + 273294060Ssmh clientSourceFile + "\n" + parameterType + " " + returnType); 274294060Ssmh } 275294060Ssmh } 276294060Ssmh 277294060Ssmh abstract class SourceFile extends SimpleJavaFileObject { 278294060Ssmh 279294060Ssmh protected String template; 280264391Snwhitehorn 281294060Ssmh public SourceFile(String filename, String template) { 282294060Ssmh super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE); 283294060Ssmh this.template = template; 284294060Ssmh } 285281058Srpaulo 286294060Ssmh @Override 287294060Ssmh public CharSequence getCharContent(boolean ignoreEncodingErrors) { 288264391Snwhitehorn return toString(); 289264391Snwhitehorn } 290294060Ssmh 291294060Ssmh public abstract String toString(); 292264391Snwhitehorn } 293294060Ssmh 294294060Ssmh static class DiagnosticChecker 295294060Ssmh implements javax.tools.DiagnosticListener<JavaFileObject> { 296264391Snwhitehorn 297294060Ssmh boolean errorFound = false; 298264391Snwhitehorn 299294060Ssmh public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 300294060Ssmh if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { 301294060Ssmh errorFound = true; 302294060Ssmh } 303264391Snwhitehorn } 304294060Ssmh } 305294060Ssmh 306294060Ssmh SamKind samKind; 307294060Ssmh TypeKind samTargetType; 308294060Ssmh TypeKind parameterType; 309264391Snwhitehorn TypeKind returnType; 310294060Ssmh Context context; 311294060Ssmh LambdaBody lambdaBodyType; 312264391Snwhitehorn LambdaKind lambdaKind; 313294060Ssmh ParameterKind parameterKind; 314294060Ssmh Keyword keyword; 315294060Ssmh GenericDeclKind genericDeclKind; 316264391Snwhitehorn 317294060Ssmh TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT, 318294060Ssmh TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk, 319294060Ssmh ParameterKind pk, Keyword kw, GenericDeclKind gdk) { 320294060Ssmh samKind = sk; 321264414Snwhitehorn samTargetType = samTargetT; 322264414Snwhitehorn parameterType = parameterT; 323294060Ssmh returnType = returnT; 324294060Ssmh context = c; 325281058Srpaulo lambdaKind = lk; 326294060Ssmh parameterKind = pk; 327294060Ssmh keyword = kw; 328294060Ssmh lambdaBodyType = lb; 329294060Ssmh genericDeclKind = gdk; 330264391Snwhitehorn } 331294060Ssmh 332294060Ssmh public static void main(String[] args) throws Exception { 333294060Ssmh for(Context ct : Context.values()) { 334294060Ssmh for (TypeKind returnT : TypeKind.values()) { 335294060Ssmh for (TypeKind parameterT : TypeKind.values()) { 336294060Ssmh for(LambdaBody lb : LambdaBody.values()) { 337294060Ssmh for (ParameterKind parameterK : ParameterKind.values()) { 338294060Ssmh for(LambdaKind lambdaK : LambdaKind.values()) { 339294060Ssmh for (SamKind sk : SamKind.values()) { 340294060Ssmh if (sk == SamKind.NON_GENERIC) { 341294060Ssmh generateNonGenericSAM(ct, returnT, 342294060Ssmh parameterT, lb, parameterK, 343294060Ssmh lambdaK, sk); 344294060Ssmh } 345294060Ssmh else if (sk == SamKind.GENERIC) { 346294060Ssmh generateGenericSAM(ct, returnT, 347294060Ssmh parameterT, lb, parameterK, 348281058Srpaulo lambdaK, sk); 349294060Ssmh } 350294060Ssmh } 351264391Snwhitehorn } 352264391Snwhitehorn } 353294060Ssmh } 354294060Ssmh } 355264391Snwhitehorn } 356294060Ssmh } 357264391Snwhitehorn 358294060Ssmh checkAfterExec(false); 359294060Ssmh } 360264391Snwhitehorn 361264391Snwhitehorn static void generateNonGenericSAM(Context ct, TypeKind returnT, 362264391Snwhitehorn TypeKind parameterT, LambdaBody lb, ParameterKind parameterK, 363294060Ssmh LambdaKind lambdaK, SamKind sk) { 364294060Ssmh if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) { 365281058Srpaulo pool.execute(new TypeInferenceComboTest(sk, null, parameterT, 366294060Ssmh returnT, lb, ct, lambdaK, parameterK, null, null)); 367264391Snwhitehorn } 368264391Snwhitehorn } 369293460Ssmh 370264391Snwhitehorn static void generateGenericSAM(Context ct, TypeKind returnT, 371264391Snwhitehorn TypeKind parameterT, LambdaBody lb, ParameterKind parameterK, 372264391Snwhitehorn LambdaKind lambdaK, SamKind sk) { 373264391Snwhitehorn for (Keyword kw : Keyword.values()) { 374293460Ssmh for (TypeKind samTargetT : TypeKind.values()) { 375264391Snwhitehorn if(samTargetT != TypeKind.VOID && 376293460Ssmh samTargetT != TypeKind.INT && 377264391Snwhitehorn samTargetT != TypeKind.GENERIC && 378293460Ssmh (parameterT == TypeKind.GENERIC || 379264391Snwhitehorn returnT == TypeKind.GENERIC)) { 380264391Snwhitehorn if(ct != Context.METHOD_CALL) { 381264391Snwhitehorn pool.execute( 382264391Snwhitehorn new TypeInferenceComboTest(sk, samTargetT, parameterT, 383293460Ssmh returnT, lb, ct, lambdaK, parameterK, kw, null)); 384293460Ssmh } else {//Context.METHOD_CALL 385264391Snwhitehorn for (GenericDeclKind gdk : 386264391Snwhitehorn GenericDeclKind.values()) 387264391Snwhitehorn pool.execute( 388264391Snwhitehorn new TypeInferenceComboTest(sk, samTargetT, 389264391Snwhitehorn parameterT, returnT, lb, ct, lambdaK, 390264391Snwhitehorn parameterK, kw, gdk)); 391264391Snwhitehorn } 392264391Snwhitehorn } 393264391Snwhitehorn } 394264391Snwhitehorn } 395264391Snwhitehorn } 396264391Snwhitehorn 397} 398