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