aoqi@0: /* aoqi@0: * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * @test aoqi@0: * @bug 7115052 8003280 8006694 aoqi@0: * @summary Add lambda tests aoqi@0: * Add parser support for method references aoqi@0: * temporarily workaround combo tests are causing time out in several platforms aoqi@0: * @library ../lib aoqi@0: * @build JavacTestingAbstractThreadedTest aoqi@0: * @run main/othervm MethodReferenceParserTest aoqi@0: */ aoqi@0: aoqi@0: // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) aoqi@0: // see JDK-8006746 aoqi@0: aoqi@0: import java.net.URI; aoqi@0: import java.util.Arrays; aoqi@0: import javax.tools.Diagnostic; aoqi@0: import javax.tools.JavaFileObject; aoqi@0: import javax.tools.SimpleJavaFileObject; aoqi@0: import com.sun.source.util.JavacTask; aoqi@0: aoqi@0: public class MethodReferenceParserTest aoqi@0: extends JavacTestingAbstractThreadedTest aoqi@0: implements Runnable { aoqi@0: aoqi@0: enum ReferenceKind { aoqi@0: METHOD_REF("#Q::#Gm"), aoqi@0: CONSTRUCTOR_REF("#Q::#Gnew"), aoqi@0: FALSE_REF("min < max"), aoqi@0: ERR_SUPER("#Q::#Gsuper"), aoqi@0: ERR_METH0("#Q::#Gm()"), aoqi@0: ERR_METH1("#Q::#Gm(X)"), aoqi@0: ERR_CONSTR0("#Q::#Gnew()"), aoqi@0: ERR_CONSTR1("#Q::#Gnew(X)"); aoqi@0: aoqi@0: String referenceTemplate; aoqi@0: aoqi@0: ReferenceKind(String referenceTemplate) { aoqi@0: this.referenceTemplate = referenceTemplate; aoqi@0: } aoqi@0: aoqi@0: String getReferenceString(QualifierKind qk, GenericKind gk) { aoqi@0: return referenceTemplate aoqi@0: .replaceAll("#Q", qk.qualifier) aoqi@0: .replaceAll("#G", gk.typeParameters); aoqi@0: } aoqi@0: aoqi@0: boolean erroneous() { aoqi@0: switch (this) { aoqi@0: case ERR_SUPER: aoqi@0: case ERR_METH0: aoqi@0: case ERR_METH1: aoqi@0: case ERR_CONSTR0: aoqi@0: case ERR_CONSTR1: aoqi@0: return true; aoqi@0: default: return false; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: enum ContextKind { aoqi@0: ASSIGN("SAM s = #E;"), aoqi@0: METHOD("m(#E, i);"); aoqi@0: aoqi@0: String contextTemplate; aoqi@0: aoqi@0: ContextKind(String contextTemplate) { aoqi@0: this.contextTemplate = contextTemplate; aoqi@0: } aoqi@0: aoqi@0: String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk, aoqi@0: GenericKind gk, SubExprKind sk) { aoqi@0: return contextTemplate.replaceAll("#E", ek.expressionString(rk, qk, gk, sk)); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: enum GenericKind { aoqi@0: NONE(""), aoqi@0: ONE(""), aoqi@0: TWO(""); aoqi@0: aoqi@0: String typeParameters; aoqi@0: aoqi@0: GenericKind(String typeParameters) { aoqi@0: this.typeParameters = typeParameters; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: enum QualifierKind { aoqi@0: THIS("this"), aoqi@0: SUPER("super"), aoqi@0: NEW("new Foo()"), aoqi@0: METHOD("m()"), aoqi@0: FIELD("a.f"), aoqi@0: UBOUND_SIMPLE("A"), aoqi@0: UNBOUND_ARRAY1("int[]"), aoqi@0: UNBOUND_ARRAY2("A[][]"), aoqi@0: UNBOUND_GENERIC1("A"), aoqi@0: UNBOUND_GENERIC2("A"), aoqi@0: UNBOUND_GENERIC3("A"), aoqi@0: UNBOUND_GENERIC4("A"), aoqi@0: NESTED_GENERIC1("A, A>"), aoqi@0: NESTED_GENERIC2("A,A>, A,A>>"); aoqi@0: aoqi@0: String qualifier; aoqi@0: aoqi@0: QualifierKind(String qualifier) { aoqi@0: this.qualifier = qualifier; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: enum ExprKind { aoqi@0: NONE("#R::S"), aoqi@0: SINGLE_PAREN1("(#R#S)"), aoqi@0: SINGLE_PAREN2("(#R)#S"), aoqi@0: DOUBLE_PAREN1("((#R#S))"), aoqi@0: DOUBLE_PAREN2("((#R)#S)"), aoqi@0: DOUBLE_PAREN3("((#R))#S"); aoqi@0: aoqi@0: String expressionTemplate; aoqi@0: aoqi@0: ExprKind(String expressionTemplate) { aoqi@0: this.expressionTemplate = expressionTemplate; aoqi@0: } aoqi@0: aoqi@0: String expressionString(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) { aoqi@0: return expressionTemplate aoqi@0: .replaceAll("#R", rk.getReferenceString(qk, gk)) aoqi@0: .replaceAll("#S", sk.subExpression); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: enum SubExprKind { aoqi@0: NONE(""), aoqi@0: SELECT_FIELD(".f"), aoqi@0: SELECT_METHOD(".f()"), aoqi@0: SELECT_NEW(".new Foo()"), aoqi@0: POSTINC("++"), aoqi@0: POSTDEC("--"); aoqi@0: aoqi@0: String subExpression; aoqi@0: aoqi@0: SubExprKind(String subExpression) { aoqi@0: this.subExpression = subExpression; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public static void main(String... args) throws Exception { aoqi@0: for (ReferenceKind rk : ReferenceKind.values()) { aoqi@0: for (QualifierKind qk : QualifierKind.values()) { aoqi@0: for (GenericKind gk : GenericKind.values()) { aoqi@0: for (SubExprKind sk : SubExprKind.values()) { aoqi@0: for (ExprKind ek : ExprKind.values()) { aoqi@0: for (ContextKind ck : ContextKind.values()) { aoqi@0: pool.execute(new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck)); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: checkAfterExec(); aoqi@0: } aoqi@0: aoqi@0: ReferenceKind rk; aoqi@0: QualifierKind qk; aoqi@0: GenericKind gk; aoqi@0: SubExprKind sk; aoqi@0: ExprKind ek; aoqi@0: ContextKind ck; aoqi@0: JavaSource source; aoqi@0: DiagnosticChecker diagChecker; aoqi@0: aoqi@0: MethodReferenceParserTest(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk, ExprKind ek, ContextKind ck) { aoqi@0: this.rk = rk; aoqi@0: this.qk = qk; aoqi@0: this.gk = gk; aoqi@0: this.sk = sk; aoqi@0: this.ek = ek; aoqi@0: this.ck = ck; aoqi@0: this.source = new JavaSource(); aoqi@0: this.diagChecker = new DiagnosticChecker(); aoqi@0: } aoqi@0: aoqi@0: class JavaSource extends SimpleJavaFileObject { aoqi@0: aoqi@0: String template = "class Test {\n" + aoqi@0: " void test() {\n" + aoqi@0: " #C\n" + aoqi@0: " }" + aoqi@0: "}"; aoqi@0: aoqi@0: String source; aoqi@0: aoqi@0: public JavaSource() { aoqi@0: super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); aoqi@0: source = template.replaceAll("#C", ck.contextString(ek, rk, qk, gk, sk)); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public CharSequence getCharContent(boolean ignoreEncodingErrors) { aoqi@0: return source; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void run() { aoqi@0: JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, aoqi@0: null, null, Arrays.asList(source)); aoqi@0: try { aoqi@0: ct.parse(); aoqi@0: } catch (Throwable ex) { aoqi@0: processException(ex); aoqi@0: return; aoqi@0: } aoqi@0: check(); aoqi@0: } aoqi@0: aoqi@0: void check() { aoqi@0: checkCount.incrementAndGet(); aoqi@0: aoqi@0: if (diagChecker.errorFound != rk.erroneous()) { aoqi@0: throw new Error("invalid diagnostics for source:\n" + aoqi@0: source.getCharContent(true) + aoqi@0: "\nFound error: " + diagChecker.errorFound + aoqi@0: "\nExpected error: " + rk.erroneous()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static class DiagnosticChecker implements javax.tools.DiagnosticListener { aoqi@0: aoqi@0: boolean errorFound; aoqi@0: aoqi@0: public void report(Diagnostic diagnostic) { aoqi@0: if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { aoqi@0: errorFound = true; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: }