~ubuntu-branches/ubuntu/natty/aspectj/natty

« back to all changes in this revision

Viewing changes to org.aspectj/modules/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java

  • Committer: Bazaar Package Importer
  • Author(s): Damien Raude-Morvan
  • Date: 2009-10-04 16:37:23 UTC
  • mfrom: (1.1.3 upstream) (3.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20091004163723-ck4y7j7fhjxskkie
Tags: 1.6.6+dfsg-1
* New upstream release.
  - Update 02_use_gjdoc.diff patch
* Update my email address

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
package org.aspectj.ajdt.internal.compiler.ast;
13
13
 
14
14
import java.lang.reflect.Modifier;
15
 
import java.util.Stack;
16
15
import java.util.ArrayList;
17
16
import java.util.List;
 
17
import java.util.Stack;
18
18
 
19
19
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
20
20
import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope;
29
29
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
30
30
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
31
31
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 
32
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NameReference;
32
33
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
33
34
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
34
35
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
35
36
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
36
37
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
37
38
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
 
39
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
 
40
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
38
41
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
39
42
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
40
43
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
 
44
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
41
45
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
42
46
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
43
47
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
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};
75
 
        
76
 
        
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 };
 
82
 
 
83
        private final CompilationUnitDeclaration unit;
 
84
        private final Stack typeStack = new Stack();
79
85
        private AspectJAnnotations ajAnnotations;
80
 
        
 
86
 
81
87
        public ValidateAtAspectJAnnotationsVisitor(CompilationUnitDeclaration unit) {
82
88
                this.unit = unit;
83
89
        }
84
 
        
 
90
 
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);
89
95
                return true;
90
96
        }
91
 
        
92
 
        public void endVisit(TypeDeclaration localTypeDeclaration,BlockScope scope) {
 
97
 
 
98
        public void endVisit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
93
99
                typeStack.pop();
94
100
        }
95
 
        
96
 
        public boolean visit(TypeDeclaration memberTypeDeclaration,ClassScope scope) {
 
101
 
 
102
        public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
97
103
                typeStack.push(memberTypeDeclaration);
98
104
                ajAnnotations = new AspectJAnnotations(memberTypeDeclaration.annotations);
99
105
                checkTypeDeclaration(memberTypeDeclaration);
100
106
                return true;
101
107
        }
102
 
        
103
 
        public void endVisit(TypeDeclaration memberTypeDeclaration,ClassScope scope) {
 
108
 
 
109
        public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
104
110
                typeStack.pop();
105
111
        }
106
 
        
 
112
 
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);
111
117
                return true;
112
118
        }
113
 
        
114
 
        public void endVisit(TypeDeclaration typeDeclaration,CompilationUnitScope scope) {
 
119
 
 
120
        public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
115
121
                typeStack.pop();
116
122
        }
117
 
        
 
123
 
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);
130
137
                                                if (parentSTB.scope != null) {
131
138
                                                        TypeDeclaration parentDecl = parentSTB.scope.referenceContext;
132
139
                                                        if (isAspect(parentDecl)) {
133
 
                                                                typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart,typeDecl.sourceEnd,"a class cannot extend an aspect");
 
140
                                                                typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart, typeDecl.sourceEnd,
 
141
                                                                                "a class cannot extend an aspect");
134
142
                                                        }
135
143
                                                }
136
144
                                        }
137
145
                                }
138
146
                        }
139
147
                } else {
140
 
                        // check that aspect doesn't have @Aspect annotation, we've already added on ourselves.
 
148
                        // check that aspect doesn't have @Aspect annotation, we've already
 
149
                        // added on ourselves.
141
150
                        if (ajAnnotations.hasMultipleAspectAnnotations) {
142
 
                                        typeDecl.scope.problemReporter().signalError(
143
 
                                                        typeDecl.sourceStart,
144
 
                                                        typeDecl.sourceEnd,
145
 
                                                        "aspects cannot have @Aspect annotation"
146
 
                                                        );
 
151
                                typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart, typeDecl.sourceEnd,
 
152
                                                "aspects cannot have @Aspect annotation");
147
153
                        }
148
154
                }
149
155
                CompilationAndWeavingContext.leavingPhase(tok);
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");
158
163
                }
159
164
                return true;
160
165
        }
 
166
 
161
167
        public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
