blob: 6e5a522fadf09286716723d122ae4545ed64c1c2 [file] [log] [blame]
/*
* Copyright (c) 2010-2020 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*/
package org.eclipse.scout.sdk.core.model.ecj;
import static java.util.Collections.emptyList;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.CharLiteral;
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.Literal;
import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.Reference;
import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.StringConstant;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.VoidTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
import org.eclipse.scout.sdk.core.model.api.Flags;
import org.eclipse.scout.sdk.core.model.api.IMetaValue;
import org.eclipse.scout.sdk.core.model.api.ISourceRange;
import org.eclipse.scout.sdk.core.model.ecj.metavalue.MetaValueFactory;
import org.eclipse.scout.sdk.core.model.spi.AbstractJavaEnvironment;
import org.eclipse.scout.sdk.core.model.spi.AnnotatableSpi;
import org.eclipse.scout.sdk.core.model.spi.AnnotationElementSpi;
import org.eclipse.scout.sdk.core.model.spi.AnnotationSpi;
import org.eclipse.scout.sdk.core.model.spi.CompilationUnitSpi;
import org.eclipse.scout.sdk.core.model.spi.FieldSpi;
import org.eclipse.scout.sdk.core.model.spi.JavaElementSpi;
import org.eclipse.scout.sdk.core.model.spi.MemberSpi;
import org.eclipse.scout.sdk.core.model.spi.MethodParameterSpi;
import org.eclipse.scout.sdk.core.model.spi.MethodSpi;
import org.eclipse.scout.sdk.core.model.spi.TypeParameterSpi;
import org.eclipse.scout.sdk.core.model.spi.TypeSpi;
import org.eclipse.scout.sdk.core.util.SdkException;
public final class SpiWithEcjUtils {
private static final String DEPRECATED_ANNOTATION_FQN = Deprecated.class.getName();
private SpiWithEcjUtils() {
}
static List<TypeParameterSpi> createTypeParameters(AbstractMemberWithEcj<?> owner, TypeVariableBinding[] typeParams) {
if (typeParams == null || typeParams.length < 1) {
return emptyList();
}
List<TypeParameterSpi> result = new ArrayList<>(typeParams.length);
int index = 0;
JavaEnvironmentWithEcj env = (JavaEnvironmentWithEcj) owner.getJavaEnvironment();
for (TypeVariableBinding param : typeParams) {
result.add(env.createBindingTypeParameter(owner, param, index));
index++;
}
return result;
}
static TypeSpi bindingToInnerType(JavaEnvironmentWithEcj env, TypeBinding primaryTypeBinding, String innerTypes) {
if (primaryTypeBinding == null) {
return null;
}
TypeSpi result = bindingToType(env, primaryTypeBinding);
// it is an inner type: step into
StringTokenizer st = new StringTokenizer(innerTypes, "$", false);
while (st.hasMoreTokens()) {
String name = st.nextToken();
TypeSpi innerType = null;
for (TypeSpi t : result.getTypes()) {
if (t.getElementName().equals(name)) {
innerType = t;
break;
}
}
if (innerType == null) {
return null;
}
result = innerType;
}
return result;
}
static List<TypeSpi> bindingsToTypes(JavaEnvironmentWithEcj env, ReferenceBinding[] exceptions) {
if (exceptions == null || exceptions.length < 1) {
return emptyList();
}
List<TypeSpi> result = new ArrayList<>(exceptions.length);
for (ReferenceBinding r : exceptions) {
TypeSpi t = bindingToType(env, r);
if (t != null) {
result.add(t);
}
}
return result;
}
//public only for junit testing purposes
static TypeSpi bindingToType(JavaEnvironmentWithEcj env, TypeBinding b) {
return bindingToType(env, b, null);
}
static TypeSpi bindingToType(JavaEnvironmentWithEcj env, TypeBinding b, BindingTypeWithEcj declaringType) {
return bindingToType(env, b, declaringType, false);
}
static List<TypeParameterSpi> toTypeParameterSpi(TypeParameter[] typeParams, AbstractMemberWithEcj<?> method, JavaEnvironmentWithEcj env) {
if (typeParams == null || typeParams.length < 1) {
return emptyList();
}
List<TypeParameterSpi> result = new ArrayList<>(typeParams.length);
for (int i = 0; i < typeParams.length; i++) {
result.add(env.createDeclarationTypeParameter(method, typeParams[i], i));
}
return result;
}
static ISourceRange getJavaDocSource(ASTNode doc, TypeSpi declaringType, JavaEnvironmentWithEcj env) {
if (doc == null) {
return null;
}
CompilationUnitSpi cu = declaringType.getCompilationUnit();
return env.getSource(cu, doc.sourceStart, doc.sourceEnd);
}
static MethodSpi findNewMethodIn(MethodSpi m) {
AbstractJavaElementWithEcj<?> declaringType = (AbstractJavaElementWithEcj<?>) m.getDeclaringType();
TypeSpi newType = (TypeSpi) declaringType.internalFindNewElement();
if (newType != null) {
String oldSig = m.wrap().identifier();
for (MethodSpi newM : newType.getMethods()) {
if (oldSig.equals(newM.wrap().identifier())) {
return newM;
}
}
}
return null;
}
static TypeSpi bindingToType(JavaEnvironmentWithEcj env, TypeBinding b, BindingTypeWithEcj declaringType, boolean isWildCard) {
if (b instanceof VoidTypeBinding) {
return env.createVoidType();
}
if (b instanceof WildcardBinding) {
WildcardBinding wb = (WildcardBinding) b;
TypeBinding allBounds = wb.allBounds();
if (allBounds == null) {
// wildcard only binding: <?>
return env.createWildcardOnlyType();
}
return bindingToType(env, allBounds, declaringType, true);
}
if (b instanceof ReferenceBinding) {
// reference to complex type
return env.createBindingType((ReferenceBinding) b, declaringType, isWildCard);
}
if (b instanceof BaseTypeBinding) {
return env.createBindingBaseType((BaseTypeBinding) b);
}
if (b instanceof ArrayBinding) {
return env.createBindingArrayType((ArrayBinding) b, isWildCard);
}
if (b == null) {
throw new IllegalArgumentException("TypeBinding cannot be null");
}
throw new IllegalStateException("Unsupported binding type: " + b.getClass().getName());
}
@SuppressWarnings("squid:AssignmentInSubExpressionCheck")
static int getTypeFlags(int modifiers, AllocationExpression allocation, boolean hasDeprecatedAnnotation) {
int currentModifiers = modifiers;
boolean isEnumInit = allocation != null && allocation.enumConstant != null;
if (isEnumInit) {
currentModifiers |= ClassFileConstants.AccEnum;
}
boolean deprecated = hasDeprecatedAnnotation || (currentModifiers & ClassFileConstants.AccDeprecated) != 0;
currentModifiers &= ExtraCompilerModifiers.AccJustFlag;
if (deprecated) {
currentModifiers |= ClassFileConstants.AccDeprecated;
}
return currentModifiers & ~Flags.AccSuper;
}
static int getMethodFlags(int modifiers, boolean isVarargs, boolean isDeprecated) {
int currentModifiers = modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDefaultMethod);
if (isVarargs) {
currentModifiers |= ClassFileConstants.AccVarargs;
}
if (isDeprecated) {
currentModifiers |= ClassFileConstants.AccDeprecated;
}
return currentModifiers;
}
/**
* @param owner
* The owner whose declaring type should be returned.
* @return the declaring type for this element. For {@link TypeSpi} this is the {@link TypeSpi} itself and NOT the
* enclosing type {@link TypeSpi#getDeclaringType()}
*/
static TypeSpi declaringTypeOf(JavaElementSpi owner) {
if (owner instanceof TypeSpi) {
return (TypeSpi) owner;
}
if (owner instanceof MemberSpi) {
return ((MemberSpi) owner).getDeclaringType();
}
if (owner instanceof TypeParameterSpi) {
return declaringTypeOf(((TypeParameterSpi) owner).getDeclaringMember());
}
if (owner instanceof MethodParameterSpi) {
return ((MethodParameterSpi) owner).getDeclaringMethod().getDeclaringType();
}
if (owner instanceof AnnotationSpi) {
return declaringTypeOf(((AnnotationSpi) owner).getOwner());
}
if (owner instanceof AnnotationElementSpi) {
return declaringTypeOf(((AnnotationElementSpi) owner).getDeclaringAnnotation());
}
throw new SdkException("Unknown owner type: {}", owner.getClass().getName());
}
static Scope memberScopeOf(JavaElementSpi owner) {
if (owner instanceof TypeSpi) {
return classScopeOf(owner);
}
if (owner instanceof MethodSpi) {
return methodScopeOf(owner);
}
if (owner instanceof TypeParameterSpi) {
return memberScopeOf(((TypeParameterSpi) owner).getDeclaringMember());
}
if (owner instanceof MethodParameterSpi) {
return methodScopeOf(((MethodParameterSpi) owner).getDeclaringMethod());
}
if (owner instanceof AnnotationSpi) {
return memberScopeOf(((AnnotationSpi) owner).getOwner());
}
throw new SdkException("Unknown owner type: {}", owner.getClass().getName());
}
static ClassScope classScopeOf(JavaElementSpi owner) {
TypeSpi t = declaringTypeOf(owner);
if (t instanceof DeclarationTypeWithEcj) {
return ((DeclarationTypeWithEcj) t).getInternalTypeDeclaration().scope;
}
if (t instanceof AbstractTypeWithEcj) {
Binding b = ((AbstractTypeWithEcj) t).getInternalBinding();
if (b instanceof SourceTypeBinding) {
return ((SourceTypeBinding) b).scope;
}
}
return null;
}
static MethodScope methodScopeOf(JavaElementSpi owner) {
if (owner instanceof BindingMethodWithEcj) {
AbstractMethodDeclaration d = sourceMethodOf((BindingMethodWithEcj) owner);
if (d != null) {
return d.scope;
}
}
else if (owner instanceof DeclarationMethodWithEcj) {
return ((DeclarationMethodWithEcj) owner).getInternalMethodDeclaration().scope;
}
else if (owner instanceof TypeParameterSpi) {
return methodScopeOf(((TypeParameterSpi) owner).getDeclaringMember());
}
else if (owner instanceof MethodParameterSpi) {
return methodScopeOf(((MethodParameterSpi) owner).getDeclaringMethod());
}
else if (owner instanceof AnnotationSpi) {
return methodScopeOf(((AnnotationSpi) owner).getOwner());
}
return null;
}
static AbstractMethodDeclaration sourceMethodOf(BindingMethodWithEcj b) {
return sourceMethodOf(b.getInternalBinding());
}
static AbstractMethodDeclaration sourceMethodOf(MethodBinding b) {
return nvl(b.original(), b).sourceMethod();
}
static <T> T nvl(T a, T b) {
if (a == null) {
return b;
}
return a;
}
static Annotation findAnnotationDeclaration(AnnotationSpi annotationSpi) {
Annotation[] declaredAnnotations = null;
AnnotatableSpi owner = annotationSpi.getOwner();
if (owner instanceof BindingTypeWithEcj) {
ReferenceBinding b = ((BindingTypeWithEcj) owner).getInternalBinding();
b = nvl(b.actualType(), b);
if (b instanceof SourceTypeBinding) {
declaredAnnotations = ((SourceTypeBinding) b).scope.referenceContext.annotations;
}
}
else if (owner instanceof BindingMethodWithEcj) {
MethodBinding b = ((BindingMethodWithEcj) owner).getInternalBinding();
AbstractMethodDeclaration sourceMethod = sourceMethodOf(b);
if (sourceMethod != null) {
declaredAnnotations = sourceMethod.annotations;
}
}
else if (owner instanceof BindingFieldWithEcj) {
FieldBinding b = ((BindingFieldWithEcj) owner).getInternalBinding();
b = nvl(b.original(), b);
if (b.sourceField() != null) {
declaredAnnotations = b.sourceField().annotations;
}
}
else if (owner instanceof BindingTypeParameterWithEcj) {
TypeVariableBinding b = ((BindingTypeParameterWithEcj) owner).getInternalBinding();
b = (TypeVariableBinding) nvl(b.original(), b);
if (b.declaringElement instanceof SourceTypeBinding) {
declaredAnnotations = ((SourceTypeBinding) b.declaringElement).scope.referenceContext.annotations;
}
}
if (declaredAnnotations != null && annotationSpi instanceof BindingAnnotationWithEcj) {
AnnotationBinding binding = ((BindingAnnotationWithEcj) annotationSpi).getInternalBinding();
//fast visit
for (Annotation decl : declaredAnnotations) {
if (decl.getCompilerAnnotation() == binding) {
return decl;
}
}
//full visit
FindAnnotationVisitor v = new FindAnnotationVisitor(binding);
for (Annotation decl : declaredAnnotations) {
decl.traverse(v, (BlockScope) null);
if (v.getResult() != null) {
break;
}
}
return v.getResult();
}
return null;
}
static MemberValuePair findAnnotationValueDeclaration(BindingAnnotationElementWithEcj a) {
Annotation annotationDeclaration = findAnnotationDeclaration(a.getDeclaringAnnotation());
if (annotationDeclaration == null) {
return null;
}
FindMemberValuePairVisitor v = new FindMemberValuePairVisitor(a.getInternalBinding());
annotationDeclaration.traverse(v, (BlockScope) null);
return v.getResult();
}
static List<BindingAnnotationWithEcj> createBindingAnnotations(AnnotatableSpi owner, Binding binding) {
Object lock = ((AbstractJavaEnvironment) owner.getJavaEnvironment()).lock();
AnnotationBinding[] annotations;
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (lock) {
annotations = binding.getAnnotations();
}
return createBindingAnnotations(owner, annotations);
}
static List<BindingAnnotationWithEcj> createBindingAnnotations(AnnotatableSpi owner, AnnotationBinding[] annotationBindings) {
if (annotationBindings == null || annotationBindings.length < 1) {
return emptyList();
}
List<BindingAnnotationWithEcj> result = new ArrayList<>(annotationBindings.length);
JavaEnvironmentWithEcj env = (JavaEnvironmentWithEcj) owner.getJavaEnvironment();
for (AnnotationBinding annotation : annotationBindings) {
if (annotation != null) {
result.add(env.createBindingAnnotation(owner, annotation));
}
}
return result;
}
static List<DeclarationAnnotationWithEcj> createDeclarationAnnotations(JavaEnvironmentWithEcj env, AnnotatableSpi owner, Annotation[] annotations) {
if (annotations == null || annotations.length < 1) {
return emptyList();
}
List<DeclarationAnnotationWithEcj> result = new ArrayList<>(annotations.length);
for (Annotation annotation : annotations) {
result.add(env.createDeclarationAnnotation(owner, annotation));
}
return result;
}
/**
* transform this {@link Expression} to a compiled binding value of type {@link Constant}, {@link TypeBinding},
* {@link FieldBinding}, {@link AnnotationBinding}
*/
@SuppressWarnings("pmd:NPathComplexity")
static Object compileExpression(Expression expression, ClassScope scopeForTypeLookup, JavaEnvironmentWithEcj env) {
if (expression == null) {
return null;
}
if (expression instanceof NullLiteral) {
return expression;
}
if (expression instanceof Literal) {
if (expression.constant == null) {
((Literal) expression).computeConstant();
}
return expression.constant;
}
if (expression instanceof ArrayInitializer) {
Expression[] array = ((ArrayInitializer) expression).expressions;
if (array != null) {
int n = array.length;
Object[] values = new Object[n];
for (int i = 0; i < n; i++) {
values[i] = compileExpression(array[i], scopeForTypeLookup, env);
}
return values;
}
return DefaultProblem.EMPTY_VALUES;
}
if (expression instanceof UnaryExpression) {
UnaryExpression ue = (UnaryExpression) expression;
Expression inner = ue.expression;
if (inner instanceof Literal) {
int id = getTypeIdForLiteral((Literal) inner);
if (id > 0) {
Object candidate = compileExpression(inner, scopeForTypeLookup, env);
if (candidate instanceof Constant) {
return Constant.computeConstantOperation((Constant) candidate, id, ((expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT));
}
}
}
}
else if (expression instanceof ClassLiteralAccess) {
TypeBinding val = ((ClassLiteralAccess) expression).targetType;
if (val == null) {
TypeReference type = ((ClassLiteralAccess) expression).type;
if (type != null) {
if (type.resolvedType == null && scopeForTypeLookup != null) {
synchronized (env.lock()) {
type.resolveType(scopeForTypeLookup);
}
}
val = type.resolvedType;
}
}
return val;
}
if (expression instanceof Annotation) {
Annotation annotation = (Annotation) expression;
AnnotationBinding compilerAnnotation = annotation.getCompilerAnnotation();
if (compilerAnnotation == null) {
synchronized (env.lock()) {
annotation.resolveType(scopeForTypeLookup.referenceContext.staticInitializerScope);
}
}
return annotation.getCompilerAnnotation();
}
if (expression instanceof Reference) {
FieldBinding fieldBinding = null;
if (expression instanceof NameReference) {
Binding binding = ((NameReference) expression).binding;
if (binding != null && binding.kind() == Binding.FIELD) {
fieldBinding = (FieldBinding) binding;
}
else if (expression instanceof QualifiedNameReference) {
char[][] tokens = ((QualifiedNameReference) expression).tokens;
TypeBinding baseType = scopeForTypeLookup.getType(tokens, tokens.length - 1);
if (baseType instanceof ReferenceBinding) {
ReferenceBinding ref = (ReferenceBinding) baseType;
FieldBinding field = ref.getField(tokens[tokens.length - 1], true);
if (field != null) {
return field;
}
}
String str = CharOperation.toString(tokens);
return StringConstant.fromValue(str);
}
}
else {
fieldBinding = ((Reference) expression).fieldBinding();
}
if (fieldBinding != null) {
return fieldBinding;
}
}
return ElementValuePair.getValue(expression);
}
/**
* transform a raw annotation value from {@link ElementValuePair#getValue(Expression)} or compiled expression value
* from {@link #compileExpression(Expression, ClassScope, JavaEnvironmentWithEcj)} to a {@link IMetaValue} that can be
* wrapped inside a {@link AnnotationElementSpi}
*/
@SuppressWarnings("pmd:NPathComplexity")
static IMetaValue resolveCompiledValue(JavaEnvironmentWithEcj env, AnnotatableSpi owner, Object compiledValue) {
if (compiledValue == null || Constant.NotAConstant.equals(compiledValue)) {
return null;
}
if (compiledValue instanceof NullLiteral) {
return MetaValueFactory.createNull();
}
if (compiledValue instanceof Constant) {
// primitives and string
return MetaValueFactory.createFromConstant((Constant) compiledValue);
}
if (compiledValue instanceof TypeBinding) {
// type
return MetaValueFactory.createFromType(bindingToType(env, (TypeBinding) compiledValue));
}
if (compiledValue instanceof FieldBinding) {
// enum constants
FieldBinding fb = (FieldBinding) compiledValue;
TypeSpi type = bindingToType(env, fb.declaringClass);
String name = new String(fb.name);
for (FieldSpi f : type.getFields()) {
if (f.getElementName().equals(name)) {
return MetaValueFactory.createFromEnum(f);
}
}
return MetaValueFactory.createUnknown("ENUM " + fb.declaringClass.debugName() + '#' + name);
}
if (compiledValue instanceof AnnotationBinding) {
// annotation binding
AnnotationBinding a = (AnnotationBinding) compiledValue;
return MetaValueFactory.createFromAnnotation(env.createBindingAnnotation(owner, a));
}
if (compiledValue.getClass().isArray()) {
// arrays
int n = Array.getLength(compiledValue);
IMetaValue[] metaArray = new IMetaValue[n];
if (n > 0) {
for (int i = 0; i < n; i++) {
metaArray[i] = resolveCompiledValue(env, owner, Array.get(compiledValue, i));
}
}
return MetaValueFactory.createArray(metaArray);
}
return MetaValueFactory.createUnknown(compiledValue);
}
static int getTypeIdForLiteral(Literal l) {
if (l instanceof LongLiteral) {
return TypeIds.T_long;
}
if (l instanceof IntLiteral) {
return TypeIds.T_int;
}
if (l instanceof FloatLiteral) {
return TypeIds.T_float;
}
if (l instanceof DoubleLiteral) {
return TypeIds.T_double;
}
if (l instanceof CharLiteral) {
return TypeIds.T_char;
}
return -1;
}
static boolean hasDeprecatedAnnotation(Collection<? extends AnnotationSpi> annotations) {
if (annotations == null || annotations.isEmpty()) {
return false;
}
for (AnnotationSpi annotation : annotations) {
if (annotation != null && DEPRECATED_ANNOTATION_FQN.equals(annotation.getType().getName())) {
return true;
}
}
return false;
}
private static final class FindAnnotationVisitor extends ASTVisitor {
private final AnnotationBinding m_binding;
private Annotation m_result;
private FindAnnotationVisitor(AnnotationBinding binding) {
m_binding = binding;
}
public Annotation getResult() {
return m_result;
}
@Override
public boolean visit(MarkerAnnotation annotation, BlockScope scope) {
return internalVisit(annotation);
}
@Override
public boolean visit(NormalAnnotation annotation, BlockScope scope) {
return internalVisit(annotation);
}
@Override
public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
return internalVisit(annotation);
}
private boolean internalVisit(Annotation annotation) {
if (annotation.getCompilerAnnotation() == m_binding) {
m_result = annotation;
}
return m_result == null;
}
}
private static final class FindMemberValuePairVisitor extends ASTVisitor {
private final ElementValuePair m_binding;
private MemberValuePair m_result;
private FindMemberValuePairVisitor(ElementValuePair binding) {
m_binding = binding;
}
public MemberValuePair getResult() {
return m_result;
}
@Override
public boolean visit(MemberValuePair pair, BlockScope scope0) {
if (pair.compilerElementPair == m_binding) {
m_result = pair;
}
return m_result == null;
}
}
}