View | Details | Raw Unified | Return to bug 421479 | Differences between
and this patch

Collapse All | Expand All

(-)ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java (+134 lines)
Lines 59-64 Link Here
59
		return new Java18ProjectTestSetup(test);
59
		return new Java18ProjectTestSetup(test);
60
	}
60
	}
61
61
62
	@Override
62
	protected void setUp() throws Exception {
63
	protected void setUp() throws Exception {
63
		Hashtable options= TestOptions.getDefaultOptions();
64
		Hashtable options= TestOptions.getDefaultOptions();
64
		options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
65
		options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
Lines 74-79 Link Here
74
		fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
75
		fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
75
	}
76
	}
76
77
78
	@Override
77
	protected void tearDown() throws Exception {
79
	protected void tearDown() throws Exception {
78
		JavaProjectHelper.clear(fJProject1, Java18ProjectTestSetup.getDefaultClasspath());
80
		JavaProjectHelper.clear(fJProject1, Java18ProjectTestSetup.getDefaultClasspath());
79
	}
81
	}
Lines 930-935 Link Here
930
		assertExpectedExistInProposals(proposals, new String[] { expected1 });
932
		assertExpectedExistInProposals(proposals, new String[] { expected1 });
931
	}
933
	}
932
934
935
	// Bug 421479
936
	public void testConvertToLambda19() throws Exception {
937
		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
938
		StringBuffer buf= new StringBuffer();
939
		buf.append("package test1;\n");
940
		buf.append("@FunctionalInterface\n");
941
		buf.append("interface Func2 {\n");
942
		buf.append("    enum En {\n");
943
		buf.append("        A, B;\n");
944
		buf.append("        enum COLOR {\n");
945
		buf.append("            D, E\n");
946
		buf.append("        }\n");
947
		buf.append("    }\n");
948
		buf.append("\n");
949
		buf.append("    void foo();\n");
950
		buf.append("\n");
951
		buf.append("    String NAME = \"\";\n");
952
		buf.append("\n");
953
		buf.append("    static String staticName() {\n");
954
		buf.append("        return NAME;\n");
955
		buf.append("    }\n");
956
		buf.append("}\n");
957
		buf.append("\n");
958
		buf.append("class Test2 {\n");
959
		buf.append("    void bar() {\n");
960
		buf.append("        Func2 f = new Func2() {\n");
961
		buf.append("            @Override\n");
962
		buf.append("            public void foo() {\n");
963
		buf.append("                System.out.println(NAME);\n");
964
		buf.append("                System.out.println(En.A);\n");
965
		buf.append("                System.out.println(En.COLOR.D);\n");
966
		buf.append("                System.out.println(Func2.NAME);\n");
967
		buf.append("                System.out.println(Func2.En.A);\n");
968
		buf.append("                System.out.println(test1.Func2.En.COLOR.D);\n");
969
		buf.append("                System.out.println(Test2.this);\n");
970
		buf.append("                bar();\n");
971
		buf.append("            }\n");
972
		buf.append("        };\n");
973
		buf.append("    }\n");
974
		buf.append("}\n");
975
		ICompilationUnit cu= pack1.createCompilationUnit("Func2.java", buf.toString(), false, null);
976
977
		int offset= buf.toString().indexOf("public void");
978
		AssistContext context= getCorrectionContext(cu, offset, 0);
979
		assertNoErrors(context);
980
		List proposals= collectAssists(context, false);
981
982
		assertNumberOfProposals(proposals, 1);
983
		assertCorrectLabels(proposals);
984
985
		buf= new StringBuffer();
986
		buf.append("package test1;\n");
987
		buf.append("@FunctionalInterface\n");
988
		buf.append("interface Func2 {\n");
989
		buf.append("    enum En {\n");
990
		buf.append("        A, B;\n");
991
		buf.append("        enum COLOR {\n");
992
		buf.append("            D, E\n");
993
		buf.append("        }\n");
994
		buf.append("    }\n");
995
		buf.append("\n");
996
		buf.append("    void foo();\n");
997
		buf.append("\n");
998
		buf.append("    String NAME = \"\";\n");
999
		buf.append("\n");
1000
		buf.append("    static String staticName() {\n");
1001
		buf.append("        return NAME;\n");
1002
		buf.append("    }\n");
1003
		buf.append("}\n");
1004
		buf.append("\n");
1005
		buf.append("class Test2 {\n");
1006
		buf.append("    void bar() {\n");
1007
		buf.append("        Func2 f = () -> {\n");
1008
		buf.append("            System.out.println(Func2.NAME);\n");
1009
		buf.append("            System.out.println(Func2.En.A);\n");
1010
		buf.append("            System.out.println(Func2.En.COLOR.D);\n");
1011
		buf.append("            System.out.println(Func2.NAME);\n");
1012
		buf.append("            System.out.println(Func2.En.A);\n");
1013
		buf.append("            System.out.println(test1.Func2.En.COLOR.D);\n");
1014
		buf.append("            System.out.println(Test2.this);\n");
1015
		buf.append("            bar();\n");
1016
		buf.append("        };\n");
1017
		buf.append("    }\n");
1018
		buf.append("}\n");
1019
		String expected1= buf.toString();
1020
1021
		assertExpectedExistInProposals(proposals, new String[] { expected1 });
1022
	}
