annotate method if asked even it's (implicitly) inferred as NotNull

This commit is contained in:
Alexey Kudravtsev
2017-06-29 15:50:42 +03:00
parent 258afb3833
commit 8037bdbfd1
5 changed files with 86 additions and 25 deletions

View File

@@ -68,7 +68,8 @@ public class AnnotateMethodFix implements LocalQuickFix {
List<MethodSignatureBackedByPsiMethod> superMethodSignatures = method.findSuperMethodSignaturesIncludingStatic(true);
for (MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) {
PsiMethod superMethod = superMethodSignature.getMethod();
if (!AnnotationUtil.isAnnotated(superMethod, myAnnotation, false, false) && superMethod.getManager().isInProject(superMethod)) {
if (!AnnotationUtil.isAnnotated(superMethod, myAnnotation, false, false, true, null) &&
superMethod.getManager().isInProject(superMethod)) {
int ret = shouldAnnotateBaseMethod(method, superMethod, project);
if (ret != 0 && ret != 1) return;
if (ret == 0) {
@@ -79,7 +80,9 @@ public class AnnotateMethodFix implements LocalQuickFix {
if (annotateOverriddenMethods()) {
PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
for (PsiMethod psiMethod : methods) {
if (AnnotationUtil.isAnnotatingApplicable(psiMethod, myAnnotation) && !AnnotationUtil.isAnnotated(psiMethod, myAnnotation, false, false) && psiMethod.getManager().isInProject(psiMethod)) {
if (AnnotationUtil.isAnnotatingApplicable(psiMethod, myAnnotation) &&
!AnnotationUtil.isAnnotated(psiMethod, myAnnotation, false, false, true, null) &&
psiMethod.getManager().isInProject(psiMethod)) {
toAnnotate.add(psiMethod);
}
}

View File

@@ -86,13 +86,10 @@ public class AnnotationUtil {
}
private static PsiAnnotation findOwnAnnotation(final PsiModifierListOwner listOwner, Collection<String> annotationNames) {
ConcurrentFactoryMap<Collection<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
Map<Collection<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
() -> {
ConcurrentFactoryMap<Collection<String>, PsiAnnotation> value = new ConcurrentFactoryMap<Collection<String>, PsiAnnotation>() {
@Nullable
@Override
protected PsiAnnotation create(Collection<String> annotationNames1) {
Map<Collection<String>, PsiAnnotation> value = ConcurrentFactoryMap.createConcurrentMap(annotationNames1-> {
final PsiModifierList list = listOwner.getModifierList();
if (list == null) return null;
for (PsiAnnotation annotation : list.getAnnotations()) {
@@ -102,20 +99,17 @@ public class AnnotationUtil {
}
return null;
}
};
);
return CachedValueProvider.Result.create(value, PsiModificationTracker.MODIFICATION_COUNT);
});
return map.get(annotationNames);
}
private static PsiAnnotation findNonCodeAnnotation(final PsiModifierListOwner listOwner, Collection<String> annotationNames) {
ConcurrentFactoryMap<Collection<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
Map<Collection<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
() -> {
ConcurrentFactoryMap<Collection<String>, PsiAnnotation> value = new ConcurrentFactoryMap<Collection<String>, PsiAnnotation>() {
@Nullable
@Override
protected PsiAnnotation create(Collection<String> annotationNames1) {
Map<Collection<String>, PsiAnnotation> value = ConcurrentFactoryMap.createConcurrentMap(annotationNames1-> {
final Project project = listOwner.getProject();
final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project);
for (String annotationName : annotationNames1) {
@@ -134,7 +128,7 @@ public class AnnotationUtil {
return null;
}
};
);
return CachedValueProvider.Result.create(value, PsiModificationTracker.MODIFICATION_COUNT);
});
return map.get(annotationNames);
@@ -184,13 +178,11 @@ public class AnnotationUtil {
PsiAnnotation directAnnotation = findAnnotation(listOwner, annotationNames);
if (directAnnotation != null) return directAnnotation;
ConcurrentFactoryMap<Set<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
Map<Set<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
() -> {
ConcurrentFactoryMap<Set<String>, PsiAnnotation> value = new ConcurrentFactoryMap<Set<String>, PsiAnnotation>() {
@Nullable
@Override
protected PsiAnnotation create(Set<String> annotationNames1) {
Map<Set<String>, PsiAnnotation> value = ConcurrentFactoryMap.createConcurrentMap(annotationNames1->
{
for (PsiModifierListOwner superOwner : getSuperAnnotationOwners(listOwner)) {
PsiAnnotation annotation = findAnnotation(superOwner, annotationNames1);
if (annotation != null) {
@@ -199,7 +191,7 @@ public class AnnotationUtil {
}
return null;
}
};
);
return CachedValueProvider.Result.create(value, PsiModificationTracker.MODIFICATION_COUNT);
});
return map.get(annotationNames);
@@ -280,6 +272,15 @@ public class AnnotationUtil {
boolean checkHierarchy,
boolean skipExternal,
@Nullable Set<PsiMember> processed) {
return isAnnotated(listOwner, annotationFQN, checkHierarchy, skipExternal, skipExternal, processed);
}
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
@NotNull String annotationFQN,
boolean checkHierarchy,
boolean skipExternal,
boolean skipInferred,
@Nullable Set<PsiMember> processed) {
if (!listOwner.isValid()) return false;
PsiModifierList modifierList = listOwner.getModifierList();
@@ -289,14 +290,23 @@ public class AnnotationUtil {
if (annotation != null) return true;
PsiType type = null;
if (listOwner instanceof PsiMethod) type = ((PsiMethod)listOwner).getReturnType();
else if (listOwner instanceof PsiVariable) type = ((PsiVariable)listOwner).getType();
if (listOwner instanceof PsiMethod) {
type = ((PsiMethod)listOwner).getReturnType();
}
else if (listOwner instanceof PsiVariable) {
type = ((PsiVariable)listOwner).getType();
}
if (type != null && type.findAnnotation(annotationFQN) != null) return true;
if (!skipExternal) {
final Project project = listOwner.getProject();
if (ExternalAnnotationsManager.getInstance(project).findExternalAnnotation(listOwner, annotationFQN) != null ||
InferredAnnotationsManager.getInstance(project).findInferredAnnotation(listOwner, annotationFQN) != null) {
if (ExternalAnnotationsManager.getInstance(project).findExternalAnnotation(listOwner, annotationFQN) != null) {
return true;
}
}
if (!skipInferred) {
final Project project = listOwner.getProject();
if (InferredAnnotationsManager.getInstance(project).findInferredAnnotation(listOwner, annotationFQN) != null) {
return true;
}
}
@@ -536,7 +546,7 @@ public class AnnotationUtil {
if (a == null) {
return b == null;
}
else if (b == null) {
if (b == null) {
return false;
}
final String name = a.getQualifiedName();

View File

@@ -0,0 +1,18 @@
// "Annotate overridden methods as '@NotNull'" "true"
import org.jetbrains.annotations.NotNull;
abstract class P2 {
@NotNull<caret>
String foo(@NotNull String p) {
return p;
}
Object o = new P2() {
@NotNull
@Override
String foo(String p) {
return "";
}
};
}

View File

@@ -0,0 +1,17 @@
// "Annotate overridden methods as '@NotNull'" "true"
import org.jetbrains.annotations.NotNull;
abstract class P2 {
@NotNull<caret>
String foo(@NotNull String p) {
return p;
}
Object o = new P2() {
@Override
String foo(String p) {
return "";
}
};
}

View File

@@ -67,3 +67,16 @@ public class AnnotateMethodTest extends LightQuickFixTestCase {
return LanguageLevel.JDK_1_5;
}
}
abstract class P2 {
@NotNull<caret>
String foo(@NotNull String p) {
return p;
}
Object o = new P2() {
@Override
String foo(String p) {
return "";
}
};
}