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

Mon, 21 Jan 2013 20:13:56 +0000

author
mcimadamore
date
Mon, 21 Jan 2013 20:13:56 +0000
changeset 1510
7873d37f5b37
parent 1482
954541f13717
child 1520
5c956be64b9e
permissions
-rw-r--r--

8005244: Implement overload resolution as per latest spec EDR
Summary: Add support for stuck expressions and provisional applicability
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2011, 2013, 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  */
    24 /**
    25  * @test
    26  * @bug 8003280
    27  * @summary Add lambda tests
    28  *  perform automated checks in type inference in lambda expressions
    29  *  in different contexts
    30  * @library ../../../lib
    31  * @build JavacTestingAbstractThreadedTest
    32  * @compile  TypeInferenceComboTest.java
    33  * @run main/timeout=360 TypeInferenceComboTest
    34  */
    36 import java.net.URI;
    37 import java.util.Arrays;
    38 import javax.tools.Diagnostic;
    39 import javax.tools.JavaFileObject;
    40 import javax.tools.SimpleJavaFileObject;
    41 import com.sun.source.util.JavacTask;
    43 public class TypeInferenceComboTest
    44     extends JavacTestingAbstractThreadedTest
    45     implements Runnable {
    46     enum Context {
    47         ASSIGNMENT("SAM#Type s = #LBody;"),
    48         METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" +
    49                     "void method2() {\n" +
    50                     "    method1(#LBody);\n" +
    51                     "}"),
    52         RETURN_OF_METHOD("SAM#Type method1() {\n" +
    53                 "    return #LBody;\n" +
    54                 "}"),
    55         LAMBDA_RETURN_EXPRESSION("SAM2 s2 = () -> {return (SAM#Type)#LBody;};\n"),
    56         ARRAY_INITIALIZER("Object[] oarray = {\"a\", 1, (SAM#Type)#LBody};");
    58         String context;
    60         Context(String context) {
    61             this.context = context;
    62         }
    64         String getContext(SamKind sk, TypeKind samTargetT, Keyword kw,
    65                 TypeKind parameterT, TypeKind returnT, LambdaKind lk,
    66                 ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) {
    67             String result = context;
    68             if (sk == SamKind.GENERIC) {
    69                 if(this == Context.METHOD_CALL) {
    70                     result = result.replaceAll("#GenericDeclKind",
    71                             gdk.getGenericDeclKind(samTargetT));
    72                     if(gdk == GenericDeclKind.NON_GENERIC)
    73                         result = result.replaceAll("#Type", "<" +
    74                                 samTargetT.typeStr + ">");
    75                     else //#GenericDeclKind is <T> or <T extends xxx>
    76                         result = result.replaceAll("#Type", "<T>");
    77                 }
    78                 else {
    79                     if(kw == Keyword.VOID)
    80                         result = result.replaceAll("#Type", "<" +
    81                                 samTargetT.typeStr + ">");
    82                     else
    83                         result = result.replaceAll("#Type", "<? " + kw.keyStr +
    84                                 " " + samTargetT.typeStr + ">");
    85                 }
    86             }
    87             else
    88                 result = result.replaceAll("#Type", "").
    89                         replaceAll("#GenericDeclKind", "");
    91             return result.replaceAll("#LBody",
    92                     lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk));
    93         }
    94     }
    96     enum SamKind {
    97         GENERIC("interface SAM<T> { #R m(#ARG); }"),
    98         NON_GENERIC("interface SAM { #R m(#ARG); }");
   100         String sam_str;
   102         SamKind(String sam_str) {
   103             this.sam_str = sam_str;
   104         }
   106         String getSam(TypeKind parameterT, TypeKind returnT) {
   107             return sam_str.replaceAll("#ARG",
   108                     parameterT == TypeKind.VOID ?
   109                         "" : parameterT.typeStr + " arg")
   110                     .replaceAll("#R", returnT.typeStr);
   111         }
   112     }
   114     enum TypeKind {
   115         VOID("void", ""),
   116         STRING("String", "\"hello\""),
   117         INTEGER("Integer", "1"),
   118         INT("int", "0"),
   119         COMPARATOR("java.util.Comparator<String>",
   120                 "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"),
   121         SAM("SAM2", "null"),
   122         GENERIC("T", null);
   124         String typeStr;
   125         String valStr;
   127         TypeKind(String typeStr, String valStr) {
   128             this.typeStr = typeStr;
   129             this.valStr = valStr;
   130         }
   131     }
   133     enum LambdaKind {
   134         EXPRESSION("#VAL"),
   135         STATEMENT("{return #VAL;}");
   137         String stmt;
   139         LambdaKind(String stmt) {
   140             this.stmt = stmt;
   141         }
   142     }
   144     enum ParameterKind {
   145         EXPLICIT("#TYPE"),
   146         IMPLICIT("");
   148         String paramTemplate;
   150         ParameterKind(String paramTemplate) {
   151              this.paramTemplate = paramTemplate;
   152         }
   153     }
   155     enum Keyword {
   156         SUPER("super"),
   157         EXTENDS("extends"),
   158         VOID("");
   160         String keyStr;
   162         Keyword(String keyStr) {
   163             this.keyStr = keyStr;
   164         }
   165     }
   167     enum LambdaBody {
   168         //no 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");
   173         String bodyStr;
   175         LambdaBody(String bodyStr) {
   176             this.bodyStr = bodyStr;
   177         }
   179         String getLambdaBody(TypeKind samTargetT, TypeKind parameterT,
   180                 TypeKind returnT, LambdaKind lk, ParameterKind pk) {
   181             String result = bodyStr.replaceAll("#PK", pk.paramTemplate);
   183             if(result.contains("#TYPE")) {
   184                 if (parameterT == TypeKind.GENERIC && this != RETURN_VOID)
   185                     result = result.replaceAll("#TYPE",
   186                             samTargetT == null? "": samTargetT.typeStr);
   187                 else
   188                     result = result.replaceAll("#TYPE", parameterT.typeStr);
   189             }
   190             if (this == RETURN_ARG && parameterT == returnT)
   191                 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg"));
   192             else {
   193                 if(returnT != TypeKind.GENERIC)
   194                     return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL",
   195                             (returnT==TypeKind.VOID &&
   196                             lk==LambdaKind.EXPRESSION) ? "{}" : returnT.valStr));
   197                 else
   198                     return result.replaceAll("#RET",
   199                             lk.stmt.replaceAll("#VAL", samTargetT.valStr));
   200             }
   201         }
   202     }
   204     enum GenericDeclKind {
   205         NON_GENERIC(""),
   206         GENERIC_NOBOUND("<T>"),
   207         GENERIC_BOUND("<T extends #ExtendedType>");
   208         String typeStr;
   210         GenericDeclKind(String typeStr) {
   211             this.typeStr = typeStr;
   212         }
   214         String getGenericDeclKind(TypeKind et) {
   215             return typeStr.replaceAll("#ExtendedType", et==null? "":et.typeStr);
   216         }
   217     }
   219     boolean checkTypeInference() {
   220         if (parameterType == TypeKind.VOID) {
   221             if (lambdaBodyType != LambdaBody.RETURN_VOID)
   222                 return false;
   223         }
   224         else if (lambdaBodyType != LambdaBody.RETURN_ARG)
   225             return false;
   226         if (  genericDeclKind == GenericDeclKind.GENERIC_NOBOUND ||
   227                 genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
   228             if ( parameterType == TypeKind.GENERIC &&
   229                     parameterKind == ParameterKind.IMPLICIT) //cyclic inference
   230                 return false;
   231         }
   232         return true;
   233     }
   235     String templateStr = "#C\n" +
   236                          "interface SAM2 {\n" +
   237                          "    SAM m();\n" +
   238                          "}\n";
   239     SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) {
   240         public String toString() {
   241             return template.replaceAll("#C",
   242                     samKind.getSam(parameterType, returnType));
   243         }
   244     };
   246     SourceFile clientSourceFile = new SourceFile("Client.java",
   247                                                  "class Client { \n" +
   248                                                  "    #Context\n" +
   249                                                  "}") {
   250         public String toString() {
   251             return template.replaceAll("#Context",
   252                     context.getContext(samKind, samTargetType, keyword,
   253                     parameterType, returnType, lambdaKind, parameterKind,
   254                     genericDeclKind, lambdaBodyType));
   255         }
   256     };
   258     public void run() {
   259         outWriter.println("kk:");
   260         StringBuilder sb = new StringBuilder("SamKind:");
   261         sb.append(samKind).append(" SamTargetType:")
   262             .append(samTargetType).append(" ParameterType:").append(parameterType)
   263             .append(" ReturnType:").append(returnType).append(" Context:")
   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);
   269         DiagnosticChecker dc = new DiagnosticChecker();
   270         JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc,
   271                 null, null, Arrays.asList(samSourceFile, clientSourceFile));
   272         try {
   273             ct.analyze();
   274         } catch (Throwable t) {
   275             processException(t);
   276         }
   277         if (dc.errorFound == checkTypeInference()) {
   278             throw new AssertionError(samSourceFile + "\n\n" +
   279                     clientSourceFile + "\n" + parameterType + " " + returnType);
   280         }
   281     }
   283     abstract class SourceFile extends SimpleJavaFileObject {
   285         protected String template;
   287         public SourceFile(String filename, String template) {
   288             super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
   289             this.template = template;
   290         }
   292         @Override
   293         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   294             return toString();
   295         }
   297         public abstract String toString();
   298     }
   300     static class DiagnosticChecker
   301         implements javax.tools.DiagnosticListener<JavaFileObject> {
   303         boolean errorFound = false;
   305         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   306             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   307                 errorFound = true;
   308             }
   309         }
   310     }
   312     SamKind samKind;
   313     TypeKind samTargetType;
   314     TypeKind parameterType;
   315     TypeKind returnType;
   316     Context context;
   317     LambdaBody lambdaBodyType;
   318     LambdaKind lambdaKind;
   319     ParameterKind parameterKind;
   320     Keyword keyword;
   321     GenericDeclKind genericDeclKind;
   323     TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT,
   324             TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk,
   325             ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
   326         samKind = sk;
   327         samTargetType = samTargetT;
   328         parameterType = parameterT;
   329         returnType = returnT;
   330         context = c;
   331         lambdaKind = lk;
   332         parameterKind = pk;
   333         keyword = kw;
   334         lambdaBodyType = lb;
   335         genericDeclKind = gdk;
   336     }
   338     public static void main(String[] args) throws Exception {
   339         for(Context ct : Context.values()) {
   340             for (TypeKind returnT : TypeKind.values()) {
   341                 for (TypeKind parameterT : TypeKind.values()) {
   342                     for(LambdaBody lb : LambdaBody.values()) {
   343                         for (ParameterKind parameterK : ParameterKind.values()) {
   344                             for(LambdaKind lambdaK : LambdaKind.values()) {
   345                                 for (SamKind sk : SamKind.values()) {
   346                                     if (sk == SamKind.NON_GENERIC) {
   347                                         generateNonGenericSAM(ct, returnT,
   348                                                 parameterT, lb, parameterK,
   349                                                 lambdaK, sk);
   350                                     }
   351                                     else if (sk == SamKind.GENERIC) {
   352                                         generateGenericSAM(ct, returnT,
   353                                                 parameterT, lb, parameterK,
   354                                                 lambdaK, sk);
   355                                     }
   356                                 }
   357                             }
   358                         }
   359                     }
   360                 }
   361             }
   362         }
   364         checkAfterExec(false);
   365     }
   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     }
   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     }
   403 }

mercurial