diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index 3754485bdbf9..15e381aad25e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -126,6 +126,7 @@ public final class AnnotationsHighlightUtil { } PsiAnnotationMethod annotationMethod = ObjectUtils.tryCast(method, PsiAnnotationMethod.class); if (annotationMethod == null) return null; + if (!annotationMethod.isPhysical()) return null; boolean fromDefaultValue = PsiTreeUtil.isAncestor(annotationMethod.getDefaultValue(), value, false); if (value instanceof PsiAnnotation) { PsiJavaCodeReferenceElement nameRef = ((PsiAnnotation)value).getNameReferenceElement(); diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/completion/LombokOnXCompletionContributorFilter.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/completion/LombokOnXCompletionContributorFilter.java new file mode 100644 index 000000000000..aa68fd8835bc --- /dev/null +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/completion/LombokOnXCompletionContributorFilter.java @@ -0,0 +1,71 @@ +package de.plushnikov.intellij.plugin.completion; + +import com.intellij.codeInsight.completion.CompletionContributor; +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiUtil; +import com.intellij.util.containers.ContainerUtil; +import de.plushnikov.intellij.plugin.LombokClassNames; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collection; + +/** + * A completion contributor filter for Lombok onX-Annotations, and they default onX-Methods without underscore (_) at the end. + * These default methods can/should be used only for old JDKs like 1.7 From 1.8 synthetic underscored methods should be used. + * @see Lombok onX-Documentation + */ +public class LombokOnXCompletionContributorFilter extends CompletionContributor { + + @Override + public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) { + if (PsiUtil.getLanguageLevel(parameters.getPosition().getProject()).isLessThan(LanguageLevel.JDK_1_8)) { + return; + } + + result.runRemainingContributors(parameters, completionResult -> { + LookupElement lookupElement = completionResult.getLookupElement(); + if (shouldKeepItem(lookupElement)) { + result.passResult(completionResult); + } + }); + } + + private static boolean shouldKeepItem(LookupElement item) { + if (ONX_PARAMETERS.contains(item.getLookupString())) { + if (item.getPsiElement() instanceof PsiMethod psiMethod) { + final PsiClass containingClass = psiMethod.getContainingClass(); + if (null != containingClass && containingClass.isAnnotationType()) { + if (ONXABLE_ANNOTATION_NAMES.contains(containingClass.getName())) { + return !ONXABLE_ANNOTATION_FQNS.contains(containingClass.getQualifiedName()); + } + } + } + } + return true; + } + + private static final Collection ONX_PARAMETERS = Arrays.asList( + "onConstructor", + "onMethod", + "onParam" + ); + + private static final Collection ONXABLE_ANNOTATION_FQNS = Arrays.asList( + LombokClassNames.GETTER, + LombokClassNames.SETTER, + LombokClassNames.WITH, + LombokClassNames.WITHER, + LombokClassNames.NO_ARGS_CONSTRUCTOR, + LombokClassNames.REQUIRED_ARGS_CONSTRUCTOR, + LombokClassNames.ALL_ARGS_CONSTRUCTOR, + LombokClassNames.EQUALS_AND_HASHCODE + ); + private static final Collection ONXABLE_ANNOTATION_NAMES = ContainerUtil.map(ONXABLE_ANNOTATION_FQNS, StringUtil::getShortName); +} diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/extension/LombokHighlightErrorFilter.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/extension/LombokHighlightErrorFilter.java index 22c77f6c43fa..49292f768685 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/extension/LombokHighlightErrorFilter.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/extension/LombokHighlightErrorFilter.java @@ -23,9 +23,6 @@ import java.util.regex.Pattern; public class LombokHighlightErrorFilter implements HighlightInfoFilter { private static final class Holder { - static final Pattern LOMBOK_ANY_ANNOTATION_REQUIRED = - Pattern.compile(JavaErrorBundle.message("incompatible.types", "lombok.*AnyAnnotation\\[\\]", "__*")); - static final Map>> registeredHooks; static { @@ -59,12 +56,9 @@ public class LombokHighlightErrorFilter implements HighlightInfoFilter { } // handle rest cases - String description = highlightInfo.getDescription(); if (HighlightSeverity.ERROR.equals(highlightInfo.getSeverity())) { //Handling onX parameters - if (OnXAnnotationHandler.isOnXParameterAnnotation(highlightInfo, file) - || OnXAnnotationHandler.isOnXParameterValue(highlightInfo, file) - || (description != null && Holder.LOMBOK_ANY_ANNOTATION_REQUIRED.matcher(description).matches())) { + if (OnXAnnotationHandler.isOnXParameterAnnotation(highlightInfo, file)) { return false; } } @@ -99,12 +93,14 @@ public class LombokHighlightErrorFilter implements HighlightInfoFilter { @Override public void processHook(@NotNull PsiElement highlightedElement, @NotNull HighlightInfo highlightInfo) { PsiElement importantParent = PsiTreeUtil.getParentOfType(highlightedElement, - PsiMethod.class, PsiLambdaExpression.class, PsiMethodReferenceExpression.class, PsiClassInitializer.class + PsiMethod.class, PsiLambdaExpression.class, + PsiMethodReferenceExpression.class, PsiClassInitializer.class ); // applicable only for methods if (importantParent instanceof PsiMethod) { - AddAnnotationFix fix = PsiQuickFixFactory.createAddAnnotationFix(LombokClassNames.SNEAKY_THROWS, (PsiModifierListOwner) importantParent); + AddAnnotationFix fix = + PsiQuickFixFactory.createAddAnnotationFix(LombokClassNames.SNEAKY_THROWS, (PsiModifierListOwner)importantParent); highlightInfo.registerFix(fix, null, null, null, null); } } @@ -122,5 +118,4 @@ public class LombokHighlightErrorFilter implements HighlightInfoFilter { abstract public void processHook(@NotNull PsiElement highlightedElement, @NotNull HighlightInfo highlightInfo); } - } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/handler/OnXAnnotationHandler.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/handler/OnXAnnotationHandler.java index 525b90c3db8b..5c607b220c59 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/handler/OnXAnnotationHandler.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/handler/OnXAnnotationHandler.java @@ -12,12 +12,11 @@ import java.util.regex.Pattern; public final class OnXAnnotationHandler { - private static final Pattern UNDERSCORES = Pattern.compile("__*"); - private static final Pattern CANNOT_RESOLVE_SYMBOL_UNDERSCORES_MESSAGE = Pattern.compile(JavaErrorBundle.message("cannot.resolve.symbol", "__*")); - private static final Pattern CANNOT_RESOLVE_METHOD_UNDERSCORES_MESSAGE = Pattern.compile(JavaErrorBundle.message("cannot.resolve.method", "(onMethod|onConstructor|onParam)_+")); - + private static final Pattern LOMBOK_ANY_ANNOTATION_REQUIRED = + Pattern.compile(JavaErrorBundle.message("incompatible.types", "lombok.*AnyAnnotation\\[\\]", "__*")); + private static final Pattern CANNOT_RESOLVE_SYMBOL_UNDERSCORES_MESSAGE = + Pattern.compile(JavaErrorBundle.message("cannot.resolve.symbol", "__*")); private static final String ANNOTATION_TYPE_EXPECTED = JavaErrorBundle.message("annotation.annotation.type.expected"); - private static final String CANNOT_FIND_METHOD_VALUE_MESSAGE = JavaErrorBundle.message("annotation.missing.method", "value"); private static final Collection ONXABLE_ANNOTATIONS = Arrays.asList( LombokClassNames.GETTER, @@ -38,8 +37,8 @@ public final class OnXAnnotationHandler { public static boolean isOnXParameterAnnotation(HighlightInfo highlightInfo, PsiFile file) { final String description = StringUtil.notNullize(highlightInfo.getDescription()); if (!(ANNOTATION_TYPE_EXPECTED.equals(description) - || CANNOT_RESOLVE_SYMBOL_UNDERSCORES_MESSAGE.matcher(description).matches() - || CANNOT_RESOLVE_METHOD_UNDERSCORES_MESSAGE.matcher(description).matches())) { + || CANNOT_RESOLVE_SYMBOL_UNDERSCORES_MESSAGE.matcher(description).matches() + || LOMBOK_ANY_ANNOTATION_REQUIRED.matcher(description).matches())) { return false; } @@ -59,22 +58,8 @@ public final class OnXAnnotationHandler { } PsiElement containingAnnotation = nameValuePair.getContext().getContext(); - return containingAnnotation instanceof PsiAnnotation && ONXABLE_ANNOTATIONS.contains(((PsiAnnotation) containingAnnotation).getQualifiedName()); - } - - public static boolean isOnXParameterValue(HighlightInfo highlightInfo, PsiFile file) { - if (!CANNOT_FIND_METHOD_VALUE_MESSAGE.equals(highlightInfo.getDescription())) { - return false; - } - - PsiElement highlightedElement = file.findElementAt(highlightInfo.getStartOffset()); - PsiNameValuePair nameValuePair = findContainingNameValuePair(highlightedElement); - if (nameValuePair == null || !(nameValuePair.getContext() instanceof PsiAnnotationParameterList)) { - return false; - } - - PsiElement leftSibling = nameValuePair.getContext().getPrevSibling(); - return (leftSibling != null && UNDERSCORES.matcher(StringUtil.notNullize(leftSibling.getText())).matches()); + return containingAnnotation instanceof PsiAnnotation && + ONXABLE_ANNOTATIONS.contains(((PsiAnnotation)containingAnnotation).getQualifiedName()); } private static PsiNameValuePair findContainingNameValuePair(PsiElement highlightedElement) { @@ -83,6 +68,6 @@ public final class OnXAnnotationHandler { nameValuePair = nameValuePair.getContext(); } - return (PsiNameValuePair) nameValuePair; + return (PsiNameValuePair)nameValuePair; } } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/lombok/LombokAnnotationProcessor.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/lombok/LombokAnnotationProcessor.java new file mode 100644 index 000000000000..4d14cc98196b --- /dev/null +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/lombok/LombokAnnotationProcessor.java @@ -0,0 +1,77 @@ +package de.plushnikov.intellij.plugin.processor.lombok; + +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiArrayType; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiType; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.containers.ContainerUtil; +import de.plushnikov.intellij.plugin.psi.LombokLightAnnotationMethodBuilder; +import de.plushnikov.intellij.plugin.psi.LombokLightArrayInitializerMemberValue; +import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +import static de.plushnikov.intellij.plugin.LombokClassNames.*; + +public final class LombokAnnotationProcessor { + private static final Map, Collection>> config = initializeConfig(); + + private static Map, Collection>> initializeConfig() { + return Map.of( + "onParam_", createAnnotationsPair(SETTER, EQUALS_AND_HASHCODE, WITH, WITHER), + "onMethod_", createAnnotationsPair(GETTER, SETTER, WITH, WITHER), + "onConstructor_", createAnnotationsPair(ALL_ARGS_CONSTRUCTOR, REQUIRED_ARGS_CONSTRUCTOR, NO_ARGS_CONSTRUCTOR) + ); + } + + private static Pair, Collection> createAnnotationsPair(String... fqns) { + Collection fqnList = Arrays.asList(fqns); + Collection shortNamesList = ContainerUtil.map(fqnList, StringUtil::getShortName); + return Pair.pair(shortNamesList, fqnList); + } + + @NotNull + public static List process(@NotNull PsiClass psiClass, @Nullable String nameHint) { + if (nameHint != null && !ContainerUtil.exists(config.keySet(), nameHint::startsWith)) { + return Collections.emptyList(); + } + + List result = new ArrayList<>(); + + if (nameHint != null) { + final Pair, Collection> hintConfig = config.get(nameHint); + addAnnotationMethods(psiClass, hintConfig.getFirst(), hintConfig.getSecond(), nameHint, result); + } + else { + for (Map.Entry, Collection>> entry : config.entrySet()) { + addAnnotationMethods(psiClass, entry.getValue().getFirst(), entry.getValue().getSecond(), entry.getKey(), result); + } + } + + return result; + } + + private static void addAnnotationMethods(@NotNull PsiClass psiClass, + @NotNull Collection onXAnnotationNames, + @NotNull Collection onXAnnotationFQNs, + @NotNull String methodName, + @NotNull List result) { + if (onXAnnotationNames.contains(psiClass.getName()) && onXAnnotationFQNs.contains(psiClass.getQualifiedName())) { + result.add(createAnnotationMethod(psiClass, methodName)); + } + } + + private static LombokLightMethodBuilder createAnnotationMethod(@NotNull PsiClass psiClass, @NotNull String methodName) { + final PsiType myAnnotationType = + PsiType.getJavaLangObject(psiClass.getManager(), GlobalSearchScope.projectScope(psiClass.getProject())); + return new LombokLightAnnotationMethodBuilder(psiClass.getManager(), methodName) + .withDefaultValue(new LombokLightArrayInitializerMemberValue(psiClass.getManager(), psiClass.getLanguage())) + .withContainingClass(psiClass) + .withMethodReturnType(new PsiArrayType(myAnnotationType)); + } +} \ No newline at end of file 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 f27d028545bf..0a78b37b7cc7 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 @@ -5,13 +5,18 @@ import com.intellij.psi.*; import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.augment.PsiExtensionMethod; import com.intellij.psi.impl.source.PsiExtensibleClass; +import com.intellij.psi.search.GlobalSearchScope; import com.siyeh.ig.psiutils.InitializationUtils; import de.plushnikov.intellij.plugin.LombokClassNames; import de.plushnikov.intellij.plugin.processor.LombokProcessorManager; import de.plushnikov.intellij.plugin.processor.Processor; import de.plushnikov.intellij.plugin.processor.ValProcessor; +import de.plushnikov.intellij.plugin.processor.lombok.LombokAnnotationProcessor; import de.plushnikov.intellij.plugin.processor.method.ExtensionMethodsHelper; import de.plushnikov.intellij.plugin.processor.modifier.ModifierProcessor; +import de.plushnikov.intellij.plugin.psi.LombokLightAnnotationMethodBuilder; +import de.plushnikov.intellij.plugin.psi.LombokLightClassBuilder; +import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder; import de.plushnikov.intellij.plugin.util.PsiAnnotationSearchUtil; import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil; import org.jetbrains.annotations.NotNull; @@ -118,22 +123,26 @@ public class LombokAugmentProvider extends PsiAugmentProvider { @NotNull final Class type, @Nullable String nameHint) { final List emptyResult = Collections.emptyList(); - if ((type != PsiClass.class && type != PsiField.class && type != PsiMethod.class) || !(element instanceof PsiExtensibleClass) - || (element instanceof PsiCompiledElement) // skip compiled classes - ) { + if (type != PsiClass.class && type != PsiField.class && type != PsiMethod.class || !(element instanceof PsiExtensibleClass psiClass)) { return emptyResult; } - final PsiClass psiClass = (PsiClass)element; if (!psiClass.getLanguage().isKindOf(JavaLanguage.INSTANCE)) { return emptyResult; } - // Skip processing of Annotations and Interfaces + + // skip processing if disabled, or no lombok library is present + if (!hasLombokLibrary(element.getProject())) { + return emptyResult; + } + if (psiClass.isAnnotationType() && type == PsiMethod.class) { + return (List)LombokAnnotationProcessor.process(psiClass, nameHint); + } + // Skip processing of other Annotations and Interfaces if (psiClass.isAnnotationType() || psiClass.isInterface()) { return emptyResult; } - // skip processing if disabled, or no lombok library is present - if (!hasLombokLibrary(element.getProject())) { + if (element instanceof PsiCompiledElement) { // skip compiled classes) return emptyResult; } diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightAnnotationMemberValue.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightAnnotationMemberValue.java new file mode 100644 index 000000000000..f617dbf6cf95 --- /dev/null +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightAnnotationMemberValue.java @@ -0,0 +1,21 @@ +package de.plushnikov.intellij.plugin.psi; + +import com.intellij.lang.Language; +import com.intellij.psi.PsiAnnotationMemberValue; +import com.intellij.psi.PsiManager; +import com.intellij.psi.SyntheticElement; +import com.intellij.psi.impl.light.LightElement; +import org.jetbrains.annotations.NotNull; + +public class LombokLightAnnotationMemberValue extends LightElement implements PsiAnnotationMemberValue, SyntheticElement { + + public LombokLightAnnotationMemberValue(@NotNull PsiManager manager, + @NotNull Language language) { + super(manager, language); + } + + @Override + public String toString() { + return "LombokLightAnnotationMemberValue:" + getName(); + } +} diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightAnnotationMethodBuilder.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightAnnotationMethodBuilder.java new file mode 100644 index 000000000000..428026d44417 --- /dev/null +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightAnnotationMethodBuilder.java @@ -0,0 +1,25 @@ +package de.plushnikov.intellij.plugin.psi; + +import com.intellij.psi.PsiAnnotationMemberValue; +import com.intellij.psi.PsiAnnotationMethod; +import com.intellij.psi.PsiManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class LombokLightAnnotationMethodBuilder extends LombokLightMethodBuilder implements PsiAnnotationMethod { + private PsiAnnotationMemberValue defaultValue; + + public LombokLightAnnotationMethodBuilder(@NotNull PsiManager manager, @NotNull String name) { + super(manager, name); + } + + public LombokLightAnnotationMethodBuilder withDefaultValue(PsiAnnotationMemberValue defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + @Override + public @Nullable PsiAnnotationMemberValue getDefaultValue() { + return defaultValue; + } +} diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightArrayInitializerMemberValue.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightArrayInitializerMemberValue.java new file mode 100644 index 000000000000..812fd1f0e8fc --- /dev/null +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/psi/LombokLightArrayInitializerMemberValue.java @@ -0,0 +1,27 @@ +package de.plushnikov.intellij.plugin.psi; + +import com.intellij.lang.Language; +import com.intellij.psi.PsiAnnotationMemberValue; +import com.intellij.psi.PsiArrayInitializerMemberValue; +import com.intellij.psi.PsiManager; +import com.intellij.psi.SyntheticElement; +import com.intellij.psi.impl.light.LightElement; +import org.jetbrains.annotations.NotNull; + +public class LombokLightArrayInitializerMemberValue extends LightElement implements PsiArrayInitializerMemberValue, SyntheticElement { + + public LombokLightArrayInitializerMemberValue(@NotNull PsiManager manager, + @NotNull Language language) { + super(manager, language); + } + + @Override + public String toString() { + return "LombokLightArrayInitializerMemberValue:" + getName(); + } + + @Override + public PsiAnnotationMemberValue @NotNull [] getInitializers() { + return PsiAnnotationMemberValue.EMPTY_ARRAY; + } +} 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 1cb0f5c62ea0..8678df3af360 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 @@ -26,6 +26,7 @@ public class LombokLightClassBuilder extends LightPsiClassBuilder implements Psi private final LombokLightModifierList myModifierList; private boolean myIsEnum; + private boolean myIsAnnotationType; private PsiField[] myFields; private PsiMethod[] myMethods; @@ -35,6 +36,7 @@ public class LombokLightClassBuilder extends LightPsiClassBuilder implements Psi public LombokLightClassBuilder(@NotNull PsiElement context, @NotNull String simpleName, @NotNull String qualifiedName) { super(context, simpleName); myIsEnum = false; + myIsAnnotationType = false; myQualifiedName = qualifiedName; myBaseIcon = LombokIcons.Nodes.LombokClass; myModifierList = new LombokLightModifierList(context.getManager(), context.getLanguage()); @@ -91,6 +93,11 @@ public class LombokLightClassBuilder extends LightPsiClassBuilder implements Psi return myIsEnum; } + @Override + public boolean isAnnotationType() { + return myIsAnnotationType; + } + @Override public PsiField @NotNull [] getFields() { if (null == myFields) { @@ -141,6 +148,11 @@ public class LombokLightClassBuilder extends LightPsiClassBuilder implements Psi return this; } + public LombokLightClassBuilder withAnnotationType(boolean isAnnotationType) { + myIsAnnotationType = isAnnotationType; + return this; + } + public LombokLightClassBuilder withImplicitModifier(@PsiModifier.ModifierConstant @NotNull @NonNls String modifier) { myModifierList.addImplicitModifierProperty(modifier); return this; diff --git a/plugins/lombok/src/main/resources/META-INF/plugin.xml b/plugins/lombok/src/main/resources/META-INF/plugin.xml index 6e11a57cdb23..36e086ced0f8 100644 --- a/plugins/lombok/src/main/resources/META-INF/plugin.xml +++ b/plugins/lombok/src/main/resources/META-INF/plugin.xml @@ -76,6 +76,8 @@ + + diff --git a/plugins/lombok/src/test/java/com/intellij/java/lomboktest/LombokHighlightingTest.java b/plugins/lombok/src/test/java/com/intellij/java/lomboktest/LombokHighlightingTest.java index 30cc4e66f5bf..96b3da3ef342 100644 --- a/plugins/lombok/src/test/java/com/intellij/java/lomboktest/LombokHighlightingTest.java +++ b/plugins/lombok/src/test/java/com/intellij/java/lomboktest/LombokHighlightingTest.java @@ -61,6 +61,10 @@ public class LombokHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testOnXExample() { + doTest(); + } + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/completion/LombokOnXCompletionContributorFilterTest.java b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/completion/LombokOnXCompletionContributorFilterTest.java new file mode 100644 index 000000000000..3272b96d64e8 --- /dev/null +++ b/plugins/lombok/src/test/java/de/plushnikov/intellij/plugin/completion/LombokOnXCompletionContributorFilterTest.java @@ -0,0 +1,71 @@ +package de.plushnikov.intellij.plugin.completion; + +import com.intellij.codeInsight.completion.CompletionType; +import com.intellij.ide.highlighter.JavaFileType; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.pom.java.LanguageLevel; +import de.plushnikov.intellij.plugin.AbstractLombokLightCodeInsightTestCase; +import org.intellij.lang.annotations.Language; + +import java.util.Arrays; +import java.util.List; + +public class LombokOnXCompletionContributorFilterTest extends AbstractLombokLightCodeInsightTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_8); + } + + public void testOnConstructorJdk7() { + LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7); + testOnAnnotation(""" + import lombok.AllArgsConstructor; + + @AllArgsConstructor() + public class OnXExample { + private final long unid; + } + """, Arrays.asList("access", "onConstructor", "onConstructor_", "staticName")); + } + + public void testOnConstructor() { + testOnAnnotation(""" + import lombok.RequiredArgsConstructor; + + @RequiredArgsConstructor(onConstructor_ = @Deprecated) + public class OnXExample { + private final long unid; + } + """, Arrays.asList("access", "onConstructor_", "staticName")); + } + + public void testOnMethod() { + testOnAnnotation(""" + import lombok.Getter; + + public class OnXExample { + @Getter(onMethod_ = {@Deprecated, @SuppressWarnings(value = "someId")}) + private long unid; + } + """, Arrays.asList("lazy = true", "onMethod_", "value", "lazy = false")); + } + + public void testOnParam() { + testOnAnnotation(""" + import lombok.Setter; + + public class OnXExample { + @Setter(onMethod_ = @Deprecated, onParam_ = @SuppressWarnings(value ="someOtherId")) + private long unid; + } + """, Arrays.asList("onMethod_", "onParam_", "value")); + } + + private void testOnAnnotation(@Language("JAVA") String textInput, List expected) { + myFixture.configureByText(JavaFileType.INSTANCE, textInput); + myFixture.complete(CompletionType.BASIC); + List strings = myFixture.getLookupElementStrings(); + assertSameElements(strings, expected); + } +} diff --git a/plugins/lombok/testData/highlighting/OnXExample.java b/plugins/lombok/testData/highlighting/OnXExample.java new file mode 100644 index 000000000000..4ccee6ad5add --- /dev/null +++ b/plugins/lombok/testData/highlighting/OnXExample.java @@ -0,0 +1,15 @@ +package highlighting; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +//@AllArgsConstructor(onConstructor_ = @Deprecated) +@AllArgsConstructor(onConstructor = @__( @Deprecated)) +@RequiredArgsConstructor(onConstructor_ = @Deprecated) +public class OnXExample { + @Getter(onMethod_ = {@Deprecated, @SuppressWarnings(value = "someId")}) //JDK8 + @Setter(onMethod_ = @Deprecated, onParam_ = @SuppressWarnings(value = "someOtherId")) //JDK8 + private long unid; +} \ No newline at end of file