diff options
author | Noopur Gupta | 2014-10-27 23:58:33 +0000 |
---|---|---|
committer | Markus Keller | 2014-10-27 23:58:33 +0000 |
commit | fd1973006b8d69c372d0b6fa2cbd79fe8d6cc3fe (patch) | |
tree | b8ebc4148ce473b697589621f017a4ec0f5df310 | |
parent | 2499089503d2b0333b921bf73c11984cf2379b1b (diff) | |
download | eclipse.jdt.ui-I20141028-2000.tar.gz eclipse.jdt.ui-I20141028-2000.tar.xz eclipse.jdt.ui-I20141028-2000.zip |
Bug 428741: [1.8][quick assist] convert method reference expression to lambdaI20141104-0800I20141029-2000I20141029-0800I20141028-2000I20141028-0800I20141027-2000
Bug 439601: [1.8][quick assist] convert lambda expression to method reference
6 files changed, 1906 insertions, 52 deletions
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java index d912c7fd28..2f2b715365 100644 --- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java @@ -1093,7 +1093,7 @@ public class AssistQuickFixTest18 extends QuickFixTest { assertNoErrors(context); List proposals= collectAssists(context, false); - assertNumberOfProposals(proposals, 5); + assertNumberOfProposals(proposals, 6); assertCorrectLabels(proposals); buf= new StringBuffer(); @@ -1242,7 +1242,7 @@ public class AssistQuickFixTest18 extends QuickFixTest { assertNoErrors(context); List proposals= collectAssists(context, false); - assertNumberOfProposals(proposals, 3); + assertNumberOfProposals(proposals, 4); assertCorrectLabels(proposals); buf= new StringBuffer(); @@ -1476,7 +1476,7 @@ public class AssistQuickFixTest18 extends QuickFixTest { assertNoErrors(context); List proposals= collectAssists(context, false); - assertNumberOfProposals(proposals, 2); + assertNumberOfProposals(proposals, 3); assertCorrectLabels(proposals); buf= new StringBuffer(); @@ -2100,4 +2100,1415 @@ public class AssistQuickFixTest18 extends QuickFixTest { String expected1= buf.toString(); assertExpectedExistInProposals(proposals, new String[] { expected1 }); } + + public void testConvertMethodReferenceToLambda1() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class E1 {\n"); + buf.append(" Baz bm = E1::test;\n"); + buf.append(" static <X> void test(X x) {}\n"); + buf.append("}\n"); + buf.append("interface Foo<T, N extends Number> {\n"); + buf.append(" void m(N arg2);\n"); + buf.append(" void m(T arg1);\n"); + buf.append("}\n"); + buf.append("interface Baz extends Foo<Integer, Integer> {}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E1.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("::") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class E1 {\n"); + buf.append(" Baz bm = arg2 -> E1.test(arg2);\n"); + buf.append(" static <X> void test(X x) {}\n"); + buf.append("}\n"); + buf.append("interface Foo<T, N extends Number> {\n"); + buf.append(" void m(N arg2);\n"); + buf.append(" void m(T arg1);\n"); + buf.append("}\n"); + buf.append("interface Baz extends Foo<Integer, Integer> {}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + public void testConvertMethodReferenceToLambda2() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("interface J<R> {\n"); + buf.append(" <T> R run(T t);\n"); + buf.append("}\n"); + buf.append("public class E2 {\n"); + buf.append(" J<String> j1 = E2::<Object>test; \n"); + buf.append(" \n"); + buf.append(" static <T> String test(T t) {\n"); + buf.append(" return \"\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E2.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("::") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_lambda_expression); + } + + public void testConvertMethodReferenceToLambda3() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf1= new StringBuffer(); + buf1.append("package test1;\n"); + buf1.append("import java.util.HashSet;\n"); + buf1.append("import java.util.function.*;\n"); + buf1.append("class E3<T> {\n"); + buf1.append(" IntFunction<int[][][]> ma = int[][][]::/*[1]*/new;\n"); + buf1.append(" Supplier<MyHashSet<Integer>> mb = MyHashSet::/*[2]*/new;\n"); + buf1.append(" Function<T, MyHashSet<Number>> mc = MyHashSet<Number>::/*[3]*/<T> new;\n"); + buf1.append(" Function<String, MyHashSet<Integer>> md = MyHashSet::/*[4]*/new;\n"); + buf1.append("}\n"); + buf1.append("class MyHashSet<T> extends HashSet<T> {\n"); + buf1.append(" public MyHashSet() {}\n"); + buf1.append(" public <A> MyHashSet(A a) {}\n"); + buf1.append(" public MyHashSet(String i) {}\n"); + buf1.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E3.java", buf1.toString(), false, null); + + // [1] + int offset= buf1.toString().indexOf("::/*[1]*/") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.HashSet;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("class E3<T> {\n"); + buf.append(" IntFunction<int[][][]> ma = arg0 -> new int[arg0][][];\n"); + buf.append(" Supplier<MyHashSet<Integer>> mb = MyHashSet::/*[2]*/new;\n"); + buf.append(" Function<T, MyHashSet<Number>> mc = MyHashSet<Number>::/*[3]*/<T> new;\n"); + buf.append(" Function<String, MyHashSet<Integer>> md = MyHashSet::/*[4]*/new;\n"); + buf.append("}\n"); + buf.append("class MyHashSet<T> extends HashSet<T> {\n"); + buf.append(" public MyHashSet() {}\n"); + buf.append(" public <A> MyHashSet(A a) {}\n"); + buf.append(" public MyHashSet(String i) {}\n"); + buf.append("}\n"); + String expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [2] + offset= buf1.toString().indexOf("::/*[2]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.HashSet;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("class E3<T> {\n"); + buf.append(" IntFunction<int[][][]> ma = int[][][]::/*[1]*/new;\n"); + buf.append(" Supplier<MyHashSet<Integer>> mb = () -> new MyHashSet<>();\n"); + buf.append(" Function<T, MyHashSet<Number>> mc = MyHashSet<Number>::/*[3]*/<T> new;\n"); + buf.append(" Function<String, MyHashSet<Integer>> md = MyHashSet::/*[4]*/new;\n"); + buf.append("}\n"); + buf.append("class MyHashSet<T> extends HashSet<T> {\n"); + buf.append(" public MyHashSet() {}\n"); + buf.append(" public <A> MyHashSet(A a) {}\n"); + buf.append(" public MyHashSet(String i) {}\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [3] + offset= buf1.toString().indexOf("::/*[3]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.HashSet;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("class E3<T> {\n"); + buf.append(" IntFunction<int[][][]> ma = int[][][]::/*[1]*/new;\n"); + buf.append(" Supplier<MyHashSet<Integer>> mb = MyHashSet::/*[2]*/new;\n"); + buf.append(" Function<T, MyHashSet<Number>> mc = arg0 -> new<T> MyHashSet<Number>(arg0);\n"); + buf.append(" Function<String, MyHashSet<Integer>> md = MyHashSet::/*[4]*/new;\n"); + buf.append("}\n"); + buf.append("class MyHashSet<T> extends HashSet<T> {\n"); + buf.append(" public MyHashSet() {}\n"); + buf.append(" public <A> MyHashSet(A a) {}\n"); + buf.append(" public MyHashSet(String i) {}\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [4] + offset= buf1.toString().indexOf("::/*[4]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.HashSet;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("class E3<T> {\n"); + buf.append(" IntFunction<int[][][]> ma = int[][][]::/*[1]*/new;\n"); + buf.append(" Supplier<MyHashSet<Integer>> mb = MyHashSet::/*[2]*/new;\n"); + buf.append(" Function<T, MyHashSet<Number>> mc = MyHashSet<Number>::/*[3]*/<T> new;\n"); + buf.append(" Function<String, MyHashSet<Integer>> md = arg0 -> new MyHashSet<>(arg0);\n"); + buf.append("}\n"); + buf.append("class MyHashSet<T> extends HashSet<T> {\n"); + buf.append(" public MyHashSet() {}\n"); + buf.append(" public <A> MyHashSet(A a) {}\n"); + buf.append(" public MyHashSet(String i) {}\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + } + + public void testConvertMethodReferenceToLambda4() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E4 {\n"); + buf.append(" Function<String, String> p1 = E4::<Float> staticMethod;\n"); + buf.append(" static <F> String staticMethod(String s) {\n"); + buf.append(" return \"s\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E4.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("::") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E4 {\n"); + buf.append(" Function<String, String> p1 = arg0 -> E4.<Float> staticMethod(arg0);\n"); + buf.append(" static <F> String staticMethod(String s) {\n"); + buf.append(" return \"s\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + public void testConvertMethodReferenceToLambda5() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf1= new StringBuffer(); + buf1.append("package test1;\n"); + buf1.append("import java.util.function.*;\n"); + buf1.append("public class E5<T> {\n"); + buf1.append(" <F> String method1() {\n"); + buf1.append(" return \"a\";\n"); + buf1.append(" }\n"); + buf1.append(" <F> String method1(E5<T> e) {\n"); + buf1.append(" return \"b\";\n"); + buf1.append(" }\n"); + buf1.append("}\n"); + buf1.append("class Sub extends E5<Integer> {\n"); + buf1.append(" Supplier<String> s1 = super::/*[1]*/method1;\n"); + buf1.append(" Supplier<String> s2 = Sub.super::/*[2]*/<Float>method1;\n"); + buf1.append(" Function<E5<Integer>, String> s3 = super::/*[3]*/<Float>method1;\n"); + buf1.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E5.java", buf1.toString(), false, null); + + // [1] + int offset= buf1.toString().indexOf("::/*[1]*/") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E5<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" <F> String method1(E5<T> e) {\n"); + buf.append(" return \"b\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("class Sub extends E5<Integer> {\n"); + buf.append(" Supplier<String> s1 = () -> super./*[1]*/method1();\n"); + buf.append(" Supplier<String> s2 = Sub.super::/*[2]*/<Float>method1;\n"); + buf.append(" Function<E5<Integer>, String> s3 = super::/*[3]*/<Float>method1;\n"); + buf.append("}\n"); + String expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [2] + offset= buf1.toString().indexOf("::/*[2]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E5<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" <F> String method1(E5<T> e) {\n"); + buf.append(" return \"b\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("class Sub extends E5<Integer> {\n"); + buf.append(" Supplier<String> s1 = super::/*[1]*/method1;\n"); + buf.append(" Supplier<String> s2 = () -> Sub.super.<Float> method1();\n"); + buf.append(" Function<E5<Integer>, String> s3 = super::/*[3]*/<Float>method1;\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [3] + offset= buf1.toString().indexOf("::/*[3]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E5<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" <F> String method1(E5<T> e) {\n"); + buf.append(" return \"b\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + buf.append("class Sub extends E5<Integer> {\n"); + buf.append(" Supplier<String> s1 = super::/*[1]*/method1;\n"); + buf.append(" Supplier<String> s2 = Sub.super::/*[2]*/<Float>method1;\n"); + buf.append(" Function<E5<Integer>, String> s3 = arg0 -> super.<Float> method1(arg0);\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + } + + public void testConvertMethodReferenceToLambda6() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf1= new StringBuffer(); + buf1.append("package test1;\n"); + buf1.append("import java.util.function.*;\n"); + buf1.append("public class E6<T> {\n"); + buf1.append(" <F> String method1() {\n"); + buf1.append(" return \"a\";\n"); + buf1.append(" }\n"); + buf1.append(" <F> String method1(E6<T> e) {\n"); + buf1.append(" return \"b\";\n"); + buf1.append(" }\n"); + buf1.append(" Supplier<String> v1 = new E6<Integer>()::/*[1]*/method1;\n"); + buf1.append(" Supplier<String> v2 = this::/*[2]*/<Float>method1;\n"); + buf1.append(" Function<E6<Integer>, String> v3 = new E6<Integer>()::/*[3]*/<Float>method1;\n"); + buf1.append(" T1[] ts = new T1[5];\n"); + buf1.append(" BiFunction<Integer, Integer, Integer> m6 = ts[1]::/*[4]*/bar;\n"); + buf1.append(" int[] is = new int[5];\n"); + buf1.append(" Supplier<int[]> m10 = is::/*[5]*/clone;\n"); + buf1.append("}\n"); + buf1.append("class T1 {\n"); + buf1.append(" int bar(int i, int j) { return i + j; }\n"); + buf1.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E6.java", buf1.toString(), false, null); + + // [1] + int offset= buf1.toString().indexOf("::/*[1]*/") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E6<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" <F> String method1(E6<T> e) {\n"); + buf.append(" return \"b\";\n"); + buf.append(" }\n"); + buf.append(" Supplier<String> v1 = () -> new E6<Integer>()./*[1]*/method1();\n"); + buf.append(" Supplier<String> v2 = this::/*[2]*/<Float>method1;\n"); + buf.append(" Function<E6<Integer>, String> v3 = new E6<Integer>()::/*[3]*/<Float>method1;\n"); + buf.append(" T1[] ts = new T1[5];\n"); + buf.append(" BiFunction<Integer, Integer, Integer> m6 = ts[1]::/*[4]*/bar;\n"); + buf.append(" int[] is = new int[5];\n"); + buf.append(" Supplier<int[]> m10 = is::/*[5]*/clone;\n"); + buf.append("}\n"); + buf.append("class T1 {\n"); + buf.append(" int bar(int i, int j) { return i + j; }\n"); + buf.append("}\n"); + String expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [2] + offset= buf1.toString().indexOf("::/*[2]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E6<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" <F> String method1(E6<T> e) {\n"); + buf.append(" return \"b\";\n"); + buf.append(" }\n"); + buf.append(" Supplier<String> v1 = new E6<Integer>()::/*[1]*/method1;\n"); + buf.append(" Supplier<String> v2 = () -> this.<Float> method1();\n"); + buf.append(" Function<E6<Integer>, String> v3 = new E6<Integer>()::/*[3]*/<Float>method1;\n"); + buf.append(" T1[] ts = new T1[5];\n"); + buf.append(" BiFunction<Integer, Integer, Integer> m6 = ts[1]::/*[4]*/bar;\n"); + buf.append(" int[] is = new int[5];\n"); + buf.append(" Supplier<int[]> m10 = is::/*[5]*/clone;\n"); + buf.append("}\n"); + buf.append("class T1 {\n"); + buf.append(" int bar(int i, int j) { return i + j; }\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [3] + offset= buf1.toString().indexOf("::/*[3]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E6<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" <F> String method1(E6<T> e) {\n"); + buf.append(" return \"b\";\n"); + buf.append(" }\n"); + buf.append(" Supplier<String> v1 = new E6<Integer>()::/*[1]*/method1;\n"); + buf.append(" Supplier<String> v2 = this::/*[2]*/<Float>method1;\n"); + buf.append(" Function<E6<Integer>, String> v3 = arg0 -> new E6<Integer>().<Float> method1(arg0);\n"); + buf.append(" T1[] ts = new T1[5];\n"); + buf.append(" BiFunction<Integer, Integer, Integer> m6 = ts[1]::/*[4]*/bar;\n"); + buf.append(" int[] is = new int[5];\n"); + buf.append(" Supplier<int[]> m10 = is::/*[5]*/clone;\n"); + buf.append("}\n"); + buf.append("class T1 {\n"); + buf.append(" int bar(int i, int j) { return i + j; }\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [4] + offset= buf1.toString().indexOf("::/*[4]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E6<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" <F> String method1(E6<T> e) {\n"); + buf.append(" return \"b\";\n"); + buf.append(" }\n"); + buf.append(" Supplier<String> v1 = new E6<Integer>()::/*[1]*/method1;\n"); + buf.append(" Supplier<String> v2 = this::/*[2]*/<Float>method1;\n"); + buf.append(" Function<E6<Integer>, String> v3 = new E6<Integer>()::/*[3]*/<Float>method1;\n"); + buf.append(" T1[] ts = new T1[5];\n"); + buf.append(" BiFunction<Integer, Integer, Integer> m6 = (arg0, arg1) -> ts[1]./*[4]*/bar(arg0, arg1);\n"); + buf.append(" int[] is = new int[5];\n"); + buf.append(" Supplier<int[]> m10 = is::/*[5]*/clone;\n"); + buf.append("}\n"); + buf.append("class T1 {\n"); + buf.append(" int bar(int i, int j) { return i + j; }\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [5] + offset= buf1.toString().indexOf("::/*[5]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E6<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" <F> String method1(E6<T> e) {\n"); + buf.append(" return \"b\";\n"); + buf.append(" }\n"); + buf.append(" Supplier<String> v1 = new E6<Integer>()::/*[1]*/method1;\n"); + buf.append(" Supplier<String> v2 = this::/*[2]*/<Float>method1;\n"); + buf.append(" Function<E6<Integer>, String> v3 = new E6<Integer>()::/*[3]*/<Float>method1;\n"); + buf.append(" T1[] ts = new T1[5];\n"); + buf.append(" BiFunction<Integer, Integer, Integer> m6 = ts[1]::/*[4]*/bar;\n"); + buf.append(" int[] is = new int[5];\n"); + buf.append(" Supplier<int[]> m10 = () -> is./*[5]*/clone();\n"); + buf.append("}\n"); + buf.append("class T1 {\n"); + buf.append(" int bar(int i, int j) { return i + j; }\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + } + + public void testConvertMethodReferenceToLambda7() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf1= new StringBuffer(); + buf1.append("package test1;\n"); + buf1.append("import java.util.function.*;\n"); + buf1.append("public class E7<T> {\n"); + buf1.append(" <F> String method1() {\n"); + buf1.append(" return \"a\";\n"); + buf1.append(" }\n"); + buf1.append(" Function<E7<Integer>, String> v1 = E7<Integer>::/*[1]*/<Float> method1;\n"); + buf1.append(" Function<int[], int[]> v2 = int[]::/*[2]*/clone;\n"); + buf1.append(" BiFunction<int[], int[], Boolean> v3 = int[]::/*[3]*/equals;\n"); + buf1.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E7.java", buf1.toString(), false, null); + + // [1] + int offset= buf1.toString().indexOf("::/*[1]*/") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E7<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" Function<E7<Integer>, String> v1 = arg0 -> arg0.<Float> method1();\n"); + buf.append(" Function<int[], int[]> v2 = int[]::/*[2]*/clone;\n"); + buf.append(" BiFunction<int[], int[], Boolean> v3 = int[]::/*[3]*/equals;\n"); + buf.append("}\n"); + String expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [2] + offset= buf1.toString().indexOf("::/*[2]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E7<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" Function<E7<Integer>, String> v1 = E7<Integer>::/*[1]*/<Float> method1;\n"); + buf.append(" Function<int[], int[]> v2 = arg0 -> arg0./*[2]*/clone();\n"); + buf.append(" BiFunction<int[], int[], Boolean> v3 = int[]::/*[3]*/equals;\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + + // [3] + offset= buf1.toString().indexOf("::/*[3]*/") + 1; + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("public class E7<T> {\n"); + buf.append(" <F> String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append(" Function<E7<Integer>, String> v1 = E7<Integer>::/*[1]*/<Float> method1;\n"); + buf.append(" Function<int[], int[]> v2 = int[]::/*[2]*/clone;\n"); + buf.append(" BiFunction<int[], int[], Boolean> v3 = (arg0, arg1) -> arg0./*[3]*/equals(arg1);\n"); + buf.append("}\n"); + expected= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected }); + } + + public void testConvertMethodReferenceToLambda8() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.*;\n"); + buf.append("import java.util.function.Supplier;\n"); + buf.append("public class E8 {\n"); + buf.append(" List<String> list = new ArrayList<>();\n"); + buf.append(" Supplier<Iterator<String>> mr = (list.size() == 5 ? list.subList(0, 3) : list)::iterator;\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E8.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("::") + 1; + 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 java.util.*;\n"); + buf.append("import java.util.function.Supplier;\n"); + buf.append("public class E8 {\n"); + buf.append(" List<String> list = new ArrayList<>();\n"); + buf.append(" Supplier<Iterator<String>> mr = () -> (list.size() == 5 ? list.subList(0, 3) : list).iterator();\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + public void testConvertMethodReferenceToLambda9() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class E9 {\n"); + buf.append(" private void test(int t) {\n"); + buf.append(" FI t1= E9::bar;\n"); + buf.append(" }\n"); + buf.append(" private static void bar(int x, int y, int z) {}\n"); + buf.append("}\n"); + buf.append("interface FI {\n"); + buf.append(" void foo(int t, int t1, int t2);\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E9.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("::") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class E9 {\n"); + buf.append(" private void test(int t) {\n"); + buf.append(" FI t1= (t3, t11, t2) -> E9.bar(t3, t11, t2);\n"); + buf.append(" }\n"); + buf.append(" private static void bar(int x, int y, int z) {}\n"); + buf.append("}\n"); + buf.append("interface FI {\n"); + buf.append(" void foo(int t, int t1, int t2);\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + public void testConvertMethodReferenceToLambda10() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.lang.annotation.*;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("\n"); + buf.append("@Target(ElementType.TYPE_USE)\n"); + buf.append("@interface Great {}\n"); + buf.append("\n"); + buf.append("public class E10 {\n"); + buf.append(" LongSupplier foo() {\n"); + buf.append(" return @Great System::currentTimeMillis;\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E10.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("::") + 1; + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.lang.annotation.*;\n"); + buf.append("import java.util.function.*;\n"); + buf.append("\n"); + buf.append("@Target(ElementType.TYPE_USE)\n"); + buf.append("@interface Great {}\n"); + buf.append("\n"); + buf.append("public class E10 {\n"); + buf.append(" LongSupplier foo() {\n"); + buf.append(" return () -> System.currentTimeMillis();\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + public void testConvertLambdaToMethodReference1() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.BiFunction;\n"); + buf.append("import java.util.function.Consumer;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("import java.util.function.IntFunction;\n"); + buf.append("import java.util.function.Supplier;\n"); + buf.append("public class E1 extends E {\n"); + buf.append(" Supplier<String> a1= () ->/*[1]*/ {\n"); + buf.append(" String s = \"\";\n"); + buf.append(" return s;\n"); + buf.append(" };\n"); + buf.append(" Consumer<String> a2= s ->/*[2]*/ {\n"); + buf.append(" return;\n"); + buf.append(" };\n"); + buf.append("\n"); + buf.append(" Supplier<E1.In> a3= () ->/*[3]*/ (new E1()).new In();\n"); + buf.append(" Supplier<E1> a4= () ->/*[4]*/ new E1() {\n"); + buf.append(" void test() {\n"); + buf.append(" System.out.println(\"hey\");\n"); + buf.append(" }\n"); + buf.append(" };\n"); + buf.append(" Function<String, Integer> a5= s ->/*[5]*/ new Integer(s+1);\n"); + buf.append("\n"); + buf.append(" BiFunction<Integer, Integer, int[][][]> a6 = (a, b) ->/*[6]*/ new int[a][b][];\n"); + buf.append(" IntFunction<Integer[][][]> a61 = value ->/*[61]*/ new Integer[][][] {{{7, 8}}};\n"); + buf.append(" Function<Integer, int[]> a7 = t ->/*[7]*/ new int[100];\n"); + buf.append("\n"); + buf.append(" BiFunction<Character, Integer, String> a8 = (c, i) ->/*[8]*/ super.method1();\n"); + buf.append(" BiFunction<Character, Integer, String> a9 = (c, i) ->/*[9]*/ method1();\n"); + buf.append(" \n"); + buf.append(" class In {}\n"); + buf.append("}\n"); + buf.append("class E {\n"); + buf.append(" String method1() {\n"); + buf.append(" return \"a\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E1.java", buf.toString(), false, null); + + int offset= buf.toString().indexOf("->/*[1]*/"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 1); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[2]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[3]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[4]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[5]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[6]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[61]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[7]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[8]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf.toString().indexOf("->/*[9]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + } + + public void testConvertLambdaToMethodReference2() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf1= new StringBuffer(); + buf1.append("package test1;\n"); + buf1.append("import java.util.function.Function;\n"); + buf1.append("public class E2<T> {\n"); + buf1.append(" public <A> E2(A a) {}\n"); + buf1.append(" public E2(String s) {}\n"); + buf1.append(" \n"); + buf1.append(" Function<T, E2<Integer>> a1 = t ->/*[1]*/ (new<T> E2<Integer>(t));\n"); + buf1.append(" Function<String, E2<Integer>> a2 = t ->/*[2]*/ new E2<>(t);\n"); + buf1.append(" \n"); + buf1.append(" Function<Integer, Float[]> a3 = t ->/*[3]*/ new Float[t];\n"); + buf1.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E2.java", buf1.toString(), false, null); + + int offset= buf1.toString().indexOf("->/*[1]*/"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E2<T> {\n"); + buf.append(" public <A> E2(A a) {}\n"); + buf.append(" public E2(String s) {}\n"); + buf.append(" \n"); + buf.append(" Function<T, E2<Integer>> a1 = E2<Integer>::<T> new;\n"); + buf.append(" Function<String, E2<Integer>> a2 = t ->/*[2]*/ new E2<>(t);\n"); + buf.append(" \n"); + buf.append(" Function<Integer, Float[]> a3 = t ->/*[3]*/ new Float[t];\n"); + buf.append("}\n"); + String expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("->/*[2]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E2<T> {\n"); + buf.append(" public <A> E2(A a) {}\n"); + buf.append(" public E2(String s) {}\n"); + buf.append(" \n"); + buf.append(" Function<T, E2<Integer>> a1 = t ->/*[1]*/ (new<T> E2<Integer>(t));\n"); + buf.append(" Function<String, E2<Integer>> a2 = E2::new;\n"); + buf.append(" \n"); + buf.append(" Function<Integer, Float[]> a3 = t ->/*[3]*/ new Float[t];\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("->/*[3]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E2<T> {\n"); + buf.append(" public <A> E2(A a) {}\n"); + buf.append(" public E2(String s) {}\n"); + buf.append(" \n"); + buf.append(" Function<T, E2<Integer>> a1 = t ->/*[1]*/ (new<T> E2<Integer>(t));\n"); + buf.append(" Function<String, E2<Integer>> a2 = t ->/*[2]*/ new E2<>(t);\n"); + buf.append(" \n"); + buf.append(" Function<Integer, Float[]> a3 = Float[]::new;\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + public void testConvertLambdaToMethodReference3() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf1= new StringBuffer(); + buf1.append("package test1;\n"); + buf1.append("import java.util.function.Function;\n"); + buf1.append("public class E3<T> extends SuperE3<Number> {\n"); + buf1.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf1.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf1.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf1.append("\n"); + buf1.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf1.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf1.append("\n"); + buf1.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf1.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf1.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf1.append("\n"); + buf1.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf1.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf1.append("\n"); + buf1.append(" <V> String method2() { return \"m2\"; }\n"); + buf1.append("}\n"); + buf1.append("class SuperE3<S> {\n"); + buf1.append(" String method1(int i) { return \"m1\"; }\n"); + buf1.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf1.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E3.java", buf1.toString(), false, null); + + int offset= buf1.toString().indexOf("-> /*[1]*/"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = super::method1;\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[2]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = E3.super::method1;\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[3]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = SuperE3::<Float> staticMethod1;\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[4]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = E3::staticMethod1;\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[5]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = E3::staticMethod1;\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[6]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = this::method1;\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[7]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = this::method1;\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[8]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = (new SuperE3<String>())::method1;\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[9]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = E3<Integer>::<Float> method2;\n"); + buf.append(" Function<E3, String> p2 = t -> /*[10]*/t.method2();\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("-> /*[10]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E3<T> extends SuperE3<Number> {\n"); + buf.append(" Function<Integer, String> a1 = t -> /*[1]*/super.method1(t);\n"); + buf.append(" Function<Integer, String> a2 = t -> /*[2]*/E3.super.method1(t);\n"); + buf.append(" Function<Integer, String> a3 = t -> /*[3]*/super.<Float> staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> s1 = t -> /*[4]*/(new E3()).staticMethod1(t);\n"); + buf.append(" Function<Integer, String> s2 = t -> /*[5]*/staticMethod1(t);\n"); + buf.append("\n"); + buf.append(" Function<Integer, String> b1 = t -> /*[6]*/method1(t);\n"); + buf.append(" Function<Integer, String> b2 = t -> /*[7]*/this.method1(t);\n"); + buf.append(" Function<Integer, String> b3 = t -> /*[8]*/(new SuperE3<String>()).method1(t);\n"); + buf.append("\n"); + buf.append(" Function<E3<Integer>, String> p1 = t -> /*[9]*/t.<Float> method2();\n"); + buf.append(" Function<E3, String> p2 = E3::method2;\n"); + buf.append("\n"); + buf.append(" <V> String method2() { return \"m2\"; }\n"); + buf.append("}\n"); + buf.append("class SuperE3<S> {\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" static <V> String staticMethod1(int i) { return \"s\"; }\n"); + buf.append("}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } + + public void testConvertLambdaToMethodReference4() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf1= new StringBuffer(); + buf1.append("package test1;\n"); + buf1.append("import java.util.function.BiFunction;\n"); + buf1.append("import java.util.function.Function;\n"); + buf1.append("public class E4 {\n"); + buf1.append(" static String staticMethod1() { return \"s\"; }\n"); + buf1.append(" Function<E4, String> s1 = t ->/*[1]*/ staticMethod1();\n"); + buf1.append(" \n"); + buf1.append(" int myVal= 0;\n"); + buf1.append(" String method1(int i) { return \"m1\"; }\n"); + buf1.append(" BiFunction<Float, Integer, String> p1 = (t, u) ->/*[2]*/ method1(u);\n"); + buf1.append(" BiFunction<SubE4, Integer, String> p2 = (t, u) ->/*[3]*/ method1(u);\n"); + buf1.append(" \n"); + buf1.append(" BiFunction<SubE4, Integer, String> p3 = (t, u) ->/*[4]*/ t.method1(u);\n"); + buf1.append(" BiFunction<E4, Integer, String> p4 = (t, u) ->/*[5]*/ t.method1(u);\n"); + buf1.append(" \n"); + buf1.append(" Function<int[], int[]> a1 = t ->/*[6]*/ t.clone();\n"); + buf1.append("}\n"); + buf1.append("class SubE4 extends E4 {}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E4.java", buf1.toString(), false, null); + + int offset= buf1.toString().indexOf("->/*[1]*/"); + AssistContext context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + List proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf1.toString().indexOf("->/*[2]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf1.toString().indexOf("->/*[3]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 3); + assertCorrectLabels(proposals); + assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_convert_to_method_reference); + + offset= buf1.toString().indexOf("->/*[4]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.BiFunction;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E4 {\n"); + buf.append(" static String staticMethod1() { return \"s\"; }\n"); + buf.append(" Function<E4, String> s1 = t ->/*[1]*/ staticMethod1();\n"); + buf.append(" \n"); + buf.append(" int myVal= 0;\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" BiFunction<Float, Integer, String> p1 = (t, u) ->/*[2]*/ method1(u);\n"); + buf.append(" BiFunction<SubE4, Integer, String> p2 = (t, u) ->/*[3]*/ method1(u);\n"); + buf.append(" \n"); + buf.append(" BiFunction<SubE4, Integer, String> p3 = SubE4::method1;\n"); + buf.append(" BiFunction<E4, Integer, String> p4 = (t, u) ->/*[5]*/ t.method1(u);\n"); + buf.append(" \n"); + buf.append(" Function<int[], int[]> a1 = t ->/*[6]*/ t.clone();\n"); + buf.append("}\n"); + buf.append("class SubE4 extends E4 {}\n"); + String expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("->/*[5]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.BiFunction;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E4 {\n"); + buf.append(" static String staticMethod1() { return \"s\"; }\n"); + buf.append(" Function<E4, String> s1 = t ->/*[1]*/ staticMethod1();\n"); + buf.append(" \n"); + buf.append(" int myVal= 0;\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" BiFunction<Float, Integer, String> p1 = (t, u) ->/*[2]*/ method1(u);\n"); + buf.append(" BiFunction<SubE4, Integer, String> p2 = (t, u) ->/*[3]*/ method1(u);\n"); + buf.append(" \n"); + buf.append(" BiFunction<SubE4, Integer, String> p3 = (t, u) ->/*[4]*/ t.method1(u);\n"); + buf.append(" BiFunction<E4, Integer, String> p4 = E4::method1;\n"); + buf.append(" \n"); + buf.append(" Function<int[], int[]> a1 = t ->/*[6]*/ t.clone();\n"); + buf.append("}\n"); + buf.append("class SubE4 extends E4 {}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + + offset= buf1.toString().indexOf("->/*[6]*/"); + context= getCorrectionContext(cu, offset, 0); + assertNoErrors(context); + proposals= collectAssists(context, false); + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.function.BiFunction;\n"); + buf.append("import java.util.function.Function;\n"); + buf.append("public class E4 {\n"); + buf.append(" static String staticMethod1() { return \"s\"; }\n"); + buf.append(" Function<E4, String> s1 = t ->/*[1]*/ staticMethod1();\n"); + buf.append(" \n"); + buf.append(" int myVal= 0;\n"); + buf.append(" String method1(int i) { return \"m1\"; }\n"); + buf.append(" BiFunction<Float, Integer, String> p1 = (t, u) ->/*[2]*/ method1(u);\n"); + buf.append(" BiFunction<SubE4, Integer, String> p2 = (t, u) ->/*[3]*/ method1(u);\n"); + buf.append(" \n"); + buf.append(" BiFunction<SubE4, Integer, String> p3 = (t, u) ->/*[4]*/ t.method1(u);\n"); + buf.append(" BiFunction<E4, Integer, String> p4 = (t, u) ->/*[5]*/ t.method1(u);\n"); + buf.append(" \n"); + buf.append(" Function<int[], int[]> a1 = int[]::clone;\n"); + buf.append("}\n"); + buf.append("class SubE4 extends E4 {}\n"); + expected1= buf.toString(); + assertExpectedExistInProposals(proposals, new String[] { expected1 }); + } } diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodes.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodes.java index 3cb6db497a..00d83f2580 100644 --- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodes.java +++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodes.java @@ -691,32 +691,7 @@ public class ASTNodes { if (methodBinding != null) { ITypeBinding invocationTargetType; - if (parent instanceof MethodInvocation || parent instanceof SuperMethodInvocation) { - if (invocationQualifier != null) { - invocationTargetType= invocationQualifier.resolveTypeBinding(); - if (invocationTargetType != null && parent instanceof SuperMethodInvocation) { - invocationTargetType= invocationTargetType.getSuperclass(); - } - } else { - ITypeBinding enclosingType= getEnclosingType(parent); - if (enclosingType != null && parent instanceof SuperMethodInvocation) { - enclosingType= enclosingType.getSuperclass(); - } - if (enclosingType != null) { - IMethodBinding methodInHierarchy= Bindings.findMethodInHierarchy(enclosingType, methodBinding.getName(), methodBinding.getParameterTypes()); - if (methodInHierarchy != null) { - invocationTargetType= enclosingType; - } else { - invocationTargetType= methodBinding.getDeclaringClass(); - } - } else { - // not expected - invocationTargetType= methodBinding.getDeclaringClass(); - } - } - } else { - invocationTargetType= methodBinding.getDeclaringClass(); - } + invocationTargetType= getInvocationType(parent, methodBinding, invocationQualifier); if (invocationTargetType != null) { TypeBindingVisitor visitor= new AmbiguousTargetMethodAnalyzer(invocationTargetType, methodBinding, argumentIndex, argumentCount, expressionIsExplicitlyTyped); return !(visitor.visit(invocationTargetType) && Bindings.visitHierarchy(invocationTargetType, visitor)); @@ -726,6 +701,47 @@ public class ASTNodes { return true; } + /** + * Returns the binding of the type which declares the method being invoked. + * + * @param invocationNode the method invocation node + * @param methodBinding binding of the method being invoked + * @param invocationQualifier the qualifier used for method invocation, or <code>null</code> if + * none + * @return the binding of the type which declares the method being invoked, or <code>null</code> + * if the type cannot be resolved + */ + public static ITypeBinding getInvocationType(ASTNode invocationNode, IMethodBinding methodBinding, Expression invocationQualifier) { + ITypeBinding invocationType; + if (invocationNode instanceof MethodInvocation || invocationNode instanceof SuperMethodInvocation) { + if (invocationQualifier != null) { + invocationType= invocationQualifier.resolveTypeBinding(); + if (invocationType != null && invocationNode instanceof SuperMethodInvocation) { + invocationType= invocationType.getSuperclass(); + } + } else { + ITypeBinding enclosingType= getEnclosingType(invocationNode); + if (enclosingType != null && invocationNode instanceof SuperMethodInvocation) { + enclosingType= enclosingType.getSuperclass(); + } + if (enclosingType != null) { + IMethodBinding methodInHierarchy= Bindings.findMethodInHierarchy(enclosingType, methodBinding.getName(), methodBinding.getParameterTypes()); + if (methodInHierarchy != null) { + invocationType= enclosingType; + } else { + invocationType= methodBinding.getDeclaringClass(); + } + } else { + // not expected + invocationType= methodBinding.getDeclaringClass(); + } + } + } else { + invocationType= methodBinding.getDeclaringClass(); + } + return invocationType; + } + private static class AmbiguousTargetMethodAnalyzer implements TypeBindingVisitor { private ITypeBinding fDeclaringType; private IMethodBinding fOriginalMethod; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java index 1c10ed4d97..d19910ce6c 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java @@ -47,11 +47,13 @@ public final class CorrectionMessages extends NLS { public static String QuickAssistProcessor_convert_local_to_field_description; public static String QuickAssistProcessor_convert_to_indexed_for_loop; public static String QuickAssistProcessor_convert_to_iterator_for_loop; + public static String QuickAssistProcessor_convert_to_lambda_expression; public static String QuickAssistProcessor_generate_enhanced_for_loop; public static String QuickAssistProcessor_generate_iterator_for_loop; public static String QuickAssistProcessor_generate_for_loop; public static String QuickAssistProcessor_generate_index_for_loop; public static String QuickAssistProcessor_convert_to_message_format; + public static String QuickAssistProcessor_convert_to_method_reference; public static String QuickAssistProcessor_convert_to_multiple_singletype_catch_blocks; public static String QuickAssistProcessor_convert_to_single_multicatch_block; public static String QuickAssistProcessor_convert_to_string_buffer_description; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties index 219f42106c..4017bec53a 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties @@ -347,11 +347,13 @@ QuickAssistProcessor_typetoarrayInitializer_description=Add type to initializer QuickAssistProcessor_convert_local_to_field_description=Convert local variable to field QuickAssistProcessor_convert_to_indexed_for_loop=Convert to 'for' loop using index QuickAssistProcessor_convert_to_iterator_for_loop=Convert to 'for' loop using Iterator +QuickAssistProcessor_convert_to_lambda_expression=Convert to lambda expression QuickAssistProcessor_generate_enhanced_for_loop=Create enhanced 'for' loop QuickAssistProcessor_generate_iterator_for_loop=Create 'for' loop using Iterator QuickAssistProcessor_generate_for_loop=Create 'for' loop QuickAssistProcessor_generate_index_for_loop=Create 'for' loop using index QuickAssistProcessor_convert_to_message_format=Use 'MessageFormat' for string concatenation +QuickAssistProcessor_convert_to_method_reference=Convert to method reference QuickAssistProcessor_convert_to_multiple_singletype_catch_blocks=Use separate catch blocks QuickAssistProcessor_convert_to_single_multicatch_block=Combine catch blocks QuickAssistProcessor_convert_to_string_buffer_description=Use ''{0}'' for string concatenation diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/IProposalRelevance.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/IProposalRelevance.java index d9f0fca11d..56723e3965 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/IProposalRelevance.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/IProposalRelevance.java @@ -126,6 +126,8 @@ public interface IProposalRelevance { public static final int CHANGE_TO_ATTRIBUTE_SIMILAR_NAME= 6; public static final int CREATE_FIELD= 6; public static final int CONVERT_TO_LAMBDA_EXPRESSION= 6; + public static final int CONVERT_METHOD_REFERENCE_TO_LAMBDA= 6; + public static final int CONVERT_TO_METHOD_REFERENCE= 6; public static final int ADD_ALL_MISSING_TAGS= 5; public static final int QUALIFY_INNER_TYPE_NAME= 5; @@ -290,7 +292,7 @@ public interface IProposalRelevance { public static final int ADD_PARANOIDAL_PARENTHESES= -9; public static final int ADD_PARENTHESES_FOR_EXPRESSION= -10; - + //Be careful while tweaking these values because WordCorrectionProposal uses -distance (between the words) as relevance. public static final int DISABLE_SPELL_CHECKING= Integer.MIN_VALUE + 1; public static final int WORD_IGNORE= Integer.MIN_VALUE + 1; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java index 4c8b230cba..d4d0df9523 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java @@ -42,6 +42,7 @@ import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModelMarker; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; @@ -63,10 +64,12 @@ import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ConditionalExpression; +import org.eclipse.jdt.core.dom.CreationReference; import org.eclipse.jdt.core.dom.Dimension; import org.eclipse.jdt.core.dom.DoStatement; import org.eclipse.jdt.core.dom.EnhancedForStatement; import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ExpressionMethodReference; import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.FieldAccess; import org.eclipse.jdt.core.dom.ForStatement; @@ -81,6 +84,7 @@ import org.eclipse.jdt.core.dom.LabeledStatement; 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.MethodReference; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.NameQualifiedType; @@ -99,6 +103,7 @@ import org.eclipse.jdt.core.dom.Statement; import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; import org.eclipse.jdt.core.dom.SuperMethodInvocation; +import org.eclipse.jdt.core.dom.SuperMethodReference; import org.eclipse.jdt.core.dom.SwitchCase; import org.eclipse.jdt.core.dom.SwitchStatement; import org.eclipse.jdt.core.dom.SynchronizedStatement; @@ -106,6 +111,7 @@ import org.eclipse.jdt.core.dom.ThisExpression; import org.eclipse.jdt.core.dom.TryStatement; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.TypeMethodReference; import org.eclipse.jdt.core.dom.UnionType; import org.eclipse.jdt.core.dom.VariableDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationExpression; @@ -123,6 +129,7 @@ import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; import org.eclipse.jdt.internal.corext.dom.ASTNodes; import org.eclipse.jdt.internal.corext.dom.Bindings; import org.eclipse.jdt.internal.corext.dom.DimensionRewrite; +import org.eclipse.jdt.internal.corext.dom.JdtASTMatcher; import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder; import org.eclipse.jdt.internal.corext.dom.ModifierRewrite; import org.eclipse.jdt.internal.corext.dom.Selection; @@ -236,6 +243,8 @@ public class QuickAssistProcessor implements IQuickAssistProcessor { || getChangeLambdaBodyToBlockProposal(context, coveringNode, null) || getChangeLambdaBodyToExpressionProposal(context, coveringNode, null) || getAddInferredLambdaParameterTypes(context, coveringNode, null) + || getConvertMethodReferenceToLambdaProposal(context, coveringNode, null) + || getConvertLambdaToMethodReferenceProposal(context, coveringNode, null) || getRemoveBlockProposals(context, coveringNode, null) || getMakeVariableDeclarationFinalProposals(context, null) || getMissingCaseStatementProposals(context, coveringNode, null) @@ -285,6 +294,8 @@ public class QuickAssistProcessor implements IQuickAssistProcessor { getChangeLambdaBodyToBlockProposal(context, coveringNode, resultingCollections); getChangeLambdaBodyToExpressionProposal(context, coveringNode, resultingCollections); getAddInferredLambdaParameterTypes(context, coveringNode, resultingCollections); + getConvertMethodReferenceToLambdaProposal(context, coveringNode, resultingCollections); + getConvertLambdaToMethodReferenceProposal(context, coveringNode, resultingCollections); if (!getConvertForLoopProposal(context, coveringNode, resultingCollections)) getConvertIterableLoopProposal(context, coveringNode, resultingCollections); getConvertEnhancedForLoopProposal(context, coveringNode, resultingCollections); @@ -595,6 +606,219 @@ public class QuickAssistProcessor implements IQuickAssistProcessor { return true; } + private static boolean getConvertMethodReferenceToLambdaProposal(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) throws JavaModelException { + MethodReference methodReference; + if (covering instanceof MethodReference) { + methodReference= (MethodReference) covering; + } else if (covering.getParent() instanceof MethodReference) { + methodReference= (MethodReference) covering.getParent(); + } else { + return false; + } + + IMethodBinding referredMethodBinding= methodReference.resolveMethodBinding(); + if (referredMethodBinding == null && !(methodReference instanceof CreationReference)) + return false; + + ITypeBinding targetTypeBinding= ASTNodes.getTargetType(methodReference); + if (targetTypeBinding == null) + return false; + + IMethodBinding functionalMethod= targetTypeBinding.getFunctionalInterfaceMethod(); + if (functionalMethod.isSynthetic()) { + functionalMethod= Bindings.findOverriddenMethodInType(functionalMethod.getDeclaringClass(), functionalMethod); + } + if (functionalMethod == null) + return false; + if (functionalMethod.isGenericMethod()) // generic lambda expressions are not allowed + return false; + + if (resultingCollections == null) + return true; + + AST ast= methodReference.getAST(); + ASTRewrite rewrite= ASTRewrite.create(ast); + ImportRewrite importRewrite= null; + LambdaExpression lambda= ast.newLambdaExpression(); + + String[] lambdaParamNames= getUniqueParameterNames(methodReference, functionalMethod); + List<VariableDeclaration> lambdaParameters= lambda.parameters(); + for (String paramName : lambdaParamNames) { + VariableDeclarationFragment lambdaParameter= ast.newVariableDeclarationFragment(); + lambdaParameter.setName(ast.newSimpleName(paramName)); + lambdaParameters.add(lambdaParameter); + } + + int noOfLambdaParameters= lambdaParamNames.length; + lambda.setParentheses(noOfLambdaParameters != 1); + + if (methodReference instanceof CreationReference) { + CreationReference creationRef= (CreationReference) methodReference; + Type type= creationRef.getType(); + if (type instanceof ArrayType) { + ArrayCreation arrayCreation= ast.newArrayCreation(); + lambda.setBody(arrayCreation); + + ArrayType arrayType= (ArrayType) type; + Type copiedElementType= (Type) rewrite.createCopyTarget(arrayType.getElementType()); + arrayCreation.setType(ast.newArrayType(copiedElementType, arrayType.getDimensions())); + arrayCreation.dimensions().add(ast.newSimpleName(lambdaParamNames[0])); + } else { + ClassInstanceCreation cic= ast.newClassInstanceCreation(); + lambda.setBody(cic); + + ITypeBinding typeBinding= type.resolveBinding(); + if (!(type instanceof ParameterizedType) && typeBinding != null && typeBinding.getTypeDeclaration().isGenericType()) { + cic.setType(ast.newParameterizedType((Type) rewrite.createCopyTarget(type))); + } else { + cic.setType((Type) rewrite.createCopyTarget(type)); + } + cic.arguments().addAll(getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames)); + cic.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments())); + } + + } else if (Modifier.isStatic(referredMethodBinding.getModifiers()) && !referredMethodBinding.isSynthetic()) { // TODO: Remove #isSynthetic check after bug 440344 is fixed (eg: int[]::clone) + MethodInvocation methodInvocation= ast.newMethodInvocation(); + lambda.setBody(methodInvocation); + + Expression expr= null; + if (methodReference instanceof ExpressionMethodReference) { + ExpressionMethodReference expressionMethodReference= (ExpressionMethodReference) methodReference; + expr= (Expression) rewrite.createCopyTarget(expressionMethodReference.getExpression()); + } else if (methodReference instanceof TypeMethodReference) { + Type type= ((TypeMethodReference) methodReference).getType(); + ITypeBinding typeBinding= type.resolveBinding(); + if (typeBinding != null) { + importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true); + expr= ast.newName(importRewrite.addImport(typeBinding)); + } + } + if (expr == null) { + return false; + } + methodInvocation.setExpression(expr); + SimpleName name= getMethodInvocationName(methodReference); + methodInvocation.setName((SimpleName) rewrite.createCopyTarget(name)); + methodInvocation.arguments().addAll(getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames)); + methodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments())); + + } else if (methodReference instanceof SuperMethodReference) { + SuperMethodInvocation superMethodInvocation= ast.newSuperMethodInvocation(); + lambda.setBody(superMethodInvocation); + + Name superQualifier= ((SuperMethodReference) methodReference).getQualifier(); + if (superQualifier != null) { + superMethodInvocation.setQualifier((Name) rewrite.createCopyTarget(superQualifier)); + } + SimpleName name= getMethodInvocationName(methodReference); + superMethodInvocation.setName((SimpleName) rewrite.createCopyTarget(name)); + superMethodInvocation.arguments().addAll(getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames)); + superMethodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments())); + + } else { + MethodInvocation methodInvocation= ast.newMethodInvocation(); + lambda.setBody(methodInvocation); + + boolean isTypeReference= isTypeReferenceToInstanceMethod(methodReference); + if (isTypeReference) { + methodInvocation.setExpression(ast.newSimpleName(lambdaParamNames[0])); + } else { + Expression expr= ((ExpressionMethodReference) methodReference).getExpression(); + methodInvocation.setExpression((Expression) rewrite.createCopyTarget(expr)); + } + SimpleName name= getMethodInvocationName(methodReference); + methodInvocation.setName((SimpleName) rewrite.createCopyTarget(name)); + methodInvocation.arguments().addAll(getInvocationArguments(ast, isTypeReference ? 1 : 0, noOfLambdaParameters, lambdaParamNames)); + methodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments())); + } + + rewrite.replace(methodReference, lambda, null); + + // add proposal + String label= CorrectionMessages.QuickAssistProcessor_convert_to_lambda_expression; + Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); + ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CONVERT_METHOD_REFERENCE_TO_LAMBDA, image); + if (importRewrite != null) { + proposal.setImportRewrite(importRewrite); + } + resultingCollections.add(proposal); + return true; + } + + private static String[] getUniqueParameterNames(MethodReference methodReference, IMethodBinding functionalMethod) throws JavaModelException { + String[] parameterNames= ((IMethod) functionalMethod.getJavaElement()).getParameterNames(); + List<String> oldNames= new ArrayList<String>(Arrays.asList(parameterNames)); + String[] newNames= new String[oldNames.size()]; + List<String> excludedNames= new ArrayList<String>(ASTNodes.getVisibleLocalVariablesInScope(methodReference)); + + for (int i= 0; i < oldNames.size(); i++) { + String paramName= oldNames.get(i); + List<String> allNamesToExclude= new ArrayList<String>(excludedNames); + allNamesToExclude.addAll(oldNames.subList(0, i)); + allNamesToExclude.addAll(oldNames.subList(i + 1, oldNames.size())); + if (allNamesToExclude.contains(paramName)) { + String newParamName= createName(paramName, allNamesToExclude); + excludedNames.add(newParamName); + newNames[i]= newParamName; + } else { + newNames[i]= paramName; + } + } + return newNames; + } + + private static String createName(String candidate, List<String> excludedNames) { + int i= 1; + String result= candidate; + while (excludedNames.contains(result)) { + result= candidate + i++; + } + return result; + } + + private static boolean isTypeReferenceToInstanceMethod(MethodReference methodReference) { + if (methodReference instanceof TypeMethodReference) + return true; + if (methodReference instanceof ExpressionMethodReference) { + Expression expression= ((ExpressionMethodReference) methodReference).getExpression(); + if (expression instanceof Name) { + IBinding nameBinding= ((Name) expression).resolveBinding(); + if (nameBinding != null && nameBinding instanceof ITypeBinding) { + return true; + } + } + } + return false; + } + + private static List<SimpleName> getInvocationArguments(AST ast, int begIndex, int noOfLambdaParameters, String[] lambdaParamNames) { + List<SimpleName> args= new ArrayList<SimpleName>(); + for (int i= begIndex; i < noOfLambdaParameters; i++) { + args.add(ast.newSimpleName(lambdaParamNames[i])); + } + return args; + } + + private static List<Type> getCopiedTypeArguments(ASTRewrite rewrite, List<Type> typeArguments) { + List<Type> copiedTypeArgs= new ArrayList<Type>(); + for (Type typeArg : typeArguments) { + copiedTypeArgs.add((Type) rewrite.createCopyTarget(typeArg)); + } + return copiedTypeArgs; + } + + private static SimpleName getMethodInvocationName(MethodReference methodReference) { + SimpleName name= null; + if (methodReference instanceof ExpressionMethodReference) { + name= ((ExpressionMethodReference) methodReference).getName(); + } else if (methodReference instanceof TypeMethodReference) { + name= ((TypeMethodReference) methodReference).getName(); + } else if (methodReference instanceof SuperMethodReference) { + name= ((SuperMethodReference) methodReference).getName(); + } + return name; + } + private static boolean getChangeLambdaBodyToBlockProposal(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) { LambdaExpression lambda; if (covering instanceof LambdaExpression) { @@ -653,26 +877,10 @@ public class QuickAssistProcessor implements IQuickAssistProcessor { return false; Block lambdaBody= (Block) lambda.getBody(); - if (lambdaBody.statements().size() != 1) - return false; - Expression exprBody; - Statement singleStatement= (Statement) lambdaBody.statements().get(0); - if (singleStatement instanceof ReturnStatement) { - Expression returnExpr= ((ReturnStatement) singleStatement).getExpression(); - if (returnExpr == null) - return false; - exprBody= returnExpr; - } else if (singleStatement instanceof ExpressionStatement) { - Expression expression= ((ExpressionStatement) singleStatement).getExpression(); - if (isValidExpressionBody(expression)) { - exprBody= expression; - } else { - return false; - } - } else { + Expression exprBody= getExpressionFromLambdaBody(lambdaBody); + if (exprBody == null) return false; - } if (resultingCollections == null) return true; @@ -691,21 +899,234 @@ public class QuickAssistProcessor implements IQuickAssistProcessor { return true; } + private static Expression getExpressionFromLambdaBody(Block lambdaBody) { + if (lambdaBody.statements().size() != 1) + return null; + Statement singleStatement= (Statement) lambdaBody.statements().get(0); + if (singleStatement instanceof ReturnStatement) { + return ((ReturnStatement) singleStatement).getExpression(); + } else if (singleStatement instanceof ExpressionStatement) { + Expression expression= ((ExpressionStatement) singleStatement).getExpression(); + if (isValidExpressionBody(expression)) { + return expression; + } + } + return null; + } + private static boolean isValidExpressionBody(Expression expression) { - boolean isValidExpressionBody= expression instanceof Assignment + if (expression instanceof Assignment || expression instanceof ClassInstanceCreation || expression instanceof MethodInvocation || expression instanceof PostfixExpression - || expression instanceof SuperMethodInvocation; + || expression instanceof SuperMethodInvocation) { + return true; + } if (expression instanceof PrefixExpression) { Operator operator= ((PrefixExpression) expression).getOperator(); if (operator == Operator.INCREMENT || operator == Operator.DECREMENT) { - isValidExpressionBody= true; + return true; + } + } + return false; + } + + private static boolean getConvertLambdaToMethodReferenceProposal(IInvocationContext context, ASTNode coveringNode, Collection<ICommandAccess> resultingCollections) { + LambdaExpression lambda; + if (coveringNode instanceof LambdaExpression) { + lambda= (LambdaExpression) coveringNode; + } else if (coveringNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY) { + lambda= (LambdaExpression) coveringNode.getParent(); + } else { + return false; + } + + ASTNode lambdaBody= lambda.getBody(); + Expression exprBody; + if (lambdaBody instanceof Block) { + exprBody= getExpressionFromLambdaBody((Block) lambdaBody); + } else { + exprBody= (Expression) lambdaBody; + } + while (exprBody instanceof ParenthesizedExpression) { + exprBody= ((ParenthesizedExpression) exprBody).getExpression(); + } + if (exprBody == null || !isValidReferenceToMethod(exprBody)) + return false; + + List<Expression> lambdaParameters= new ArrayList<Expression>(); + for (VariableDeclaration param : (List<VariableDeclaration>) lambda.parameters()) { + lambdaParameters.add(param.getName()); + } + if (exprBody instanceof ClassInstanceCreation) { + ClassInstanceCreation cic= (ClassInstanceCreation) exprBody; + if (cic.getExpression() != null || cic.getAnonymousClassDeclaration() != null) + return false; + if (!matches(lambdaParameters, cic.arguments())) + return false; + } else if (exprBody instanceof ArrayCreation) { + List<Expression> dimensions= ((ArrayCreation) exprBody).dimensions(); + if (dimensions.size() != 1) + return false; + if (!matches(lambdaParameters, dimensions)) + return false; + } else if (exprBody instanceof SuperMethodInvocation) { + SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) exprBody; + IMethodBinding methodBinding= superMethodInvocation.resolveMethodBinding(); + if (methodBinding == null) + return false; + if (Modifier.isStatic(methodBinding.getModifiers())) { + ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(superMethodInvocation, methodBinding, superMethodInvocation.getQualifier()); + if (invocationTypeBinding == null) + return false; + } + if (!matches(lambdaParameters, superMethodInvocation.arguments())) + return false; + } else { // MethodInvocation + MethodInvocation methodInvocation= (MethodInvocation) exprBody; + IMethodBinding methodBinding= methodInvocation.resolveMethodBinding(); + if (methodBinding == null) + return false; + + Expression invocationExpr= methodInvocation.getExpression(); + if (Modifier.isStatic(methodBinding.getModifiers())) { + ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(methodInvocation, methodBinding, invocationExpr); + if (invocationTypeBinding == null) + return false; + if (!matches(lambdaParameters, methodInvocation.arguments())) + return false; + } else if ((lambda.parameters().size() - methodInvocation.arguments().size()) == 1) { + if (invocationExpr == null) + return false; + ITypeBinding invocationTypeBinding= invocationExpr.resolveTypeBinding(); + if (invocationTypeBinding == null) + return false; + IMethodBinding lambdaMethodBinding= lambda.resolveMethodBinding(); + if (lambdaMethodBinding == null) + return false; + ITypeBinding firstParamType= lambdaMethodBinding.getParameterTypes()[0]; + if (!((Bindings.equals(invocationTypeBinding, firstParamType) || Bindings.isSuperType(invocationTypeBinding, firstParamType)) + && JdtASTMatcher.doNodesMatch(lambdaParameters.get(0), invocationExpr) + && matches(lambdaParameters.subList(1, lambdaParameters.size()), methodInvocation.arguments()))) + return false; + } else if (!matches(lambdaParameters, methodInvocation.arguments())) { + return false; + } + } + + if (resultingCollections == null) + return true; + + AST ast= lambda.getAST(); + ASTRewrite rewrite= ASTRewrite.create(ast); + ImportRewrite importRewrite= null; + MethodReference replacement; + + if (exprBody instanceof ClassInstanceCreation) { + CreationReference creationReference= ast.newCreationReference(); + replacement= creationReference; + + ClassInstanceCreation cic= (ClassInstanceCreation) exprBody; + Type type= cic.getType(); + if (type.isParameterizedType() && ((ParameterizedType) type).typeArguments().size() == 0) { + type= ((ParameterizedType) type).getType(); + } + creationReference.setType((Type) rewrite.createCopyTarget(type)); + creationReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, cic.typeArguments())); + } else if (exprBody instanceof ArrayCreation) { + CreationReference creationReference= ast.newCreationReference(); + replacement= creationReference; + + ArrayType arrayType= ((ArrayCreation) exprBody).getType(); + Type copiedElementType= (Type) rewrite.createCopyTarget(arrayType.getElementType()); + creationReference.setType(ast.newArrayType(copiedElementType, arrayType.getDimensions())); + } else if (exprBody instanceof SuperMethodInvocation) { + SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) exprBody; + IMethodBinding methodBinding= superMethodInvocation.resolveMethodBinding(); + Name superQualifier= superMethodInvocation.getQualifier(); + + if (Modifier.isStatic(methodBinding.getModifiers())) { + TypeMethodReference typeMethodReference= ast.newTypeMethodReference(); + replacement= typeMethodReference; + + typeMethodReference.setName((SimpleName) rewrite.createCopyTarget(superMethodInvocation.getName())); + importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true); + ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(superMethodInvocation, methodBinding, superQualifier); + typeMethodReference.setType(importRewrite.addImport(invocationTypeBinding.getTypeDeclaration(), ast)); + typeMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, superMethodInvocation.typeArguments())); + } else { + SuperMethodReference superMethodReference= ast.newSuperMethodReference(); + replacement= superMethodReference; + + if (superQualifier != null) { + superMethodReference.setQualifier((Name) rewrite.createCopyTarget(superQualifier)); + } + superMethodReference.setName((SimpleName) rewrite.createCopyTarget(superMethodInvocation.getName())); + superMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, superMethodInvocation.typeArguments())); + } + } else { // MethodInvocation + MethodInvocation methodInvocation= (MethodInvocation) exprBody; + IMethodBinding methodBinding= methodInvocation.resolveMethodBinding(); + Expression invocationQualifier= methodInvocation.getExpression(); + + boolean isStaticMethod= Modifier.isStatic(methodBinding.getModifiers()); + boolean isTypeRefToInstanceMethod= methodInvocation.arguments().size() != lambda.parameters().size(); + + if (isStaticMethod || isTypeRefToInstanceMethod) { + TypeMethodReference typeMethodReference= ast.newTypeMethodReference(); + replacement= typeMethodReference; + + typeMethodReference.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName())); + importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true); + ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(methodInvocation, methodBinding, invocationQualifier); + typeMethodReference.setType(importRewrite.addImport(invocationTypeBinding, ast)); + typeMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodInvocation.typeArguments())); + + } else { + ExpressionMethodReference exprMethodReference= ast.newExpressionMethodReference(); + replacement= exprMethodReference; + + exprMethodReference.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName())); + if (invocationQualifier != null) { + exprMethodReference.setExpression((Expression) rewrite.createCopyTarget(invocationQualifier)); + } else { + exprMethodReference.setExpression(ast.newThisExpression()); + } + exprMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodInvocation.typeArguments())); } } - return isValidExpressionBody; + + rewrite.replace(lambda, replacement, null); + + // add correction proposal + String label= CorrectionMessages.QuickAssistProcessor_convert_to_method_reference; + Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE); + ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CONVERT_TO_METHOD_REFERENCE, image); + if (importRewrite != null) { + proposal.setImportRewrite(importRewrite); + } + resultingCollections.add(proposal); + return true; + } + + private static boolean isValidReferenceToMethod(Expression expression) { + return expression instanceof ClassInstanceCreation + || expression instanceof ArrayCreation + || expression instanceof SuperMethodInvocation + || expression instanceof MethodInvocation; + } + + private static boolean matches(List<Expression> expected, List<Expression> toMatch) { + if (toMatch.size() != expected.size()) + return false; + for (int i= 0; i < toMatch.size(); i++) { + if (!JdtASTMatcher.doNodesMatch(expected.get(i), toMatch.get(i))) + return false; + } + return true; } + public static boolean getAddInferredLambdaParameterTypes(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) { LambdaExpression lambda; if (covering instanceof LambdaExpression) { |