From 67819c1e1fad4a8cdbd212855f918fdbd5c25f48 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 26 Jun 2017 16:05:46 +0300 Subject: [PATCH] disable move initializer to constructor for final fields with usages in initializers (IDEA-174973) --- .../MoveInitializerToConstructorAction.java | 29 ++++++++++++++++--- .../beforeUsedInAnotherField.java | 5 ++++ 2 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeUsedInAnotherField.java diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java index 64e39663ef48..095349d0079c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java @@ -21,10 +21,11 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.QuickFixFactory; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiModifier; +import com.intellij.psi.*; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -45,6 +46,26 @@ public class MoveInitializerToConstructorAction extends BaseMoveInitializerToMet return CodeInsightBundle.message("intention.move.initializer.to.constructor"); } + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + if (super.isAvailable(project, editor, element)) { + final PsiField field = PsiTreeUtil.getParentOfType(element, PsiField.class); + assert field != null; + if (field.hasModifierProperty(PsiModifier.FINAL)) { + PsiClass containingClass = field.getContainingClass(); + assert containingClass != null; + PsiClassInitializer[] initializers = containingClass.getInitializers(); + PsiElement[] elements = + Arrays.stream(containingClass.getFields()) + .filter(f -> f.hasInitializer()).map(f -> f.getInitializer()) + .toArray(PsiElement[]::new); + return ReferencesSearch.search(field, new LocalSearchScope(ArrayUtil.mergeArrays(elements, initializers))).findFirst() == null; + } + return true; + } + return false; + } + @NotNull @Override protected Collection getUnsuitableModifiers() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeUsedInAnotherField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeUsedInAnotherField.java new file mode 100644 index 000000000000..6a8669d4672a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeUsedInAnotherField.java @@ -0,0 +1,5 @@ +// "Move initializer to constructor" "false" +public class X { + final int i=7; + int j = i; +}