From 1aea1b76e711d38369a45638c698d65426b62865 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 8 Jul 2015 19:45:12 +0300 Subject: [PATCH] safe delete: delete type parameters of the overriding method, otherwise it would be a compilation error (IDEA-142378) --- .../daemon/impl/quickfix/SafeDeleteFix.java | 2 +- .../safeDelete/JavaSafeDeleteProcessor.java | 32 +++++++++++++++++-- .../TypeParameterWithinMethodHierarchy.java | 11 +++++++ ...eParameterWithinMethodHierarchy_after.java | 11 +++++++ .../intellij/refactoring/SafeDeleteTest.java | 4 +++ .../src/messages/RefactoringBundle.properties | 1 + 6 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/refactoring/safeDelete/TypeParameterWithinMethodHierarchy.java create mode 100644 java/java-tests/testData/refactoring/safeDelete/TypeParameterWithinMethodHierarchy_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SafeDeleteFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SafeDeleteFix.java index 206dea7c8c02..c5019eab07ab 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SafeDeleteFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SafeDeleteFix.java @@ -59,7 +59,7 @@ public class SafeDeleteFix extends LocalQuickFixAndIntentionActionOnPsiElement { if (startElement instanceof PsiParameter) { SafeDeleteProcessor.createInstance(project, null, elements, false, false, true).run(); } else { - SafeDeleteHandler.invoke(project, elements, false); + SafeDeleteHandler.invoke(project, elements, true); } } diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java index 767bc52f845f..60c8ca56d996 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java @@ -154,9 +154,37 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase { } return parametersToDelete; } - else { - return Collections.singletonList(element); + else if (element instanceof PsiTypeParameter) { + final PsiTypeParameterListOwner owner = ((PsiTypeParameter)element).getOwner(); + if (owner instanceof PsiMethod && !owner.hasModifierProperty(PsiModifier.STATIC)) { + final PsiTypeParameterList typeParameterList = owner.getTypeParameterList(); + if (typeParameterList != null) { + final int index = typeParameterList.getTypeParameterIndex((PsiTypeParameter)element); + if (index >= 0) { + final ArrayList overriders = new ArrayList(); + overriders.add((PsiTypeParameter)element); + OverridingMethodsSearch.search((PsiMethod)owner).forEach(new Processor() { + public boolean process(PsiMethod overrider) { + final PsiTypeParameter[] typeParameters = overrider.getTypeParameters(); + if (index < typeParameters.length) { + overriders.add(typeParameters[index]); + } + return true; + } + }); + if (!overriders.isEmpty()) { + String message = RefactoringBundle.message("0.is.a.part.of.method.hierarchy.do.you.want.to.delete.multiple.type.parameters", UsageViewUtil.getLongName(owner)); + int result = ApplicationManager.getApplication().isUnitTestMode() + ? Messages.YES :Messages.showYesNoCancelDialog(project, message, SafeDeleteHandler.REFACTORING_NAME, Messages.getQuestionIcon()); + if (result == Messages.CANCEL) return null; + if (result == Messages.YES) return overriders; + } + } + } + } } + + return Collections.singletonList(element); } @Override diff --git a/java/java-tests/testData/refactoring/safeDelete/TypeParameterWithinMethodHierarchy.java b/java/java-tests/testData/refactoring/safeDelete/TypeParameterWithinMethodHierarchy.java new file mode 100644 index 000000000000..012a128b71ef --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/TypeParameterWithinMethodHierarchy.java @@ -0,0 +1,11 @@ +class A { + public <T> void foo() {} +} + +class B extends A { + + @Override + public void foo() { + super.foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/safeDelete/TypeParameterWithinMethodHierarchy_after.java b/java/java-tests/testData/refactoring/safeDelete/TypeParameterWithinMethodHierarchy_after.java new file mode 100644 index 000000000000..3606f905be19 --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/TypeParameterWithinMethodHierarchy_after.java @@ -0,0 +1,11 @@ +class A { + public void foo() {} +} + +class B extends A { + + @Override + public void foo() { + super.foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java index e0578927e8d5..280b8fd2b8ae 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java @@ -277,6 +277,10 @@ public class SafeDeleteTest extends MultiFileTestCase { doSingleFileTest(); } + public void testTypeParameterWithinMethodHierarchy() throws Exception { + doSingleFileTest(); + } + public void testClassWithInnerStaticImport() throws Exception { doTest("ClassWithInnerStaticImport"); } diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index b3e85fae875f..31d2c0e8df79 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -712,6 +712,7 @@ please.enter.a.valid.name.for.inverted.element=Please enter a valid name for inv invert.boolean.name.of.inverted.element=&Name of inverted {0}: invert.0.1=Invert {0} {1} and its usages 0.is.a.part.of.method.hierarchy.do.you.want.to.delete.multiple.parameters={0} is a part of method hierarchy. Do you want to delete multiple parameters? +0.is.a.part.of.method.hierarchy.do.you.want.to.delete.multiple.type.parameters={0} is a part of method hierarchy. Do you want to delete multiple type parameters? move.inner.class.to.be.moved=Class to be moved move.specified.classes.to=Move specified classes to: destination.directory.does.not.correspond.to.any.package=The destination directory does not correspond to any package