1023
1024
	// Bug 421479
1025
	public void testConvertToLambda20() throws Exception {
1026
		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
1027
		StringBuffer buf= new StringBuffer();
1028
		buf.append("package test1;\n");
1029
		buf.append("@FunctionalInterface\n");
1030
		buf.append("interface Func2 {\n");
1031
		buf.append("    enum En {\n");
1032
		buf.append("        A, B\n");
1033
		buf.append("    }\n");
1034
		buf.append("\n");
1035
		buf.append("    void foo();\n");
1036
		buf.append("\n");
1037
		buf.append("    String NAME = \"\";\n");
1038
		buf.append("\n");
1039
		buf.append("    static String staticName() {\n");
1040
		buf.append("        return NAME;\n");
1041
		buf.append("    }\n");
1042
		buf.append("}\n");
1043
		buf.append("\n");
1044
		buf.append("class Test2 {\n");
1045
		buf.append("    void bar() {\n");
1046
		buf.append("        Func2 f = new Func2() {\n");
1047
		buf.append("            @Override\n");
1048
		buf.append("            public void foo() {\n");
1049
		buf.append("                System.out.println(NAME);\n");
1050
		buf.append("                System.out.println(En.A);\n");
1051
		buf.append("                foo();\n");
1052
		buf.append("            }\n");
1053
		buf.append("        };\n");
1054
		buf.append("    }\n");
1055
		buf.append("}\n");
1056
		ICompilationUnit cu= pack1.createCompilationUnit("Func2.java", buf.toString(), false, null);
1057
1058
		int offset= buf.toString().indexOf("public void");
1059
		AssistContext context= getCorrectionContext(cu, offset, 0);
1060
		assertNoErrors(context);
1061
		List proposals= collectAssists(context, false);
1062
1063
		assertNumberOfProposals(proposals, 0);
1064
1065
	}
