aoqi@0: /* aoqi@0: * Copyright (c) 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 8023835 aoqi@0: * @summary Verify that implicit type of lambda parameter is correctly attributed aoqi@0: * in Scope aoqi@0: * @run main ScopeTest aoqi@0: */ aoqi@0: aoqi@0: import com.sun.source.tree.CompilationUnitTree; aoqi@0: import com.sun.source.tree.MemberSelectTree; aoqi@0: import com.sun.source.tree.Scope; aoqi@0: import com.sun.source.util.JavacTask; aoqi@0: import com.sun.source.util.TreePath; aoqi@0: import com.sun.source.util.TreePathScanner; aoqi@0: import com.sun.source.util.Trees; aoqi@0: import com.sun.tools.javac.api.JavacTaskImpl; aoqi@0: import com.sun.tools.javac.api.JavacTool; aoqi@0: import com.sun.tools.javac.model.JavacTypes; aoqi@0: import java.io.IOException; aoqi@0: import java.net.URI; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.Collections; aoqi@0: import javax.lang.model.element.Element; aoqi@0: import javax.lang.model.type.TypeMirror; aoqi@0: import javax.lang.model.util.Types; aoqi@0: import javax.tools.JavaFileObject; aoqi@0: import javax.tools.JavaFileObject.Kind; aoqi@0: import javax.tools.SimpleJavaFileObject; aoqi@0: aoqi@0: public class ScopeTest { aoqi@0: aoqi@0: private static final String SOURCE_CODE = aoqi@0: "public class Test {\n" + aoqi@0: " private static void test() {\n" + aoqi@0: " InvokeOn f = null;\n" + aoqi@0: " f.run(x -> { x.correct(); });\n" + aoqi@0: " }\n" + aoqi@0: " public static final class FooBar {\n" + aoqi@0: " public void dontRun() { }\n" + aoqi@0: " }\n" + aoqi@0: "}\n" + aoqi@0: "class InvokeOn {\n" + aoqi@0: " public void run(I i) { }\n" + aoqi@0: "}\n" + aoqi@0: "class FooBar {\n" + aoqi@0: " public void correct() { }\n" + aoqi@0: "}\n" + aoqi@0: "interface I {\n" + aoqi@0: " public void run(FooBar f);\n" + aoqi@0: "}"; aoqi@0: aoqi@0: public static void main(String... args) throws Exception { aoqi@0: verifyLambdaScopeCorrect(""); aoqi@0: verifyLambdaScopeCorrect("package test;"); aoqi@0: } aoqi@0: aoqi@0: private static void verifyLambdaScopeCorrect(final String packageClause) throws Exception { aoqi@0: JavacTool tool = JavacTool.create(); aoqi@0: JavaFileObject source = new SimpleJavaFileObject(URI.create("mem://Test.java"), Kind.SOURCE) { aoqi@0: @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { aoqi@0: return packageClause + SOURCE_CODE; aoqi@0: } aoqi@0: @Override public boolean isNameCompatible(String simpleName, Kind kind) { aoqi@0: return true; aoqi@0: } aoqi@0: }; aoqi@0: Iterable fos = Collections.singletonList(source); aoqi@0: JavacTask task = tool.getTask(null, null, null, new ArrayList(), null, fos); aoqi@0: final Types types = JavacTypes.instance(((JavacTaskImpl) task).getContext()); aoqi@0: final Trees trees = Trees.instance(task); aoqi@0: CompilationUnitTree cu = task.parse().iterator().next(); aoqi@0: aoqi@0: task.analyze(); aoqi@0: aoqi@0: new TreePathScanner() { aoqi@0: @Override public Void visitMemberSelect(MemberSelectTree node, Void p) { aoqi@0: if (node.getIdentifier().contentEquals("correct")) { aoqi@0: TypeMirror xType = trees.getTypeMirror(new TreePath(getCurrentPath(), node.getExpression())); aoqi@0: Scope scope = trees.getScope(getCurrentPath()); aoqi@0: for (Element l : scope.getLocalElements()) { aoqi@0: if (!l.getSimpleName().contentEquals("x")) continue; aoqi@0: if (!types.isSameType(xType, l.asType())) { aoqi@0: throw new IllegalStateException("Incorrect variable type in scope: " + l.asType() + "; should be: " + xType); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: return super.visitMemberSelect(node, p); aoqi@0: } aoqi@0: }.scan(cu, null); aoqi@0: } aoqi@0: }