162
168
                if (methodDeclaration.hasErrors()) {
163
169
                        return false;
164
170
                }
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
 
176
                        // members
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");
178
182
                                }
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");
187
 
                                }                               
 
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");
 
188
                                }
188
189
                        } else {
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");
194
193
                                }
195
194
                        }
196
195
                        CompilationAndWeavingContext.leavingPhase(tok);
197
196
                        return false;
198
197
                }
199
 
                
 
198
 
200
199
                if (ajAnnotations.hasAdviceAnnotation) {
201
200
                        validateAdvice(methodDeclaration);
202
201
                } else if (ajAnnotations.hasPointcutAnnotation) {
203
 
                        convertToPointcutDeclaration(methodDeclaration,scope);
 
202
                        convertToPointcutDeclaration(methodDeclaration, scope);
204
203
                }
205
204
                CompilationAndWeavingContext.leavingPhase(tok);
206
205
                return false;
207
206
        }
208
 
        
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);
213
 
        }
214
 
        
 
207
 
 
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);
 
212
        // }
 
213
 
215
214
        private boolean insideAspect() {
216
 
                if (typeStack.empty()) return false;
 
215
                if (typeStack.empty())
 
216
                        return false;
217
217
                TypeDeclaration typeDecl = (TypeDeclaration) typeStack.peek();
218
218
                return isAspect(typeDecl);
219
219
        }
220
 
        
 
220
 
221
221
        private boolean isAspect(TypeDeclaration typeDecl) {
222
 
                if (typeDecl instanceof AspectDeclaration) return true;
 
222
                if (typeDecl instanceof AspectDeclaration)
 
223
                        return true;
223
224
                return new AspectJAnnotations(typeDecl.annotations).hasAspectAnnotation;
224
225
        }
225
 
        
 
226
 
226
227
        /**
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.
231
229
         */
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");
237
236
                                return;
238
237
                        }
239
238
                }
240
 
                
 
239
 
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");
245
245
                        }
246
246
                }
247
247
 
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");
251
 
//        }
 
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");
 
252
                // }
252
253
 
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");
262
 
                                        }                       
 
265
                                                typeDecl.scope.problemReporter().signalError(typeDecl.sourceStart, typeDecl.sourceEnd,
 
266
                                                                "cannot extend a concrete aspect");
 
267
                                        }
263
268
                                }
264
269
                        }
265
270
                }
268
273
 
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);
272
278
 
273
279
                try {
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];
 
284
                                if (pc != null)
 
285
                                        pc.resolve(new EclipseScope(bindings, typeDecl.scope));
279
286
                        }
280
 
                } catch(ParserException pEx) {
281
 
                        typeDecl.scope.problemReporter().parseError(
282
 
                                        pcLoc[0] + pEx.getLocation().getStart(),
283
 
                                        pcLoc[0] + pEx.getLocation().getEnd() ,
284
 
                                        -1, 
285
 
                                        perClause.toCharArray(), 
286
 
                                        perClause, 
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() });
288
291
                }
289
292
        }
290
 
        
 
293
 
291
294
        /**
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
298
298
         */
299
299
        private void validateAdvice(MethodDeclaration methodDeclaration) {
300
 
                
 
300
 
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");
305
304
                }
306
 
                
 
305
 
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");
310
309
                }
311
310
 
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");
315
314
                }
316
 
                                
 
315
 
317
316
                if (ajAnnotations.hasMultipleAdviceAnnotations) {
318
317
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.duplicateAdviceAnnotation);
319
318
                }
320
319
                if (ajAnnotations.hasPointcutAnnotation) {
321
 
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.pointcutAnnotation);                      
 
320
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.pointcutAnnotation);
322
321
                }
323
322
                if (ajAnnotations.hasAspectAnnotation) {
324
 
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.aspectAnnotation);                        
 
323
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.aspectAnnotation);
325
324
                }
326
325
                if (ajAnnotations.hasAdviceNameAnnotation) {
327
 
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceNameAnnotation);                    
 
326
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceNameAnnotation);
328
327
                }
329
328
 
330
329
                if (ajAnnotations.adviceKind != AdviceKind.Around) {
331
330
                        ensureVoidReturnType(methodDeclaration);
332
 
                }         
333
 
                
 
331
                }
 
332
 
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");
342
342
                                }
343
343
                        }
344
344
                }
345
 
                
 
345
 
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");
353
354
                                }
