### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.ui.tests diff --git ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java index 0aad318..5aba5f1 100644 --- ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java +++ ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java @@ -59,6 +59,7 @@ return new Java18ProjectTestSetup(test); } + @Override protected void setUp() throws Exception { Hashtable options= TestOptions.getDefaultOptions(); options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE); @@ -74,6 +75,7 @@ fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src"); } + @Override protected void tearDown() throws Exception { JavaProjectHelper.clear(fJProject1, Java18ProjectTestSetup.getDefaultClasspath()); } @@ -930,6 +932,550 @@ assertExpectedExistInProposals(proposals, new String[] { expected1 }); } + // Bug 421479 + public void testConvertToLambda19() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func2 {\n"); + buf.append(" enum En {\n"); + buf.append(" A, B;\n"); + buf.append(" enum COLOR {\n"); + buf.append(" D, E\n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append(" void foo();\n"); + buf.append("\n"); + buf.append(" String NAME = \"\";\n"); + buf.append("\n"); + buf.append(" static String staticName() {\n"); + buf.append(" return NAME;\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test2 {\n"); + buf.append(" void bar() {\n"); + buf.append(" Func2 f = new Func2() {\n"); + buf.append(" @Override\n"); + buf.append(" public void foo() {\n"); + buf.append(" System.out.println(NAME);\n"); + buf.append(" System.out.println(Func2.NAME);\n"); + buf.append(" System.out.println(En.A);\n"); + buf.append(" System.out.println(Func2.En.A);\n"); + buf.append(" System.out.println(En.COLOR.D);\n"); + buf.append(" System.out.println(Func2.En.COLOR.D);\n"); + buf.append(" System.out.println(Test2.this);\n"); + buf.append(" bar();\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("Func2.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n\n"); + buf.append("import test1.Func2.En;\n\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func2 {\n"); + buf.append(" enum En {\n"); + buf.append(" A, B;\n"); + buf.append(" enum COLOR {\n"); + buf.append(" D, E\n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append(" void foo();\n"); + buf.append("\n"); + buf.append(" String NAME = \"\";\n"); + buf.append("\n"); + buf.append(" static String staticName() {\n"); + buf.append(" return NAME;\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test2 {\n"); + buf.append(" void bar() {\n"); + buf.append(" Func2 f = () -> {\n"); + buf.append(" System.out.println(Func2.NAME);\n"); + buf.append(" System.out.println(Func2.NAME);\n"); + buf.append(" System.out.println(Func2.En.A);\n"); + buf.append(" System.out.println(Func2.En.A);\n"); + buf.append(" System.out.println(En.COLOR.D);\n"); + buf.append(" System.out.println(Func2.En.COLOR.D);\n"); + buf.append(" System.out.println(Test2.this);\n"); + buf.append(" bar();\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + // Bug 421479 + public void testConvertToLambda20() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("interface Func {\n"); + buf.append(" void go();\n"); + buf.append(" String NAME = Func.class.getName();\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("public class Test {\n"); + buf.append(" void foo() {\n"); + buf.append(" Func f= new Func() {\n"); + buf.append(" @Override\n"); + buf.append(" public void go() {\n"); + buf.append(" System.out.println(NAME);\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("Test.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("interface Func {\n"); + buf.append(" void go();\n"); + buf.append(" String NAME = Func.class.getName();\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("public class Test {\n"); + buf.append(" void foo() {\n"); + buf.append(" Func f= () -> System.out.println(Func.NAME);\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + // Bug 421479 + public void testConvertToLambda21() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import test1.Func2.En.COLOR;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func2 {\n"); + buf.append(" enum En {\n"); + buf.append(" A, B;\n"); + buf.append(" enum COLOR {\n"); + buf.append(" D, E\n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append(" void foo();\n"); + buf.append("\n"); + buf.append(" String NAME = \"\";\n"); + buf.append("\n"); + buf.append(" static String staticName() {\n"); + buf.append(" return NAME;\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test2 {\n"); + buf.append(" void bar() {\n"); + buf.append(" Func2 f = new Func2() {\n"); + buf.append(" @Override\n"); + buf.append(" public void foo() {\n"); + buf.append(" System.out.println(COLOR.D);\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("Func2.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import test1.Func2.En.COLOR;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func2 {\n"); + buf.append(" enum En {\n"); + buf.append(" A, B;\n"); + buf.append(" enum COLOR {\n"); + buf.append(" D, E\n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append(" void foo();\n"); + buf.append("\n"); + buf.append(" String NAME = \"\";\n"); + buf.append("\n"); + buf.append(" static String staticName() {\n"); + buf.append(" return NAME;\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test2 {\n"); + buf.append(" void bar() {\n"); + buf.append(" Func2 f = () -> System.out.println(COLOR.D);\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + // Bug 421479 + public void testConvertToLambda22() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import test1.Func2.En.*;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func2 {\n"); + buf.append(" enum En {\n"); + buf.append(" A, B;\n"); + buf.append(" enum COLOR {\n"); + buf.append(" D, E\n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append(" void foo();\n"); + buf.append("\n"); + buf.append(" String NAME = \"\";\n"); + buf.append("\n"); + buf.append(" static String staticName() {\n"); + buf.append(" return NAME;\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test2 {\n"); + buf.append(" void bar() {\n"); + buf.append(" Func2 f = new Func2() {\n"); + buf.append(" @Override\n"); + buf.append(" public void foo() {\n"); + buf.append(" System.out.println(COLOR.D);\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("Func2.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import test1.Func2.En.*;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func2 {\n"); + buf.append(" enum En {\n"); + buf.append(" A, B;\n"); + buf.append(" enum COLOR {\n"); + buf.append(" D, E\n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append(" void foo();\n"); + buf.append("\n"); + buf.append(" String NAME = \"\";\n"); + buf.append("\n"); + buf.append(" static String staticName() {\n"); + buf.append(" return NAME;\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test2 {\n"); + buf.append(" void bar() {\n"); + buf.append(" Func2 f = () -> System.out.println(COLOR.D);\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + // Bug 421479 + public void testConvertToLambda23() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func {\n"); + buf.append(" class C {\n"); + buf.append(" static class CIn { static int i= 0; } \n"); + buf.append(" static String NAME = \"\";\n"); + buf.append(" }\n"); + buf.append(" void foo();\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test {\n"); + buf.append(" static class C {\n"); + buf.append(" static class CIn { static int i= 1; } \n"); + buf.append(" static String NAME = \"\";\n"); + buf.append(" }\n"); + buf.append(" void bar() {\n"); + buf.append(" Func f = new Func() {\n"); + buf.append(" @Override\n"); + buf.append(" public void foo() {\n"); + buf.append(" System.out.println(C.CIn.i);\n"); + buf.append(" System.out.println(C.NAME);\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("Func.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func {\n"); + buf.append(" class C {\n"); + buf.append(" static class CIn { static int i= 0; } \n"); + buf.append(" static String NAME = \"\";\n"); + buf.append(" }\n"); + buf.append(" void foo();\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test {\n"); + buf.append(" static class C {\n"); + buf.append(" static class CIn { static int i= 1; } \n"); + buf.append(" static String NAME = \"\";\n"); + buf.append(" }\n"); + buf.append(" void bar() {\n"); + buf.append(" Func f = () -> {\n"); + buf.append(" System.out.println(test1.Func.C.CIn.i);\n"); + buf.append(" System.out.println(Func.C.NAME);\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + // Bug 421479 + public void testConvertToLambda24() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func {\n"); + buf.append(" class C {\n"); + buf.append(" static class CIn { static int i= 0; } \n"); + buf.append(" }\n"); + buf.append(" void foo();\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test extends TT {\n"); + buf.append(" static class C {\n"); + buf.append(" static class CIn { static int i= 1; } \n"); + buf.append(" }\n"); + buf.append(" void bar() {\n"); + buf.append(" test1.Func f = new test1.Func() {\n"); + buf.append(" @Override\n"); + buf.append(" public void foo() {\n"); + buf.append(" System.out.println(C.CIn.i); // [1]\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class TT {\n"); + buf.append(" class Func {\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("Func.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func {\n"); + buf.append(" class C {\n"); + buf.append(" static class CIn { static int i= 0; } \n"); + buf.append(" }\n"); + buf.append(" void foo();\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test extends TT {\n"); + buf.append(" static class C {\n"); + buf.append(" static class CIn { static int i= 1; } \n"); + buf.append(" }\n"); + buf.append(" void bar() {\n"); + buf.append(" test1.Func f = () -> System.out.println(test1.Func.C.CIn.i);\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class TT {\n"); + buf.append(" class Func {\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + // Bug 421479 + public void testConvertToLambda25() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface FI extends FIS {\n"); + buf.append(" void run(int x);\n"); + buf.append(" public static void test(int e) {\n"); + buf.append(" FI fi = new FI() {\n"); + buf.append(" @Override\n"); + buf.append(" public void run(int x) {\n"); + buf.append(" System.out.println(e);\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" fi.run(e);\n"); + buf.append(" } \n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("interface FIS {\n"); + buf.append(" int e= 0; \n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("FI.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface FI extends FIS {\n"); + buf.append(" void run(int x);\n"); + buf.append(" public static void test(int e) {\n"); + buf.append(" FI fi = x -> System.out.println(FIS.e);\n"); + buf.append(" fi.run(e);\n"); + buf.append(" } \n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("interface FIS {\n"); + buf.append(" int e= 0; \n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + // Bug 421479 + public void testConvertToLambda26() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("@FunctionalInterface\n"); + buf.append("interface Func2 {\n"); + buf.append(" enum En {\n"); + buf.append(" A, B\n"); + buf.append(" }\n"); + buf.append("\n"); + buf.append(" void foo();\n"); + buf.append("\n"); + buf.append(" String NAME = \"\";\n"); + buf.append("\n"); + buf.append(" static String staticName() {\n"); + buf.append(" return NAME;\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("\n"); + buf.append("class Test2 {\n"); + buf.append(" void bar() {\n"); + buf.append(" Func2 f = new Func2() {\n"); + buf.append(" @Override\n"); + buf.append(" public void foo() {\n"); + buf.append(" foo();\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("Func2.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 0); + } + + // Bug 421479 + public void testConvertToLambda27() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Consumer;\n"); + buf.append("\n"); + buf.append("public class Test {\n"); + buf.append(" static void run(Consumer consumer) {\n"); + buf.append(" System.out.println(\"consumer\");\n"); + buf.append(" }\n"); + buf.append(" static {\n"); + buf.append(" run(new Consumer() {\n"); + buf.append(" @Override\n"); + buf.append(" public void accept(Integer integer) {\n"); + buf.append(" System.out.println(andThen(null));\n"); + buf.append(" }\n"); + buf.append(" });\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("Test.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("public void"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 0); + } + public void testConvertToLambdaAmbiguousOverridden() throws Exception { IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); StringBuffer buf= new StringBuffer(); #P org.eclipse.jdt.ui diff --git core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java index dec2ec4..5dafb0e 100644 --- core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java +++ core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java @@ -36,11 +36,15 @@ import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.LambdaExpression; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.Name; +import org.eclipse.jdt.core.dom.QualifiedName; import org.eclipse.jdt.core.dom.ReturnStatement; import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SimpleType; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.Statement; import org.eclipse.jdt.core.dom.SuperFieldAccess; @@ -61,6 +65,7 @@ import org.eclipse.jdt.internal.corext.dom.Bindings; import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor; import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder; +import org.eclipse.jdt.internal.corext.dom.TypeRules; import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; import org.eclipse.jdt.internal.corext.refactoring.structure.ImportRemover; import org.eclipse.jdt.internal.corext.util.JavaModelUtil; @@ -71,6 +76,86 @@ import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; public class LambdaExpressionsFix extends CompilationUnitRewriteOperationsFix { + + private static final class InterfaceAccessQualifier extends HierarchicalASTVisitor { + + private ClassInstanceCreation classInstanceCreation; + + private ITypeBinding typeBinding; + + private CompilationUnitRewrite cuRewrite; + + private TextEditGroup categorizedGroup; + + public InterfaceAccessQualifier(CompilationUnitRewrite rewrite, ClassInstanceCreation classInstance, TextEditGroup group) { + this.classInstanceCreation= classInstance; + this.typeBinding= classInstanceCreation.getType().resolveBinding(); + this.cuRewrite= rewrite; + this.categorizedGroup= group; + } + + @Override + public boolean visit(SimpleName node) { + IBinding resolveBinding= node.resolveBinding(); + ITypeBinding declaringClass= null; + if (resolveBinding instanceof IVariableBinding) { + declaringClass= ((IVariableBinding) resolveBinding).getDeclaringClass(); + } else if (resolveBinding instanceof ITypeBinding) { + declaringClass= ((ITypeBinding) resolveBinding).getDeclaringClass(); + } + if (declaringClass != null && (Bindings.equals(typeBinding, declaringClass) || TypeRules.canAssign(typeBinding, declaringClass))) { + ASTRewrite rewrite= cuRewrite.getASTRewrite(); + String qualifier= declaringClass.getErasure().getName(); + AST ast= cuRewrite.getAST(); + SimpleName simpleName= ast.newSimpleName(node.getIdentifier()); + rewrite.set(node, SimpleName.IDENTIFIER_PROPERTY, ast.newQualifiedName(ast.newName(qualifier), simpleName).getFullyQualifiedName(), categorizedGroup); + } + return true; + } + + @Override + public boolean visit(QualifiedName node) { + Name qualifier= node.getQualifier(); + if (qualifier instanceof SimpleName) { + // Ignore if already qualified with the functional interface + if (Bindings.equals(typeBinding, qualifier.resolveBinding())) + return false; + return true; + } + // Ignore if already qualified with the functional interface + IBinding qualifierBinding= ASTNodes.getLeftMostSimpleName(qualifier).resolveBinding(); + if (qualifierBinding == null || Bindings.equals(typeBinding, qualifierBinding)) { + return false; + } + + IBinding resolveBinding= node.resolveBinding(); + ITypeBinding declaringClass= null; + if (resolveBinding instanceof IVariableBinding) { + declaringClass= ((IVariableBinding) resolveBinding).getDeclaringClass(); + } else if (resolveBinding instanceof ITypeBinding) { + declaringClass= ((ITypeBinding) resolveBinding).getDeclaringClass(); + } + while (declaringClass != null) { + if (Bindings.equals(typeBinding, declaringClass) && qualifierBinding instanceof ITypeBinding) { + ImportRewrite importRewrite= cuRewrite.getImportRewrite(); + ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(classInstanceCreation, importRewrite); + Type addImport= importRewrite.addImport((ITypeBinding) qualifierBinding, cuRewrite.getAST(), importRewriteContext); + ImportRemover importRemover= cuRewrite.getImportRemover(); + importRemover.registerAddedImports(addImport); + if (addImport instanceof SimpleType) { + Name qualifiedName= ((SimpleType) addImport).getName(); + if (qualifiedName instanceof QualifiedName && qualifier instanceof QualifiedName) { + ASTRewrite rewrite= cuRewrite.getASTRewrite(); + rewrite.set(qualifier, QualifiedName.QUALIFIER_PROPERTY, qualifiedName, categorizedGroup); + } + } + return false; + } + declaringClass= declaringClass.getDeclaringClass(); + } + return false; + } + } private static final class FunctionalAnonymousClassesFinder extends ASTVisitor { @@ -176,8 +261,9 @@ @Override public boolean visit(MethodInvocation node) { IMethodBinding binding= node.resolveMethodBinding(); - if (binding != null && !JdtFlags.isStatic(binding) && node.getExpression() == null - && Bindings.isSuperType(binding.getDeclaringClass(), fFunctionalInterface, false)) + if (binding != null + && ((!JdtFlags.isStatic(binding) && node.getExpression() == null && Bindings.isSuperType(binding.getDeclaringClass(), fFunctionalInterface, true)) + || (Bindings.equals(binding, fMethodDeclaration.resolveBinding())))) throw new AbortSearchException(); return true; } @@ -250,8 +336,9 @@ } } } - //TODO: Bug 421479: [1.8][clean up][quick assist] convert anonymous to lambda must consider lost scope of interface -// lambdaBody.accept(new InterfaceAccessQualifier(rewrite, classInstanceCreation.getType().resolveBinding())); //TODO: maybe need a separate ASTRewrite and string placeholder + + // Qualify the lost scope of the interface + lambdaBody.accept(new InterfaceAccessQualifier(cuRewrite, classInstanceCreation, group)); lambdaExpression.setBody(rewrite.createCopyTarget(lambdaBody)); Expression replacement= lambdaExpression; @@ -547,7 +634,7 @@ return methodBinding.getReturnType().getFunctionalInterfaceMethod() != null; } - //TODO: should also check whether variable is of a functional type + //TODO: should also check whether variable is of a functional type return locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY || locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY || locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY