[java] IDEA-345355 Refactor HighlightingFeature (in progress)

JavaFeature.EFFECTIVELY_FINAL

GitOrigin-RevId: d52ab73d7d24745b149b5a4704f1dee55e4179f0
This commit is contained in:
Tagir Valeev
2024-02-07 18:02:07 +01:00
committed by intellij-monorepo-bot
parent 72890668ad
commit ea2b70a2d1
12 changed files with 23 additions and 13 deletions

View File

@@ -17,6 +17,7 @@ package com.siyeh.ig.psiutils;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.openapi.util.Comparing;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
@@ -484,7 +485,7 @@ public final class VariableAccessUtils {
final boolean finalVariableIntroduction =
!initialization.hasModifierProperty(PsiModifier.FINAL) && variable.hasModifierProperty(PsiModifier.FINAL) ||
PsiUtil.isLanguageLevel8OrHigher(initialization) &&
PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, initialization) &&
!HighlightControlFlowUtil.isEffectivelyFinal(initialization, containingScope, null) &&
HighlightControlFlowUtil.isEffectivelyFinal(variable, containingScope, null);
final boolean canCaptureThis = initialization instanceof PsiField && !initialization.hasModifierProperty(PsiModifier.STATIC);

View File

@@ -16,6 +16,7 @@
package com.siyeh.ig.serialization;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
@@ -108,7 +109,7 @@ public final class SerializableStoresNonSerializableInspection extends BaseInspe
}
final PsiVariable variable = (PsiVariable)target;
if (!variable.hasModifierProperty(PsiModifier.FINAL)) {
if (!PsiUtil.isLanguageLevel8OrHigher(variable) ||
if (!PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, variable) ||
!HighlightControlFlowUtil.isEffectivelyFinal(variable, myClassOrLambda, expression)) {
// don't warn on uncompilable code.
return;

View File

@@ -18,13 +18,13 @@ package com.siyeh.ig.style;
import com.intellij.codeInspection.CleanupLocalInspectionTool;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.options.OptPane;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.RemoveModifierFix;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import org.jetbrains.annotations.NotNull;
@@ -189,7 +189,7 @@ public final class UnnecessaryFinalOnLocalVariableOrParameterInspection extends
private static boolean isNecessaryFinal(PsiVariable variable, PsiElement context) {
return PsiUtil.isConstantExpression(variable.getInitializer()) ||
!PsiUtil.isLanguageLevel8OrHigher(variable) && VariableAccessUtils.variableIsUsedInInnerClass(variable, context);
!PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, variable) && VariableAccessUtils.variableIsUsedInInnerClass(variable, context);
}
private void check(PsiParameter parameter) {

View File

@@ -74,6 +74,7 @@ feature.type.annotations=Type annotations
feature.type.receivers=Receiver parameters
feature.intersections.in.casts=Intersection types in casts
feature.static.interface.calls=Static interface method calls
feature.effectively.final=Effectively final variables
feature.try.with.resources.refs=Resource references
feature.modules=Modules
feature.collection.factories=Collection factory methods

View File

@@ -38,6 +38,7 @@ public enum JavaFeature {
RECEIVERS(LanguageLevel.JDK_1_8, "feature.type.receivers"),
INTERSECTION_CASTS(LanguageLevel.JDK_1_8, "feature.intersections.in.casts"),
STATIC_INTERFACE_CALLS(LanguageLevel.JDK_1_8, "feature.static.interface.calls"),
EFFECTIVELY_FINAL(LanguageLevel.JDK_1_8, "feature.effectively.final"),
REFS_AS_RESOURCE(LanguageLevel.JDK_1_9, "feature.try.with.resources.refs"),
MODULES(LanguageLevel.JDK_1_9, "feature.modules"),
COLLECTION_FACTORIES(LanguageLevel.JDK_1_9, "feature.collection.factories"),

View File

@@ -34,6 +34,7 @@ import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.pom.java.JavaFeature;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.*;
@@ -1268,7 +1269,7 @@ public class ExtractMethodProcessor implements MatchProvider {
}
});
}
else if (!PsiUtil.isLanguageLevel8OrHigher(myTargetClass)){
else if (!PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, myTargetClass)){
method.accept(new JavaRecursiveElementVisitor() {
@Override public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
final PsiElement resolved = expression.resolve();

View File

@@ -3,6 +3,7 @@ package com.intellij.refactoring.extractMethod.newImpl
import com.intellij.codeInsight.AnnotationUtil
import com.intellij.openapi.project.Project
import com.intellij.pom.java.JavaFeature
import com.intellij.psi.*
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.codeStyle.JavaCodeStyleSettings
@@ -73,7 +74,7 @@ class SignatureBuilder(private val project: Project) {
inputParameters.forEach { parameter ->
val shouldBeFinal = when {
useDefaultFinal -> parameter.references.none { reference -> PsiUtil.isAccessedForWriting(reference) }
! PsiUtil.isLanguageLevel8OrHigher(element) -> parameter.references.any { reference -> isInsideAnonymousOrLocal(reference, scope) }
!PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, element) -> parameter.references.any { reference -> isInsideAnonymousOrLocal(reference, scope) }
else -> false
}
val methodParameter = parameterList.parameters.find { it.name == parameter.name }

View File

@@ -9,6 +9,7 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
@@ -254,7 +255,7 @@ class InlineToAnonymousConstructorProcessor {
try {
final PsiDeclarationStatement declaration = myElementFactory.createVariableDeclarationStatement(localName, type, initializer);
PsiLocalVariable variable = (PsiLocalVariable)declaration.getDeclaredElements()[0];
if (!PsiUtil.isLanguageLevel8OrHigher(myNewExpression) ||
if (!PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, myNewExpression) ||
JavaCodeStyleSettings.getInstance(initializer.getContainingFile()).GENERATE_FINAL_LOCALS) {
PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, true);
}

View File

@@ -15,6 +15,7 @@ import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiFormatUtil;
@@ -276,7 +277,7 @@ public class IntroduceFunctionalVariableHandler extends IntroduceVariableHandler
for (VariableData data : getChosenParameters()) {
if (!data.passAsParameter) {
PsiElement scope = PsiUtil.getVariableCodeBlock(data.variable, null);
if (PsiUtil.isLanguageLevel8OrHigher(data.variable)
if (PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, data.variable)
? scope != null && !HighlightControlFlowUtil.isEffectivelyFinal(data.variable, scope, null)
: data.variable.hasModifierProperty(PsiModifier.FINAL)) {
conflicts.putValue(null, JavaBundle.message("introduce.functional.variable.accessibility.conflict", data.name));

View File

@@ -15,6 +15,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
@@ -80,7 +81,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
vars.size() == 1 ? 0 : 1);
}
case COPY_TO_FINAL -> JavaBundle.message("intention.name.copy.to.final.temp.variable", myVariable.getName(),
!PsiUtil.isLanguageLevel8OrHigher(myContext) ? 0 : 1);
!PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, myContext) ? 0 : 1);
default -> "";
};
}
@@ -207,7 +208,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
PsiDeclarationStatement copyDecl = factory.createVariableDeclarationStatement(newName, type, initializer);
PsiVariable newVariable = (PsiVariable)copyDecl.getDeclaredElements()[0];
final boolean mustBeFinal =
!PsiUtil.isLanguageLevel8OrHigher(context) || JavaCodeStyleSettings.getInstance(context.getContainingFile()).GENERATE_FINAL_LOCALS;
!PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, context) || JavaCodeStyleSettings.getInstance(context.getContainingFile()).GENERATE_FINAL_LOCALS;
PsiUtil.setModifierProperty(newVariable, PsiModifier.FINAL, mustBeFinal);
PsiElement statement = getStatementToInsertBefore(variable, context);
if (statement == null) return;

View File

@@ -16,6 +16,7 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
@@ -303,7 +304,7 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
public static void makeFinalIfNeeded(@NotNull InsertionContext context, @NotNull PsiVariable variable) {
PsiElement place = context.getFile().findElementAt(context.getTailOffset() - 1);
if (place == null || PsiUtil.isLanguageLevel8OrHigher(place) || JspPsiUtil.isInJspFile(place)) {
if (place == null || PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, place) || JspPsiUtil.isInJspFile(place)) {
return;
}

View File

@@ -271,9 +271,9 @@ public final class ThreadLocalConversionRule extends TypeConversionRule {
@Override
public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) {
PsiExpression replaced = super.replace(expression, evaluator);
boolean atLeastJava8 = PsiUtil.isLanguageLevel8OrHigher(replaced);
boolean effectivelyFinalSupported = PsiUtil.isAvailable(JavaFeature.EFFECTIVELY_FINAL, replaced);
for (PsiVariable var : myVariablesToMakeFinal) {
if (!atLeastJava8 || !HighlightControlFlowUtil.isEffectivelyFinal(var, replaced, null)) {
if (!effectivelyFinalSupported || !HighlightControlFlowUtil.isEffectivelyFinal(var, replaced, null)) {
VariableAccessFromInnerClassFix.fixAccess(var, replaced);
}
}