354
355
                        }
355
356
                }
356
357
 
357
358
                resolveAndSetPointcut(methodDeclaration, ajAnnotations.adviceAnnotation);
358
 
                
359
 
        }
360
 
 
361
 
    /**
362
 
     * Get the argument names as a string list
363
 
     * @param arguments
364
 
     * @return argument names (possibly empty)
365
 
     */
366
 
    private List toArgumentNames(Argument[] arguments) {
367
 
        List names = new ArrayList();
368
 
        if (arguments == null) {
369
 
            return names;
370
 
        } else {
371
 
            for (int i = 0; i < arguments.length; i++) {
372
 
                names.add(new String(arguments[i].name));
373
 
            }
374
 
            return names;
375
 
        }
376
 
    }
377
 
 
378
 
    private void resolveAndSetPointcut(MethodDeclaration methodDeclaration, Annotation adviceAnn) {
 
359
 
 
360
        }
 
361
 
 
362
        /**
 
363
         * Get the argument names as a string list
 
364
         * 
 
365
         * @param arguments
 
366
         * @return argument names (possibly empty)
 
367
         */
 
368
        private List toArgumentNames(Argument[] arguments) {
 
369
                List names = new ArrayList();
 
370
                if (arguments == null) {
 
371
                        return names;
 
372
                } else {
 
373
                        for (int i = 0; i < arguments.length; i++) {
 
374
                                names.add(new String(arguments[i].name));
 
375
                        }
 
376
                        return names;
 
377
                }
 
378
        }
 
379
 
 
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);
382
385
                try {
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();
 
390
                        pp.checkEof();
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,
395
 
                                                "anonymous",
396
 
                                                paramTypes,
397
 
                                                pc
398
 
                                );
 
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() ,
405
 
                                        -1, 
406
 
                                        pointcutExpression.toCharArray(), 
407
 
                                        pointcutExpression, 
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() });
409
407
                }
410
408
        }
411
409
 
413
411
                boolean returnsVoid = true;
414
412
                if ((methodDeclaration.returnType instanceof SingleTypeReference)) {
415
413
                        SingleTypeReference retType = (SingleTypeReference) methodDeclaration.returnType;
416
 
                        if (!CharOperation.equals(voidType,retType.token)) {
 
414
                        if (!CharOperation.equals(voidType, retType.token)) {
417
415
                                returnsVoid = false;
418
416
                        }
419
417
                } else {
421
419
                }
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");
426
423
                }
427
424
        }
428
 
        
 
425
 
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)
 
434
                        extraArgName = "";
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);
447
446
                        } else {
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);
449
448
                        }
450
449
                }
451
450
                return ret;
452
451
        }
453
 
        
 
452
 
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]);
460
459
                }
461
460
                return argName;
462
461
        }
469
468
                                location[0] = sv.sourceStart;
470
469
                                location[1] = sv.sourceEnd;
471
470
                                return new String(sv.source());
 
471
                        } else if (sma.memberValue instanceof NameReference
 
472
                                        && (((NameReference) sma.memberValue).binding instanceof FieldBinding)) {
 
473
                                Binding b = ((NameReference) sma.memberValue).binding;
 
474
                                Constant c = ((FieldBinding) b).constant;
 
475
                                return c.stringValue();
472
476
                        }
473
477
                }
474
 
                if (! (inAnnotation instanceof NormalAnnotation)) return null;
 
478
                if (!(inAnnotation instanceof NormalAnnotation))
 
479
                        return null;
475
480
                NormalAnnotation ann = (NormalAnnotation) inAnnotation;
476
481
                MemberValuePair[] mvps = ann.memberValuePairs;
477
 
                if (mvps == null) return null;
 
482
                if (mvps == null)
 
483
                        return null;
478
484
                for (int i = 0; i < mvps.length; i++) {
479
 
                        if (CharOperation.equals(memberName.toCharArray(),mvps[i].name)) {
 
485
                        if (CharOperation.equals(memberName.toCharArray(), mvps[i].name)) {
480
486
                                if (mvps[i].value instanceof StringLiteral) {
481
487
                                        StringLiteral sv = (StringLiteral) mvps[i].value;
482
488
                                        location[0] = sv.sourceStart;
487
493
                }
488
494
                return null;
489
495
        }
490
 
        
 
496
 
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");
497
503
                        }
498
504
                }
