package de.plushnikov.intellij.plugin.util;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiAnnotationOwner;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.regex.Pattern;
public class PsiAnnotationSearchUtil {
private static final Key<String> LOMBOK_ANNOTATION_FQN_KEY = Key.create("LOMBOK_ANNOTATION_FQN");
@Nullable
public static PsiAnnotation findAnnotation(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Class<? extends Annotation> annotationType) {
return findAnnotationQuick(psiModifierListOwner.getModifierList(), annotationType.getName());
}
@Nullable
public static PsiAnnotation findAnnotation(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Class<? extends Annotation>... annotationTypes) {
final String[] qualifiedNames = new String[annotationTypes.length];
for (int i = 0; i < annotationTypes.length; i++) {
qualifiedNames[i] = annotationTypes[i].getName();
}
return findAnnotationQuick(psiModifierListOwner.getModifierList(), qualifiedNames);
}
@Nullable
private static PsiAnnotation findAnnotationQuick(@Nullable PsiAnnotationOwner annotationOwner, @NotNull String... qualifiedNames) {
if (annotationOwner == null || qualifiedNames.length == 0) {
return null;
}
PsiAnnotation[] annotations = annotationOwner.getAnnotations();
if (annotations.length == 0) {
return null;
}
final String[] shortNames = new String[qualifiedNames.length];
for (int i = 0; i < qualifiedNames.length; i++) {
shortNames[i] = StringUtil.getShortName(qualifiedNames[i]);
}
for (PsiAnnotation annotation : annotations) {
PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement();
if (referenceElement != null && ArrayUtil.find(shortNames, referenceElement.getReferenceName()) > -1) {
String annotationQualifiedName = annotation.getCopyableUserData(LOMBOK_ANNOTATION_FQN_KEY);
if (null == annotationQualifiedName) {
annotationQualifiedName = annotation.getQualifiedName();
if (null != annotationQualifiedName && annotationQualifiedName.indexOf('.') > -1) {
annotation.putCopyableUserData(LOMBOK_ANNOTATION_FQN_KEY, annotationQualifiedName);
}
}
if (ArrayUtil.find(qualifiedNames, annotationQualifiedName) > -1) {
return annotation;
}
}
}
return null;
}
public static boolean isAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Class<? extends Annotation> annotationType) {
return null != findAnnotation(psiModifierListOwner, annotationType);
}
public static boolean isNotAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Class<? extends Annotation> annotationType) {
return !isAnnotatedWith(psiModifierListOwner, annotationType);
}
public static boolean isAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Class<? extends Annotation>... annotationTypes) {
return null != findAnnotation(psiModifierListOwner, annotationTypes);
}
public static boolean isNotAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Class<? extends Annotation>... annotationTypes) {
return !isAnnotatedWith(psiModifierListOwner, annotationTypes);
}
public static boolean isAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Pattern annotationPattern) {
final PsiModifierList psiModifierList = psiModifierListOwner.getModifierList();
if (psiModifierList != null) {
for (PsiAnnotation psiAnnotation : psiModifierList.getAnnotations()) {
final String suspect = getSimpleNameOf(psiAnnotation);
if (annotationPattern.matcher(suspect).matches()) {
return true;
}
}
}
return false;
}
@NotNull
public static String getSimpleNameOf(@NotNull PsiAnnotation psiAnnotation) {
PsiJavaCodeReferenceElement referenceElement = psiAnnotation.getNameReferenceElement();
return StringUtil.notNullize(null == referenceElement ? null : referenceElement.getReferenceName());
}
public static boolean checkAnnotationsSimpleNameExistsIn(@NotNull PsiModifierListOwner modifierListOwner, @NotNull Collection<String> annotationNames) {
final PsiModifierList modifierList = modifierListOwner.getModifierList();
if (null != modifierList) {
for (PsiAnnotation psiAnnotation : modifierList.getAnnotations()) {
final String simpleName = getSimpleNameOf(psiAnnotation);
if (annotationNames.contains(simpleName)) {
return true;
}
}
}
return false;
}
}