sb.append("}");
return sb.toString();
}
private boolean doDeclareAnnotations(DeclareAnnotation decA, SourceTypeBinding sourceType, boolean reportProblems) {
ResolvedType rtx = factory.fromEclipse(sourceType);
if (!decA.matches(rtx)) {
return false;
}
if (!rtx.isExposedToWeaver()) {
return false;
}
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_ANNOTATIONS,
sourceType.sourceName);
// Get the annotation specified in the declare
UnresolvedType aspectType = decA.getAspect();
if (aspectType instanceof ReferenceType) {
ReferenceType rt = (ReferenceType) aspectType;
if (rt.isParameterizedType() || rt.isRawType()) {
aspectType = rt.getGenericType();
}
}
TypeBinding tb = factory.makeTypeBinding(aspectType);
// Hideousness follows:
// There are multiple situations to consider here and they relate to the
// combinations of
// where the annotation is coming from and where the annotation is going
// to be put:
//
// 1. Straight full build, all from source - the annotation is from a
// dec@type and
// is being put on some type. Both types are real SourceTypeBindings.
// WORKS
// 2. Incremental build, changing the affected type - the annotation is
// from a
// dec@type in a BinaryTypeBinding (so has to be accessed via bcel) and
// the
// affected type is a real SourceTypeBinding. Mostly works (pr128665)
// 3. ?
SourceTypeBinding stb = (SourceTypeBinding) tb;
Annotation[] toAdd = null;
long abits = 0;
AbstractMethodDeclaration methodDecl = null;
// Might have to retrieve the annotation through BCEL and construct an
// eclipse one for it.
if (stb instanceof BinaryTypeBinding) {
toAdd = retrieveAnnotationFromBinaryTypeBinding(decA, stb);
if (toAdd != null && toAdd.length > 0 && toAdd[0].resolvedType != null) {
abits = toAdd[0].resolvedType.getAnnotationTagBits();
}
} else if (stb != null) {
// much nicer, its a real SourceTypeBinding so we can stay in
// eclipse land
// if (decA.getAnnotationMethod() != null) {
char[] declareSelector = decA.getAnnotationMethod().toCharArray();
ReferenceBinding rb = stb;
String declaringAspectName = decA.getDeclaringType().getRawName();
while (rb != null && !new String(CharOperation.concatWith(rb.compoundName, '.')).equals(declaringAspectName)) {
rb = rb.superclass();
}
MethodBinding[] mbs = rb.getMethods(declareSelector);
ReferenceBinding declaringBinding = mbs[0].declaringClass;
if (declaringBinding instanceof ParameterizedTypeBinding) {
// Unwrap - this means we don't allow the type of the annotation to be parameterized, may need to revisit that
declaringBinding = ((ParameterizedTypeBinding) declaringBinding).type;
}
if (declaringBinding instanceof BinaryTypeBinding) {
toAdd = retrieveAnnotationFromBinaryTypeBinding(decA, declaringBinding);
if (toAdd != null && toAdd.length > 0 && toAdd[0].resolvedType != null) {
abits = toAdd[0].resolvedType.getAnnotationTagBits();
}
} else {
abits = mbs[0].getAnnotationTagBits(); // ensure resolved
TypeDeclaration typeDecl = ((SourceTypeBinding) declaringBinding).scope.referenceContext;
methodDecl = typeDecl.declarationOf(mbs[0]);
toAdd = methodDecl.annotations; // this is what to add
toAdd[0] = createAnnotationCopy(toAdd[0]);
if (toAdd[0].resolvedType != null) {
abits = toAdd[0].resolvedType.getAnnotationTagBits();
// }
}
}
}
// This happens if there is another error in the code - that should be reported separately
if (toAdd == null || toAdd[0] == null || toAdd[0].type == null) {
CompilationAndWeavingContext.leavingPhase(tok);
return false;
}
if (sourceType instanceof BinaryTypeBinding) {
// In this case we can't access the source type binding to add a new
// annotation, so let's put something
// on the weaver type temporarily
ResolvedType theTargetType = factory.fromEclipse(sourceType);
TypeBinding theAnnotationType = toAdd[0].resolvedType;
// The annotation type may be null if it could not be resolved (eg. the relevant import has not been added yet)
// In this case an error will be put out about the annotation but not if we crash here
if (theAnnotationType == null) {
return false;
}
String sig = new String(theAnnotationType.signature());
UnresolvedType bcelAnnotationType = UnresolvedType.forSignature(sig);
String name = bcelAnnotationType.getName();
if (theTargetType.hasAnnotation(bcelAnnotationType)) {
CompilationAndWeavingContext.leavingPhase(tok);
return false;
}
// FIXME asc tidy up this code that duplicates whats below!
// Simple checks on the bits
boolean giveupnow = false;
if (((abits & TagBits.AnnotationTargetMASK) != 0)) {
if (isAnnotationTargettingSomethingOtherThanAnnotationOrNormal(abits)) {
// error will have been already reported
giveupnow = true;
} else if ((sourceType.isAnnotationType() && (abits & TagBits.AnnotationForAnnotationType) == 0)
|| (!sourceType.isAnnotationType() && (abits & TagBits.AnnotationForType) == 0)) {
if (reportProblems) {
if (decA.isExactPattern()) {
factory.showMessage(IMessage.ERROR, WeaverMessages.format(
WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION, rtx.getName(), toAdd[0].type,
stringifyTargets(abits)), decA.getSourceLocation(), null);
}
// dont put out the lint - the weaving process will do
// that
// else {
// if (factory.getWorld().getLint().
// invalidTargetForAnnotation.isEnabled()) {
// factory.getWorld().getLint().invalidTargetForAnnotation
// .signal(new
// String[]{rtx.getName(),toAdd[0].type.toString(),
// stringifyTargets
// (abits)},decA.getSourceLocation(),null);
// }
// }
}
giveupnow = true;
}
}
if (giveupnow) {
CompilationAndWeavingContext.leavingPhase(tok);
return false;
}
theTargetType.addAnnotation(new BcelAnnotation(new FakeAnnotation(name, sig,
(abits & TagBits.AnnotationRuntimeRetention) != 0), factory.getWorld()));
CompilationAndWeavingContext.leavingPhase(tok);
return true;
}