IG: check fields with initializers correctly in "Field may be final" inspection

This commit is contained in:
Bas Leijdekkers
2015-07-01 22:40:14 +02:00
parent d01aa8187a
commit 7ea2d6d175
3 changed files with 44 additions and 1 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2013 Bas Leijdekkers
* Copyright 2009-2015 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,10 @@ public class FinalUtils {
private FinalUtils() {}
public static boolean canBeFinal(@NotNull PsiVariable variable) {
if (variable.getInitializer() != null || variable instanceof PsiParameter) {
// parameters hava implicit initializer
return !VariableAccessUtils.variableIsAssigned(variable);
}
final FinalDefiniteAssignment definiteAssignment = new FinalDefiniteAssignment(variable);
DefiniteAssignmentUtil.checkVariable(variable, definiteAssignment);
return definiteAssignment.isDefinitelyAssigned() &&
@@ -16,7 +16,10 @@
package com.siyeh.ig.psiutils;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -79,6 +82,30 @@ public class VariableAccessUtils {
return visitor.isPassed();
}
public static boolean variableIsAssigned(@NotNull PsiVariable variable) {
if (variable instanceof PsiField) {
if (variable.hasModifierProperty(PsiModifier.PRIVATE)) {
final PsiClass aClass = PsiUtil.getTopLevelClass(variable);
return variableIsAssigned(variable, aClass);
}
return !ReferencesSearch.search(variable, variable.getUseScope()).forEach(new Processor<PsiReference>() {
@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
if (!(element instanceof PsiExpression)) {
return true;
}
final PsiExpression expression = (PsiExpression)element;
return !PsiUtil.isAccessedForWriting(expression);
}
});
}
final PsiElement context =
PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class, PsiMethod.class, PsiLambdaExpression.class,
PsiCatchSection.class, PsiForStatement.class, PsiForeachStatement.class);
return variableIsAssigned(variable, context);
}
public static boolean variableIsAssigned(
@NotNull PsiVariable variable, @Nullable PsiElement context) {
if (context == null) {
@@ -886,6 +886,18 @@ class T58 {
x = 3;
}
}
class T59 {
private int i = 0;
{
assert true : i++;
}
}
class T60 {
private int i = 1;
{
if (false) i = 2;
}
}
class Foo {
public interface Accessor<T> {