[lombok] IDEA-353161 Prevent calculation of all not relevant fields on each check

GitOrigin-RevId: b7158a0ea4ca2346c18c1ce7e95d77bf9aa212c1
This commit is contained in:
Michail Plushnikov
2024-05-12 18:12:59 +02:00
committed by intellij-monorepo-bot
parent 7dae9242d9
commit be6ddc2aec
10 changed files with 192 additions and 141 deletions

View File

@@ -96,10 +96,10 @@ public final class GetterProcessor extends AbstractClassProcessor {
@NotNull @NotNull
public Collection<PsiMethod> createFieldGetters(@NotNull PsiClass psiClass, @NotNull String methodModifier, @Nullable String nameHint) { public Collection<PsiMethod> createFieldGetters(@NotNull PsiClass psiClass, @NotNull String methodModifier, @Nullable String nameHint) {
Collection<PsiMethod> result = new ArrayList<>(); Collection<PsiMethod> result = new ArrayList<>();
final Collection<PsiField> getterFields = filterGetterFields(psiClass); final Collection<PsiField> getterFields = filterGetterFields(psiClass);
GetterFieldProcessor fieldProcessor = getGetterFieldProcessor();
for (PsiField getterField : getterFields) { for (PsiField getterField : getterFields) {
ContainerUtil.addIfNotNull(result, fieldProcessor.createGetterMethod(getterField, psiClass, methodModifier, nameHint)); ContainerUtil.addIfNotNull(result, GetterFieldProcessor.createGetterMethod(getterField, psiClass, methodModifier, nameHint));
} }
return result; return result;
} }
@@ -111,39 +111,51 @@ public final class GetterProcessor extends AbstractClassProcessor {
final Collection<PsiMethod> classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass); final Collection<PsiMethod> classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass);
filterToleratedElements(classMethods); filterToleratedElements(classMethods);
final GetterFieldProcessor fieldProcessor = getGetterFieldProcessor();
final AccessorsInfo.AccessorsValues classAccessorsValues = AccessorsInfo.getAccessorsValues(psiClass); final AccessorsInfo.AccessorsValues classAccessorsValues = AccessorsInfo.getAccessorsValues(psiClass);
GetterFieldProcessor fieldProcessor = getGetterFieldProcessor();
for (PsiField psiField : psiClass.getFields()) { for (PsiField psiField : psiClass.getFields()) {
boolean createGetter = true; if (shouldCreateGetter(psiField, fieldProcessor, classAccessorsValues, classMethods)) {
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
//Skip static fields.
createGetter = !modifierList.hasModifierProperty(PsiModifier.STATIC);
//Skip fields having Getter annotation already
createGetter &= PsiAnnotationSearchUtil.isNotAnnotatedWith(psiField, fieldProcessor.getSupportedAnnotationClasses());
//Skip fields that start with $
createGetter &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
//Skip fields if a method with same name and arguments count already exists
final AccessorsInfo accessorsInfo = AccessorsInfo.buildFor(psiField, classAccessorsValues);
final Collection<String> methodNames =
LombokUtils.toAllGetterNames(accessorsInfo, psiField.getName(), PsiTypes.booleanType().equals(psiField.getType()));
for (String methodName : methodNames) {
createGetter &= !PsiMethodUtil.hasSimilarMethod(classMethods, methodName, 0);
}
}
if (createGetter) {
getterFields.add(psiField); getterFields.add(psiField);
} }
} }
return getterFields; return getterFields;
} }
private static boolean shouldCreateGetter(@NotNull PsiField psiField,
@NotNull GetterFieldProcessor fieldProcessor,
@NotNull AccessorsInfo.AccessorsValues classAccessorsValues,
@NotNull Collection<PsiMethod> classMethods) {
boolean createGetter = true;
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
//Skip static fields.
createGetter = !modifierList.hasModifierProperty(PsiModifier.STATIC);
//Skip fields having Getter annotation already
createGetter &= PsiAnnotationSearchUtil.isNotAnnotatedWith(psiField, fieldProcessor.getSupportedAnnotationClasses());
//Skip fields that start with $
createGetter &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
//Skip fields if a method with same name and arguments count already exists
final AccessorsInfo accessorsInfo = AccessorsInfo.buildFor(psiField, classAccessorsValues);
final Collection<String> methodNames =
LombokUtils.toAllGetterNames(accessorsInfo, psiField.getName(), PsiTypes.booleanType().equals(psiField.getType()));
for (String methodName : methodNames) {
createGetter &= !PsiMethodUtil.hasSimilarMethod(classMethods, methodName, 0);
}
}
return createGetter;
}
@Override @Override
public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) { public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) {
final PsiClass containingClass = psiField.getContainingClass(); final PsiClass containingClass = psiField.getContainingClass();
if (null != containingClass) { if (null != containingClass) {
if (PsiClassUtil.getNames(filterGetterFields(containingClass)).contains(psiField.getName())) { final Collection<PsiMethod> classMethods = PsiClassUtil.collectClassMethodsIntern(containingClass);
filterToleratedElements(classMethods);
final AccessorsInfo.AccessorsValues classAccessorsValues = AccessorsInfo.getAccessorsValues(containingClass);
final GetterFieldProcessor fieldProcessor = getGetterFieldProcessor();
if (shouldCreateGetter(psiField, fieldProcessor, classAccessorsValues, classMethods)) {
return LombokPsiElementUsage.READ; return LombokPsiElementUsage.READ;
} }
} }

View File

@@ -68,8 +68,8 @@ public final class SetterProcessor extends AbstractClassProcessor {
} }
private static void validateAnnotationOnRightType(@NotNull PsiAnnotation psiAnnotation, private static void validateAnnotationOnRightType(@NotNull PsiAnnotation psiAnnotation,
@NotNull PsiClass psiClass, @NotNull PsiClass psiClass,
@NotNull ProblemSink builder) { @NotNull ProblemSink builder) {
if (psiClass.isAnnotationType() || psiClass.isInterface() || psiClass.isEnum()) { if (psiClass.isAnnotationType() || psiClass.isInterface() || psiClass.isEnum()) {
builder.addErrorMessage("inspection.message.s.only.supported.on.class.or.field.type", psiAnnotation.getQualifiedName()); builder.addErrorMessage("inspection.message.s.only.supported.on.class.or.field.type", psiAnnotation.getQualifiedName());
builder.markFailed(); builder.markFailed();
@@ -77,13 +77,15 @@ public final class SetterProcessor extends AbstractClassProcessor {
} }
private static void validateVisibility(@NotNull PsiAnnotation psiAnnotation, @NotNull ProblemSink builder) { private static void validateVisibility(@NotNull PsiAnnotation psiAnnotation, @NotNull ProblemSink builder) {
if(null == LombokProcessorUtil.getMethodModifier(psiAnnotation)) { if (null == LombokProcessorUtil.getMethodModifier(psiAnnotation)) {
builder.markFailed(); builder.markFailed();
} }
} }
@Override @Override
protected void generatePsiElements(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, @NotNull List<? super PsiElement> target, protected void generatePsiElements(@NotNull PsiClass psiClass,
@NotNull PsiAnnotation psiAnnotation,
@NotNull List<? super PsiElement> target,
@Nullable String nameHint) { @Nullable String nameHint) {
final String methodVisibility = LombokProcessorUtil.getMethodModifier(psiAnnotation); final String methodVisibility = LombokProcessorUtil.getMethodModifier(psiAnnotation);
if (methodVisibility != null) { if (methodVisibility != null) {
@@ -107,38 +109,48 @@ public final class SetterProcessor extends AbstractClassProcessor {
final Collection<PsiMethod> classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass); final Collection<PsiMethod> classMethods = PsiClassUtil.collectClassMethodsIntern(psiClass);
filterToleratedElements(classMethods); filterToleratedElements(classMethods);
SetterFieldProcessor fieldProcessor = getSetterFieldProcessor(); final SetterFieldProcessor fieldProcessor = getSetterFieldProcessor();
final Collection<PsiField> setterFields = new ArrayList<>(); final Collection<PsiField> setterFields = new ArrayList<>();
for (PsiField psiField : psiClass.getFields()) { for (PsiField psiField : psiClass.getFields()) {
boolean createSetter = true; if (shouldGenerateSetter(psiField, fieldProcessor, classMethods)) {
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
//Skip final fields.
createSetter = !modifierList.hasModifierProperty(PsiModifier.FINAL);
//Skip static fields.
createSetter &= !modifierList.hasModifierProperty(PsiModifier.STATIC);
//Skip fields having Setter annotation already
createSetter &= PsiAnnotationSearchUtil.isNotAnnotatedWith(psiField, fieldProcessor.getSupportedAnnotationClasses());
//Skip fields that start with $
createSetter &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
//Skip fields if a method with same name already exists
final Collection<String> methodNames = fieldProcessor.getAllSetterNames(psiField, PsiTypes.booleanType().equals(psiField.getType()));
for (String methodName : methodNames) {
createSetter &= !PsiMethodUtil.hasSimilarMethod(classMethods, methodName, 1);
}
}
if (createSetter) {
setterFields.add(psiField); setterFields.add(psiField);
} }
} }
return setterFields; return setterFields;
} }
private static boolean shouldGenerateSetter(@NotNull PsiField psiField, @NotNull SetterFieldProcessor fieldProcessor,
@NotNull Collection<PsiMethod> classMethods) {
boolean createSetter = true;
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
//Skip final fields.
createSetter = !modifierList.hasModifierProperty(PsiModifier.FINAL);
//Skip static fields.
createSetter &= !modifierList.hasModifierProperty(PsiModifier.STATIC);
//Skip fields having Setter annotation already
createSetter &= PsiAnnotationSearchUtil.isNotAnnotatedWith(psiField, fieldProcessor.getSupportedAnnotationClasses());
//Skip fields that start with $
createSetter &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
//Skip fields if a method with same name already exists
final Collection<String> methodNames = fieldProcessor.getAllSetterNames(psiField, PsiTypes.booleanType().equals(psiField.getType()));
for (String methodName : methodNames) {
createSetter &= !PsiMethodUtil.hasSimilarMethod(classMethods, methodName, 1);
}
}
return createSetter;
}
@Override @Override
public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) { public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) {
final PsiClass containingClass = psiField.getContainingClass(); final PsiClass containingClass = psiField.getContainingClass();
if (null != containingClass) { if (null != containingClass) {
if (PsiClassUtil.getNames(filterSetterFields(containingClass)).contains(psiField.getName())) { final Collection<PsiMethod> classMethods = PsiClassUtil.collectClassMethodsIntern(containingClass);
filterToleratedElements(classMethods);
final SetterFieldProcessor fieldProcessor = getSetterFieldProcessor();
if (shouldGenerateSetter(psiField, fieldProcessor, classMethods)) {
return LombokPsiElementUsage.WRITE; return LombokPsiElementUsage.WRITE;
} }
} }

View File

@@ -125,34 +125,34 @@ public final class WitherProcessor extends AbstractClassProcessor {
Collection<PsiField> witherFields = new ArrayList<>(); Collection<PsiField> witherFields = new ArrayList<>();
for (PsiField psiField : psiClass.getFields()) { for (PsiField psiField : psiClass.getFields()) {
boolean createWither = true; if (shouldGenerateWither(psiField)) {
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
// Skip static fields.
createWither = !modifierList.hasModifierProperty(PsiModifier.STATIC);
// Skip final fields that are initialized and not annotated with @Builder.Default
createWither &= !(modifierList.hasModifierProperty(PsiModifier.FINAL) && psiField.hasInitializer() &&
PsiAnnotationSearchUtil.findAnnotation(psiField, BUILDER_DEFAULT_ANNOTATION) == null);
// Skip fields that start with $
createWither &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
// Skip fields having Wither annotation already
createWither &= !PsiAnnotationSearchUtil.isAnnotatedWith(psiField, LombokClassNames.WITHER, LombokClassNames.WITH);
}
if (createWither) {
witherFields.add(psiField); witherFields.add(psiField);
} }
} }
return witherFields; return witherFields;
} }
private static boolean shouldGenerateWither(@NotNull PsiField psiField) {
boolean createWither = true;
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
// Skip static fields.
createWither = !modifierList.hasModifierProperty(PsiModifier.STATIC);
// Skip final fields that are initialized and not annotated with @Builder.Default
createWither &= !(modifierList.hasModifierProperty(PsiModifier.FINAL) && psiField.hasInitializer() &&
PsiAnnotationSearchUtil.findAnnotation(psiField, BUILDER_DEFAULT_ANNOTATION) == null);
// Skip fields that start with $
createWither &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
// Skip fields having Wither annotation already
createWither &= !PsiAnnotationSearchUtil.isAnnotatedWith(psiField, LombokClassNames.WITHER, LombokClassNames.WITH);
}
return createWither;
}
@Override @Override
public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) { public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) {
final PsiClass containingClass = psiField.getContainingClass(); if (shouldGenerateWither(psiField)) {
if (null != containingClass) { return LombokPsiElementUsage.READ_WRITE;
final Collection<PsiField> witherFields = getWitherFields(containingClass);
if (PsiClassUtil.getNames(witherFields).contains(psiField.getName())) {
return LombokPsiElementUsage.READ_WRITE;
}
} }
return LombokPsiElementUsage.NONE; return LombokPsiElementUsage.NONE;
} }

