mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-14 18:05:27 +07:00
[lombok] IDEA-255688 Using existing functionality to skip checking expressions from field initializer
and to skip checking field initializer expression GitOrigin-RevId: 67211ecbad65889dabe6385678cc1b7c47a96deb
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7b19a2dd37
commit
4222be044e
@@ -5,6 +5,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.augment.PsiAugmentProvider;
|
||||
import com.intellij.psi.augment.PsiExtensionMethod;
|
||||
import com.intellij.psi.impl.source.PsiExtensibleClass;
|
||||
import com.siyeh.ig.psiutils.InitializationUtils;
|
||||
import de.plushnikov.intellij.plugin.LombokClassNames;
|
||||
import de.plushnikov.intellij.plugin.processor.LombokProcessorManager;
|
||||
import de.plushnikov.intellij.plugin.processor.Processor;
|
||||
@@ -12,6 +13,7 @@ import de.plushnikov.intellij.plugin.processor.ValProcessor;
|
||||
import de.plushnikov.intellij.plugin.processor.method.ExtensionMethodsHelper;
|
||||
import de.plushnikov.intellij.plugin.processor.modifier.ModifierProcessor;
|
||||
import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil;
|
||||
import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -61,13 +63,40 @@ public class LombokAugmentProvider extends PsiAugmentProvider {
|
||||
/*
|
||||
* The final fields that are marked with Builder.Default contains only possible value
|
||||
* because user can set another value during the creation of the object.
|
||||
*
|
||||
* The fields marked with Getter(lazy=true) contains a value that will be calculated only at first access to the getter-Method
|
||||
*/
|
||||
//see de.plushnikov.intellij.plugin.inspection.DataFlowInspectionTest.testDefaultBuilderFinalValueInspectionIsAlwaysThat
|
||||
//see de.plushnikov.intellij.plugin.inspection.PointlessBooleanExpressionInspectionTest.testPointlessBooleanExpressionBuilderDefault
|
||||
//see com.intellij.java.lomboktest.LombokHighlightingTest.testBuilderWithDefaultRedundantInitializer
|
||||
//see com.intellij.java.lomboktest.LombokHighlightingTest.testGetterLazyInvocationProduceNPE
|
||||
//see com.intellij.java.lomboktest.LombokHighlightingTest.testGetterLazyVariableNotInitialized
|
||||
@Override
|
||||
protected boolean fieldInitializerMightBeChanged(@NotNull PsiField field) {
|
||||
return PsiAnnotationSearchUtil.isAnnotatedWith(field, LombokClassNames.BUILDER_DEFAULT);
|
||||
if (field.hasAnnotation(LombokClassNames.BUILDER_DEFAULT)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final PsiAnnotation getterAnnotation = PsiAnnotationSearchUtil.findAnnotation(field, LombokClassNames.GETTER);
|
||||
final boolean isLazyGetter = null != getterAnnotation &&
|
||||
PsiAnnotationUtil.getBooleanAnnotationValue(getterAnnotation, "lazy", false);
|
||||
|
||||
if (isLazyGetter) {
|
||||
final PsiExpression fieldInitializer = field.getInitializer();
|
||||
if (fieldInitializer instanceof PsiMethodCallExpression methodCallExpression) {
|
||||
final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression();
|
||||
if (qualifierExpression instanceof PsiReferenceExpression qualifierReferenceExpression) {
|
||||
final PsiElement referencedElement = qualifierReferenceExpression.resolve();
|
||||
if (referencedElement instanceof PsiField referencedField) {
|
||||
final PsiClass containingClass = referencedField.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
return InitializationUtils.isInitializedInConstructors(referencedField, containingClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isLazyGetter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -91,11 +120,11 @@ public class LombokAugmentProvider extends PsiAugmentProvider {
|
||||
final List<Psi> emptyResult = Collections.emptyList();
|
||||
if ((type != PsiClass.class && type != PsiField.class && type != PsiMethod.class) || !(element instanceof PsiExtensibleClass)
|
||||
|| (element instanceof PsiCompiledElement) // skip compiled classes
|
||||
) {
|
||||
) {
|
||||
return emptyResult;
|
||||
}
|
||||
|
||||
final PsiClass psiClass = (PsiClass) element;
|
||||
final PsiClass psiClass = (PsiClass)element;
|
||||
if (!psiClass.getLanguage().isKindOf(JavaLanguage.INSTANCE)) {
|
||||
return emptyResult;
|
||||
}
|
||||
@@ -120,7 +149,7 @@ public class LombokAugmentProvider extends PsiAugmentProvider {
|
||||
for (Processor processor : LombokProcessorManager.getProcessors(type)) {
|
||||
final List<? super PsiElement> generatedElements = processor.process(psiClass, nameHint);
|
||||
for (Object psiElement : generatedElements) {
|
||||
result.add((Psi) psiElement);
|
||||
result.add((Psi)psiElement);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package de.plushnikov.intellij.plugin.provider;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.MethodCallProduceNPESupport;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.psiutils.InitializationUtils;
|
||||
import de.plushnikov.intellij.plugin.LombokClassNames;
|
||||
import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil;
|
||||
import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class LombokMethodCallExpressionNPESupport implements MethodCallProduceNPESupport {
|
||||
@Override
|
||||
public boolean ignoreMethodCallExpression(@NotNull PsiExpression psiExpression) {
|
||||
final PsiField field = PsiTreeUtil.getParentOfType(psiExpression, PsiField.class);
|
||||
if (field == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiAnnotation getterAnnotation = PsiAnnotationSearchUtil.findAnnotation(field, LombokClassNames.GETTER);
|
||||
final boolean isLazyGetter = null != getterAnnotation && PsiAnnotationUtil.getBooleanAnnotationValue(getterAnnotation, "lazy", false);
|
||||
|
||||
if (isLazyGetter) {
|
||||
final PsiReference reference = psiExpression.getReference();
|
||||
if (reference != null) {
|
||||
PsiElement referencedElement = reference.resolve();
|
||||
if (!(referencedElement instanceof PsiField referencedField)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PsiClass containingClass = referencedField.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
return InitializationUtils.isInitializedInConstructors(referencedField, containingClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
return isLazyGetter;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package de.plushnikov.intellij.plugin.provider;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.VariableInitializedBeforeUsageSupport;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.plushnikov.intellij.plugin.LombokClassNames;
|
||||
import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* A class that implements the VariableInitializedBeforeUsageSupport interface to provide support for Lombok annotated variables.
|
||||
* It checks if a variable expression should be ignored based on Lombok annotations.
|
||||
*/
|
||||
public class LombokVariableInitializedBeforeUsageSupport implements VariableInitializedBeforeUsageSupport {
|
||||
@Override
|
||||
public boolean ignoreVariableExpression(@NotNull PsiReferenceExpression psiExpression, @NotNull PsiVariable psiVariable) {
|
||||
final PsiField field = PsiTreeUtil.getParentOfType(psiExpression, PsiField.class);
|
||||
if (field == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiAnnotation getterAnnotation = field.getAnnotation(LombokClassNames.GETTER);
|
||||
return null != getterAnnotation && PsiAnnotationUtil.getBooleanAnnotationValue(getterAnnotation, "lazy", false);
|
||||
}
|
||||
}
|
||||
@@ -53,8 +53,6 @@
|
||||
<lang.psiAugmentProvider implementation="de.plushnikov.intellij.plugin.provider.LombokAugmentProvider"/>
|
||||
<lang.jvm.annotationPackageSupport implementation="de.plushnikov.intellij.plugin.provider.LombokAnnotationSupport"/>
|
||||
<lang.jvm.ignoreAnnotationParamSupport implementation="de.plushnikov.intellij.plugin.provider.LombokDefaultAnnotationParamSupport"/>
|
||||
<lang.jvm.ignoreVariableInitializedBeforeUsageSupport implementation="de.plushnikov.intellij.plugin.provider.LombokVariableInitializedBeforeUsageSupport"/>
|
||||
<lang.jvm.ignoreMethodCallExpressionNPESupport implementation="de.plushnikov.intellij.plugin.provider.LombokMethodCallExpressionNPESupport"/>
|
||||
<implicitUsageProvider implementation="de.plushnikov.intellij.plugin.provider.LombokImplicitUsageProvider"/>
|
||||
<projectConfigurable groupId="language"
|
||||
key="plugin.settings.title" bundle="messages.LombokBundle"
|
||||
|
||||
@@ -14,6 +14,7 @@ public class GetterLazyInvocationProduceNPE {
|
||||
}
|
||||
|
||||
private Bar <warning descr="Field 'bar' may be 'final'">bar</warning>;
|
||||
private Bar <warning descr="Private field 'bar2' is never assigned">bar2</warning>;
|
||||
private Car car;
|
||||
|
||||
public GetterLazyInvocationProduceNPE(Bar bar, Car car) {
|
||||
@@ -21,11 +22,15 @@ public class GetterLazyInvocationProduceNPE {
|
||||
this.car = car;
|
||||
}
|
||||
|
||||
// without warning
|
||||
// without warning, because of lazy getter and initialized in constructor
|
||||
@Getter(lazy = true)
|
||||
private final String barString = bar.sayHello();
|
||||
|
||||
//with warning!
|
||||
// with warning, because of lazy getter and NOT initialized in constructor
|
||||
@Getter(lazy = true)
|
||||
private final String bar2String = bar2.<warning descr="Method invocation 'sayHello' will produce 'NullPointerException'">sayHello</warning>();
|
||||
|
||||
//with warning, because of NOT lazy getter
|
||||
@Getter
|
||||
private final String carString = car.<warning descr="Method invocation 'sayHello' will produce 'NullPointerException'">sayHello</warning>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user