test/tools/javac/lambda/LambdaParserTest.java

Thu, 10 Jan 2013 19:38:57 -0800

author
jjg
date
Thu, 10 Jan 2013 19:38:57 -0800
changeset 1490
fc4cb1577ad6
parent 1482
954541f13717
child 1503
2d2b2be57c78
permissions
-rw-r--r--

8004834: Add doclint support into javadoc
Reviewed-by: darcy

     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 7115050
    27  * @bug 8003280
    28  * @summary Add lambda tests
    29  *  Add parser support for lambda expressions
    30  * @library ../lib
    31  * @build JavacTestingAbstractThreadedTest
    32  * @run main LambdaParserTest
    33  */
    35 import java.net.URI;
    36 import java.util.Arrays;
    37 import javax.tools.Diagnostic;
    38 import javax.tools.JavaFileObject;
    39 import javax.tools.SimpleJavaFileObject;
    40 import com.sun.source.util.JavacTask;
    42 public class LambdaParserTest
    43     extends JavacTestingAbstractThreadedTest
    44     implements Runnable {
    46     enum LambdaKind {
    47         NILARY_EXPR("()->x"),
    48         NILARY_STMT("()->{ return x; }"),
    49         ONEARY_SHORT_EXPR("x->x"),
    50         ONEARY_SHORT_STMT("x->{ return x; }"),
    51         ONEARY_EXPR("(#M1 #T1 x)->x"),
    52         ONEARY_STMT("(#M1 #T1 x)->{ return x; }"),
    53         TWOARY_EXPR("(#M1 #T1 x, #M2 #T2 y)->x"),
    54         TWOARY_STMT("(#M1 #T1 x, #M2 #T2 y)->{ return x; }");
    56         String lambdaTemplate;
    58         LambdaKind(String lambdaTemplate) {
    59             this.lambdaTemplate = lambdaTemplate;
    60         }
    62         String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2,
    63                 ModifierKind mk1, ModifierKind mk2) {
    64             return lambdaTemplate.replaceAll("#M1", mk1.modifier)
    65                     .replaceAll("#M2", mk2.modifier)
    66                     .replaceAll("#T1", pk1.parameterType)
    67                     .replaceAll("#T2", pk2.parameterType);
    68         }
    70         int arity() {
    71             switch (this) {
    72                 case NILARY_EXPR:
    73                 case NILARY_STMT: return 0;
    74                 case ONEARY_SHORT_EXPR:
    75                 case ONEARY_SHORT_STMT:
    76                 case ONEARY_EXPR:
    77                 case ONEARY_STMT: return 1;
    78                 case TWOARY_EXPR:
    79                 case TWOARY_STMT: return 2;
    80                 default: throw new AssertionError("Invalid lambda kind " + this);
    81             }
    82         }
    84         boolean isShort() {
    85             return this == ONEARY_SHORT_EXPR ||
    86                     this == ONEARY_SHORT_STMT;
    87         }
    88     }
    90     enum LambdaParameterKind {
    91         IMPLICIT(""),
    92         EXPLIICT_SIMPLE("A"),
    93         EXPLIICT_SIMPLE_ARR1("A[]"),
    94         EXPLIICT_SIMPLE_ARR2("A[][]"),
    95         EXPLICIT_VARARGS("A..."),
    96         EXPLICIT_GENERIC1("A<X>"),
    97         EXPLICIT_GENERIC2("A<? extends X, ? super Y>"),
    98         EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>..."),
    99         EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]"),
   100         EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]");
   102         String parameterType;
   104         LambdaParameterKind(String parameterType) {
   105             this.parameterType = parameterType;
   106         }
   108         boolean explicit() {
   109             return this != IMPLICIT;
   110         }
   112         boolean isVarargs() {
   113             return this == EXPLICIT_VARARGS ||
   114                     this == EXPLICIT_GENERIC2_VARARGS;
   115         }
   116     }
   118     enum ModifierKind {
   119         NONE(""),
   120         FINAL("final"),
   121         PUBLIC("public");
   123         String modifier;
   125         ModifierKind(String modifier) {
   126             this.modifier = modifier;
   127         }
   129         boolean compatibleWith(LambdaParameterKind pk) {
   130             switch (this) {
   131                 case PUBLIC: return false;
   132                 case FINAL: return pk != LambdaParameterKind.IMPLICIT;
   133                 case NONE: return true;
   134                 default: throw new AssertionError("Invalid modifier kind " + this);
   135             }
   136         }
   137     }
   139     enum ExprKind {
   140         NONE("#L#S"),
   141         SINGLE_PAREN1("(#L#S)"),
   142         SINGLE_PAREN2("(#L)#S"),
   143         DOUBLE_PAREN1("((#L#S))"),
   144         DOUBLE_PAREN2("((#L)#S)"),
   145         DOUBLE_PAREN3("((#L))#S");
   147         String expressionTemplate;
   149         ExprKind(String expressionTemplate) {
   150             this.expressionTemplate = expressionTemplate;
   151         }
   153         String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2,
   154                 ModifierKind mk1, ModifierKind mk2, LambdaKind lk, SubExprKind sk) {
   155             return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2))
   156                     .replaceAll("#S", sk.subExpression);
   157         }
   158     }
   160     enum SubExprKind {
   161         NONE(""),
   162         SELECT_FIELD(".f"),
   163         SELECT_METHOD(".f()"),
   164         SELECT_NEW(".new Foo()"),
   165         POSTINC("++"),
   166         POSTDEC("--");
   168         String subExpression;
   170         SubExprKind(String subExpression) {
   171             this.subExpression = subExpression;
   172         }
   173     }
   175     public static void main(String... args) throws Exception {
   176         for (LambdaKind lk : LambdaKind.values()) {
   177             for (LambdaParameterKind pk1 : LambdaParameterKind.values()) {
   178                 if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT)
   179                     continue;
   180                 for (LambdaParameterKind pk2 : LambdaParameterKind.values()) {
   181                     if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT)
   182                         continue;
   183                     for (ModifierKind mk1 : ModifierKind.values()) {
   184                         if (mk1 != ModifierKind.NONE && lk.isShort())
   185                             continue;
   186                         if (lk.arity() < 1 && mk1 != ModifierKind.NONE)
   187                             continue;
   188                         for (ModifierKind mk2 : ModifierKind.values()) {
   189                             if (lk.arity() < 2 && mk2 != ModifierKind.NONE)
   190                                 continue;
   191                             for (SubExprKind sk : SubExprKind.values()) {
   192                                 for (ExprKind ek : ExprKind.values()) {
   193                                     pool.execute(
   194                                         new LambdaParserTest(pk1, pk2, mk1,
   195                                                              mk2, lk, sk, ek));
   196                                 }
   197                             }
   198                         }
   199                     }
   200                 }
   201             }
   202         }
   204         checkAfterExec();
   205     }
   207     LambdaParameterKind pk1;
   208     LambdaParameterKind pk2;
   209     ModifierKind mk1;
   210     ModifierKind mk2;
   211     LambdaKind lk;
   212     SubExprKind sk;
   213     ExprKind ek;
   214     JavaSource source;
   215     DiagnosticChecker diagChecker;
   217     LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2,
   218             ModifierKind mk1, ModifierKind mk2, LambdaKind lk,
   219             SubExprKind sk, ExprKind ek) {
   220         this.pk1 = pk1;
   221         this.pk2 = pk2;
   222         this.mk1 = mk1;
   223         this.mk2 = mk2;
   224         this.lk = lk;
   225         this.sk = sk;
   226         this.ek = ek;
   227         this.source = new JavaSource();
   228         this.diagChecker = new DiagnosticChecker();
   229     }
   231     class JavaSource extends SimpleJavaFileObject {
   233         String template = "class Test {\n" +
   234                           "   SAM s = #E;\n" +
   235                           "}";
   237         String source;
   239         public JavaSource() {
   240             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   241             source = template.replaceAll("#E",
   242                     ek.expressionString(pk1, pk2, mk1, mk2, lk, sk));
   243         }
   245         @Override
   246         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   247             return source;
   248         }
   249     }
   251     public void run() {
   252         JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
   253                 null, null, Arrays.asList(source));
   254         try {
   255             ct.parse();
   256         } catch (Throwable ex) {
   257             processException(ex);
   258             return;
   259         }
   260         check();
   261     }
   263     void check() {
   264         checkCount.incrementAndGet();
   266         boolean errorExpected = (lk.arity() > 0 && !mk1.compatibleWith(pk1)) ||
   267                 (lk.arity() > 1 && !mk2.compatibleWith(pk2));
   269         if (lk.arity() == 2 &&
   270                 (pk1.explicit() != pk2.explicit() ||
   271                 pk1.isVarargs())) {
   272             errorExpected = true;
   273         }
   275         if (errorExpected != diagChecker.errorFound) {
   276             throw new Error("invalid diagnostics for source:\n" +
   277                 source.getCharContent(true) +
   278                 "\nFound error: " + diagChecker.errorFound +
   279                 "\nExpected error: " + errorExpected);
   280         }
   281     }
   283     static class DiagnosticChecker
   284         implements javax.tools.DiagnosticListener<JavaFileObject> {
   286         boolean errorFound;
   288         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   289             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   290                 errorFound = true;
   291             }
   292         }
   293     }
   295 }

mercurial