optimize check for a specific annotation type to avoid collecting all those annotation types

This commit is contained in:
Martin Lippert
2024-05-14 12:58:32 +02:00
parent 349f6c14ab
commit 92eeec8e65
4 changed files with 55 additions and 63 deletions

View File

@@ -14,7 +14,6 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.core.dom.Annotation;
@@ -43,11 +42,6 @@ public abstract class AnnotationHierarchies {
// due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=571247
private static final Object lock = new Object();
protected static boolean ignoreAnnotation(String fqname) {
return fqname.startsWith("java."); //mostly intended to capture java.lang.annotation.* types. But really it should be
//safe to ignore any type defined by the JRE since it can't possibly be inheriting from a spring annotation.
};
public static Collection<ITypeBinding> getDirectSuperAnnotations(ITypeBinding typeBinding) {
synchronized(lock) {
try {
@@ -73,37 +67,35 @@ public abstract class AnnotationHierarchies {
return ImmutableList.of();
}
}
public static Set<String> getTransitiveSuperAnnotations(ITypeBinding typeBinding) {
synchronized(lock) {
Set<String> seen = new HashSet<>();
findTransitiveSupers(typeBinding, seen).collect(Collectors.toList());
return seen;
}
}
private static Stream<ITypeBinding> findTransitiveSupers(ITypeBinding typeBinding, Set<String> seen) {
synchronized(lock) {
if (typeBinding != null) {
String qname = typeBinding.getQualifiedName();
if (seen.add(qname)) {
return Stream.concat(
Stream.of(typeBinding),
getDirectSuperAnnotations(typeBinding).stream().flatMap(superBinding -> findTransitiveSupers(superBinding, seen))
);
}
}
return Stream.empty();
}
}
public static boolean isSubtypeOf(Annotation annotation, String fqAnnotationTypeName) {
synchronized(lock) {
ITypeBinding annotationType = annotation.resolveTypeBinding();
if (annotationType!=null) {
return findTransitiveSupers(annotationType, new HashSet<>())
.anyMatch(superType -> superType.getQualifiedName().equals(fqAnnotationTypeName));
return hasTransitiveSuperAnnotationType(annotationType, fqAnnotationTypeName);
}
}
public static boolean hasTransitiveSuperAnnotationType(ITypeBinding typeBinding, String annotationType) {
synchronized(lock) {
if (typeBinding != null && annotationType != null) {
String qname = typeBinding.getQualifiedName();
// log.info("CHECK ANNOTATION TYPE: " + qname + " / " + annotationType);
if (annotationType.equals(qname)) {
return true;
}
else {
Collection<ITypeBinding> directSuperAnnotations = getDirectSuperAnnotations(typeBinding);
for (ITypeBinding superAnnotationBinding : directSuperAnnotations) {
if (hasTransitiveSuperAnnotationType(superAnnotationBinding, annotationType)) {
return true;
}
}
}
}
return false;
}
}
@@ -151,13 +143,11 @@ public abstract class AnnotationHierarchies {
}
}
public static Stream<IAnnotationBinding> findTransitiveSuperAnnotationBindings(
IAnnotationBinding annotationBinding) {
public static Stream<IAnnotationBinding> findTransitiveSuperAnnotationBindings( IAnnotationBinding annotationBinding) {
return internalFindTransitiveSuperAnnotationBindings(annotationBinding, new HashSet<>());
}
public static Stream<IAnnotationBinding> internalFindTransitiveSuperAnnotationBindings(
IAnnotationBinding annotationBinding, Set<String> seen) {
public static Stream<IAnnotationBinding> internalFindTransitiveSuperAnnotationBindings(IAnnotationBinding annotationBinding, Set<String> seen) {
synchronized (lock) {
if (annotationBinding.getAnnotationType() != null) {
if (seen.add(annotationBinding.getAnnotationType().getQualifiedName())) {
@@ -169,6 +159,25 @@ public abstract class AnnotationHierarchies {
return Stream.empty();
}
}
protected static boolean ignoreAnnotation(String fqname) {
return fqname.startsWith("java."); //mostly intended to capture java.lang.annotation.* types. But really it should be
//safe to ignore any type defined by the JRE since it can't possibly be inheriting from a spring annotation.
}
private static Stream<ITypeBinding> findTransitiveSupers(ITypeBinding typeBinding, Set<String> seen) {
synchronized(lock) {
if (typeBinding != null) {
String qname = typeBinding.getQualifiedName();
if (seen.add(qname)) {
return Stream.concat(
Stream.of(typeBinding),
getDirectSuperAnnotations(typeBinding).stream().flatMap(superBinding -> findTransitiveSupers(superBinding, seen))
);
}
}
return Stream.empty();
}
}
}

View File

@@ -12,7 +12,6 @@ package org.springframework.ide.vscode.boot.java.data.jpa.queries;
import java.net.URI;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
@@ -43,8 +42,7 @@ public class QueryJdtAstReconciler implements JdtAstReconciler {
@Override
public boolean visit(NormalAnnotation node) {
Set<String> allAnnotations = AnnotationHierarchies.getTransitiveSuperAnnotations(node.resolveTypeBinding());
if (!allAnnotations.contains(Annotations.DATA_QUERY)) {
if (!AnnotationHierarchies.hasTransitiveSuperAnnotationType(node.resolveTypeBinding(), Annotations.DATA_QUERY)) {
return false;
}
@@ -88,10 +86,10 @@ public class QueryJdtAstReconciler implements JdtAstReconciler {
@Override
public boolean visit(SingleMemberAnnotation node) {
Set<String> allAnnotations = AnnotationHierarchies.getTransitiveSuperAnnotations(node.resolveTypeBinding());
if (!allAnnotations.contains(Annotations.DATA_QUERY)) {
if (!AnnotationHierarchies.hasTransitiveSuperAnnotationType(node.resolveTypeBinding(), Annotations.DATA_QUERY)) {
return false;
}
reconcileExpression(getQueryReconciler(project), node.getValue(), problemCollector);
return false;
}

View File

@@ -14,7 +14,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.dom.ASTNode;
@@ -183,7 +182,7 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
for (Object modifier : modifiers) {
if (modifier instanceof Annotation) {
ITypeBinding typeBinding = ((Annotation) modifier).resolveTypeBinding();
if (isComponentAnnotation(typeBinding)) {
if (AnnotationHierarchies.hasTransitiveSuperAnnotationType(typeBinding, Annotations.COMPONENT)) {
return true;
}
}
@@ -191,15 +190,4 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
return false;
}
private boolean isComponentAnnotation(ITypeBinding type) {
Set<String> transitiveSuperAnnotations = AnnotationHierarchies.getTransitiveSuperAnnotations(type);
for (String annotationType : transitiveSuperAnnotations) {
if (Annotations.COMPONENT.equals(annotationType)) {
return true;
}
}
return false;
}
}

View File

@@ -12,7 +12,6 @@ package org.springframework.ide.vscode.boot.java.reconcilers;
import java.net.URI;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.Expression;
@@ -50,7 +49,7 @@ public class AnnotationParamReconciler implements AnnotationReconciler {
if (node instanceof SingleMemberAnnotation) {
visitSingleMemberAnnotation((SingleMemberAnnotation) node, typeBinding, problemCollector);
} else if (node instanceof NormalAnnotation) {
visitNornalAnnotation((NormalAnnotation) node, typeBinding, problemCollector);
visitNormalAnnotation((NormalAnnotation) node, typeBinding, problemCollector);
}
}
@@ -59,8 +58,7 @@ public class AnnotationParamReconciler implements AnnotationReconciler {
return;
}
Set<String> allAnnotations = AnnotationHierarchies.getTransitiveSuperAnnotations(typeBinding);
if (!allAnnotations.contains(this.annotationType)) {
if (!AnnotationHierarchies.hasTransitiveSuperAnnotationType(typeBinding, this.annotationType)) {
return;
}
@@ -71,13 +69,12 @@ public class AnnotationParamReconciler implements AnnotationReconciler {
}
}
protected void visitNornalAnnotation(NormalAnnotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
protected void visitNormalAnnotation(NormalAnnotation node, ITypeBinding typeBinding, IProblemCollector problemCollector) {
if (paramName == null) {
return;
}
Set<String> allAnnotations = AnnotationHierarchies.getTransitiveSuperAnnotations(typeBinding);
if (!allAnnotations.contains(this.annotationType)) {
if (!AnnotationHierarchies.hasTransitiveSuperAnnotationType(typeBinding, this.annotationType)) {
return;
}