Bug 428741: [1.8][quick assist] convert method reference expression to lambda
Bug 439601: [1.8][quick assist] convert lambda expression to method reference
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 d912c7f..2f2b715 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 @@
 		assertNoErrors(context);
 		List proposals= collectAssists(context, false);
 
-		assertNumberOfProposals(proposals, 5);
+		assertNumberOfProposals(proposals, 6);
 		assertCorrectLabels(proposals);
 
 		buf= new StringBuffer();
@@ -1242,7 +1242,7 @@
 		assertNoErrors(context);
 		List proposals= collectAssists(context, false);
 
-		assertNumberOfProposals(proposals, 3);
+		assertNumberOfProposals(proposals, 4);
 		assertCorrectLabels(proposals);
 
 		buf= new StringBuffer();
@@ -1476,7 +1476,7 @@
 		assertNoErrors(context);
 		List proposals= collectAssists(context, false);
 	
-		assertNumberOfProposals(proposals, 2);
+		assertNumberOfProposals(proposals, 3);
 		assertCorrectLabels(proposals);
 	
 		buf= new StringBuffer();
@@ -2100,4 +2100,1415 @@
 		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 3cb6db4..00d83f2 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 @@
 
 		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 @@
 		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 1c10ed4..d19910c 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 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 219f421..4017bec 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_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 d9f0fca1..56723e3 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 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 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 4c8b230..d4d0df9 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.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.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.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.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.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.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 @@
 				|| 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 @@
 				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 @@
 		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 @@
 			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 @@
 		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 isValidExpressionBody;
+		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()));
+			}
+		}
+
+		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) {