View File

@@ -184,27 +184,30 @@ public abstract class AbstractConstructorClassProcessor extends AbstractClassPro
Collection<PsiField> fields = psiClass.isRecord() ? RecordAugmentProvider.getFieldAugments(psiClass) Collection<PsiField> fields = psiClass.isRecord() ? RecordAugmentProvider.getFieldAugments(psiClass)
: PsiClassUtil.collectClassFieldsIntern(psiClass); : PsiClassUtil.collectClassFieldsIntern(psiClass);
for (PsiField psiField : fields) { for (PsiField psiField : fields) {
// skip fields named $ if (isNotInitializedAndNotStaticField(psiField, classAnnotatedWithValue)) {
boolean addField = !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
final PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
// skip static fields
addField &= !modifierList.hasModifierProperty(PsiModifier.STATIC);
boolean isFinal = isFieldFinal(psiField, modifierList, classAnnotatedWithValue);
// skip initialized final fields
addField &= (!isFinal || !psiField.hasInitializer() ||
PsiAnnotationSearchUtil.findAnnotation(psiField, BUILDER_DEFAULT_ANNOTATION) != null);
}
if (addField) {
allNotInitializedNotStaticFields.add(psiField); allNotInitializedNotStaticFields.add(psiField);
} }
} }
return allNotInitializedNotStaticFields; return allNotInitializedNotStaticFields;
} }
static boolean isNotInitializedAndNotStaticField(@NotNull PsiField psiField, boolean classAnnotatedWithValue) {
// skip fields named $
boolean addField = !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
final PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
// skip static fields
addField &= !modifierList.hasModifierProperty(PsiModifier.STATIC);
boolean isFinal = isFieldFinal(psiField, modifierList, classAnnotatedWithValue);
// skip initialized final fields
addField &= (!isFinal || !psiField.hasInitializer() ||
PsiAnnotationSearchUtil.findAnnotation(psiField, BUILDER_DEFAULT_ANNOTATION) != null);
}
return addField;
}
@NotNull @NotNull
public static Collection<PsiField> getAllFields(@NotNull PsiClass psiClass) { public static Collection<PsiField> getAllFields(@NotNull PsiClass psiClass) {
return getAllNotInitializedAndNotStaticFields(psiClass); return getAllNotInitializedAndNotStaticFields(psiClass);
@@ -221,19 +224,25 @@ public abstract class AbstractConstructorClassProcessor extends AbstractClassPro
final boolean classAnnotatedWithValue = PsiAnnotationSearchUtil.isAnnotatedWith(psiClass, LombokClassNames.VALUE); final boolean classAnnotatedWithValue = PsiAnnotationSearchUtil.isAnnotatedWith(psiClass, LombokClassNames.VALUE);
for (PsiField psiField : getAllNotInitializedAndNotStaticFields(psiClass)) { for (PsiField psiField : getAllNotInitializedAndNotStaticFields(psiClass)) {
final PsiModifierList modifierList = psiField.getModifierList(); if (isRequiredField(psiField, ignoreNonNull, classAnnotatedWithValue)) {
if (null != modifierList) { result.add(psiField);
final boolean isFinal = isFieldFinal(psiField, modifierList, classAnnotatedWithValue);
final boolean isNonNull = !ignoreNonNull && PsiAnnotationSearchUtil.isAnnotatedWith(psiField, LombokUtils.NONNULL_ANNOTATIONS);
// accept initialized final or nonnull fields
if ((isFinal || isNonNull) && !psiField.hasInitializer()) {
result.add(psiField);
}
} }
} }
return result; return result;
} }
static boolean isRequiredField(@NotNull PsiField psiField, boolean ignoreNonNull, boolean classAnnotatedWithValue) {
final PsiModifierList modifierList = psiField.getModifierList();
boolean shouldAddField = false;
if (null != modifierList) {
final boolean isFinal = isFieldFinal(psiField, modifierList, classAnnotatedWithValue);
final boolean isNonNull = !ignoreNonNull && PsiAnnotationSearchUtil.isAnnotatedWith(psiField, LombokUtils.NONNULL_ANNOTATIONS);
// accept initialized final or nonnull fields
shouldAddField = (isFinal || isNonNull) && !psiField.hasInitializer();
}
return shouldAddField;
}
private static boolean isFieldFinal(@NotNull PsiField psiField, @NotNull PsiModifierList modifierList, boolean classAnnotatedWithValue) { private static boolean isFieldFinal(@NotNull PsiField psiField, @NotNull PsiModifierList modifierList, boolean classAnnotatedWithValue) {
boolean isFinal = modifierList.hasModifierProperty(PsiModifier.FINAL); boolean isFinal = modifierList.hasModifierProperty(PsiModifier.FINAL);
if (!isFinal && classAnnotatedWithValue) { if (!isFinal && classAnnotatedWithValue) {

View File

@@ -5,6 +5,7 @@ import de.plushnikov.intellij.plugin.LombokClassNames;
import de.plushnikov.intellij.plugin.problem.ProblemSink; import de.plushnikov.intellij.plugin.problem.ProblemSink;
import de.plushnikov.intellij.plugin.processor.LombokPsiElementUsage; import de.plushnikov.intellij.plugin.processor.LombokPsiElementUsage;
import de.plushnikov.intellij.plugin.util.LombokProcessorUtil; import de.plushnikov.intellij.plugin.util.LombokProcessorUtil;
import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil;
import de.plushnikov.intellij.plugin.util.PsiClassUtil; import de.plushnikov.intellij.plugin.util.PsiClassUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -64,7 +65,8 @@ public final class AllArgsConstructorProcessor extends AbstractConstructorClassP
public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) { public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) {
final PsiClass containingClass = psiField.getContainingClass(); final PsiClass containingClass = psiField.getContainingClass();
if (null != containingClass) { if (null != containingClass) {
if (PsiClassUtil.getNames(getAllNotInitializedAndNotStaticFields(containingClass)).contains(psiField.getName())) { final boolean classAnnotatedWithValue = PsiAnnotationSearchUtil.isAnnotatedWith(containingClass, LombokClassNames.VALUE);
if (isNotInitializedAndNotStaticField(psiField, classAnnotatedWithValue)) {
return LombokPsiElementUsage.WRITE; return LombokPsiElementUsage.WRITE;
} }
} }

View File

@@ -6,6 +6,7 @@ import de.plushnikov.intellij.plugin.problem.ProblemSink;
import de.plushnikov.intellij.plugin.processor.LombokPsiElementUsage; import de.plushnikov.intellij.plugin.processor.LombokPsiElementUsage;
import de.plushnikov.intellij.plugin.quickfix.PsiQuickFixFactory; import de.plushnikov.intellij.plugin.quickfix.PsiQuickFixFactory;
import de.plushnikov.intellij.plugin.util.LombokProcessorUtil; import de.plushnikov.intellij.plugin.util.LombokProcessorUtil;
import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil;
import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil; import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
import de.plushnikov.intellij.plugin.util.PsiClassUtil; import de.plushnikov.intellij.plugin.util.PsiClassUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -78,14 +79,14 @@ public final class NoArgsConstructorProcessor extends AbstractConstructorClassPr
@Override @Override
public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) { public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) {
final PsiClass containingClass = psiField.getContainingClass(); final boolean forceConstructorWithJavaDefaults = isForceConstructor(psiAnnotation);
if (null != containingClass) { if(forceConstructorWithJavaDefaults) {
final PsiClass containingClass = psiField.getContainingClass();
final boolean forceConstructorWithJavaDefaults = isForceConstructor(psiAnnotation); if (null != containingClass) {
final Collection<PsiField> params = getConstructorFields(containingClass, forceConstructorWithJavaDefaults); final boolean classAnnotatedWithValue = PsiAnnotationSearchUtil.isAnnotatedWith(containingClass, LombokClassNames.VALUE);
if (isRequiredField(psiField, false, classAnnotatedWithValue)) {
if (PsiClassUtil.getNames(params).contains(psiField.getName())) { return LombokPsiElementUsage.WRITE;
return LombokPsiElementUsage.WRITE; }
} }
} }
return LombokPsiElementUsage.NONE; return LombokPsiElementUsage.NONE;

View File

@@ -5,6 +5,7 @@ import de.plushnikov.intellij.plugin.LombokClassNames;
import de.plushnikov.intellij.plugin.problem.ProblemSink; import de.plushnikov.intellij.plugin.problem.ProblemSink;
import de.plushnikov.intellij.plugin.processor.LombokPsiElementUsage; import de.plushnikov.intellij.plugin.processor.LombokPsiElementUsage;
import de.plushnikov.intellij.plugin.util.LombokProcessorUtil; import de.plushnikov.intellij.plugin.util.LombokProcessorUtil;
import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil;
import de.plushnikov.intellij.plugin.util.PsiClassUtil; import de.plushnikov.intellij.plugin.util.PsiClassUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -54,7 +55,8 @@ public final class RequiredArgsConstructorProcessor extends AbstractConstructorC
public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) { public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) {
final PsiClass containingClass = psiField.getContainingClass(); final PsiClass containingClass = psiField.getContainingClass();
if (null != containingClass) { if (null != containingClass) {
if (PsiClassUtil.getNames(getRequiredFields(containingClass)).contains(psiField.getName())) { final boolean classAnnotatedWithValue = PsiAnnotationSearchUtil.isAnnotatedWith(containingClass, LombokClassNames.VALUE);
if (isRequiredField(psiField, false, classAnnotatedWithValue)) {
return LombokPsiElementUsage.WRITE; return LombokPsiElementUsage.WRITE;
} }
} }

View File

@@ -49,20 +49,34 @@ public abstract class AbstractFieldNameConstantsProcessor extends AbstractClassP
Collection<PsiMember> filterMembers(@NotNull PsiClass psiClass, PsiAnnotation psiAnnotation) { Collection<PsiMember> filterMembers(@NotNull PsiClass psiClass, PsiAnnotation psiAnnotation) {
final Collection<PsiMember> result = new ArrayList<>(); final Collection<PsiMember> result = new ArrayList<>();
final boolean onlyExplicitlyIncluded = PsiAnnotationUtil.getBooleanAnnotationValue(psiAnnotation, "onlyExplicitlyIncluded", false); final boolean onlyExplicitlyIncluded = isOnlyExplicitlyIncluded(psiAnnotation);
Collection<? extends PsiMember> psiMembers; Collection<? extends PsiMember> psiMembers;
if(psiClass.isRecord()) { if (psiClass.isRecord()) {
psiMembers = List.of(psiClass.getRecordComponents()); psiMembers = List.of(psiClass.getRecordComponents());
}else{ }
psiMembers = PsiClassUtil.collectClassFieldsIntern(psiClass); else {
psiMembers = PsiClassUtil.collectClassFieldsIntern(psiClass);
} }
for (PsiMember psiMember : psiMembers) { for (PsiMember psiMember : psiMembers) {
boolean useField = true; if (shouldUseField(psiMember, onlyExplicitlyIncluded)) {
result.add(psiMember);
}
}
return result;
}
private static boolean shouldUseField(@NotNull PsiMember psiMember, boolean onlyExplicitlyIncluded) {
boolean useField = true;
if (onlyExplicitlyIncluded) {
//Only use fields annotated with @FieldNameConstants.Include, Include annotation overrides other rules
useField = PsiAnnotationSearchUtil.isAnnotatedWith(psiMember, FIELD_NAME_CONSTANTS_INCLUDE);
}
else {
PsiModifierList modifierList = psiMember.getModifierList(); PsiModifierList modifierList = psiMember.getModifierList();
if (null != modifierList) { if (null != modifierList) {
//Skip static fields. //Skip static fields.
useField = !modifierList.hasModifierProperty(PsiModifier.STATIC); useField = !modifierList.hasModifierProperty(PsiModifier.STATIC);
//Skip transient fields //Skip transient fields
@@ -72,17 +86,8 @@ public abstract class AbstractFieldNameConstantsProcessor extends AbstractClassP
useField &= !StringUtil.notNullize(psiMember.getName()).startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER); useField &= !StringUtil.notNullize(psiMember.getName()).startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
//Skip fields annotated with @FieldNameConstants.Exclude //Skip fields annotated with @FieldNameConstants.Exclude
useField &= !PsiAnnotationSearchUtil.isAnnotatedWith(psiMember, FIELD_NAME_CONSTANTS_EXCLUDE); useField &= !PsiAnnotationSearchUtil.isAnnotatedWith(psiMember, FIELD_NAME_CONSTANTS_EXCLUDE);
if (onlyExplicitlyIncluded) {
//Only use fields annotated with @FieldNameConstants.Include, Include annotation overrides other rules
useField = PsiAnnotationSearchUtil.isAnnotatedWith(psiMember, FIELD_NAME_CONSTANTS_INCLUDE);
}
if (useField) {
result.add(psiMember);
}
} }
return result; return useField;
} }
@NotNull @NotNull
@@ -97,10 +102,15 @@ public abstract class AbstractFieldNameConstantsProcessor extends AbstractClassP
public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) { public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) {
final PsiClass containingClass = psiField.getContainingClass(); final PsiClass containingClass = psiField.getContainingClass();
if (null != containingClass) { if (null != containingClass) {
if (PsiClassUtil.getNames(filterMembers(containingClass, psiAnnotation)).contains(psiField.getName())) { final boolean onlyExplicitlyIncluded = isOnlyExplicitlyIncluded(psiAnnotation);
if (shouldUseField(psiField, onlyExplicitlyIncluded)) {
return LombokPsiElementUsage.USAGE; return LombokPsiElementUsage.USAGE;
} }
} }
return LombokPsiElementUsage.NONE; return LombokPsiElementUsage.NONE;
} }
private static boolean isOnlyExplicitlyIncluded(@NotNull PsiAnnotation psiAnnotation) {
return PsiAnnotationUtil.getBooleanAnnotationValue(psiAnnotation, "onlyExplicitlyIncluded", false);
}
} }

View File

@@ -65,7 +65,9 @@ public final class FieldNameConstantsOldProcessor extends AbstractClassProcessor
} }
@Override @Override
protected void generatePsiElements(@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, @NotNull List<? super PsiElement> target, protected void generatePsiElements(@NotNull PsiClass psiClass,
@NotNull PsiAnnotation psiAnnotation,
@NotNull List<? super PsiElement> target,
@Nullable String nameHint) { @Nullable String nameHint) {
final Collection<PsiField> psiFields = filterFields(psiClass); final Collection<PsiField> psiFields = filterFields(psiClass);
for (PsiField psiField : psiFields) { for (PsiField psiField : psiFields) {
@@ -79,35 +81,34 @@ public final class FieldNameConstantsOldProcessor extends AbstractClassProcessor
private static Collection<PsiField> filterFields(@NotNull PsiClass psiClass) { private static Collection<PsiField> filterFields(@NotNull PsiClass psiClass) {
final Collection<PsiField> psiFields = new ArrayList<>(); final Collection<PsiField> psiFields = new ArrayList<>();
FieldNameConstantsFieldProcessor fieldProcessor = getFieldNameConstantsFieldProcessor(); final FieldNameConstantsFieldProcessor fieldProcessor = getFieldNameConstantsFieldProcessor();
for (PsiField psiField : PsiClassUtil.collectClassFieldsIntern(psiClass)) { for (PsiField psiField : PsiClassUtil.collectClassFieldsIntern(psiClass)) {
boolean useField = true; if (shouldUseField(psiField, fieldProcessor)) {
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
//Skip static fields.
useField = !modifierList.hasModifierProperty(PsiModifier.STATIC);
//Skip fields having same annotation already
useField &= PsiAnnotationSearchUtil.isNotAnnotatedWith(psiField, fieldProcessor.getSupportedAnnotationClasses());
//Skip fields that start with $
useField &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
}
if (useField) {
psiFields.add(psiField); psiFields.add(psiField);
} }
} }
return psiFields; return psiFields;
} }
private static boolean shouldUseField(@NotNull PsiField psiField, @NotNull FieldNameConstantsFieldProcessor fieldProcessor) {
boolean useField = true;
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
//Skip static fields.
useField = !modifierList.hasModifierProperty(PsiModifier.STATIC);
//Skip fields having same annotation already
useField &= PsiAnnotationSearchUtil.isNotAnnotatedWith(psiField, fieldProcessor.getSupportedAnnotationClasses());
//Skip fields that start with $
useField &= !psiField.getName().startsWith(LombokUtils.LOMBOK_INTERN_FIELD_MARKER);
}
return useField;
}
@Override @Override
public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) { public LombokPsiElementUsage checkFieldUsage(@NotNull PsiField psiField, @NotNull PsiAnnotation psiAnnotation) {
final PsiClass containingClass = psiField.getContainingClass(); if (shouldUseField(psiField, getFieldNameConstantsFieldProcessor())) {
if (null != containingClass) { return LombokPsiElementUsage.USAGE;
if (PsiClassUtil.getNames(filterFields(containingClass)).contains(psiField.getName())) {
return LombokPsiElementUsage.USAGE;
}
} }
return LombokPsiElementUsage.NONE; return LombokPsiElementUsage.NONE;
} }
} }

