Improved type annotation support

PsiTypeElementImpl#addAnnotation implemented
AddAnnotationPsiFix, NullableNotNullManager adjusted
Fixes IDEA-232258 "Annotate overridden method parameters @NotNull" erroneously adds notNull to the param, not its type
Fixes IDEA-232565 Intention "Annotate overriding methods as NotNull" doesn't respect "type use"
Also, AddAnnotationPsiFix can be applied in batch now when annotations are not external.

GitOrigin-RevId: 0b652d3b032ed0d1c701beeda102c5e3c841762c
This commit is contained in:
Tagir Valeev
2020-02-12 12:32:19 +07:00
committed by intellij-monorepo-bot
parent ba85ab49e2
commit 2c486b2d0a
13 changed files with 456 additions and 79 deletions

View File

@@ -17,9 +17,28 @@ public abstract class ExternalAnnotationsManager {
public static final Topic<ExternalAnnotationsListener> TOPIC = Topic.create("external annotations", ExternalAnnotationsListener.class);
/**
* Describes where to place the new annotation
*/
public enum AnnotationPlace {
/**
* Annotation must be placed right in the code
*/
IN_CODE,
/**
* Annotation must be placed externally
*/
EXTERNAL,
/**
* User should be asked to decide whether they want to create new annotation root for external annotation.
* {@link ExternalAnnotationsManager#chooseAnnotationsPlace(PsiElement)} asks user automatically, so this result is never returned,
* but it requires EDT thread. On the other hand, {@link ExternalAnnotationsManager#chooseAnnotationsPlaceNoUi(PsiElement)}
* never display UI but may return this result.
*/
NEED_ASK_USER,
/**
* User actively cancelled the annotation addition, so it should not be added at all.
*/
NOWHERE
}
@@ -106,6 +125,18 @@ public abstract class ExternalAnnotationsManager {
@NotNull String annotationFQN,
PsiNameValuePair @Nullable [] value);
/**
* @param element element to add new annotation for
* @return place where the annotation must be added. No UI is displayed, so can be called inside any read-action.
* May return {@link AnnotationPlace#NEED_ASK_USER} if the user confirmation is necessary.
*/
@NotNull
public abstract AnnotationPlace chooseAnnotationsPlaceNoUi(@NotNull PsiElement element);
/**
* @param element element to add new annotation for
* @return place where the annotation must be added. Must be called in EDT.
*/
@NotNull
public abstract AnnotationPlace chooseAnnotationsPlace(@NotNull PsiElement element);

View File

@@ -315,6 +315,10 @@ public abstract class NullableNotNullManager {
? findAnnotationInHierarchy(owner, qualifiedNames)
: findAnnotation(owner, qualifiedNames);
PsiType type = getOwnerType(owner);
if (memberAnno != null && type instanceof PsiArrayType && AnnotationTargetUtil.isTypeAnnotation(memberAnno)) {
// Ambiguous TYPE_USE annotation on array type: we consider that it annotates an array component instead.
memberAnno = null;
}
if (memberAnno != null) {
PsiAnnotation annotation = preferTypeAnnotation(memberAnno, type);
if (annotation != memberAnno && !qualifiedNames.contains(annotation.getQualifiedName())) return null;