diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 1728a75df40f..9bf9b9fb0553 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -6,6 +6,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; @@ -347,8 +348,19 @@ public final class PsiClassImplUtil { private final ConcurrentMap myAllMembers; MemberCache(@NotNull PsiClass psiClass, @NotNull GlobalSearchScope scope) { + boolean dumb = DumbService.isDumb(psiClass.getProject()); myAllSupers = JBTreeTraverser - .from((PsiClass c) -> ContainerUtil.mapNotNull(c.getSupers(), s -> PsiSuperMethodUtil.correctClassByScope(s, scope))) + .from((PsiClass c) -> ContainerUtil.mapNotNull(c.getSupers(), + superOne -> { + PsiClass correctedClass = PsiSuperMethodUtil.correctClassByScope(superOne, scope); + if (correctedClass == null && dumb) { + if (superOne.getContainingFile() instanceof PsiJavaFile && + ((PsiJavaFile)superOne.getContainingFile()).getPackageStatement() == null) { + return superOne; + } + } + return correctedClass; + })) .unique() .withRoot(psiClass) .toList(); diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/handler/SneakyThrowsExceptionHandler.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/handler/SneakyThrowsExceptionHandler.java index 4022cf3caab3..c37691759440 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/handler/SneakyThrowsExceptionHandler.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/handler/SneakyThrowsExceptionHandler.java @@ -75,8 +75,9 @@ public final class SneakyThrowsExceptionHandler extends CustomExceptionHandler { return false; } + List throwable = List.of(PsiType.getJavaLangThrowable(psiAnnotation.getManager(), psiAnnotation.getResolveScope())); final Collection sneakedExceptionTypes = - PsiAnnotationUtil.getAnnotationValues(psiAnnotation, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME, PsiType.class); + PsiAnnotationUtil.getAnnotationValues(psiAnnotation, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME, PsiType.class, throwable); //Default SneakyThrows handles all exceptions return sneakedExceptionTypes.isEmpty() || sneakedExceptionTypes.iterator().next().equalsToText(JAVA_LANG_THROWABLE) diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterOrSetterMayBeUsedInspection.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterOrSetterMayBeUsedInspection.java index 6a5446882213..377c97987896 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterOrSetterMayBeUsedInspection.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokGetterOrSetterMayBeUsedInspection.java @@ -1,7 +1,9 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package de.plushnikov.intellij.plugin.inspection; -import com.intellij.codeInspection.*; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; import com.intellij.modcommand.ModPsiUpdater; import com.intellij.modcommand.PsiUpdateModCommandQuickFix; import com.intellij.openapi.project.Project; @@ -13,6 +15,7 @@ import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.javadoc.PsiDocToken; import com.siyeh.ig.psiutils.CommentTracker; +import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -21,7 +24,6 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Objects; public abstract class LombokGetterOrSetterMayBeUsedInspection extends LombokJavaInspectionBase { @@ -58,7 +60,7 @@ public abstract class LombokGetterOrSetterMayBeUsedInspection extends LombokJava } boolean isLombokAnnotationAtClassLevel = true; for (PsiField field : psiClass.getFields()) { - PsiAnnotation annotation = field.getAnnotation(getAnnotationName()); + PsiAnnotation annotation = PsiAnnotationSearchUtil.findAnnotation(field, getAnnotationName()); if (annotation != null) { if (!annotation.getAttributes().isEmpty() || field.hasModifierProperty(PsiModifier.STATIC)) { isLombokAnnotationAtClassLevel = false; @@ -183,7 +185,7 @@ public abstract class LombokGetterOrSetterMayBeUsedInspection extends LombokJava removeMethodAndMoveJavaDoc(field, method); } for (PsiField annotatedField : annotatedFields) { - PsiAnnotation oldAnnotation = annotatedField.getAnnotation(getAnnotationName()); + PsiAnnotation oldAnnotation = PsiAnnotationSearchUtil.findAnnotation(annotatedField, getAnnotationName()); if (oldAnnotation != null) { new CommentTracker().deleteAndRestoreComments(oldAnnotation); } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokInspection.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokInspection.java index f62d39580e9d..c4e16edf86bf 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokInspection.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/LombokInspection.java @@ -1,14 +1,10 @@ package de.plushnikov.intellij.plugin.inspection; -import com.intellij.codeInsight.daemon.impl.quickfix.SafeDeleteFix; -import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.RemoveAnnotationQuickFix; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteAnnotation; -import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverrideAnnotation; import com.intellij.util.JavaPsiConstructorUtil; import de.plushnikov.intellij.plugin.LombokBundle; import de.plushnikov.intellij.plugin.LombokClassNames; @@ -19,6 +15,7 @@ import de.plushnikov.intellij.plugin.processor.Processor; import de.plushnikov.intellij.plugin.processor.ValProcessor; import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder; import de.plushnikov.intellij.plugin.quickfix.PsiQuickFixFactory; +import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -86,8 +83,8 @@ public final class LombokInspection extends LombokJavaInspectionBase { if (annotation.hasQualifiedName(LombokClassNames.BUILDER_DEFAULT)) { final PsiClass parentOfAnnotation = PsiTreeUtil.getParentOfType(annotation, PsiClass.class); if (null != parentOfAnnotation) { - if (!parentOfAnnotation.hasAnnotation(LombokClassNames.BUILDER) && - !parentOfAnnotation.hasAnnotation(LombokClassNames.SUPER_BUILDER)) { + if (!PsiAnnotationSearchUtil.isAnnotatedWith(parentOfAnnotation, LombokClassNames.BUILDER) && + !PsiAnnotationSearchUtil.isAnnotatedWith(parentOfAnnotation, LombokClassNames.SUPER_BUILDER)) { final LombokProblemInstance problemInstance = new LombokProblemInstance( LombokBundle.message("inspection.message.builder.default.requires.builder.annotation"), ProblemHighlightType.GENERIC_ERROR); problemInstance.withLocalQuickFixes( diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/modifiers/LombokRedundantModifierInspection.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/modifiers/LombokRedundantModifierInspection.java index 95d19c9847fd..951294d83ad6 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/modifiers/LombokRedundantModifierInspection.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/inspection/modifiers/LombokRedundantModifierInspection.java @@ -1,11 +1,11 @@ package de.plushnikov.intellij.plugin.inspection.modifiers; -import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.ig.fixes.RemoveModifierFix; import de.plushnikov.intellij.plugin.inspection.LombokJavaInspectionBase; +import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -82,8 +82,8 @@ public abstract class LombokRedundantModifierInspection extends LombokJavaInspec || (infoType != RedundantModifiersInfoType.VARIABLE && !(parentModifierListOwner instanceof PsiClass))) { continue; } - if ((supportedAnnotation == null || parentModifierListOwner.hasAnnotation(supportedAnnotation)) && - redundantModifiersInfo.getType().getSupportedClass().isAssignableFrom(psiModifierListOwner.getClass())) { + if ((supportedAnnotation == null || PsiAnnotationSearchUtil.isAnnotatedWith(parentModifierListOwner, supportedAnnotation)) && + redundantModifiersInfo.getType().getSupportedClass().isAssignableFrom(psiModifierListOwner.getClass())) { PsiModifierList psiModifierList = psiModifierListOwner.getModifierList(); if (psiModifierList == null || (redundantModifiersInfo.getDontRunOnModifier() != null && psiModifierList.hasExplicitModifier(redundantModifiersInfo.getDontRunOnModifier()))) { diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/lombokconfig/ConfigDiscovery.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/lombokconfig/ConfigDiscovery.java index 7e98f29207fe..74e68bf51d0e 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/lombokconfig/ConfigDiscovery.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/lombokconfig/ConfigDiscovery.java @@ -2,6 +2,7 @@ package de.plushnikov.intellij.plugin.lombokconfig; import com.google.common.annotations.VisibleForTesting; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -124,6 +125,9 @@ public class ConfigDiscovery { @Nullable private ConfigValue readProperty(@NotNull ConfigKey configKey, @NotNull Project project, @NotNull VirtualFile directory) { + if (DumbService.getInstance(project).isAlternativeResolveEnabled()) { + return LombokConfigIndex.readPropertyWithAlternativeResolver(configKey, project, directory); + } GlobalSearchScope directoryScope = GlobalSearchScopes.directoryScope(project, directory, false); List values = getFileBasedIndex().getValues(LombokConfigIndex.NAME, configKey, directoryScope); if (!values.isEmpty()) { diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/lombokconfig/LombokConfigIndex.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/lombokconfig/LombokConfigIndex.java index d15317c254c4..ba03998c39f8 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/lombokconfig/LombokConfigIndex.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/lombokconfig/LombokConfigIndex.java @@ -1,8 +1,15 @@ package de.plushnikov.intellij.plugin.lombokconfig; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.*; @@ -16,6 +23,7 @@ import de.plushnikov.intellij.plugin.language.psi.LombokConfigFile; import de.plushnikov.intellij.plugin.language.psi.LombokConfigProperty; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.DataInput; import java.io.DataOutput; @@ -25,6 +33,8 @@ import java.util.HashMap; import java.util.Map; public final class LombokConfigIndex extends FileBasedIndexExtension { + @NotNull + private static final String LOMBOK_CONFIG_FILE_NAME = "lombok.config"; @NonNls public static final ID NAME = ID.create("LombokConfigIndex"); @@ -41,56 +51,64 @@ public final class LombokConfigIndex extends FileBasedIndexExtension map(@NotNull FileContent inputData) { - Map result = Collections.emptyMap(); - final VirtualFile directoryFile = inputData.getFile().getParent(); if (null != directoryFile) { final String canonicalPath = PathUtil.toSystemIndependentName(directoryFile.getCanonicalPath()); if (null != canonicalPath) { - final Map configValues = extractValues((LombokConfigFile)inputData.getPsiFile()); - - final boolean stopBubblingValue = Boolean.parseBoolean(configValues.get(StringUtil.toLowerCase(ConfigKey.CONFIG_STOP_BUBBLING.getConfigKey()))); - result = ContainerUtil.map2Map(ConfigKey.values(), - key -> Pair.create(key, - new ConfigValue(configValues.get(StringUtil.toLowerCase(key.getConfigKey())), stopBubblingValue))); + PsiFile psiFile = inputData.getPsiFile(); + return createConfigMapResult(psiFile); } } - return result; - } - - private static Map extractValues(LombokConfigFile configFile) { - Map result = new HashMap<>(); - - final LombokConfigCleaner[] configCleaners = LombokConfigUtil.getLombokConfigCleaners(configFile); - for (LombokConfigCleaner configCleaner : configCleaners) { - final String key = StringUtil.toLowerCase(configCleaner.getKey()); - - final ConfigKey configKey = ConfigKey.fromConfigStringKey(key); - if (null != configKey) { - result.put(key, configKey.getConfigDefaultValue()); - } - } - - final LombokConfigProperty[] configProperties = LombokConfigUtil.getLombokConfigProperties(configFile); - for (LombokConfigProperty configProperty : configProperties) { - final String key = StringUtil.toLowerCase(configProperty.getKey()); - final String value = configProperty.getValue(); - final String sign = configProperty.getSign(); - if (null == sign) { - result.put(key, value); - } - else { - final String previousValue = StringUtil.defaultIfEmpty(result.get(key), ""); - final String combinedValue = previousValue + sign + value + ";"; - result.put(key, combinedValue); - } - } - - return result; + return Collections.emptyMap(); } }; } + private static @NotNull Map createConfigMapResult(@Nullable PsiFile psiFile) { + if (!(psiFile instanceof LombokConfigFile)) { + return Map.of(); + } + final Map configValues = extractValues((LombokConfigFile)psiFile); + + final boolean stopBubblingValue = + Boolean.parseBoolean(configValues.get(StringUtil.toLowerCase(ConfigKey.CONFIG_STOP_BUBBLING.getConfigKey()))); + return ContainerUtil.map2Map(ConfigKey.values(), + key -> Pair.create(key, + new ConfigValue(configValues.get(StringUtil.toLowerCase(key.getConfigKey())), + stopBubblingValue))); + } + + private static Map extractValues(LombokConfigFile configFile) { + Map result = new HashMap<>(); + + final LombokConfigCleaner[] configCleaners = LombokConfigUtil.getLombokConfigCleaners(configFile); + for (LombokConfigCleaner configCleaner : configCleaners) { + final String key = StringUtil.toLowerCase(configCleaner.getKey()); + + final ConfigKey configKey = ConfigKey.fromConfigStringKey(key); + if (null != configKey) { + result.put(key, configKey.getConfigDefaultValue()); + } + } + + final LombokConfigProperty[] configProperties = LombokConfigUtil.getLombokConfigProperties(configFile); + for (LombokConfigProperty configProperty : configProperties) { + final String key = StringUtil.toLowerCase(configProperty.getKey()); + final String value = configProperty.getValue(); + final String sign = configProperty.getSign(); + if (null == sign) { + result.put(key, value); + } + else { + final String previousValue = StringUtil.defaultIfEmpty(result.get(key), ""); + final String combinedValue = previousValue + sign + value + ";"; + result.put(key, combinedValue); + } + } + + return result; + } + @NotNull @Override public KeyDescriptor getKeyDescriptor() { @@ -134,4 +152,27 @@ public final class LombokConfigIndex extends FileBasedIndexExtension values = CachedValuesManager.getCachedValue(psiFile, () -> { + Map result = createConfigMapResult(psiFile); + //CONFIG_CHANGE_TRACKER is not really accurate, but it is already used for this purpose + return CachedValueProvider.Result.create(result, LombokConfigChangeListener.CONFIG_CHANGE_TRACKER); + }); + return values.get(key); + } } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/EqualsAndHashCodeProcessor.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/EqualsAndHashCodeProcessor.java index 37440925a789..0a769b4c8b1f 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/EqualsAndHashCodeProcessor.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/EqualsAndHashCodeProcessor.java @@ -62,8 +62,8 @@ public final class EqualsAndHashCodeProcessor extends AbstractClassProcessor { } if (problemSink.deepValidation()) { - final Collection excludeProperty = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "exclude", String.class); - final Collection ofProperty = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "of", String.class); + final Collection excludeProperty = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "exclude", String.class, List.of()); + final Collection ofProperty = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "of", String.class, List.of()); if (!excludeProperty.isEmpty() && !ofProperty.isEmpty()) { problemSink.addWarningMessage("inspection.message.exclude.are.mutually.exclusive.exclude.parameter.will.be.ignored") diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/ToStringProcessor.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/ToStringProcessor.java index ca2d5cf3f9b4..411b6cd5c2b6 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/ToStringProcessor.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/clazz/ToStringProcessor.java @@ -55,8 +55,8 @@ public final class ToStringProcessor extends AbstractClassProcessor { } if (problemSink.deepValidation()) { - final Collection excludeProperty = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "exclude", String.class); - final Collection ofProperty = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "of", String.class); + final Collection excludeProperty = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "exclude", String.class, List.of()); + final Collection ofProperty = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "of", String.class, List.of()); if (!excludeProperty.isEmpty() && !ofProperty.isEmpty()) { problemSink.addWarningMessage("inspection.message.exclude.are.mutually.exclusive.exclude.parameter.will.be.ignored") diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/field/AccessorsInfo.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/field/AccessorsInfo.java index fb5860fd891c..db733326d7e2 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/field/AccessorsInfo.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/field/AccessorsInfo.java @@ -15,6 +15,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; +import java.util.List; /** * @author Plushnikov Michail @@ -148,7 +149,7 @@ public class AccessorsInfo { Boolean chainDeclaredValue = PsiAnnotationUtil.getDeclaredBooleanAnnotationValue(accessorsAnnotation, CHAIN_VALUE); Boolean fluentDeclaredValue = PsiAnnotationUtil.getDeclaredBooleanAnnotationValue(accessorsAnnotation, FLUENT_VALUE); Boolean makeFinalDeclaredValue = PsiAnnotationUtil.getDeclaredBooleanAnnotationValue(accessorsAnnotation, MAKE_FINAL_VALUE); - Collection prefixes = PsiAnnotationUtil.getAnnotationValues(accessorsAnnotation, PREFIX_VALUE, String.class); + Collection prefixes = PsiAnnotationUtil.getAnnotationValues(accessorsAnnotation, PREFIX_VALUE, String.class, List.of()); return new AccessorsValues(chainDeclaredValue, fluentDeclaredValue, makeFinalDeclaredValue, prefixes); } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderHandler.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderHandler.java index 0091d5fc5f24..85d3a17ffb09 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderHandler.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderHandler.java @@ -75,7 +75,7 @@ public class BuilderHandler { public static Map>> getExistingMethodsWithParameterTypes(@NotNull PsiClass psiClass) { return PsiClassUtil.collectClassMethodsIntern(psiClass).stream() - .filter(psiMethod -> !psiMethod.hasAnnotation(LombokClassNames.TOLERATE)) + .filter(psiMethod -> !PsiAnnotationSearchUtil.isAnnotatedWith(psiMethod, LombokClassNames.TOLERATE)) .collect(Collectors.groupingBy(PsiMethod::getName, Collectors.mapping(BuilderHandler::getMethodParameterTypes, Collectors.toList()))); } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderInfo.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderInfo.java index 91f3c55641cf..c72d0eb7be7a 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderInfo.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/BuilderInfo.java @@ -63,8 +63,8 @@ public class BuilderInfo { result.capitalizationStrategy = CapitalizationStrategy.defaultValue(); result.deprecated = PsiImplUtil.isDeprecated(psiVariable); - result.hasBuilderDefaultAnnotation = psiVariable.hasAnnotation(BUILDER_DEFAULT_ANNOTATION); - result.singularAnnotation = psiVariable.getAnnotation(LombokClassNames.SINGULAR); + result.hasBuilderDefaultAnnotation = PsiAnnotationSearchUtil.isAnnotatedWith(psiVariable, BUILDER_DEFAULT_ANNOTATION); + result.singularAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiVariable, LombokClassNames.SINGULAR); result.builderElementHandler = SingularHandlerFactory.getHandlerFor(psiVariable, null != result.singularAnnotation); result.nullAnnotationLibrary = LombokNullAnnotationLibraryDefned.NONE; diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/DelegateHandler.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/DelegateHandler.java index 3a9c41d3b126..e1b8c9803647 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/DelegateHandler.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/DelegateHandler.java @@ -88,7 +88,7 @@ public final class DelegateHandler { } private static Collection collectDelegateTypes(PsiAnnotation psiAnnotation, PsiType psiType) { - Collection types = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, TYPES_PARAMETER, PsiType.class); + Collection types = PsiAnnotationUtil.getAnnotationValues(psiAnnotation, TYPES_PARAMETER, PsiType.class, List.of()); if (types.isEmpty()) { types = Collections.singletonList(psiType); } @@ -129,7 +129,7 @@ public final class DelegateHandler { } private static Collection collectExcludeTypes(PsiAnnotation psiAnnotation) { - return PsiAnnotationUtil.getAnnotationValues(psiAnnotation, EXCLUDES_PARAMETER, PsiType.class); + return PsiAnnotationUtil.getAnnotationValues(psiAnnotation, EXCLUDES_PARAMETER, PsiType.class, List.of()); } public static void generateElements(@NotNull T psiElement, diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/EqualsAndHashCodeToStringHandler.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/EqualsAndHashCodeToStringHandler.java index bbfc132a30a5..1d9b9087b065 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/EqualsAndHashCodeToStringHandler.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/handler/EqualsAndHashCodeToStringHandler.java @@ -100,9 +100,9 @@ public final class EqualsAndHashCodeToStringHandler { final Collection excludeProperty; if (!explicitOf) { ofProperty = Collections.emptyList(); - excludeProperty = makeSet(PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "exclude", String.class)); + excludeProperty = makeSet(PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "exclude", String.class, List.of())); } else { - ofProperty = makeSet(PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "of", String.class)); + ofProperty = makeSet(PsiAnnotationUtil.getAnnotationValues(psiAnnotation, "of", String.class, List.of())); excludeProperty = Collections.emptyList(); } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/method/ExtensionMethodsHelper.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/method/ExtensionMethodsHelper.java index 35e08ec067bf..2abf215ab4eb 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/method/ExtensionMethodsHelper.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/method/ExtensionMethodsHelper.java @@ -13,6 +13,7 @@ import com.intellij.util.containers.ContainerUtil; import de.plushnikov.intellij.plugin.LombokClassNames; import de.plushnikov.intellij.plugin.psi.LombokExtensionMethod; import de.plushnikov.intellij.plugin.psi.LombokLightParameter; +import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil; import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil; import de.plushnikov.intellij.plugin.util.PsiClassUtil; import org.jetbrains.annotations.NotNull; @@ -43,10 +44,10 @@ public final class ExtensionMethodsHelper { @Nullable PsiClass context = PsiTreeUtil.getContextOfType(place, PsiClass.class); while (context != null) { - final @Nullable PsiAnnotation annotation = context.getAnnotation(LombokClassNames.EXTENSION_METHOD); + final @Nullable PsiAnnotation annotation = PsiAnnotationSearchUtil.findAnnotation(context, LombokClassNames.EXTENSION_METHOD); if (annotation != null) { - final Set providers = PsiAnnotationUtil.getAnnotationValues(annotation, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME, PsiType.class).stream() + final Set providers = PsiAnnotationUtil.getAnnotationValues(annotation, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME, PsiType.class, List.of()).stream() .filter(PsiClassType.class::isInstance) .map(PsiClassType.class::cast) .map(PsiClassType::resolve) diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAugmentProvider.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAugmentProvider.java index 283d2d31848e..bfa77d5367d1 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAugmentProvider.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/provider/LombokAugmentProvider.java @@ -1,6 +1,9 @@ package de.plushnikov.intellij.plugin.provider; import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.PossiblyDumbAware; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.*; import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.augment.PsiExtensionMethod; @@ -28,7 +31,7 @@ import static de.plushnikov.intellij.plugin.util.LombokLibraryUtil.hasLombokLibr * * @author Plushnikov Michail */ -public final class LombokAugmentProvider extends PsiAugmentProvider { +public final class LombokAugmentProvider extends PsiAugmentProvider implements PossiblyDumbAware { private static final class Holder { static final Collection modifierProcessors = LombokProcessorManager.getLombokModifierProcessors(); } @@ -36,6 +39,11 @@ public final class LombokAugmentProvider extends PsiAugmentProvider { public LombokAugmentProvider() { } + @Override + public boolean isDumbAware() { + return Registry.is("lombok.dumb.mode.enabled", false); + } + @NotNull @Override protected Set transformModifiers(@NotNull PsiModifierList modifierList, @NotNull final Set modifiers) { @@ -47,18 +55,30 @@ public final class LombokAugmentProvider extends PsiAugmentProvider { // make copy of original modifiers Set result = new HashSet<>(modifiers); - // Loop through all available processors and give all of them a chance to respond - for (ModifierProcessor processor : Holder.modifierProcessors) { - if (processor.isSupported(modifierList)) { - processor.transformModifiers(modifierList, result); + DumbService dumbService = DumbService.getInstance(modifierList.getProject()); + Runnable runnable = () -> { + // Loop through all available processors and give all of them a chance to respond + for (ModifierProcessor processor : Holder.modifierProcessors) { + if (processor.isSupported(modifierList)) { + processor.transformModifiers(modifierList, result); + } } + }; + if (dumbService.isDumb() && !dumbService.isAlternativeResolveEnabled()) { + dumbService.runWithAlternativeResolveEnabled(() -> runnable.run()); } + else { + runnable.run(); + } return result; } @Override public boolean canInferType(@NotNull PsiTypeElement typeElement) { + //skip if dumb mode, allow only `getAugments` + if (DumbService.isDumb(typeElement.getProject())) return false; + return hasLombokLibrary(typeElement.getProject()) && ValProcessor.canInferType(typeElement); } @@ -75,7 +95,10 @@ public final class LombokAugmentProvider extends PsiAugmentProvider { //see com.intellij.java.lomboktest.LombokHighlightingTest.testGetterLazyVariableNotInitialized @Override protected boolean fieldInitializerMightBeChanged(@NotNull PsiField field) { - if (field.hasAnnotation(LombokClassNames.BUILDER_DEFAULT)) { + //skip if dumb mode, allow only `getAugments` + if (DumbService.isDumb(field.getProject())) return false; + + if (PsiAnnotationSearchUtil.isAnnotatedWith(field, LombokClassNames.BUILDER_DEFAULT)) { return true; } @@ -104,6 +127,9 @@ public final class LombokAugmentProvider extends PsiAugmentProvider { @Nullable @Override protected PsiType inferType(@NotNull PsiTypeElement typeElement) { + //skip if dumb mode, allow only `getAugments` + if (DumbService.isDumb(typeElement.getProject())) return null; + return hasLombokLibrary(typeElement.getProject()) ? ValProcessor.inferType(typeElement) : null; } @@ -145,7 +171,10 @@ public final class LombokAugmentProvider extends PsiAugmentProvider { // All invoker of AugmentProvider already make caching, // and we want to try to skip recursive calls completely - + DumbService dumbService = DumbService.getInstance(psiClass.getProject()); + if (DumbService.isDumb(psiClass.getProject()) && !dumbService.isAlternativeResolveEnabled()) { + return dumbService.computeWithAlternativeResolveEnabled(()-> getPsis(psiClass, type, nameHint)); + } return getPsis(psiClass, type, nameHint); } @@ -165,6 +194,9 @@ public final class LombokAugmentProvider extends PsiAugmentProvider { protected List getExtensionMethods(@NotNull PsiClass aClass, @NotNull String nameHint, @NotNull PsiElement context) { + //skip if dumb mode, allow only `getAugments` + if (DumbService.isDumb(aClass.getProject())) return Collections.emptyList(); + if (!hasLombokLibrary(context.getProject())) { return Collections.emptyList(); } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightClassBuilder.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightClassBuilder.java index 8678df3af360..7d3d1fe3ade5 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightClassBuilder.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightClassBuilder.java @@ -1,5 +1,6 @@ package de.plushnikov.intellij.plugin.psi; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.ElementPresentationUtil; @@ -101,7 +102,16 @@ public class LombokLightClassBuilder extends LightPsiClassBuilder implements Psi @Override public PsiField @NotNull [] getFields() { if (null == myFields) { - Collection generatedFields = fieldSupplier.apply(this); + Collection generatedFields; + DumbService dumbService = DumbService.getInstance(getProject()); + if (dumbService.isDumb() && !dumbService.isAlternativeResolveEnabled()) { + generatedFields = dumbService.computeWithAlternativeResolveEnabled( + () -> fieldSupplier.apply(this) + ); + } + else { + generatedFields = fieldSupplier.apply(this); + } myFields = generatedFields.toArray(PsiField.EMPTY_ARRAY); fieldSupplier = c -> Collections.emptyList(); } @@ -111,7 +121,16 @@ public class LombokLightClassBuilder extends LightPsiClassBuilder implements Psi @Override public PsiMethod @NotNull [] getMethods() { if (null == myMethods) { - Collection generatedMethods = methodSupplier.apply(this); + Collection generatedMethods; + DumbService dumbService = DumbService.getInstance(getProject()); + if (dumbService.isDumb() && !dumbService.isAlternativeResolveEnabled()) { + generatedMethods = dumbService.computeWithAlternativeResolveEnabled( + () -> methodSupplier.apply(this) + ); + } + else { + generatedMethods = methodSupplier.apply(this); + } myMethods = generatedMethods.toArray(PsiMethod.EMPTY_ARRAY); methodSupplier = c -> Collections.emptyList(); } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightMethodBuilder.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightMethodBuilder.java index 7061ec4e915f..da0a64314135 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightMethodBuilder.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightMethodBuilder.java @@ -3,6 +3,7 @@ package de.plushnikov.intellij.plugin.psi; import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil; import com.intellij.lang.ASTNode; import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.TextRange; @@ -189,7 +190,15 @@ public class LombokLightMethodBuilder extends LightMethodBuilder implements Synt Function builderBodyFunction = myBuilderBodyFunction; if (null == myBodyCodeBlock && (bodyAsText != null || builderBodyFunction != null)) { if (bodyAsText == null) { - bodyAsText = builderBodyFunction.apply(this); + DumbService dumbService = DumbService.getInstance(getProject()); + if (dumbService.isDumb() && !dumbService.isAlternativeResolveEnabled()) { + bodyAsText = dumbService.computeWithAlternativeResolveEnabled( + () -> builderBodyFunction.apply(this) + ); + } + else { + bodyAsText = builderBodyFunction.apply(this); + } } final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getProject()); myBodyCodeBlock = elementFactory.createCodeBlockFromText("{" + bodyAsText + "}", this); diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/LombokProcessorUtil.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/LombokProcessorUtil.java index 90fd8c0679ed..b896b39dd6c2 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/LombokProcessorUtil.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/LombokProcessorUtil.java @@ -1,5 +1,6 @@ package de.plushnikov.intellij.plugin.util; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; @@ -84,18 +85,24 @@ public final class LombokProcessorUtil { } public static Collection getOldOnX(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameterName) { - PsiAnnotationMemberValue onXValue = psiAnnotation.hasAttribute(parameterName) ? psiAnnotation.findAttributeValue(parameterName) : null; + PsiAnnotationMemberValue onXValue; + if (DumbService.isDumb(psiAnnotation.getProject())) { + onXValue = psiAnnotation.findDeclaredAttributeValue(parameterName); + } + else { + onXValue = psiAnnotation.hasAttribute(parameterName) ? psiAnnotation.findAttributeValue(parameterName) : null; + } if (!(onXValue instanceof PsiAnnotation)) { return Collections.emptyList(); } - Collection annotations = PsiAnnotationUtil.getAnnotationValues((PsiAnnotation)onXValue, "value", PsiAnnotation.class); + Collection annotations = PsiAnnotationUtil.getAnnotationValues((PsiAnnotation)onXValue, "value", PsiAnnotation.class, List.of()); return collectAnnotationStrings(annotations); } public static Collection getNewOnX(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameterName) { - if (psiAnnotation.hasAttribute(parameterName)) { + if (DumbService.isDumb(psiAnnotation.getProject()) || psiAnnotation.hasAttribute(parameterName)) { final Collection annotations = - PsiAnnotationUtil.getAnnotationValues(psiAnnotation, parameterName, PsiAnnotation.class); + PsiAnnotationUtil.getAnnotationValues(psiAnnotation, parameterName, PsiAnnotation.class, List.of()); return collectAnnotationStrings(annotations); } return Collections.emptyList(); diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationSearchUtil.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationSearchUtil.java index c11c4509f4c4..575eb4e85f71 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationSearchUtil.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationSearchUtil.java @@ -1,9 +1,9 @@ package de.plushnikov.intellij.plugin.util; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiJavaCodeReferenceElement; -import com.intellij.psi.PsiModifierListOwner; +import com.intellij.psi.*; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -14,13 +14,60 @@ public final class PsiAnnotationSearchUtil { @Nullable public static PsiAnnotation findAnnotation(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull String annotationFQN) { + if (isDumbMode(psiModifierListOwner)) { + return findAnnotationInDumbMode(psiModifierListOwner, annotationFQN); + } return psiModifierListOwner.getAnnotation(annotationFQN); } + private static @Nullable PsiAnnotation findAnnotationInDumbMode(@NotNull PsiModifierListOwner owner, @NotNull String annotationFQN) { + for (PsiAnnotation annotation : owner.getAnnotations()) { + if (hasQualifiedNameInDumbMode(annotation, annotationFQN)) { + return annotation; + } + } + return null; + } + + private static boolean hasQualifiedNameInDumbMode(PsiAnnotation annotation, @NotNull String fqn) { + PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement(); + if (referenceElement == null) return false; + String qualifiedName = referenceElement.getReferenceName(); + if (qualifiedName == null) return false; + if (qualifiedName.equals(fqn)) return true; + String referenceElementText = referenceElement.getText(); + if (referenceElementText != null && referenceElementText.equals(fqn)) return true; + if (!fqn.endsWith(qualifiedName)) return false; + PsiFile containingFile = annotation.getContainingFile(); + if (!(containingFile instanceof PsiJavaFile javaFile)) { + return false; + } + String packageName = StringUtil.getPackageName(fqn); + PsiImportList importList = javaFile.getImportList(); + if (importList == null) return false; + int indexMayByOuterClass = fqn.length() - qualifiedName.length() - 1; + String mayBeOuterClass = indexMayByOuterClass > 0 ? fqn.substring(0, indexMayByOuterClass) : null; + return importList.findOnDemandImportStatement(packageName) != null || + importList.findSingleClassImportStatement(fqn) != null || + (mayBeOuterClass!=null && importList.findSingleClassImportStatement(mayBeOuterClass) != null); + } + + private static boolean isDumbMode(@NotNull PsiElement context) { + Project project = context.getProject(); + return DumbService.isDumb(project); + } + @Nullable public static PsiAnnotation findAnnotation(@NotNull PsiModifierListOwner psiModifierListOwner, String @NotNull ... annotationFQNs) { + boolean isDumbMode = isDumbMode(psiModifierListOwner); for (String annotationFQN : annotationFQNs) { - PsiAnnotation annotation = psiModifierListOwner.getAnnotation(annotationFQN); + PsiAnnotation annotation; + if (isDumbMode) { + annotation = findAnnotationInDumbMode(psiModifierListOwner, annotationFQN); + } + else { + annotation = psiModifierListOwner.getAnnotation(annotationFQN); + } if (annotation != null) { return annotation; } @@ -29,6 +76,9 @@ public final class PsiAnnotationSearchUtil { } public static boolean isAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull String annotationFQN) { + if (isDumbMode(psiModifierListOwner)) { + return findAnnotationInDumbMode(psiModifierListOwner, annotationFQN) != null; + } return psiModifierListOwner.hasAnnotation(annotationFQN); } @@ -79,6 +129,9 @@ public final class PsiAnnotationSearchUtil { public static boolean checkAnnotationHasOneOfFQNs(@NotNull PsiAnnotation psiAnnotation, String @NotNull ... annotationFQNs) { + if (isDumbMode(psiAnnotation)) { + return ContainerUtil.or(annotationFQNs, fqn-> hasQualifiedNameInDumbMode(psiAnnotation, fqn)); + } return ContainerUtil.or(annotationFQNs, psiAnnotation::hasQualifiedName); } } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationUtil.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationUtil.java index 32e689194b04..5c2b5a5fa8f1 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationUtil.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/util/PsiAnnotationUtil.java @@ -1,6 +1,7 @@ package de.plushnikov.intellij.plugin.util; import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; @@ -10,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; /** * Some util methods for annotation processing @@ -35,9 +37,19 @@ public final class PsiAnnotationUtil { } @NotNull - public static Collection getAnnotationValues(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter, @NotNull Class asClass) { + public static Collection getAnnotationValues(@NotNull PsiAnnotation psiAnnotation, + @NotNull String parameter, + @NotNull Class asClass, + @NotNull List defaultDumbValue) { Collection result = Collections.emptyList(); - PsiAnnotationMemberValue attributeValue = psiAnnotation.findAttributeValue(parameter); + PsiAnnotationMemberValue attributeValue; + if (DumbService.isDumb(psiAnnotation.getProject())) { + attributeValue = psiAnnotation.findDeclaredAttributeValue(parameter); + if (attributeValue == null) return defaultDumbValue; + } + else { + attributeValue = psiAnnotation.findAttributeValue(parameter); + } if (attributeValue instanceof PsiArrayInitializerMemberValue) { final PsiAnnotationMemberValue[] memberValues = ((PsiArrayInitializerMemberValue) attributeValue).getInitializers(); result = new ArrayList<>(memberValues.length); diff --git a/plugins/lombok/src/main/resources/META-INF/plugin.xml b/plugins/lombok/src/main/resources/META-INF/plugin.xml index 4e407d42ded7..06d9674c6899 100644 --- a/plugins/lombok/src/main/resources/META-INF/plugin.xml +++ b/plugins/lombok/src/main/resources/META-INF/plugin.xml @@ -250,6 +250,9 @@ + + diff --git a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/AbstractLombokParsingTestCase.java b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/AbstractLombokParsingTestCase.java index d6fb647ed3c3..2699cca1f2d2 100644 --- a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/AbstractLombokParsingTestCase.java +++ b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/AbstractLombokParsingTestCase.java @@ -2,10 +2,12 @@ package de.plushnikov.intellij.plugin; import com.google.common.base.Objects; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.PomNamedTarget; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.testFramework.DumbModeTestUtils; import com.intellij.util.containers.ContainerUtil; import de.plushnikov.intellij.plugin.util.PsiElementUtil; import org.jetbrains.annotations.NotNull; @@ -48,6 +50,8 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC } public void doTest(String testName) { + DumbModeTestUtils.runInDumbModeSynchronously(getProject(), + () -> compareFiles(loadBeforeLombokFile(testName), loadAfterDeLombokFile(testName))); compareFiles(loadBeforeLombokFile(testName), loadAfterDeLombokFile(testName)); } @@ -147,11 +151,13 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC assertEquals("Initializers are not equals ", afterInitializerText, beforeInitializerText); } - private static void compareType(PsiType beforeType, PsiType afterType, PomNamedTarget whereTarget) { + private void compareType(PsiType beforeType, PsiType afterType, PomNamedTarget whereTarget) { if (null != beforeType && null != afterType) { - final String afterText = stripJavaLang(afterType.getCanonicalText()); - final String beforeText = stripJavaLang(beforeType.getCanonicalText()); - assertEquals(String.format("Types are not equal for element: %s", whereTarget.getName()), afterText, beforeText); + DumbService.getInstance(getProject()).runWithAlternativeResolveEnabled(() -> { + final String afterText = stripJavaLang(afterType.getCanonicalText()); + final String beforeText = stripJavaLang(beforeType.getCanonicalText()); + assertEquals(String.format("Types are not equal for element: %s", whereTarget.getName()), afterText, beforeText); + }); } } @@ -184,15 +190,16 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC } private void compareAnnotations(PsiModifierList beforeModifierList, PsiModifierList afterModifierList) { + DumbService dumbService = DumbService.getInstance(beforeModifierList.getProject()); if (shouldCompareAnnotations()) { Collection beforeAnnotations = Arrays.stream(beforeModifierList.getAnnotations()) - .map(PsiAnnotation::getQualifiedName) + .map(an-> dumbService.computeWithAlternativeResolveEnabled(()->an.getQualifiedName())) .filter(Pattern.compile("lombok.*").asPredicate().negate().or(LombokClassNames.NON_NULL::equals)) .filter(Pattern.compile(annotationToComparePattern()).asPredicate()) .filter(Predicate.not(annotationsToIgnoreList()::contains)) .toList(); Collection afterAnnotations = Arrays.stream(afterModifierList.getAnnotations()) - .map(PsiAnnotation::getQualifiedName) + .map(an-> dumbService.computeWithAlternativeResolveEnabled(()->an.getQualifiedName())) .filter(Pattern.compile(annotationToComparePattern()).asPredicate()) .filter(Predicate.not(annotationsToIgnoreList()::contains)) .toList(); @@ -204,8 +211,10 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC // compare annotations parameter list for (PsiAnnotation beforeAnnotation : beforeModifierList.getAnnotations()) { - String qualifiedName = beforeAnnotation.getQualifiedName(); - PsiAnnotation afterAnnotation = afterModifierList.findAnnotation(qualifiedName); + String qualifiedName = + dumbService.computeWithAlternativeResolveEnabled(() -> beforeAnnotation.getQualifiedName()); + PsiAnnotation afterAnnotation = + dumbService.computeWithAlternativeResolveEnabled(() -> afterModifierList.findAnnotation(qualifiedName)); if (null != afterAnnotation) { Map beforeParameter = Stream.of(beforeAnnotation.getParameterList().getAttributes()) .collect(Collectors.toMap(PsiNameValuePair::getAttributeName, p -> p.getValue().getText())); @@ -287,8 +296,10 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC private static Collection mapToTypeString(PsiParameterList compareMethodParameterList) { Collection result = new ArrayList<>(); final PsiParameter[] compareMethodParameterListParameters = compareMethodParameterList.getParameters(); + DumbService dumbService = DumbService.getInstance(compareMethodParameterList.getProject()); for (PsiParameter compareMethodParameterListParameter : compareMethodParameterListParameters) { - result.add(stripJavaLang(compareMethodParameterListParameter.getType().getCanonicalText())); + PsiType type = compareMethodParameterListParameter.getType(); + result.add(stripJavaLang(dumbService.computeWithAlternativeResolveEnabled(() -> type.getCanonicalText()))); } return result; } @@ -303,10 +314,12 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC PsiClassType[] afterTypes = afterThrows.getReferencedTypes(); assertEquals("Throws counts are different for Method :" + psiMethod.getName(), beforeTypes.length, afterTypes.length); + DumbService dumbService = DumbService.getInstance(psiMethod.getProject()); for (PsiClassType beforeType : beforeTypes) { boolean found = false; for (PsiClassType afterType : afterTypes) { - if (beforeType.equals(afterType)) { + boolean equals = dumbService.computeWithAlternativeResolveEnabled(()->beforeType.equals(afterType)); + if (equals) { found = true; break; } @@ -332,7 +345,9 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC ContainerUtil.map(afterConstructor.getParameterList().getParameters(), PsiParameter::getType); for (PsiMethod beforeConstructor : beforeConstructors) { - if (PsiElementUtil.methodMatches(beforeConstructor, null, null, afterConstructor.getName(), afterConstructorParameterTypes)) { + boolean methodMatches = DumbService.getInstance(getProject()).computeWithAlternativeResolveEnabled( + () -> PsiElementUtil.methodMatches(beforeConstructor, null, null, afterConstructor.getName(), afterConstructorParameterTypes)); + if (methodMatches) { final PsiModifierList intellijConstructorModifierList = beforeConstructor.getModifierList(); compareModifiers(intellijConstructorModifierList, theirsFieldModifierList); diff --git a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/configsystem/GetterDumbModeTest.java b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/configsystem/GetterDumbModeTest.java new file mode 100644 index 000000000000..30ab152d055f --- /dev/null +++ b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/configsystem/GetterDumbModeTest.java @@ -0,0 +1,41 @@ +package de.plushnikov.intellij.plugin.configsystem; + +import com.intellij.testFramework.DumbModeTestUtils; + +public class GetterDumbModeTest extends AbstractLombokConfigSystemTestCase { + + @Override + protected String getBasePath() { + return super.getBasePath() + "/configsystem/getter"; + } + + public void testDumb$GetterClassTest() { + final String fullFileName = getTestName(true).replace('$', '/') + ".java"; + final int lastIndexOf = fullFileName.lastIndexOf('/'); + final String subPath = fullFileName.substring(0, lastIndexOf); + final String fileName = fullFileName.substring(lastIndexOf + 1); + + DumbModeTestUtils.runInDumbModeSynchronously( + getProject(), + () -> { + myFixture.copyFileToProject(subPath + "/before/lombok.config", subPath + "/before/lombok.config"); + doTest(subPath + "/before/inner/" + fileName, subPath + "/after/inner/" + fileName); + } + ); + } + public void testDumbStopBubbling$GetterClassTest() { + final String fullFileName = getTestName(true).replace('$', '/') + ".java"; + final int lastIndexOf = fullFileName.lastIndexOf('/'); + final String subPath = fullFileName.substring(0, lastIndexOf); + final String fileName = fullFileName.substring(lastIndexOf + 1); + + DumbModeTestUtils.runInDumbModeSynchronously( + getProject(), + () -> { + myFixture.copyFileToProject(subPath + "/before/inner/lombok.config", subPath + "/before/inner/lombok.config"); + myFixture.copyFileToProject(subPath + "/before/lombok.config", subPath + "/before/lombok.config"); + doTest(subPath + "/before/inner/" + fileName, subPath + "/after/inner/" + fileName); + } + ); + } +} \ No newline at end of file diff --git a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/lombokconfig/ConfigDiscoveryTest.java b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/lombokconfig/ConfigDiscoveryTest.java index efd29db4d48c..b2ef2f70be4d 100644 --- a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/lombokconfig/ConfigDiscoveryTest.java +++ b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/lombokconfig/ConfigDiscoveryTest.java @@ -1,5 +1,7 @@ package de.plushnikov.intellij.plugin.lombokconfig; +import com.intellij.mock.MockDumbService; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; @@ -64,6 +66,7 @@ public class ConfigDiscoveryTest { } }; + when(project.getService(DumbService.class)).thenReturn(new MockDumbService(project)); when(psiFile.getProject()).thenReturn(project); when(psiClass.getContainingFile()).thenReturn(psiFile); when(psiFile.getOriginalFile()).thenReturn(psiFile); diff --git a/plugins/lombok/testData/configsystem/getter/dumb/after/inner/GetterClassTest.java b/plugins/lombok/testData/configsystem/getter/dumb/after/inner/GetterClassTest.java new file mode 100644 index 000000000000..2999811bca2b --- /dev/null +++ b/plugins/lombok/testData/configsystem/getter/dumb/after/inner/GetterClassTest.java @@ -0,0 +1,32 @@ +public class GetterClassTest { + private int intProperty; + private String stringProperty; + private boolean booleanProperty; + private Boolean booleanObjectProperty; + + public static void main(String[] args) { + final GetterClassTest test = new GetterClassTest(); + + test.getIntProperty(); + test.getStringProperty(); + test.getBooleanObjectProperty(); + + test.getBooleanProperty(); + } + + public int getIntProperty() { + return this.intProperty; + } + + public String getStringProperty() { + return this.stringProperty; + } + + public boolean getBooleanProperty() { + return this.booleanProperty; + } + + public Boolean getBooleanObjectProperty() { + return this.booleanObjectProperty; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/configsystem/getter/dumb/before/inner/GetterClassTest.java b/plugins/lombok/testData/configsystem/getter/dumb/before/inner/GetterClassTest.java new file mode 100644 index 000000000000..aa5207fd579e --- /dev/null +++ b/plugins/lombok/testData/configsystem/getter/dumb/before/inner/GetterClassTest.java @@ -0,0 +1,19 @@ +import lombok.Getter; + +@Getter +public class GetterClassTest { + private int intProperty; + private String stringProperty; + private boolean booleanProperty; + private Boolean booleanObjectProperty; + + public static void main(String[] args) { + final GetterClassTest test = new GetterClassTest(); + + test.getIntProperty(); + test.getStringProperty(); + test.getBooleanObjectProperty(); + + test.getBooleanProperty(); + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/configsystem/getter/dumb/before/lombok.config b/plugins/lombok/testData/configsystem/getter/dumb/before/lombok.config new file mode 100644 index 000000000000..08244ee36f5b --- /dev/null +++ b/plugins/lombok/testData/configsystem/getter/dumb/before/lombok.config @@ -0,0 +1,3 @@ +lombok.getter.noIsPrefix = true + +config.stopBubbling = true \ No newline at end of file diff --git a/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/after/inner/GetterClassTest.java b/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/after/inner/GetterClassTest.java new file mode 100644 index 000000000000..02064e80b7b5 --- /dev/null +++ b/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/after/inner/GetterClassTest.java @@ -0,0 +1,32 @@ +public class GetterClassTest { + private int intProperty; + private String stringProperty; + private boolean booleanProperty; + private Boolean booleanObjectProperty; + + public static void main(String[] args) { + final GetterClassTest test = new GetterClassTest(); + + test.getIntProperty(); + test.getStringProperty(); + test.getBooleanObjectProperty(); + + test.isBooleanProperty(); + } + + public int getIntProperty() { + return this.intProperty; + } + + public String getStringProperty() { + return this.stringProperty; + } + + public boolean isBooleanProperty() { + return this.booleanProperty; + } + + public Boolean getBooleanObjectProperty() { + return this.booleanObjectProperty; + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/inner/GetterClassTest.java b/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/inner/GetterClassTest.java new file mode 100644 index 000000000000..534539d0b29c --- /dev/null +++ b/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/inner/GetterClassTest.java @@ -0,0 +1,19 @@ +import lombok.Getter; + +@Getter +public class GetterClassTest { + private int intProperty; + private String stringProperty; + private boolean booleanProperty; + private Boolean booleanObjectProperty; + + public static void main(String[] args) { + final GetterClassTest test = new GetterClassTest(); + + test.getIntProperty(); + test.getStringProperty(); + test.getBooleanObjectProperty(); + + test.isBooleanProperty(); + } +} \ No newline at end of file diff --git a/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/inner/lombok.config b/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/inner/lombok.config new file mode 100644 index 000000000000..c2c97296e4ad --- /dev/null +++ b/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/inner/lombok.config @@ -0,0 +1 @@ +config.stopBubbling = true \ No newline at end of file diff --git a/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/lombok.config b/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/lombok.config new file mode 100644 index 000000000000..1b07d539a18c --- /dev/null +++ b/plugins/lombok/testData/configsystem/getter/dumbStopBubbling/before/lombok.config @@ -0,0 +1,2 @@ +lombok.getter.noIsPrefix = true +config.stopBubbling = true \ No newline at end of file