de.plushnikov.intellij.lombok.util.PsiAnnotationUtil Maven / Gradle / Ivy
package de.plushnikov.intellij.lombok.util;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiArrayInitializerMemberValue;
import com.intellij.psi.PsiClassObjectAccessExpression;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiEnumConstant;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeElement;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.util.ClassUtil;
import com.intellij.util.StringBuilderSpinAllocator;
import lombok.handlers.TransformationsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Pattern;
/**
* @author peichhorn
* @author Plushnikov Michail
*/
public class PsiAnnotationUtil {
private static final String[] EMPTY_STRING_ARRAY = new String[0];
public static boolean isNotAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Class extends Annotation>... annotationTypes) {
return !isAnnotatedWith(psiModifierListOwner, annotationTypes);
}
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) {
final Collection annotationTypeNames = new HashSet();
for (Class> annotationType : annotationTypes) {
annotationTypeNames.add(annotationType.getName());
}
final PsiModifierList psiModifierList = psiModifierListOwner.getModifierList();
if (psiModifierList != null) {
for (PsiAnnotation psiAnnotation : psiModifierList.getApplicableAnnotations()) {
if (annotationTypeNames.contains(psiAnnotation.getQualifiedName())) {
return true;
}
}
}
return false;
}
public static boolean isAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Class extends Annotation> annotationType) {
final PsiModifierList psiModifierList = psiModifierListOwner.getModifierList();
if (psiModifierList != null) {
for (PsiAnnotation psiAnnotation : psiModifierList.getApplicableAnnotations()) {
if (annotationType.getName().equals(psiAnnotation.getQualifiedName())) {
return true;
}
}
}
return false;
}
public static boolean isAnnotatedWith(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Pattern annotationPattern) {
final PsiModifierList psiModifierList = psiModifierListOwner.getModifierList();
if (psiModifierList != null) {
for (PsiAnnotation psiAnnotation : psiModifierList.getApplicableAnnotations()) {
final String suspect = getSimpleNameOf(psiAnnotation);
if (annotationPattern.matcher(suspect).matches()) {
return true;
}
}
}
return false;
}
@NotNull
public static String getSimpleNameOf(@NotNull PsiAnnotation psiAnnotation) {
return ClassUtil.extractClassName(StringUtil.notNullize(psiAnnotation.getQualifiedName()));
}
@NotNull
public static List findAnnotations(@NotNull PsiModifierListOwner psiModifierListOwner, @NotNull final Pattern annotationPattern) {
final List annoations = new ArrayList();
final PsiModifierList psiModifierList = psiModifierListOwner.getModifierList();
if (psiModifierList != null) {
for (PsiAnnotation psiAnnotation : psiModifierList.getApplicableAnnotations()) {
final String name = getSimpleNameOf(psiAnnotation);
if (annotationPattern.matcher(name).matches()) {
annoations.add(psiAnnotation);
}
}
}
return annoations;
}
@Nullable
public static T getAnnotationValue(@NotNull PsiAnnotation psiAnnotation, Class asClass) {
return getAnnotationValue(psiAnnotation, "value", asClass);
}
@NotNull
public static Collection getAnnotationValues(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter, @NotNull Class asClass) {
Collection result = Collections.emptyList();
PsiAnnotationMemberValue attributeValue = psiAnnotation.findAttributeValue(parameter);
if (attributeValue instanceof PsiArrayInitializerMemberValue) {
final PsiAnnotationMemberValue[] memberValues = ((PsiArrayInitializerMemberValue) attributeValue).getInitializers();
result = new ArrayList(memberValues.length);
for (PsiAnnotationMemberValue memberValue : memberValues) {
T value = resolveElementValue(memberValue, asClass);
if (null != value) {
result.add(value);
}
}
} else if (null != attributeValue) {
T value = resolveElementValue(attributeValue, asClass);
if (null != value) {
result = Collections.singletonList(value);
}
}
return result;
}
@Nullable
public static T getAnnotationValue(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter, @NotNull Class asClass) {
T result = null;
PsiAnnotationMemberValue attributeValue = psiAnnotation.findAttributeValue(parameter);
if (null != attributeValue) {
result = resolveElementValue(attributeValue, asClass);
}
return result;
}
@Nullable
private static T resolveElementValue(@NotNull PsiElement psiElement, @NotNull Class asClass) {
T value = null;
if (psiElement instanceof PsiReferenceExpression) {
final PsiElement resolved = ((PsiReferenceExpression) psiElement).resolve();
if (resolved instanceof PsiEnumConstant) {
final PsiEnumConstant psiEnumConstant = (PsiEnumConstant) resolved;
//Enums are supported as VALUE-Strings only
if (asClass.isAssignableFrom(String.class)) {
value = (T) psiEnumConstant.getName();
}
} else if (resolved instanceof PsiVariable) {
final PsiVariable psiVariable = (PsiVariable) resolved;
Object elementValue = psiVariable.computeConstantValue();
if (null != elementValue && asClass.isAssignableFrom(elementValue.getClass())) {
value = (T) elementValue;
}
}
} else if (psiElement instanceof PsiLiteralExpression) {
Object elementValue = ((PsiLiteralExpression) psiElement).getValue();
if (null != elementValue && asClass.isAssignableFrom(elementValue.getClass())) {
value = (T) elementValue;
}
} else if (psiElement instanceof PsiClassObjectAccessExpression) {
PsiTypeElement elementValue = ((PsiClassObjectAccessExpression) psiElement).getOperand();
//Enums are supported as VALUE-Strings only
if (asClass.isAssignableFrom(PsiType.class)) {
value = (T) elementValue.getType();
}
}
return value;
}
@Nullable
public static T getDeclaredAnnotationValue(@NotNull PsiAnnotation psiAnnotation, @NotNull String parameter, @NotNull Class asClass) {
T value = null;
PsiAnnotationMemberValue attributeValue = psiAnnotation.findDeclaredAttributeValue(parameter);
if (null != attributeValue) {
value = resolveElementValue(attributeValue, asClass);
}
return value;
}
@NotNull
public static Collection collectAnnotationsToCopy(@NotNull PsiField psiField) {
Collection annotationsToCopy = new ArrayList();
PsiModifierList modifierList = psiField.getModifierList();
if (null != modifierList) {
for (PsiAnnotation psiAnnotation : modifierList.getAnnotations()) {
final String annotationName = getSimpleNameOf(psiAnnotation);
if (TransformationsUtil.NON_NULL_PATTERN.matcher(annotationName).matches()) {
annotationsToCopy.add(psiAnnotation.getQualifiedName());
}
}
}
return annotationsToCopy;
}
@NotNull
public static String buildAnnotationsString(@NotNull Collection annotationsToCopy) {
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
for (String annotationName : annotationsToCopy) {
builder.append('@').append(annotationName).append(' ');
}
return builder.toString();
} finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
}