From 006b9b1742afd2ba558cc23ac0d06ea2c2dd72dc Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Tue, 4 Jul 2017 10:28:25 +0200 Subject: [PATCH] split declaration: detect same variables after declaration (IDEA-175261) --- .../impl/SplitDeclarationAction.java | 26 +++++++++++++++++-- .../codeStyle/JavaCodeStyleManagerImpl.java | 6 ++--- .../afterForLoopAfterAnonymous.java | 15 +++++++++++ .../beforeForLoopAfterAnonymous.java | 14 ++++++++++ ...beforeForLoopConflictingLocalInLambda.java | 9 +++++++ 5 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/afterForLoopAfterAnonymous.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeForLoopAfterAnonymous.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeForLoopConflictingLocalInLambda.java diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java index 479350c73bbc..b8a1fa69b194 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.javadoc.PsiDocComment; @@ -81,10 +82,31 @@ public class SplitDeclarationAction extends PsiElementBaseIntentionAction { PsiElement parent = decl.getParent(); if (parent instanceof PsiForStatement) { String varName = var.getName(); - if (varName == null || - JavaPsiFacade.getInstance(decl.getProject()).getResolveHelper().resolveReferencedVariable(varName, parent.getParent()) != null) { + if (varName == null) { return false; } + + parent = parent.getNextSibling(); + while (parent != null) { + Ref conflictFound = new Ref<>(false); + parent.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitClass(PsiClass aClass) { } + + @Override + public void visitVariable(PsiVariable variable) { + super.visitVariable(variable); + if (varName.equals(variable.getName())) { + conflictFound.set(true); + stopWalking(); + } + } + }); + if (conflictFound.get()) { + return false; + } + parent = parent.getNextSibling(); + } } setText(CodeInsightBundle.message("intention.split.declaration.assignment.text")); return true; diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java index 91aed4ee92c1..7281d2314488 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java @@ -1005,9 +1005,9 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { return true; } - private static boolean hasConflictingVariableAfterwards(@Nullable PsiElement scope, - @NotNull final String name, - @NotNull Predicate canBeReused) { + public static boolean hasConflictingVariableAfterwards(@Nullable PsiElement scope, + @NotNull final String name, + @NotNull Predicate canBeReused) { PsiElement run = scope; while (run != null) { class CancelException extends RuntimeException { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/afterForLoopAfterAnonymous.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/afterForLoopAfterAnonymous.java new file mode 100644 index 000000000000..7b8976121707 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/afterForLoopAfterAnonymous.java @@ -0,0 +1,15 @@ +// "Split into declaration and assignment" "true" +class Test { + { + int i; + for (i = 0; i<10; i++) { + System.out.println(); + } + + new Runnable() { + { + int i = 0; + } + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeForLoopAfterAnonymous.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeForLoopAfterAnonymous.java new file mode 100644 index 000000000000..7bc8ef80e287 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeForLoopAfterAnonymous.java @@ -0,0 +1,14 @@ +// "Split into declaration and assignment" "true" +class Test { + { + for (int i=0; i<10; i++) { + System.out.println(); + } + + new Runnable() { + { + int i = 0; + } + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeForLoopConflictingLocalInLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeForLoopConflictingLocalInLambda.java new file mode 100644 index 000000000000..c7a8aca25945 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeForLoopConflictingLocalInLambda.java @@ -0,0 +1,9 @@ +// "Split into declaration and assignment" "false" +class Test { + { + for (int i=0; i<10; i++) { + System.out.println(); + } + Runnable r = () -> {int i = 0;}; + } +} \ No newline at end of file