From e9a17dfad87ebab97cbc6177f28df7ec7d0d680f Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 22 Jul 2014 18:32:57 +0200 Subject: [PATCH] field can be local: when field is used in method for read it can't be converted to local if used in another methods (IDEA-127159) --- .../FieldCanBeLocalInspectionBase.java | 21 +++++++++++++------ .../afterMultipleMethodsMultipleFields.java | 17 +++++++++++++++ .../beforeMultipleMethodsMultipleFields.java | 18 ++++++++++++++++ .../beforeMultipleMethodsOnReadOnly.java | 18 ++++++++++++++++ 4 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/afterMultipleMethodsMultipleFields.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethodsMultipleFields.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethodsOnReadOnly.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspectionBase.java index f84abbb0e3d6..e13f3e66a198 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspectionBase.java @@ -132,6 +132,7 @@ public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionT final Set candidates, final Set usedFields, final boolean ignoreFieldsUsedInMultipleMethods) { + final Set ignored = new HashSet(); aClass.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitElement(PsiElement element) { @@ -144,7 +145,7 @@ public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionT final PsiCodeBlock body = method.getBody(); if (body != null) { - checkCodeBlock(body, candidates, usedFields, ignoreFieldsUsedInMultipleMethods); + checkCodeBlock(body, candidates, usedFields, ignoreFieldsUsedInMultipleMethods, ignored); } } @@ -153,14 +154,14 @@ public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionT super.visitLambdaExpression(expression); final PsiElement body = expression.getBody(); if (body != null) { - checkCodeBlock(body, candidates, usedFields, ignoreFieldsUsedInMultipleMethods); + checkCodeBlock(body, candidates, usedFields, ignoreFieldsUsedInMultipleMethods, ignored); } } @Override public void visitClassInitializer(PsiClassInitializer initializer) { super.visitClassInitializer(initializer); - checkCodeBlock(initializer.getBody(), candidates, usedFields, ignoreFieldsUsedInMultipleMethods); + checkCodeBlock(initializer.getBody(), candidates, usedFields, ignoreFieldsUsedInMultipleMethods, ignored); } }); } @@ -168,20 +169,28 @@ public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionT private static void checkCodeBlock(final PsiElement body, final Set candidates, Set usedFields, - boolean ignoreFieldsUsedInMultipleMethods) { + boolean ignoreFieldsUsedInMultipleMethods, + Set ignored) { try { + final Ref> writtenVariables = new Ref>(); final ControlFlow controlFlow = ControlFlowFactory.getInstance(body.getProject()).getControlFlow(body, AllVariablesControlFlowPolicy.getInstance()); final List usedVars = ControlFlowUtil.getUsedVariables(controlFlow, 0, controlFlow.getSize()); for (PsiVariable usedVariable : usedVars) { if (usedVariable instanceof PsiField) { final PsiField usedField = (PsiField)usedVariable; - if (!usedFields.add(usedField) && ignoreFieldsUsedInMultipleMethods) { + if (!getWrittenVariables(controlFlow, writtenVariables).contains(usedField)) { + ignored.add(usedField); + } + + if (!usedFields.add(usedField) && (ignoreFieldsUsedInMultipleMethods || ignored.contains(usedField))) { candidates.remove(usedField); //used in more than one code block } } } - final Ref> writtenVariables = new Ref>(); + + if (candidates.isEmpty()) return; + final List readBeforeWrites = ControlFlowUtil.getReadBeforeWrite(controlFlow); for (final PsiReferenceExpression readBeforeWrite : readBeforeWrites) { final PsiElement resolved = readBeforeWrite.resolve(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/afterMultipleMethodsMultipleFields.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/afterMultipleMethodsMultipleFields.java new file mode 100644 index 000000000000..9d1502b44bc0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/afterMultipleMethodsMultipleFields.java @@ -0,0 +1,17 @@ +// "Convert to local" "true" +class MyClassTest { + + private boolean editable = false; + + boolean isEditable() { + return editable; + } + + void setEditable(boolean editable) { + this.editable = editable; + } + + public void setEditable1(final boolean editable1) { + boolean editable11 = editable1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethodsMultipleFields.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethodsMultipleFields.java new file mode 100644 index 000000000000..4c6ead704f57 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethodsMultipleFields.java @@ -0,0 +1,18 @@ +// "Convert to local" "true" +class MyClassTest { + + private boolean editable = false; + private boolean editable1 = false; + + boolean isEditable() { + return editable; + } + + void setEditable(boolean editable) { + this.editable = editable; + } + + public void setEditable1(final boolean editable1) { + this.editable1 = editable1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethodsOnReadOnly.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethodsOnReadOnly.java new file mode 100644 index 000000000000..db61483db9ad --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convert2Local/beforeMultipleMethodsOnReadOnly.java @@ -0,0 +1,18 @@ +// "Convert to local" "false" +class MyClassTest { + + private boolean editable = false; + private boolean editable1 = false; + + boolean isEditable() { + return editable; + } + + void setEditable(boolean editable) { + this.editable = editable; + } + + public void setEditable1(final boolean editable1) { + this.editable1 = editable1; + } +} \ No newline at end of file