From 2a8fc8cbc6641102aa156256c3dede08cce49d22 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Mon, 17 Oct 2016 17:50:39 +0200 Subject: [PATCH] extract method object: process parameters as output variables (IDEA-162642) --- .../ExtractMethodObjectProcessor.java | 40 ++++++++++++- .../AssignReturnValueToForeachParameter.java | 34 +++++++++++ ...gnReturnValueToForeachParameter.java.after | 59 +++++++++++++++++++ ...ethodObjectWithMultipleExitPointsTest.java | 4 ++ 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/AssignReturnValueToForeachParameter.java create mode 100644 java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/AssignReturnValueToForeachParameter.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java index 1967e444c74a..e801402502c3 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java @@ -345,6 +345,17 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { } } + @Override + public void visitParameter(PsiParameter parameter) { + super.visitParameter(parameter); + final PsiElement declarationScope = parameter.getDeclarationScope(); + for (PsiVariable variable : outputVariables) { + if (Comparing.strEqual(variable.getName(), parameter.getName())) { + replacementMap.put(parameter, myElementFactory.createStatementFromText(myInnerClassName + ".this." + var2FieldNames.get(variable.getName()) + " = " + parameter.getName() + ";", declarationScope)); + } + } + } + @Override public void visitReferenceExpression(final PsiReferenceExpression expression) { super.visitReferenceExpression(expression); @@ -368,16 +379,37 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { } } + Map blocksToReplace = new LinkedHashMap<>(); for (PsiElement statement : replacementMap.keySet()) { final PsiElement replacement = replacementMap.get(statement); if (replacement != null) { - if (statement instanceof PsiLocalVariable) { + if (statement instanceof PsiParameter) { + PsiCodeBlock codeBlock = null; + final PsiElement declarationScope = ((PsiParameter)statement).getDeclarationScope(); + if (declarationScope instanceof PsiForeachStatement) { + final PsiStatement loopBody = ((PsiForeachStatement)declarationScope).getBody(); + if (loopBody instanceof PsiBlockStatement) { + codeBlock = ((PsiBlockStatement)loopBody).getCodeBlock(); + } + else { + blocksToReplace.put((PsiStatement)replacement, (PsiForeachStatement)declarationScope); + } + } + else if (declarationScope instanceof PsiCatchSection){ + codeBlock = ((PsiCatchSection)declarationScope).getCatchBlock(); + } + if (codeBlock != null) { + codeBlock.addBefore(replacement, codeBlock.getFirstBodyElement()); + } + } + else if (statement instanceof PsiLocalVariable) { PsiLocalVariable variable = (PsiLocalVariable)statement; variable.normalizeDeclaration(); PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(statement, PsiDeclarationStatement.class); LOG.assertTrue(declaration != null); declaration.replace(replacement); - } else { + } + else { if (statement instanceof PsiReturnStatement) { final PsiExpression returnValue = ((PsiReturnStatement)statement).getReturnValue(); if (!(returnValue instanceof PsiReferenceExpression || returnValue == null || returnValue instanceof PsiLiteralExpression)) { @@ -392,6 +424,10 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { } } + for (PsiStatement statement : blocksToReplace.keySet()) { + RefactoringUtil.putStatementInLoopBody(statement, blocksToReplace.get(statement), null); + } + myChangeReturnType = true; } diff --git a/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/AssignReturnValueToForeachParameter.java b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/AssignReturnValueToForeachParameter.java new file mode 100644 index 000000000000..7a7fdb71711e --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/AssignReturnValueToForeachParameter.java @@ -0,0 +1,34 @@ + +import java.util.Arrays; +import java.util.List; + +class Foo { + private List foos = Arrays.asList(new Foo("one"), new Foo("two")); + + private String name; + + public Foo(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public List getFoos() { + return foos; + } + + public Foo getFoo(String name) { + if (name != null) + for (Foo foo : getFoos()) + if (foo.getName().equals(name)) { + return foo; + } + + + + return null; + } + +} diff --git a/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/AssignReturnValueToForeachParameter.java.after b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/AssignReturnValueToForeachParameter.java.after new file mode 100644 index 000000000000..87aaa35c604d --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/AssignReturnValueToForeachParameter.java.after @@ -0,0 +1,59 @@ + +import java.util.Arrays; +import java.util.List; + +class Foo { + private List foos = Arrays.asList(new Foo("one"), new Foo("two")); + + private String name; + + public Foo(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public List getFoos() { + return foos; + } + + public Foo getFoo(String name) { + if (name != null) + Inner inner = new Inner(name).invoke();if (inner.is()) return inner.getFoo(); + + + return null; + } + + private class Inner { + private boolean myResult; + private String name; + private Foo foo; + + public Inner(String name) { + this.name = name; + } + + boolean is() { + return myResult; + } + + public Foo getFoo() { + return foo; + } + + public Inner invoke() { + for (Foo foo : getFoos()) { + Inner.this.foo = foo; + if (foo.getName().equals(name)) { + myResult = true; + return this; + } + } + myResult = false; + return this; + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObjectWithMultipleExitPointsTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObjectWithMultipleExitPointsTest.java index 0dcfe73574ab..20f78f6e9b33 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObjectWithMultipleExitPointsTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObjectWithMultipleExitPointsTest.java @@ -146,4 +146,8 @@ public class ExtractMethodObjectWithMultipleExitPointsTest extends LightRefactor public void testFormattingInside() throws Exception { doTest(); } + + public void testAssignReturnValueToForeachParameter() throws Exception { + doTest(); + } }