1066
933
	public void testConvertToLambdaAmbiguousOverridden() throws Exception {
1067
	public void testConvertToLambdaAmbiguousOverridden() throws Exception {
934
		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
1068
		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
935
		StringBuffer buf= new StringBuffer();
1069
		StringBuffer buf= new StringBuffer();
(-)core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java (-4 / +80 lines)
Lines 34-42 Link Here
34
import org.eclipse.jdt.core.dom.IBinding;
34
import org.eclipse.jdt.core.dom.IBinding;
35
import org.eclipse.jdt.core.dom.IMethodBinding;
35
import org.eclipse.jdt.core.dom.IMethodBinding;
36
import org.eclipse.jdt.core.dom.ITypeBinding;
36
import org.eclipse.jdt.core.dom.ITypeBinding;
37
import org.eclipse.jdt.core.dom.IVariableBinding;
37
import org.eclipse.jdt.core.dom.LambdaExpression;
38
import org.eclipse.jdt.core.dom.LambdaExpression;
38
import org.eclipse.jdt.core.dom.MethodDeclaration;
39
import org.eclipse.jdt.core.dom.MethodDeclaration;
39
import org.eclipse.jdt.core.dom.MethodInvocation;
40
import org.eclipse.jdt.core.dom.MethodInvocation;
41
import org.eclipse.jdt.core.dom.Name;
42
import org.eclipse.jdt.core.dom.QualifiedName;
40
import org.eclipse.jdt.core.dom.ReturnStatement;
43
import org.eclipse.jdt.core.dom.ReturnStatement;
41
import org.eclipse.jdt.core.dom.SimpleName;
44
import org.eclipse.jdt.core.dom.SimpleName;
42
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
45
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
Lines 69-74 Link Here
69
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
72
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
70
73
71
public class LambdaExpressionsFix extends CompilationUnitRewriteOperationsFix {
74
public class LambdaExpressionsFix extends CompilationUnitRewriteOperationsFix {
75
76
	private static final class InterfaceAccessQualifier extends HierarchicalASTVisitor {
77
78
		List<Name> nameNodes;
79
80
		private ITypeBinding typeBinding;
81
82
		public InterfaceAccessQualifier(ITypeBinding typeBinding) {
83
			this.typeBinding= typeBinding;
84
			nameNodes= new ArrayList<Name>();
85
		}
86
87
		@Override
88
		public boolean visit(SimpleName node) {
89
			IBinding resolveBinding= node.resolveBinding();
90
			ITypeBinding declaringClass= null;
91
			if (resolveBinding instanceof IVariableBinding) {
92
				declaringClass= ((IVariableBinding) resolveBinding).getDeclaringClass();
93
			} else if (resolveBinding instanceof ITypeBinding) {
94
				declaringClass= ((ITypeBinding) resolveBinding).getDeclaringClass();
95
			}
96
			if (declaringClass != null && Bindings.equals(typeBinding, declaringClass)) {
97
				nameNodes.add(node);
98
			}
99
			return true;
100
		}
101
102
		@Override
103
		public boolean visit(QualifiedName node) {
104
			Name qualifier= node.getQualifier();
105
			String fullyQualifiedName= qualifier.getFullyQualifiedName();
106
			// Ignore if already qualified with the functional interface
107
			if (fullyQualifiedName.startsWith(typeBinding.getQualifiedName()) || fullyQualifiedName.startsWith(typeBinding.getName())) {
108
				return false;
109
			}
110
			IBinding resolveBinding= node.resolveBinding();
111
			ITypeBinding declaringClass= null;
112
			if (resolveBinding instanceof IVariableBinding) {
113
				declaringClass= ((IVariableBinding) resolveBinding).getDeclaringClass();
114
			} else if (resolveBinding instanceof ITypeBinding) {
115
				declaringClass= ((ITypeBinding) resolveBinding).getDeclaringClass();
116
			}
117
			while (declaringClass != null) {
118
				if (Bindings.equals(typeBinding, declaringClass)) {
119
					nameNodes.add(qualifier);
120
					return false;
121
				}
122
				declaringClass= declaringClass.getDeclaringClass();
123
			}
124
			return false;
125
		}
126
	}
72
127
73
	private static final class FunctionalAnonymousClassesFinder extends ASTVisitor {
128
	private static final class FunctionalAnonymousClassesFinder extends ASTVisitor {
74
129
Lines 177-182 Link Here
177
			if (binding != null && !JdtFlags.isStatic(binding) && node.getExpression() == null
232
			if (binding != null && !JdtFlags.isStatic(binding) && node.getExpression() == null
178
					&& Bindings.isSuperType(binding.getDeclaringClass(), fFunctionalInterface, false))
233
					&& Bindings.isSuperType(binding.getDeclaringClass(), fFunctionalInterface, false))
179
				throw new AbortSearchException();
234
				throw new AbortSearchException();
235
			if (Bindings.equals(binding, fMethodDeclaration.resolveBinding())) {
236
				throw new AbortSearchException();
237
			}
180
			return true;
238
			return true;
181
		}
239
		}
182
	}
240
	}
Lines 238-245 Link Here
238
						}
296
						}