499
 
                
 
505
 
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!");
503
509
                }
504
 
                
 
510
 
505
511
                PointcutDeclaration pcDecl = new PointcutDeclaration(unit.compilationResult);
506
 
                copyAllFields(methodDeclaration,pcDecl);
 
512
                copyAllFields(methodDeclaration, pcDecl);
507
513
 
508
514
                if (ajAnnotations.hasAdviceAnnotation) {
509
 
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceAnnotation);                        
 
515
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceAnnotation);
510
516
                }
511
517
                if (ajAnnotations.hasAspectAnnotation) {
512
 
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.aspectAnnotation);                        
 
518
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.aspectAnnotation);
513
519
                }
514
520
                if (ajAnnotations.hasAdviceNameAnnotation) {
515
 
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceNameAnnotation);                    
 
521
                        methodDeclaration.scope.problemReporter().disallowedTargetForAnnotation(ajAnnotations.adviceNameAnnotation);
516
522
                }
517
 
        
518
 
                boolean noValueSupplied=true;
 
523
 
 
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);
522
528
                try {
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
527
 
            } else {
528
 
                noValueSupplied=false;
529
 
                pc = new PatternParser(pointcutExpression,context).parsePointcut();
530
 
            }
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
 
533
                        } else {
 
534
                                noValueSupplied = false;
 
535
                                pc = new PatternParser(pointcutExpression, context).parsePointcut();
 
536
                        }
 
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");
544
 
//              }
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");
 
555
                        // }
 
556
                        swap(onType, methodDeclaration, pcDecl);
546
557
                        if (pc != null) {
547
 
                // has an expression
548
 
                pc.resolve(new EclipseScope(bindings,methodDeclaration.scope));
549
 
                HasIfPCDVisitor ifFinder = new HasIfPCDVisitor();
550
 
                pc.traverse(ifFinder, null);
551
 
                containsIfPcd = ifFinder.containsIfPcd;
552
 
            }
553
 
        } catch(ParserException pEx) {
554
 
                        methodDeclaration.scope.problemReporter().parseError(
555
 
                                        pcLocation[0] + pEx.getLocation().getStart(),
556
 
                                        pcLocation[0] + pEx.getLocation().getEnd() ,
557
 
                                        -1, 
558
 
                                        pointcutExpression.toCharArray(), 
559
 
                                        pointcutExpression, 
560
 
                                        new String[] {pEx.getMessage()});
 
558
                                // has an expression
 
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();
 
563
                                }
 
564
                                eScope.setLimitedImports(packageName);
 
565
                                pc.resolve(eScope);
 
566
                                HasIfPCDVisitor ifFinder = new HasIfPCDVisitor();
 
567
                                pc.traverse(ifFinder, null);
 
568
                                containsIfPcd = ifFinder.containsIfPcd;
 
569
                        }
 
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() });
561
574
                }
562
 
                
 
575
 
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;
569
 
                } 
 
580
                        if (CharOperation.equals(voidType, retType.token))
 
581
                                returnsVoid = true;
 
582
                        if (CharOperation.equals(booleanType, retType.token))
 
583
                                returnsBoolean = true;
 
584
                }
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");
574
589
                }
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");
579
594
                }
580
 
                
 
595
 
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");
 
600
                }
 
601
 
 
602
                if (pcDecl.pointcutDesignator == null) {
 
603
                        if (Modifier.isAbstract(methodDeclaration.modifiers) || noValueSupplied // this
 
604
                        // is
 
605
                        // a
 
606
                        // matches
 
607
                        // nothing
 
608
                        // pointcut
 
609
                        // those 2 checks makes sense for aop.xml concretization but NOT for
 
610
                        // regular abstraction of pointcut
 
611
                        // && returnsVoid
 
612
                        // && (methodDeclaration.arguments == null ||
 
613
                        // methodDeclaration.arguments.length == 0)) {
 
614
                        ) {
 
615
                                // fine
 
616
                        } else {
 
617
                                methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
 
618
                                                methodDeclaration.returnType.sourceEnd,
 
619
                                                "Method annotated with @Pointcut() for abstract pointcut must be abstract");
 
620
                        }
 
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");
585
625
                }
 
626
        }
586
627
 
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
591
 
                //&& returnsVoid
592
 
                //&& (methodDeclaration.arguments == null || methodDeclaration.arguments.length == 0)) {
