64
68
private static final char[] aspectSig = "Lorg/aspectj/lang/annotation/Aspect;".toCharArray();
65
69
private static final char[] declareParentsSig = "Lorg/aspectj/lang/annotation/DeclareParents;".toCharArray();
66
70
private static final char[] adviceNameSig = "Lorg/aspectj/lang/annotation/AdviceName;".toCharArray();
67
private static final char[] orgAspectJLangAnnotation = "org/aspectj/lang/annotation/".toCharArray();
71
// private static final char[] orgAspectJLangAnnotation =
72
// "org/aspectj/lang/annotation/".toCharArray();
68
73
private static final char[] voidType = "void".toCharArray();
69
74
private static final char[] booleanType = "boolean".toCharArray();
70
75
private static final char[] joinPoint = "Lorg/aspectj/lang/JoinPoint;".toCharArray();
71
76
private static final char[] joinPointStaticPart = "Lorg/aspectj/lang/JoinPoint$StaticPart;".toCharArray();
72
77
private static final char[] joinPointEnclosingStaticPart = "Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;".toCharArray();
73
78
private static final char[] proceedingJoinPoint = "Lorg/aspectj/lang/ProceedingJoinPoint;".toCharArray();
74
private static final char[][] adviceSigs = new char[][] {beforeAdviceSig,afterAdviceSig,afterReturningAdviceSig,afterThrowingAdviceSig,aroundAdviceSig};
77
private CompilationUnitDeclaration unit;
78
private Stack typeStack = new Stack();
79
// private static final char[][] adviceSigs = new char[][] {
80
// beforeAdviceSig, afterAdviceSig, afterReturningAdviceSig,
81
// afterThrowingAdviceSig, aroundAdviceSig };
83
private final CompilationUnitDeclaration unit;
84
private final Stack typeStack = new Stack();
79
85
private AspectJAnnotations ajAnnotations;
81
87
public ValidateAtAspectJAnnotationsVisitor(CompilationUnitDeclaration unit) {
85
91
public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
86
92
typeStack.push(localTypeDeclaration);
87
93
ajAnnotations = new AspectJAnnotations(localTypeDeclaration.annotations);
88
94
checkTypeDeclaration(localTypeDeclaration);
92
public void endVisit(TypeDeclaration localTypeDeclaration,BlockScope scope) {
98
public void endVisit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
96
public boolean visit(TypeDeclaration memberTypeDeclaration,ClassScope scope) {
102
public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
97
103
typeStack.push(memberTypeDeclaration);
98
104
ajAnnotations = new AspectJAnnotations(memberTypeDeclaration.annotations);
99
105
checkTypeDeclaration(memberTypeDeclaration);
103
public void endVisit(TypeDeclaration memberTypeDeclaration,ClassScope scope) {
109
public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
107
113
public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
108
114
typeStack.push(typeDeclaration);
109
115
ajAnnotations = new AspectJAnnotations(typeDeclaration.annotations);
110
116
checkTypeDeclaration(typeDeclaration);
114
public void endVisit(TypeDeclaration typeDeclaration,CompilationUnitScope scope) {
120
public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
118
124
private void checkTypeDeclaration(TypeDeclaration typeDecl) {
119
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.VALIDATING_AT_ASPECTJ_ANNOTATIONS, typeDecl.name);
125
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
126
CompilationAndWeavingContext.VALIDATING_AT_ASPECTJ_ANNOTATIONS, typeDecl.name);
120
127
if (!(typeDecl instanceof AspectDeclaration)) {
121
128
if (ajAnnotations.hasAspectAnnotation) {
122
129
validateAspectDeclaration(typeDecl);
152
158
public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
153
159
ajAnnotations = new AspectJAnnotations(fieldDeclaration.annotations);
154
160
if (ajAnnotations.hasDeclareParents && !insideAspect()) {
155
scope.problemReporter().signalError(fieldDeclaration.sourceStart,
156
fieldDeclaration.sourceEnd,
157
"DeclareParents can only be used inside an aspect type");
161
scope.problemReporter().signalError(fieldDeclaration.sourceStart, fieldDeclaration.sourceEnd,
162
"DeclareParents can only be used inside an aspect type");
161
167
public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
162
168
if (methodDeclaration.hasErrors()) {
165
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.VALIDATING_AT_ASPECTJ_ANNOTATIONS, methodDeclaration.selector);
171
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
172
CompilationAndWeavingContext.VALIDATING_AT_ASPECTJ_ANNOTATIONS, methodDeclaration.selector);
166
173
ajAnnotations = new AspectJAnnotations(methodDeclaration.annotations);
167
174
if (!methodDeclaration.getClass().equals(AjMethodDeclaration.class)) {
168
// simply test for innapropriate use of annotations on code-style members
175
// simply test for innapropriate use of annotations on code-style
169
177
if (methodDeclaration instanceof PointcutDeclaration) {
170
if (ajAnnotations.hasMultiplePointcutAnnotations ||
171
ajAnnotations.hasAdviceAnnotation ||
172
ajAnnotations.hasAspectAnnotation ||
173
ajAnnotations.hasAdviceNameAnnotation) {
174
methodDeclaration.scope.problemReporter().signalError(
175
methodDeclaration.sourceStart,
176
methodDeclaration.sourceEnd,
177
"@AspectJ annotations cannot be declared on this aspect member");
178
if (ajAnnotations.hasMultiplePointcutAnnotations || ajAnnotations.hasAdviceAnnotation
179
|| ajAnnotations.hasAspectAnnotation || ajAnnotations.hasAdviceNameAnnotation) {
180
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart,
181
methodDeclaration.sourceEnd, "@AspectJ annotations cannot be declared on this aspect member");
179
183
} else if (methodDeclaration instanceof AdviceDeclaration) {
180
if (ajAnnotations.hasMultipleAdviceAnnotations ||
181
ajAnnotations.hasAspectAnnotation ||
182
ajAnnotations.hasPointcutAnnotation) {
183
methodDeclaration.scope.problemReporter().signalError(
184
methodDeclaration.sourceStart,
185
methodDeclaration.sourceEnd,
186
"Only @AdviceName AspectJ annotation allowed on advice");
184
if (ajAnnotations.hasMultipleAdviceAnnotations || ajAnnotations.hasAspectAnnotation
185
|| ajAnnotations.hasPointcutAnnotation) {
186
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart,
187
methodDeclaration.sourceEnd, "Only @AdviceName AspectJ annotation allowed on advice");
189
190
if (ajAnnotations.hasAspectJAnnotations()) {
190
methodDeclaration.scope.problemReporter().signalError(
191
methodDeclaration.sourceStart,
192
methodDeclaration.sourceEnd,
193
"@AspectJ annotations cannot be declared on this aspect member");
191
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart,
192
methodDeclaration.sourceEnd, "@AspectJ annotations cannot be declared on this aspect member");
196
195
CompilationAndWeavingContext.leavingPhase(tok);
200
199
if (ajAnnotations.hasAdviceAnnotation) {
201
200
validateAdvice(methodDeclaration);
202
201
} else if (ajAnnotations.hasPointcutAnnotation) {
203
convertToPointcutDeclaration(methodDeclaration,scope);
202
convertToPointcutDeclaration(methodDeclaration, scope);
205
204
CompilationAndWeavingContext.leavingPhase(tok);
209
private boolean isAspectJAnnotation(Annotation ann) {
210
if (ann.resolvedType == null) return false;
211
char[] sig = ann.resolvedType.signature();
212
return CharOperation.contains(orgAspectJLangAnnotation, sig);
208
// private boolean isAspectJAnnotation(Annotation ann) {
209
// if (ann.resolvedType == null) return false;
210
// char[] sig = ann.resolvedType.signature();
211
// return CharOperation.contains(orgAspectJLangAnnotation, sig);
215
214
private boolean insideAspect() {
216
if (typeStack.empty()) return false;
215
if (typeStack.empty())
217
217
TypeDeclaration typeDecl = (TypeDeclaration) typeStack.peek();
218
218
return isAspect(typeDecl);
221
221
private boolean isAspect(TypeDeclaration typeDecl) {
222
if (typeDecl instanceof AspectDeclaration) return true;
222
if (typeDecl instanceof AspectDeclaration)
223
224
return new AspectJAnnotations(typeDecl.annotations).hasAspectAnnotation;
227
* aspect must be public
228
* nested aspect must be static
229
* cannot extend a concrete aspect
230
* pointcut in perclause must be good.
228
* aspect must be public nested aspect must be static cannot extend a concrete aspect pointcut in perclause must be good.
232
230
private void validateAspectDeclaration(TypeDeclaration typeDecl) {
233
231
if (typeStack.size() > 1) {
234
232
// it's a nested aspect
235
233
if (!Modifier.isStatic(typeDecl.modifiers)) {
236
typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart, typeDecl.sourceEnd, "inner aspects must be static");
234
typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart, typeDecl.sourceEnd,
235
"inner aspects must be static");
241
240
SourceTypeBinding binding = typeDecl.binding;
242
241
if (binding != null) {
243
242
if (binding.isEnum() || binding.isInterface() || binding.isAnnotationType()) {
244
typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart,typeDecl.sourceEnd,"only classes can have an @Aspect annotation");
243
typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart, typeDecl.sourceEnd,
244
"only classes can have an @Aspect annotation");
248
//FIXME AV - do we really want that
249
// if (!Modifier.isPublic(typeDecl.modifiers)) {
250
// typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart,typeDecl.sourceEnd,"@Aspect class must be public");
248
// FIXME AV - do we really want that
249
// if (!Modifier.isPublic(typeDecl.modifiers)) {
250
// typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart,
251
// typeDecl.sourceEnd,"@Aspect class must be public");
253
TypeReference parentRef = typeDecl.superclass;
254
TypeReference parentRef = typeDecl.superclass;
254
255
if (parentRef != null) {
255
256
TypeBinding parentBinding = parentRef.resolvedType;
256
257
if (parentBinding instanceof SourceTypeBinding) {
257
258
SourceTypeBinding parentSTB = (SourceTypeBinding) parentBinding;
258
if (parentSTB.scope!=null) { // scope is null if its a binarytypebinding (in AJ world, thats a subclass of SourceTypeBinding)
259
TypeDeclaration parentDecl = parentSTB.scope.referenceContext;
259
if (parentSTB.scope != null) { // scope is null if its a
260
// binarytypebinding (in AJ
261
// world, thats a subclass of
262
// SourceTypeBinding)
263
TypeDeclaration parentDecl = parentSTB.scope.referenceContext;
260
264
if (isAspect(parentDecl) && !Modifier.isAbstract(parentDecl.modifiers)) {
261
typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart,typeDecl.sourceEnd,"cannot extend a concrete aspect");
265
typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart, typeDecl.sourceEnd,
266
"cannot extend a concrete aspect");
269
274
int[] pcLoc = new int[2];
270
275
String perClause = getStringLiteralFor("value", aspectAnnotation, pcLoc);
271
AspectDeclaration aspectDecl = new AspectDeclaration(typeDecl.compilationResult);
276
// AspectDeclaration aspectDecl = new
277
// AspectDeclaration(typeDecl.compilationResult);
274
280
if (perClause != null && !perClause.equals("")) {
275
ISourceContext context = new EclipseSourceContext(unit.compilationResult,pcLoc[0]);
276
Pointcut pc = new PatternParser(perClause,context).maybeParsePerClause();
277
FormalBinding[] bindings = new FormalBinding[0];
278
if (pc != null) pc.resolve(new EclipseScope(bindings,typeDecl.scope));
281
ISourceContext context = new EclipseSourceContext(unit.compilationResult, pcLoc[0]);
282
Pointcut pc = new PatternParser(perClause, context).maybeParsePerClause();
283
FormalBinding[] bindings = new FormalBinding[0];
285
pc.resolve(new EclipseScope(bindings, typeDecl.scope));
280
} catch(ParserException pEx) {
281
typeDecl.scope.problemReporter().parseError(
282
pcLoc[0] + pEx.getLocation().getStart(),
283
pcLoc[0] + pEx.getLocation().getEnd() ,
285
perClause.toCharArray(),
287
new String[] {pEx.getMessage()});
287
} catch (ParserException pEx) {
288
typeDecl.scope.problemReporter().parseError(pcLoc[0] + pEx.getLocation().getStart(),
289
pcLoc[0] + pEx.getLocation().getEnd(), -1, perClause.toCharArray(), perClause,
290
new String[] { pEx.getMessage() });
292
* 1) Advice must be public
293
* 2) Advice must have a void return type if not around advice
294
* 3) Advice must not have any other @AspectJ annotations
295
* 4) After throwing advice must declare the thrown formal
296
* 5) After returning advice must declare the returning formal
297
* 6) Advice must not be static
295
* 1) Advice must be public 2) Advice must have a void return type if not around advice 3) Advice must not have any other @AspectJ
296
* annotations 4) After throwing advice must declare the thrown formal 5) After returning advice must declare the returning
297
* formal 6) Advice must not be static
299
299
private void validateAdvice(MethodDeclaration methodDeclaration) {
301
301
if (!insideAspect()) {
302
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart,
303
methodDeclaration.sourceEnd,
304
"Advice must be declared inside an aspect type");
302
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart, methodDeclaration.sourceEnd,
303
"Advice must be declared inside an aspect type");
307
306
if (!Modifier.isPublic(methodDeclaration.modifiers)) {
308
methodDeclaration.scope.problemReporter()
309
.signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"advice must be public");
307
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart, methodDeclaration.sourceEnd,
308
"advice must be public");
312
311
if (Modifier.isStatic(methodDeclaration.modifiers)) {
313
methodDeclaration.scope.problemReporter()
314
.signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"advice can not be declared static");
312
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart, methodDeclaration.sourceEnd,
313
"advice can not be declared static");
317
316
if (ajAnnotations.hasMultipleAdviceAnnotations) {
318
317
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.duplicateAdviceAnnotation);
320
319
if (ajAnnotations.hasPointcutAnnotation) {
321
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.pointcutAnnotation);
320
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.pointcutAnnotation);
323
322
if (ajAnnotations.hasAspectAnnotation) {
324
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.aspectAnnotation);
323
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.aspectAnnotation);
326
325
if (ajAnnotations.hasAdviceNameAnnotation) {
327
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceNameAnnotation);
326
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceNameAnnotation);
330
329
if (ajAnnotations.adviceKind != AdviceKind.Around) {
331
330
ensureVoidReturnType(methodDeclaration);
334
333
if (ajAnnotations.adviceKind == AdviceKind.AfterThrowing) {
335
334
int[] throwingLocation = new int[2];
336
String thrownFormal = getStringLiteralFor("throwing",ajAnnotations.adviceAnnotation,throwingLocation);
335
String thrownFormal = getStringLiteralFor("throwing", ajAnnotations.adviceAnnotation, throwingLocation);
337
336
if (thrownFormal != null) {
338
Argument[] arguments = methodDeclaration.arguments;
337
// Argument[] arguments = methodDeclaration.arguments;
339
338
if (!toArgumentNames(methodDeclaration.arguments).contains(thrownFormal)) {
340
methodDeclaration.scope.problemReporter()
341
.signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"throwing formal '" + thrownFormal + "' must be declared as a parameter in the advice signature");
339
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart,
340
methodDeclaration.sourceEnd,
341
"throwing formal '" + thrownFormal + "' must be declared as a parameter in the advice signature");
346
346
if (ajAnnotations.adviceKind == AdviceKind.AfterReturning) {
347
347
int[] throwingLocation = new int[2];
348
String returningFormal = getStringLiteralFor("returning",ajAnnotations.adviceAnnotation,throwingLocation);
348
String returningFormal = getStringLiteralFor("returning", ajAnnotations.adviceAnnotation, throwingLocation);
349
349
if (returningFormal != null) {
350
350
if (!toArgumentNames(methodDeclaration.arguments).contains(returningFormal)) {
351
methodDeclaration.scope.problemReporter()
352
.signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"returning formal '" + returningFormal + "' must be declared as a parameter in the advice signature");
351
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart,
352
methodDeclaration.sourceEnd,
353
"returning formal '" + returningFormal + "' must be declared as a parameter in the advice signature");
357
358
resolveAndSetPointcut(methodDeclaration, ajAnnotations.adviceAnnotation);
362
* Get the argument names as a string list
364
* @return argument names (possibly empty)
366
private List toArgumentNames(Argument[] arguments) {
367
List names = new ArrayList();
368
if (arguments == null) {
371
for (int i = 0; i < arguments.length; i++) {
372
names.add(new String(arguments[i].name));
378
private void resolveAndSetPointcut(MethodDeclaration methodDeclaration, Annotation adviceAnn) {
363
* Get the argument names as a string list
366
* @return argument names (possibly empty)
368
private List toArgumentNames(Argument[] arguments) {
369
List names = new ArrayList();
370
if (arguments == null) {
373
for (int i = 0; i < arguments.length; i++) {
374
names.add(new String(arguments[i].name));
380
private void resolveAndSetPointcut(MethodDeclaration methodDeclaration, Annotation adviceAnn) {
379
381
int[] pcLocation = new int[2];
380
String pointcutExpression = getStringLiteralFor("pointcut",adviceAnn,pcLocation);
381
if (pointcutExpression == null) pointcutExpression = getStringLiteralFor("value",adviceAnn,pcLocation);
382
String pointcutExpression = getStringLiteralFor("pointcut", adviceAnn, pcLocation);
383
if (pointcutExpression == null)
384
pointcutExpression = getStringLiteralFor("value", adviceAnn, pcLocation);
383
ISourceContext context = new EclipseSourceContext(unit.compilationResult,pcLocation[0]);
384
Pointcut pc = new PatternParser(pointcutExpression,context).parsePointcut();
386
// +1 to give first char of pointcut string
387
ISourceContext context = new EclipseSourceContext(unit.compilationResult, pcLocation[0] + 1);
388
PatternParser pp = new PatternParser(pointcutExpression, context);
389
Pointcut pc = pp.parsePointcut();
385
391
FormalBinding[] bindings = buildFormalAdviceBindingsFrom(methodDeclaration);
386
pc.resolve(new EclipseScope(bindings,methodDeclaration.scope));
392
pc.resolve(new EclipseScope(bindings, methodDeclaration.scope));
387
393
EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(methodDeclaration.scope);
388
// now create a ResolvedPointcutDefinition,make an attribute out of it, and add it to the method
394
// now create a ResolvedPointcutDefinition,make an attribute out of
395
// it, and add it to the method
389
396
UnresolvedType[] paramTypes = new UnresolvedType[bindings.length];
390
for (int i = 0; i < paramTypes.length; i++) paramTypes[i] = bindings[i].getType();
391
ResolvedPointcutDefinition resPcutDef =
392
new ResolvedPointcutDefinition(
393
factory.fromBinding(((TypeDeclaration)typeStack.peek()).binding),
394
methodDeclaration.modifiers,
397
for (int i = 0; i < paramTypes.length; i++)
398
paramTypes[i] = bindings[i].getType();
399
ResolvedPointcutDefinition resPcutDef = new ResolvedPointcutDefinition(factory.fromBinding(((TypeDeclaration) typeStack
400
.peek()).binding), methodDeclaration.modifiers, "anonymous", paramTypes, pc);
399
401
AjAttribute attr = new AjAttribute.PointcutDeclarationAttribute(resPcutDef);
400
((AjMethodDeclaration)methodDeclaration).addAttribute(new EclipseAttributeAdapter(attr));
401
} catch(ParserException pEx) {
402
methodDeclaration.scope.problemReporter().parseError(
403
pcLocation[0] + pEx.getLocation().getStart(),
404
pcLocation[0] + pEx.getLocation().getEnd() ,
406
pointcutExpression.toCharArray(),
408
new String[] {pEx.getMessage()});
402
((AjMethodDeclaration) methodDeclaration).addAttribute(new EclipseAttributeAdapter(attr));
403
} catch (ParserException pEx) {
404
methodDeclaration.scope.problemReporter().parseError(pcLocation[0] + pEx.getLocation().getStart(),
405
pcLocation[0] + pEx.getLocation().getEnd(), -1, pointcutExpression.toCharArray(), pointcutExpression,
406
new String[] { pEx.getMessage() });
422
420
if (!returnsVoid) {
423
421
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
424
methodDeclaration.returnType.sourceEnd,
425
"This advice must return void");
422
methodDeclaration.returnType.sourceEnd, "This advice must return void");
429
426
private FormalBinding[] buildFormalAdviceBindingsFrom(MethodDeclaration mDecl) {
430
if (mDecl.arguments == null) return new FormalBinding[0];
431
if (mDecl.binding == null) return new FormalBinding[0];
427
if (mDecl.arguments == null)
428
return new FormalBinding[0];
429
if (mDecl.binding == null)
430
return new FormalBinding[0];
432
431
EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(mDecl.scope);
433
432
String extraArgName = maybeGetExtraArgName();
434
if (extraArgName == null) extraArgName = "";
433
if (extraArgName == null)
435
435
FormalBinding[] ret = new FormalBinding[mDecl.arguments.length];
436
436
for (int i = 0; i < mDecl.arguments.length; i++) {
437
Argument arg = mDecl.arguments[i];
438
String name = new String(arg.name);
439
TypeBinding argTypeBinding = mDecl.binding.parameters[i];
440
UnresolvedType type = factory.fromBinding(argTypeBinding);
441
if (CharOperation.equals(joinPoint,argTypeBinding.signature()) ||
442
CharOperation.equals(joinPointStaticPart,argTypeBinding.signature()) ||
443
CharOperation.equals(joinPointEnclosingStaticPart,argTypeBinding.signature()) ||
444
CharOperation.equals(proceedingJoinPoint,argTypeBinding.signature()) ||
445
name.equals(extraArgName)) {
446
ret[i] = new FormalBinding.ImplicitFormalBinding(type,name,i);
437
Argument arg = mDecl.arguments[i];
438
String name = new String(arg.name);
439
TypeBinding argTypeBinding = mDecl.binding.parameters[i];
440
UnresolvedType type = factory.fromBinding(argTypeBinding);
441
if (CharOperation.equals(joinPoint, argTypeBinding.signature())
442
|| CharOperation.equals(joinPointStaticPart, argTypeBinding.signature())
443
|| CharOperation.equals(joinPointEnclosingStaticPart, argTypeBinding.signature())
444
|| CharOperation.equals(proceedingJoinPoint, argTypeBinding.signature()) || name.equals(extraArgName)) {
445
ret[i] = new FormalBinding.ImplicitFormalBinding(type, name, i);
448
ret[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd, "unknown");
447
ret[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd);
454
453
private String maybeGetExtraArgName() {
455
454
String argName = null;
456
455
if (ajAnnotations.adviceKind == AdviceKind.AfterReturning) {
457
argName = getStringLiteralFor("returning",ajAnnotations.adviceAnnotation,new int[2]);
456
argName = getStringLiteralFor("returning", ajAnnotations.adviceAnnotation, new int[2]);
458
457
} else if (ajAnnotations.adviceKind == AdviceKind.AfterThrowing) {
459
argName = getStringLiteralFor("throwing",ajAnnotations.adviceAnnotation,new int[2]);
458
argName = getStringLiteralFor("throwing", ajAnnotations.adviceAnnotation, new int[2]);
491
497
private void convertToPointcutDeclaration(MethodDeclaration methodDeclaration, ClassScope scope) {
492
498
TypeDeclaration typeDecl = (TypeDeclaration) typeStack.peek();
493
499
if (typeDecl.binding != null) {
494
500
if (!typeDecl.binding.isClass()) {
495
methodDeclaration.scope.problemReporter()
496
.signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"pointcuts can only be declared in a class or an aspect");
501
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart, methodDeclaration.sourceEnd,
502
"pointcuts can only be declared in a class or an aspect");
500
506
if (methodDeclaration.thrownExceptions != null && methodDeclaration.thrownExceptions.length > 0) {
501
methodDeclaration.scope.problemReporter()
502
.signalError(methodDeclaration.sourceStart,methodDeclaration.sourceEnd,"pointcuts cannot throw exceptions!");
507
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.sourceStart, methodDeclaration.sourceEnd,
508
"pointcuts cannot throw exceptions!");
505
511
PointcutDeclaration pcDecl = new PointcutDeclaration(unit.compilationResult);
506
copyAllFields(methodDeclaration,pcDecl);
512
copyAllFields(methodDeclaration, pcDecl);
508
514
if (ajAnnotations.hasAdviceAnnotation) {
509
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceAnnotation);
515
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceAnnotation);
511
517
if (ajAnnotations.hasAspectAnnotation) {
512
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.aspectAnnotation);
518
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.aspectAnnotation);
514
520
if (ajAnnotations.hasAdviceNameAnnotation) {
515
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceNameAnnotation);
521
methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceNameAnnotation);
518
boolean noValueSupplied=true;
524
boolean noValueSupplied = true;
519
525
boolean containsIfPcd = false;
520
526
int[] pcLocation = new int[2];
521
String pointcutExpression = getStringLiteralFor("value",ajAnnotations.pointcutAnnotation,pcLocation);
527
String pointcutExpression = getStringLiteralFor("value", ajAnnotations.pointcutAnnotation, pcLocation);
523
ISourceContext context = new EclipseSourceContext(unit.compilationResult,pcLocation[0]);
524
Pointcut pc = null;//abstract
525
if (pointcutExpression == null || pointcutExpression.length() == 0) {
526
noValueSupplied=true; // matches nothing pointcut
528
noValueSupplied=false;
529
pc = new PatternParser(pointcutExpression,context).parsePointcut();
531
pcDecl.pointcutDesignator = (pc==null)?null:new PointcutDesignator(pc);
529
ISourceContext context = new EclipseSourceContext(unit.compilationResult, pcLocation[0]);
530
Pointcut pc = null;// abstract
531
if (pointcutExpression == null || pointcutExpression.length() == 0) {
532
noValueSupplied = true; // matches nothing pointcut
534
noValueSupplied = false;
535
pc = new PatternParser(pointcutExpression, context).parsePointcut();
537
pcDecl.pointcutDesignator = (pc == null) ? null : new PointcutDesignator(pc);
532
538
pcDecl.setGenerateSyntheticPointcutMethod();
533
539
TypeDeclaration onType = (TypeDeclaration) typeStack.peek();
534
540
pcDecl.postParse(onType);
535
// EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(methodDeclaration.scope);
536
// int argsLength = methodDeclaration.arguments == null ? 0 : methodDeclaration.arguments.length;
541
// EclipseFactory factory =
542
// EclipseFactory.fromScopeLookupEnvironment
543
// (methodDeclaration.scope);
544
// int argsLength = methodDeclaration.arguments == null ? 0 :
545
// methodDeclaration.arguments.length;
537
546
FormalBinding[] bindings = buildFormalAdviceBindingsFrom(methodDeclaration);
538
// FormalBinding[] bindings = new FormalBinding[argsLength];
539
// for (int i = 0, len = bindings.length; i < len; i++) {
540
// Argument arg = methodDeclaration.arguments[i];
541
// String name = new String(arg.name);
542
// UnresolvedType type = factory.fromBinding(methodDeclaration.binding.parameters[i]);
543
// bindings[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd, "unknown");
545
swap(onType,methodDeclaration,pcDecl);
547
// FormalBinding[] bindings = new FormalBinding[argsLength];
548
// for (int i = 0, len = bindings.length; i < len; i++) {
549
// Argument arg = methodDeclaration.arguments[i];
550
// String name = new String(arg.name);
551
// UnresolvedType type =
552
// factory.fromBinding(methodDeclaration.binding.parameters[i]);
553
// bindings[i] = new FormalBinding(type, name, i, arg.sourceStart,
554
// arg.sourceEnd, "unknown");
556
swap(onType, methodDeclaration, pcDecl);
546
557
if (pc != null) {
548
pc.resolve(new EclipseScope(bindings,methodDeclaration.scope));
549
HasIfPCDVisitor ifFinder = new HasIfPCDVisitor();
550
pc.traverse(ifFinder, null);
551
containsIfPcd = ifFinder.containsIfPcd;
553
} catch(ParserException pEx) {
554
methodDeclaration.scope.problemReporter().parseError(
555
pcLocation[0] + pEx.getLocation().getStart(),
556
pcLocation[0] + pEx.getLocation().getEnd() ,
558
pointcutExpression.toCharArray(),
560
new String[] {pEx.getMessage()});
559
EclipseScope eScope = new EclipseScope(bindings, methodDeclaration.scope);
560
char[] packageName = null;
561
if (typeDecl.binding != null && typeDecl.binding.getPackage() != null) {
562
packageName = typeDecl.binding.getPackage().readableName();
564
eScope.setLimitedImports(packageName);
566
HasIfPCDVisitor ifFinder = new HasIfPCDVisitor();
567
pc.traverse(ifFinder, null);
568
containsIfPcd = ifFinder.containsIfPcd;
570
} catch (ParserException pEx) {
571
methodDeclaration.scope.problemReporter().parseError(pcLocation[0] + pEx.getLocation().getStart(),
572
pcLocation[0] + pEx.getLocation().getEnd(), -1, pointcutExpression.toCharArray(), pointcutExpression,
573
new String[] { pEx.getMessage() });
563
576
boolean returnsVoid = false;
564
577
boolean returnsBoolean = false;
565
578
if ((methodDeclaration.returnType instanceof SingleTypeReference)) {
566
579
SingleTypeReference retType = (SingleTypeReference) methodDeclaration.returnType;
567
if (CharOperation.equals(voidType,retType.token)) returnsVoid = true;
568
if (CharOperation.equals(booleanType,retType.token)) returnsBoolean = true;
580
if (CharOperation.equals(voidType, retType.token))
582
if (CharOperation.equals(booleanType, retType.token))
583
returnsBoolean = true;
570
585
if (!returnsVoid && !containsIfPcd) {
571
586
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
572
methodDeclaration.returnType.sourceEnd,
573
"Methods annotated with @Pointcut must return void unless the pointcut contains an if() expression");
587
methodDeclaration.returnType.sourceEnd,
588
"Methods annotated with @Pointcut must return void unless the pointcut contains an if() expression");
575
590
if (!returnsBoolean && containsIfPcd) {
576
591
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
577
methodDeclaration.returnType.sourceEnd,
578
"Methods annotated with @Pointcut must return boolean when the pointcut contains an if() expression");
592
methodDeclaration.returnType.sourceEnd,
593
"Methods annotated with @Pointcut must return boolean when the pointcut contains an if() expression");
581
596
if (methodDeclaration.statements != null && methodDeclaration.statements.length > 0 && !containsIfPcd) {
597
methodDeclaration.scope.problemReporter()
598
.signalError(methodDeclaration.returnType.sourceStart, methodDeclaration.returnType.sourceEnd,
599
"Pointcuts without an if() expression should have an empty method body");
602
if (pcDecl.pointcutDesignator == null) {
603
if (Modifier.isAbstract(methodDeclaration.modifiers) || noValueSupplied // this
609
// those 2 checks makes sense for aop.xml concretization but NOT for
610
// regular abstraction of pointcut
612
// && (methodDeclaration.arguments == null ||
613
// methodDeclaration.arguments.length == 0)) {
617
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
618
methodDeclaration.returnType.sourceEnd,
619
"Method annotated with @Pointcut() for abstract pointcut must be abstract");
621
} else if (Modifier.isAbstract(methodDeclaration.modifiers)) {
582
622
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
583
methodDeclaration.returnType.sourceEnd,
584
"Pointcuts without an if() expression should have an empty method body");
623
methodDeclaration.returnType.sourceEnd,
624
"Method annotated with non abstract @Pointcut(\"" + pointcutExpression + "\") is abstract");
587
if (pcDecl.pointcutDesignator == null) {
588
if (Modifier.isAbstract(methodDeclaration.modifiers)
589
|| noValueSupplied // this is a matches nothing pointcut
590
//those 2 checks makes sense for aop.xml concretization but NOT for regular abstraction of pointcut
592
//&& (methodDeclaration.arguments == null || methodDeclaration.arguments.length == 0)) {
596
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
597
methodDeclaration.returnType.sourceEnd,
598
"Method annotated with @Pointcut() for abstract pointcut must be abstract");
600
} else if (Modifier.isAbstract(methodDeclaration.modifiers)) {
601
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
602
methodDeclaration.returnType.sourceEnd,
603
"Method annotated with non abstract @Pointcut(\""+pointcutExpression+"\") is abstract");
607
628
private void copyAllFields(MethodDeclaration from, MethodDeclaration to) {
608
629
to.annotations = from.annotations;
609
630
to.arguments = from.arguments;
658
677
Annotation duplicateAdviceAnnotation = null;
659
678
Annotation duplicatePointcutAnnotation = null;
660
679
Annotation duplicateAspectAnnotation = null;
662
681
public AspectJAnnotations(Annotation[] annotations) {
663
if (annotations == null) return;
682
if (annotations == null)
664
684
for (int i = 0; i < annotations.length; i++) {
665
if (annotations[i].resolvedType == null) continue; // user messed up annotation declaration
685
if (annotations[i].resolvedType == null)
686
continue; // user messed up annotation declaration
666
687
char[] sig = annotations[i].resolvedType.signature();
667
if (CharOperation.equals(afterAdviceSig,sig)) {
688
if (CharOperation.equals(afterAdviceSig, sig)) {
668
689
adviceKind = AdviceKind.After;
669
690
addAdviceAnnotation(annotations[i]);
670
} else if (CharOperation.equals(afterReturningAdviceSig,sig)) {
691
} else if (CharOperation.equals(afterReturningAdviceSig, sig)) {
671
692
adviceKind = AdviceKind.AfterReturning;
672
693
addAdviceAnnotation(annotations[i]);
673
} else if (CharOperation.equals(afterThrowingAdviceSig,sig)) {
694
} else if (CharOperation.equals(afterThrowingAdviceSig, sig)) {
674
695
adviceKind = AdviceKind.AfterThrowing;
675
696
addAdviceAnnotation(annotations[i]);
676
} else if (CharOperation.equals(beforeAdviceSig,sig)) {
697
} else if (CharOperation.equals(beforeAdviceSig, sig)) {
677
698
adviceKind = AdviceKind.Before;
678
699
addAdviceAnnotation(annotations[i]);
679
} else if (CharOperation.equals(aroundAdviceSig,sig)) {
700
} else if (CharOperation.equals(aroundAdviceSig, sig)) {
680
701
adviceKind = AdviceKind.Around;
681
702
addAdviceAnnotation(annotations[i]);
682
} else if (CharOperation.equals(adviceNameSig,sig)) {
703
} else if (CharOperation.equals(adviceNameSig, sig)) {
683
704
hasAdviceNameAnnotation = true;
684
705
adviceNameAnnotation = annotations[i];
685
} else if (CharOperation.equals(declareParentsSig,sig)) {
706
} else if (CharOperation.equals(declareParentsSig, sig)) {
686
707
hasDeclareParents = true;
687
} else if (CharOperation.equals(aspectSig,sig)) {
708
} else if (CharOperation.equals(aspectSig, sig)) {
688
709
if (hasAspectAnnotation) {
689
710
hasMultipleAspectAnnotations = true;
690
711
duplicateAspectAnnotation = annotations[i];