This includes a change in shadows in Parser class: protected void consumeDeclareAnnotation(char kind) { concatNodeLists(); ASTNode tokens = popPseudoTokens(";"); int annotationCount = this.expressionLengthPtr+1; Annotation[] annotations = new Annotation[annotationCount]; int count = 0; int length; while (this.expressionLengthPtr>0 && (length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { System.arraycopy( this.expressionStack, (this.expressionPtr -= length) + 1, annotations = new Annotation[length], count++, length); } // int length; // Annotation[] annotations = new Annotation[1]; // there should only ever be one for us... // if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) { // System.arraycopy( // this.expressionStack, // (this.expressionPtr -= length) + 1, // annotations = new Annotation[length], // 0, // length); // } MethodDeclaration declareDecl = declarationFactory.createDeclareAnnotationDeclaration(this.compilationUnit.compilationResult,tokens,annotations,this,kind); pushOnAstStack(declareDecl); } It touches so much code though and requires a change to serialized form.bug356694
@@ -25,22 +25,31 @@ import org.aspectj.weaver.patterns.DeclareAnnotation; | |||
public class DeclareAnnotationDeclaration extends DeclareDeclaration { | |||
private Annotation annotation; | |||
// private Annotation[] annotation; | |||
private boolean isRemover = false; | |||
public DeclareAnnotationDeclaration(CompilationResult result, DeclareAnnotation symbolicDeclare, Annotation annotation) { | |||
public DeclareAnnotationDeclaration(CompilationResult result, DeclareAnnotation symbolicDeclare, Annotation[] annotations) { | |||
super(result, symbolicDeclare); | |||
this.annotation = annotation; | |||
// this.annotations = annotations; | |||
addAnnotation(annotation); | |||
for (int a=0;a<annotations.length;a++) { | |||
addAnnotation(annotations[a]); | |||
} | |||
if (symbolicDeclare == null) { | |||
return; // there is an error that will already be getting reported (e.g. incorrect pattern on decaf/decac) | |||
} | |||
this.isRemover = symbolicDeclare.isRemover(); | |||
symbolicDeclare.setAnnotationString(annotation.toString()); | |||
symbolicDeclare.setAnnotationLocation(annotation.sourceStart, annotation.sourceEnd); | |||
StringBuilder sb = new StringBuilder(); | |||
for (int a=0;a<annotations.length;a++) { | |||
if (a>0) { | |||
sb.append(" "); | |||
} | |||
sb.append(annotations[a].toString()); | |||
} | |||
symbolicDeclare.setAnnotationString(sb.toString()); | |||
symbolicDeclare.setAnnotationLocation(annotations[0].sourceStart, annotations[annotations.length-1].sourceEnd); | |||
} | |||
public void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo flowInfo) { | |||
super.analyseCode(classScope, initializationContext, flowInfo); | |||
@@ -49,35 +58,41 @@ public class DeclareAnnotationDeclaration extends DeclareDeclaration { | |||
classScope.problemReporter().signalError(this.sourceStart(), this.sourceEnd, | |||
"Annotation removal only supported for declare @field (compiler limitation)"); | |||
} | |||
else if (isRemover && !(annotation instanceof MarkerAnnotation)) { | |||
classScope.problemReporter().signalError(this.sourceStart(), this.sourceEnd, | |||
"Annotation removal does not allow values to be specified for the annotation (compiler limitation)"); | |||
else if (isRemover) { // && !(annotation instanceof MarkerAnnotation)) { | |||
for (int a=0;a<annotations.length;a++) { | |||
if (!(annotations[a] instanceof MarkerAnnotation)) { | |||
classScope.problemReporter().signalError(this.sourceStart(), this.sourceEnd, | |||
"Annotation removal does not allow values to be specified for the annotation (compiler limitation)"); | |||
} | |||
} | |||
} | |||
} | |||
long bits = annotation.resolvedType.getAnnotationTagBits(); | |||
if ((bits & TagBits.AnnotationTarget) != 0) { | |||
// The annotation is stored against a method. For declare @type we need to | |||
// confirm the annotation targets the right types. Earlier checking will | |||
// have not found this problem because an annotation for target METHOD will | |||
// not be reported on as we *do* store it against a method in this case | |||
DeclareAnnotation.Kind k = ((DeclareAnnotation) declareDecl).getKind(); | |||
if (k.equals(DeclareAnnotation.AT_TYPE)) { | |||
if ((bits & TagBits.AnnotationForMethod) != 0) { | |||
classScope.problemReporter().disallowedTargetForAnnotation(annotation); | |||
for (int a=0;a<annotations.length;a++) { | |||
long bits = annotations[a].resolvedType.getAnnotationTagBits(); | |||
if ((bits & TagBits.AnnotationTarget) != 0) { | |||
// The annotation is stored against a method. For declare @type we need to | |||
// confirm the annotation targets the right types. Earlier checking will | |||
// have not found this problem because an annotation for target METHOD will | |||
// not be reported on as we *do* store it against a method in this case | |||
DeclareAnnotation.Kind k = ((DeclareAnnotation) declareDecl).getKind(); | |||
if (k.equals(DeclareAnnotation.AT_TYPE)) { | |||
if ((bits & TagBits.AnnotationForMethod) != 0) { | |||
classScope.problemReporter().disallowedTargetForAnnotation(annotations[a]); | |||
} | |||
} | |||
} | |||
if (k.equals(DeclareAnnotation.AT_FIELD)) { | |||
if ((bits & TagBits.AnnotationForMethod) != 0) { | |||
classScope.problemReporter().disallowedTargetForAnnotation(annotation); | |||
if (k.equals(DeclareAnnotation.AT_FIELD)) { | |||
if ((bits & TagBits.AnnotationForMethod) != 0) { | |||
classScope.problemReporter().disallowedTargetForAnnotation(annotations[a]); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
public Annotation getDeclaredAnnotation() { | |||
return annotation; | |||
public Annotation[] getDeclaredAnnotations() { | |||
return annotations; | |||
} | |||
protected boolean shouldDelegateCodeGeneration() { |
@@ -144,16 +144,17 @@ public class DeclarationFactory implements IDeclarationFactory { | |||
} | |||
public MethodDeclaration createDeclareAnnotationDeclaration(CompilationResult result, ASTNode pseudoTokens, | |||
Annotation annotation, Parser parser, char kind) { | |||
Annotation[] annotations, Parser parser, char kind) { | |||
DeclareAnnotation declare = (DeclareAnnotation) ((PseudoTokens) pseudoTokens).parseAnnotationDeclare(parser); | |||
if (declare != null) { | |||
if (kind == '-') { | |||
declare.setRemover(true); | |||
} | |||
} | |||
DeclareAnnotationDeclaration decl = new DeclareAnnotationDeclaration(result, declare, annotation); | |||
DeclareAnnotationDeclaration decl = new DeclareAnnotationDeclaration(result, declare, annotations); | |||
return decl; | |||
} | |||
public MethodDeclaration createInterTypeFieldDeclaration(CompilationResult result, TypeReference onType) { | |||
return new InterTypeFieldDeclaration(result, onType); |
@@ -51,8 +51,8 @@ public class DeclareAnnotation extends Declare { | |||
private ResolvedType containingAspect; | |||
private List<String> annotationMethods; | |||
private List<String> annotationStrings; | |||
private AnnotationAJ annotation; // discovered when required | |||
private ResolvedType annotationType; // discovered when required | |||
private AnnotationAJ[] annotations; // discovered when required | |||
private ResolvedType[] annotationTypes; // discovered when required | |||
// not serialized: | |||
private int annotationStart; | |||
@@ -150,7 +150,7 @@ public class DeclareAnnotation extends Declare { | |||
} | |||
ret.annotationMethods = this.annotationMethods; | |||
ret.annotationStrings = this.annotationStrings; | |||
ret.annotation = this.annotation; | |||
ret.annotations = this.annotations; | |||
ret.containingAspect = this.containingAspect; | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
@@ -365,7 +365,7 @@ public class DeclareAnnotation extends Declare { | |||
* finds that method and retrieves the annotation | |||
*/ | |||
private void ensureAnnotationDiscovered() { | |||
if (annotation != null) { | |||
if (annotations != null) { | |||
return; | |||
} | |||
String annotationMethod = annotationMethods.get(0); | |||
@@ -427,9 +427,10 @@ public class DeclareAnnotation extends Declare { | |||
/** | |||
* @return the type of the annotation | |||
*/ | |||
public ResolvedType getAnnotationType() { | |||
if (annotationType == null) { | |||
public ResolvedType[] getAnnotationTypes() { | |||
if (annotationTypes == null) { | |||
String annotationMethod = annotationMethods.get(0); | |||
List<ResolvedType> annoTypesToStore = new ArrayList<ResolvedType>(); | |||
for (Iterator<ResolvedMember> iter = containingAspect.getMethods(true, true); iter.hasNext();) { | |||
ResolvedMember member = iter.next(); | |||
if (member.getName().equals(annotationMethod)) { | |||
@@ -439,23 +440,20 @@ public class DeclareAnnotation extends Declare { | |||
return null; | |||
} | |||
int idx = 0; | |||
if (annoTypes[0].getSignature().equals("Lorg/aspectj/internal/lang/annotation/ajcDeclareAnnotation;")) { | |||
idx = 1; | |||
for (int i=0;i<annoTypes.length;i++) { | |||
if (!annoTypes[0].getSignature().equals("Lorg/aspectj/internal/lang/annotation/ajcDeclareAnnotation;")) { | |||
annoTypesToStore.add(annoTypes[i]); | |||
} | |||
} | |||
annotationType = annoTypes[idx]; | |||
// if (annoTypes[0].getSignature().equals("Lorg/aspectj/internal/lang/annotation/ajcDeclareAnnotation;")) { | |||
// idx = 1; | |||
// } | |||
annotationTypes = annoTypesToStore.toArray(new ResolvedType[annoTypesToStore.size()]);//annoTypes[idx]; | |||
break; | |||
} | |||
} | |||
} | |||
return annotationType; | |||
} | |||
/** | |||
* @return true if the annotation specified is allowed on a field | |||
*/ | |||
public boolean isAnnotationAllowedOnField() { | |||
ensureAnnotationDiscovered(); | |||
return annotation.allowedOnField(); | |||
return annotationTypes; | |||
} | |||
public String getPatternAsString() { |
@@ -21,9 +21,9 @@ import org.aspectj.testing.XMLBasedAjcTestCase; | |||
*/ | |||
public class Ajc171Tests extends org.aspectj.testing.XMLBasedAjcTestCase { | |||
// public void testMultipleAnnos_356594() { | |||
// runTest("multiple annos 1"); | |||
// } | |||
public void testMultipleAnnos_356594() { | |||
runTest("multiple annos 1"); | |||
} | |||
// --- | |||