1 /* *******************************************************************
2 * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
4 * This program and the accompanying materials are made available
5 * under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * PARC initial implementation
11 * ******************************************************************/
13 package org.aspectj.ajdt.internal.compiler.lookup;
15 import java.lang.reflect.Modifier;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.Iterator;
21 import java.util.List;
25 import org.aspectj.ajdt.internal.compiler.CommonPrinter;
26 import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
27 import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
28 import org.aspectj.asm.AsmManager;
29 import org.aspectj.bridge.IMessage;
30 import org.aspectj.bridge.context.CompilationAndWeavingContext;
31 import org.aspectj.bridge.context.ContextToken;
32 import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
33 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
34 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
35 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
36 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
37 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
38 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
39 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
40 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
41 import org.aspectj.org.eclipse.jdt.internal.compiler.env.AccessRestriction;
42 import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType;
43 import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment;
44 import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
45 import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
46 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
47 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
48 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
49 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
50 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
51 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
52 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding;
53 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
54 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
55 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
56 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
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.SourceTypeCollisionException;
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.org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
63 import org.aspectj.weaver.AnnotationAJ;
64 import org.aspectj.weaver.ConcreteTypeMunger;
65 import org.aspectj.weaver.ReferenceType;
66 import org.aspectj.weaver.ReferenceTypeDelegate;
67 import org.aspectj.weaver.ResolvedMember;
68 import org.aspectj.weaver.ResolvedType;
69 import org.aspectj.weaver.ResolvedTypeMunger;
70 import org.aspectj.weaver.UnresolvedType;
71 import org.aspectj.weaver.WeaverMessages;
72 import org.aspectj.weaver.WeaverStateInfo;
73 import org.aspectj.weaver.World;
74 import org.aspectj.weaver.bcel.BcelAnnotation;
75 import org.aspectj.weaver.bcel.BcelObjectType;
76 import org.aspectj.weaver.bcel.FakeAnnotation;
77 import org.aspectj.weaver.bcel.LazyClassGen;
78 import org.aspectj.weaver.patterns.DeclareAnnotation;
79 import org.aspectj.weaver.patterns.DeclareParents;
82 * Overrides the default eclipse LookupEnvironment for two purposes.
84 * 1. To provide some additional phases to <code>completeTypeBindings</code> that weave declare parents and inter-type declarations
85 * at the correct time.
87 * 2. To intercept the loading of new binary types to ensure the they will have declare parents and inter-type declarations woven
92 public class AjLookupEnvironment extends LookupEnvironment implements AnonymousClassCreationListener {
93 public EclipseFactory factory = null;
95 // private boolean builtInterTypesAndPerClauses = false;
96 private final List<SourceTypeBinding> pendingTypesToWeave = new ArrayList<SourceTypeBinding>();
98 // Q: What are dangerousInterfaces?
99 // A: An interface is considered dangerous if an ITD has been made upon it
101 // requires the top most implementors of the interface to be woven *and yet*
103 // responsible for the ITD is not in the 'world'.
104 // Q: Err, how can that happen?
105 // A: When a type is on the inpath, it is 'processed' when completing type
107 // point we look at any type mungers it was affected by previously (stored
109 // state info attribute). Effectively we are working with a type munger and
110 // yet may not have its
111 // originating aspect in the world. This is a problem if, for example, the
113 // a 'body' for a method targetting an interface - since the top most
114 // implementors should
115 // be woven by the munger from the aspect. When this happens we store the
116 // interface name here
117 // in the map - if we later process a type that is the topMostImplementor of
119 // interface then we put out an error message.
122 * interfaces targetted by ITDs that have to be implemented by accessing the topMostImplementor of the interface, yet the aspect
123 * where the ITD originated is not in the world
125 private final Map dangerousInterfaces = new HashMap();
127 public AjLookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter,
128 INameEnvironment nameEnvironment) {
129 super(typeRequestor, options, problemReporter, nameEnvironment);
132 public AjLookupEnvironment(LookupEnvironment env, ModuleBinding moduleBinding) {
133 super(env, moduleBinding);
136 // ??? duplicates some of super's code
138 public void completeTypeBindings() {
139 AsmManager.setCompletingTypeBindings(true);
140 ContextToken completeTypeBindingsToken = CompilationAndWeavingContext.enteringPhase(
141 CompilationAndWeavingContext.COMPLETING_TYPE_BINDINGS, "");
142 // builtInterTypesAndPerClauses = false;
143 // pendingTypesToWeave = new ArrayList();
144 stepCompleted = BUILD_TYPE_HIERARCHY;
146 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
147 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CHECK_AND_SET_IMPORTS,
148 units[i].compilationResult.fileName);
149 units[i].scope.checkAndSetImports();
150 CompilationAndWeavingContext.leavingPhase(tok);
152 stepCompleted = CHECK_AND_SET_IMPORTS;
154 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
155 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CONNECTING_TYPE_HIERARCHY,
156 units[i].compilationResult.fileName);
157 units[i].scope.connectTypeHierarchy();
158 CompilationAndWeavingContext.leavingPhase(tok);
160 stepCompleted = CONNECT_TYPE_HIERARCHY;
162 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
163 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.BUILDING_FIELDS_AND_METHODS,
164 units[i].compilationResult.fileName);
165 // units[i].scope.checkParameterizedTypes(); do this check a little
166 // later, after ITDs applied to stbs
167 units[i].scope.buildFieldsAndMethods();
168 CompilationAndWeavingContext.leavingPhase(tok);
171 // would like to gather up all TypeDeclarations at this point and put
172 // them in the factory
173 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
174 SourceTypeBinding[] b = units[i].scope.topLevelTypes;
175 for (SourceTypeBinding sourceTypeBinding : b) {
176 factory.addSourceTypeBinding(sourceTypeBinding, units[i]);
177 if (sourceTypeBinding.superclass instanceof MissingTypeBinding) {
178 // e37: Undoing the work in ClassScope.connectSuperClass() as it will lead to cascade errors
179 // TODO allow MissingTypeBinding through here and cope with it in all situations later?
180 sourceTypeBinding.superclass = units[i].scope.getJavaLangObject();
185 // We won't find out about anonymous types until later though, so
187 // told about them when they turn up.
188 AnonymousClassPublisher.aspectOf().setAnonymousClassCreationListener(this);
190 // need to build inter-type declarations for all AspectDeclarations at
192 // this MUST be done in order from super-types to subtypes
193 List<SourceTypeBinding> typesToProcess = new ArrayList<SourceTypeBinding>();
194 List<SourceTypeBinding> aspectsToProcess = new ArrayList<SourceTypeBinding>();
195 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
196 CompilationUnitScope cus = units[i].scope;
197 SourceTypeBinding[] stbs = cus.topLevelTypes;
198 for (SourceTypeBinding stb : stbs) {
199 typesToProcess.add(stb);
200 TypeDeclaration typeDeclaration = stb.scope.referenceContext;
201 if (typeDeclaration instanceof AspectDeclaration) {
202 aspectsToProcess.add(stb);
206 factory.getWorld().getCrosscuttingMembersSet().reset();
208 // Need to do these before the other ITDs
209 for (SourceTypeBinding aspectToProcess : aspectsToProcess) {
210 processInterTypeMemberTypes(aspectToProcess.scope);
213 while (typesToProcess.size() > 0) {
214 // removes types from the list as they are processed...
215 collectAllITDsAndDeclares(typesToProcess.get(0), typesToProcess);
218 factory.finishTypeMungers();
221 final List<ConcreteTypeMunger> typeMungers = factory.getTypeMungers();
223 final List<DeclareParents> declareParents = factory.getDeclareParents();
224 final List<DeclareAnnotation> declareAnnotationOnTypes = factory.getDeclareAnnotationOnTypes();
228 // We now have some list of types to process, and we are about to apply
230 // There can be situations where the order of types passed to the
231 // compiler causes the
232 // output from the compiler to vary - THIS IS BAD. For example, if we
234 // and class B extends A. Also, an aspect that 'declare parents: A+
235 // implements Serializable'
236 // then depending on whether we see A first, we may or may not make B
239 // The fix is to process them in the right order, ensuring that for a
240 // type we process its
241 // supertypes and superinterfaces first. This algorithm may have
243 // - partial hierarchies (e.g. suppose types A,B,C are in a hierarchy
244 // and A and C are to be woven but not B)
245 // - weaving that brings new types in for processing (see
246 // pendingTypesToWeave.add() calls) after we thought
247 // we had the full list.
249 // but these aren't common cases (he bravely said...)
250 boolean typeProcessingOrderIsImportant = declareParents.size() > 0 || declareAnnotationOnTypes.size() > 0; // DECAT
252 if (typeProcessingOrderIsImportant) {
253 typesToProcess = new ArrayList<SourceTypeBinding>();
254 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
255 CompilationUnitScope cus = units[i].scope;
256 SourceTypeBinding[] stbs = cus.topLevelTypes;
257 for (SourceTypeBinding stb : stbs) {
258 typesToProcess.add(stb);
262 List<SourceTypeBinding> stb2 = new ArrayList<SourceTypeBinding>();
263 stb2.addAll(typesToProcess);
265 while (typesToProcess.size() > 0) {
266 // A side effect of weaveIntertypes() is that the processed type is removed from the collection
267 weaveIntertypes(typesToProcess, typesToProcess.get(0), typeMungers, declareParents, declareAnnotationOnTypes, 1);
270 while (stb2.size() > 0) {
271 // A side effect of weaveIntertypes() is that the processed type is removed from the collection
272 weaveIntertypes(stb2, stb2.get(0), typeMungers, declareParents, declareAnnotationOnTypes, 2);
276 // Order isn't important
277 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
278 weaveInterTypeDeclarations(units[i].scope, typeMungers, declareParents, declareAnnotationOnTypes);
282 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
283 units[i].scope.checkParameterizedTypes();
286 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
287 SourceTypeBinding[] b = units[i].scope.topLevelTypes;
288 for (SourceTypeBinding sourceTypeBinding : b) {
289 ContextToken tok = CompilationAndWeavingContext.enteringPhase(
290 CompilationAndWeavingContext.RESOLVING_POINTCUT_DECLARATIONS, sourceTypeBinding.sourceName);
291 resolvePointcutDeclarations(sourceTypeBinding.scope);
292 CompilationAndWeavingContext.leavingPhase(tok);
296 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
297 SourceTypeBinding[] b = units[i].scope.topLevelTypes;
298 for (SourceTypeBinding sourceTypeBinding : b) {
299 ContextToken tok = CompilationAndWeavingContext.enteringPhase(
300 CompilationAndWeavingContext.ADDING_DECLARE_WARNINGS_AND_ERRORS, sourceTypeBinding.sourceName);
301 addAdviceLikeDeclares(sourceTypeBinding.scope);
302 CompilationAndWeavingContext.leavingPhase(tok);
306 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
307 units[i] = null; // release unnecessary reference to the parsed unit
310 stepCompleted = BUILD_FIELDS_AND_METHODS;
311 lastCompletedUnitIndex = lastUnitIndex;
312 AsmManager.setCompletingTypeBindings(false);
313 factory.getWorld().getCrosscuttingMembersSet().verify();
314 CompilationAndWeavingContext.leavingPhase(completeTypeBindingsToken);
316 if (isProcessingAnnotations) {
317 throw new SourceTypeCollisionException(); // TODO(yushkovskiy): temporary solution; forcing to recompile units to insert mungers into types
322 // * For any given sourcetypebinding, this method checks that if it is a
323 // parameterized aspect that
324 // * the type parameters specified for any supertypes meet the bounds for
328 // private void verifyAnyTypeParametersMeetBounds(SourceTypeBinding
330 // ResolvedType onType = factory.fromEclipse(sourceType);
331 // if (onType.isAspect()) {
332 // ResolvedType superType = factory.fromEclipse(sourceType.superclass);
333 // // Don't need to check if it was used in its RAW form or isnt generic
334 // if (superType.isGenericType() || superType.isParameterizedType()) {
335 // TypeVariable[] typeVariables = superType.getTypeVariables();
336 // UnresolvedType[] typeParams = superType.getTypeParameters();
337 // if (typeVariables!=null && typeParams!=null) {
338 // for (int i = 0; i < typeVariables.length; i++) {
340 // typeVariables[i].canBeBoundTo(typeParams[i].resolve(factory.getWorld()));
341 // if (!ok) { // the supplied parameter violates the bounds
342 // // Type {0} does not meet the specification for type parameter {1} ({2})
343 // in generic type {3}
345 // WeaverMessages.format(
346 // WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
349 // typeVariables[i].getDisplayName(),
350 // superType.getGenericType().getName());
351 // factory.getWorld().getMessageHandler().handleMessage(MessageUtil.error(msg
352 // ,onType.getSourceLocation()));
360 public void doSupertypesFirst(ReferenceBinding rb, Collection<? extends ReferenceBinding> yetToProcess) {
361 if (rb instanceof SourceTypeBinding) {
362 if (yetToProcess.contains(rb)) {
363 collectAllITDsAndDeclares((SourceTypeBinding) rb, yetToProcess);
365 } else if (rb instanceof ParameterizedTypeBinding) {
366 // If its a PTB we need to pull the SourceTypeBinding out of it.
367 ParameterizedTypeBinding ptb = (ParameterizedTypeBinding) rb;
368 if (ptb.type instanceof SourceTypeBinding && yetToProcess.contains(ptb.type)) {
369 collectAllITDsAndDeclares((SourceTypeBinding) ptb.type, yetToProcess);
375 * Find all the ITDs and Declares, but it is important we do this from the supertypes down to the subtypes.
378 * @param yetToProcess
380 private void collectAllITDsAndDeclares(SourceTypeBinding sourceType, Collection<? extends ReferenceBinding> yetToProcess) {
381 // Look at the supertype first
382 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.COLLECTING_ITDS_AND_DECLARES,
383 sourceType.sourceName);
385 yetToProcess.remove(sourceType);
386 // look out our direct supertype
387 doSupertypesFirst(sourceType.superclass(), yetToProcess);
389 // now check our membertypes (pr119570)
390 ReferenceBinding[] memberTypes = sourceType.memberTypes;
391 for (ReferenceBinding memberType : memberTypes) {
392 SourceTypeBinding rb = (SourceTypeBinding) memberType;
393 if (!rb.superclass().equals(sourceType)) {
394 doSupertypesFirst(rb.superclass(), yetToProcess);
398 buildInterTypeAndPerClause(sourceType.scope);
399 addCrosscuttingStructures(sourceType.scope);
400 CompilationAndWeavingContext.leavingPhase(tok);
404 * Weave the parents and intertype decls into a given type. This method looks at the supertype and superinterfaces for the
405 * specified type and recurses to weave those first if they are in the full list of types we are going to process during this
406 * compile... it stops recursing the first time it hits a type we aren't going to process during this compile. This could cause
407 * problems if you supply 'pieces' of a hierarchy, i.e. the bottom and the top, but not the middle - but what the hell are you
408 * doing if you do that?
410 * @param mode 0=do everything, 1=do declare parents, 2=do ITDs
412 private void weaveIntertypes(List<SourceTypeBinding> typesToProcess, SourceTypeBinding typeToWeave,
413 List<ConcreteTypeMunger> typeMungers, List<DeclareParents> declareParents,
414 List<DeclareAnnotation> declareAnnotationOnTypes, int mode) {
415 // Look at the supertype first
416 ReferenceBinding superType = typeToWeave.superclass();
417 if (typesToProcess.contains(superType) && superType instanceof SourceTypeBinding) {
418 // System.err.println("Recursing to supertype "+new
419 // String(superType.getFileName()));
420 weaveIntertypes(typesToProcess, (SourceTypeBinding) superType, typeMungers, declareParents, declareAnnotationOnTypes,
423 // Then look at the superinterface list
424 ReferenceBinding[] interfaceTypes = typeToWeave.superInterfaces();
425 for (ReferenceBinding binding : interfaceTypes) {
426 if (typesToProcess.contains(binding) && binding instanceof SourceTypeBinding) {
427 // System.err.println("Recursing to superinterface "+new
428 // String(binding.getFileName()));
429 weaveIntertypes(typesToProcess, (SourceTypeBinding) binding, typeMungers, declareParents, declareAnnotationOnTypes,
431 } else if (binding instanceof ParameterizedTypeBinding && (((ParameterizedTypeBinding) binding).type instanceof SourceTypeBinding) && typesToProcess.contains(((ParameterizedTypeBinding) binding).type)) {
432 weaveIntertypes(typesToProcess, (SourceTypeBinding) ((ParameterizedTypeBinding) binding).type, typeMungers, declareParents, declareAnnotationOnTypes, mode);
435 weaveInterTypeDeclarations(typeToWeave, typeMungers, declareParents, declareAnnotationOnTypes, false, mode);
436 typesToProcess.remove(typeToWeave);
439 private void doPendingWeaves() {
440 for (SourceTypeBinding t: pendingTypesToWeave) {
441 ContextToken tok = CompilationAndWeavingContext.enteringPhase(
442 CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS, t.sourceName);
443 weaveInterTypeDeclarations(t);
444 CompilationAndWeavingContext.leavingPhase(tok);
446 pendingTypesToWeave.clear();
449 private void addAdviceLikeDeclares(ClassScope s) {
450 TypeDeclaration dec = s.referenceContext;
452 if (dec instanceof AspectDeclaration) {
453 ResolvedType typeX = factory.fromEclipse(dec.binding);
454 factory.getWorld().getCrosscuttingMembersSet().addAdviceLikeDeclares(typeX);
457 SourceTypeBinding sourceType = s.referenceContext.binding;
458 ReferenceBinding[] memberTypes = sourceType.memberTypes;
459 for (ReferenceBinding memberType : memberTypes) {
460 addAdviceLikeDeclares(((SourceTypeBinding) memberType).scope);
464 private void addCrosscuttingStructures(ClassScope s) {
465 TypeDeclaration dec = s.referenceContext;
467 if (dec instanceof AspectDeclaration) {
468 ResolvedType typeX = factory.fromEclipse(dec.binding);
469 factory.getWorld().getCrosscuttingMembersSet().addOrReplaceAspect(typeX, false);
471 if (typeX.getSuperclass().isAspect() && !typeX.getSuperclass().isExposedToWeaver()) {
472 factory.getWorld().getCrosscuttingMembersSet().addOrReplaceAspect(typeX.getSuperclass(), false);
476 SourceTypeBinding sourceType = s.referenceContext.binding;
477 ReferenceBinding[] memberTypes = sourceType.memberTypes;
478 for (ReferenceBinding memberType : memberTypes) {
479 addCrosscuttingStructures(((SourceTypeBinding) memberType).scope);
483 private void resolvePointcutDeclarations(ClassScope s) {
484 TypeDeclaration dec = s.referenceContext;
485 SourceTypeBinding sourceType = s.referenceContext.binding;
486 boolean hasPointcuts = false;
487 AbstractMethodDeclaration[] methods = dec.methods;
488 boolean initializedMethods = false;
489 if (methods != null) {
490 for (AbstractMethodDeclaration method : methods) {
491 if (method instanceof PointcutDeclaration) {
493 if (!initializedMethods) {
494 sourceType.methods(); // force initialization
495 initializedMethods = true;
497 ((PointcutDeclaration) method).resolvePointcut(s);
502 if (hasPointcuts || dec instanceof AspectDeclaration || couldBeAnnotationStyleAspectDeclaration(dec)) {
503 ReferenceType name = (ReferenceType) factory.fromEclipse(sourceType);
504 EclipseSourceType eclipseSourceType = (EclipseSourceType) name.getDelegate();
505 eclipseSourceType.checkPointcutDeclarations();
508 ReferenceBinding[] memberTypes = sourceType.memberTypes;
509 for (ReferenceBinding memberType : memberTypes) {
510 resolvePointcutDeclarations(((SourceTypeBinding) memberType).scope);
515 * Return true if the declaration has @Aspect annotation. Called 'couldBe' rather than 'is' because someone else may have
516 * defined an annotation called Aspect - we can't verify the full name (including package name) because it may not have been
517 * resolved just yet and rather going through expensive resolution when we dont have to, this gives us a cheap check that tells
518 * us whether to bother.
520 private boolean couldBeAnnotationStyleAspectDeclaration(TypeDeclaration dec) {
521 Annotation[] annotations = dec.annotations;
522 boolean couldBeAtAspect = false;
523 if (annotations != null) {
524 for (int i = 0; i < annotations.length && !couldBeAtAspect; i++) {
525 if (annotations[i].toString().equals("@Aspect")) {
526 couldBeAtAspect = true;
530 return couldBeAtAspect;
534 * Applies any intertype member type declarations up front.
536 private void processInterTypeMemberTypes(ClassScope classScope) {
537 TypeDeclaration dec = classScope.referenceContext;
538 if (dec instanceof AspectDeclaration) {
539 ((AspectDeclaration) dec).processIntertypeMemberTypes(classScope);
541 // if we are going to support nested aspects making itd member types, copy the logic from the end of
542 // buildInterTypeAndPerClause() which walks members
545 private void buildInterTypeAndPerClause(ClassScope s) {
546 TypeDeclaration dec = s.referenceContext;
547 if (dec instanceof AspectDeclaration) {
548 ((AspectDeclaration) dec).buildInterTypeAndPerClause(s);
551 SourceTypeBinding sourceType = s.referenceContext.binding;
552 // test classes don't extend aspects
553 if (sourceType.superclass != null) {
554 ResolvedType parent = factory.fromEclipse(sourceType.superclass);
555 if (parent.isAspect() && !isAspect(dec)) {
556 factory.showMessage(IMessage.ERROR, "class \'" + new String(sourceType.sourceName) + "\' can not extend aspect \'"
557 + parent.getName() + "\'", factory.fromEclipse(sourceType).getSourceLocation(), null);
561 ReferenceBinding[] memberTypes = sourceType.memberTypes;
562 if (memberTypes == null) {
563 System.err.println("Unexpectedly found null for memberTypes of " + sourceType.debugName());
565 if (memberTypes != null) {
566 for (ReferenceBinding memberType : memberTypes) {
567 buildInterTypeAndPerClause(((SourceTypeBinding) memberType).scope);
572 private boolean isAspect(TypeDeclaration decl) {
573 if ((decl instanceof AspectDeclaration)) {
575 } else if (decl.annotations == null) {
578 for (int i = 0; i < decl.annotations.length; i++) {
579 Annotation ann = decl.annotations[i];
580 if (ann.type instanceof SingleTypeReference) {
581 if (CharOperation.equals("Aspect".toCharArray(), ((SingleTypeReference) ann.type).token)) {
584 } else if (ann.type instanceof QualifiedTypeReference) {
585 QualifiedTypeReference qtr = (QualifiedTypeReference) ann.type;
586 if (qtr.tokens.length != 5) {
589 if (!CharOperation.equals("org".toCharArray(), qtr.tokens[0])) {
592 if (!CharOperation.equals("aspectj".toCharArray(), qtr.tokens[1])) {
595 if (!CharOperation.equals("lang".toCharArray(), qtr.tokens[2])) {
598 if (!CharOperation.equals("annotation".toCharArray(), qtr.tokens[3])) {
601 if (!CharOperation.equals("Aspect".toCharArray(), qtr.tokens[4])) {
611 private void weaveInterTypeDeclarations(CompilationUnitScope unit, List<ConcreteTypeMunger> typeMungers,
612 List<DeclareParents> declareParents, List<DeclareAnnotation> declareAnnotationOnTypes) {
613 for (int i = 0, length = unit.topLevelTypes.length; i < length; i++) {
614 weaveInterTypeDeclarations(unit.topLevelTypes[i], typeMungers, declareParents, declareAnnotationOnTypes, false, 0);
618 private void weaveInterTypeDeclarations(SourceTypeBinding sourceType) {
619 if (!factory.areTypeMungersFinished()) {
620 if (!pendingTypesToWeave.contains(sourceType)) {
621 pendingTypesToWeave.add(sourceType);
623 // inner type ITD support - may need this for some incremental cases...
624 // List<ConcreteTypeMunger> ctms = factory.getWorld().getCrosscuttingMembersSet().getTypeMungersOfKind(
625 // ResolvedTypeMunger.InnerClass);
626 // // List<ConcreteTypeMunger> innerTypeMungers = new ArrayList<ConcreteTypeMunger>();
627 // // for (ConcreteTypeMunger ctm : ctms) {
628 // // if (ctm.getMunger() != null && ctm.getMunger().getKind() == ResolvedTypeMunger.InnerClass) {
629 // // innerTypeMungers.add(ctm);
632 // // that includes the innertype one...
633 // // doPendingWeaves at this level is about applying inner class
634 // BinaryTypeBinding t = (BinaryTypeBinding) sourceType;
635 // for (ConcreteTypeMunger ctm : innerTypeMungers) {
636 // NewMemberClassTypeMunger nmctm = (NewMemberClassTypeMunger) ctm.getMunger();
637 // ReferenceBinding[] rbs = t.memberTypes;
638 // UnresolvedType ut = factory.fromBinding(t);
639 // if (ut.equals(nmctm.getTargetType())) {
640 // // got a match here
641 // SourceTypeBinding aspectTypeBinding = (SourceTypeBinding) factory.makeTypeBinding(ctm.getAspectType());
643 // char[] mungerMemberTypeName = ("$" + nmctm.getMemberTypeName()).toCharArray();
644 // ReferenceBinding innerTypeBinding = null;
645 // for (ReferenceBinding innerType : aspectTypeBinding.memberTypes) {
646 // char[] compounded = CharOperation.concatWith(innerType.compoundName, '.');
647 // if (org.aspectj.org.eclipse.jdt.core.compiler.CharOperation.endsWith(compounded, mungerMemberTypeName)) {
648 // innerTypeBinding = innerType;
652 // // may be unresolved if the aspect type binding was a BinaryTypeBinding
653 // if (innerTypeBinding instanceof UnresolvedReferenceBinding) {
654 // innerTypeBinding = BinaryTypeBinding
655 // .resolveType(innerTypeBinding, factory.getLookupEnvironment(), true);
657 // t.memberTypes(); // cause initialization
658 // t.memberTypes = new ReferenceBinding[] { innerTypeBinding };
661 // // The inner type from the aspect should be put into the membertypebindings for this
668 weaveInterTypeDeclarations(sourceType, factory.getTypeMungers(), factory.getDeclareParents(),
669 factory.getDeclareAnnotationOnTypes(), true, 0);
674 * @param mode 0=do everything, 1=do declare parents, 2=do ITDs
676 private void weaveInterTypeDeclarations(SourceTypeBinding sourceType, List<ConcreteTypeMunger> typeMungers,
677 List<DeclareParents> declareParents, List<DeclareAnnotation> declareAnnotationOnTypes, boolean skipInners, int mode) {
679 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS,
680 sourceType.sourceName);
682 ResolvedType onType = factory.fromEclipse(sourceType);
684 // AMC we shouldn't need this when generic sigs are fixed??
685 if (onType.isRawType()) {
686 onType = onType.getGenericType();
689 WeaverStateInfo info = onType.getWeaverState();
692 // this test isnt quite right - there will be a case where we fail to
694 // with a 'dangerous interface' because the type is reweavable when we
696 // because the type wasn't going to be rewoven... if that happens, we
698 // move this test and dangerous interface processing to the end of this
700 // make it conditional on whether any of the typeMungers passed into
702 // matched this type.
703 if (info != null && !info.isOldStyle() && !info.isReweavable()) {
704 processTypeMungersFromExistingWeaverState(sourceType, onType);
705 CompilationAndWeavingContext.leavingPhase(tok);
709 // Check if the type we are looking at is the topMostImplementor of a
710 // dangerous interface -
711 // report a problem if it is.
712 for (Object o : dangerousInterfaces.entrySet()) {
713 Map.Entry entry = (Map.Entry) o;
714 ResolvedType interfaceType = (ResolvedType) entry.getKey();
715 if (onType.isTopmostImplementor(interfaceType)) {
716 factory.showMessage(IMessage.ERROR, onType + ": " + entry.getValue(), onType.getSourceLocation(), null);
720 boolean needOldStyleWarning = (info != null && info.isOldStyle());
722 onType.clearInterTypeMungers();
723 onType.ensureConsistent();
725 // FIXME asc perf Could optimize here, after processing the expected set
726 // of types we may bring
727 // binary types that are not exposed to the weaver, there is no need to
728 // attempt declare parents
729 // or declare annotation really - unless we want to report the
730 // not-exposed to weaver
733 List<DeclareParents> decpToRepeat = new ArrayList<DeclareParents>();
734 List<DeclareAnnotation> decaToRepeat = new ArrayList<DeclareAnnotation>();
735 boolean anyNewParents = false;
736 boolean anyNewAnnotations = false;
739 // try and apply all decps - if they match, then great. If they don't
741 // check if they are starred-annotation patterns. If they are not
743 // annotation patterns then they might match later...remember that...
744 for (DeclareParents decp : declareParents) {
745 if (!decp.isMixin()) {
746 boolean didSomething = doDeclareParents(decp, sourceType);
748 if (factory.pushinCollector != null) {
749 factory.pushinCollector.tagAsMunged(sourceType, decp.getParents().get(0));
751 anyNewParents = true;
753 if (!decp.getChild().isStarAnnotation()) {
754 decpToRepeat.add(decp);
760 for (DeclareAnnotation deca : declareAnnotationOnTypes) {
761 boolean didSomething = doDeclareAnnotations(deca, sourceType, true);
763 anyNewAnnotations = true;
765 if (!deca.getTypePattern().isStar()) {
766 decaToRepeat.add(deca);
771 List<Object> forRemoval = new ArrayList<Object>();
772 // now lets loop over and over until we have done all we can
773 while ((anyNewAnnotations || anyNewParents) && (!decpToRepeat.isEmpty() || !decaToRepeat.isEmpty())) {
774 anyNewParents = anyNewAnnotations = false;
776 for (DeclareParents decp : decpToRepeat) {
777 boolean didSomething = doDeclareParents(decp, sourceType);
779 if (factory.pushinCollector != null) {
780 factory.pushinCollector.tagAsMunged(sourceType, decp.getParents().get(0));
782 anyNewParents = true;
783 forRemoval.add(decp);
786 decpToRepeat.removeAll(forRemoval);
789 for (DeclareAnnotation deca : decaToRepeat) {
790 boolean didSomething = doDeclareAnnotations(deca, sourceType, false);
792 if (factory.pushinCollector != null) {
793 factory.pushinCollector.tagAsMunged(sourceType, deca.getAnnotationString());
795 anyNewAnnotations = true;
796 forRemoval.add(deca);
799 decaToRepeat.removeAll(forRemoval);
802 if (mode == 0 || mode == 2) {
803 for (ConcreteTypeMunger typeMunger : typeMungers) {
804 EclipseTypeMunger munger = (EclipseTypeMunger) typeMunger;
805 if (munger.matches(onType)) {
806 // if (needOldStyleWarning) {
807 // factory.showMessage(IMessage.WARNING, "The class for " + onType
808 // + " should be recompiled with ajc-1.1.1 for best results", onType.getSourceLocation(), null);
809 // needOldStyleWarning = false;
811 onType.addInterTypeMunger(munger, true);
812 if (munger.getMunger() != null && munger.getMunger().getKind() == ResolvedTypeMunger.InnerClass) {
813 // Must do these right now, because if we do an ITD member afterwards it may attempt to reference the
814 // type being applied (the call above 'addInterTypeMunger' will fail for these ITDs if it needed
815 // it to be in place)
816 if (munger.munge(sourceType, onType)) {
817 if (factory.pushinCollector != null) {
818 factory.pushinCollector.tagAsMunged(sourceType, munger.getSourceMethod());
825 onType.checkInterTypeMungers();
826 for (ConcreteTypeMunger concreteTypeMunger : onType.getInterTypeMungers()) {
827 EclipseTypeMunger munger = (EclipseTypeMunger) concreteTypeMunger;
828 if (munger.getMunger() == null || munger.getMunger().getKind() != ResolvedTypeMunger.InnerClass) {
829 if (munger.munge(sourceType, onType)) {
830 if (factory.pushinCollector != null) {
831 factory.pushinCollector.tagAsMunged(sourceType, munger.getSourceMethod());
838 // Call if you would like to do source weaving of declare
839 // @method/@constructor
840 // at source time... no need to do this as it can't impact anything, but
842 // future generations to enjoy. Method source is commented out at the
843 // end of this module
844 // doDeclareAnnotationOnMethods();
846 // Call if you would like to do source weaving of declare @field
847 // at source time... no need to do this as it can't impact anything, but
849 // future generations to enjoy. Method source is commented out at the
850 // end of this module
851 // doDeclareAnnotationOnFields();
854 CompilationAndWeavingContext.leavingPhase(tok);
858 ReferenceBinding[] memberTypes = sourceType.memberTypes;
859 for (ReferenceBinding memberType : memberTypes) {
860 if (memberType instanceof SourceTypeBinding) {
861 weaveInterTypeDeclarations((SourceTypeBinding) memberType, typeMungers, declareParents,
862 declareAnnotationOnTypes, false, mode);
865 CompilationAndWeavingContext.leavingPhase(tok);
869 * Called when we discover we are weaving intertype declarations on some type that has an existing 'WeaverStateInfo' object -
870 * this is typically some previously woven type that has been passed on the inpath.
872 * sourceType and onType are the 'same type' - the former is the 'Eclipse' version and the latter is the 'Weaver' version.
874 private void processTypeMungersFromExistingWeaverState(SourceTypeBinding sourceType, ResolvedType onType) {
875 List<ConcreteTypeMunger> previouslyAppliedMungers = onType.getWeaverState().getTypeMungers(onType);
877 for (ConcreteTypeMunger m : previouslyAppliedMungers) {
878 EclipseTypeMunger munger = factory.makeEclipseTypeMunger(m);
879 if (munger.munge(sourceType, onType)) {
880 if (onType.isInterface() && munger.getMunger().needsAccessToTopmostImplementor()) {
881 if (!onType.getWorld().getCrosscuttingMembersSet().containsAspect(munger.getAspectType())) {
883 .put(onType, "implementors of " + onType + " must be woven by " + munger.getAspectType());
891 private boolean doDeclareParents(DeclareParents declareParents, SourceTypeBinding sourceType) {
892 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_PARENTS,
893 sourceType.sourceName);
894 ResolvedType resolvedSourceType = factory.fromEclipse(sourceType);
895 List<ResolvedType> newParents = declareParents.findMatchingNewParents(resolvedSourceType, false);
896 if (!newParents.isEmpty()) {
897 for (ResolvedType parent : newParents) {
898 if (dangerousInterfaces.containsKey(parent)) {
899 ResolvedType onType = factory.fromEclipse(sourceType);
900 factory.showMessage(IMessage.ERROR, onType + ": " + dangerousInterfaces.get(parent),
901 onType.getSourceLocation(), null);
903 if (Modifier.isFinal(parent.getModifiers())) {
904 factory.showMessage(IMessage.ERROR, "cannot extend final class " + parent.getClassName(),
905 declareParents.getSourceLocation(), null);
907 // do not actually do it if the type isn't exposed - this
908 // will correctly reported as a problem elsewhere
909 if (!resolvedSourceType.isExposedToWeaver()) {
912 // AsmRelationshipProvider.getDefault().
913 // addDeclareParentsRelationship
914 // (declareParents.getSourceLocation(),
915 // factory.fromEclipse(sourceType), newParents);
916 addParent(sourceType, parent);
919 CompilationAndWeavingContext.leavingPhase(tok);
922 CompilationAndWeavingContext.leavingPhase(tok);
926 private String stringifyTargets(long bits) {
927 if ((bits & TagBits.AnnotationTargetMASK) == 0) {
930 Set<String> s = new HashSet<String>();
931 if ((bits & TagBits.AnnotationForAnnotationType) != 0) {
932 s.add("ANNOTATION_TYPE");
934 if ((bits & TagBits.AnnotationForConstructor) != 0) {
935 s.add("CONSTRUCTOR");
937 if ((bits & TagBits.AnnotationForField) != 0) {
940 if ((bits & TagBits.AnnotationForLocalVariable) != 0) {
941 s.add("LOCAL_VARIABLE");
943 if ((bits & TagBits.AnnotationForMethod) != 0) {
946 if ((bits & TagBits.AnnotationForPackage) != 0) {
949 if ((bits & TagBits.AnnotationForParameter) != 0) {
952 if ((bits & TagBits.AnnotationForType) != 0) {
955 StringBuffer sb = new StringBuffer();
957 for (Iterator<String> iter = s.iterator(); iter.hasNext();) {
958 String element = iter.next();
960 if (iter.hasNext()) {
965 return sb.toString();
968 private boolean doDeclareAnnotations(DeclareAnnotation decA, SourceTypeBinding sourceType, boolean reportProblems) {
969 ResolvedType rtx = factory.fromEclipse(sourceType);
970 if (!decA.matches(rtx)) {
973 if (!rtx.isExposedToWeaver()) {
977 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_ANNOTATIONS,
978 sourceType.sourceName);
980 // Get the annotation specified in the declare
981 UnresolvedType aspectType = decA.getAspect();
982 if (aspectType instanceof ReferenceType) {
983 ReferenceType rt = (ReferenceType) aspectType;
984 if (rt.isParameterizedType() || rt.isRawType()) {
985 aspectType = rt.getGenericType();
988 TypeBinding tb = factory.makeTypeBinding(aspectType);
990 // Hideousness follows:
992 // There are multiple situations to consider here and they relate to the
994 // where the annotation is coming from and where the annotation is going
997 // 1. Straight full build, all from source - the annotation is from a
999 // is being put on some type. Both types are real SourceTypeBindings.
1001 // 2. Incremental build, changing the affected type - the annotation is
1003 // dec@type in a BinaryTypeBinding (so has to be accessed via bcel) and
1005 // affected type is a real SourceTypeBinding. Mostly works (pr128665)
1008 SourceTypeBinding stb = (SourceTypeBinding) tb;
1009 Annotation[] toAdd = null;
1012 AbstractMethodDeclaration methodDecl = null;
1013 // Might have to retrieve the annotation through BCEL and construct an
1014 // eclipse one for it.
1015 if (stb instanceof BinaryTypeBinding) {
1016 toAdd = retrieveAnnotationFromBinaryTypeBinding(decA, stb);
1017 if (toAdd != null && toAdd.length > 0 && toAdd[0].resolvedType != null) {
1018 abits = toAdd[0].resolvedType.getAnnotationTagBits();
1020 } else if (stb != null) {
1021 // much nicer, its a real SourceTypeBinding so we can stay in
1023 // if (decA.getAnnotationMethod() != null) {
1024 char[] declareSelector = decA.getAnnotationMethod().toCharArray();
1026 ReferenceBinding rb = stb;
1027 String declaringAspectName = decA.getDeclaringType().getRawName();
1028 while (rb != null && !new String(CharOperation.concatWith(rb.compoundName, '.')).equals(declaringAspectName)) {
1029 rb = rb.superclass();
1031 MethodBinding[] mbs = rb.getMethods(declareSelector);
1033 ReferenceBinding declaringBinding = mbs[0].declaringClass;
1034 if (declaringBinding instanceof ParameterizedTypeBinding) {
1035 // Unwrap - this means we don't allow the type of the annotation to be parameterized, may need to revisit that
1036 declaringBinding = ((ParameterizedTypeBinding) declaringBinding).type;
1038 if (declaringBinding instanceof BinaryTypeBinding) {
1039 toAdd = retrieveAnnotationFromBinaryTypeBinding(decA, declaringBinding);
1040 if (toAdd != null && toAdd.length > 0 && toAdd[0].resolvedType != null) {
1041 abits = toAdd[0].resolvedType.getAnnotationTagBits();
1044 abits = mbs[0].getAnnotationTagBits(); // ensure resolved
1045 TypeDeclaration typeDecl = ((SourceTypeBinding) declaringBinding).scope.referenceContext;
1046 methodDecl = typeDecl.declarationOf(mbs[0]);
1047 toAdd = methodDecl.annotations; // this is what to add
1048 toAdd[0] = createAnnotationCopy(toAdd[0]);
1049 if (toAdd[0].resolvedType != null) {
1050 abits = toAdd[0].resolvedType.getAnnotationTagBits();
1056 // This happens if there is another error in the code - that should be reported separately
1057 if (toAdd == null || toAdd[0] == null || toAdd[0].type == null) {
1058 CompilationAndWeavingContext.leavingPhase(tok);
1061 if (sourceType instanceof BinaryTypeBinding) {
1062 // In this case we can't access the source type binding to add a new
1063 // annotation, so let's put something
1064 // on the weaver type temporarily
1065 ResolvedType theTargetType = factory.fromEclipse(sourceType);
1066 TypeBinding theAnnotationType = toAdd[0].resolvedType;
1067 // The annotation type may be null if it could not be resolved (eg. the relevant import has not been added yet)
1068 // In this case an error will be put out about the annotation but not if we crash here
1069 if (theAnnotationType == null) {
1072 String sig = new String(theAnnotationType.signature());
1073 UnresolvedType bcelAnnotationType = UnresolvedType.forSignature(sig);
1074 String name = bcelAnnotationType.getName();
1075 if (theTargetType.hasAnnotation(bcelAnnotationType)) {
1076 CompilationAndWeavingContext.leavingPhase(tok);
1080 // FIXME asc tidy up this code that duplicates whats below!
1081 // Simple checks on the bits
1082 boolean giveupnow = false;
1083 if (((abits & TagBits.AnnotationTargetMASK) != 0)) {
1084 if (isAnnotationTargettingSomethingOtherThanAnnotationOrNormal(abits)) {
1085 // error will have been already reported
1087 } else if ((sourceType.isAnnotationType() && (abits & TagBits.AnnotationForAnnotationType) == 0)
1088 || (!sourceType.isAnnotationType() && (abits & TagBits.AnnotationForType) == 0)) {
1090 if (reportProblems) {
1091 if (decA.isExactPattern()) {
1092 factory.showMessage(IMessage.ERROR, WeaverMessages.format(
1093 WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION, rtx.getName(), toAdd[0].type,
1094 stringifyTargets(abits)), decA.getSourceLocation(), null);
1096 // dont put out the lint - the weaving process will do
1099 // if (factory.getWorld().getLint().
1100 // invalidTargetForAnnotation.isEnabled()) {
1101 // factory.getWorld().getLint().invalidTargetForAnnotation
1103 // String[]{rtx.getName(),toAdd[0].type.toString(),
1105 // (abits)},decA.getSourceLocation(),null);
1113 CompilationAndWeavingContext.leavingPhase(tok);
1117 theTargetType.addAnnotation(new BcelAnnotation(new FakeAnnotation(name, sig,
1118 (abits & TagBits.AnnotationRuntimeRetention) != 0), factory.getWorld()));
1119 CompilationAndWeavingContext.leavingPhase(tok);
1123 Annotation currentAnnotations[] = sourceType.scope.referenceContext.annotations;
1124 if (currentAnnotations != null) {
1125 for (Annotation annotation : currentAnnotations) {
1126 String a = CharOperation.toString(annotation.type.getTypeName());
1127 String b = CharOperation.toString(toAdd[0].type.getTypeName());
1128 // FIXME asc we have a lint for attempting to add an annotation
1129 // twice to a method,
1130 // we could put it out here *if* we can resolve the problem of
1131 // errors coming out
1132 // multiple times if we have cause to loop through here
1134 CompilationAndWeavingContext.leavingPhase(tok);
1140 if (((abits & TagBits.AnnotationTargetMASK) != 0)) {
1141 if ((abits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType)) == 0) {
1142 // this means it specifies something other than annotation or
1143 // normal type - error will have been already reported,
1144 // just resolution process above
1145 CompilationAndWeavingContext.leavingPhase(tok);
1148 if ((sourceType.isAnnotationType() && (abits & TagBits.AnnotationForAnnotationType) == 0)
1149 || (!sourceType.isAnnotationType() && (abits & TagBits.AnnotationForType) == 0)) {
1151 if (reportProblems) {
1152 if (decA.isExactPattern()) {
1153 factory.showMessage(IMessage.ERROR, WeaverMessages.format(
1154 WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION, rtx.getName(), toAdd[0].type,
1155 stringifyTargets(abits)), decA.getSourceLocation(), null);
1157 // dont put out the lint - the weaving process will do that
1160 // (factory.getWorld().getLint().invalidTargetForAnnotation
1162 // factory.getWorld().getLint().invalidTargetForAnnotation.
1164 // String[]{rtx.getName(),toAdd[0].type.toString(),
1165 // stringifyTargets(abits)},decA.getSourceLocation(),null);
1169 CompilationAndWeavingContext.leavingPhase(tok);
1174 // Build a new array of annotations
1176 // remember the current set (rememberAnnotations only does something the
1177 // first time it is called for a type)
1178 sourceType.scope.referenceContext.rememberAnnotations();
1180 // AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(
1181 // decA.getSourceLocation(), rtx.getSourceLocation());
1182 final Annotation[] abefore = sourceType.scope.referenceContext.annotations;
1183 final Annotation[] newset = new Annotation[toAdd.length + (abefore == null ? 0 : abefore.length)];
1184 System.arraycopy(toAdd, 0, newset, 0, toAdd.length);
1185 if (abefore != null) {
1186 System.arraycopy(abefore, 0, newset, toAdd.length, abefore.length);
1188 sourceType.scope.referenceContext.annotations = newset;
1189 if ((sourceType.tagBits & TagBits.AnnotationResolved)!=0) {
1190 sourceType.tagBits = sourceType.tagBits - TagBits.AnnotationResolved;
1192 CompilationAndWeavingContext.leavingPhase(tok);
1193 if (factory.pushinCollector != null) {
1194 factory.pushinCollector.tagAsMunged(sourceType, new CommonPrinter((methodDecl == null ? null : methodDecl.scope))
1195 .printAnnotation(toAdd[0]).toString());
1200 private Annotation[] retrieveAnnotationFromBinaryTypeBinding(DeclareAnnotation decA, ReferenceBinding declaringBinding) {
1201 ReferenceType rt = (ReferenceType) factory.fromEclipse(declaringBinding);
1202 ResolvedMember[] methods = rt.getDeclaredMethods();
1203 ResolvedMember decaMethod = null;
1204 String nameToLookFor = decA.getAnnotationMethod();
1205 for (ResolvedMember method : methods) {
1206 if (method.getName().equals(nameToLookFor)) {
1207 decaMethod = method;
1211 if (decaMethod != null) { // could assert this ...
1212 AnnotationAJ[] axs = decaMethod.getAnnotations();
1213 if (axs != null) { // another error has occurred, dont crash here because of it
1214 Annotation[] toAdd = new Annotation[1];
1215 toAdd[0] = createAnnotationFromBcelAnnotation(axs[0], decaMethod.getSourceLocation().getOffset(), factory);
1216 // BUG BUG BUG - We dont test these abits are correct, in fact
1217 // we'll be very lucky if they are.
1218 // What does that mean? It means on an incremental compile you
1219 // might get away with an
1220 // annotation that isn't allowed on a type being put on a type.
1221 // if (toAdd[0].resolvedType != null) {
1222 // abits = toAdd[0].resolvedType.getAnnotationTagBits();
1231 * Transform an annotation from its AJ form to an eclipse form. We *DONT* care about the values of the annotation. that is
1232 * because it is only being stuck on a type during type completion to allow for other constructs (decps, decas) that might be
1233 * looking for it - when the class actually gets to disk it wont have this new annotation on it and during weave time we will do
1234 * the right thing copying across values too.
1236 private static Annotation createAnnotationFromBcelAnnotation(AnnotationAJ annX, int pos, EclipseFactory factory) {
1237 String name = annX.getTypeName();
1238 TypeBinding tb = factory.makeTypeBinding(annX.getType());
1239 // String theName = annX.getSignature().getBaseName();
1240 char[][] typeName = CharOperation.splitOn('.', name.replace('$', '.').toCharArray()); // pr149293 - not bulletproof...
1241 long[] positions = new long[typeName.length];
1242 for (int i = 0; i < positions.length; i++) {
1245 TypeReference annType = new QualifiedTypeReference(typeName, positions);
1246 NormalAnnotation ann = new NormalAnnotation(annType, pos);
1247 ann.resolvedType = tb; // yuck - is this OK in all cases?
1248 // We don't need membervalues...
1249 // Expression pcExpr = new
1250 // StringLiteral(pointcutExpression.toCharArray(),pos,pos);
1251 // MemberValuePair[] mvps = new MemberValuePair[2];
1252 // mvps[0] = new MemberValuePair("value".toCharArray(),pos,pos,pcExpr);
1253 // Expression argNamesExpr = new
1254 // StringLiteral(argNames.toCharArray(),pos,pos);
1256 // MemberValuePair("argNames".toCharArray(),pos,pos,argNamesExpr);
1257 // ann.memberValuePairs = mvps;
1262 * Create a copy of an annotation, not deep but deep enough so we don't copy across fields that will get us into trouble like
1265 private static Annotation createAnnotationCopy(Annotation ann) {
1266 NormalAnnotation ann2 = new NormalAnnotation(ann.type, ann.sourceStart);
1267 ann2.memberValuePairs = ann.memberValuePairs();
1268 ann2.resolvedType = ann.resolvedType;
1269 ann2.bits = ann.bits;
1271 // String name = annX.getTypeName();
1272 // TypeBinding tb = factory.makeTypeBinding(annX.getSignature());
1273 // String theName = annX.getSignature().getBaseName();
1274 // char[][] typeName =
1275 // CharOperation.splitOn('.',name.replace('$','.').toCharArray());
1276 // //pr149293 - not bulletproof...
1277 // long[] positions = new long[typeName.length];
1278 // for (int i = 0; i < positions.length; i++) positions[i]=pos;
1279 // TypeReference annType = new
1280 // QualifiedTypeReference(typeName,positions);
1281 // NormalAnnotation ann = new NormalAnnotation(annType,pos);
1282 // ann.resolvedType=tb; // yuck - is this OK in all cases?
1283 // // We don't need membervalues...
1284 // // Expression pcExpr = new
1285 // StringLiteral(pointcutExpression.toCharArray(),pos,pos);
1286 // // MemberValuePair[] mvps = new MemberValuePair[2];
1288 // MemberValuePair("value".toCharArray(),pos,pos,pcExpr);
1289 // // Expression argNamesExpr = new
1290 // StringLiteral(argNames.toCharArray(),pos,pos);
1292 // MemberValuePair("argNames".toCharArray(),pos,pos,argNamesExpr);
1293 // // ann.memberValuePairs = mvps;
1297 private boolean isAnnotationTargettingSomethingOtherThanAnnotationOrNormal(long abits) {
1298 return (abits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType)) == 0;
1301 // private void reportDeclareParentsMessage(WeaveMessage.WeaveMessageKind wmk, SourceTypeBinding sourceType, ResolvedType parent) {
1302 // if (!factory.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
1303 // String filename = new String(sourceType.getFileName());
1305 // int takefrom = filename.lastIndexOf('/');
1306 // if (takefrom == -1) {
1307 // takefrom = filename.lastIndexOf('\\');
1309 // filename = filename.substring(takefrom + 1);
1311 // factory.getWorld()
1312 // .getMessageHandler()
1314 // WeaveMessage.constructWeavingMessage(wmk,
1315 // new String[] { CharOperation.toString(sourceType.compoundName), filename,
1316 // parent.getClassName(),
1317 // getShortname(parent.getSourceLocation().getSourceFile().getPath()) }));
1321 // private String getShortname(String path) {
1322 // int takefrom = path.lastIndexOf('/');
1323 // if (takefrom == -1) {
1324 // takefrom = path.lastIndexOf('\\');
1326 // return path.substring(takefrom + 1);
1329 private void addParent(SourceTypeBinding sourceType, ResolvedType parent) {
1330 ReferenceBinding parentBinding = (ReferenceBinding) factory.makeTypeBinding(parent);
1331 if (parentBinding == null) {
1332 return; // The parent is missing, it will be reported elsewhere.
1334 // Due to e37 switching to MethodVerifier15 for everything, it is important added types are correctly
1335 // raw or not. For example, if Comparable is used in generic form compareTo(T) will be used to check
1336 // methods against in the verifier rather than compareTo(Object)
1337 if (!factory.getWorld().isInJava5Mode()) {
1338 parentBinding = (ReferenceBinding)convertToRawType(parentBinding, false /*do not force conversion of enclosing types*/);
1339 } else if (sourceType.isGenericType()) {
1340 RawTypeBinding rawTargetType = (RawTypeBinding)convertToRawType(sourceType, false);
1341 if (rawTargetType != null) {
1342 // assert: don't need to 'rememberTypeHierarchy' because the class file is constructed based on the generic type
1343 if (parentBinding.isClass()) {
1344 rawTargetType.superclass = parentBinding;
1346 ReferenceBinding[] oldI = rawTargetType.superInterfaces;
1347 ReferenceBinding[] newI;
1349 newI = new ReferenceBinding[1];
1350 newI[0] = parentBinding;
1352 int n = oldI.length;
1353 newI = new ReferenceBinding[n + 1];
1354 System.arraycopy(oldI, 0, newI, 0, n);
1355 newI[n] = parentBinding;
1357 rawTargetType.superInterfaces = newI;
1360 // TODO what about parameterized types?
1362 sourceType.rememberTypeHierarchy();
1363 if (parentBinding.isClass()) {
1364 sourceType.superclass = parentBinding;
1366 // this used to be true, but I think I've fixed it now, decp is done
1368 // TAG: WeavingMessage DECLARE PARENTS: EXTENDS
1369 // Compiler restriction: Can't do EXTENDS at weave time
1370 // So, only see this message if doing a source compilation
1371 // reportDeclareParentsMessage(WeaveMessage.
1372 // WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
1375 ReferenceBinding[] oldI = sourceType.superInterfaces;
1376 ReferenceBinding[] newI;
1378 newI = new ReferenceBinding[1];
1379 newI[0] = parentBinding;
1381 int n = oldI.length;
1382 newI = new ReferenceBinding[n + 1];
1383 System.arraycopy(oldI, 0, newI, 0, n);
1384 newI[n] = parentBinding;
1386 sourceType.superInterfaces = newI;
1387 // warnOnAddedInterface(factory.fromEclipse(sourceType),parent); //
1388 // now reported at weave time...
1390 // this used to be true, but I think I've fixed it now, decp is done
1392 // TAG: WeavingMessage DECLARE PARENTS: IMPLEMENTS
1393 // This message will come out of BcelTypeMunger.munge if doing a
1395 // reportDeclareParentsMessage(WeaveMessage.
1396 // WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,sourceType,parent);
1400 // also add it to the bcel delegate if there is one
1401 if (sourceType instanceof BinaryTypeBinding) {
1402 ResolvedType onType = factory.fromEclipse(sourceType);
1403 ReferenceType rt = (ReferenceType) onType;
1404 ReferenceTypeDelegate rtd = rt.getDelegate();
1405 if (rtd instanceof BcelObjectType) {
1406 if (rt.isRawType()) {
1407 rt = rt.getGenericType();
1409 rt.addParent(parent);
1410 // ((BcelObjectType) rtd).addParent(parent);
1416 public void warnOnAddedInterface(ResolvedType type, ResolvedType parent) {
1417 World world = factory.getWorld();
1418 ResolvedType serializable = world.getCoreType(UnresolvedType.SERIALIZABLE);
1419 if (serializable.isAssignableFrom(type) && !serializable.isAssignableFrom(parent)
1420 && !LazyClassGen.hasSerialVersionUIDField(type)) {
1421 world.getLint().needsSerialVersionUIDField.signal(new String[] { type.getName().toString(),
1422 "added interface " + parent.getName().toString() }, null, null);
1426 private final List pendingTypesToFinish = new ArrayList();
1427 boolean inBinaryTypeCreationAndWeaving = false;
1428 boolean processingTheQueue = false;
1431 public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding,
1432 boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
1434 if (inBinaryTypeCreationAndWeaving) {
1435 BinaryTypeBinding ret = super.createBinaryTypeFrom(binaryType, packageBinding, needFieldsAndMethods, accessRestriction);
1436 pendingTypesToFinish.add(ret);
1440 inBinaryTypeCreationAndWeaving = true;
1442 BinaryTypeBinding ret = super.createBinaryTypeFrom(binaryType, packageBinding, needFieldsAndMethods, accessRestriction);
1443 factory.getWorld().validateType(factory.fromBinding(ret));
1444 // if you need the bytes to pass to validate, here they
1445 // are:((ClassFileReader)binaryType).getReferenceBytes()
1446 weaveInterTypeDeclarations(ret);
1449 inBinaryTypeCreationAndWeaving = false;
1451 // Start processing the list...
1452 if (pendingTypesToFinish.size() > 0) {
1453 processingTheQueue = true;
1454 while (!pendingTypesToFinish.isEmpty()) {
1455 BinaryTypeBinding nextVictim = (BinaryTypeBinding) pendingTypesToFinish.remove(0);
1456 // During this call we may recurse into this method and add
1457 // more entries to the pendingTypesToFinish list.
1458 weaveInterTypeDeclarations(nextVictim);
1460 processingTheQueue = false;
1466 * Callback driven when the compiler detects an anonymous type during block resolution. We need to add it to the weaver so that
1467 * we don't trip up later.
1472 public void anonymousTypeBindingCreated(LocalTypeBinding aBinding) {
1473 factory.addSourceTypeBinding(aBinding, null);
1477 public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) {
1478 if (this.isProcessingAnnotations && hasAspectDeclarations(unit)) {
1479 throw new SourceTypeCollisionException();
1481 super.buildTypeBindings(unit, accessRestriction);
1484 private static boolean hasAspectDeclarations(CompilationUnitDeclaration unit) {
1485 for (int j = 0; j < unit.types.length; j++) {
1486 if (unit.types[j] instanceof AspectDeclaration) {
1494 public void reset() {
1495 this.factory.cleanup();
1500 public LookupEnvironment wrapInModuleEnvironment(ModuleBinding moduleBinding) {
1501 AjLookupEnvironment newAjLookupEnvironment = new AjLookupEnvironment(this, moduleBinding);
1502 newAjLookupEnvironment.factory = this.factory;
1503 return newAjLookupEnvironment;
1507 // commented out, supplied as info on how to manipulate annotations in an
1510 // public void doDeclareAnnotationOnMethods() {
1511 // Do the declare annotation on fields/methods/ctors
1512 // Collection daoms = factory.getDeclareAnnotationOnMethods();
1513 // if (daoms!=null && daoms.size()>0 && !(sourceType instanceof
1514 // BinaryTypeBinding)) {
1515 // System.err.println("Going through the methods on "+sourceType.debugName()+
1516 // " looking for DECA matches");
1517 // // We better take a look through them...
1518 // for (Iterator iter = daoms.iterator(); iter.hasNext();) {
1519 // DeclareAnnotation element = (DeclareAnnotation) iter.next();
1520 // System.err.println("Looking for anything that might match "+element+" on "+
1521 // sourceType.debugName()+" "+getType(sourceType.
1522 // compoundName).debugName()+" "+(sourceType instanceof BinaryTypeBinding));
1524 // ReferenceBinding rbb = getType(sourceType.compoundName);
1525 // // fix me if we ever uncomment this code... should iterate the other way
1526 // round, over the methods then over the decas
1527 // sourceType.methods();
1528 // MethodBinding sourceMbs[] = sourceType.methods;
1529 // for (int i = 0; i < sourceMbs.length; i++) {
1530 // MethodBinding sourceMb = sourceMbs[i];
1531 // MethodBinding mbbbb =
1532 // ((SourceTypeBinding)rbb).getExactMethod(sourceMb.selector
1533 // ,sourceMb.parameters);
1534 // boolean isCtor = sourceMb.selector[0]=='<';
1536 // if ((element.isDeclareAtConstuctor() ^ !isCtor)) {
1537 // System.err.println("Checking "+sourceMb+" ... declaringclass="+sourceMb.
1538 // declaringClass.debugName()+" rbb="+rbb.debugName()+" "+
1539 // sourceMb.declaringClass.equals(rbb));
1541 // ResolvedMember rm = null;
1542 // rm = EclipseFactory.makeResolvedMember(mbbbb);
1543 // if (element.matches(rm,factory.getWorld())) {
1544 // System.err.println("MATCH");
1546 // // Determine the set of annotations that are currently on the method
1547 // ReferenceBinding rb = getType(sourceType.compoundName);
1548 // // TypeBinding tb = factory.makeTypeBinding(decA.getAspect());
1549 // MethodBinding mb =
1550 // ((SourceTypeBinding)rb).getExactMethod(sourceMb.selector,sourceMb
1552 // //long abits = mbs[0].getAnnotationTagBits(); // ensure resolved
1553 // TypeDeclaration typeDecl =
1554 // ((SourceTypeBinding)sourceMb.declaringClass).scope.referenceContext;
1555 // AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(sourceMb);
1556 // Annotation[] currentlyHas = methodDecl.annotations; // this is what to add
1557 // //abits = toAdd[0].resolvedType.getAnnotationTagBits();
1559 // // Determine the annotations to add to that method
1560 // TypeBinding tb = factory.makeTypeBinding(element.getAspect());
1561 // MethodBinding[] aspectMbs =
1562 // ((SourceTypeBinding)tb).getMethods(element.getAnnotationMethod
1563 // ().toCharArray());
1564 // long abits = aspectMbs[0].getAnnotationTagBits(); // ensure resolved
1565 // TypeDeclaration typeDecl2 =
1566 // ((SourceTypeBinding)aspectMbs[0].declaringClass).scope.referenceContext;
1567 // AbstractMethodDeclaration methodDecl2 =
1568 // typeDecl2.declarationOf(aspectMbs[0]);
1569 // Annotation[] toAdd = methodDecl2.annotations; // this is what to add
1570 // // abits = toAdd[0].resolvedType.getAnnotationTagBits();
1571 // System.err.println("Has: "+currentlyHas+" toAdd: "+toAdd);
1573 // // fix me? should check if it already has the annotation
1574 // //Annotation abefore[] = sourceType.scope.referenceContext.annotations;
1575 // Annotation[] newset = new
1576 // Annotation[(currentlyHas==null?0:currentlyHas.length)+1];
1577 // System.arraycopy(toAdd,0,newset,0,toAdd.length);
1578 // if (currentlyHas!=null) {
1579 // System.arraycopy(currentlyHas,0,newset,1,currentlyHas.length);
1581 // methodDecl.annotations = newset;
1582 // System.err.println("New set on "+CharOperation.charToString(sourceMb.selector)
1585 // System.err.println("NO MATCH");
1592 // commented out, supplied as info on how to manipulate annotations in an
1595 // public void doDeclareAnnotationOnFields() {
1596 // Collection daofs = factory.getDeclareAnnotationOnFields();
1597 // if (daofs!=null && daofs.size()>0 && !(sourceType instanceof
1598 // BinaryTypeBinding)) {
1599 // System.err.println("Going through the fields on "+sourceType.debugName()+
1600 // " looking for DECA matches");
1601 // // We better take a look through them...
1602 // for (Iterator iter = daofs.iterator(); iter.hasNext();) {
1603 // DeclareAnnotation element = (DeclareAnnotation) iter.next();
1604 // System.err.println("Processing deca "+element+" on "+sourceType.debugName()+
1605 // " "+getType(sourceType.compoundName).debugName()+" "
1606 // +(sourceType instanceof BinaryTypeBinding));
1608 // ReferenceBinding rbb = getType(sourceType.compoundName);
1609 // // fix me? should iterate the other way round, over the methods then over the
1611 // sourceType.fields(); // resolve the bloody things
1612 // FieldBinding sourceFbs[] = sourceType.fields;
1613 // for (int i = 0; i < sourceFbs.length; i++) {
1614 // FieldBinding sourceFb = sourceFbs[i];
1615 // //FieldBinding fbbbb =
1616 // ((SourceTypeBinding)rbb).getgetExactMethod(sourceMb.selector
1617 // ,sourceMb.parameters);
1619 // System.err.println("Checking "+sourceFb+" ... declaringclass="+sourceFb.
1620 // declaringClass.debugName()+" rbb="+rbb.debugName());
1622 // ResolvedMember rm = null;
1623 // rm = EclipseFactory.makeResolvedMember(sourceFb);
1624 // if (element.matches(rm,factory.getWorld())) {
1625 // System.err.println("MATCH");
1627 // // Determine the set of annotations that are currently on the field
1628 // ReferenceBinding rb = getType(sourceType.compoundName);
1629 // // TypeBinding tb = factory.makeTypeBinding(decA.getAspect());
1630 // FieldBinding fb = ((SourceTypeBinding)rb).getField(sourceFb.name,true);
1631 // //long abits = mbs[0].getAnnotationTagBits(); // ensure resolved
1632 // TypeDeclaration typeDecl =
1633 // ((SourceTypeBinding)sourceFb.declaringClass).scope.referenceContext;
1634 // FieldDeclaration fd = typeDecl.declarationOf(sourceFb);
1635 // //AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(sourceMb);
1636 // Annotation[] currentlyHas = fd.annotations; // this is what to add
1637 // //abits = toAdd[0].resolvedType.getAnnotationTagBits();
1639 // // Determine the annotations to add to that method
1640 // TypeBinding tb = factory.makeTypeBinding(element.getAspect());
1641 // MethodBinding[] aspectMbs =
1642 // ((SourceTypeBinding)tb).getMethods(element.getAnnotationMethod
1643 // ().toCharArray());
1644 // long abits = aspectMbs[0].getAnnotationTagBits(); // ensure resolved
1645 // TypeDeclaration typeDecl2 =
1646 // ((SourceTypeBinding)aspectMbs[0].declaringClass).scope.referenceContext;
1647 // AbstractMethodDeclaration methodDecl2 =
1648 // typeDecl2.declarationOf(aspectMbs[0]);
1649 // Annotation[] toAdd = methodDecl2.annotations; // this is what to add
1650 // // abits = toAdd[0].resolvedType.getAnnotationTagBits();
1651 // System.err.println("Has: "+currentlyHas+" toAdd: "+toAdd);
1653 // // fix me? check if it already has the annotation
1656 // //Annotation abefore[] = sourceType.scope.referenceContext.annotations;
1657 // Annotation[] newset = new
1658 // Annotation[(currentlyHas==null?0:currentlyHas.length)+1];
1659 // System.arraycopy(toAdd,0,newset,0,toAdd.length);
1660 // if (currentlyHas!=null) {
1661 // System.arraycopy(currentlyHas,0,newset,1,currentlyHas.length);
1663 // fd.annotations = newset;
1664 // System.err.println("New set on "+CharOperation.charToString(sourceFb.name)+
1667 // System.err.println("NO MATCH");