OpenJDK / lambda / lambda / langtools
changeset 855:9a616df38d88
Added basic support for constructor references.
Syntax is as follows:
ClassName [optionalTypeArgs] '#' 'new' [optionalArgs]
Examples:
Foo#new -> (*)Foo [most specific constructor]
Foo#new() -> ()Foo
Foo#new("Hello!") -> (String)Foo
Foo<String>#new("Hello!") -> (String)Foo<String>
author | mcimadamore |
---|---|
date | Mon, 17 Jan 2011 14:34:40 +0000 |
parents | 89631f9e86b7 |
children | a953c0c02c7c |
files | src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Lower.java src/share/classes/com/sun/tools/javac/parser/JavacParser.java test/tools/javac/lambda/MethodReference17.java test/tools/javac/lambda/MethodReference18.java test/tools/javac/lambda/MethodReference19.java test/tools/javac/lambda/MethodReference20.java test/tools/javac/lambda/MethodReference20.out |
diffstat | 8 files changed, 287 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jan 06 13:19:18 2011 +0000 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Jan 17 14:34:40 2011 +0000 @@ -2751,6 +2751,7 @@ Symbol sym = null; Type owntype = null; switch (tree.mode) { + case NEW: case INVOKE: JCMethodInvocation apply = (JCMethodInvocation) expr; Type mtype = attribExpr(apply, localEnv); @@ -2799,11 +2800,14 @@ Type mtype = tree.meth.type; List<Type> args = mtype.getParameterTypes(); if (!msym.isStatic() && + !msym.isConstructor() && TreeInfo.isStaticSelector(base, names)) { args = args.prepend(base.type); } return new FunctionType(args, - mtype.getReturnType(), + msym.isConstructor() ? + base.type : + mtype.getReturnType(), mtype.getThrownTypes(), syms.methodHandleType.tsym); }
--- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Jan 06 13:19:18 2011 +0000 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Mon Jan 17 14:34:40 2011 +0000 @@ -2896,7 +2896,8 @@ @Override public void visitReference(JCMemberReference tree) { if (tree.expr.getTag() != JCTree.APPLY || - tree.getMode() != ReferenceMode.INVOKE) { + !(tree.getMode() == ReferenceMode.INVOKE || + tree.getMode() == ReferenceMode.NEW)) { throw new AssertionError(); } JCMethodInvocation apply = (JCMethodInvocation)tree.expr;
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Jan 06 13:19:18 2011 +0000 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Jan 17 14:34:40 2011 +0000 @@ -1593,7 +1593,9 @@ /** * MemberReferenceSuffix = "#" Ident + * | "#" "new" * | "#" [TypeArguments] Ident MethodParameterTypes + * | "#" [TypeArguments] "new" MethodParameterTypes */ JCExpression memberReferenceSuffix(JCExpression t) { int pos1 = S.pos(); @@ -1608,7 +1610,17 @@ if (S.token() == LT) { typeArgs = typeArguments(); } - t = toP(F.at(pos1).Select(t, ident())); + Name refName = null; + ReferenceMode refMode = null; + if (S.token() == NEW) { + refMode = ReferenceMode.NEW; + refName = names.init; + S.nextToken(); + } else { + refMode = ReferenceMode.INVOKE; + refName = ident(); + } + t = toP(F.at(pos1).Select(t, refName)); int pos2 = S.pos(); if (S.token() == LPAREN) { List<JCExpression> types = methodParameterTypes(); @@ -1617,7 +1629,7 @@ else { t = toP(F.at(pos2).Apply(typeArgs, t, null, true)); } - return toP(F.at(t.getStartPosition()).Reference(ReferenceMode.INVOKE, t)); + return toP(F.at(t.getStartPosition()).Reference(refMode, t)); } /** MethodParameterTypes = "(" [ typeList ] ")"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference17.java Mon Jan 17 14:34:40 2011 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011, 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 + * @summary basic test for constructor references + * @author Maurizio Cimadamore + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles MethodReference17 + */ + +public class MethodReference17 { + + static void assertTrue(boolean cond) { + assertionCount++; + if (!cond) + throw new AssertionError(); + } + + static int assertionCount = 0; + + MethodReference17() { + assertTrue(true); + } + + interface SAM1 { + MethodReference17 m(); + } + + static abstract class SAM2 { + abstract MethodReference17 m(); + } + + static void test1(SAM1 s1) { + s1.m(); + } + + static void test2(SAM2 s2) { + s2.m(); + } + + public static void main(String[] args) { + SAM1 s1 = MethodReference17#new; + s1.m(); + SAM2 s2 = MethodReference17#new; + s2.m(); + test1(MethodReference17#new); + test2(MethodReference17#new); + assertTrue(assertionCount == 4); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference18.java Mon Jan 17 14:34:40 2011 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011, 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 + * @summary basic test for constructor references + * @author Maurizio Cimadamore + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles MethodReference18 + */ + +public class MethodReference18 { + + static void assertTrue(boolean cond) { + assertionCount++; + if (!cond) + throw new AssertionError(); + } + + static int assertionCount = 0; + + MethodReference18(Object o) { + assertTrue(true); + } + + MethodReference18(Number n) { + assertTrue(false); + } + + interface SAM1 { + MethodReference18 m(Object o); + } + + static abstract class SAM2 { + abstract MethodReference18 m(Object o); + } + + static void test1(SAM1 s1, Object arg) { + s1.m(arg); + } + + static void test2(SAM2 s2, Object arg) { + s2.m(arg); + } + + public static void main(String[] args) { + SAM1 s1 = MethodReference18#new(Object); + s1.m(""); + SAM2 s2 = MethodReference18#new(Object); + s2.m(""); + test1(MethodReference18#new(Object), ""); + test2(MethodReference18#new(Object), ""); + assertTrue(assertionCount == 4); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference19.java Mon Jan 17 14:34:40 2011 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011, 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 + * @summary basic test for constructor references and generic classes + * @author Maurizio Cimadamore + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles MethodReference19 + */ + +public class MethodReference19<X> { + + static void assertTrue(boolean cond) { + assertionCount++; + if (!cond) + throw new AssertionError(); + } + + static int assertionCount = 0; + + MethodReference19(X x) { + assertTrue(true); + } + + interface SAM1<Z> { + MethodReference19<Z> m(Z z); + } + + static abstract class SAM2<Z> { + abstract MethodReference19<Z> m(Z z); + } + + static <Y> void test1(SAM1<Y> s1, Y arg) { + s1.m(arg); + } + + static <Y> void test2(SAM2<Y> s2, Y arg) { + s2.m(arg); + } + + public static void main(String[] args) { + SAM1<String> s1 = MethodReference19<String>#new; + s1.m(""); + SAM2<String> s2 = MethodReference19<String>#new; + s2.m(""); + test1(MethodReference19<String>#new, ""); + test2(MethodReference19<String>#new, ""); + assertTrue(assertionCount == 4); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference20.java Mon Jan 17 14:34:40 2011 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011, 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 + * @summary basic test for constructor references and generic classes + * @author Maurizio Cimadamore + * @compile/fail/ref=MethodReference20.out -XDrawDiagnostics MethodReference20.java + */ + +class MethodReference20<X> { + + MethodReference20(X x) { } + + interface SAM<Z> { + MethodReference20<Z> m(Z z); + } + + static void test(SAM<Integer> s) { } + + public static void main(String[] args) { + SAM<Integer> s1 = MethodReference20<String>#new; + SAM<Integer> s2 = MethodReference20<String>#new(Integer); + test(MethodReference20<String>#new); + test(MethodReference20<String>#new(Integer)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReference20.out Mon Jan 17 14:34:40 2011 +0000 @@ -0,0 +1,5 @@ +MethodReference20.java:42:27: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.incompatible.target.in.lambda.conv: m, kindname.interface, MethodReference20.SAM)), #MethodReference20<java.lang.String>(java.lang.String), MethodReference20.SAM<java.lang.Integer> +MethodReference20.java:43:53: compiler.err.cant.apply.symbol.1: kindname.constructor, MethodReference20, java.lang.String, java.lang.Integer, kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists: java.lang.Integer, java.lang.String, null) +MethodReference20.java:44:9: compiler.err.cant.apply.symbol.1: kindname.method, test, MethodReference20.SAM<java.lang.Integer>, #MethodReference20<java.lang.String>(java.lang.String), kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists.1: #MethodReference20<java.lang.String>(java.lang.String), MethodReference20.SAM<java.lang.Integer>, (compiler.misc.incompatible.target.in.lambda.conv: m, kindname.interface, MethodReference20.SAM)) +MethodReference20.java:45:40: compiler.err.cant.apply.symbol.1: kindname.constructor, MethodReference20, java.lang.String, java.lang.Integer, kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists: java.lang.Integer, java.lang.String, null) +4 errors