Bug 430487: [1.8][refactoring] Rename Method refactoring breaks lambda
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod0/in/A.java b/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod0/in/A.java
new file mode 100644
index 0000000..c46bc4b
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod0/in/A.java
@@ -0,0 +1,9 @@
+package p;
+@FunctionalInterface
+interface I {
+	int m();
+}
+
+public class A {
+	I i1= () -> 2;
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod0/out/A.java b/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod0/out/A.java
new file mode 100644
index 0000000..5e25f4d
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod0/out/A.java
@@ -0,0 +1,9 @@
+package p;
+@FunctionalInterface
+interface I {
+	int k();
+}
+
+public class A {
+	I i1= () -> 2;
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod1/in/A.java b/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod1/in/A.java
new file mode 100644
index 0000000..bde80b9
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod1/in/A.java
@@ -0,0 +1,19 @@
+package p;
+@FunctionalInterface
+interface I {
+    int m();
+}
+
+public class A implements I {
+    I i1= this::m;
+    I i2= A::length;
+
+    @Override
+    public int m() {
+        return 0;
+    }
+
+    public static int length() {
+        return 42;
+    }
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod1/out/A.java b/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod1/out/A.java
new file mode 100644
index 0000000..5ddd706
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/RenameTests18/testMethod1/out/A.java
@@ -0,0 +1,19 @@
+package p;
+@FunctionalInterface
+interface I {
+    int k();
+}
+
+public class A implements I {
+    I i1= this::k;
+    I i2= A::length;
+
+    @Override
+    public int k() {
+        return 0;
+    }
+
+    public static int length() {
+        return 42;
+    }
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/AllRefactoringTests.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/AllRefactoringTests.java
index dc65149..f11b200 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/AllRefactoringTests.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/AllRefactoringTests.java
@@ -21,6 +21,8 @@
 	public static Test suite() {
 		TestSuite suite= new TestSuite(clazz.getName());
 
+		suite.addTest(RenameTests18.suite());
+
 		//--code
 		suite.addTest(ExtractMethodTests.suite());
 		suite.addTest(ExtractMethodTests17.suite());
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/RenameTests.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/RenameTests.java
index a719c10..5e5c7d2 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/RenameTests.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/RenameTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -36,6 +36,8 @@
 		suite.addTest(RenameNonPrivateFieldTests.suite());
 		suite.addTest(RenameJavaProjectTests.suite());
 		suite.addTest(RenameTests18.suite());
+		
+		//XXX: NOT part of AllRefactoringTests. Also add suites there!
 
 		return suite;
 	}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/RenameTests18.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/RenameTests18.java
index 64aa807..0737dd4 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/RenameTests18.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/RenameTests18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 IBM Corporation and others.
+ * Copyright (c) 2013, 2014 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,7 +26,9 @@
 
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.SourceRange;
 import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
@@ -46,11 +48,11 @@
 	}
 
 	public static Test suite() {
-		return new RefactoringTestSetup( new TestSuite(clazz));
+		return setUpTest(new TestSuite(clazz));
 	}
 
 	public static Test setUpTest(Test someTest) {
-		return new RefactoringTestSetup(someTest);
+		return new Java18Setup(someTest);
 	}
 
 	protected String getRefactoringPath() {
@@ -78,7 +80,7 @@
 		return new SourceRange(offset + AbstractSelectionTestCase.SQUARE_BRACKET_OPEN.length(), end - offset);
 	}
 
-	private void helper2(String newFieldName, boolean updateReferences) throws Exception {
+	private void renameLocalVariable(String newFieldName, boolean updateReferences) throws Exception {
 		ParticipantTesting.reset();
 		ICompilationUnit cu= createCUfromTestFile(getPackageP(), "A");
 
@@ -119,22 +121,68 @@
 		assertEqualLines("invalid redo", getFileContents(getOutputTestFileName("A")), cu.getSource());
 	}
 
-
-
-	//--------- tests ----------
 	public void testLambda0() throws Exception {
-		helper2("renamedF", true);
+		renameLocalVariable("renamedF", true);
 	}
 
 	public void testLambda1() throws Exception {
-		helper2("renamedP", true);
+		renameLocalVariable("renamedP", true);
 	}
 
 	public void testLambda2() throws Exception {
-		helper2("renamedIi", true);
+		renameLocalVariable("renamedIi", true);
 	}
 	
 	public void testLambda3() throws Exception {
-		helper2("x_renamed", true);
+		renameLocalVariable("x_renamed", true);
+	}
+
+
+	private void renameMethodInInterface(String methodName, String newMethodName, String[] signatures, boolean shouldPass, boolean updateReferences, boolean createDelegate) throws Exception{
+		ICompilationUnit cu= createCUfromTestFile(getPackageP(), "A");
+		IType interfaceI= getType(cu, "I");
+		IMethod method= interfaceI.getMethod(methodName, signatures);
+
+		RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_METHOD);
+		descriptor.setJavaElement(method);
+		descriptor.setUpdateReferences(updateReferences);
+		descriptor.setNewName(newMethodName);
+		descriptor.setKeepOriginal(createDelegate);
+		descriptor.setDeprecateDelegate(true);
+
+		assertEquals("was supposed to pass", null, performRefactoring(descriptor));
+		if (!shouldPass){
+			assertTrue("incorrect renaming because of a java model bug", ! getFileContents(getOutputTestFileName("A")).equals(cu.getSource()));
+			return;
+		}
+		assertEqualLines("incorrect renaming", getFileContents(getOutputTestFileName("A")), cu.getSource());
+
+		assertTrue("anythingToUndo", RefactoringCore.getUndoManager().anythingToUndo());
+		assertTrue("! anythingToRedo", !RefactoringCore.getUndoManager().anythingToRedo());
+		//assertEquals("1 to undo", 1, Refactoring.getUndoManager().getRefactoringLog().size());
+
+		RefactoringCore.getUndoManager().performUndo(null, new NullProgressMonitor());
+		assertEqualLines("invalid undo", getFileContents(getInputTestFileName("A")), cu.getSource());
+
+		assertTrue("! anythingToUndo", !RefactoringCore.getUndoManager().anythingToUndo());
+		assertTrue("anythingToRedo", RefactoringCore.getUndoManager().anythingToRedo());
+		//assertEquals("1 to redo", 1, Refactoring.getUndoManager().getRedoStack().size());
+
+		RefactoringCore.getUndoManager().performRedo(null, new NullProgressMonitor());
+		assertEqualLines("invalid redo", getFileContents(getOutputTestFileName("A")), cu.getSource());
+	}
+
+	private void renameMethodInInterface() throws Exception{
+		renameMethodInInterface("m", "k", new String[0], true, true, false);
+	}
+	
+	// method with a lambda method as reference
+	public void testMethod0() throws Exception{
+		renameMethodInInterface();
+	}
+	
+	// method with method references as reference
+	public void testMethod1() throws Exception{
+		renameMethodInInterface();
 	}
 }
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/rename/MethodOccurenceCollector.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/rename/MethodOccurenceCollector.java
index 8aca3a1..7d88247 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/rename/MethodOccurenceCollector.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/rename/MethodOccurenceCollector.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,9 +13,11 @@
 import org.eclipse.core.runtime.CoreException;
 
 import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.compiler.IScanner;
 import org.eclipse.jdt.core.compiler.ITerminalSymbols;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.core.search.MethodDeclarationMatch;
 import org.eclipse.jdt.core.search.MethodReferenceMatch;
 import org.eclipse.jdt.core.search.SearchMatch;
 
@@ -58,6 +60,14 @@
 			return;
 		}
 
+		// lambda expression
+		if (match instanceof MethodDeclarationMatch
+				&& match.getElement() instanceof IMethod
+				&& ((IMethod) match.getElement()).isLambdaMethod()) {
+			// don't touch the lambda
+			return;
+		}
+
 		//Not a standard reference -- use scanner to find last identifier token before left parenthesis:
 		IScanner scanner= getScanner(unit);
 		scanner.setSource(matchText.toCharArray());