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 (+132 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(Func2.En.COLOR.D);\n");
969
		buf.append("                bar();\n");
970
		buf.append("            }\n");
971
		buf.append("        };\n");
972
		buf.append("    }\n");
973
		buf.append("}\n");
974
		ICompilationUnit cu= pack1.createCompilationUnit("Func2.java", buf.toString(), false, null);
975
976
		int offset= buf.toString().indexOf("public void");
977
		AssistContext context= getCorrectionContext(cu, offset, 0);
978
		assertNoErrors(context);
979
		List proposals= collectAssists(context, false);
980
981
		assertNumberOfProposals(proposals, 1);
982
		assertCorrectLabels(proposals);
983
984
		buf= new StringBuffer();
985
		buf.append("package test1;\n");
986
		buf.append("@FunctionalInterface\n");
987
		buf.append("interface Func2 {\n");
988
		buf.append("    enum En {\n");
989
		buf.append("        A, B;\n");
990
		buf.append("        enum COLOR {\n");
991
		buf.append("            D, E\n");
992
		buf.append("        }\n");
993
		buf.append("    }\n");
994
		buf.append("\n");
995
		buf.append("    void foo();\n");
996
		buf.append("\n");
997
		buf.append("    String NAME = \"\";\n");
998
		buf.append("\n");
999
		buf.append("    static String staticName() {\n");
1000
		buf.append("        return NAME;\n");
1001
		buf.append("    }\n");
1002
		buf.append("}\n");
1003
		buf.append("\n");
1004
		buf.append("class Test2 {\n");
1005
		buf.append("    void bar() {\n");
1006
		buf.append("        Func2 f = () -> {\n");
1007
		buf.append("            System.out.println(Func2.NAME);\n");
1008
		buf.append("            System.out.println(Func2.En.A);\n");
1009
		buf.append("            System.out.println(Func2.En.COLOR.D);\n");
1010
		buf.append("            System.out.println(Func2.NAME);\n");
1011
		buf.append("            System.out.println(Func2.En.A);\n");
1012
		buf.append("            System.out.println(Func2.En.COLOR.D);\n");
1013
		buf.append("            bar();\n");
1014
		buf.append("        };\n");
1015
		buf.append("    }\n");
1016
		buf.append("}\n");
1017
		String expected1= buf.toString();
1018
1019
		assertExpectedExistInProposals(proposals, new String[] { expected1 });
1020
	}
1021
1022
	// Bug 421479
1023
	public void testConvertToLambda20() throws Exception {
1024
		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
1025
		StringBuffer buf= new StringBuffer();
1026
		buf.append("package test1;\n");
1027
		buf.append("@FunctionalInterface\n");
1028
		buf.append("interface Func2 {\n");
1029
		buf.append("    enum En {\n");
1030
		buf.append("        A, B\n");
1031
		buf.append("    }\n");
1032
		buf.append("\n");
1033
		buf.append("    void foo();\n");
1034
		buf.append("\n");
1035
		buf.append("    String NAME = \"\";\n");
1036
		buf.append("\n");
1037
		buf.append("    static String staticName() {\n");
1038
		buf.append("        return NAME;\n");
1039
		buf.append("    }\n");
1040
		buf.append("}\n");
1041
		buf.append("\n");
1042
		buf.append("class Test2 {\n");
1043
		buf.append("    void bar() {\n");
1044
		buf.append("        Func2 f = new Func2() {\n");
1045
		buf.append("            @Override\n");
1046
		buf.append("            public void foo() {\n");
1047
		buf.append("                System.out.println(NAME);\n");
1048
		buf.append("                System.out.println(En.A);\n");
1049
		buf.append("                foo();\n");
1050
		buf.append("            }\n");
1051
		buf.append("        };\n");
1052
		buf.append("    }\n");
1053
		buf.append("}\n");
1054
		ICompilationUnit cu= pack1.createCompilationUnit("Func2.java", buf.toString(), false, null);
1055
1056
		int offset= buf.toString().indexOf("public void");
1057
		AssistContext context= getCorrectionContext(cu, offset, 0);
1058
		assertNoErrors(context);
1059
		List proposals= collectAssists(context, false);
1060
1061
		assertNumberOfProposals(proposals, 0);
1062
1063
	}
