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)

This commit is contained in:
Anna Kozlova
2014-07-22 20:37:38 +02:00
parent f9e6f065a4
commit e9a17dfad8
4 changed files with 68 additions and 6 deletions
@@ -132,6 +132,7 @@ public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionT
final Set<PsiField> candidates,
final Set<PsiField> usedFields,
final boolean ignoreFieldsUsedInMultipleMethods) {
final Set<PsiField> ignored = new HashSet<PsiField>();
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<PsiField> candidates,
Set<PsiField> usedFields,
boolean ignoreFieldsUsedInMultipleMethods) {
boolean ignoreFieldsUsedInMultipleMethods,
Set<PsiField> ignored) {
try {
final Ref<Collection<PsiVariable>> writtenVariables = new Ref<Collection<PsiVariable>>();
final ControlFlow
controlFlow = ControlFlowFactory.getInstance(body.getProject()).getControlFlow(body, AllVariablesControlFlowPolicy.getInstance());
final List<PsiVariable> 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<Collection<PsiVariable>> writtenVariables = new Ref<Collection<PsiVariable>>();
if (candidates.isEmpty()) return;
final List<PsiReferenceExpression> readBeforeWrites = ControlFlowUtil.getReadBeforeWrite(controlFlow);
for (final PsiReferenceExpression readBeforeWrite : readBeforeWrites) {
final PsiElement resolved = readBeforeWrite.resolve();
@@ -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;
}
}
@@ -0,0 +1,18 @@
// "Convert to local" "true"
class MyClassTest {
private boolean editable = false;
private boolean edit<caret>able1 = false;
boolean isEditable() {
return editable;
}
void setEditable(boolean editable) {
this.editable = editable;
}
public void setEditable1(final boolean editable1) {
this.editable1 = editable1;
}
}
@@ -0,0 +1,18 @@
// "Convert to local" "false"
class MyClassTest {
private boolean edit<caret>able = 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;
}
}