Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* PARC initial implementation
* ******************************************************************/
package org.aspectj.ajdt.internal.compiler.lookup;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.aspectj.ajdt.internal.compiler.CommonPrinter;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
import org.aspectj.asm.AsmManager;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.WeaveMessage;
import org.aspectj.bridge.context.CompilationAndWeavingContext;
import org.aspectj.bridge.context.ContextToken;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ReferenceTypeDelegate;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.ResolvedTypeMunger;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.WeaverStateInfo;
import org.aspectj.weaver.World;
import org.aspectj.weaver.bcel.BcelAnnotation;
import org.aspectj.weaver.bcel.BcelObjectType;
import org.aspectj.weaver.bcel.FakeAnnotation;
import org.aspectj.weaver.bcel.LazyClassGen;
import org.aspectj.weaver.patterns.DeclareAnnotation;
import org.aspectj.weaver.patterns.DeclareParents;
/**
* Overrides the default eclipse LookupEnvironment for two purposes.
*
* 1. To provide some additional phases to completeTypeBindings that weave declare parents and inter-type declarations
* at the correct time.
*
* 2. To intercept the loading of new binary types to ensure the they will have declare parents and inter-type declarations woven
* when appropriate.
*
* @author Jim Hugunin
*/
public class AjLookupEnvironment extends LookupEnvironment implements AnonymousClassCreationListener {
public EclipseFactory factory = null;
// private boolean builtInterTypesAndPerClauses = false;
private final List pendingTypesToWeave = new ArrayList();
// Q: What are dangerousInterfaces?
// A: An interface is considered dangerous if an ITD has been made upon it
// and that ITD
// requires the top most implementors of the interface to be woven *and yet*
// the aspect
// responsible for the ITD is not in the 'world'.
// Q: Err, how can that happen?
// A: When a type is on the inpath, it is 'processed' when completing type
// bindings. At this
// point we look at any type mungers it was affected by previously (stored
// in the weaver
// state info attribute). Effectively we are working with a type munger and
// yet may not have its
// originating aspect in the world. This is a problem if, for example, the
// aspect supplied
// a 'body' for a method targetting an interface - since the top most
// implementors should
// be woven by the munger from the aspect. When this happens we store the
// interface name here
// in the map - if we later process a type that is the topMostImplementor of
// a dangerous
// interface then we put out an error message.
/**
* interfaces targetted by ITDs that have to be implemented by accessing the topMostImplementor of the interface, yet the aspect
* where the ITD originated is not in the world
*/
private final Map dangerousInterfaces = new HashMap();
public AjLookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter,
INameEnvironment nameEnvironment) {
super(typeRequestor, options, problemReporter, nameEnvironment);
}
// ??? duplicates some of super's code
public void completeTypeBindings() {
AsmManager.setCompletingTypeBindings(true);
ContextToken completeTypeBindingsToken = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.COMPLETING_TYPE_BINDINGS, "");
// builtInterTypesAndPerClauses = false;
// pendingTypesToWeave = new ArrayList();
stepCompleted = BUILD_TYPE_HIERARCHY;
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CHECK_AND_SET_IMPORTS,
units[i].compilationResult.fileName);
units[i].scope.checkAndSetImports();
CompilationAndWeavingContext.leavingPhase(tok);
}
stepCompleted = CHECK_AND_SET_IMPORTS;
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CONNECTING_TYPE_HIERARCHY,
units[i].compilationResult.fileName);
units[i].scope.connectTypeHierarchy();
CompilationAndWeavingContext.leavingPhase(tok);
}
stepCompleted = CONNECT_TYPE_HIERARCHY;
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.BUILDING_FIELDS_AND_METHODS,
units[i].compilationResult.fileName);
// units[i].scope.checkParameterizedTypes(); do this check a little
// later, after ITDs applied to stbs
units[i].scope.buildFieldsAndMethods();
CompilationAndWeavingContext.leavingPhase(tok);
}
// would like to gather up all TypeDeclarations at this point and put
// them in the factory
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
SourceTypeBinding[] b = units[i].scope.topLevelTypes;
for (int j = 0; j < b.length; j++) {
factory.addSourceTypeBinding(b[j], units[i]);
if (b[j].superclass instanceof MissingTypeBinding) {
// e37: Undoing the work in ClassScope.connectSuperClass() as it will lead to cascade errors
// TODO allow MissingTypeBinding through here and cope with it in all situations later?
b[j].superclass = units[i].scope.getJavaLangObject();
}
}
}
// We won't find out about anonymous types until later though, so
// register to be
// told about them when they turn up.
AnonymousClassPublisher.aspectOf().setAnonymousClassCreationListener(this);
// need to build inter-type declarations for all AspectDeclarations at
// this point
// this MUST be done in order from super-types to subtypes
List typesToProcess = new ArrayList();
List aspectsToProcess = new ArrayList();
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
CompilationUnitScope cus = units[i].scope;
SourceTypeBinding[] stbs = cus.topLevelTypes;
for (int j = 0; j < stbs.length; j++) {
SourceTypeBinding stb = stbs[j];
typesToProcess.add(stb);
TypeDeclaration typeDeclaration = stb.scope.referenceContext;
if (typeDeclaration instanceof AspectDeclaration) {
aspectsToProcess.add(stb);
}
}
}
factory.getWorld().getCrosscuttingMembersSet().reset();
// Need to do these before the other ITDs
for (SourceTypeBinding aspectToProcess : aspectsToProcess) {
processInterTypeMemberTypes(aspectToProcess.scope);
}
while (typesToProcess.size() > 0) {
// removes types from the list as they are processed...
collectAllITDsAndDeclares(typesToProcess.get(0), typesToProcess);
}
factory.finishTypeMungers();
// now do weaving
final List typeMungers = factory.getTypeMungers();
final List declareParents = factory.getDeclareParents();
final List declareAnnotationOnTypes = factory.getDeclareAnnotationOnTypes();
doPendingWeaves();
// We now have some list of types to process, and we are about to apply
// the type mungers.
// There can be situations where the order of types passed to the
// compiler causes the
// output from the compiler to vary - THIS IS BAD. For example, if we
// have class A
// and class B extends A. Also, an aspect that 'declare parents: A+
// implements Serializable'
// then depending on whether we see A first, we may or may not make B
// serializable.
// The fix is to process them in the right order, ensuring that for a
// type we process its
// supertypes and superinterfaces first. This algorithm may have
// problems with:
// - partial hierarchies (e.g. suppose types A,B,C are in a hierarchy
// and A and C are to be woven but not B)
// - weaving that brings new types in for processing (see
// pendingTypesToWeave.add() calls) after we thought
// we had the full list.
//
// but these aren't common cases (he bravely said...)
boolean typeProcessingOrderIsImportant = declareParents.size() > 0 || declareAnnotationOnTypes.size() > 0; // DECAT
if (typeProcessingOrderIsImportant) {
typesToProcess = new ArrayList();
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
CompilationUnitScope cus = units[i].scope;
SourceTypeBinding[] stbs = cus.topLevelTypes;
for (int j = 0; j < stbs.length; j++) {
SourceTypeBinding stb = stbs[j];
typesToProcess.add(stb);
}
}
List stb2 = new ArrayList();
stb2.addAll(typesToProcess);
while (typesToProcess.size() > 0) {
// A side effect of weaveIntertypes() is that the processed type is removed from the collection
weaveIntertypes(typesToProcess, typesToProcess.get(0), typeMungers, declareParents, declareAnnotationOnTypes, 1);
}
while (stb2.size() > 0) {
// A side effect of weaveIntertypes() is that the processed type is removed from the collection
weaveIntertypes(stb2, stb2.get(0), typeMungers, declareParents, declareAnnotationOnTypes, 2);
}
} else {
// Order isn't important
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
weaveInterTypeDeclarations(units[i].scope, typeMungers, declareParents, declareAnnotationOnTypes);
}
}
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
units[i].scope.checkParameterizedTypes();
}
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
SourceTypeBinding[] b = units[i].scope.topLevelTypes;
for (int j = 0; j < b.length; j++) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.RESOLVING_POINTCUT_DECLARATIONS, b[j].sourceName);
resolvePointcutDeclarations(b[j].scope);
CompilationAndWeavingContext.leavingPhase(tok);
}
}
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
SourceTypeBinding[] b = units[i].scope.topLevelTypes;
for (int j = 0; j < b.length; j++) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.ADDING_DECLARE_WARNINGS_AND_ERRORS, b[j].sourceName);
addAdviceLikeDeclares(b[j].scope);
CompilationAndWeavingContext.leavingPhase(tok);
}
}
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
units[i] = null; // release unnecessary reference to the parsed unit
}
stepCompleted = BUILD_FIELDS_AND_METHODS;
lastCompletedUnitIndex = lastUnitIndex;
AsmManager.setCompletingTypeBindings(false);
factory.getWorld().getCrosscuttingMembersSet().verify();
CompilationAndWeavingContext.leavingPhase(completeTypeBindingsToken);
if (isProcessingAnnotations) {
throw new SourceTypeCollisionException(); // TODO(yushkovskiy): temporary solution; forcing to recompile units to insert mungers into types
}
}
// /**
// * For any given sourcetypebinding, this method checks that if it is a
// parameterized aspect that
// * the type parameters specified for any supertypes meet the bounds for
// the generic type
// * variables.
// */
// private void verifyAnyTypeParametersMeetBounds(SourceTypeBinding
// sourceType) {
// ResolvedType onType = factory.fromEclipse(sourceType);
// if (onType.isAspect()) {
// ResolvedType superType = factory.fromEclipse(sourceType.superclass);
// // Don't need to check if it was used in its RAW form or isnt generic
// if (superType.isGenericType() || superType.isParameterizedType()) {
// TypeVariable[] typeVariables = superType.getTypeVariables();
// UnresolvedType[] typeParams = superType.getTypeParameters();
// if (typeVariables!=null && typeParams!=null) {
// for (int i = 0; i < typeVariables.length; i++) {
// boolean ok =
// typeVariables[i].canBeBoundTo(typeParams[i].resolve(factory.getWorld()));
// if (!ok) { // the supplied parameter violates the bounds
// // Type {0} does not meet the specification for type parameter {1} ({2})
// in generic type {3}
// String msg =
// WeaverMessages.format(
// WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
// typeParams[i],
// new Integer(i+1),
// typeVariables[i].getDisplayName(),
// superType.getGenericType().getName());
// factory.getWorld().getMessageHandler().handleMessage(MessageUtil.error(msg
// ,onType.getSourceLocation()));
// }
// }
// }
// }
// }
// }
public void doSupertypesFirst(ReferenceBinding rb, Collection extends ReferenceBinding> yetToProcess) {
if (rb instanceof SourceTypeBinding) {
if (yetToProcess.contains(rb)) {
collectAllITDsAndDeclares((SourceTypeBinding) rb, yetToProcess);
}
} else if (rb instanceof ParameterizedTypeBinding) {
// If its a PTB we need to pull the SourceTypeBinding out of it.
ParameterizedTypeBinding ptb = (ParameterizedTypeBinding) rb;
if (ptb.type instanceof SourceTypeBinding && yetToProcess.contains(ptb.type)) {
collectAllITDsAndDeclares((SourceTypeBinding) ptb.type, yetToProcess);
}
}
}
/**
* Find all the ITDs and Declares, but it is important we do this from the supertypes down to the subtypes.
*
* @param sourceType
* @param yetToProcess
*/
private void collectAllITDsAndDeclares(SourceTypeBinding sourceType, Collection extends ReferenceBinding> yetToProcess) {
// Look at the supertype first
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.COLLECTING_ITDS_AND_DECLARES,
sourceType.sourceName);
yetToProcess.remove(sourceType);
// look out our direct supertype
doSupertypesFirst(sourceType.superclass(), yetToProcess);
// now check our membertypes (pr119570)
ReferenceBinding[] memberTypes = sourceType.memberTypes;
for (int i = 0, length = memberTypes.length; i < length; i++) {
SourceTypeBinding rb = (SourceTypeBinding) memberTypes[i];
if (!rb.superclass().equals(sourceType)) {
doSupertypesFirst(rb.superclass(), yetToProcess);
}
}
buildInterTypeAndPerClause(sourceType.scope);
addCrosscuttingStructures(sourceType.scope);
CompilationAndWeavingContext.leavingPhase(tok);
}
/**
* Weave the parents and intertype decls into a given type. This method looks at the supertype and superinterfaces for the
* specified type and recurses to weave those first if they are in the full list of types we are going to process during this
* compile... it stops recursing the first time it hits a type we aren't going to process during this compile. This could cause
* 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
* doing if you do that?
*
* @param mode 0=do everything, 1=do declare parents, 2=do ITDs
*/
private void weaveIntertypes(List typesToProcess, SourceTypeBinding typeToWeave,
List typeMungers, List declareParents,
List declareAnnotationOnTypes, int mode) {
// Look at the supertype first
ReferenceBinding superType = typeToWeave.superclass();
if (typesToProcess.contains(superType) && superType instanceof SourceTypeBinding) {
// System.err.println("Recursing to supertype "+new
// String(superType.getFileName()));
weaveIntertypes(typesToProcess, (SourceTypeBinding) superType, typeMungers, declareParents, declareAnnotationOnTypes,
mode);
}
// Then look at the superinterface list
ReferenceBinding[] interfaceTypes = typeToWeave.superInterfaces();
for (int i = 0; i < interfaceTypes.length; i++) {
ReferenceBinding binding = interfaceTypes[i];
if (typesToProcess.contains(binding) && binding instanceof SourceTypeBinding) {
// System.err.println("Recursing to superinterface "+new
// String(binding.getFileName()));
weaveIntertypes(typesToProcess, (SourceTypeBinding) binding, typeMungers, declareParents, declareAnnotationOnTypes,
mode);
}
else if (binding instanceof ParameterizedTypeBinding && (((ParameterizedTypeBinding)binding).type instanceof SourceTypeBinding) && typesToProcess.contains(((ParameterizedTypeBinding)binding).type)) {
weaveIntertypes(typesToProcess, (SourceTypeBinding) ((ParameterizedTypeBinding)binding).type, typeMungers, declareParents, declareAnnotationOnTypes, mode);
}
}
weaveInterTypeDeclarations(typeToWeave, typeMungers, declareParents, declareAnnotationOnTypes, false, mode);
typesToProcess.remove(typeToWeave);
}
private void doPendingWeaves() {
for (SourceTypeBinding t: pendingTypesToWeave) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS, t.sourceName);
weaveInterTypeDeclarations(t);
CompilationAndWeavingContext.leavingPhase(tok);
}
pendingTypesToWeave.clear();
}
private void addAdviceLikeDeclares(ClassScope s) {
TypeDeclaration dec = s.referenceContext;
if (dec instanceof AspectDeclaration) {
ResolvedType typeX = factory.fromEclipse(dec.binding);
factory.getWorld().getCrosscuttingMembersSet().addAdviceLikeDeclares(typeX);
}
SourceTypeBinding sourceType = s.referenceContext.binding;
ReferenceBinding[] memberTypes = sourceType.memberTypes;
for (int i = 0, length = memberTypes.length; i < length; i++) {
addAdviceLikeDeclares(((SourceTypeBinding) memberTypes[i]).scope);
}
}
private void addCrosscuttingStructures(ClassScope s) {
TypeDeclaration dec = s.referenceContext;
if (dec instanceof AspectDeclaration) {
ResolvedType typeX = factory.fromEclipse(dec.binding);
factory.getWorld().getCrosscuttingMembersSet().addOrReplaceAspect(typeX, false);
if (typeX.getSuperclass().isAspect() && !typeX.getSuperclass().isExposedToWeaver()) {
factory.getWorld().getCrosscuttingMembersSet().addOrReplaceAspect(typeX.getSuperclass(), false);
}
}
SourceTypeBinding sourceType = s.referenceContext.binding;
ReferenceBinding[] memberTypes = sourceType.memberTypes;
for (int i = 0, length = memberTypes.length; i < length; i++) {
addCrosscuttingStructures(((SourceTypeBinding) memberTypes[i]).scope);
}
}
private void resolvePointcutDeclarations(ClassScope s) {
TypeDeclaration dec = s.referenceContext;
SourceTypeBinding sourceType = s.referenceContext.binding;
boolean hasPointcuts = false;
AbstractMethodDeclaration[] methods = dec.methods;
boolean initializedMethods = false;
if (methods != null) {
for (int i = 0; i < methods.length; i++) {
if (methods[i] instanceof PointcutDeclaration) {
hasPointcuts = true;
if (!initializedMethods) {
sourceType.methods(); // force initialization
initializedMethods = true;
}
((PointcutDeclaration) methods[i]).resolvePointcut(s);
}
}
}
if (hasPointcuts || dec instanceof AspectDeclaration || couldBeAnnotationStyleAspectDeclaration(dec)) {
ReferenceType name = (ReferenceType) factory.fromEclipse(sourceType);
EclipseSourceType eclipseSourceType = (EclipseSourceType) name.getDelegate();
eclipseSourceType.checkPointcutDeclarations();
}
ReferenceBinding[] memberTypes = sourceType.memberTypes;
for (int i = 0, length = memberTypes.length; i < length; i++) {
resolvePointcutDeclarations(((SourceTypeBinding) memberTypes[i]).scope);
}
}
/**
* Return true if the declaration has @Aspect annotation. Called 'couldBe' rather than 'is' because someone else may have
* defined an annotation called Aspect - we can't verify the full name (including package name) because it may not have been
* resolved just yet and rather going through expensive resolution when we dont have to, this gives us a cheap check that tells
* us whether to bother.
*/
private boolean couldBeAnnotationStyleAspectDeclaration(TypeDeclaration dec) {
Annotation[] annotations = dec.annotations;
boolean couldBeAtAspect = false;
if (annotations != null) {
for (int i = 0; i < annotations.length && !couldBeAtAspect; i++) {
if (annotations[i].toString().equals("@Aspect")) {
couldBeAtAspect = true;
}
}
}
return couldBeAtAspect;
}
/**
* Applies any intertype member type declarations up front.
*/
private void processInterTypeMemberTypes(ClassScope classScope) {
TypeDeclaration dec = classScope.referenceContext;
if (dec instanceof AspectDeclaration) {
((AspectDeclaration) dec).processIntertypeMemberTypes(classScope);
}
// if we are going to support nested aspects making itd member types, copy the logic from the end of
// buildInterTypeAndPerClause() which walks members
}
private void buildInterTypeAndPerClause(ClassScope s) {
TypeDeclaration dec = s.referenceContext;
if (dec instanceof AspectDeclaration) {
((AspectDeclaration) dec).buildInterTypeAndPerClause(s);
}
SourceTypeBinding sourceType = s.referenceContext.binding;
// test classes don't extend aspects
if (sourceType.superclass != null) {
ResolvedType parent = factory.fromEclipse(sourceType.superclass);
if (parent.isAspect() && !isAspect(dec)) {
factory.showMessage(IMessage.ERROR, "class \'" + new String(sourceType.sourceName) + "\' can not extend aspect \'"
+ parent.getName() + "\'", factory.fromEclipse(sourceType).getSourceLocation(), null);
}
}
ReferenceBinding[] memberTypes = sourceType.memberTypes;
if (memberTypes == null) {
System.err.println("Unexpectedly found null for memberTypes of " + sourceType.debugName());
}
if (memberTypes != null) {
for (int i = 0, length = memberTypes.length; i < length; i++) {
buildInterTypeAndPerClause(((SourceTypeBinding) memberTypes[i]).scope);
}
}
}
private boolean isAspect(TypeDeclaration decl) {
if ((decl instanceof AspectDeclaration)) {
return true;
} else if (decl.annotations == null) {
return false;
} else {
for (int i = 0; i < decl.annotations.length; i++) {
Annotation ann = decl.annotations[i];
if (ann.type instanceof SingleTypeReference) {
if (CharOperation.equals("Aspect".toCharArray(), ((SingleTypeReference) ann.type).token)) {
return true;
}
} else if (ann.type instanceof QualifiedTypeReference) {
QualifiedTypeReference qtr = (QualifiedTypeReference) ann.type;
if (qtr.tokens.length != 5) {
return false;
}
if (!CharOperation.equals("org".toCharArray(), qtr.tokens[0])) {
return false;
}
if (!CharOperation.equals("aspectj".toCharArray(), qtr.tokens[1])) {
return false;
}
if (!CharOperation.equals("lang".toCharArray(), qtr.tokens[2])) {
return false;
}
if (!CharOperation.equals("annotation".toCharArray(), qtr.tokens[3])) {
return false;
}
if (!CharOperation.equals("Aspect".toCharArray(), qtr.tokens[4])) {
return false;
}
return true;
}
}
}
return false;
}
private void weaveInterTypeDeclarations(CompilationUnitScope unit, List typeMungers,
List declareParents, List declareAnnotationOnTypes) {
for (int i = 0, length = unit.topLevelTypes.length; i < length; i++) {
weaveInterTypeDeclarations(unit.topLevelTypes[i], typeMungers, declareParents, declareAnnotationOnTypes, false, 0);
}
}
private void weaveInterTypeDeclarations(SourceTypeBinding sourceType) {
if (!factory.areTypeMungersFinished()) {
if (!pendingTypesToWeave.contains(sourceType)) {
pendingTypesToWeave.add(sourceType);
// inner type ITD support - may need this for some incremental cases...
// List ctms = factory.getWorld().getCrosscuttingMembersSet().getTypeMungersOfKind(
// ResolvedTypeMunger.InnerClass);
// // List innerTypeMungers = new ArrayList();
// // for (ConcreteTypeMunger ctm : ctms) {
// // if (ctm.getMunger() != null && ctm.getMunger().getKind() == ResolvedTypeMunger.InnerClass) {
// // innerTypeMungers.add(ctm);
// // }
// // }
// // that includes the innertype one...
// // doPendingWeaves at this level is about applying inner class
// BinaryTypeBinding t = (BinaryTypeBinding) sourceType;
// for (ConcreteTypeMunger ctm : innerTypeMungers) {
// NewMemberClassTypeMunger nmctm = (NewMemberClassTypeMunger) ctm.getMunger();
// ReferenceBinding[] rbs = t.memberTypes;
// UnresolvedType ut = factory.fromBinding(t);
// if (ut.equals(nmctm.getTargetType())) {
// // got a match here
// SourceTypeBinding aspectTypeBinding = (SourceTypeBinding) factory.makeTypeBinding(ctm.getAspectType());
//
// char[] mungerMemberTypeName = ("$" + nmctm.getMemberTypeName()).toCharArray();
// ReferenceBinding innerTypeBinding = null;
// for (ReferenceBinding innerType : aspectTypeBinding.memberTypes) {
// char[] compounded = CharOperation.concatWith(innerType.compoundName, '.');
// if (org.aspectj.org.eclipse.jdt.core.compiler.CharOperation.endsWith(compounded, mungerMemberTypeName)) {
// innerTypeBinding = innerType;
// break;
// }
// }
// // may be unresolved if the aspect type binding was a BinaryTypeBinding
// if (innerTypeBinding instanceof UnresolvedReferenceBinding) {
// innerTypeBinding = BinaryTypeBinding
// .resolveType(innerTypeBinding, factory.getLookupEnvironment(), true);
// }
// t.memberTypes(); // cause initialization
// t.memberTypes = new ReferenceBinding[] { innerTypeBinding };
//
// int stop = 1;
// // The inner type from the aspect should be put into the membertypebindings for this
//
// }
// }
}
} else {
weaveInterTypeDeclarations(sourceType, factory.getTypeMungers(), factory.getDeclareParents(),
factory.getDeclareAnnotationOnTypes(), true, 0);
}
}
/**
* @param mode 0=do everything, 1=do declare parents, 2=do ITDs
*/
private void weaveInterTypeDeclarations(SourceTypeBinding sourceType, List typeMungers,
List declareParents, List declareAnnotationOnTypes, boolean skipInners, int mode) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS,
sourceType.sourceName);
ResolvedType onType = factory.fromEclipse(sourceType);
// AMC we shouldn't need this when generic sigs are fixed??
if (onType.isRawType()) {
onType = onType.getGenericType();
}
WeaverStateInfo info = onType.getWeaverState();
if (mode < 2) {
// this test isnt quite right - there will be a case where we fail to
// flag a problem
// with a 'dangerous interface' because the type is reweavable when we
// should have
// because the type wasn't going to be rewoven... if that happens, we
// should perhaps
// move this test and dangerous interface processing to the end of this
// method and
// make it conditional on whether any of the typeMungers passed into
// here actually
// matched this type.
if (info != null && !info.isOldStyle() && !info.isReweavable()) {
processTypeMungersFromExistingWeaverState(sourceType, onType);
CompilationAndWeavingContext.leavingPhase(tok);
return;
}
// Check if the type we are looking at is the topMostImplementor of a
// dangerous interface -
// report a problem if it is.
for (Iterator i = dangerousInterfaces.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
ResolvedType interfaceType = (ResolvedType) entry.getKey();
if (onType.isTopmostImplementor(interfaceType)) {
factory.showMessage(IMessage.ERROR, onType + ": " + entry.getValue(), onType.getSourceLocation(), null);
}
}
boolean needOldStyleWarning = (info != null && info.isOldStyle());
onType.clearInterTypeMungers();
onType.ensureConsistent();
// FIXME asc perf Could optimize here, after processing the expected set
// of types we may bring
// binary types that are not exposed to the weaver, there is no need to
// attempt declare parents
// or declare annotation really - unless we want to report the
// not-exposed to weaver
// messages...
List decpToRepeat = new ArrayList();
List decaToRepeat = new ArrayList();
boolean anyNewParents = false;
boolean anyNewAnnotations = false;
// first pass
// try and apply all decps - if they match, then great. If they don't
// then
// check if they are starred-annotation patterns. If they are not
// starred
// annotation patterns then they might match later...remember that...
for (DeclareParents decp : declareParents) {
if (!decp.isMixin()) {
boolean didSomething = doDeclareParents(decp, sourceType);
if (didSomething) {
if (factory.pushinCollector != null) {
factory.pushinCollector.tagAsMunged(sourceType, decp.getParents().get(0));
}
anyNewParents = true;
} else {
if (!decp.getChild().isStarAnnotation()) {
decpToRepeat.add(decp);
}
}
}
}
for (DeclareAnnotation deca : declareAnnotationOnTypes) {
boolean didSomething = doDeclareAnnotations(deca, sourceType, true);
if (didSomething) {
anyNewAnnotations = true;
} else {
if (!deca.getTypePattern().isStar()) {
decaToRepeat.add(deca);
}
}
}
List