From 2b0a160b8af18d0549b258baa6d11abcd6bfbfdc Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 24 Jul 2019 17:10:21 +0700 Subject: [PATCH] VariableExtractor: do not rewrite while-loop condition if occurrences appear outside of the loop (IDEA-218704) GitOrigin-RevId: 213471de9a6d623336673a3b968ec4724215012a --- .../introduceVariable/VariableExtractor.java | 5 +++-- .../WhileConditionPlusNormal.after.java | 15 +++++++++++++++ .../WhileConditionPlusNormal.java | 14 ++++++++++++++ .../WhileConditionPlusNormal2.after.java | 15 +++++++++++++++ .../WhileConditionPlusNormal2.java | 14 ++++++++++++++ .../java/refactoring/IntroduceVariableTest.java | 2 ++ 6 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal.after.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal2.after.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal2.java diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java index b765c450d72f..0ab2c25f1d28 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java @@ -279,8 +279,9 @@ class VariableExtractor { Set allOccurrences = StreamEx.of(occurrences).append(expr).toSet(); PsiExpression firstOccurrence = Collections.min(allOccurrences, Comparator.comparing(e -> e.getTextRange().getStartOffset())); if (anchor instanceof PsiWhileStatement) { - PsiExpression condition = ((PsiWhileStatement)anchor).getCondition(); - if (condition != null) { + PsiWhileStatement whileStatement = (PsiWhileStatement)anchor; + PsiExpression condition = whileStatement.getCondition(); + if (condition != null && allOccurrences.stream().allMatch(occurrence -> PsiTreeUtil.isAncestor(whileStatement, occurrence, true))) { if (firstOccurrence != null && PsiTreeUtil.isAncestor(condition, firstOccurrence, false)) { PsiPolyadicExpression polyadic = ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(condition), PsiPolyadicExpression.class); if (polyadic != null && JavaTokenType.ANDAND.equals(polyadic.getOperationTokenType())) { diff --git a/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal.after.java b/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal.after.java new file mode 100644 index 000000000000..b51842c75ab6 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal.after.java @@ -0,0 +1,15 @@ +import java.util.Arrays; + +class Test { + void foo(int[] a) { + int log = 0; + int temp = a.length; + while (1 << log < temp) { + log++; + } + int n = 1 << log; + int[] b = new int[2 * n]; + System.arraycopy(a, 0, b, n, temp); + Arrays.fill(b, n + temp, 2 * n, -1); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal.java b/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal.java new file mode 100644 index 000000000000..b1d8848a67e1 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal.java @@ -0,0 +1,14 @@ +import java.util.Arrays; + +class Test { + void foo(int[] a) { + int log = 0; + while (1 << log < a.length) { + log++; + } + int n = 1 << log; + int[] b = new int[2 * n]; + System.arraycopy(a, 0, b, n, a.length); + Arrays.fill(b, n + a.length, 2 * n, -1); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal2.after.java b/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal2.after.java new file mode 100644 index 000000000000..b51842c75ab6 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal2.after.java @@ -0,0 +1,15 @@ +import java.util.Arrays; + +class Test { + void foo(int[] a) { + int log = 0; + int temp = a.length; + while (1 << log < temp) { + log++; + } + int n = 1 << log; + int[] b = new int[2 * n]; + System.arraycopy(a, 0, b, n, temp); + Arrays.fill(b, n + temp, 2 * n, -1); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal2.java b/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal2.java new file mode 100644 index 000000000000..7a5df5a4898b --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/WhileConditionPlusNormal2.java @@ -0,0 +1,14 @@ +import java.util.Arrays; + +class Test { + void foo(int[] a) { + int log = 0; + while (1 << log < a.length) { + log++; + } + int n = 1 << log; + int[] b = new int[2 * n]; + System.arraycopy(a, 0, b, n, a.length); + Arrays.fill(b, n + a.length, 2 * n, -1); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java index 95eb6b6faf36..ebdd04bb5b84 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java @@ -93,6 +93,8 @@ public class IntroduceVariableTest extends LightJavaCodeInsightTestCase { public void testWhileCondition2() { doTest("temp", true, false, false, "Node"); } public void testWhileConditionIncomplete() { doTest("temp", true, false, false, "boolean"); } public void testWhileConditionNoBrace() { doTest("temp", true, false, false, "int"); } + public void testWhileConditionPlusNormal() { doTest("temp", true, false, false, "int"); } + public void testWhileConditionPlusNormal2() { doTest("temp", true, false, false, "int"); } public void testField() { doTest("temp", false, false, false, CommonClassNames.JAVA_LANG_STRING); } public void testFieldAll() { doTest("temp", true, false, false, CommonClassNames.JAVA_LANG_STRING); } public void testCaseLabel() { doTest("temp", true, false, false, "int"); }