]> source.dussan.org Git - aspectj.git/blob
49c80e318cbaea08790af2ae308f1457a0929dc9
[aspectj.git] /
1 /* *******************************************************************
2  * Copyright (c) 2002,2010 Contributors
3  * All rights reserved.
4  * This program and the accompanying materials are made available
5  * under the terms of the Eclipse Public License v 2.0
6  * which accompanies this distribution and is available at
7  * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
8  *
9  * Contributors:
10  *     PARC                 initial implementation
11  *     Alexandre Vasseur    support for @AJ perClause
12  * ******************************************************************/
13
14 package org.aspectj.ajdt.internal.compiler.lookup;
15
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.List;
20
21 import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
22 import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
23 import org.aspectj.ajdt.internal.compiler.ast.DeclareAnnotationDeclaration;
24 import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
25 import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
26 import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
27 import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext;
28 import org.aspectj.bridge.IMessage;
29 import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
30 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
31 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
32 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
33 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
34 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
35 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
36 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
37 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
38 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Literal;
39 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
40 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
41 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NameReference;
42 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
43 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
44 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
45 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
46 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
47 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
48 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
49 import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
50 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
51 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
52 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
53 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
54 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
55 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
56 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
57 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
58 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
59 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
60 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
61 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
62 import org.aspectj.weaver.AbstractReferenceTypeDelegate;
63 import org.aspectj.weaver.AnnotationAJ;
64 import org.aspectj.weaver.AnnotationAnnotationValue;
65 import org.aspectj.weaver.AnnotationNameValuePair;
66 import org.aspectj.weaver.AnnotationTargetKind;
67 import org.aspectj.weaver.AnnotationValue;
68 import org.aspectj.weaver.ArrayAnnotationValue;
69 import org.aspectj.weaver.BCException;
70 import org.aspectj.weaver.ClassAnnotationValue;
71 import org.aspectj.weaver.EnumAnnotationValue;
72 import org.aspectj.weaver.ReferenceType;
73 import org.aspectj.weaver.ResolvedMember;
74 import org.aspectj.weaver.ResolvedPointcutDefinition;
75 import org.aspectj.weaver.ResolvedType;
76 import org.aspectj.weaver.StandardAnnotation;
77 import org.aspectj.weaver.TypeVariable;
78 import org.aspectj.weaver.UnresolvedType;
79 import org.aspectj.weaver.WeaverStateInfo;
80 import org.aspectj.weaver.World;
81 import org.aspectj.weaver.bcel.AtAjAttributes.LazyResolvedPointcutDefinition;
82 import org.aspectj.weaver.patterns.Declare;
83 import org.aspectj.weaver.patterns.FormalBinding;
84 import org.aspectj.weaver.patterns.ParserException;
85 import org.aspectj.weaver.patterns.PatternParser;
86 import org.aspectj.weaver.patterns.PerClause;
87 import org.aspectj.weaver.patterns.PerFromSuper;
88 import org.aspectj.weaver.patterns.PerSingleton;
89 import org.aspectj.weaver.patterns.Pointcut;
90
91 /**
92  * Supports viewing eclipse TypeDeclarations/SourceTypeBindings as a ResolvedType
93  *
94  * @author Jim Hugunin
95  * @author Andy Clement
96  */
97 public class EclipseSourceType extends AbstractReferenceTypeDelegate {
98         private static final char[] pointcutSig = "Lorg/aspectj/lang/annotation/Pointcut;".toCharArray();
99         private static final char[] aspectSig = "Lorg/aspectj/lang/annotation/Aspect;".toCharArray();
100         protected ResolvedPointcutDefinition[] declaredPointcuts = null;
101         protected ResolvedMember[] declaredMethods = null;
102         protected ResolvedMember[] declaredFields = null;
103
104         public List<Declare> declares = new ArrayList<>();
105         public List<EclipseTypeMunger> typeMungers = new ArrayList<>();
106
107         private final EclipseFactory factory;
108
109         private final SourceTypeBinding binding;
110         private final TypeDeclaration declaration;
111         private final CompilationUnitDeclaration unit;
112         private boolean annotationsFullyResolved = false;
113         private boolean annotationTypesAreResolved = false;
114         private ResolvedType[] annotationTypes = null;
115
116         private boolean discoveredAnnotationTargetKinds = false;
117         private AnnotationTargetKind[] annotationTargetKinds;
118         private AnnotationAJ[] annotations = null;
119
120         protected EclipseFactory eclipseWorld() {
121                 return factory;
122         }
123
124         public EclipseSourceType(ReferenceType resolvedTypeX, EclipseFactory factory, SourceTypeBinding binding,
125                         TypeDeclaration declaration, CompilationUnitDeclaration unit) {
126                 super(resolvedTypeX, true);
127                 this.factory = factory;
128                 this.binding = binding;
129                 this.declaration = declaration;
130                 this.unit = unit;
131
132                 setSourceContext(new EclipseSourceContext(declaration.compilationResult));
133                 resolvedTypeX.setStartPos(declaration.sourceStart);
134                 resolvedTypeX.setEndPos(declaration.sourceEnd);
135         }
136
137         @Override
138         public boolean isAspect() {
139                 final boolean isCodeStyle = declaration instanceof AspectDeclaration;
140                 return isCodeStyle ? isCodeStyle : isAnnotationStyleAspect();
141         }
142
143         @Override
144         public boolean isAnonymous() {
145                 if (declaration.binding != null) {
146                         return declaration.binding.isAnonymousType();
147                 }
148                 return ((declaration.modifiers & (ASTNode.IsAnonymousType | ASTNode.IsLocalType)) != 0);
149         }
150
151         @Override
152         public boolean isNested() {
153                 if (declaration.binding != null) {
154                         return (declaration.binding.isMemberType());
155                 }
156                 return ((declaration.modifiers & ASTNode.IsMemberType) != 0);
157         }
158
159         @Override
160         public ResolvedType getOuterClass() {
161                 if (declaration.binding != null) {
162                         ReferenceBinding enclosingType = declaration.binding.enclosingType();
163                         return enclosingType==null?null:eclipseWorld().fromEclipse(enclosingType);
164                 }
165                 // TODO are we going to make a mistake here if the binding is null?
166                 // Do we ever get asked when the binding is null
167                 if (declaration.enclosingType == null) {
168                         return null;
169                 }
170                 return eclipseWorld().fromEclipse(declaration.enclosingType.binding);
171         }
172
173         @Override
174         public boolean isAnnotationStyleAspect() {
175                 if (declaration.annotations == null) {
176                         return false;
177                 }
178                 ResolvedType[] annotations = getAnnotationTypes();
179                 for (ResolvedType annotation : annotations) {
180                         if ("org.aspectj.lang.annotation.Aspect".equals(annotation.getName())) {
181                                 return true;
182                         }
183                 }
184                 return false;
185         }
186
187         /** Returns "" if there is a problem */
188         private String getPointcutStringFromAnnotationStylePointcut(AbstractMethodDeclaration amd) {
189                 Annotation[] ans = amd.annotations;
190                 if (ans == null) {
191                         return "";
192                 }
193                 for (Annotation an : ans) {
194                         if (an.resolvedType == null) {
195                                 continue; // XXX happens if we do this very early from
196                         }
197                         // buildInterTypeandPerClause
198                         // may prevent us from resolving references made in @Pointcuts to
199                         // an @Pointcut in a code-style aspect
200                         char[] sig = an.resolvedType.signature();
201                         if (CharOperation.equals(pointcutSig, sig)) {
202                                 if (an.memberValuePairs().length == 0) {
203                                         return ""; // empty pointcut expression
204                                 }
205                                 Expression expr = an.memberValuePairs()[0].value;
206                                 if (expr instanceof StringLiteral) {
207                                         StringLiteral sLit = ((StringLiteral) expr);
208                                         return new String(sLit.source());
209                                 } else if (expr instanceof NameReference && (((NameReference) expr).binding instanceof FieldBinding)) {
210                                         Binding b = ((NameReference) expr).binding;
211                                         Constant c = ((FieldBinding) b).constant();
212                                         return c.stringValue();
213                                 } else {
214                                         throw new BCException("Do not know how to recover pointcut definition from " + expr + " (type "
215                                                         + expr.getClass().getName() + ")");
216                                 }
217                         }
218                 }
219                 return "";
220         }
221
222         private boolean isAnnotationStylePointcut(Annotation[] annotations) {
223                 if (annotations == null) {
224                         return false;
225                 }
226                 for (Annotation annotation : annotations) {
227                         if (annotation.resolvedType == null) {
228                                 continue; // XXX happens if we do this very early from
229                         }
230                         // buildInterTypeandPerClause
231                         // may prevent us from resolving references made in @Pointcuts to
232                         // an @Pointcut in a code-style aspect
233                         char[] sig = annotation.resolvedType.signature();
234                         if (CharOperation.equals(pointcutSig, sig)) {
235                                 return true;
236                         }
237                 }
238                 return false;
239         }
240
241         @Override
242         public WeaverStateInfo getWeaverState() {
243                 return null;
244         }
245
246         @Override
247         public ResolvedType getSuperclass() {
248                 if (binding.isInterface()) {
249                         return getResolvedTypeX().getWorld().getCoreType(UnresolvedType.OBJECT);
250                 }
251                 // XXX what about java.lang.Object
252                 return eclipseWorld().fromEclipse(binding.superclass());
253         }
254
255         @Override
256         public ResolvedType[] getDeclaredInterfaces() {
257                 return eclipseWorld().fromEclipse(binding.superInterfaces());
258         }
259
260         protected void fillDeclaredMembers() {
261                 List<ResolvedMember> declaredPointcuts = new ArrayList<>();
262                 List<ResolvedMember> declaredMethods = new ArrayList<>();
263                 List<ResolvedMember> declaredFields = new ArrayList<>();
264
265                 MethodBinding[] ms = binding.methods(); // the important side-effect of this call is to make
266                 // sure bindings are completed
267                 AbstractMethodDeclaration[] methods = declaration.methods;
268                 if (methods != null) {
269                         for (AbstractMethodDeclaration amd : methods) {
270                                 if (amd == null || amd.ignoreFurtherInvestigation) {
271                                         continue;
272                                 }
273                                 if (amd instanceof PointcutDeclaration) {
274                                         PointcutDeclaration d = (PointcutDeclaration) amd;
275                                         ResolvedPointcutDefinition df = d.makeResolvedPointcutDefinition(factory);
276                                         if (df != null) {
277                                                 declaredPointcuts.add(df);
278                                         }
279                                 } else if (amd instanceof InterTypeDeclaration) {
280                                         // these are handled in a separate pass
281                                         continue;
282                                 } else if (amd instanceof DeclareDeclaration && !(amd instanceof DeclareAnnotationDeclaration)) { // surfaces
283                                         // the
284                                         // annotated
285                                         // ajc$ method
286                                         // these are handled in a separate pass
287                                         continue;
288                                 } else if (amd instanceof AdviceDeclaration) {
289                                         // these are ignored during compilation and only used during
290                                         // weaving
291                                         continue;
292                                 } else if ((amd.annotations != null) && isAnnotationStylePointcut(amd.annotations)) {
293                                         // consider pointcuts defined via annotations
294                                         ResolvedPointcutDefinition df = makeResolvedPointcutDefinition(amd);
295                                         if (df != null) {
296                                                 declaredPointcuts.add(df);
297                                         }
298                                 } else {
299                                         if (amd.binding == null || !amd.binding.isValidBinding()) {
300                                                 continue;
301                                         }
302                                         ResolvedMember member = factory.makeResolvedMember(amd.binding);
303                                         if (unit != null) {
304                                                 boolean positionKnown = true;
305                                                 if (amd.binding.sourceMethod() == null) {
306                                                         if (amd.binding.declaringClass instanceof SourceTypeBinding) {
307                                                                 SourceTypeBinding stb = ((SourceTypeBinding) amd.binding.declaringClass);
308                                                                 if (stb.scope == null || stb.scope.referenceContext == null) {
309                                                                         positionKnown = false;
310                                                                 }
311                                                         }
312                                                 }
313                                                 if (positionKnown) { // pr229829
314                                                         member.setSourceContext(new EclipseSourceContext(unit.compilationResult, amd.binding.sourceStart()));
315                                                         member.setPosition(amd.binding.sourceStart(), amd.binding.sourceEnd());
316                                                 } else {
317                                                         member.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
318                                                         member.setPosition(0, 0);
319                                                 }
320                                         }
321                                         declaredMethods.add(member);
322                                 }
323                         }
324                 }
325
326                 if (isEnum()) {
327                         // The bindings for the eclipse binding will include values/valueof
328                         for (MethodBinding mb : ms) {
329                                 if ((mb instanceof SyntheticMethodBinding) && mb.isStatic()) { // cannot use .isSynthetic() because it isn't truly synthetic
330                                         if (CharOperation.equals(mb.selector, valuesCharArray) && mb.parameters.length == 0 && mb.returnType.isArrayType() && ((ArrayBinding) mb.returnType).leafComponentType() == binding) {
331                                                 // static <EnumType>[] values()
332                                                 ResolvedMember valuesMember = factory.makeResolvedMember(mb);
333                                                 valuesMember.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
334                                                 valuesMember.setPosition(0, 0);
335                                                 declaredMethods.add(valuesMember);
336                                         } else if (CharOperation.equals(mb.selector, valueOfCharArray) && mb.parameters.length == 1 && CharOperation.equals(mb.parameters[0].signature(), jlString) && mb.returnType == binding) {
337                                                 // static <EnumType> valueOf(String)
338                                                 ResolvedMember valueOfMember = factory.makeResolvedMember(mb);
339                                                 valueOfMember.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
340                                                 valueOfMember.setPosition(0, 0);
341                                                 declaredMethods.add(valueOfMember);
342                                         }
343                                 }
344                         }
345                 }
346
347                 FieldBinding[] fields = binding.fields();
348                 for (FieldBinding f : fields) {
349                         declaredFields.add(factory.makeResolvedMember(f));
350                 }
351
352                 this.declaredPointcuts = declaredPointcuts.toArray(new ResolvedPointcutDefinition[0]);
353                 this.declaredMethods = declaredMethods.toArray(new ResolvedMember[0]);
354                 this.declaredFields = declaredFields.toArray(new ResolvedMember[0]);
355         }
356
357         private final static char[] valuesCharArray = "values".toCharArray();
358         private final static char[] valueOfCharArray = "valueOf".toCharArray();
359         private final static char[] jlString = "Ljava/lang/String;".toCharArray();
360
361
362         private ResolvedPointcutDefinition makeResolvedPointcutDefinition(AbstractMethodDeclaration md) {
363                 if (md.binding == null) {
364                         return null; // there is another error that has caused this...
365                         // pr138143
366                 }
367
368                 EclipseSourceContext eSourceContext = new EclipseSourceContext(md.compilationResult);
369                 Pointcut pc = null;
370                 if (!md.isAbstract()) {
371                         String expression = getPointcutStringFromAnnotationStylePointcut(md);
372                         try {
373                                 pc = new PatternParser(expression, eSourceContext).parsePointcut();
374                         } catch (ParserException pe) { // error will be reported by other
375                                 // means...
376                                 pc = Pointcut.makeMatchesNothing(Pointcut.SYMBOLIC);
377                         }
378                 }
379
380                 FormalBinding[] bindings = buildFormalAdviceBindingsFrom(md);
381
382                 ResolvedPointcutDefinition rpd = new LazyResolvedPointcutDefinition(factory.fromBinding(md.binding.declaringClass),
383                                 md.modifiers, new String(md.selector), factory.fromBindings(md.binding.parameters),
384                                 factory.fromBinding(md.binding.returnType), pc, new EclipseScope(bindings, md.scope));
385
386                 rpd.setPosition(md.sourceStart, md.sourceEnd);
387                 rpd.setSourceContext(eSourceContext);
388                 return rpd;
389         }
390
391         private static final char[] joinPoint = "Lorg/aspectj/lang/JoinPoint;".toCharArray();
392         private static final char[] joinPointStaticPart = "Lorg/aspectj/lang/JoinPoint$StaticPart;".toCharArray();
393         private static final char[] joinPointEnclosingStaticPart = "Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;".toCharArray();
394         private static final char[] proceedingJoinPoint = "Lorg/aspectj/lang/ProceedingJoinPoint;".toCharArray();
395
396         private FormalBinding[] buildFormalAdviceBindingsFrom(AbstractMethodDeclaration mDecl) {
397                 if (mDecl.arguments == null) {
398                         return new FormalBinding[0];
399                 }
400                 if (mDecl.binding == null) {
401                         return new FormalBinding[0];
402                 }
403                 EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(mDecl.scope);
404                 String extraArgName = "";// maybeGetExtraArgName();
405                 FormalBinding[] ret = new FormalBinding[mDecl.arguments.length];
406                 for (int i = 0; i < mDecl.arguments.length; i++) {
407                         Argument arg = mDecl.arguments[i];
408                         String name = new String(arg.name);
409                         TypeBinding argTypeBinding = mDecl.binding.parameters[i];
410                         UnresolvedType type = factory.fromBinding(argTypeBinding);
411                         if (CharOperation.equals(joinPoint, argTypeBinding.signature())
412                                         || CharOperation.equals(joinPointStaticPart, argTypeBinding.signature())
413                                         || CharOperation.equals(joinPointEnclosingStaticPart, argTypeBinding.signature())
414                                         || CharOperation.equals(proceedingJoinPoint, argTypeBinding.signature()) || name.equals(extraArgName)) {
415                                 ret[i] = new FormalBinding.ImplicitFormalBinding(type, name, i);
416                         } else {
417                                 ret[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd);
418                         }
419                 }
420                 return ret;
421         }
422
423         /**
424          * This method may not return all fields, for example it may not include the ajc$initFailureCause or ajc$perSingletonInstance
425          * fields - see bug 129613
426          */
427         @Override
428         public ResolvedMember[] getDeclaredFields() {
429                 if (declaredFields == null) {
430                         fillDeclaredMembers();
431                 }
432                 return declaredFields;
433         }
434
435         /**
436          * This method may not return all methods, for example it may not include clinit, aspectOf, hasAspect or ajc$postClinit methods
437          * - see bug 129613
438          */
439         @Override
440         public ResolvedMember[] getDeclaredMethods() {
441                 if (declaredMethods == null) {
442                         fillDeclaredMembers();
443                 }
444                 return declaredMethods;
445         }
446
447         @Override
448         public ResolvedMember[] getDeclaredPointcuts() {
449                 if (declaredPointcuts == null) {
450                         fillDeclaredMembers();
451                 }
452                 return declaredPointcuts;
453         }
454
455         @Override
456         public int getModifiers() {
457                 // only return the real Java modifiers, not the extra eclipse ones
458                 return binding.modifiers & ExtraCompilerModifiers.AccJustFlag;
459         }
460
461         @Override
462         public String toString() {
463                 return "EclipseSourceType(" + new String(binding.sourceName()) + ")";
464         }
465
466         // XXX make sure this is applied to classes and interfaces
467         public void checkPointcutDeclarations() {
468                 ResolvedMember[] pointcuts = getDeclaredPointcuts();
469                 boolean sawError = false;
470                 for (int i = 0, len = pointcuts.length; i < len; i++) {
471                         if (pointcuts[i] == null) {
472                                 // Something else is broken in this file and will be reported separately
473                                 continue;
474                         }
475                         if (pointcuts[i].isAbstract()) {
476                                 if (!this.isAspect()) {
477                                         eclipseWorld().showMessage(IMessage.ERROR, "The abstract pointcut " + pointcuts[i].getName()+ " can only be defined in an aspect",
478                                                         pointcuts[i].getSourceLocation(), null);
479                                         sawError = true;
480                                 } else if (!binding.isAbstract()) {
481                                         eclipseWorld().showMessage(IMessage.ERROR, "abstract pointcut in concrete aspect: " + pointcuts[i],
482                                                         pointcuts[i].getSourceLocation(), null);
483                                         sawError = true;
484                                 }
485                         }
486
487                         for (int j = i + 1; j < len; j++) {
488                                 if (pointcuts[j] == null) {
489                                         // Something else is broken in this file and will be reported separately
490                                         continue;
491                                 }
492                                 if (pointcuts[i].getName().equals(pointcuts[j].getName())) {
493                                         eclipseWorld().showMessage(IMessage.ERROR, "duplicate pointcut name: " + pointcuts[j].getName(),
494                                                         pointcuts[i].getSourceLocation(), pointcuts[j].getSourceLocation());
495                                         sawError = true;
496                                 }
497                         }
498                 }
499
500                 // now check all inherited pointcuts to be sure that they're handled
501                 // reasonably
502                 if (sawError || !isAspect()) {
503                         return;
504                 }
505
506                 // find all pointcuts that override ones from super and check override
507                 // is legal
508                 // i.e. same signatures and greater or equal visibility
509                 // find all inherited abstract pointcuts and make sure they're
510                 // concretized if I'm concrete
511                 // find all inherited pointcuts and make sure they don't conflict
512                 getResolvedTypeX().getExposedPointcuts(); // ??? this is an odd
513                 // construction
514
515         }
516
517         // ???
518         // public CrosscuttingMembers collectCrosscuttingMembers() {
519         // return crosscuttingMembers;
520         // }
521
522         // public ISourceLocation getSourceLocation() {
523         // TypeDeclaration dec = binding.scope.referenceContext;
524         // return new EclipseSourceLocation(dec.compilationResult, dec.sourceStart,
525         // dec.sourceEnd);
526         // }
527
528         @Override
529         public boolean isInterface() {
530                 return binding.isInterface();
531         }
532
533         // XXXAJ5: Should be constants in the eclipse compiler somewhere, once it
534         // supports 1.5
535         public final static short ACC_ANNOTATION = 0x2000;
536         public final static short ACC_ENUM = 0x4000;
537
538         @Override
539         public boolean isEnum() {
540                 return (binding.getAccessFlags() & ACC_ENUM) != 0;
541         }
542
543         @Override
544         public boolean isAnnotation() {
545                 return (binding.getAccessFlags() & ACC_ANNOTATION) != 0;
546         }
547
548         @Override
549         public boolean isAnnotationWithRuntimeRetention() {
550                 if (!isAnnotation()) {
551                         return false;
552                 } else {
553                         return (binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
554                 }
555         }
556
557         @Override
558         public String getRetentionPolicy() {
559                 if (isAnnotation()) {
560                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention) {
561                                 return "RUNTIME";
562                         }
563                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationSourceRetention) {
564                                 return "SOURCE";
565                         }
566                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention) {
567                                 return "CLASS";
568                         }
569                 }
570                 return null;
571         }
572
573         @Override
574         public boolean canAnnotationTargetType() {
575                 if (isAnnotation()) {
576                         return ((binding.getAnnotationTagBits() & TagBits.AnnotationForType) != 0);
577                 }
578                 return false;
579         }
580
581         @Override
582         public AnnotationTargetKind[] getAnnotationTargetKinds() {
583                 if (discoveredAnnotationTargetKinds) {
584                         return annotationTargetKinds;
585                 }
586                 discoveredAnnotationTargetKinds = true;
587                 annotationTargetKinds = null; // null means we have no idea or the
588                 // @Target annotation hasn't been used
589                 // if (isAnnotation()) {
590                 // Annotation[] annotationsOnThisType = declaration.annotations;
591                 // if (annotationsOnThisType != null) {
592                 // for (int i = 0; i < annotationsOnThisType.length; i++) {
593                 // Annotation a = annotationsOnThisType[i];
594                 // if (a.resolvedType != null) {
595                 // String packageName = new
596                 // String(a.resolvedType.qualifiedPackageName()).concat(".");
597                 // String sourceName = new String(a.resolvedType.qualifiedSourceName());
598                 // if ((packageName +
599                 // sourceName).equals(UnresolvedType.AT_TARGET.getName())) {
600                 // MemberValuePair[] pairs = a.memberValuePairs();
601                 // for (int j = 0; j < pairs.length; j++) {
602                 // MemberValuePair pair = pairs[j];
603                 // targetKind = pair.value.toString();
604                 // return targetKind;
605                 // }
606                 // }
607                 // }
608                 // }
609                 // }
610                 // }
611                 // return targetKind;
612                 if (isAnnotation()) {
613                         List<AnnotationTargetKind> targetKinds = new ArrayList<>();
614
615                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationForAnnotationType) != 0) {
616                                 targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE);
617                         }
618                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationForConstructor) != 0) {
619                                 targetKinds.add(AnnotationTargetKind.CONSTRUCTOR);
620                         }
621                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationForField) != 0) {
622                                 targetKinds.add(AnnotationTargetKind.FIELD);
623                         }
624                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationForLocalVariable) != 0) {
625                                 targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE);
626                         }
627                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationForMethod) != 0) {
628                                 targetKinds.add(AnnotationTargetKind.METHOD);
629                         }
630                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationForPackage) != 0) {
631                                 targetKinds.add(AnnotationTargetKind.PACKAGE);
632                         }
633                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationForParameter) != 0) {
634                                 targetKinds.add(AnnotationTargetKind.PARAMETER);
635                         }
636                         if ((binding.getAnnotationTagBits() & TagBits.AnnotationForType) != 0) {
637                                 targetKinds.add(AnnotationTargetKind.TYPE);
638                         }
639
640                         if (!targetKinds.isEmpty()) {
641                                 annotationTargetKinds = new AnnotationTargetKind[targetKinds.size()];
642                                 return targetKinds.toArray(annotationTargetKinds);
643                         }
644                 }
645                 return annotationTargetKinds;
646         }
647
648         /**
649          * Ensure the annotation types have been resolved, where resolved means the eclipse type bindings have been converted to their
650          * ResolvedType representations. This does not deeply resolve the annotations, it only does the type names.
651          */
652         private void ensureAnnotationTypesResolved() {
653                 // may need to re-resolve if new annotations have been added
654                 int declarationAnnoCount = (declaration.annotations == null ? 0 : declaration.annotations.length);
655                 if (!annotationTypesAreResolved || declarationAnnoCount != annotationTypes.length) {
656                         Annotation[] as = declaration.annotations;
657                         if (as == null) {
658                                 annotationTypes = ResolvedType.NONE;
659                         } else {
660                                 annotationTypes = new ResolvedType[as.length];
661                                 for (int a = 0; a < as.length; a++) {
662                                         TypeBinding tb = as[a].type.resolveType(declaration.staticInitializerScope);
663                                         if (tb == null) {
664                                                 annotationTypes[a] = ResolvedType.MISSING;
665                                         } else {
666                                                 annotationTypes[a] = factory.fromTypeBindingToRTX(tb);
667                                         }
668                                 }
669                         }
670                         annotationTypesAreResolved = true;
671                 }
672         }
673
674         @Override
675         public boolean hasAnnotation(UnresolvedType ofType) {
676                 ensureAnnotationTypesResolved();
677                 for (ResolvedType annotationType : annotationTypes) {
678                         if (ofType.equals(annotationType)) {
679                                 return true;
680                         }
681                 }
682                 return false;
683         }
684
685         /**
686          * WARNING: This method does not have a complete implementation.
687          *
688          * The aim is that it converts Eclipse annotation objects to the AspectJ form of annotations (the type AnnotationAJ). The
689          * AnnotationX objects returned are wrappers over either a Bcel annotation type or the AspectJ AnnotationAJ type. The minimal
690          * implementation provided here is for processing the RetentionPolicy and Target annotation types - these are the only ones
691          * which the weaver will attempt to process from an EclipseSourceType.
692          *
693          * More notes: The pipeline has required us to implement this. With the pipeline we can be weaving a type and asking questions
694          * of annotations before they have been turned into Bcel objects - ie. when they are still in EclipseSourceType form. Without
695          * the pipeline we would have converted everything to Bcel objects before proceeding with weaving. Because the pipeline won't
696          * start weaving until all aspects have been compiled and the fact that no AspectJ constructs match on the values within
697          * annotations, this code only needs to deal with converting system annotations that the weaver needs to process
698          * (RetentionPolicy, Target).
699          */
700         @Override
701         public AnnotationAJ[] getAnnotations() {
702                 int declarationAnnoCount = (declaration.annotations == null ? 0 : declaration.annotations.length);
703                 if (annotations != null && annotations.length == declarationAnnoCount) {
704                         return annotations; // only do this once
705                 }
706                 if (!annotationsFullyResolved || annotations.length!=declarationAnnoCount) {
707                         TypeDeclaration.resolveAnnotations(declaration.staticInitializerScope, declaration.annotations, binding);
708                         annotationsFullyResolved = true;
709                 }
710                 Annotation[] as = declaration.annotations;
711                 if (as == null || as.length == 0) {
712                         annotations = AnnotationAJ.EMPTY_ARRAY;
713                 } else {
714                         annotations = new AnnotationAJ[as.length];
715                         for (int i = 0; i < as.length; i++) {
716                                 annotations[i] = convertEclipseAnnotation(as[i], factory.getWorld());
717                         }
718                 }
719                 return annotations;
720         }
721
722         @Override
723         public boolean hasAnnotations() {
724                 return (declaration.annotations != null && declaration.annotations.length != 0);
725         }
726
727         /**
728          * Convert one eclipse annotation into an AnnotationX object containing an AnnotationAJ object.
729          *
730          * This code and the helper methods used by it will go *BANG* if they encounter anything not currently supported - this is safer
731          * than limping along with a malformed annotation. When the *BANG* is encountered the bug reporter should indicate the kind of
732          * annotation they were working with and this code can be enhanced to support it.
733          */
734         public AnnotationAJ convertEclipseAnnotation(Annotation eclipseAnnotation, World w) {
735                 // TODO if it is sourcevisible, we shouldn't let it through!!!!!!!!!
736                 // testcase!
737                 ResolvedType annotationType = factory.fromTypeBindingToRTX(eclipseAnnotation.type.resolvedType);
738                 // long bs = (eclipseAnnotation.bits & TagBits.AnnotationRetentionMASK);
739                 boolean isRuntimeVisible = (eclipseAnnotation.bits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
740                 StandardAnnotation annotationAJ = new StandardAnnotation(annotationType, isRuntimeVisible);
741                 generateAnnotation(eclipseAnnotation, annotationAJ, w);
742                 return annotationAJ;
743         }
744
745         static class MissingImplementationException extends RuntimeException {
746                 MissingImplementationException(String reason) {
747                         super(reason);
748                 }
749         }
750
751         /**
752          * Use the information in the supplied eclipse based annotation to fill in the standard annotation.
753          *
754          * @param annotation eclipse based annotation representation
755          * @param annotationAJ AspectJ based annotation representation
756          */
757         private void generateAnnotation(Annotation annotation, StandardAnnotation annotationAJ, World w) {
758                 if (annotation instanceof NormalAnnotation) {
759                         NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
760                         MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
761                         if (memberValuePairs != null) {
762                                 int memberValuePairsLength = memberValuePairs.length;
763                                 for (MemberValuePair memberValuePair : memberValuePairs) {
764                                         MethodBinding methodBinding = memberValuePair.binding;
765                                         if (methodBinding == null) {
766                                                 // is this just a marker annotation?
767                                                 if (memberValuePair.value instanceof MarkerAnnotation) {
768                                                         MarkerAnnotation eMarkerAnnotation = (MarkerAnnotation) memberValuePair.value;
769                                                         AnnotationBinding eMarkerAnnotationBinding = eMarkerAnnotation.getCompilerAnnotation();
770                                                         ReferenceBinding eAnnotationType = eMarkerAnnotationBinding.getAnnotationType();
771                                                         ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(eAnnotationType);
772                                                         boolean isRuntimeVisible = (eMarkerAnnotation.bits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
773                                                         StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType, isRuntimeVisible);
774                                                         AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
775                                                         AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
776                                                         annotationAJ.addNameValuePair(anvp);
777                                                         // } else if (memberValuePair.value instanceof NormalAnnotation) {
778                                                         // NormalAnnotation eNormalAnnotation = (NormalAnnotation) memberValuePair.value;
779                                                         // AnnotationBinding eMarkerAnnotationBinding = eNormalAnnotation.getCompilerAnnotation();
780                                                         // ReferenceBinding eAnnotationType = eMarkerAnnotationBinding.getAnnotationType();
781                                                         // ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(eAnnotationType);
782                                                         // boolean isRuntimeVisible = (eNormalAnnotation.bits & TagBits.AnnotationRetentionMASK) ==
783                                                         // TagBits.AnnotationRuntimeRetention;
784                                                         // StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType, isRuntimeVisible);
785                                                         // MemberValuePair[] pairs = eNormalAnnotation.memberValuePairs;
786                                                         // if (pairs != null) {
787                                                         // for (int p = 0; p < pairs.length; p++) {
788                                                         // MemberValuePair pair = pairs[p];
789                                                         // throw new IllegalStateException("nyi");
790                                                         //
791                                                         // }
792                                                         // }
793                                                         // AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
794                                                         // AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
795                                                         // annotationAJ.addNameValuePair(anvp);
796                                                 } else if (memberValuePair.value instanceof Literal) {
797                                                         AnnotationValue av = generateElementValue(memberValuePair.value,
798                                                                         ((Literal) memberValuePair.value).resolvedType);
799                                                         AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
800                                                         annotationAJ.addNameValuePair(anvp);
801                                                 } else if (memberValuePair.value instanceof ArrayInitializer) {
802                                                         ArrayInitializer arrayInitializer = (ArrayInitializer) memberValuePair.value;
803                                                         Expression[] expressions = arrayInitializer.expressions;
804                                                         AnnotationValue[] arrayValues = new AnnotationValue[expressions.length];
805                                                         for (int e = 0; e < expressions.length; e++) {
806                                                                 arrayValues[e] = generateElementValue(expressions[e],
807                                                                                 ((ArrayBinding) arrayInitializer.resolvedType).leafComponentType);
808                                                         }
809                                                         AnnotationValue array = new ArrayAnnotationValue(arrayValues);
810                                                         AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), array);
811                                                         annotationAJ.addNameValuePair(anvp);
812                                                 } else {
813                                                         throw new MissingImplementationException(
814                                                                         "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation ["
815                                                                                         + annotation + "]");
816                                                 }
817                                         } else {
818                                                 AnnotationValue av = generateElementValue(memberValuePair.value, methodBinding.returnType);
819                                                 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
820                                                 annotationAJ.addNameValuePair(anvp);
821                                         }
822                                 }
823                         }
824                 } else if (annotation instanceof SingleMemberAnnotation) {
825                         // this is a single member annotation (one member value)
826                         SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
827                         MemberValuePair mvp = singleMemberAnnotation.memberValuePairs()[0];
828                         if (mvp.value instanceof ArrayInitializer) {
829                                 ArrayInitializer arrayInitializer = (ArrayInitializer) mvp.value;
830                                 Expression[] expressions = arrayInitializer.expressions;
831                                 AnnotationValue[] arrayValues = new AnnotationValue[expressions.length];
832                                 for (int e = 0; e < expressions.length; e++) {
833                                         arrayValues[e] = generateElementValue(expressions[e],
834                                                         ((ArrayBinding) arrayInitializer.resolvedType).leafComponentType);
835                                 }
836                                 AnnotationValue array = new ArrayAnnotationValue(arrayValues);
837                                 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(mvp.name), array);
838                                 annotationAJ.addNameValuePair(anvp);
839                         } else if (mvp.value instanceof Literal) {
840                                 AnnotationValue av = generateElementValue(mvp.value,
841                                                 ((Literal) mvp.value).resolvedType);
842                                 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(mvp.name), av);
843                                 annotationAJ.addNameValuePair(anvp);
844                         } else {
845                                 MethodBinding methodBinding = mvp.binding;
846                                 if (methodBinding == null) {
847                                         throw new MissingImplementationException(
848                                                         "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation [" + annotation + "]");
849                                 } else {
850                                         AnnotationValue av = generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType);
851                                         annotationAJ.addNameValuePair(new AnnotationNameValuePair(new String(
852                                                         singleMemberAnnotation.memberValuePairs()[0].name), av));
853                                 }
854                         }
855                 } else if (annotation instanceof MarkerAnnotation) {
856                         return;
857                 } else {
858                         // this is something else...
859                         throw new MissingImplementationException(
860                                         "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation [" + annotation + "]");
861                 }
862         }
863
864         private AnnotationValue generateElementValue(Expression defaultValue, TypeBinding memberValuePairReturnType) {
865                 Constant constant = defaultValue.constant;
866                 TypeBinding defaultValueBinding = defaultValue.resolvedType;
867                 if (defaultValueBinding == null) {
868                         throw new MissingImplementationException(
869                                         "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value [" + defaultValue
870                                                         + "]");
871                 } else {
872                         if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
873                                 if (constant != null && constant != Constant.NotAConstant) {
874                                         // Testcase for this clause is MultiProjectIncrementalTests.testAnnotations_pr262154()
875                                         AnnotationValue av = EclipseAnnotationConvertor.generateElementValueForConstantExpression(defaultValue,
876                                                         defaultValueBinding);
877                                         return new ArrayAnnotationValue(new AnnotationValue[] { av });
878                                 } else {
879                                         AnnotationValue av = generateElementValueForNonConstantExpression(defaultValue, defaultValueBinding);
880                                         return new ArrayAnnotationValue(new AnnotationValue[] { av });
881                                 }
882                         } else {
883                                 if (constant != null && constant != Constant.NotAConstant) {
884                                         AnnotationValue av = EclipseAnnotationConvertor.generateElementValueForConstantExpression(defaultValue,
885                                                         defaultValueBinding);
886                                         if (av == null) {
887                                                 throw new MissingImplementationException(
888                                                                 "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
889                                                                                 + defaultValue + "]");
890                                         }
891                                         return av;
892                                         // generateElementValue(attributeOffset, defaultValue,
893                                         // constant, memberValuePairReturnType.leafComponentType());
894                                 } else {
895                                         AnnotationValue av = generateElementValueForNonConstantExpression(defaultValue, defaultValueBinding);
896                                         return av;
897                                 }
898                         }
899                 }
900         }
901
902         private AnnotationValue generateElementValueForNonConstantExpression(Expression defaultValue, TypeBinding defaultValueBinding) {
903                 if (defaultValueBinding != null) {
904                         if (defaultValueBinding.isEnum()) {
905                                 FieldBinding fieldBinding = null;
906                                 if (defaultValue instanceof QualifiedNameReference) {
907                                         QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
908                                         fieldBinding = (FieldBinding) nameReference.binding;
909                                 } else if (defaultValue instanceof SingleNameReference) {
910                                         SingleNameReference nameReference = (SingleNameReference) defaultValue;
911                                         fieldBinding = (FieldBinding) nameReference.binding;
912                                 } else {
913                                         throw new MissingImplementationException(
914                                                         "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
915                                                                         + defaultValue + "]");
916                                 }
917                                 if (fieldBinding != null) {
918                                         String sig = new String(fieldBinding.type.signature());
919                                         AnnotationValue enumValue = new EnumAnnotationValue(sig, new String(fieldBinding.name));
920                                         return enumValue;
921                                 }
922                                 throw new MissingImplementationException(
923                                                 "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value [" + defaultValue
924                                                                 + "]");
925                         } else if (defaultValue instanceof ClassLiteralAccess) {
926                                 ClassLiteralAccess cla = (ClassLiteralAccess)defaultValue;
927                                 TypeBinding claTargetType = cla.targetType;
928 //                              ResolvedType classLiteralType = factory.fromTypeBindingToRTX(defaultValueBinding);
929                                 String classLiteralSig = new String(claTargetType.signature());
930                                 AnnotationValue classValue = new ClassAnnotationValue(classLiteralSig);
931                                 return classValue;
932                         } else if (defaultValueBinding.isAnnotationType()) {
933                                 if (defaultValue instanceof MarkerAnnotation) {
934                                         ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(defaultValueBinding);
935                                         StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType,
936                                                         ajAnnotationType.isAnnotationWithRuntimeRetention());
937                                         AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
938                                         return av;
939                                 } else if (defaultValue instanceof NormalAnnotation) {
940                                         NormalAnnotation normalAnnotation = (NormalAnnotation) defaultValue;
941                                         ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(defaultValueBinding);
942                                         StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType,
943                                                         ajAnnotationType.isAnnotationWithRuntimeRetention());
944                                         MemberValuePair[] pairs = normalAnnotation.memberValuePairs;
945                                         if (pairs != null) {
946                                                 for (MemberValuePair pair : pairs) {
947                                                         Expression valueEx = pair.value;
948                                                         AnnotationValue pairValue = null;
949                                                         if (valueEx instanceof Literal) {
950                                                                 pairValue = generateElementValue(valueEx, ((Literal) valueEx).resolvedType);
951                                                         } else {
952                                                                 pairValue = generateElementValue(pair.value, pair.binding.returnType);
953                                                         }
954                                                         ajAnnotation.addNameValuePair(new AnnotationNameValuePair(new String(pair.name), pairValue));
955                                                 }
956                                         }
957                                         AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
958                                         return av;
959                                 } else {
960                                         throw new MissingImplementationException(
961                                                         "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
962                                                                         + defaultValue + "]");
963                                 }
964                         } else if (defaultValueBinding.isArrayType()) {
965                                 // array type
966                                 if (defaultValue instanceof ArrayInitializer) {
967                                         ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
968                                         int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
969                                         AnnotationValue[] values = new AnnotationValue[arrayLength];
970                                         for (int i = 0; i < arrayLength; i++) {
971                                                 values[i] = generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType());// ,
972                                                 // attributeOffset
973                                                 // )
974                                                 // ;
975                                         }
976                                         ArrayAnnotationValue aav = new ArrayAnnotationValue(values);
977                                         return aav;
978                                 } else {
979                                         throw new MissingImplementationException(
980                                                         "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
981                                                                         + defaultValue + "]");
982                                 }
983                                 // } else if (defaultValue instanceof MagicLiteral) {
984                                 // if (defaultValue instanceof FalseLiteral) {
985                                 // new AnnotationValue
986                                 // } else if (defaultValue instanceof TrueLiteral) {
987                                 //
988                                 // } else {
989                                 // throw new MissingImplementationException(
990                                 // "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value ["
991                                 // +defaultValue+"]");
992                                 // }
993                         } else {
994                                 // class type
995                                 throw new MissingImplementationException(
996                                                 "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value [" + defaultValue
997                                                                 + "]");
998                                 // if (contentsOffset + 3 >= this.contents.length) {
999                                 // resizeContents(3);
1000                                 // }
1001                                 // contents[contentsOffset++] = (byte) 'c';
1002                                 // if (defaultValue instanceof ClassLiteralAccess) {
1003                                 // ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess)
1004                                 // defaultValue;
1005                                 // final int classInfoIndex =
1006                                 // constantPool.literalIndex(classLiteralAccess
1007                                 // .targetType.signature());
1008                                 // contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
1009                                 // contents[contentsOffset++] = (byte) classInfoIndex;
1010                                 // } else {
1011                                 // contentsOffset = attributeOffset;
1012                                 // }
1013                         }
1014                 } else {
1015                         throw new MissingImplementationException(
1016                                         "Please raise an AspectJ bug.  AspectJ does not know how to convert this annotation value [" + defaultValue
1017                                                         + "]");
1018                         // contentsOffset = attributeOffset;
1019                 }
1020         }
1021
1022         @Override
1023         public ResolvedType[] getAnnotationTypes() {
1024                 ensureAnnotationTypesResolved();
1025                 return annotationTypes;
1026         }
1027
1028         @Override
1029         public PerClause getPerClause() {
1030                 // should probably be: ((AspectDeclaration)declaration).perClause;
1031                 // but we don't need this level of detail, and working with real per
1032                 // clauses
1033                 // at this stage of compilation is not worth the trouble
1034                 if (!isAnnotationStyleAspect()) {
1035                         if (declaration instanceof AspectDeclaration) {
1036                                 PerClause pc = ((AspectDeclaration) declaration).perClause;
1037                                 if (pc != null) {
1038                                         return pc;
1039                                 }
1040                         }
1041                         return new PerSingleton();
1042                 } else {
1043                         // for @Aspect, we do need the real kind though we don't need the
1044                         // real perClause
1045                         // at least try to get the right perclause
1046                         PerClause pc = null;
1047                         if (declaration instanceof AspectDeclaration) {
1048                                 pc = ((AspectDeclaration) declaration).perClause;
1049                         }
1050                         if (pc == null) {
1051                                 PerClause.Kind kind = getPerClauseForTypeDeclaration(declaration);
1052                                 // returning a perFromSuper is enough to get the correct kind..
1053                                 // (that's really a hack - AV)
1054                                 return new PerFromSuper(kind);
1055                         }
1056                         return pc;
1057                 }
1058         }
1059
1060         PerClause.Kind getPerClauseForTypeDeclaration(TypeDeclaration typeDeclaration) {
1061                 Annotation[] annotations = typeDeclaration.annotations;
1062                 if (annotations == null) {
1063                         // Can happen if an aspect is extending a regular class
1064                         return null;
1065                 }
1066                 for (Annotation annotation : annotations) {
1067                         if (annotation != null && annotation.resolvedType != null
1068                                         && CharOperation.equals(aspectSig, annotation.resolvedType.signature())) {
1069                                 // found @Aspect(...)
1070                                 if (annotation.memberValuePairs() == null || annotation.memberValuePairs().length == 0) {
1071                                         // it is an @Aspect or @Aspect()
1072                                         // needs to use PerFromSuper if declaration extends a super
1073                                         // aspect
1074                                         PerClause.Kind kind = lookupPerClauseKind(typeDeclaration.binding.superclass);
1075                                         // if no super aspect, we have a @Aspect() means singleton
1076                                         if (kind == null) {
1077                                                 return PerClause.SINGLETON;
1078                                         } else {
1079                                                 return kind;
1080                                         }
1081                                 } else if (annotation instanceof SingleMemberAnnotation) {
1082                                         // it is an @Aspect(...something...)
1083                                         SingleMemberAnnotation theAnnotation = (SingleMemberAnnotation) annotation;
1084                                         String clause = new String(((StringLiteral) theAnnotation.memberValue).source());// TODO
1085                                         // cast
1086                                         // safe
1087                                         // ?
1088                                         return determinePerClause(typeDeclaration, clause);
1089                                 } else if (annotation instanceof NormalAnnotation) {
1090                                         // this kind if it was added by the visitor!
1091                                         // it is an @Aspect(...something...)
1092                                         NormalAnnotation theAnnotation = (NormalAnnotation) annotation;
1093                                         if (theAnnotation.memberValuePairs == null || theAnnotation.memberValuePairs.length < 1) {
1094                                                 return PerClause.SINGLETON;
1095                                         }
1096                                         String clause = new String(((StringLiteral) theAnnotation.memberValuePairs[0].value).source());// TODO
1097                                         // cast
1098                                         // safe
1099                                         // ?
1100                                         return determinePerClause(typeDeclaration, clause);
1101                                 } else {
1102                                         eclipseWorld().showMessage(
1103                                                         IMessage.ABORT,
1104                                                         "@Aspect annotation is expected to be SingleMemberAnnotation with 'String value()' as unique element",
1105                                                         new EclipseSourceLocation(typeDeclaration.compilationResult, typeDeclaration.sourceStart,
1106                                                                         typeDeclaration.sourceEnd), null);
1107                                         return PerClause.SINGLETON;// fallback strategy just to avoid NPE
1108                                 }
1109                         }
1110                 }
1111                 return null;// no @Aspect annotation at all (not as aspect)
1112         }
1113
1114         private PerClause.Kind determinePerClause(TypeDeclaration typeDeclaration, String clause) {
1115                 if (clause.startsWith("perthis(")) {
1116                         return PerClause.PEROBJECT;
1117                 } else if (clause.startsWith("pertarget(")) {
1118                         return PerClause.PEROBJECT;
1119                 } else if (clause.startsWith("percflow(")) {
1120                         return PerClause.PERCFLOW;
1121                 } else if (clause.startsWith("percflowbelow(")) {
1122                         return PerClause.PERCFLOW;
1123                 } else if (clause.startsWith("pertypewithin(")) {
1124                         return PerClause.PERTYPEWITHIN;
1125                 } else if (clause.startsWith("issingleton(")) {
1126                         return PerClause.SINGLETON;
1127                 } else {
1128                         eclipseWorld().showMessage(
1129                                         IMessage.ABORT,
1130                                         "cannot determine perClause '" + clause + "'",
1131                                         new EclipseSourceLocation(typeDeclaration.compilationResult, typeDeclaration.sourceStart,
1132                                                         typeDeclaration.sourceEnd), null);
1133                         return PerClause.SINGLETON;// fallback strategy just to avoid NPE
1134                 }
1135         }
1136
1137         // adapted from AspectDeclaration
1138         private PerClause.Kind lookupPerClauseKind(ReferenceBinding binding) {
1139                 final PerClause.Kind kind;
1140                 if (binding instanceof BinaryTypeBinding) {
1141                         ResolvedType superTypeX = factory.fromEclipse(binding);
1142                         PerClause perClause = superTypeX.getPerClause();
1143                         // clause is null for non aspect classes since coming from BCEL
1144                         // attributes
1145                         if (perClause != null) {
1146                                 kind = superTypeX.getPerClause().getKind();
1147                         } else {
1148                                 kind = null;
1149                         }
1150                 } else if (binding instanceof SourceTypeBinding) {
1151                         SourceTypeBinding sourceSc = (SourceTypeBinding) binding;
1152                         if (sourceSc.scope.referenceContext instanceof AspectDeclaration) {
1153                                 // code style
1154                                 kind = ((AspectDeclaration) sourceSc.scope.referenceContext).perClause.getKind();
1155                         } else { // if (sourceSc.scope.referenceContext instanceof
1156                                 // TypeDeclaration) {
1157                                 // if @Aspect: perFromSuper, else if @Aspect(..) get from anno
1158                                 // value, else null
1159                                 kind = getPerClauseForTypeDeclaration((sourceSc.scope.referenceContext));
1160                         }
1161                 } else {
1162                         // XXX need to handle this too
1163                         kind = null;
1164                 }
1165                 return kind;
1166         }
1167
1168         @Override
1169         public Collection<Declare> getDeclares() {
1170                 return declares;
1171         }
1172
1173         @Override
1174         public Collection<ResolvedMember> getPrivilegedAccesses() {
1175                 return Collections.emptyList();
1176         }
1177
1178         @Override
1179         public Collection getTypeMungers() {
1180                 return typeMungers;
1181         }
1182
1183         @Override
1184         public boolean doesNotExposeShadowMungers() {
1185                 return true;
1186         }
1187
1188         @Override
1189         public String getDeclaredGenericSignature() {
1190                 return CharOperation.charToString(binding.genericSignature());
1191         }
1192
1193         @Override
1194         public boolean isGeneric() {
1195                 return binding.isGenericType();
1196         }
1197
1198         @Override
1199         public TypeVariable[] getTypeVariables() {
1200                 if (declaration.typeParameters == null) {
1201                         return new TypeVariable[0];
1202                 }
1203                 TypeVariable[] typeVariables = new TypeVariable[declaration.typeParameters.length];
1204                 for (int i = 0; i < typeVariables.length; i++) {
1205                         typeVariables[i] = typeParameter2TypeVariable(declaration.typeParameters[i]);
1206                 }
1207                 return typeVariables;
1208         }
1209
1210         private TypeVariable typeParameter2TypeVariable(TypeParameter typeParameter) {
1211                 String name = new String(typeParameter.name);
1212                 ReferenceBinding superclassBinding = typeParameter.binding.superclass;
1213                 UnresolvedType superclass = UnresolvedType.forSignature(new String(superclassBinding.signature()));
1214                 UnresolvedType[] superinterfaces = null;
1215                 ReferenceBinding[] superInterfaceBindings = typeParameter.binding.superInterfaces;
1216                 if (superInterfaceBindings != null) {
1217                         superinterfaces = new UnresolvedType[superInterfaceBindings.length];
1218                         for (int i = 0; i < superInterfaceBindings.length; i++) {
1219                                 superinterfaces[i] = UnresolvedType.forSignature(new String(superInterfaceBindings[i].signature()));
1220                         }
1221                 }
1222                 // XXX what about lower binding?
1223                 TypeVariable tv = new TypeVariable(name, superclass, superinterfaces);
1224                 tv.setDeclaringElement(factory.fromBinding(typeParameter.binding.declaringElement));
1225                 tv.setRank(typeParameter.binding.rank);
1226                 return tv;
1227         }
1228
1229 }