test/tools/javac/lambda/LambdaParserTest.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 2525
2eb010b6cb22
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

mcimadamore@1144 1 /*
vromero@1482 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
mcimadamore@1144 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@1144 4 *
mcimadamore@1144 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@1144 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@1144 7 * published by the Free Software Foundation.
mcimadamore@1144 8 *
mcimadamore@1144 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@1144 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@1144 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@1144 12 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@1144 13 * accompanied this code).
mcimadamore@1144 14 *
mcimadamore@1144 15 * You should have received a copy of the GNU General Public License version
mcimadamore@1144 16 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@1144 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@1144 18 *
mcimadamore@1144 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@1144 20 * or visit www.oracle.com if you need additional information or have any
mcimadamore@1144 21 * questions.
mcimadamore@1144 22 */
mcimadamore@1144 23
mcimadamore@1144 24 /*
mcimadamore@1144 25 * @test
vromero@1520 26 * @bug 7115050 8003280 8005852 8006694
mcimadamore@1415 27 * @summary Add lambda tests
mcimadamore@1415 28 * Add parser support for lambda expressions
vromero@1520 29 * temporarily workaround combo tests are causing time out in several platforms
vromero@1482 30 * @library ../lib
vromero@1482 31 * @build JavacTestingAbstractThreadedTest
vromero@1520 32 * @run main/othervm LambdaParserTest
mcimadamore@1144 33 */
mcimadamore@1144 34
vromero@1520 35 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
vromero@1520 36 // see JDK-8006746
vromero@1520 37
mcimadamore@1144 38 import java.net.URI;
mcimadamore@1144 39 import java.util.Arrays;
mcimadamore@1144 40 import javax.tools.Diagnostic;
mcimadamore@1144 41 import javax.tools.JavaFileObject;
mcimadamore@1144 42 import javax.tools.SimpleJavaFileObject;
vromero@1482 43 import com.sun.source.util.JavacTask;
mcimadamore@1144 44
vromero@1482 45 public class LambdaParserTest
vromero@1482 46 extends JavacTestingAbstractThreadedTest
vromero@1482 47 implements Runnable {
mcimadamore@1144 48
mcimadamore@1144 49 enum LambdaKind {
mcimadamore@1144 50 NILARY_EXPR("()->x"),
mcimadamore@1144 51 NILARY_STMT("()->{ return x; }"),
mcimadamore@1503 52 ONEARY_SHORT_EXPR("#PN->x"),
mcimadamore@1503 53 ONEARY_SHORT_STMT("#PN->{ return x; }"),
mcimadamore@1503 54 ONEARY_EXPR("(#M1 #T1 #PN)->x"),
mcimadamore@1503 55 ONEARY_STMT("(#M1 #T1 #PN)->{ return x; }"),
mcimadamore@1503 56 TWOARY_EXPR("(#M1 #T1 #PN, #M2 #T2 y)->x"),
mcimadamore@1503 57 TWOARY_STMT("(#M1 #T1 #PN, #M2 #T2 y)->{ return x; }");
mcimadamore@1144 58
mcimadamore@1144 59 String lambdaTemplate;
mcimadamore@1144 60
mcimadamore@1144 61 LambdaKind(String lambdaTemplate) {
mcimadamore@1144 62 this.lambdaTemplate = lambdaTemplate;
mcimadamore@1144 63 }
mcimadamore@1144 64
mcimadamore@1144 65 String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2,
mcimadamore@1503 66 ModifierKind mk1, ModifierKind mk2, LambdaParameterName pn) {
mcimadamore@1144 67 return lambdaTemplate.replaceAll("#M1", mk1.modifier)
mcimadamore@1144 68 .replaceAll("#M2", mk2.modifier)
mcimadamore@1144 69 .replaceAll("#T1", pk1.parameterType)
mcimadamore@1503 70 .replaceAll("#T2", pk2.parameterType)
mcimadamore@1503 71 .replaceAll("#PN", pn.nameStr);
mcimadamore@1144 72 }
mcimadamore@1144 73
mcimadamore@1144 74 int arity() {
mcimadamore@1144 75 switch (this) {
mcimadamore@1144 76 case NILARY_EXPR:
mcimadamore@1144 77 case NILARY_STMT: return 0;
mcimadamore@1144 78 case ONEARY_SHORT_EXPR:
mcimadamore@1144 79 case ONEARY_SHORT_STMT:
mcimadamore@1144 80 case ONEARY_EXPR:
mcimadamore@1144 81 case ONEARY_STMT: return 1;
mcimadamore@1144 82 case TWOARY_EXPR:
mcimadamore@1144 83 case TWOARY_STMT: return 2;
mcimadamore@1144 84 default: throw new AssertionError("Invalid lambda kind " + this);
mcimadamore@1144 85 }
mcimadamore@1144 86 }
mcimadamore@1144 87
mcimadamore@1144 88 boolean isShort() {
mcimadamore@1144 89 return this == ONEARY_SHORT_EXPR ||
mcimadamore@1144 90 this == ONEARY_SHORT_STMT;
mcimadamore@1144 91 }
mcimadamore@1144 92 }
mcimadamore@1144 93
mcimadamore@1503 94 enum LambdaParameterName {
mcimadamore@1503 95 IDENT("x"),
mcimadamore@1503 96 UNDERSCORE("_");
mcimadamore@1503 97
mcimadamore@1503 98 String nameStr;
mcimadamore@1503 99
mcimadamore@1503 100 LambdaParameterName(String nameStr) {
mcimadamore@1503 101 this.nameStr = nameStr;
mcimadamore@1503 102 }
mcimadamore@1503 103 }
mcimadamore@1503 104
mcimadamore@1144 105 enum LambdaParameterKind {
mcimadamore@1144 106 IMPLICIT(""),
mcimadamore@1144 107 EXPLIICT_SIMPLE("A"),
mcimadamore@1436 108 EXPLIICT_SIMPLE_ARR1("A[]"),
mcimadamore@1436 109 EXPLIICT_SIMPLE_ARR2("A[][]"),
mcimadamore@1144 110 EXPLICIT_VARARGS("A..."),
mcimadamore@1144 111 EXPLICIT_GENERIC1("A<X>"),
mcimadamore@1436 112 EXPLICIT_GENERIC2("A<? extends X, ? super Y>"),
mcimadamore@1436 113 EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>..."),
mcimadamore@1436 114 EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]"),
mcimadamore@1436 115 EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]");
mcimadamore@1144 116
mcimadamore@1144 117 String parameterType;
mcimadamore@1144 118
mcimadamore@1144 119 LambdaParameterKind(String parameterType) {
mcimadamore@1144 120 this.parameterType = parameterType;
mcimadamore@1144 121 }
mcimadamore@1144 122
mcimadamore@1144 123 boolean explicit() {
mcimadamore@1144 124 return this != IMPLICIT;
mcimadamore@1144 125 }
mcimadamore@1436 126
mcimadamore@1436 127 boolean isVarargs() {
mcimadamore@1436 128 return this == EXPLICIT_VARARGS ||
mcimadamore@1436 129 this == EXPLICIT_GENERIC2_VARARGS;
mcimadamore@1436 130 }
mcimadamore@1144 131 }
mcimadamore@1144 132
mcimadamore@1144 133 enum ModifierKind {
mcimadamore@1144 134 NONE(""),
mcimadamore@1144 135 FINAL("final"),
mcimadamore@1144 136 PUBLIC("public");
mcimadamore@1144 137
mcimadamore@1144 138 String modifier;
mcimadamore@1144 139
mcimadamore@1144 140 ModifierKind(String modifier) {
mcimadamore@1144 141 this.modifier = modifier;
mcimadamore@1144 142 }
mcimadamore@1144 143
mcimadamore@1144 144 boolean compatibleWith(LambdaParameterKind pk) {
mcimadamore@1144 145 switch (this) {
mcimadamore@1144 146 case PUBLIC: return false;
mcimadamore@1144 147 case FINAL: return pk != LambdaParameterKind.IMPLICIT;
mcimadamore@1144 148 case NONE: return true;
mcimadamore@1144 149 default: throw new AssertionError("Invalid modifier kind " + this);
mcimadamore@1144 150 }
mcimadamore@1144 151 }
mcimadamore@1144 152 }
mcimadamore@1144 153
mcimadamore@1144 154 enum ExprKind {
mcimadamore@1144 155 NONE("#L#S"),
mcimadamore@1144 156 SINGLE_PAREN1("(#L#S)"),
mcimadamore@1144 157 SINGLE_PAREN2("(#L)#S"),
mcimadamore@1144 158 DOUBLE_PAREN1("((#L#S))"),
mcimadamore@1144 159 DOUBLE_PAREN2("((#L)#S)"),
mcimadamore@1144 160 DOUBLE_PAREN3("((#L))#S");
mcimadamore@1144 161
mcimadamore@1144 162 String expressionTemplate;
mcimadamore@1144 163
mcimadamore@1144 164 ExprKind(String expressionTemplate) {
mcimadamore@1144 165 this.expressionTemplate = expressionTemplate;
mcimadamore@1144 166 }
mcimadamore@1144 167
mcimadamore@1144 168 String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2,
mcimadamore@1503 169 ModifierKind mk1, ModifierKind mk2, LambdaKind lk, LambdaParameterName pn, SubExprKind sk) {
mcimadamore@1503 170 return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2, pn))
mcimadamore@1144 171 .replaceAll("#S", sk.subExpression);
mcimadamore@1144 172 }
mcimadamore@1144 173 }
mcimadamore@1144 174
mcimadamore@1144 175 enum SubExprKind {
mcimadamore@1144 176 NONE(""),
mcimadamore@1144 177 SELECT_FIELD(".f"),
mcimadamore@1144 178 SELECT_METHOD(".f()"),
mcimadamore@1144 179 SELECT_NEW(".new Foo()"),
mcimadamore@1144 180 POSTINC("++"),
mcimadamore@1144 181 POSTDEC("--");
mcimadamore@1144 182
mcimadamore@1144 183 String subExpression;
mcimadamore@1144 184
mcimadamore@1144 185 SubExprKind(String subExpression) {
mcimadamore@1144 186 this.subExpression = subExpression;
mcimadamore@1144 187 }
mcimadamore@1144 188 }
mcimadamore@1144 189
mcimadamore@1144 190 public static void main(String... args) throws Exception {
mcimadamore@1144 191 for (LambdaKind lk : LambdaKind.values()) {
mcimadamore@1503 192 for (LambdaParameterName pn : LambdaParameterName.values()) {
mcimadamore@1503 193 for (LambdaParameterKind pk1 : LambdaParameterKind.values()) {
mcimadamore@1503 194 if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT)
vromero@1482 195 continue;
mcimadamore@1503 196 for (LambdaParameterKind pk2 : LambdaParameterKind.values()) {
mcimadamore@1503 197 if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT)
vromero@1482 198 continue;
mcimadamore@1503 199 for (ModifierKind mk1 : ModifierKind.values()) {
mcimadamore@1503 200 if (mk1 != ModifierKind.NONE && lk.isShort())
vromero@1482 201 continue;
mcimadamore@1503 202 if (lk.arity() < 1 && mk1 != ModifierKind.NONE)
mcimadamore@1503 203 continue;
mcimadamore@1503 204 for (ModifierKind mk2 : ModifierKind.values()) {
mcimadamore@1503 205 if (lk.arity() < 2 && mk2 != ModifierKind.NONE)
mcimadamore@1503 206 continue;
mcimadamore@1503 207 for (SubExprKind sk : SubExprKind.values()) {
mcimadamore@1503 208 for (ExprKind ek : ExprKind.values()) {
mcimadamore@1503 209 pool.execute(
mcimadamore@1503 210 new LambdaParserTest(pk1, pk2, mk1,
mcimadamore@1503 211 mk2, lk, sk, ek, pn));
mcimadamore@1503 212 }
mcimadamore@1144 213 }
mcimadamore@1144 214 }
mcimadamore@1144 215 }
mcimadamore@1144 216 }
mcimadamore@1144 217 }
mcimadamore@1144 218 }
mcimadamore@1144 219 }
vromero@1482 220
vromero@1482 221 checkAfterExec();
mcimadamore@1144 222 }
mcimadamore@1144 223
mcimadamore@1144 224 LambdaParameterKind pk1;
mcimadamore@1144 225 LambdaParameterKind pk2;
mcimadamore@1144 226 ModifierKind mk1;
mcimadamore@1144 227 ModifierKind mk2;
mcimadamore@1144 228 LambdaKind lk;
mcimadamore@1503 229 LambdaParameterName pn;
mcimadamore@1144 230 SubExprKind sk;
mcimadamore@1144 231 ExprKind ek;
mcimadamore@1144 232 JavaSource source;
mcimadamore@1144 233 DiagnosticChecker diagChecker;
mcimadamore@1144 234
vromero@1482 235 LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2,
vromero@1482 236 ModifierKind mk1, ModifierKind mk2, LambdaKind lk,
mcimadamore@1503 237 SubExprKind sk, ExprKind ek, LambdaParameterName pn) {
mcimadamore@1144 238 this.pk1 = pk1;
mcimadamore@1144 239 this.pk2 = pk2;
mcimadamore@1144 240 this.mk1 = mk1;
mcimadamore@1144 241 this.mk2 = mk2;
mcimadamore@1144 242 this.lk = lk;
mcimadamore@1503 243 this.pn = pn;
mcimadamore@1144 244 this.sk = sk;
mcimadamore@1144 245 this.ek = ek;
mcimadamore@1144 246 this.source = new JavaSource();
mcimadamore@1144 247 this.diagChecker = new DiagnosticChecker();
mcimadamore@1144 248 }
mcimadamore@1144 249
mcimadamore@1144 250 class JavaSource extends SimpleJavaFileObject {
mcimadamore@1144 251
mcimadamore@1144 252 String template = "class Test {\n" +
mcimadamore@1144 253 " SAM s = #E;\n" +
mcimadamore@1144 254 "}";
mcimadamore@1144 255
mcimadamore@1144 256 String source;
mcimadamore@1144 257
mcimadamore@1144 258 public JavaSource() {
mcimadamore@1144 259 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
vromero@1482 260 source = template.replaceAll("#E",
mcimadamore@1503 261 ek.expressionString(pk1, pk2, mk1, mk2, lk, pn, sk));
mcimadamore@1144 262 }
mcimadamore@1144 263
mcimadamore@1144 264 @Override
mcimadamore@1144 265 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@1144 266 return source;
mcimadamore@1144 267 }
mcimadamore@1144 268 }
mcimadamore@1144 269
vromero@1482 270 public void run() {
vromero@1482 271 JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
mcimadamore@1415 272 null, null, Arrays.asList(source));
mcimadamore@1144 273 try {
mcimadamore@1144 274 ct.parse();
mcimadamore@1144 275 } catch (Throwable ex) {
vromero@1482 276 processException(ex);
vromero@1482 277 return;
mcimadamore@1144 278 }
mcimadamore@1144 279 check();
mcimadamore@1144 280 }
mcimadamore@1144 281
mcimadamore@1144 282 void check() {
vromero@1482 283 checkCount.incrementAndGet();
mcimadamore@1144 284
mcimadamore@1144 285 boolean errorExpected = (lk.arity() > 0 && !mk1.compatibleWith(pk1)) ||
mcimadamore@1144 286 (lk.arity() > 1 && !mk2.compatibleWith(pk2));
mcimadamore@1144 287
mcimadamore@1144 288 if (lk.arity() == 2 &&
mcimadamore@1144 289 (pk1.explicit() != pk2.explicit() ||
mcimadamore@1436 290 pk1.isVarargs())) {
mcimadamore@1144 291 errorExpected = true;
mcimadamore@1144 292 }
mcimadamore@1144 293
mcimadamore@1503 294 errorExpected |= pn == LambdaParameterName.UNDERSCORE &&
mcimadamore@1503 295 lk.arity() > 0;
mcimadamore@1503 296
mcimadamore@1144 297 if (errorExpected != diagChecker.errorFound) {
mcimadamore@1144 298 throw new Error("invalid diagnostics for source:\n" +
mcimadamore@1144 299 source.getCharContent(true) +
mcimadamore@1144 300 "\nFound error: " + diagChecker.errorFound +
mcimadamore@1144 301 "\nExpected error: " + errorExpected);
mcimadamore@1144 302 }
mcimadamore@1144 303 }
mcimadamore@1144 304
vromero@1482 305 static class DiagnosticChecker
vromero@1482 306 implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@1144 307
mcimadamore@1144 308 boolean errorFound;
mcimadamore@1144 309
mcimadamore@1144 310 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@1144 311 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
mcimadamore@1144 312 errorFound = true;
mcimadamore@1144 313 }
mcimadamore@1144 314 }
mcimadamore@1144 315 }
vromero@1482 316
mcimadamore@1144 317 }

mercurial