Java: make "Field can be local variable" Flexible Constructor Bodies aware (IDEA-364189)

GitOrigin-RevId: 370bf973497cc428ff1fa8047684c62e793941be
This commit is contained in:
Bas Leijdekkers
2025-02-05 10:21:50 +00:00
committed by intellij-monorepo-bot
parent ccc23ffa86
commit bd5e9ca16b
3 changed files with 27 additions and 16 deletions
@@ -19,6 +19,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
@@ -43,14 +44,11 @@ public final class FieldCanBeLocalInspection extends AbstractBaseJavaLocalInspec
public final JDOMExternalizableStringList EXCLUDE_ANNOS = new JDOMExternalizableStringList();
public boolean IGNORE_FIELDS_USED_IN_MULTIPLE_METHODS = true;
private void doCheckClass(PsiClass aClass,
ProblemsHolder holder,
List<String> excludeAnnos,
boolean ignoreFieldsUsedInMultipleMethods) {
private void doCheckClass(PsiClass aClass, ProblemsHolder holder) {
if (aClass.isInterface()) return;
final Set<PsiField> candidates = new LinkedHashSet<>();
final Set<PsiField> candidates = new HashSet<>();
for (PsiField field : aClass.getFields()) {
if (!field.isPhysical() || AnnotationUtil.isAnnotated(field, excludeAnnos, 0)) {
if (!field.isPhysical() || AnnotationUtil.isAnnotated(field, EXCLUDE_ANNOS, 0)) {
continue;
}
if (field.hasModifierProperty(PsiModifier.VOLATILE)) {
@@ -63,16 +61,16 @@ public final class FieldCanBeLocalInspection extends AbstractBaseJavaLocalInspec
candidates.add(field);
}
}
if (candidates.isEmpty()) return;
removeFieldsReferencedFromInitializers(aClass, aClass, candidates);
if (candidates.isEmpty()) return;
final Set<PsiField> usedFields = new HashSet<>();
removeReadFields(aClass, candidates, usedFields, ignoreFieldsUsedInMultipleMethods);
removeReadFields(aClass, candidates, usedFields, IGNORE_FIELDS_USED_IN_MULTIPLE_METHODS);
if (candidates.isEmpty()) return;
final List<ImplicitUsageProvider> implicitUsageProviders = ImplicitUsageProvider.EP_NAME.getExtensionList();
final List<ImplicitUsageProvider> implicitUsageProviders = ImplicitUsageProvider.EP_NAME.getExtensionList();
final PsiClass scope = findVariableScope(aClass);
FieldLoop:
@@ -120,8 +118,7 @@ public final class FieldCanBeLocalInspection extends AbstractBaseJavaLocalInspec
root.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitMethod(@NotNull PsiMethod method) {
if (method.isConstructor()) {
if (method.isConstructor() && !PsiUtil.isAvailable(JavaFeature.STATEMENTS_BEFORE_SUPER, method)) {
final PsiCodeBlock body = method.getBody();
if (body != null) {
final PsiStatement[] statements = body.getStatements();
@@ -156,7 +153,6 @@ public final class FieldCanBeLocalInspection extends AbstractBaseJavaLocalInspec
@Override
public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
excludeFieldCandidate(expression);
super.visitReferenceExpression(expression);
}
@@ -167,9 +163,7 @@ public final class FieldCanBeLocalInspection extends AbstractBaseJavaLocalInspec
}
private void excludeFieldCandidate(PsiReference ref) {
if (ref == null) return;
final PsiElement resolved = ref.resolve();
if (resolved instanceof PsiField field && aClass.equals(field.getContainingClass())) {
if (ref != null && ref.resolve() instanceof PsiField field && aClass.equals(field.getContainingClass())) {
candidates.remove(field);
}
}
@@ -339,7 +333,7 @@ public final class FieldCanBeLocalInspection extends AbstractBaseJavaLocalInspec
@Override
public void visitClass(@NotNull PsiClass aClass) {
super.visitClass(aClass);
doCheckClass(aClass, holder, EXCLUDE_ANNOS, IGNORE_FIELDS_USED_IN_MULTIPLE_METHODS);
doCheckClass(aClass, holder);
}
};
}
@@ -0,0 +1,10 @@
class ClassName {
private static String <warning descr="Field can be converted to a local variable">SOME_CONSTANT</warning> = "XXX";
public ClassName() {
this(SOME_CONSTANT);
}
public ClassName(String somethingElse) {
}
}
@@ -4,6 +4,8 @@ package com.intellij.java.codeInspection;
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.varScopeCanBeNarrowed.FieldCanBeLocalInspection;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
@@ -63,6 +65,11 @@ public class FieldCanBeLocalTest extends LightJavaCodeInsightFixtureTestCase {
doTest();
}
public void testConstructorThisRef2() {
IdeaTestUtil.setModuleLanguageLevel(getModule(), LanguageLevel.JDK_23_PREVIEW, myFixture.getTestRootDisposable());
doTest();
}
public void testStaticQualifiedFieldAccessForWriting() {
doTest();
}