From 02a33bd98411eae5bcfde48b905219f93825c66d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 23 Oct 2025 11:57:31 +0200 Subject: [PATCH] Java: ignore duplicates in constructor after Introduce Parameter (IDEA-381116) GitOrigin-RevId: 6d16a2a593d2eb28e4b1a949377bdb1126aa2487 --- .../IntroduceParameterProcessor.java | 2 +- .../util/duplicates/MethodDuplicatesHandler.java | 9 +++++++-- .../afterCodeDuplicatesFromConstructor.java | 2 +- .../afterIgnoreDuplicatesInConstructor.java | 14 ++++++++++++++ .../beforeIgnoreDuplicatesInConstructor.java | 14 ++++++++++++++ .../java/refactoring/IntroduceParameterTest.java | 11 +++++++++-- 6 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 java/java-tests/testData/refactoring/introduceParameter/afterIgnoreDuplicatesInConstructor.java create mode 100644 java/java-tests/testData/refactoring/introduceParameter/beforeIgnoreDuplicatesInConstructor.java diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java index 6863432169c0..897a7f755927 100644 --- a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java +++ b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceParameter/IntroduceParameterProcessor.java @@ -501,7 +501,7 @@ public class IntroduceParameterProcessor extends BaseRefactoringProcessor implem } private void processMethodsDuplicates() { - if (!myMethodToReplaceIn.isValid()) return; + if (!myMethodToReplaceIn.isValid() || !MethodDuplicatesHandler.isAvailableOn(myMethodToReplaceIn)) return; MethodDuplicatesHandler.invokeOnScope(myProject, Collections.singleton(myMethodToReplaceIn), new AnalysisScope(myMethodToReplaceIn.getContainingFile()), true); } diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java b/java/java-impl-refactorings/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java index 634038491ff1..14abbb1d7c04 100644 --- a/java/java-impl-refactorings/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java +++ b/java/java-impl-refactorings/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.refactoring.util.duplicates; import com.intellij.analysis.AnalysisScope; @@ -55,6 +55,10 @@ public class MethodDuplicatesHandler implements RefactoringActionHandler, Contex @Override public boolean isAvailableForQuickList(@NotNull Editor editor, @NotNull PsiFile file, @NotNull DataContext dataContext) { PsiMember member = findMember(editor, file); + return isAvailableOn(member); + } + + public static boolean isAvailableOn(PsiMember member) { return member != null && getCannotRefactorMessage(member) == null; } @@ -100,7 +104,8 @@ public class MethodDuplicatesHandler implements RefactoringActionHandler, Contex final Module module = ModuleUtilCore.findModuleForPsiElement(file); final BaseAnalysisActionDialog dlg = new BaseAnalysisActionDialog(JavaRefactoringBundle.message("replace.method.duplicates.scope.chooser.title", getRefactoringName()), - JavaRefactoringBundle.message("replace.method.duplicates.scope.chooser.message"), project, BaseAnalysisActionDialog.standardItems(project, scope, module, element), + JavaRefactoringBundle.message("replace.method.duplicates.scope.chooser.message"), project, + BaseAnalysisActionDialog.standardItems(project, scope, module, element), AnalysisUIOptions.getInstance(project), false); if (dlg.showAndGet()) { AnalysisScope selectedScope = dlg.getScope(scope); diff --git a/java/java-tests/testData/refactoring/introduceParameter/afterCodeDuplicatesFromConstructor.java b/java/java-tests/testData/refactoring/introduceParameter/afterCodeDuplicatesFromConstructor.java index 889fd06ea058..3ae24a37ddf3 100644 --- a/java/java-tests/testData/refactoring/introduceParameter/afterCodeDuplicatesFromConstructor.java +++ b/java/java-tests/testData/refactoring/introduceParameter/afterCodeDuplicatesFromConstructor.java @@ -5,7 +5,7 @@ class A { class B extends A { public B(String a) { - this(a, ""); + super(a); } public B(String a, final String anObject) { super(a); diff --git a/java/java-tests/testData/refactoring/introduceParameter/afterIgnoreDuplicatesInConstructor.java b/java/java-tests/testData/refactoring/introduceParameter/afterIgnoreDuplicatesInConstructor.java new file mode 100644 index 000000000000..2ddfd5dd7add --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceParameter/afterIgnoreDuplicatesInConstructor.java @@ -0,0 +1,14 @@ +class Surreptitious { + Surreptitious(int i) { + System.out.println(i); + } + + void x(int i) { + System.out.println(i); + } +} +class Clandestine { + void y(int i) { + System.out.println(i); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceParameter/beforeIgnoreDuplicatesInConstructor.java b/java/java-tests/testData/refactoring/introduceParameter/beforeIgnoreDuplicatesInConstructor.java new file mode 100644 index 000000000000..0960af5cb52a --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceParameter/beforeIgnoreDuplicatesInConstructor.java @@ -0,0 +1,14 @@ +class Surreptitious { + Surreptitious() { + System.out.println(0); + } + + void x(int i) { + System.out.println(i); + } +} +class Clandestine { + void y(int i) { + System.out.println(i); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceParameterTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceParameterTest.java index 27ce7cbbb317..4ddeac727fe1 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceParameterTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceParameterTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.refactoring; import com.intellij.JavaTestUtil; @@ -386,6 +386,13 @@ public class IntroduceParameterTest extends LightJavaCodeInsightTestCase { NonBlockingReadActionImpl.waitForAsyncTaskCompletion(); checkResultByFile("/refactoring/introduceParameter/after" + getTestName(false) + ".java"); } + + public void testIgnoreDuplicatesInConstructor() { + configureByFile("/refactoring/introduceParameter/before" + getTestName(false) + ".java"); + perform(IntroduceVariableBase.JavaReplaceChoice.ALL, 0, "i", false, false, true, false, 0, true); + NonBlockingReadActionImpl.waitForAsyncTaskCompletion(); + checkResultByFile("/refactoring/introduceParameter/after" + getTestName(false) + ".java"); + } public void testTypeAnnotation() { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); @@ -521,7 +528,7 @@ public class IntroduceParameterTest extends LightJavaCodeInsightTestCase { boolean removeLocalVariable, boolean replaceAllOccurrences, boolean declareFinal, - final boolean removeUnusedParameters) { + boolean removeUnusedParameters) { final int offset = getEditor().getCaretModel().getOffset(); final PsiElement element = Objects.requireNonNull(getFile().findElementAt(offset)).getParent(); assertTrue(element instanceof PsiLocalVariable);