diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java index c254f92d8e63..174da3d5d6fc 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java @@ -152,6 +152,7 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor { findSubmemberHidesMemberCollisions(methodToRename, newName, result); findMemberHidesOuterMemberCollisions((PsiMethod) element, newName, result); findCollisionsAgainstNewName(methodToRename, newName, result); + findHidingMethodWithOtherSignature(methodToRename, newName, result); final PsiClass containingClass = methodToRename.getContainingClass(); if (containingClass != null) { final PsiMethod patternMethod = (PsiMethod)methodToRename.copy(); @@ -175,18 +176,59 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor { } } - public void findExistingNameConflicts(final PsiElement element, final String newName, final MultiMap conflicts) { - if (element instanceof PsiCompiledElement) return; - PsiMethod refactoredMethod = (PsiMethod)element; - if (newName.equals(refactoredMethod.getName())) return; - final PsiMethod prototype = (PsiMethod)refactoredMethod.copy(); + private static void findHidingMethodWithOtherSignature(final PsiMethod methodToRename, final String newName, final List result) { + final PsiClass containingClass = methodToRename.getContainingClass(); + if (containingClass != null) { + final PsiMethod prototype = getPrototypeWithNewName(methodToRename, newName); + if (prototype == null || containingClass.findMethodBySignature(prototype, true) != null) return; + + final PsiMethod[] methodsByName = containingClass.findMethodsByName(newName, true); + if (methodsByName.length > 0) { + + for (UsageInfo info : result) { + final PsiElement element = info.getElement(); + if (element instanceof PsiReferenceExpression) { + if (((PsiReferenceExpression)element).resolve() == methodToRename) { + final PsiMethodCallExpression copy = (PsiMethodCallExpression)JavaPsiFacade.getElementFactory(element.getProject()) + .createExpressionFromText(element.getParent().getText(), element); + final PsiReferenceExpression expression = (PsiReferenceExpression)copy.getMethodExpression().handleElementRename(newName); + final JavaResolveResult resolveResult = expression.advancedResolve(true); + final PsiMember resolveResultElement = (PsiMember)resolveResult.getElement(); + if (resolveResult.isValidResult() && resolveResultElement != null) { + result.add(new UnresolvableCollisionUsageInfo(element, methodToRename) { + @Override + public String getDescription() { + return "Method call would be linked to \"" + RefactoringUIUtil.getDescription(resolveResultElement, true) + + "\" after rename"; + } + }); + break; + } + } + } + } + } + } + } + + private static PsiMethod getPrototypeWithNewName(PsiMethod methodToRename, String newName) { + final PsiMethod prototype = (PsiMethod)methodToRename.copy(); try { prototype.setName(newName); } catch (IncorrectOperationException e) { LOG.error(e); - return; + return null; } + return prototype; + } + + public void findExistingNameConflicts(final PsiElement element, final String newName, final MultiMap conflicts) { + if (element instanceof PsiCompiledElement) return; + final PsiMethod refactoredMethod = (PsiMethod)element; + if (newName.equals(refactoredMethod.getName())) return; + final PsiMethod prototype = getPrototypeWithNewName(refactoredMethod, newName); + if (prototype == null) return; ConflictsUtil.checkMethodConflicts( refactoredMethod.getContainingClass(), diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameMethodCollisionWithOtherSignature.java b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodCollisionWithOtherSignature.java new file mode 100644 index 000000000000..b6273cc915ab --- /dev/null +++ b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodCollisionWithOtherSignature.java @@ -0,0 +1,12 @@ +class RenameTest { + static void foo1(Number n) { + System.out.println("1"); + } + static void foo2(Long i) { + System.out.println("2"); + } + public static void main(String[] args) { + long n = 0; + foo1(n); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignature.java b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignature.java new file mode 100644 index 000000000000..f61861a53911 --- /dev/null +++ b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignature.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class RenameTest { + static void foo1(Number n) { + System.out.println("1"); + } + static void foo2(String i) { + System.out.println("2"); + } + public static void main(String[] args) { + long n = 0; + foo1(n); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignature.java.after b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignature.java.after new file mode 100644 index 000000000000..657d42a74c71 --- /dev/null +++ b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignature.java.after @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class RenameTest { + static void foo2(Number n) { + System.out.println("1"); + } + static void foo2(String i) { + System.out.println("2"); + } + public static void main(String[] args) { + long n = 0; + foo2(n); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java index 018391261a31..b7364982affc 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java @@ -154,6 +154,21 @@ public class RenameCollisionsTest extends LightRefactoringTestCase { fail("Conflicts were not found"); } + public void testRenameMethodCollisionWithOtherSignature() throws Exception { + try { + doTest("foo2"); + } + catch (BaseRefactoringProcessor.ConflictsInTestsException e) { + Assert.assertEquals("Method call would be linked to \"method RenameTest.foo2(Long)\" after rename", e.getMessage()); + return; + } + fail("Conflicts were not found"); + } + + public void testRenameMethodNoCollisionWithOtherSignature() throws Exception { + doTest("foo2"); + } + public void testRenameTypeParameterToExistingClassName() throws Exception { doTest("P"); }