test/tools/javac/lambda/LambdaParserTest.java

Thu, 17 Jan 2013 18:15:20 +0000

author
mcimadamore
date
Thu, 17 Jan 2013 18:15:20 +0000
changeset 1503
2d2b2be57c78
parent 1482
954541f13717
child 1520
5c956be64b9e
permissions
-rw-r--r--

8005852: Treatment of '_' as identifier
Summary: warn when '_' is found in an identifier position
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 7115050 8003280 8005852
    27  * @summary Add lambda tests
    28  *  Add parser support for lambda expressions
    29  * @library ../lib
    30  * @build JavacTestingAbstractThreadedTest
    31  * @run main LambdaParserTest
    32  */
    34 import java.net.URI;
    35 import java.util.Arrays;
    36 import javax.tools.Diagnostic;
    37 import javax.tools.JavaFileObject;
    38 import javax.tools.SimpleJavaFileObject;
    39 import com.sun.source.util.JavacTask;
    41 public class LambdaParserTest
    42     extends JavacTestingAbstractThreadedTest
    43     implements Runnable {
    45     enum LambdaKind {
    46         NILARY_EXPR("()->x"),
    47         NILARY_STMT("()->{ return x; }"),
    48         ONEARY_SHORT_EXPR("#PN->x"),
    49         ONEARY_SHORT_STMT("#PN->{ return x; }"),
    50         ONEARY_EXPR("(#M1 #T1 #PN)->x"),
    51         ONEARY_STMT("(#M1 #T1 #PN)->{ return x; }"),
    52         TWOARY_EXPR("(#M1 #T1 #PN, #M2 #T2 y)->x"),
    53         TWOARY_STMT("(#M1 #T1 #PN, #M2 #T2 y)->{ return x; }");
    55         String lambdaTemplate;
    57         LambdaKind(String lambdaTemplate) {
    58             this.lambdaTemplate = lambdaTemplate;
    59         }
    61         String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2,
    62                 ModifierKind mk1, ModifierKind mk2, LambdaParameterName pn) {
    63             return lambdaTemplate.replaceAll("#M1", mk1.modifier)
    64                     .replaceAll("#M2", mk2.modifier)
    65                     .replaceAll("#T1", pk1.parameterType)
    66                     .replaceAll("#T2", pk2.parameterType)
    67                     .replaceAll("#PN", pn.nameStr);
    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 LambdaParameterName {
    91         IDENT("x"),
    92         UNDERSCORE("_");
    94         String nameStr;
    96         LambdaParameterName(String nameStr) {
    97             this.nameStr = nameStr;
    98         }
    99     }
   101     enum LambdaParameterKind {
   102         IMPLICIT(""),
   103         EXPLIICT_SIMPLE("A"),
   104         EXPLIICT_SIMPLE_ARR1("A[]"),
   105         EXPLIICT_SIMPLE_ARR2("A[][]"),
   106         EXPLICIT_VARARGS("A..."),
   107         EXPLICIT_GENERIC1("A<X>"),
   108         EXPLICIT_GENERIC2("A<? extends X, ? super Y>"),
   109         EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>..."),
   110         EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]"),
   111         EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]");
   113         String parameterType;
   115         LambdaParameterKind(String parameterType) {
   116             this.parameterType = parameterType;
   117         }
   119         boolean explicit() {
   120             return this != IMPLICIT;
   121         }
   123         boolean isVarargs() {
   124             return this == EXPLICIT_VARARGS ||
   125                     this == EXPLICIT_GENERIC2_VARARGS;
   126         }
   127     }
   129     enum ModifierKind {
   130         NONE(""),
   131         FINAL("final"),
   132         PUBLIC("public");
   134         String modifier;
   136         ModifierKind(String modifier) {
   137             this.modifier = modifier;
   138         }
   140         boolean compatibleWith(LambdaParameterKind pk) {
   141             switch (this) {
   142                 case PUBLIC: return false;
   143                 case FINAL: return pk != LambdaParameterKind.IMPLICIT;
   144                 case NONE: return true;
   145                 default: throw new AssertionError("Invalid modifier kind " + this);
   146             }
   147         }
   148     }
   150     enum ExprKind {
   151         NONE("#L#S"),
   152         SINGLE_PAREN1("(#L#S)"),
   153         SINGLE_PAREN2("(#L)#S"),
   154         DOUBLE_PAREN1("((#L#S))"),
   155         DOUBLE_PAREN2("((#L)#S)"),
   156         DOUBLE_PAREN3("((#L))#S");
   158         String expressionTemplate;
   160         ExprKind(String expressionTemplate) {
   161             this.expressionTemplate = expressionTemplate;
   162         }
   164         String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2,
   165                 ModifierKind mk1, ModifierKind mk2, LambdaKind lk, LambdaParameterName pn, SubExprKind sk) {
   166             return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2, pn))
   167                     .replaceAll("#S", sk.subExpression);
   168         }
   169     }
   171     enum SubExprKind {
   172         NONE(""),
   173         SELECT_FIELD(".f"),
   174         SELECT_METHOD(".f()"),
   175         SELECT_NEW(".new Foo()"),
   176         POSTINC("++"),
   177         POSTDEC("--");
   179         String subExpression;
   181         SubExprKind(String subExpression) {
   182             this.subExpression = subExpression;
   183         }
   184     }
   186     public static void main(String... args) throws Exception {
   187         for (LambdaKind lk : LambdaKind.values()) {
   188             for (LambdaParameterName pn : LambdaParameterName.values()) {
   189                 for (LambdaParameterKind pk1 : LambdaParameterKind.values()) {
   190                     if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT)
   191                         continue;
   192                     for (LambdaParameterKind pk2 : LambdaParameterKind.values()) {
   193                         if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT)
   194                             continue;
   195                         for (ModifierKind mk1 : ModifierKind.values()) {
   196                             if (mk1 != ModifierKind.NONE && lk.isShort())
   197                                 continue;
   198                             if (lk.arity() < 1 && mk1 != ModifierKind.NONE)
   199                                 continue;
   200                             for (ModifierKind mk2 : ModifierKind.values()) {
   201                                 if (lk.arity() < 2 && mk2 != ModifierKind.NONE)
   202                                     continue;
   203                                 for (SubExprKind sk : SubExprKind.values()) {
   204                                     for (ExprKind ek : ExprKind.values()) {
   205                                         pool.execute(
   206                                             new LambdaParserTest(pk1, pk2, mk1,
   207                                                                  mk2, lk, sk, ek, pn));
   208                                     }
   209                                 }
   210                             }
   211                         }
   212                     }
   213                 }
   214             }
   215         }
   217         checkAfterExec();
   218     }
   220     LambdaParameterKind pk1;
   221     LambdaParameterKind pk2;
   222     ModifierKind mk1;
   223     ModifierKind mk2;
   224     LambdaKind lk;
   225     LambdaParameterName pn;
   226     SubExprKind sk;
   227     ExprKind ek;
   228     JavaSource source;
   229     DiagnosticChecker diagChecker;
   231     LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2,
   232             ModifierKind mk1, ModifierKind mk2, LambdaKind lk,
   233             SubExprKind sk, ExprKind ek, LambdaParameterName pn) {
   234         this.pk1 = pk1;
   235         this.pk2 = pk2;
   236         this.mk1 = mk1;
   237         this.mk2 = mk2;
   238         this.lk = lk;
   239         this.pn = pn;
   240         this.sk = sk;
   241         this.ek = ek;
   242         this.source = new JavaSource();
   243         this.diagChecker = new DiagnosticChecker();
   244     }
   246     class JavaSource extends SimpleJavaFileObject {
   248         String template = "class Test {\n" +
   249                           "   SAM s = #E;\n" +
   250                           "}";
   252         String source;
   254         public JavaSource() {
   255             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   256             source = template.replaceAll("#E",
   257                     ek.expressionString(pk1, pk2, mk1, mk2, lk, pn, sk));
   258         }
   260         @Override
   261         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   262             return source;
   263         }
   264     }
   266     public void run() {
   267         JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
   268                 null, null, Arrays.asList(source));
   269         try {
   270             ct.parse();
   271         } catch (Throwable ex) {
   272             processException(ex);
   273             return;
   274         }
   275         check();
   276     }
   278     void check() {
   279         checkCount.incrementAndGet();
   281         boolean errorExpected = (lk.arity() > 0 && !mk1.compatibleWith(pk1)) ||
   282                 (lk.arity() > 1 && !mk2.compatibleWith(pk2));
   284         if (lk.arity() == 2 &&
   285                 (pk1.explicit() != pk2.explicit() ||
   286                 pk1.isVarargs())) {
   287             errorExpected = true;
   288         }
   290         errorExpected |= pn == LambdaParameterName.UNDERSCORE &&
   291                 lk.arity() > 0;
   293         if (errorExpected != diagChecker.errorFound) {
   294             throw new Error("invalid diagnostics for source:\n" +
   295                 source.getCharContent(true) +
   296                 "\nFound error: " + diagChecker.errorFound +
   297                 "\nExpected error: " + errorExpected);
   298         }
   299     }
   301     static class DiagnosticChecker
   302         implements javax.tools.DiagnosticListener<JavaFileObject> {
   304         boolean errorFound;
   306         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   307             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   308                 errorFound = true;
   309             }
   310         }
   311     }
   313 }

mercurial