From 0dbd16d7efa9d45d44f38b772319bb2728beea29 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 15 Mar 2010 19:39:04 +0300 Subject: [PATCH] field can be local: treat non-primitive fields as read/write (IDEA-52901) --- .../FieldCanBeLocalInspection.java | 14 +++++++++++--- .../localStateVar2InnerClass/expected.xml | 2 ++ .../localStateVar2InnerClass/src/Test.java | 11 +++++++++++ .../fieldCanBeLocal/stateField/expected.xml | 3 +++ .../fieldCanBeLocal/stateField/src/Test.java | 8 ++++++++ .../codeInspection/FieldCanBeLocalTest.java | 2 ++ 6 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/inspection/fieldCanBeLocal/localStateVar2InnerClass/expected.xml create mode 100644 java/java-tests/testData/inspection/fieldCanBeLocal/localStateVar2InnerClass/src/Test.java create mode 100644 java/java-tests/testData/inspection/fieldCanBeLocal/stateField/expected.xml create mode 100644 java/java-tests/testData/inspection/fieldCanBeLocal/stateField/src/Test.java diff --git a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java index d6c709e8fa87..c78e0a180756 100644 --- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java @@ -15,9 +15,9 @@ */ package com.intellij.codeInspection.varScopeCanBeNarrowed; +import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.ImplicitUsageProvider; -import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; @@ -29,6 +29,7 @@ import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; @@ -153,13 +154,13 @@ public class FieldCanBeLocalInspection extends BaseLocalInspectionTool { } } } - final Collection writtenVariables = ControlFlowUtil.getWrittenVariables(controlFlow, 0, controlFlow.getSize(), false); + final Ref> writtenVariables = new Ref>(); final List readBeforeWrites = ControlFlowUtil.getReadBeforeWrite(controlFlow); for (final PsiReferenceExpression readBeforeWrite : readBeforeWrites) { final PsiElement resolved = readBeforeWrite.resolve(); if (resolved instanceof PsiField) { final PsiField field = (PsiField)resolved; - if (writtenVariables.contains(field)){ + if (!(field.getType() instanceof PsiPrimitiveType) || getWrittenVariables(controlFlow, writtenVariables).contains(field)){ PsiElement parent = body.getParent(); if (!(parent instanceof PsiMethod) || !((PsiMethod)parent).isConstructor() || @@ -177,6 +178,13 @@ public class FieldCanBeLocalInspection extends BaseLocalInspectionTool { } } + private static Collection getWrittenVariables(ControlFlow controlFlow, Ref> writtenVariables) { + if (writtenVariables.get() == null) { + writtenVariables.set(ControlFlowUtil.getWrittenVariables(controlFlow, 0, controlFlow.getSize(), false)); + } + return writtenVariables.get(); + } + private static void removeFieldsReferencedFromInitializers(final PsiClass aClass, final Set candidates) { aClass.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitMethod(PsiMethod method) { diff --git a/java/java-tests/testData/inspection/fieldCanBeLocal/localStateVar2InnerClass/expected.xml b/java/java-tests/testData/inspection/fieldCanBeLocal/localStateVar2InnerClass/expected.xml new file mode 100644 index 000000000000..4704d91e891d --- /dev/null +++ b/java/java-tests/testData/inspection/fieldCanBeLocal/localStateVar2InnerClass/expected.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/fieldCanBeLocal/localStateVar2InnerClass/src/Test.java b/java/java-tests/testData/inspection/fieldCanBeLocal/localStateVar2InnerClass/src/Test.java new file mode 100644 index 000000000000..155a4d1dfd6f --- /dev/null +++ b/java/java-tests/testData/inspection/fieldCanBeLocal/localStateVar2InnerClass/src/Test.java @@ -0,0 +1,11 @@ +import java.util.*; +public class Outer { + private Map value = new HashMap(); + + public class Inner { + + public Inner(String s) { + if (!value.containsKey(s)) value.put(s, ""); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/fieldCanBeLocal/stateField/expected.xml b/java/java-tests/testData/inspection/fieldCanBeLocal/stateField/expected.xml new file mode 100644 index 000000000000..580a889dbfd6 --- /dev/null +++ b/java/java-tests/testData/inspection/fieldCanBeLocal/stateField/expected.xml @@ -0,0 +1,3 @@ + + + diff --git a/java/java-tests/testData/inspection/fieldCanBeLocal/stateField/src/Test.java b/java/java-tests/testData/inspection/fieldCanBeLocal/stateField/src/Test.java new file mode 100644 index 000000000000..79774c0c5ee9 --- /dev/null +++ b/java/java-tests/testData/inspection/fieldCanBeLocal/stateField/src/Test.java @@ -0,0 +1,8 @@ +import java.util.*; +public class Test { + private final Map myModuleToOutput = new HashMap(); + + void foo() { + if (myModuleToOutput.containsKey(null)) myModuleToOutput.put("", ""); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java index 10630e3c49c4..24a8d482ba1b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java @@ -26,4 +26,6 @@ public class FieldCanBeLocalTest extends InspectionTestCase { public void testStaticAccess() throws Exception { doTest(); } public void testInnerClassConstructor() throws Exception { doTest(); } public void testLocalVar2InnerClass() throws Exception { doTest(); } + public void testStateField() throws Exception { doTest(); } + public void testLocalStateVar2InnerClass() throws Exception { doTest(); } }