test/tools/javac/lambda/MethodReferenceParserTest.java

Tue, 14 May 2013 11:11:09 -0700

author
rfield
date
Tue, 14 May 2013 11:11:09 -0700
changeset 1752
c09b7234cded
parent 1520
5c956be64b9e
child 1774
37295244f534
permissions
-rw-r--r--

8012556: Implement lambda methods on interfaces as static
8006140: Javac NPE compiling Lambda expression on initialization expression of static field in interface
Summary: Lambdas occurring in static contexts or those not needing instance information should be generated into static methods. This has long been the case for classes. However, as a work-around to the lack of support for statics on interfaces, interface lambda methods have been generated into default methods. For lambdas in interface static contexts (fields and static methods) this causes an NPE in javac because there is no 'this'. MethodHandles now support static methods on interfaces. This changeset allows lambda methods to be generated as static interface methods. An existing bug in Hotspot (8013875) is exposed in a test when the "-esa" flag is used. This test and another test that already exposed this bug have been marked with @ignore.
Reviewed-by: mcimadamore

     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 7115052
    27  * @bug 8003280 8006694
    28  * @summary Add lambda tests
    29  *  Add parser support for method references
    30  *  temporarily workaround combo tests are causing time out in several platforms
    31  * @library ../lib
    32  * @build JavacTestingAbstractThreadedTest
    33  * @run main/othervm MethodReferenceParserTest
    34  */
    36 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
    37 // see JDK-8006746
    39 import java.net.URI;
    40 import java.util.Arrays;
    41 import javax.tools.Diagnostic;
    42 import javax.tools.JavaFileObject;
    43 import javax.tools.SimpleJavaFileObject;
    44 import com.sun.source.util.JavacTask;
    46 public class MethodReferenceParserTest
    47     extends JavacTestingAbstractThreadedTest
    48     implements Runnable {
    50     enum ReferenceKind {
    51         METHOD_REF("#Q::#Gm"),
    52         CONSTRUCTOR_REF("#Q::#Gnew"),
    53         FALSE_REF("min < max"),
    54         ERR_SUPER("#Q::#Gsuper"),
    55         ERR_METH0("#Q::#Gm()"),
    56         ERR_METH1("#Q::#Gm(X)"),
    57         ERR_CONSTR0("#Q::#Gnew()"),
    58         ERR_CONSTR1("#Q::#Gnew(X)");
    60         String referenceTemplate;
    62         ReferenceKind(String referenceTemplate) {
    63             this.referenceTemplate = referenceTemplate;
    64         }
    66         String getReferenceString(QualifierKind qk, GenericKind gk) {
    67             return referenceTemplate
    68                     .replaceAll("#Q", qk.qualifier)
    69                     .replaceAll("#G", gk.typeParameters);
    70         }
    72         boolean erroneous() {
    73             switch (this) {
    74                 case ERR_SUPER:
    75                 case ERR_METH0:
    76                 case ERR_METH1:
    77                 case ERR_CONSTR0:
    78                 case ERR_CONSTR1:
    79                     return true;
    80                 default: return false;
    81             }
    82         }
    83     }
    85     enum ContextKind {
    86         ASSIGN("SAM s = #E;"),
    87         METHOD("m(#E, i);");
    89         String contextTemplate;
    91         ContextKind(String contextTemplate) {
    92             this.contextTemplate = contextTemplate;
    93         }
    95         String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk,
    96                 GenericKind gk, SubExprKind sk) {
    97             return contextTemplate.replaceAll("#E", ek.expressionString(rk, qk, gk, sk));
    98         }
    99     }
   101     enum GenericKind {
   102         NONE(""),
   103         ONE("<X>"),
   104         TWO("<X,Y>");
   106         String typeParameters;
   108         GenericKind(String typeParameters) {
   109             this.typeParameters = typeParameters;
   110         }
   111     }
   113     enum QualifierKind {
   114         THIS("this"),
   115         SUPER("super"),
   116         NEW("new Foo()"),
   117         METHOD("m()"),
   118         FIELD("a.f"),
   119         UBOUND_SIMPLE("A"),
   120         UNBOUND_ARRAY1("int[]"),
   121         UNBOUND_ARRAY2("A<G>[][]"),
   122         UNBOUND_GENERIC1("A<X>"),
   123         UNBOUND_GENERIC2("A<X, Y>"),
   124         UNBOUND_GENERIC3("A<? extends X, ? super Y>"),
   125         UNBOUND_GENERIC4("A<int[], short[][]>"),
   126         NESTED_GENERIC1("A<A<X,Y>, A<X,Y>>"),
   127         NESTED_GENERIC2("A<A<A<X,Y>,A<X,Y>>, A<A<X,Y>,A<X,Y>>>");
   129         String qualifier;
   131         QualifierKind(String qualifier) {
   132             this.qualifier = qualifier;
   133         }
   134     }
   136     enum ExprKind {
   137         NONE("#R::S"),
   138         SINGLE_PAREN1("(#R#S)"),
   139         SINGLE_PAREN2("(#R)#S"),
   140         DOUBLE_PAREN1("((#R#S))"),
   141         DOUBLE_PAREN2("((#R)#S)"),
   142         DOUBLE_PAREN3("((#R))#S");
   144         String expressionTemplate;
   146         ExprKind(String expressionTemplate) {
   147             this.expressionTemplate = expressionTemplate;
   148         }
   150         String expressionString(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) {
   151             return expressionTemplate
   152                     .replaceAll("#R", rk.getReferenceString(qk, gk))
   153                     .replaceAll("#S", sk.subExpression);
   154         }
   155     }
   157     enum SubExprKind {
   158         NONE(""),
   159         SELECT_FIELD(".f"),
   160         SELECT_METHOD(".f()"),
   161         SELECT_NEW(".new Foo()"),
   162         POSTINC("++"),
   163         POSTDEC("--");
   165         String subExpression;
   167         SubExprKind(String subExpression) {
   168             this.subExpression = subExpression;
   169         }
   170     }
   172     public static void main(String... args) throws Exception {
   173         for (ReferenceKind rk : ReferenceKind.values()) {
   174             for (QualifierKind qk : QualifierKind.values()) {
   175                 for (GenericKind gk : GenericKind.values()) {
   176                     for (SubExprKind sk : SubExprKind.values()) {
   177                         for (ExprKind ek : ExprKind.values()) {
   178                             for (ContextKind ck : ContextKind.values()) {
   179                                 pool.execute(new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck));
   180                             }
   181                         }
   182                     }
   183                 }
   184             }
   185         }
   187         checkAfterExec();
   188     }
   190     ReferenceKind rk;
   191     QualifierKind qk;
   192     GenericKind gk;
   193     SubExprKind sk;
   194     ExprKind ek;
   195     ContextKind ck;
   196     JavaSource source;
   197     DiagnosticChecker diagChecker;
   199     MethodReferenceParserTest(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk, ExprKind ek, ContextKind ck) {
   200         this.rk = rk;
   201         this.qk = qk;
   202         this.gk = gk;
   203         this.sk = sk;
   204         this.ek = ek;
   205         this.ck = ck;
   206         this.source = new JavaSource();
   207         this.diagChecker = new DiagnosticChecker();
   208     }
   210     class JavaSource extends SimpleJavaFileObject {
   212         String template = "class Test {\n" +
   213                           "   void test() {\n" +
   214                           "      #C\n" +
   215                           "   }" +
   216                           "}";
   218         String source;
   220         public JavaSource() {
   221             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   222             source = template.replaceAll("#C", ck.contextString(ek, rk, qk, gk, sk));
   223         }
   225         @Override
   226         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   227             return source;
   228         }
   229     }
   231     @Override
   232     public void run() {
   233         JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
   234                 null, null, Arrays.asList(source));
   235         try {
   236             ct.parse();
   237         } catch (Throwable ex) {
   238             processException(ex);
   239             return;
   240         }
   241         check();
   242     }
   244     void check() {
   245         checkCount.incrementAndGet();
   247         if (diagChecker.errorFound != rk.erroneous()) {
   248             throw new Error("invalid diagnostics for source:\n" +
   249                 source.getCharContent(true) +
   250                 "\nFound error: " + diagChecker.errorFound +
   251                 "\nExpected error: " + rk.erroneous());
   252         }
   253     }
   255     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   257         boolean errorFound;
   259         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   260             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   261                 errorFound = true;
   262             }
   263         }
   264     }
   266 }

mercurial