239
					}
297
					}
240
				}
298
				}
241
				//TODO: Bug 421479: [1.8][clean up][quick assist] convert anonymous to lambda must consider lost scope of interface
299
242
//				lambdaBody.accept(new InterfaceAccessQualifier(rewrite, classInstanceCreation.getType().resolveBinding())); //TODO: maybe need a separate ASTRewrite and string placeholder
300
				ITypeBinding typeBinding= classInstanceCreation.getType().resolveBinding();
301
				InterfaceAccessQualifier visitor= new InterfaceAccessQualifier(typeBinding);
302
				lambdaBody.accept(visitor);
303
				qualifyNameNodes(rewrite, typeBinding, visitor.nameNodes, group);
243
				
304
				
244
				lambdaExpression.setBody(rewrite.createCopyTarget(lambdaBody));
305
				lambdaExpression.setBody(rewrite.createCopyTarget(lambdaBody));
245
				Expression replacement= lambdaExpression;
306
				Expression replacement= lambdaExpression;
Lines 248-254 Link Here
248
					cast.setExpression(lambdaExpression);
309
					cast.setExpression(lambdaExpression);
249
					ImportRewrite importRewrite= cuRewrite.getImportRewrite();
310
					ImportRewrite importRewrite= cuRewrite.getImportRewrite();
250
					ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(classInstanceCreation, importRewrite);
311
					ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(classInstanceCreation, importRewrite);
251
					Type castType= importRewrite.addImport(classInstanceCreation.getType().resolveBinding(), ast, importRewriteContext);
312
					Type castType= importRewrite.addImport(typeBinding, ast, importRewriteContext);
252
					cast.setType(castType);
313
					cast.setType(castType);
253
					importRemover.registerAddedImports(castType);
314
					importRemover.registerAddedImports(castType);
254
					replacement= cast;
315
					replacement= cast;
Lines 257-262 Link Here
257
318
258
				importRemover.registerRemovedNode(classInstanceCreation);
319
				importRemover.registerRemovedNode(classInstanceCreation);
259
				importRemover.registerRetainedNode(lambdaBody);
320
				importRemover.registerRetainedNode(lambdaBody);
321
			}
322
		}
323
324
		private void qualifyNameNodes(ASTRewrite rewrite, ITypeBinding typeBinding, List<Name> nameNodes, TextEditGroup group) {
325
			for (Name name : nameNodes) {
326
				AST ast= name.getAST();
327
				SimpleName simpleName= null;
328
				String qualifier= typeBinding.getName();
329
				if (name instanceof SimpleName) {
330
					simpleName= ast.newSimpleName(((SimpleName) name).getIdentifier());
331
					rewrite.set(name, SimpleName.IDENTIFIER_PROPERTY, ast.newQualifiedName(ast.newName(qualifier), simpleName).getFullyQualifiedName(), group);
332
				} else if (name instanceof QualifiedName) {
333
					qualifier= qualifier + '.' + ((QualifiedName) name).getQualifier().getFullyQualifiedName();
334
					rewrite.set(name, QualifiedName.QUALIFIER_PROPERTY, ast.newName(qualifier), group);
335
				}
260
			}
336
			}
261
		}
337
		}
262
338
Lines 531-537 Link Here
531
			return methodBinding.getReturnType().getFunctionalInterfaceMethod() != null;
607
			return methodBinding.getReturnType().getFunctionalInterfaceMethod() != null;
532
		}
608
		}
533
		
609
		
534
		//TODO: should also check whether variable is of a functional type 
610
		//TODO: should also check whether variable is of a functional type
535
		return locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY
611
		return locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY
536
				|| locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY
612
				|| locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY
537
				|| locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY
613
				|| locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY

Return to bug 421479