1064
933
	public void testConvertToLambdaAmbiguousOverridden() throws Exception {
1065
	public void testConvertToLambdaAmbiguousOverridden() throws Exception {
934
		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
1066
		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
935
		StringBuffer buf= new StringBuffer();
1067
		StringBuffer buf= new StringBuffer();
(-)core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java (-4 / +75 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
			if (resolveBinding instanceof IVariableBinding) {
91
				ITypeBinding declaringClass= ((IVariableBinding) resolveBinding).getDeclaringClass();
92
				if (declaringClass != null && Bindings.equals(typeBinding, declaringClass)) {
93
					nameNodes.add(node);
94
				}
95
			}
96
			return true;
97
		}
98
99
		@Override
100
		public boolean visit(QualifiedName node) {
101
			IBinding resolveBinding= node.resolveBinding();
102
			Name qualifier= node.getQualifier();
103
			if (!(qualifier instanceof SimpleName)) {
104
				qualifier= ASTNodes.getLeftMostSimpleName(qualifier);
105
			}
106
			IBinding qualifierBinding= qualifier.resolveBinding();
107
			if (Bindings.equals(typeBinding, qualifierBinding)) {
108
				return false;
109
			}
110
			if (resolveBinding instanceof IVariableBinding) {
111
				ITypeBinding declaringClass= ((IVariableBinding) resolveBinding).getDeclaringClass();
112
				while (declaringClass != null && declaringClass.isEnum()) {
113
					declaringClass= declaringClass.getDeclaringClass();
114
				}
115
				if (declaringClass != null && Bindings.equals(typeBinding, declaringClass)) {
116
					nameNodes.add(qualifier);
117
				}
118
			}
119
			return false;
120
		}
121
	}
72
122
73
	private static final class FunctionalAnonymousClassesFinder extends ASTVisitor {
123
	private static final class FunctionalAnonymousClassesFinder extends ASTVisitor {
74
124
Lines 177-182 Link Here
177
			if (binding != null && !JdtFlags.isStatic(binding) && node.getExpression() == null
227
			if (binding != null && !JdtFlags.isStatic(binding) && node.getExpression() == null
178
					&& Bindings.isSuperType(binding.getDeclaringClass(), fFunctionalInterface, false))
228
					&& Bindings.isSuperType(binding.getDeclaringClass(), fFunctionalInterface, false))
179
				throw new AbortSearchException();
229
				throw new AbortSearchException();
230
			if (Bindings.equals(fMethodDeclaration.resolveBinding(), binding)) {
231
				throw new AbortSearchException();
232
			}
180
			return true;
233
			return true;
181
		}
234
		}
182
	}
235
	}
Lines 238-245 Link Here
238
						}
291
						}
239
					}
292
					}
240
				}
293
				}
241
				//TODO: Bug 421479: [1.8][clean up][quick assist] convert anonymous to lambda must consider lost scope of interface
294
242
//				lambdaBody.accept(new InterfaceAccessQualifier(rewrite, classInstanceCreation.getType().resolveBinding())); //TODO: maybe need a separate ASTRewrite and string placeholder
295
				ITypeBinding typeBinding= classInstanceCreation.getType().resolveBinding();
296
				InterfaceAccessQualifier visitor= new InterfaceAccessQualifier(typeBinding);
297
				lambdaBody.accept(visitor);
298
				qualifyNameNodes(rewrite, typeBinding, visitor.nameNodes, group);
243
				
299
				
244
				lambdaExpression.setBody(rewrite.createCopyTarget(lambdaBody));
300
				lambdaExpression.setBody(rewrite.createCopyTarget(lambdaBody));
245
				Expression replacement= lambdaExpression;
301
				Expression replacement= lambdaExpression;
Lines 248-254 Link Here
248
					cast.setExpression(lambdaExpression);
304
					cast.setExpression(lambdaExpression);
249
					ImportRewrite importRewrite= cuRewrite.getImportRewrite();
305
					ImportRewrite importRewrite= cuRewrite.getImportRewrite();
250
					ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(classInstanceCreation, importRewrite);
306
					ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(classInstanceCreation, importRewrite);
251
					Type castType= importRewrite.addImport(classInstanceCreation.getType().resolveBinding(), ast, importRewriteContext);
307
					Type castType= importRewrite.addImport(typeBinding, ast, importRewriteContext);
252
					cast.setType(castType);
308
					cast.setType(castType);
253
					importRemover.registerAddedImports(castType);
309
					importRemover.registerAddedImports(castType);
254
					replacement= cast;
310
					replacement= cast;
Lines 257-262 Link Here
257
313
258
				importRemover.registerRemovedNode(classInstanceCreation);
314
				importRemover.registerRemovedNode(classInstanceCreation);
259
				importRemover.registerRetainedNode(lambdaBody);
315
				importRemover.registerRetainedNode(lambdaBody);
316
			}
317
		}
318
319
		private void qualifyNameNodes(ASTRewrite rewrite, ITypeBinding typeBinding, List<Name> nameNodes, TextEditGroup group) {
320
			for (Name name : nameNodes) {
321
				AST ast= name.getAST();
322
				SimpleName simpleName= null;
323
				String qualifier= typeBinding.getName();
324
				if (name instanceof SimpleName) {
325
					simpleName= ast.newSimpleName(((SimpleName) name).getIdentifier());
326
					rewrite.set(name, SimpleName.IDENTIFIER_PROPERTY, ast.newQualifiedName(ast.newName(qualifier), simpleName).getFullyQualifiedName(), group);
327
				} else if (name instanceof QualifiedName) {
328
					qualifier= qualifier + '.' + ((QualifiedName) name).getQualifier().getFullyQualifiedName();
329
					rewrite.set(name, QualifiedName.QUALIFIER_PROPERTY, ast.newName(qualifier), group);
330
				}
260
			}
331
			}
261
		}
332
		}
262
333
Lines 531-537 Link Here
531
			return methodBinding.getReturnType().getFunctionalInterfaceMethod() != null;
602
			return methodBinding.getReturnType().getFunctionalInterfaceMethod() != null;
532
		}
603
		}
533
		
604
		
534
		//TODO: should also check whether variable is of a functional type 
605
		//TODO: should also check whether variable is of a functional type
535
		return locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY
606
		return locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY
536
				|| locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY
607
				|| locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY
537
				|| locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY
608
				|| locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY

Return to bug 421479