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 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
10 * PARC initial implementation
11 * ******************************************************************/
13 package org.aspectj.ajdt.internal.compiler.lookup;
15 import java.lang.reflect.Modifier;
18 import org.aspectj.ajdt.internal.compiler.CommonPrinter;
19 import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
20 import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
21 import org.aspectj.asm.AsmManager;
22 import org.aspectj.bridge.IMessage;
23 import org.aspectj.bridge.context.CompilationAndWeavingContext;
24 import org.aspectj.bridge.context.ContextToken;
25 import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
26 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
27 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
28 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
29 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
30 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
31 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
32 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
33 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
34 import org.aspectj.org.eclipse.jdt.internal.compiler.env.AccessRestriction;
35 import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType;
36 import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment;
37 import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
38 import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
39 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
40 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
41 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
42 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
43 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
44 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
45 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding;
46 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
47 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
48 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
49 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
50 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
51 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
52 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException;
53 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
54 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
55 import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
56 import org.aspectj.weaver.AnnotationAJ;
57 import org.aspectj.weaver.ConcreteTypeMunger;
58 import org.aspectj.weaver.ReferenceType;
59 import org.aspectj.weaver.ReferenceTypeDelegate;
60 import org.aspectj.weaver.ResolvedMember;
61 import org.aspectj.weaver.ResolvedType;
62 import org.aspectj.weaver.ResolvedTypeMunger;
63 import org.aspectj.weaver.UnresolvedType;
64 import org.aspectj.weaver.WeaverMessages;
65 import org.aspectj.weaver.WeaverStateInfo;
66 import org.aspectj.weaver.World;
67 import org.aspectj.weaver.bcel.BcelAnnotation;
68 import org.aspectj.weaver.bcel.BcelObjectType;
69 import org.aspectj.weaver.bcel.FakeAnnotation;
70 import org.aspectj.weaver.bcel.LazyClassGen;
71 import org.aspectj.weaver.patterns.Declare;
72 import org.aspectj.weaver.patterns.DeclareAnnotation;
73 import org.aspectj.weaver.patterns.DeclareParents;
76 * Overrides the default eclipse LookupEnvironment for two purposes.
78 * 1. To provide some additional phases to <code>completeTypeBindings</code> that weave declare parents and inter-type declarations
79 * at the correct time.
81 * 2. To intercept the loading of new binary types to ensure the they will have declare parents and inter-type declarations woven
86 public class AjLookupEnvironment extends LookupEnvironment implements AnonymousClassCreationListener {
87 public EclipseFactory factory = null;
89 // private boolean builtInterTypesAndPerClauses = false;
90 private final List<SourceTypeBinding> pendingTypesToWeave = new ArrayList<>();
92 // Q: What are dangerousInterfaces?
93 // A: An interface is considered dangerous if an ITD has been made upon it
95 // requires the top most implementors of the interface to be woven *and yet*
97 // responsible for the ITD is not in the 'world'.
98 // Q: Err, how can that happen?
99 // A: When a type is on the inpath, it is 'processed' when completing type
101 // point we look at any type mungers it was affected by previously (stored
103 // state info attribute). Effectively we are working with a type munger and
104 // yet may not have its
105 // originating aspect in the world. This is a problem if, for example, the
107 // a 'body' for a method targetting an interface - since the top most
108 // implementors should
109 // be woven by the munger from the aspect. When this happens we store the
110 // interface name here
111 // in the map - if we later process a type that is the topMostImplementor of
113 // interface then we put out an error message.
116 * interfaces targetted by ITDs that have to be implemented by accessing the topMostImplementor of the interface, yet the aspect
117 * where the ITD originated is not in the world
119 private final Map<ResolvedType, String> dangerousInterfaces = new HashMap<>();
121 public AjLookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter,
122 INameEnvironment nameEnvironment) {
123 super(typeRequestor, options, problemReporter, nameEnvironment);
126 public AjLookupEnvironment(LookupEnvironment env, ModuleBinding moduleBinding) {
127 super(env, moduleBinding);
130 // ??? duplicates some of super's code
132 public void completeTypeBindings() {
133 AsmManager.setCompletingTypeBindings(true);
134 ContextToken completeTypeBindingsToken = CompilationAndWeavingContext.enteringPhase(
135 CompilationAndWeavingContext.COMPLETING_TYPE_BINDINGS, "");
136 // builtInterTypesAndPerClauses = false;
137 // pendingTypesToWeave = new ArrayList();
138 stepCompleted = BUILD_TYPE_HIERARCHY;
140 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
141 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CHECK_AND_SET_IMPORTS,
142 units[i].compilationResult.fileName);
143 units[i].scope.checkAndSetImports();
144 CompilationAndWeavingContext.leavingPhase(tok);
146 stepCompleted = CHECK_AND_SET_IMPORTS;
148 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
149 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CONNECTING_TYPE_HIERARCHY1,
150 units[i].compilationResult.fileName);
151 units[i].scope.connectTypeHierarchy1();
152 CompilationAndWeavingContext.leavingPhase(tok);
154 stepCompleted = CONNECT_TYPE_HIERARCHY1;
155 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
156 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CONNECTING_TYPE_HIERARCHY2,
157 units[i].compilationResult.fileName);
158 units[i].scope.connectTypeHierarchy2();
159 CompilationAndWeavingContext.leavingPhase(tok);
161 stepCompleted = CONNECT_TYPE_HIERARCHY2;
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<>();
194 List<SourceTypeBinding> aspectsToProcess = new ArrayList<>();
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<>();
254 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
255 CompilationUnitScope cus = units[i].scope;
256 SourceTypeBinding[] stbs = cus.topLevelTypes;
257 Collections.addAll(typesToProcess, stbs);
260 List<SourceTypeBinding> stb2 = new ArrayList<>(typesToProcess);
262 while (typesToProcess.size() > 0) {
263 // A side effect of weaveIntertypes() is that the processed type is removed from the collection
264 weaveIntertypes(typesToProcess, typesToProcess.get(0), typeMungers, declareParents, declareAnnotationOnTypes, 1);
267 while (stb2.size() > 0) {
268 // A side effect of weaveIntertypes() is that the processed type is removed from the collection
269 weaveIntertypes(stb2, stb2.get(0), typeMungers, declareParents, declareAnnotationOnTypes, 2);
273 // Order isn't important
274 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
275 weaveInterTypeDeclarations(units[i].scope, typeMungers, declareParents, declareAnnotationOnTypes);
279 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
280 units[i].scope.checkParameterizedTypes();
283 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
284 SourceTypeBinding[] b = units[i].scope.topLevelTypes;
285 for (SourceTypeBinding sourceTypeBinding : b) {
286 ContextToken tok = CompilationAndWeavingContext.enteringPhase(
287 CompilationAndWeavingContext.RESOLVING_POINTCUT_DECLARATIONS, sourceTypeBinding.sourceName);
288 resolvePointcutDeclarations(sourceTypeBinding.scope);
289 CompilationAndWeavingContext.leavingPhase(tok);
293 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
294 SourceTypeBinding[] b = units[i].scope.topLevelTypes;
295 for (SourceTypeBinding sourceTypeBinding : b) {
296 ContextToken tok = CompilationAndWeavingContext.enteringPhase(
297 CompilationAndWeavingContext.ADDING_DECLARE_WARNINGS_AND_ERRORS, sourceTypeBinding.sourceName);
298 addAdviceLikeDeclares(sourceTypeBinding.scope);
299 CompilationAndWeavingContext.leavingPhase(tok);
303 for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
304 units[i] = null; // release unnecessary reference to the parsed unit
307 stepCompleted = BUILD_FIELDS_AND_METHODS;
308 lastCompletedUnitIndex = lastUnitIndex;
309 AsmManager.setCompletingTypeBindings(false);
310 factory.getWorld().getCrosscuttingMembersSet().verify();
311 CompilationAndWeavingContext.leavingPhase(completeTypeBindingsToken);
313 if (isProcessingAnnotations) {
314 throw new SourceTypeCollisionException(); // TODO(yushkovskiy): temporary solution; forcing to recompile units to insert mungers into types
319 // * For any given sourcetypebinding, this method checks that if it is a
320 // parameterized aspect that
321 // * the type parameters specified for any supertypes meet the bounds for
325 // private void verifyAnyTypeParametersMeetBounds(SourceTypeBinding
327 // ResolvedType onType = factory.fromEclipse(sourceType);
328 // if (onType.isAspect()) {
329 // ResolvedType superType = factory.fromEclipse(sourceType.superclass);
330 // // Don't need to check if it was used in its RAW form or isnt generic
331 // if (superType.isGenericType() || superType.isParameterizedType()) {
332 // TypeVariable[] typeVariables = superType.getTypeVariables();
333 // UnresolvedType[] typeParams = superType.getTypeParameters();
334 // if (typeVariables!=null && typeParams!=null) {
335 // for (int i = 0; i < typeVariables.length; i++) {
337 // typeVariables[i].canBeBoundTo(typeParams[i].resolve(factory.getWorld()));
338 // if (!ok) { // the supplied parameter violates the bounds
339 // // Type {0} does not meet the specification for type parameter {1} ({2})
340 // in generic type {3}
342 // WeaverMessages.format(
343 // WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
346 // typeVariables[i].getDisplayName(),
347 // superType.getGenericType().getName());
348 // factory.getWorld().getMessageHandler().handleMessage(MessageUtil.error(msg
349 // ,onType.getSourceLocation()));
357 public void doSupertypesFirst(ReferenceBinding rb, Collection<? extends ReferenceBinding> yetToProcess) {
358 if (rb instanceof SourceTypeBinding) {
359 if (yetToProcess.contains(rb)) {
360 collectAllITDsAndDeclares((SourceTypeBinding) rb, yetToProcess);
362 } else if (rb instanceof ParameterizedTypeBinding) {
363 // If its a PTB we need to pull the SourceTypeBinding out of it.
364 ParameterizedTypeBinding ptb = (ParameterizedTypeBinding) rb;
365 if (ptb.type instanceof SourceTypeBinding && yetToProcess.contains(ptb.type)) {
366 collectAllITDsAndDeclares((SourceTypeBinding) ptb.type, yetToProcess);
372 * Find all the ITDs and Declares, but it is important we do this from the supertypes down to the subtypes.
375 * @param yetToProcess
377 private void collectAllITDsAndDeclares(SourceTypeBinding sourceType, Collection<? extends ReferenceBinding> yetToProcess) {
378 // Look at the supertype first
379 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.COLLECTING_ITDS_AND_DECLARES,
380 sourceType.sourceName);
382 yetToProcess.remove(sourceType);
383 // look out our direct supertype
384 doSupertypesFirst(sourceType.superclass(), yetToProcess);
386 // now check our membertypes (pr119570)
387 ReferenceBinding[] memberTypes = sourceType.memberTypes;
388 for (ReferenceBinding memberType : memberTypes) {
389 SourceTypeBinding rb = (SourceTypeBinding) memberType;
390 if (!rb.superclass().equals(sourceType)) {
391 doSupertypesFirst(rb.superclass(), yetToProcess);
395 buildInterTypeAndPerClause(sourceType.scope);
396 addCrosscuttingStructures(sourceType.scope);
397 CompilationAndWeavingContext.leavingPhase(tok);
401 * Weave the parents and intertype decls into a given type. This method looks at the supertype and superinterfaces for the
402 * specified type and recurses to weave those first if they are in the full list of types we are going to process during this
403 * compile... it stops recursing the first time it hits a type we aren't going to process during this compile. This could cause
404 * 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
405 * doing if you do that?
407 * @param mode 0=do everything, 1=do declare parents, 2=do ITDs
409 private void weaveIntertypes(List<SourceTypeBinding> typesToProcess, SourceTypeBinding typeToWeave,
410 List<ConcreteTypeMunger> typeMungers, List<DeclareParents> declareParents,
411 List<DeclareAnnotation> declareAnnotationOnTypes, int mode) {
412 // Look at the supertype first
413 ReferenceBinding superType = typeToWeave.superclass();
414 if (typesToProcess.contains(superType) && superType instanceof SourceTypeBinding) {
415 // System.err.println("Recursing to supertype "+new
416 // String(superType.getFileName()));
417 weaveIntertypes(typesToProcess, (SourceTypeBinding) superType, typeMungers, declareParents, declareAnnotationOnTypes,
420 // Then look at the superinterface list
421 ReferenceBinding[] interfaceTypes = typeToWeave.superInterfaces();
422 for (ReferenceBinding binding : interfaceTypes) {
423 if (typesToProcess.contains(binding) && binding instanceof SourceTypeBinding) {
424 // System.err.println("Recursing to superinterface "+new
425 // String(binding.getFileName()));
426 weaveIntertypes(typesToProcess, (SourceTypeBinding) binding, typeMungers, declareParents, declareAnnotationOnTypes,
428 } else if (binding instanceof ParameterizedTypeBinding && (((ParameterizedTypeBinding) binding).type instanceof SourceTypeBinding) && typesToProcess.contains(((ParameterizedTypeBinding) binding).type)) {
429 weaveIntertypes(typesToProcess, (SourceTypeBinding) ((ParameterizedTypeBinding) binding).type, typeMungers, declareParents, declareAnnotationOnTypes, mode);
432 weaveInterTypeDeclarations(typeToWeave, typeMungers, declareParents, declareAnnotationOnTypes, false, mode);
433 typesToProcess.remove(typeToWeave);
436 private void doPendingWeaves() {
437 for (SourceTypeBinding t: pendingTypesToWeave) {
438 ContextToken tok = CompilationAndWeavingContext.enteringPhase(
439 CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS, t.sourceName);
440 weaveInterTypeDeclarations(t);
441 CompilationAndWeavingContext.leavingPhase(tok);
443 pendingTypesToWeave.clear();
446 private void addAdviceLikeDeclares(ClassScope s) {
447 TypeDeclaration dec = s.referenceContext;
449 if (dec instanceof AspectDeclaration) {
450 ResolvedType typeX = factory.fromEclipse(dec.binding);
451 factory.getWorld().getCrosscuttingMembersSet().addAdviceLikeDeclares(typeX);
454 SourceTypeBinding sourceType = s.referenceContext.binding;
455 ReferenceBinding[] memberTypes = sourceType.memberTypes;
456 for (ReferenceBinding memberType : memberTypes) {
457 addAdviceLikeDeclares(((SourceTypeBinding) memberType).scope);
461 private void addCrosscuttingStructures(ClassScope s) {
462 TypeDeclaration dec = s.referenceContext;
464 if (dec instanceof AspectDeclaration) {
465 ResolvedType typeX = factory.fromEclipse(dec.binding);
466 factory.getWorld().getCrosscuttingMembersSet().addOrReplaceAspect(typeX, false);
468 if (typeX.getSuperclass().isAspect() && !typeX.getSuperclass().isExposedToWeaver()) {
469 factory.getWorld().getCrosscuttingMembersSet().addOrReplaceAspect(typeX.getSuperclass(), false);
473 SourceTypeBinding sourceType = s.referenceContext.binding;
474 ReferenceBinding[] memberTypes = sourceType.memberTypes;
475 for (ReferenceBinding memberType : memberTypes) {
476 addCrosscuttingStructures(((SourceTypeBinding) memberType).scope);
480 private void resolvePointcutDeclarations(ClassScope s) {
481 TypeDeclaration dec = s.referenceContext;
482 SourceTypeBinding sourceType = s.referenceContext.binding;
483 boolean hasPointcuts = false;
484 AbstractMethodDeclaration[] methods = dec.methods;
485 boolean initializedMethods = false;
486 if (methods != null) {
487 for (AbstractMethodDeclaration method : methods) {
488 if (method instanceof PointcutDeclaration) {
490 if (!initializedMethods) {
491 sourceType.methods(); // force initialization
492 initializedMethods = true;
494 ((PointcutDeclaration) method).resolvePointcut(s);
499 if (hasPointcuts || dec instanceof AspectDeclaration || couldBeAnnotationStyleAspectDeclaration(dec)) {
500 ReferenceType name = (ReferenceType) factory.fromEclipse(sourceType);
501 EclipseSourceType eclipseSourceType = (EclipseSourceType) name.getDelegate();
502 eclipseSourceType.checkPointcutDeclarations();
505 ReferenceBinding[] memberTypes = sourceType.memberTypes;
506 for (ReferenceBinding memberType : memberTypes) {
507 resolvePointcutDeclarations(((SourceTypeBinding) memberType).scope);
512 * Return true if the declaration has @Aspect annotation. Called 'couldBe' rather than 'is' because someone else may have
513 * defined an annotation called Aspect - we can't verify the full name (including package name) because it may not have been
514 * resolved just yet and rather going through expensive resolution when we dont have to, this gives us a cheap check that tells
515 * us whether to bother.
517 private boolean couldBeAnnotationStyleAspectDeclaration(TypeDeclaration dec) {
518 Annotation[] annotations = dec.annotations;
519 boolean couldBeAtAspect = false;
520 if (annotations != null) {
521 for (int i = 0; i < annotations.length && !couldBeAtAspect; i++) {
522 if (annotations[i].toString().equals("@Aspect")) {
523 couldBeAtAspect = true;
527 return couldBeAtAspect;
531 * Applies any intertype member type declarations up front.
533 private void processInterTypeMemberTypes(ClassScope classScope) {
534 TypeDeclaration dec = classScope.referenceContext;
535 if (dec instanceof AspectDeclaration) {
536 ((AspectDeclaration) dec).processIntertypeMemberTypes(classScope);
538 // if we are going to support nested aspects making itd member types, copy the logic from the end of
539 // buildInterTypeAndPerClause() which walks members
542 private void buildInterTypeAndPerClause(ClassScope s) {
543 TypeDeclaration dec = s.referenceContext;
544 if (dec instanceof AspectDeclaration) {
545 ((AspectDeclaration) dec).buildInterTypeAndPerClause(s);
548 SourceTypeBinding sourceType = s.referenceContext.binding;
549 // test classes don't extend aspects
550 if (sourceType.superclass != null) {
551 ResolvedType parent = factory.fromEclipse(sourceType.superclass);
552 if (parent.isAspect() && !isAspect(dec)) {
553 factory.showMessage(IMessage.ERROR, "class \'" + new String(sourceType.sourceName) + "\' can not extend aspect \'"
554 + parent.getName() + "\'", factory.fromEclipse(sourceType).getSourceLocation(), null);
558 ReferenceBinding[] memberTypes = sourceType.memberTypes;
559 if (memberTypes == null) {
560 System.err.println("Unexpectedly found null for memberTypes of " + sourceType.debugName());
562 if (memberTypes != null) {
563 for (ReferenceBinding memberType : memberTypes) {
564 buildInterTypeAndPerClause(((SourceTypeBinding) memberType).scope);
569 private boolean isAspect(TypeDeclaration decl) {
570 if ((decl instanceof AspectDeclaration)) {
572 } else if (decl.annotations == null) {
575 for (int i = 0; i < decl.annotations.length; i++) {
576 Annotation ann = decl.annotations[i];
577 if (ann.type instanceof SingleTypeReference) {
578 if (CharOperation.equals("Aspect".toCharArray(), ((SingleTypeReference) ann.type).token)) {
581 } else if (ann.type instanceof QualifiedTypeReference) {
582 QualifiedTypeReference qtr = (QualifiedTypeReference) ann.type;
583 if (qtr.tokens.length != 5) {
586 if (!CharOperation.equals("org".toCharArray(), qtr.tokens[0])) {
589 if (!CharOperation.equals("aspectj".toCharArray(), qtr.tokens[1])) {
592 if (!CharOperation.equals("lang".toCharArray(), qtr.tokens[2])) {
595 if (!CharOperation.equals("annotation".toCharArray(), qtr.tokens[3])) {
598 if (!CharOperation.equals("Aspect".toCharArray(), qtr.tokens[4])) {
608 private void weaveInterTypeDeclarations(CompilationUnitScope unit, List<ConcreteTypeMunger> typeMungers,
609 List<DeclareParents> declareParents, List<DeclareAnnotation> declareAnnotationOnTypes) {
610 for (int i = 0, length = unit.topLevelTypes.length; i < length; i++) {
611 weaveInterTypeDeclarations(unit.topLevelTypes[i], typeMungers, declareParents, declareAnnotationOnTypes, false, 0);
615 private void weaveInterTypeDeclarations(SourceTypeBinding sourceType) {
616 if (!factory.areTypeMungersFinished()) {
617 if (!pendingTypesToWeave.contains(sourceType)) {
618 pendingTypesToWeave.add(sourceType);
620 // inner type ITD support - may need this for some incremental cases...
621 // List<ConcreteTypeMunger> ctms = factory.getWorld().getCrosscuttingMembersSet().getTypeMungersOfKind(
622 // ResolvedTypeMunger.InnerClass);
623 // // List<ConcreteTypeMunger> innerTypeMungers = new ArrayList<ConcreteTypeMunger>();
624 // // for (ConcreteTypeMunger ctm : ctms) {
625 // // if (ctm.getMunger() != null && ctm.getMunger().getKind() == ResolvedTypeMunger.InnerClass) {
626 // // innerTypeMungers.add(ctm);
629 // // that includes the innertype one...
630 // // doPendingWeaves at this level is about applying inner class
631 // BinaryTypeBinding t = (BinaryTypeBinding) sourceType;
632 // for (ConcreteTypeMunger ctm : innerTypeMungers) {
633 // NewMemberClassTypeMunger nmctm = (NewMemberClassTypeMunger) ctm.getMunger();
634 // ReferenceBinding[] rbs = t.memberTypes;
635 // UnresolvedType ut = factory.fromBinding(t);
636 // if (ut.equals(nmctm.getTargetType())) {
637 // // got a match here
638 // SourceTypeBinding aspectTypeBinding = (SourceTypeBinding) factory.makeTypeBinding(ctm.getAspectType());
640 // char[] mungerMemberTypeName = ("$" + nmctm.getMemberTypeName()).toCharArray();
641 // ReferenceBinding innerTypeBinding = null;
642 // for (ReferenceBinding innerType : aspectTypeBinding.memberTypes) {
643 // char[] compounded = CharOperation.concatWith(innerType.compoundName, '.');
644 // if (org.aspectj.org.eclipse.jdt.core.compiler.CharOperation.endsWith(compounded, mungerMemberTypeName)) {
645 // innerTypeBinding = innerType;
649 // // may be unresolved if the aspect type binding was a BinaryTypeBinding
650 // if (innerTypeBinding instanceof UnresolvedReferenceBinding) {
651 // innerTypeBinding = BinaryTypeBinding
652 // .resolveType(innerTypeBinding, factory.getLookupEnvironment(), true);
654 // t.memberTypes(); // cause initialization
655 // t.memberTypes = new ReferenceBinding[] { innerTypeBinding };
658 // // The inner type from the aspect should be put into the membertypebindings for this
665 weaveInterTypeDeclarations(sourceType, factory.getTypeMungers(), factory.getDeclareParents(),
666 factory.getDeclareAnnotationOnTypes(), true, 0);
671 * @param mode 0=do everything, 1=do declare parents, 2=do ITDs
673 private void weaveInterTypeDeclarations(SourceTypeBinding sourceType, List<ConcreteTypeMunger> typeMungers,
674 List<DeclareParents> declareParents, List<DeclareAnnotation> declareAnnotationOnTypes, boolean skipInners, int mode) {
676 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS,
677 sourceType.sourceName);
679 ResolvedType onType = factory.fromEclipse(sourceType);
681 // AMC we shouldn't need this when generic sigs are fixed??
682 if (onType.isRawType()) {
683 onType = onType.getGenericType();
686 WeaverStateInfo info = onType.getWeaverState();
689 // this test isnt quite right - there will be a case where we fail to
691 // with a 'dangerous interface' because the type is reweavable when we
693 // because the type wasn't going to be rewoven... if that happens, we
695 // move this test and dangerous interface processing to the end of this
697 // make it conditional on whether any of the typeMungers passed into
699 // matched this type.
700 if (info != null && !info.isOldStyle() && !info.isReweavable()) {
701 processTypeMungersFromExistingWeaverState(sourceType, onType);
702 CompilationAndWeavingContext.leavingPhase(tok);
706 // Check if the type we are looking at is the topMostImplementor of a
707 // dangerous interface -
708 // report a problem if it is.
709 for (Map.Entry<ResolvedType, String> entry : dangerousInterfaces.entrySet()) {
710 ResolvedType interfaceType = entry.getKey();
711 if (onType.isTopmostImplementor(interfaceType)) {
712 factory.showMessage(IMessage.ERROR, onType + ": " + entry.getValue(), onType.getSourceLocation(), null);
716 boolean needOldStyleWarning = (info != null && info.isOldStyle());
718 onType.clearInterTypeMungers();
719 onType.ensureConsistent();
721 // FIXME asc perf Could optimize here, after processing the expected set
722 // of types we may bring
723 // binary types that are not exposed to the weaver, there is no need to
724 // attempt declare parents
725 // or declare annotation really - unless we want to report the
726 // not-exposed to weaver
729 List<DeclareParents> decpToRepeat = new ArrayList<>();
730 List<DeclareAnnotation> decaToRepeat = new ArrayList<>();
731 boolean anyNewParents = false;
732 boolean anyNewAnnotations = false;
735 // try and apply all decps - if they match, then great. If they don't
737 // check if they are starred-annotation patterns. If they are not
739 // annotation patterns then they might match later...remember that...
740 for (DeclareParents decp : declareParents) {
741 if (!decp.isMixin()) {
742 boolean didSomething = doDeclareParents(decp, sourceType);
744 if (factory.pushinCollector != null) {
745 factory.pushinCollector.tagAsMunged(sourceType, decp.getParents().get(0));
747 anyNewParents = true;
749 if (!decp.getChild().isStarAnnotation()) {
750 decpToRepeat.add(decp);
756 for (DeclareAnnotation deca : declareAnnotationOnTypes) {
757 boolean didSomething = doDeclareAnnotations(deca, sourceType, true);
759 anyNewAnnotations = true;
761 if (!deca.getTypePattern().isStar()) {
762 decaToRepeat.add(deca);
767 List<Declare> forRemoval = new ArrayList<>();
768 // now lets loop over and over until we have done all we can
769 while ((anyNewAnnotations || anyNewParents) && (!decpToRepeat.isEmpty() || !decaToRepeat.isEmpty())) {
770 anyNewParents = anyNewAnnotations = false;
772 for (DeclareParents decp : decpToRepeat) {
773 boolean didSomething = doDeclareParents(decp, sourceType);
775 if (factory.pushinCollector != null) {
776 factory.pushinCollector.tagAsMunged(sourceType, decp.getParents().get(0));
778 anyNewParents = true;
779 forRemoval.add(decp);
782 decpToRepeat.removeAll(forRemoval);
785 for (DeclareAnnotation deca : decaToRepeat) {
786 boolean didSomething = doDeclareAnnotations(deca, sourceType, false);
788 if (factory.pushinCollector != null) {
789 factory.pushinCollector.tagAsMunged(sourceType, deca.getAnnotationString());
791 anyNewAnnotations = true;
792 forRemoval.add(deca);
795 decaToRepeat.removeAll(forRemoval);
798 if (mode == 0 || mode == 2) {
799 for (ConcreteTypeMunger typeMunger : typeMungers) {
800 EclipseTypeMunger munger = (EclipseTypeMunger) typeMunger;
801 if (munger.matches(onType)) {
802 // if (needOldStyleWarning) {
803 // factory.showMessage(IMessage.WARNING, "The class for " + onType
804 // + " should be recompiled with ajc-1.1.1 for best results", onType.getSourceLocation(), null);
805 // needOldStyleWarning = false;
807 onType.addInterTypeMunger(munger, true);
808 if (munger.getMunger() != null && munger.getMunger().getKind() == ResolvedTypeMunger.InnerClass) {
809 // Must do these right now, because if we do an ITD member afterwards it may attempt to reference the
810 // type being applied (the call above 'addInterTypeMunger' will fail for these ITDs if it needed
811 // it to be in place)
812 if (munger.munge(sourceType, onType)) {
813 if (factory.pushinCollector != null) {
814 factory.pushinCollector.tagAsMunged(sourceType, munger.getSourceMethod());
821 onType.checkInterTypeMungers();
822 for (ConcreteTypeMunger concreteTypeMunger : onType.getInterTypeMungers()) {
823 EclipseTypeMunger munger = (EclipseTypeMunger) concreteTypeMunger;
824 if (munger.getMunger() == null || munger.getMunger().getKind() != ResolvedTypeMunger.InnerClass) {
825 if (munger.munge(sourceType, onType)) {
826 if (factory.pushinCollector != null) {
827 factory.pushinCollector.tagAsMunged(sourceType, munger.getSourceMethod());
834 // Call if you would like to do source weaving of declare
835 // @method/@constructor
836 // at source time... no need to do this as it can't impact anything, but
838 // future generations to enjoy. Method source is commented out at the
839 // end of this module
840 // doDeclareAnnotationOnMethods();
842 // Call if you would like to do source weaving of declare @field
843 // at source time... no need to do this as it can't impact anything, but
845 // future generations to enjoy. Method source is commented out at the
846 // end of this module
847 // doDeclareAnnotationOnFields();
850 CompilationAndWeavingContext.leavingPhase(tok);
854 ReferenceBinding[] memberTypes = sourceType.memberTypes;
855 for (ReferenceBinding memberType : memberTypes) {
856 if (memberType instanceof SourceTypeBinding) {
857 weaveInterTypeDeclarations((SourceTypeBinding) memberType, typeMungers, declareParents,
858 declareAnnotationOnTypes, false, mode);
861 CompilationAndWeavingContext.leavingPhase(tok);
865 * Called when we discover we are weaving intertype declarations on some type that has an existing 'WeaverStateInfo' object -
866 * this is typically some previously woven type that has been passed on the inpath.
868 * sourceType and onType are the 'same type' - the former is the 'Eclipse' version and the latter is the 'Weaver' version.
870 private void processTypeMungersFromExistingWeaverState(SourceTypeBinding sourceType, ResolvedType onType) {
871 List<ConcreteTypeMunger> previouslyAppliedMungers = onType.getWeaverState().getTypeMungers(onType);
873 for (ConcreteTypeMunger m : previouslyAppliedMungers) {
874 EclipseTypeMunger munger = factory.makeEclipseTypeMunger(m);
875 if (munger.munge(sourceType, onType)) {
876 if (onType.isInterface() && munger.getMunger().needsAccessToTopmostImplementor()) {
877 if (!onType.getWorld().getCrosscuttingMembersSet().containsAspect(munger.getAspectType())) {
879 .put(onType, "implementors of " + onType + " must be woven by " + munger.getAspectType());
887 private boolean doDeclareParents(DeclareParents declareParents, SourceTypeBinding sourceType) {
888 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_PARENTS,
889 sourceType.sourceName);
890 ResolvedType resolvedSourceType = factory.fromEclipse(sourceType);
891 List<ResolvedType> newParents = declareParents.findMatchingNewParents(resolvedSourceType, false);
892 if (!newParents.isEmpty()) {
893 for (ResolvedType parent : newParents) {
894 if (dangerousInterfaces.containsKey(parent)) {
895 ResolvedType onType = factory.fromEclipse(sourceType);
896 factory.showMessage(IMessage.ERROR, onType + ": " + dangerousInterfaces.get(parent),
897 onType.getSourceLocation(), null);
899 if (Modifier.isFinal(parent.getModifiers())) {
900 factory.showMessage(IMessage.ERROR, "cannot extend final class " + parent.getClassName(),
901 declareParents.getSourceLocation(), null);
903 // do not actually do it if the type isn't exposed - this
904 // will correctly reported as a problem elsewhere
905 if (!resolvedSourceType.isExposedToWeaver()) {
908 // AsmRelationshipProvider.getDefault().
909 // addDeclareParentsRelationship
910 // (declareParents.getSourceLocation(),
911 // factory.fromEclipse(sourceType), newParents);
912 addParent(sourceType, parent);
915 CompilationAndWeavingContext.leavingPhase(tok);
918 CompilationAndWeavingContext.leavingPhase(tok);
922 private String stringifyTargets(long bits) {
923 if ((bits & TagBits.AnnotationTargetMASK) == 0) {
926 Set<String> s = new HashSet<>();
927 if ((bits & TagBits.AnnotationForAnnotationType) != 0) {
928 s.add("ANNOTATION_TYPE");
930 if ((bits & TagBits.AnnotationForConstructor) != 0) {
931 s.add("CONSTRUCTOR");
933 if ((bits & TagBits.AnnotationForField) != 0) {
936 if ((bits & TagBits.AnnotationForLocalVariable) != 0) {
937 s.add("LOCAL_VARIABLE");
939 if ((bits & TagBits.AnnotationForMethod) != 0) {
942 if ((bits & TagBits.AnnotationForPackage) != 0) {
945 if ((bits & TagBits.AnnotationForParameter) != 0) {
948 if ((bits & TagBits.AnnotationForType) != 0) {
951 StringBuilder sb = new StringBuilder();
953 for (Iterator<String> iter = s.iterator(); iter.hasNext();) {
954 String element = iter.next();
956 if (iter.hasNext()) {
961 return sb.toString();
964 private boolean doDeclareAnnotations(DeclareAnnotation decA, SourceTypeBinding sourceType, boolean reportProblems) {
965 ResolvedType rtx = factory.fromEclipse(sourceType);
966 if (!decA.matches(rtx)) {
969 if (!rtx.isExposedToWeaver()) {
973 ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_ANNOTATIONS,
974 sourceType.sourceName);
976 // Get the annotation specified in the declare
977 UnresolvedType aspectType = decA.getAspect();
978 if (aspectType instanceof ReferenceType) {
979 ReferenceType rt = (ReferenceType) aspectType;
980 if (rt.isParameterizedType() || rt.isRawType()) {
981 aspectType = rt.getGenericType();
984 TypeBinding tb = factory.makeTypeBinding(aspectType);
986 // Hideousness follows:
988 // There are multiple situations to consider here and they relate to the
990 // where the annotation is coming from and where the annotation is going
993 // 1. Straight full build, all from source - the annotation is from a
995 // is being put on some type. Both types are real SourceTypeBindings.
997 // 2. Incremental build, changing the affected type - the annotation is
999 // dec@type in a BinaryTypeBinding (so has to be accessed via bcel) and
1001 // affected type is a real SourceTypeBinding. Mostly works (pr128665)
1004 SourceTypeBinding stb = (SourceTypeBinding) tb;
1005 Annotation[] toAdd = null;
1008 AbstractMethodDeclaration methodDecl = null;
1009 // Might have to retrieve the annotation through BCEL and construct an
1010 // eclipse one for it.
1011 if (stb instanceof BinaryTypeBinding) {
1012 toAdd = retrieveAnnotationFromBinaryTypeBinding(decA, stb);
1013 if (toAdd != null && toAdd.length > 0 && toAdd[0].resolvedType != null) {
1014 abits = toAdd[0].resolvedType.getAnnotationTagBits();
1016 } else if (stb != null) {
1017 // much nicer, its a real SourceTypeBinding so we can stay in
1019 // if (decA.getAnnotationMethod() != null) {
1020 char[] declareSelector = decA.getAnnotationMethod().toCharArray();
1022 ReferenceBinding rb = stb;
1023 String declaringAspectName = decA.getDeclaringType().getRawName();
1024 while (rb != null && !new String(CharOperation.concatWith(rb.compoundName, '.')).equals(declaringAspectName)) {
1025 rb = rb.superclass();
1027 MethodBinding[] mbs = rb.getMethods(declareSelector);
1029 ReferenceBinding declaringBinding = mbs[0].declaringClass;
1030 if (declaringBinding instanceof ParameterizedTypeBinding) {
1031 // Unwrap - this means we don't allow the type of the annotation to be parameterized, may need to revisit that
1032 declaringBinding = ((ParameterizedTypeBinding) declaringBinding).type;
1034 if (declaringBinding instanceof BinaryTypeBinding) {
1035 toAdd = retrieveAnnotationFromBinaryTypeBinding(decA, declaringBinding);
1036 if (toAdd != null && toAdd.length > 0 && toAdd[0].resolvedType != null) {
1037 abits = toAdd[0].resolvedType.getAnnotationTagBits();
1040 abits = mbs[0].getAnnotationTagBits(); // ensure resolved
1041 TypeDeclaration typeDecl = ((SourceTypeBinding) declaringBinding).scope.referenceContext;
1042 methodDecl = typeDecl.declarationOf(mbs[0]);
1043 toAdd = methodDecl.annotations; // this is what to add
1044 toAdd[0] = createAnnotationCopy(toAdd[0]);
1045 if (toAdd[0].resolvedType != null) {
1046 abits = toAdd[0].resolvedType.getAnnotationTagBits();
1052 // This happens if there is another error in the code - that should be reported separately
1053 if (toAdd == null || toAdd[0] == null || toAdd[0].type == null) {
1054 CompilationAndWeavingContext.leavingPhase(tok);
1057 if (sourceType instanceof BinaryTypeBinding) {
1058 // In this case we can't access the source type binding to add a new
1059 // annotation, so let's put something
1060 // on the weaver type temporarily
1061 ResolvedType theTargetType = factory.fromEclipse(sourceType);
1062 TypeBinding theAnnotationType = toAdd[0].resolvedType;
1063 // The annotation type may be null if it could not be resolved (eg. the relevant import has not been added yet)
1064 // In this case an error will be put out about the annotation but not if we crash here
1065 if (theAnnotationType == null) {
1068 String sig = new String(theAnnotationType.signature());
1069 UnresolvedType bcelAnnotationType = UnresolvedType.forSignature(sig);
1070 String name = bcelAnnotationType.getName();
1071 if (theTargetType.hasAnnotation(bcelAnnotationType)) {
1072 CompilationAndWeavingContext.leavingPhase(tok);
1076 // FIXME asc tidy up this code that duplicates whats below!
1077 // Simple checks on the bits
1078 boolean giveupnow = false;
1079 if (((abits & TagBits.AnnotationTargetMASK) != 0)) {
1080 if (isAnnotationTargettingSomethingOtherThanAnnotationOrNormal(abits)) {
1081 // error will have been already reported
1083 } else if ((sourceType.isAnnotationType() && (abits & TagBits.AnnotationForAnnotationType) == 0)
1084 || (!sourceType.isAnnotationType() && (abits & TagBits.AnnotationForType) == 0)) {
1086 if (reportProblems) {
1087 if (decA.isExactPattern()) {
1088 factory.showMessage(IMessage.ERROR, WeaverMessages.format(
1089 WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION, rtx.getName(), toAdd[0].type,
1090 stringifyTargets(abits)), decA.getSourceLocation(), null);
1092 // dont put out the lint - the weaving process will do
1095 // if (factory.getWorld().getLint().
1096 // invalidTargetForAnnotation.isEnabled()) {
1097 // factory.getWorld().getLint().invalidTargetForAnnotation
1099 // String[]{rtx.getName(),toAdd[0].type.toString(),
1101 // (abits)},decA.getSourceLocation(),null);
1109 CompilationAndWeavingContext.leavingPhase(tok);
1113 theTargetType.addAnnotation(new BcelAnnotation(new FakeAnnotation(name, sig,
1114 (abits & TagBits.AnnotationRuntimeRetention) != 0), factory.getWorld()));
1115 CompilationAndWeavingContext.leavingPhase(tok);
1119 Annotation currentAnnotations[] = sourceType.scope.referenceContext.annotations;
1120 if (currentAnnotations != null) {
1121 for (Annotation annotation : currentAnnotations) {
1122 String a = CharOperation.toString(annotation.type.getTypeName());
1123 String b = CharOperation.toString(toAdd[0].type.getTypeName());
1124 // FIXME asc we have a lint for attempting to add an annotation
1125 // twice to a method,
1126 // we could put it out here *if* we can resolve the problem of
1127 // errors coming out
1128 // multiple times if we have cause to loop through here
1130 CompilationAndWeavingContext.leavingPhase(tok);
1136 if (((abits & TagBits.AnnotationTargetMASK) != 0)) {
1137 if ((abits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType)) == 0) {
1138 // this means it specifies something other than annotation or
1139 // normal type - error will have been already reported,
1140 // just resolution process above
1141 CompilationAndWeavingContext.leavingPhase(tok);
1144 if ((sourceType.isAnnotationType() && (abits & TagBits.AnnotationForAnnotationType) == 0)
1145 || (!sourceType.isAnnotationType() && (abits & TagBits.AnnotationForType) == 0)) {
1147 if (reportProblems) {
1148 if (decA.isExactPattern()) {
1149 factory.showMessage(IMessage.ERROR, WeaverMessages.format(
1150 WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION, rtx.getName(), toAdd[0].type,
1151 stringifyTargets(abits)), decA.getSourceLocation(), null);
1153 // dont put out the lint - the weaving process will do that
1156 // (factory.getWorld().getLint().invalidTargetForAnnotation
1158 // factory.getWorld().getLint().invalidTargetForAnnotation.
1160 // String[]{rtx.getName(),toAdd[0].type.toString(),
1161 // stringifyTargets(abits)},decA.getSourceLocation(),null);
1165 CompilationAndWeavingContext.leavingPhase(tok);
1170 // Build a new array of annotations
1172 // remember the current set (rememberAnnotations only does something the
1173 // first time it is called for a type)
1174 sourceType.scope.referenceContext.rememberAnnotations();
1176 // AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(
1177 // decA.getSourceLocation(), rtx.getSourceLocation());
1178 final Annotation[] abefore = sourceType.scope.referenceContext.annotations;
1179 final Annotation[] newset = new Annotation[toAdd.length + (abefore == null ? 0 : abefore.length)];
1180 System.arraycopy(toAdd, 0, newset, 0, toAdd.length);
1181 if (abefore != null) {
1182 System.arraycopy(abefore, 0, newset, toAdd.length, abefore.length);
1184 sourceType.scope.referenceContext.annotations = newset;
1185 if ((sourceType.tagBits & TagBits.AnnotationResolved)!=0) {
1186 sourceType.tagBits = sourceType.tagBits - TagBits.AnnotationResolved;
1188 CompilationAndWeavingContext.leavingPhase(tok);
1189 if (factory.pushinCollector != null) {
1190 factory.pushinCollector.tagAsMunged(sourceType, new CommonPrinter((methodDecl == null ? null : methodDecl.scope))
1191 .printAnnotation(toAdd[0]).toString());
1196 private Annotation[] retrieveAnnotationFromBinaryTypeBinding(DeclareAnnotation decA, ReferenceBinding declaringBinding) {
1197 ReferenceType rt = (ReferenceType) factory.fromEclipse(declaringBinding);
1198 ResolvedMember[] methods = rt.getDeclaredMethods();
1199 ResolvedMember decaMethod = null;
1200 String nameToLookFor = decA.getAnnotationMethod();
1201 for (ResolvedMember method : methods) {
1202 if (method.getName().equals(nameToLookFor)) {
1203 decaMethod = method;
1207 if (decaMethod != null) { // could assert this ...
1208 AnnotationAJ[] axs = decaMethod.getAnnotations();
1209 if (axs != null) { // another error has occurred, dont crash here because of it
1210 Annotation[] toAdd = new Annotation[1];
1211 toAdd[0] = createAnnotationFromBcelAnnotation(axs[0], decaMethod.getSourceLocation().getOffset(), factory);
1212 // BUG BUG BUG - We dont test these abits are correct, in fact
1213 // we'll be very lucky if they are.
1214 // What does that mean? It means on an incremental compile you
1215 // might get away with an
1216 // annotation that isn't allowed on a type being put on a type.
1217 // if (toAdd[0].resolvedType != null) {
1218 // abits = toAdd[0].resolvedType.getAnnotationTagBits();
1227 * Transform an annotation from its AJ form to an eclipse form. We *DONT* care about the values of the annotation. that is
1228 * because it is only being stuck on a type during type completion to allow for other constructs (decps, decas) that might be
1229 * 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
1230 * the right thing copying across values too.
1232 private static Annotation createAnnotationFromBcelAnnotation(AnnotationAJ annX, int pos, EclipseFactory factory) {
1233 String name = annX.getTypeName();
1234 TypeBinding tb = factory.makeTypeBinding(annX.getType());
1235 // String theName = annX.getSignature().getBaseName();
1236 char[][] typeName = CharOperation.splitOn('.', name.replace('$', '.').toCharArray()); // pr149293 - not bulletproof...
1237 long[] positions = new long[typeName.length];
1238 for (int i = 0; i < positions.length; i++) {
1241 TypeReference annType = new QualifiedTypeReference(typeName, positions);
1242 NormalAnnotation ann = new NormalAnnotation(annType, pos);
1243 ann.resolvedType = tb; // yuck - is this OK in all cases?
1244 // We don't need membervalues...
1245 // Expression pcExpr = new
1246 // StringLiteral(pointcutExpression.toCharArray(),pos,pos);
1247 // MemberValuePair[] mvps = new MemberValuePair[2];
1248 // mvps[0] = new MemberValuePair("value".toCharArray(),pos,pos,pcExpr);
1249 // Expression argNamesExpr = new
1250 // StringLiteral(argNames.toCharArray(),pos,pos);
1252 // MemberValuePair("argNames".toCharArray(),pos,pos,argNamesExpr);
1253 // ann.memberValuePairs = mvps;
1258 * 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
1261 private static Annotation createAnnotationCopy(Annotation ann) {
1262 NormalAnnotation ann2 = new NormalAnnotation(ann.type, ann.sourceStart);
1263 ann2.memberValuePairs = ann.memberValuePairs();
1264 ann2.resolvedType = ann.resolvedType;
1265 ann2.bits = ann.bits;
1267 // String name = annX.getTypeName();
1268 // TypeBinding tb = factory.makeTypeBinding(annX.getSignature());
1269 // String theName = annX.getSignature().getBaseName();
1270 // char[][] typeName =
1271 // CharOperation.splitOn('.',name.replace('$','.').toCharArray());
1272 // //pr149293 - not bulletproof...
1273 // long[] positions = new long[typeName.length];
1274 // for (int i = 0; i < positions.length; i++) positions[i]=pos;
1275 // TypeReference annType = new
1276 // QualifiedTypeReference(typeName,positions);
1277 // NormalAnnotation ann = new NormalAnnotation(annType,pos);
1278 // ann.resolvedType=tb; // yuck - is this OK in all cases?
1279 // // We don't need membervalues...
1280 // // Expression pcExpr = new
1281 // StringLiteral(pointcutExpression.toCharArray(),pos,pos);
1282 // // MemberValuePair[] mvps = new MemberValuePair[2];
1284 // MemberValuePair("value".toCharArray(),pos,pos,pcExpr);
1285 // // Expression argNamesExpr = new
1286 // StringLiteral(argNames.toCharArray(),pos,pos);
1288 // MemberValuePair("argNames".toCharArray(),pos,pos,argNamesExpr);
1289 // // ann.memberValuePairs = mvps;
1293 private boolean isAnnotationTargettingSomethingOtherThanAnnotationOrNormal(long abits) {
1294 return (abits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType)) == 0;
1297 // private void reportDeclareParentsMessage(WeaveMessage.WeaveMessageKind wmk, SourceTypeBinding sourceType, ResolvedType parent) {
1298 // if (!factory.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
1299 // String filename = new String(sourceType.getFileName());
1301 // int takefrom = filename.lastIndexOf('/');
1302 // if (takefrom == -1) {
1303 // takefrom = filename.lastIndexOf('\\');
1305 // filename = filename.substring(takefrom + 1);
1307 // factory.getWorld()
1308 // .getMessageHandler()
1310 // WeaveMessage.constructWeavingMessage(wmk,
1311 // new String[] { CharOperation.toString(sourceType.compoundName), filename,
1312 // parent.getClassName(),
1313 // getShortname(parent.getSourceLocation().getSourceFile().getPath()) }));
1317 // private String getShortname(String path) {
1318 // int takefrom = path.lastIndexOf('/');
1319 // if (takefrom == -1) {
1320 // takefrom = path.lastIndexOf('\\');
1322 // return path.substring(takefrom + 1);
1325 private void addParent(SourceTypeBinding sourceType, ResolvedType parent) {
1326 ReferenceBinding parentBinding = (ReferenceBinding) factory.makeTypeBinding(parent);
1327 if (parentBinding == null) {
1328 return; // The parent is missing, it will be reported elsewhere.
1330 // Due to e37 switching to MethodVerifier15 for everything, it is important added types are correctly
1331 // raw or not. For example, if Comparable is used in generic form compareTo(T) will be used to check
1332 // methods against in the verifier rather than compareTo(Object)
1333 if (!factory.getWorld().isInJava5Mode()) {
1334 parentBinding = (ReferenceBinding)convertToRawType(parentBinding, false /*do not force conversion of enclosing types*/);
1335 } else if (sourceType.isGenericType()) {
1336 RawTypeBinding rawTargetType = (RawTypeBinding)convertToRawType(sourceType, false);
1337 if (rawTargetType != null) {
1338 // assert: don't need to 'rememberTypeHierarchy' because the class file is constructed based on the generic type
1339 if (parentBinding.isClass()) {
1340 rawTargetType.superclass = parentBinding;
1342 ReferenceBinding[] oldI = rawTargetType.superInterfaces;
1343 ReferenceBinding[] newI;
1345 newI = new ReferenceBinding[1];
1346 newI[0] = parentBinding;
1348 int n = oldI.length;
1349 newI = new ReferenceBinding[n + 1];
1350 System.arraycopy(oldI, 0, newI, 0, n);
1351 newI[n] = parentBinding;
1353 rawTargetType.superInterfaces = newI;
1356 // TODO what about parameterized types?
1358 sourceType.rememberTypeHierarchy();
1359 if (parentBinding.isClass()) {
1360 sourceType.superclass = parentBinding;
1362 // this used to be true, but I think I've fixed it now, decp is done
1364 // TAG: WeavingMessage DECLARE PARENTS: EXTENDS
1365 // Compiler restriction: Can't do EXTENDS at weave time
1366 // So, only see this message if doing a source compilation
1367 // reportDeclareParentsMessage(WeaveMessage.
1368 // WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
1371 ReferenceBinding[] oldI = sourceType.superInterfaces;
1372 ReferenceBinding[] newI;
1374 newI = new ReferenceBinding[1];
1375 newI[0] = parentBinding;
1377 int n = oldI.length;
1378 newI = new ReferenceBinding[n + 1];
1379 System.arraycopy(oldI, 0, newI, 0, n);
1380 newI[n] = parentBinding;
1382 sourceType.superInterfaces = newI;
1383 // warnOnAddedInterface(factory.fromEclipse(sourceType),parent); //
1384 // now reported at weave time...
1386 // this used to be true, but I think I've fixed it now, decp is done
1388 // TAG: WeavingMessage DECLARE PARENTS: IMPLEMENTS
1389 // This message will come out of BcelTypeMunger.munge if doing a
1391 // reportDeclareParentsMessage(WeaveMessage.
1392 // WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,sourceType,parent);
1396 // also add it to the bcel delegate if there is one
1397 if (sourceType instanceof BinaryTypeBinding) {
1398 ResolvedType onType = factory.fromEclipse(sourceType);
1399 ReferenceType rt = (ReferenceType) onType;
1400 ReferenceTypeDelegate rtd = rt.getDelegate();
1401 if (rtd instanceof BcelObjectType) {
1402 if (rt.isRawType()) {
1403 rt = rt.getGenericType();
1405 rt.addParent(parent);
1406 // ((BcelObjectType) rtd).addParent(parent);
1412 public void warnOnAddedInterface(ResolvedType type, ResolvedType parent) {
1413 World world = factory.getWorld();
1414 ResolvedType serializable = world.getCoreType(UnresolvedType.SERIALIZABLE);
1415 if (serializable.isAssignableFrom(type) && !serializable.isAssignableFrom(parent)
1416 && !LazyClassGen.hasSerialVersionUIDField(type)) {
1417 world.getLint().needsSerialVersionUIDField.signal(new String[] { type.getName().toString(),
1418 "added interface " + parent.getName().toString() }, null, null);
1422 private final List<BinaryTypeBinding> pendingTypesToFinish = new ArrayList<>();
1423 boolean inBinaryTypeCreationAndWeaving = false;
1424 boolean processingTheQueue = false;
1427 public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding,
1428 boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
1430 if (inBinaryTypeCreationAndWeaving) {
1431 BinaryTypeBinding ret = super.createBinaryTypeFrom(binaryType, packageBinding, needFieldsAndMethods, accessRestriction);
1432 pendingTypesToFinish.add(ret);
1436 inBinaryTypeCreationAndWeaving = true;
1438 BinaryTypeBinding ret = super.createBinaryTypeFrom(binaryType, packageBinding, needFieldsAndMethods, accessRestriction);
1439 factory.getWorld().validateType(factory.fromBinding(ret));
1440 // if you need the bytes to pass to validate, here they
1441 // are:((ClassFileReader)binaryType).getReferenceBytes()
1442 weaveInterTypeDeclarations(ret);
1445 inBinaryTypeCreationAndWeaving = false;
1447 // Start processing the list...
1448 if (pendingTypesToFinish.size() > 0) {
1449 processingTheQueue = true;
1450 while (!pendingTypesToFinish.isEmpty()) {
1451 BinaryTypeBinding nextVictim = pendingTypesToFinish.remove(0);
1452 // During this call we may recurse into this method and add
1453 // more entries to the pendingTypesToFinish list.
1454 weaveInterTypeDeclarations(nextVictim);
1456 processingTheQueue = false;
1462 * Callback driven when the compiler detects an anonymous type during block resolution. We need to add it to the weaver so that
1463 * we don't trip up later.
1468 public void anonymousTypeBindingCreated(LocalTypeBinding aBinding) {
1469 factory.addSourceTypeBinding(aBinding, null);
1473 public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) {
1474 if (this.isProcessingAnnotations && hasAspectDeclarations(unit)) {
1475 throw new SourceTypeCollisionException();
1477 super.buildTypeBindings(unit, accessRestriction);
1480 private static boolean hasAspectDeclarations(CompilationUnitDeclaration unit) {
1481 if (unit.types == null)
1483 for (int j = 0; j < unit.types.length; j++) {
1484 if (unit.types[j] instanceof AspectDeclaration) {
1492 public void reset() {
1493 this.factory.cleanup();
1498 public LookupEnvironment wrapInModuleEnvironment(ModuleBinding moduleBinding) {
1499 AjLookupEnvironment newAjLookupEnvironment = new AjLookupEnvironment(this, moduleBinding);
1500 newAjLookupEnvironment.factory = this.factory;
1501 return newAjLookupEnvironment;
1505 // commented out, supplied as info on how to manipulate annotations in an
1508 // public void doDeclareAnnotationOnMethods() {
1509 // Do the declare annotation on fields/methods/ctors
1510 // Collection daoms = factory.getDeclareAnnotationOnMethods();
1511 // if (daoms!=null && daoms.size()>0 && !(sourceType instanceof
1512 // BinaryTypeBinding)) {
1513 // System.err.println("Going through the methods on "+sourceType.debugName()+
1514 // " looking for DECA matches");
1515 // // We better take a look through them...
1516 // for (Iterator iter = daoms.iterator(); iter.hasNext();) {
1517 // DeclareAnnotation element = (DeclareAnnotation) iter.next();
1518 // System.err.println("Looking for anything that might match "+element+" on "+
1519 // sourceType.debugName()+" "+getType(sourceType.
1520 // compoundName).debugName()+" "+(sourceType instanceof BinaryTypeBinding));
1522 // ReferenceBinding rbb = getType(sourceType.compoundName);
1523 // // fix me if we ever uncomment this code... should iterate the other way
1524 // round, over the methods then over the decas
1525 // sourceType.methods();
1526 // MethodBinding sourceMbs[] = sourceType.methods;
1527 // for (int i = 0; i < sourceMbs.length; i++) {
1528 // MethodBinding sourceMb = sourceMbs[i];
1529 // MethodBinding mbbbb =
1530 // ((SourceTypeBinding)rbb).getExactMethod(sourceMb.selector
1531 // ,sourceMb.parameters);
1532 // boolean isCtor = sourceMb.selector[0]=='<';
1534 // if ((element.isDeclareAtConstuctor() ^ !isCtor)) {
1535 // System.err.println("Checking "+sourceMb+" ... declaringclass="+sourceMb.
1536 // declaringClass.debugName()+" rbb="+rbb.debugName()+" "+
1537 // sourceMb.declaringClass.equals(rbb));
1539 // ResolvedMember rm = null;
1540 // rm = EclipseFactory.makeResolvedMember(mbbbb);
1541 // if (element.matches(rm,factory.getWorld())) {
1542 // System.err.println("MATCH");
1544 // // Determine the set of annotations that are currently on the method
1545 // ReferenceBinding rb = getType(sourceType.compoundName);
1546 // // TypeBinding tb = factory.makeTypeBinding(decA.getAspect());
1547 // MethodBinding mb =
1548 // ((SourceTypeBinding)rb).getExactMethod(sourceMb.selector,sourceMb
1550 // //long abits = mbs[0].getAnnotationTagBits(); // ensure resolved
1551 // TypeDeclaration typeDecl =
1552 // ((SourceTypeBinding)sourceMb.declaringClass).scope.referenceContext;
1553 // AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(sourceMb);
1554 // Annotation[] currentlyHas = methodDecl.annotations; // this is what to add
1555 // //abits = toAdd[0].resolvedType.getAnnotationTagBits();
1557 // // Determine the annotations to add to that method
1558 // TypeBinding tb = factory.makeTypeBinding(element.getAspect());
1559 // MethodBinding[] aspectMbs =
1560 // ((SourceTypeBinding)tb).getMethods(element.getAnnotationMethod
1561 // ().toCharArray());
1562 // long abits = aspectMbs[0].getAnnotationTagBits(); // ensure resolved
1563 // TypeDeclaration typeDecl2 =
1564 // ((SourceTypeBinding)aspectMbs[0].declaringClass).scope.referenceContext;
1565 // AbstractMethodDeclaration methodDecl2 =
1566 // typeDecl2.declarationOf(aspectMbs[0]);
1567 // Annotation[] toAdd = methodDecl2.annotations; // this is what to add
1568 // // abits = toAdd[0].resolvedType.getAnnotationTagBits();
1569 // System.err.println("Has: "+currentlyHas+" toAdd: "+toAdd);
1571 // // fix me? should check if it already has the annotation
1572 // //Annotation abefore[] = sourceType.scope.referenceContext.annotations;
1573 // Annotation[] newset = new
1574 // Annotation[(currentlyHas==null?0:currentlyHas.length)+1];
1575 // System.arraycopy(toAdd,0,newset,0,toAdd.length);
1576 // if (currentlyHas!=null) {
1577 // System.arraycopy(currentlyHas,0,newset,1,currentlyHas.length);
1579 // methodDecl.annotations = newset;
1580 // System.err.println("New set on "+CharOperation.charToString(sourceMb.selector)
1583 // System.err.println("NO MATCH");
1590 // commented out, supplied as info on how to manipulate annotations in an
1593 // public void doDeclareAnnotationOnFields() {
1594 // Collection daofs = factory.getDeclareAnnotationOnFields();
1595 // if (daofs!=null && daofs.size()>0 && !(sourceType instanceof
1596 // BinaryTypeBinding)) {
1597 // System.err.println("Going through the fields on "+sourceType.debugName()+
1598 // " looking for DECA matches");
1599 // // We better take a look through them...
1600 // for (Iterator iter = daofs.iterator(); iter.hasNext();) {
1601 // DeclareAnnotation element = (DeclareAnnotation) iter.next();
1602 // System.err.println("Processing deca "+element+" on "+sourceType.debugName()+
1603 // " "+getType(sourceType.compoundName).debugName()+" "
1604 // +(sourceType instanceof BinaryTypeBinding));
1606 // ReferenceBinding rbb = getType(sourceType.compoundName);
1607 // // fix me? should iterate the other way round, over the methods then over the
1609 // sourceType.fields(); // resolve the bloody things
1610 // FieldBinding sourceFbs[] = sourceType.fields;
1611 // for (int i = 0; i < sourceFbs.length; i++) {
1612 // FieldBinding sourceFb = sourceFbs[i];
1613 // //FieldBinding fbbbb =
1614 // ((SourceTypeBinding)rbb).getgetExactMethod(sourceMb.selector
1615 // ,sourceMb.parameters);
1617 // System.err.println("Checking "+sourceFb+" ... declaringclass="+sourceFb.
1618 // declaringClass.debugName()+" rbb="+rbb.debugName());
1620 // ResolvedMember rm = null;
1621 // rm = EclipseFactory.makeResolvedMember(sourceFb);
1622 // if (element.matches(rm,factory.getWorld())) {
1623 // System.err.println("MATCH");
1625 // // Determine the set of annotations that are currently on the field
1626 // ReferenceBinding rb = getType(sourceType.compoundName);
1627 // // TypeBinding tb = factory.makeTypeBinding(decA.getAspect());
1628 // FieldBinding fb = ((SourceTypeBinding)rb).getField(sourceFb.name,true);
1629 // //long abits = mbs[0].getAnnotationTagBits(); // ensure resolved
1630 // TypeDeclaration typeDecl =
1631 // ((SourceTypeBinding)sourceFb.declaringClass).scope.referenceContext;
1632 // FieldDeclaration fd = typeDecl.declarationOf(sourceFb);
1633 // //AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(sourceMb);
1634 // Annotation[] currentlyHas = fd.annotations; // this is what to add
1635 // //abits = toAdd[0].resolvedType.getAnnotationTagBits();
1637 // // Determine the annotations to add to that method
1638 // TypeBinding tb = factory.makeTypeBinding(element.getAspect());
1639 // MethodBinding[] aspectMbs =
1640 // ((SourceTypeBinding)tb).getMethods(element.getAnnotationMethod
1641 // ().toCharArray());
1642 // long abits = aspectMbs[0].getAnnotationTagBits(); // ensure resolved
1643 // TypeDeclaration typeDecl2 =
1644 // ((SourceTypeBinding)aspectMbs[0].declaringClass).scope.referenceContext;
1645 // AbstractMethodDeclaration methodDecl2 =
1646 // typeDecl2.declarationOf(aspectMbs[0]);
1647 // Annotation[] toAdd = methodDecl2.annotations; // this is what to add
1648 // // abits = toAdd[0].resolvedType.getAnnotationTagBits();
1649 // System.err.println("Has: "+currentlyHas+" toAdd: "+toAdd);
1651 // // fix me? check if it already has the annotation
1654 // //Annotation abefore[] = sourceType.scope.referenceContext.annotations;
1655 // Annotation[] newset = new
1656 // Annotation[(currentlyHas==null?0:currentlyHas.length)+1];
1657 // System.arraycopy(toAdd,0,newset,0,toAdd.length);
1658 // if (currentlyHas!=null) {
1659 // System.arraycopy(currentlyHas,0,newset,1,currentlyHas.length);
1661 // fd.annotations = newset;
1662 // System.err.println("New set on "+CharOperation.charToString(sourceFb.name)+
1665 // System.err.println("NO MATCH");