org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjtools Show documentation
Show all versions of aspectjtools Show documentation
Tools from the AspectJ project
/* *******************************************************************
* 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 v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
*
* Contributors:
* PARC initial implementation
* ******************************************************************/
package org.aspectj.ajdt.internal.compiler.lookup;
import java.lang.reflect.Modifier;
import java.util.*;
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.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.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
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.BinaryTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
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);
}
public AjLookupEnvironment(LookupEnvironment env, ModuleBinding moduleBinding) {
super(env, moduleBinding);
}
// ??? duplicates some of super's code
@Override
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 (SourceTypeBinding sourceTypeBinding : b) {
factory.addSourceTypeBinding(sourceTypeBinding, units[i]);
if (sourceTypeBinding.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?
sourceTypeBinding.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 (SourceTypeBinding stb : stbs) {
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;
Collections.addAll(typesToProcess, stbs);
}
List stb2 = new ArrayList<>(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 (SourceTypeBinding sourceTypeBinding : b) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.RESOLVING_POINTCUT_DECLARATIONS, sourceTypeBinding.sourceName);
resolvePointcutDeclarations(sourceTypeBinding.scope);
CompilationAndWeavingContext.leavingPhase(tok);
}
}
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
SourceTypeBinding[] b = units[i].scope.topLevelTypes;
for (SourceTypeBinding sourceTypeBinding : b) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.ADDING_DECLARE_WARNINGS_AND_ERRORS, sourceTypeBinding.sourceName);
addAdviceLikeDeclares(sourceTypeBinding.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 (ReferenceBinding memberType : memberTypes) {
SourceTypeBinding rb = (SourceTypeBinding) memberType;
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 (ReferenceBinding binding : interfaceTypes) {
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 (ReferenceBinding memberType : memberTypes) {
addAdviceLikeDeclares(((SourceTypeBinding) memberType).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 (ReferenceBinding memberType : memberTypes) {
addCrosscuttingStructures(((SourceTypeBinding) memberType).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 (AbstractMethodDeclaration method : methods) {
if (method instanceof PointcutDeclaration) {
hasPointcuts = true;
if (!initializedMethods) {
sourceType.methods(); // force initialization
initializedMethods = true;
}
((PointcutDeclaration) method).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 (ReferenceBinding memberType : memberTypes) {
resolvePointcutDeclarations(((SourceTypeBinding) memberType).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 (ReferenceBinding memberType : memberTypes) {
buildInterTypeAndPerClause(((SourceTypeBinding) memberType).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 (Object o : dangerousInterfaces.entrySet()) {
Map.Entry entry = (Map.Entry) o;
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
© 2015 - 2024 Weber Informatics LLC | Privacy Policy