LambdaParserTest.java revision 3019:176472b94f2e
1/* 2 * Copyright (c) 2011, 2015, 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 */ 23 24/* 25 * @test 26 * @bug 7115050 8003280 8005852 8006694 8129962 27 * @summary Add lambda tests 28 * Add parser support for lambda expressions 29 * temporarily workaround combo tests are causing time out in several platforms 30 * @library /tools/javac/lib 31 * @modules jdk.compiler/com.sun.tools.javac.api 32 * jdk.compiler/com.sun.tools.javac.code 33 * jdk.compiler/com.sun.tools.javac.comp 34 * jdk.compiler/com.sun.tools.javac.main 35 * jdk.compiler/com.sun.tools.javac.tree 36 * jdk.compiler/com.sun.tools.javac.util 37 * @build combo.ComboTestHelper 38 39 * @run main LambdaParserTest 40 */ 41 42import java.io.IOException; 43 44import combo.ComboInstance; 45import combo.ComboParameter; 46import combo.ComboTask.Result; 47import combo.ComboTestHelper; 48 49public class LambdaParserTest extends ComboInstance<LambdaParserTest> { 50 51 enum LambdaKind implements ComboParameter { 52 NILARY_EXPR("()->x"), 53 NILARY_STMT("()->{ return x; }"), 54 ONEARY_SHORT_EXPR("#{NAME}->x"), 55 ONEARY_SHORT_STMT("#{NAME}->{ return x; }"), 56 ONEARY_EXPR("(#{MOD[0]} #{TYPE[0]} #{NAME})->x"), 57 ONEARY_STMT("(#{MOD[0]} #{TYPE[0]} #{NAME})->{ return x; }"), 58 TWOARY_EXPR("(#{MOD[0]} #{TYPE[0]} #{NAME}, #{MOD[1]} #{TYPE[1]} y)->x"), 59 TWOARY_STMT("(#{MOD[0]} #{TYPE[0]} #{NAME}, #{MOD[1]} #{TYPE[1]} y)->{ return x; }"); 60 61 String lambdaTemplate; 62 63 LambdaKind(String lambdaTemplate) { 64 this.lambdaTemplate = lambdaTemplate; 65 } 66 67 @Override 68 public String expand(String optParameter) { 69 return lambdaTemplate; 70 } 71 72 int arity() { 73 switch (this) { 74 case NILARY_EXPR: 75 case NILARY_STMT: return 0; 76 case ONEARY_SHORT_EXPR: 77 case ONEARY_SHORT_STMT: 78 case ONEARY_EXPR: 79 case ONEARY_STMT: return 1; 80 case TWOARY_EXPR: 81 case TWOARY_STMT: return 2; 82 default: throw new AssertionError("Invalid lambda kind " + this); 83 } 84 } 85 86 boolean isShort() { 87 return this == ONEARY_SHORT_EXPR || 88 this == ONEARY_SHORT_STMT; 89 } 90 } 91 92 enum LambdaParameterName implements ComboParameter { 93 IDENT("x"), 94 UNDERSCORE("_"); 95 96 String nameStr; 97 98 LambdaParameterName(String nameStr) { 99 this.nameStr = nameStr; 100 } 101 102 @Override 103 public String expand(String optParameter) { 104 return nameStr; 105 } 106 } 107 108 enum LambdaParameterKind implements ComboParameter { 109 IMPLICIT(""), 110 EXPLIICT_SIMPLE("A"), 111 EXPLIICT_SIMPLE_ARR1("A[]"), 112 EXPLIICT_SIMPLE_ARR2("A[][]"), 113 EXPLICIT_VARARGS("A..."), 114 EXPLICIT_GENERIC1("A<X>"), 115 EXPLICIT_GENERIC2("A<? extends X, ? super Y>"), 116 EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>..."), 117 EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]"), 118 EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]"); 119 120 String parameterType; 121 122 LambdaParameterKind(String parameterType) { 123 this.parameterType = parameterType; 124 } 125 126 boolean explicit() { 127 return this != IMPLICIT; 128 } 129 130 boolean isVarargs() { 131 return this == EXPLICIT_VARARGS || 132 this == EXPLICIT_GENERIC2_VARARGS; 133 } 134 135 @Override 136 public String expand(String optParameter) { 137 return parameterType; 138 } 139 } 140 141 enum ModifierKind implements ComboParameter { 142 NONE(""), 143 FINAL("final"), 144 PUBLIC("public"); 145 146 String modifier; 147 148 ModifierKind(String modifier) { 149 this.modifier = modifier; 150 } 151 152 boolean compatibleWith(LambdaParameterKind pk) { 153 switch (this) { 154 case PUBLIC: return false; 155 case FINAL: return pk != LambdaParameterKind.IMPLICIT; 156 case NONE: return true; 157 default: throw new AssertionError("Invalid modifier kind " + this); 158 } 159 } 160 161 @Override 162 public String expand(String optParameter) { 163 return modifier; 164 } 165 } 166 167 enum ExprKind implements ComboParameter { 168 NONE("#{LAMBDA}#{SUBEXPR}"), 169 SINGLE_PAREN1("(#{LAMBDA}#{SUBEXPR})"), 170 SINGLE_PAREN2("(#{LAMBDA})#{SUBEXPR}"), 171 DOUBLE_PAREN1("((#{LAMBDA}#{SUBEXPR}))"), 172 DOUBLE_PAREN2("((#{LAMBDA})#{SUBEXPR})"), 173 DOUBLE_PAREN3("((#{LAMBDA}))#{SUBEXPR}"); 174 175 String expressionTemplate; 176 177 ExprKind(String expressionTemplate) { 178 this.expressionTemplate = expressionTemplate; 179 } 180 181 @Override 182 public String expand(String optParameter) { 183 return expressionTemplate; 184 } 185 } 186 187 enum SubExprKind implements ComboParameter { 188 NONE(""), 189 SELECT_FIELD(".f"), 190 SELECT_METHOD(".f()"), 191 SELECT_NEW(".new Foo()"), 192 POSTINC("++"), 193 POSTDEC("--"); 194 195 String subExpression; 196 197 SubExprKind(String subExpression) { 198 this.subExpression = subExpression; 199 } 200 201 @Override 202 public String expand(String optParameter) { 203 return subExpression; 204 } 205 } 206 207 public static void main(String... args) throws Exception { 208 new ComboTestHelper<LambdaParserTest>() 209 .withFilter(LambdaParserTest::redundantTestFilter) 210 .withFilter(LambdaParserTest::badImplicitFilter) 211 .withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values()) 212 .withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.values()) 213 .withArrayDimension("TYPE", (x, type, idx) -> x.pks[idx] = type, 2, LambdaParameterKind.values()) 214 .withArrayDimension("MOD", (x, mod, idx) -> x.mks[idx] = mod, 2, ModifierKind.values()) 215 .withDimension("EXPR", ExprKind.values()) 216 .withDimension("SUBEXPR", SubExprKind.values()) 217 .run(LambdaParserTest::new); 218 } 219 220 LambdaParameterKind[] pks = new LambdaParameterKind[2]; 221 ModifierKind[] mks = new ModifierKind[2]; 222 LambdaKind lk; 223 LambdaParameterName pn; 224 225 boolean badImplicitFilter() { 226 return !(mks[0] != ModifierKind.NONE && lk.isShort()); 227 } 228 229 boolean redundantTestFilter() { 230 for (int i = lk.arity(); i < mks.length ; i++) { 231 if (mks[i].ordinal() != 0) { 232 return false; 233 } 234 } 235 for (int i = lk.arity(); i < pks.length ; i++) { 236 if (pks[i].ordinal() != 0) { 237 return false; 238 } 239 } 240 return true; 241 } 242 243 String template = "class Test {\n" + 244 " SAM s = #{EXPR};\n" + 245 "}"; 246 247 @Override 248 public void doWork() throws IOException { 249 check(newCompilationTask() 250 .withSourceFromTemplate(template) 251 .parse()); 252 } 253 254 void check(Result<?> res) { 255 boolean errorExpected = (lk.arity() > 0 && !mks[0].compatibleWith(pks[0])) || 256 (lk.arity() > 1 && !mks[1].compatibleWith(pks[1])); 257 258 if (lk.arity() == 2 && 259 (pks[0].explicit() != pks[1].explicit() || 260 pks[0].isVarargs())) { 261 errorExpected = true; 262 } 263 264 errorExpected |= pn == LambdaParameterName.UNDERSCORE && 265 lk.arity() > 0; 266 267 if (errorExpected != res.hasErrors()) { 268 fail("invalid diagnostics for source:\n" + 269 res.compilationInfo() + 270 "\nFound error: " + res.hasErrors() + 271 "\nExpected error: " + errorExpected); 272 } 273 } 274} 275