cache frequent AnnotationUtil query results

This commit is contained in:
peter
2014-09-18 21:42:32 +02:00
parent ac17169dba
commit 0bf5e37724
3 changed files with 126 additions and 48 deletions
@@ -375,7 +375,7 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool {
}
static AllowedValues getAllowedValues(@NotNull PsiModifierListOwner element, PsiType type, Set<PsiClass> visited) {
PsiAnnotation[] annotations = AnnotationUtil.getAllAnnotations(element, true, null);
PsiAnnotation[] annotations = getAllAnnotations(element);
PsiManager manager = element.getManager();
for (PsiAnnotation annotation : annotations) {
AllowedValues values;
@@ -398,6 +398,17 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool {
return parseBeanInfo(element, manager);
}
private static PsiAnnotation[] getAllAnnotations(final PsiModifierListOwner element) {
return CachedValuesManager.getCachedValue(element, new CachedValueProvider<PsiAnnotation[]>() {
@Nullable
@Override
public Result<PsiAnnotation[]> compute() {
return Result.create(AnnotationUtil.getAllAnnotations(element, true, null),
PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
});
}
private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner, @NotNull PsiManager manager) {
PsiMethod method = null;
if (owner instanceof PsiParameter) {
@@ -17,9 +17,9 @@ package com.intellij.codeInsight;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ConcurrentFactoryMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
@@ -104,33 +104,75 @@ public class AnnotationUtil {
public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Collection<String> annotationNames,
final boolean skipExternal) {
if (listOwner == null) return null;
final PsiModifierList list = listOwner.getModifierList();
if (list == null) return null;
final PsiAnnotation[] allAnnotations = list.getAnnotations();
for (PsiAnnotation annotation : allAnnotations) {
String qualifiedName = annotation.getQualifiedName();
if (annotationNames.contains(qualifiedName)) {
return annotation;
}
PsiAnnotation annotation = findOwnAnnotation(listOwner, annotationNames);
if (annotation != null) {
return annotation;
}
if (!skipExternal) {
final Project project = listOwner.getProject();
final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project);
for (String annotationName : annotationNames) {
final PsiAnnotation annotation = annotationsManager.findExternalAnnotation(listOwner, annotationName);
if (annotation != null) {
return annotation;
return skipExternal ? null : findNonCodeAnnotation(listOwner, annotationNames);
}
private static PsiAnnotation findOwnAnnotation(final PsiModifierListOwner listOwner, Collection<String> annotationNames) {
ConcurrentFactoryMap<Collection<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
new CachedValueProvider<ConcurrentFactoryMap<Collection<String>, PsiAnnotation>>() {
@Nullable
@Override
public Result<ConcurrentFactoryMap<Collection<String>, PsiAnnotation>> compute() {
ConcurrentFactoryMap<Collection<String>, PsiAnnotation> value = new ConcurrentFactoryMap<Collection<String>, PsiAnnotation>() {
@Nullable
@Override
protected PsiAnnotation create(Collection<String> annotationNames) {
final PsiModifierList list = listOwner.getModifierList();
if (list == null) return null;
for (PsiAnnotation annotation : list.getAnnotations()) {
if (annotationNames.contains(annotation.getQualifiedName())) {
return annotation;
}
}
return null;
}
};
return Result.create(value, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
}
final InferredAnnotationsManager inferredAnnotationsManager = InferredAnnotationsManager.getInstance(project);
for (String annotationName : annotationNames) {
final PsiAnnotation annotation = inferredAnnotationsManager.findInferredAnnotation(listOwner, annotationName);
if (annotation != null) {
return annotation;
});
return map.get(annotationNames);
}
private static PsiAnnotation findNonCodeAnnotation(final PsiModifierListOwner listOwner, Collection<String> annotationNames) {
ConcurrentFactoryMap<Collection<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
new CachedValueProvider<ConcurrentFactoryMap<Collection<String>, PsiAnnotation>>() {
@Nullable
@Override
public Result<ConcurrentFactoryMap<Collection<String>, PsiAnnotation>> compute() {
ConcurrentFactoryMap<Collection<String>, PsiAnnotation> value = new ConcurrentFactoryMap<Collection<String>, PsiAnnotation>() {
@Nullable
@Override
protected PsiAnnotation create(Collection<String> annotationNames) {
final Project project = listOwner.getProject();
final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project);
for (String annotationName : annotationNames) {
final PsiAnnotation annotation = annotationsManager.findExternalAnnotation(listOwner, annotationName);
if (annotation != null) {
return annotation;
}
}
final InferredAnnotationsManager inferredAnnotationsManager = InferredAnnotationsManager.getInstance(project);
for (String annotationName : annotationNames) {
final PsiAnnotation annotation = inferredAnnotationsManager.findInferredAnnotation(listOwner, annotationName);
if (annotation != null) {
return annotation;
}
}
return null;
}
};
return Result.create(value, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
}
}
return null;
});
return map.get(annotationNames);
}
@NotNull
@@ -150,25 +192,42 @@ public class AnnotationUtil {
}
@Nullable
public static PsiAnnotation findAnnotationInHierarchy(PsiModifierListOwner listOwner, @NotNull Set<String> annotationNames) {
public static PsiAnnotation findAnnotationInHierarchy(final PsiModifierListOwner listOwner, @NotNull Set<String> annotationNames) {
PsiAnnotation directAnnotation = findAnnotation(listOwner, annotationNames);
if (directAnnotation != null) return directAnnotation;
if (listOwner instanceof PsiMethod) {
PsiMethod method = (PsiMethod)listOwner;
PsiClass aClass = method.getContainingClass();
if (aClass == null) return null;
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
return findAnnotationInHierarchy(methodSignature, annotationNames, method, null,
JavaPsiFacade.getInstance(method.getProject()).getResolveHelper());
}
if (listOwner instanceof PsiClass) {
return findAnnotationInHierarchy((PsiClass)listOwner, annotationNames, null);
}
if (listOwner instanceof PsiParameter) {
PsiParameter parameter = (PsiParameter)listOwner;
return doFindAnnotationInHierarchy(parameter, annotationNames, null);
}
return null;
ConcurrentFactoryMap<Set<String>, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
new CachedValueProvider<ConcurrentFactoryMap<Set<String>, PsiAnnotation>>() {
@Nullable
@Override
public Result<ConcurrentFactoryMap<Set<String>, PsiAnnotation>> compute() {
ConcurrentFactoryMap<Set<String>, PsiAnnotation> value = new ConcurrentFactoryMap<Set<String>, PsiAnnotation>() {
@Nullable
@Override
protected PsiAnnotation create(Set<String> annotationNames) {
if (listOwner instanceof PsiMethod) {
PsiMethod method = (PsiMethod)listOwner;
PsiClass aClass = method.getContainingClass();
if (aClass == null) return null;
HierarchicalMethodSignature methodSignature = method.getHierarchicalMethodSignature();
return findAnnotationInHierarchy(methodSignature, annotationNames, method, null,
JavaPsiFacade.getInstance(method.getProject()).getResolveHelper());
}
if (listOwner instanceof PsiClass) {
return findAnnotationInHierarchy((PsiClass)listOwner, annotationNames, null);
}
if (listOwner instanceof PsiParameter) {
PsiParameter parameter = (PsiParameter)listOwner;
return doFindAnnotationInHierarchy(parameter, annotationNames, null);
}
return null;
}
};
return Result.create(value, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
});
return map.get(annotationNames);
}
@Nullable
@@ -20,8 +20,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiConstantEvaluationHelperImpl;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.*;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
@@ -270,7 +269,7 @@ public class AnnotationUtilEx {
*
* @see com.intellij.codeInsight.AnnotationUtil#isAnnotated(com.intellij.psi.PsiModifierListOwner, java.lang.String, boolean)
*/
private static PsiAnnotation[] getAnnotations(@NotNull PsiModifierListOwner listOwner, boolean inHierarchy) {
private static PsiAnnotation[] getAnnotations(@NotNull final PsiModifierListOwner listOwner, final boolean inHierarchy) {
final PsiModifierList modifierList = listOwner.getModifierList();
if (modifierList == null) {
return PsiAnnotation.EMPTY_ARRAY;
@@ -278,6 +277,16 @@ public class AnnotationUtilEx {
if (!inHierarchy) {
return modifierList.getAnnotations();
}
return CachedValuesManager.getCachedValue(listOwner, new CachedValueProvider<PsiAnnotation[]>() {
@Nullable
@Override
public Result<PsiAnnotation[]> compute() {
return Result.create(getHierarchyAnnotations(listOwner, modifierList), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
});
}
private static PsiAnnotation[] getHierarchyAnnotations(PsiModifierListOwner listOwner, PsiModifierList modifierList) {
final Set<PsiAnnotation> all = new HashSet<PsiAnnotation>() {
public boolean add(PsiAnnotation o) {
// don't overwrite "higher level" annotations
@@ -317,5 +326,4 @@ public class AnnotationUtilEx {
}
return modifierList.getAnnotations();
}
}