View File

@@ -69,8 +69,8 @@ public final class GetterFieldProcessor extends AbstractFieldProcessor {
if (result && lazy) { if (result && lazy) {
if (!psiField.hasModifierProperty(PsiModifier.FINAL) || !psiField.hasModifierProperty(PsiModifier.PRIVATE)) { if (!psiField.hasModifierProperty(PsiModifier.FINAL) || !psiField.hasModifierProperty(PsiModifier.PRIVATE)) {
builder.addErrorMessage("inspection.message.lazy.requires.field.to.be.private.final") builder.addErrorMessage("inspection.message.lazy.requires.field.to.be.private.final")
.withLocalQuickFixes(()->PsiQuickFixFactory.createModifierListFix(psiField, PsiModifier.PRIVATE, true, false), .withLocalQuickFixes(() -> PsiQuickFixFactory.createModifierListFix(psiField, PsiModifier.PRIVATE, true, false),
()->PsiQuickFixFactory.createModifierListFix(psiField, PsiModifier.FINAL, true, false)); () -> PsiQuickFixFactory.createModifierListFix(psiField, PsiModifier.FINAL, true, false));
result = false; result = false;
} }
if (!psiField.hasInitializer()) { if (!psiField.hasInitializer()) {
@@ -107,8 +107,10 @@ public final class GetterFieldProcessor extends AbstractFieldProcessor {
@Nullable @Nullable
@Contract("_,_,_,null -> !null") @Contract("_,_,_,null -> !null")
public PsiMethod createGetterMethod(@NotNull PsiField psiField, @NotNull PsiClass psiClass, @NotNull String methodModifier, public static PsiMethod createGetterMethod(@NotNull PsiField psiField,
@Nullable String nameHint) { @NotNull PsiClass psiClass,
@NotNull String methodModifier,
@Nullable String nameHint) {
final AccessorsInfo accessorsInfo = AccessorsInfo.buildFor(psiField); final AccessorsInfo accessorsInfo = AccessorsInfo.buildFor(psiField);
final String methodName = LombokUtils.getGetterName(psiField, accessorsInfo); final String methodName = LombokUtils.getGetterName(psiField, accessorsInfo);
if (nameHint != null && !nameHint.equals(methodName)) return null; if (nameHint != null && !nameHint.equals(methodName)) return null;