593
 
                ) {
594
 
                ;//fine
595
 
            } else {
596
 
                        methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart,
597
 
                                  methodDeclaration.returnType.sourceEnd,
598
 
                                  "Method annotated with @Pointcut() for abstract pointcut must be abstract");
599
 
            }
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");
604
 
        }
605
 
    }
606
 
        
607
628
        private void copyAllFields(MethodDeclaration from, MethodDeclaration to) {
608
629
                to.annotations = from.annotations;
609
630
                to.arguments = from.arguments;
613
634
                to.bodyStart = from.bodyStart;
614
635
                to.declarationSourceEnd = from.declarationSourceEnd;
615
636
                to.declarationSourceStart = from.declarationSourceStart;
616
 
                to.errorInSignature = from.errorInSignature;
617
637
                to.explicitDeclarations = from.explicitDeclarations;
618
638
                to.ignoreFurtherInvestigation = from.ignoreFurtherInvestigation;
619
639
                to.javadoc = from.javadoc;
620
640
                to.modifiers = from.modifiers;
621
641
                to.modifiersSourceStart = from.modifiersSourceStart;
622
 
                to.needFreeReturn = from.needFreeReturn;
623
642
                to.returnType = from.returnType;
624
643
                to.scope = from.scope;
625
644
                to.selector = from.selector;
629
648
                to.thrownExceptions = from.thrownExceptions;
630
649
                to.typeParameters = from.typeParameters;
631
650
        }
632
 
        
 
651
 
633
652
        private void swap(TypeDeclaration inType, MethodDeclaration thisDeclaration, MethodDeclaration forThatDeclaration) {
634
653
                for (int i = 0; i < inType.methods.length; i++) {
635
 
                        if (inType.methods[i]  == thisDeclaration) {
 
654
                        if (inType.methods[i] == thisDeclaration) {
636
655
                                inType.methods[i] = forThatDeclaration;
637
656
                                break;
638
657
                        }
639
658
                }
640
659
        }
641
 
        
 
660
 
642
661
        private static class AspectJAnnotations {
643
662
                boolean hasAdviceAnnotation = false;
644
663
                boolean hasPointcutAnnotation = false;
648
667
                boolean hasMultipleAdviceAnnotations = false;
649
668
                boolean hasMultiplePointcutAnnotations = false;
650
669
                boolean hasMultipleAspectAnnotations = false;
651
 
                
 
670
 
652
671
                AdviceKind adviceKind = null;
653
672
                Annotation adviceAnnotation = null;
654
673
                Annotation pointcutAnnotation = null;
658
677
                Annotation duplicateAdviceAnnotation = null;
659
678
                Annotation duplicatePointcutAnnotation = null;
660
679
                Annotation duplicateAspectAnnotation = null;
661
 
                
 
680
 
662
681
                public AspectJAnnotations(Annotation[] annotations) {
663
 
                        if (annotations == null) return;
 
682
                        if (annotations == null)
 
683
                                return;
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];
692
713
                                                hasAspectAnnotation = true;
693
714
                                                aspectAnnotation = annotations[i];
694
715
                                        }
695
 
                                } else if (CharOperation.equals(pointcutSig,sig)) {
 
716
                                } else if (CharOperation.equals(pointcutSig, sig)) {
696
717
                                        if (hasPointcutAnnotation) {
697
718
                                                hasMultiplePointcutAnnotations = true;
698
719
                                                duplicatePointcutAnnotation = annotations[i];
700
721
                                                hasPointcutAnnotation = true;
701
722
                                                pointcutAnnotation = annotations[i];
702
723
                                        }
703
 
                                        
 
724
 
704
725
                                }
705
726
                        }
706
727
                }
707
 
                
 
728
 
708
729
                public boolean hasAspectJAnnotations() {
709
730
                        return hasAdviceAnnotation || hasPointcutAnnotation || hasAdviceNameAnnotation || hasAspectAnnotation;
710
731
                }
719
740
                        }
720
741
                }
721
742
        }
722
 
        
 
743
 
723
744
        private static class HasIfPCDVisitor extends AbstractPatternNodeVisitor {
724
745
                public boolean containsIfPcd = false;
725
 
                
 
746
 
726
747
                public Object visit(IfPointcut node, Object data) {
727
748
                        containsIfPcd = true;
728
749
                        return data;