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