From b5617168c3a20e80d353bdf00de8763aebc8a877 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 19 Nov 2020 20:48:34 +0100 Subject: [PATCH] java inline chained constructors: ensure elements are not invalidated during processing (IDEA-255661) GitOrigin-RevId: e600dbad74bed7eee0e0979bd1e33a2b7e9870bf --- .../inline/InlineMethodProcessor.java | 47 +++++++++---------- ...inedConstructorWithSpacesInvalidation.java | 10 ++++ ...nstructorWithSpacesInvalidation.java.after | 7 +++ .../refactoring/inline/InlineMethodTest.java | 4 ++ 4 files changed, 42 insertions(+), 26 deletions(-) create mode 100644 java/java-tests/testData/refactoring/inlineMethod/ChainedConstructorWithSpacesInvalidation.java create mode 100644 java/java-tests/testData/refactoring/inlineMethod/ChainedConstructorWithSpacesInvalidation.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java index 7635a223acf9..1aba4dc452e2 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java @@ -604,35 +604,30 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor { private static void replaceParameterReferences(final PsiElement element, final PsiMethod oldConstructor, final PsiExpression[] instanceCreationArguments) { - boolean isParameterReference = false; - if (element instanceof PsiReferenceExpression) { - final PsiReferenceExpression expression = (PsiReferenceExpression)element; - PsiElement resolved = expression.resolve(); - if (resolved instanceof PsiParameter && - element.getManager().areElementsEquivalent(((PsiParameter)resolved).getDeclarationScope(), oldConstructor)) { - isParameterReference = true; - PsiElement declarationScope = ((PsiParameter)resolved).getDeclarationScope(); - PsiParameter[] declarationParameters = ((PsiMethod)declarationScope).getParameterList().getParameters(); - for (int j = 0; j < declarationParameters.length; j++) { - if (declarationParameters[j] == resolved) { - try { - expression.replace(instanceCreationArguments[j]); - } - catch (IncorrectOperationException e) { - LOG.error(e); + Map replacement = new LinkedHashMap<>(); + element.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitReferenceExpression(PsiReferenceExpression expression) { + super.visitReferenceExpression(expression); + PsiElement resolved = expression.resolve(); + if (resolved instanceof PsiParameter && + element.getManager().areElementsEquivalent(((PsiParameter)resolved).getDeclarationScope(), oldConstructor)) { + PsiElement declarationScope = ((PsiParameter)resolved).getDeclarationScope(); + PsiParameter[] declarationParameters = ((PsiMethod)declarationScope).getParameterList().getParameters(); + for (int j = 0; j < declarationParameters.length; j++) { + if (declarationParameters[j] == resolved) { + try { + replacement.put(expression, instanceCreationArguments[j]); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } } } - } + } } - } - if (!isParameterReference) { - PsiElement child = element.getFirstChild(); - while (child != null) { - PsiElement next = child.getNextSibling(); - replaceParameterReferences(child, oldConstructor, instanceCreationArguments); - child = next; - } - } + }); + replacement.forEach(PsiElement::replace); } public void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperationException { diff --git a/java/java-tests/testData/refactoring/inlineMethod/ChainedConstructorWithSpacesInvalidation.java b/java/java-tests/testData/refactoring/inlineMethod/ChainedConstructorWithSpacesInvalidation.java new file mode 100644 index 000000000000..38b7c5296d32 --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineMethod/ChainedConstructorWithSpacesInvalidation.java @@ -0,0 +1,10 @@ +public class Foo { + private Foo(String s, String s2) { + this(s + " " + s2); + } + private Foo(String s) {} + + { + Foo foo = new Foo("a", "b") + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineMethod/ChainedConstructorWithSpacesInvalidation.java.after b/java/java-tests/testData/refactoring/inlineMethod/ChainedConstructorWithSpacesInvalidation.java.after new file mode 100644 index 000000000000..9821799370bd --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineMethod/ChainedConstructorWithSpacesInvalidation.java.after @@ -0,0 +1,7 @@ +public class Foo { + private Foo(String s) {} + + { + Foo foo = new Foo("a" + " " + "b") + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/inline/InlineMethodTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/inline/InlineMethodTest.java index 07b075996755..3f4ca68e4b79 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/inline/InlineMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/inline/InlineMethodTest.java @@ -221,6 +221,10 @@ public class InlineMethodTest extends LightRefactoringTestCase { doTestInlineThisOnly(); } + public void testChainedConstructorWithSpacesInvalidation() { + doTest(); + } + public void testChainedConstructor1() { doTest(); }