aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--weaver/src/org/aspectj/weaver/Advice.java12
-rw-r--r--weaver/src/org/aspectj/weaver/AjAttribute.java2
-rw-r--r--weaver/src/org/aspectj/weaver/Checker.java4
-rw-r--r--weaver/src/org/aspectj/weaver/CrosscuttingMembers.java2
-rw-r--r--weaver/src/org/aspectj/weaver/Member.java18
-rw-r--r--weaver/src/org/aspectj/weaver/ReferenceType.java24
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedType.java8
-rw-r--r--weaver/src/org/aspectj/weaver/Shadow.java4
-rw-r--r--weaver/src/org/aspectj/weaver/TypeFactory.java14
-rw-r--r--weaver/src/org/aspectj/weaver/UnresolvedType.java6
-rw-r--r--weaver/src/org/aspectj/weaver/World.java739
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java2
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java2
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java2
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWorld.java12
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/Utility.java4
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java4
-rw-r--r--weaver/src/org/aspectj/weaver/raw types.txt40
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java2
19 files changed, 493 insertions, 408 deletions
diff --git a/weaver/src/org/aspectj/weaver/Advice.java b/weaver/src/org/aspectj/weaver/Advice.java
index 21e6ab1ee..0e70432f0 100644
--- a/weaver/src/org/aspectj/weaver/Advice.java
+++ b/weaver/src/org/aspectj/weaver/Advice.java
@@ -38,7 +38,7 @@ public abstract class Advice extends ShadowMunger {
protected TypePattern exceptionType; // just for Softener kind
public static Advice makeCflowEntry(World world, Pointcut entry, boolean isBelow, Member stackField, int nFreeVars, List innerCflowEntries, ResolvedType inAspect){
- Advice ret = world.concreteAdvice(isBelow ? AdviceKind.CflowBelowEntry : AdviceKind.CflowEntry,
+ Advice ret = world.createAdviceMunger(isBelow ? AdviceKind.CflowBelowEntry : AdviceKind.CflowEntry,
entry, stackField, 0, entry);
//0);
ret.innerCflowEntries = innerCflowEntries;
@@ -50,7 +50,7 @@ public abstract class Advice extends ShadowMunger {
public static Advice makePerCflowEntry(World world, Pointcut entry, boolean isBelow,
Member stackField, ResolvedType inAspect, List innerCflowEntries)
{
- Advice ret = world.concreteAdvice(isBelow ? AdviceKind.PerCflowBelowEntry : AdviceKind.PerCflowEntry,
+ Advice ret = world.createAdviceMunger(isBelow ? AdviceKind.PerCflowBelowEntry : AdviceKind.PerCflowEntry,
entry, stackField, 0, entry);
ret.innerCflowEntries = innerCflowEntries;
ret.concreteAspect = inAspect;
@@ -60,7 +60,7 @@ public abstract class Advice extends ShadowMunger {
public static Advice makePerObjectEntry(World world, Pointcut entry, boolean isThis,
ResolvedType inAspect)
{
- Advice ret = world.concreteAdvice(isThis ? AdviceKind.PerThisEntry : AdviceKind.PerTargetEntry,
+ Advice ret = world.createAdviceMunger(isThis ? AdviceKind.PerThisEntry : AdviceKind.PerTargetEntry,
entry, null, 0, entry);
ret.concreteAspect = inAspect;
@@ -69,13 +69,13 @@ public abstract class Advice extends ShadowMunger {
// PTWIMPL per type within entry advice is what initializes the aspect instance in the matched type
public static Advice makePerTypeWithinEntry(World world, Pointcut p, ResolvedType inAspect) {
- Advice ret = world.concreteAdvice(AdviceKind.PerTypeWithinEntry,p,null,0,p);
+ Advice ret = world.createAdviceMunger(AdviceKind.PerTypeWithinEntry,p,null,0,p);
ret.concreteAspect = inAspect;
return ret;
}
public static Advice makeSoftener(World world, Pointcut entry, TypePattern exceptionType,ResolvedType inAspect,IHasSourceLocation loc) {
- Advice ret = world.concreteAdvice(AdviceKind.Softener, entry, null, 0, loc);
+ Advice ret = world.createAdviceMunger(AdviceKind.Softener, entry, null, 0, loc);
ret.exceptionType = exceptionType;
ret.concreteAspect = inAspect;
@@ -241,7 +241,7 @@ public abstract class Advice extends ShadowMunger {
p.m_ignoreUnboundBindingForNames =oldP.m_ignoreUnboundBindingForNames;
}
- Advice munger = world.concreteAdvice(attribute, p, signature);
+ Advice munger = world.createAdviceMunger(attribute, p, signature);
munger.concreteAspect = fromType;
//System.err.println("concretizing here " + p + " with clause " + clause);
return munger;
diff --git a/weaver/src/org/aspectj/weaver/AjAttribute.java b/weaver/src/org/aspectj/weaver/AjAttribute.java
index 8b00f3d04..01b60c581 100644
--- a/weaver/src/org/aspectj/weaver/AjAttribute.java
+++ b/weaver/src/org/aspectj/weaver/AjAttribute.java
@@ -480,7 +480,7 @@ public abstract class AjAttribute {
}
public Advice reify(Member signature, World world) {
- return world.concreteAdvice(this, pointcut, signature);
+ return world.createAdviceMunger(this, pointcut, signature);
}
public String toString() {
diff --git a/weaver/src/org/aspectj/weaver/Checker.java b/weaver/src/org/aspectj/weaver/Checker.java
index e84e199be..02678d535 100644
--- a/weaver/src/org/aspectj/weaver/Checker.java
+++ b/weaver/src/org/aspectj/weaver/Checker.java
@@ -58,8 +58,8 @@ public class Checker extends ShadowMunger {
world.getMessageHandler().handleMessage(message);
- if (world.xrefHandler != null) {
- world.xrefHandler.addCrossReference(this.getSourceLocation(),
+ if (world.getCrossReferenceHandler() != null) {
+ world.getCrossReferenceHandler().addCrossReference(this.getSourceLocation(),
shadow.getSourceLocation(),
(this.isError?IRelationship.Kind.DECLARE_ERROR:IRelationship.Kind.DECLARE_WARNING),false);
diff --git a/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java b/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java
index 1d257c065..a57961db9 100644
--- a/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java
+++ b/weaver/src/org/aspectj/weaver/CrosscuttingMembers.java
@@ -154,7 +154,7 @@ public class CrosscuttingMembers {
if (typeToExpose instanceof ResolvedType) {
typeToExpose = ((ResolvedType)typeToExpose).getGenericType();
} else {
- typeToExpose = UnresolvedType.forSignature(typeToExpose.getRawTypeSignature());
+ typeToExpose = UnresolvedType.forSignature(typeToExpose.getErasureSignature());
}
}
ResolvedMember member = new ResolvedMember(
diff --git a/weaver/src/org/aspectj/weaver/Member.java b/weaver/src/org/aspectj/weaver/Member.java
index 345d7e0a3..d84947505 100644
--- a/weaver/src/org/aspectj/weaver/Member.java
+++ b/weaver/src/org/aspectj/weaver/Member.java
@@ -76,7 +76,7 @@ public class Member implements Comparable, AnnotatedElement {
this.name = name;
this.parameterTypes = parameterTypes;
if (kind == FIELD) {
- this.signature = returnType.getRawTypeSignature();
+ this.signature = returnType.getErasureSignature();
this.declaredSignature = returnType.getSignature();
} else {
this.signature = typesToSignature(returnType, parameterTypes,true);
@@ -108,11 +108,11 @@ public class Member implements Comparable, AnnotatedElement {
StringBuffer buf = new StringBuffer();
buf.append("(");
for (int i = 0, len = paramTypes.length; i < len; i++) {
- if (paramTypes[i].isParameterizedType() && useRawTypes) buf.append(paramTypes[i].getRawTypeSignature());
+ if (paramTypes[i].isParameterizedType() && useRawTypes) buf.append(paramTypes[i].getErasureSignature());
else buf.append(paramTypes[i].getSignature());
}
buf.append(")");
- if (returnType.isParameterizedType() && useRawTypes) buf.append(returnType.getRawTypeSignature());
+ if (returnType.isParameterizedType() && useRawTypes) buf.append(returnType.getErasureSignature());
else buf.append(returnType.getSignature());
return buf.toString();
}
@@ -481,21 +481,21 @@ public class Member implements Comparable, AnnotatedElement {
// ---- things we know only with resolution
public int getModifiers(World world) {
- return world.getModifiers(this);
+ return resolve(world).getModifiers();
}
public UnresolvedType[] getExceptions(World world) {
- return world.getExceptions(this);
+ return resolve(world).getExceptions();
}
public final boolean isProtected(World world) {
- return Modifier.isProtected(world.getModifiers(this));
+ return Modifier.isProtected(resolve(world).getModifiers());
}
public final boolean isStatic(World world) {
- return Modifier.isStatic(world.getModifiers(this));
+ return Modifier.isStatic(resolve(world).getModifiers());
}
public final boolean isStrict(World world) {
- return Modifier.isStrict(world.getModifiers(this));
+ return Modifier.isStrict(resolve(world).getModifiers());
}
public final boolean isStatic() {
@@ -854,7 +854,7 @@ public class Member implements Comparable, AnnotatedElement {
}
public String[] getParameterNames(World world) {
- return world.getParameterNames(this);
+ return resolve(world).getParameterNames();
}
diff --git a/weaver/src/org/aspectj/weaver/ReferenceType.java b/weaver/src/org/aspectj/weaver/ReferenceType.java
index de65d1d86..9ee460fce 100644
--- a/weaver/src/org/aspectj/weaver/ReferenceType.java
+++ b/weaver/src/org/aspectj/weaver/ReferenceType.java
@@ -41,7 +41,7 @@ public class ReferenceType extends ResolvedType {
int endPos = 0;
public static ReferenceType fromTypeX(UnresolvedType tx, World world) {
- ReferenceType rt = new ReferenceType(tx.getRawTypeSignature(),world);
+ ReferenceType rt = new ReferenceType(tx.getErasureSignature(),world);
rt.typeKind = tx.typeKind;
return rt;
}
@@ -75,6 +75,22 @@ public class ReferenceType extends ResolvedType {
this.delegate = genericReferenceType.getDelegate();
}
+ /**
+ * Constructor used when creating a raw type.
+ */
+ public ReferenceType(
+ ResolvedType theGenericType,
+ World aWorld) {
+ super(theGenericType.getErasureSignature(),
+ theGenericType.getErasureSignature(),
+ aWorld);
+ ReferenceType genericReferenceType = (ReferenceType) theGenericType;
+ this.typeParameters = null;
+ this.genericType = genericReferenceType;
+ this.typeKind = TypeKind.RAW;
+ this.delegate = genericReferenceType.getDelegate();
+ }
+
public String getSignatureForAttribute() {
return makeDeclaredSignature(genericType,typeParameters);
}
@@ -156,7 +172,7 @@ public class ReferenceType extends ResolvedType {
public final boolean isAssignableFrom(ResolvedType other) {
if (other.isPrimitiveType()) {
- if (!world.behaveInJava5Way) return false;
+ if (!world.isInJava5Mode()) return false;
if (ResolvedType.validBoxing.contains(this.getSignature()+other.getSignature())) return true;
}
if (this == other) return true;
@@ -381,7 +397,7 @@ public class ReferenceType extends ResolvedType {
* @return
*/
private static String makeParameterizedSignature(ResolvedType aGenericType, ResolvedType[] someParameters) {
- String rawSignature = aGenericType.getRawTypeSignature();
+ String rawSignature = aGenericType.getErasureSignature();
String prefix = PARAMETERIZED_TYPE_IDENTIFIER + rawSignature.substring(1,rawSignature.length()-1);
StringBuffer ret = new StringBuffer();
@@ -396,7 +412,7 @@ public class ReferenceType extends ResolvedType {
private static String makeDeclaredSignature(ResolvedType aGenericType, UnresolvedType[] someParameters) {
StringBuffer ret = new StringBuffer();
- String rawSig = aGenericType.getRawTypeSignature();
+ String rawSig = aGenericType.getErasureSignature();
ret.append(rawSig.substring(0,rawSig.length()-1));
ret.append("<");
for (int i = 0; i < someParameters.length; i++) {
diff --git a/weaver/src/org/aspectj/weaver/ResolvedType.java b/weaver/src/org/aspectj/weaver/ResolvedType.java
index f1aa7761e..001125bb4 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedType.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedType.java
@@ -715,7 +715,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl
}
public final boolean isAssignableFrom(ResolvedType other) {
if (!other.isPrimitiveType()) {
- if (!world.behaveInJava5Way) return false;
+ if (!world.isInJava5Mode()) return false;
return validBoxing.contains(this.getSignature()+other.getSignature());
}
return assignTable[((Primitive)other).index][index];
@@ -1085,7 +1085,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl
//System.err.println(" is visible");
int c = compareMemberPrecedence(sig, existingMunger.getSignature());
if (c == 0) {
- c = getWorld().comparePrecedence(munger.getAspectType(), existingMunger.getAspectType());
+ c = getWorld().compareByPrecedenceAndHierarchy(munger.getAspectType(), existingMunger.getAspectType());
}
//System.err.println(" compare: " + c);
if (c < 0) {
@@ -1481,7 +1481,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl
* Types may have pointcuts just as they have methods and fields.
*/
public ResolvedPointcutDefinition findPointcut(String name, World world) {
- return world.findPointcut(this, name);
+ throw new UnsupportedOperationException("Not yet implemenented");
}
/**
@@ -1507,7 +1507,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl
// version from ResolvedTypeX
if (this.equals(OBJECT)) return true;
- if (world.behaveInJava5Way) {
+ if (world.isInJava5Mode()) {
if (this.isPrimitiveType()^other.isPrimitiveType()) { // If one is primitive and the other isnt
if (validBoxing.contains(this.getSignature()+other.getSignature())) return true;
}
diff --git a/weaver/src/org/aspectj/weaver/Shadow.java b/weaver/src/org/aspectj/weaver/Shadow.java
index 17e519dea..0b6186928 100644
--- a/weaver/src/org/aspectj/weaver/Shadow.java
+++ b/weaver/src/org/aspectj/weaver/Shadow.java
@@ -479,8 +479,8 @@ public abstract class Shadow {
ShadowMunger munger = (ShadowMunger) iter.next();
munger.implementOn(this);
- if (world.xrefHandler != null) {
- world.xrefHandler.addCrossReference(
+ if (world.getCrossReferenceHandler() != null) {
+ world.getCrossReferenceHandler().addCrossReference(
munger.getSourceLocation(), // What is being applied
this.getSourceLocation(), // Where is it being applied
determineRelKind(munger), // What kind of advice?
diff --git a/weaver/src/org/aspectj/weaver/TypeFactory.java b/weaver/src/org/aspectj/weaver/TypeFactory.java
index 8967f98a5..844442213 100644
--- a/weaver/src/org/aspectj/weaver/TypeFactory.java
+++ b/weaver/src/org/aspectj/weaver/TypeFactory.java
@@ -48,6 +48,20 @@ public class TypeFactory {
return (ReferenceType) pType.resolve(inAWorld);
}
+ public static ReferenceType createRawType(
+ ResolvedType aBaseType,
+ World inAWorld
+ ) {
+ if (aBaseType.isRawType()) return (ReferenceType) aBaseType;
+ if (!aBaseType.isGenericType()) {
+ if (!aBaseType.isRawType()) throw new IllegalStateException("Expecting generic type");
+ }
+ ReferenceType rType = new ReferenceType(aBaseType,inAWorld);
+ rType.setSourceContext(aBaseType.getSourceContext());
+ return (ReferenceType) rType.resolve(inAWorld);
+ }
+
+
/**
* Used by UnresolvedType.read, creates a type from a full signature.
* @param signature
diff --git a/weaver/src/org/aspectj/weaver/UnresolvedType.java b/weaver/src/org/aspectj/weaver/UnresolvedType.java
index 5173b9368..929ae74da 100644
--- a/weaver/src/org/aspectj/weaver/UnresolvedType.java
+++ b/weaver/src/org/aspectj/weaver/UnresolvedType.java
@@ -338,7 +338,7 @@ public class UnresolvedType {
return ret;
}
- public static UnresolvedType forRawTypeNames(String name) {
+ public static UnresolvedType forRawTypeName(String name) {
UnresolvedType ret = UnresolvedType.forName(name);
ret.typeKind = TypeKind.RAW;
return ret;
@@ -508,13 +508,13 @@ public class UnresolvedType {
/**
* For parameterized types, return the signature for the raw type
*/
- public String getRawTypeSignature() {
+ public String getErasureSignature() {
if (signatureErasure==null) return signature;
return signatureErasure;
}
public UnresolvedType getRawType() {
- return UnresolvedType.forSignature(getRawTypeSignature());
+ return UnresolvedType.forSignature(getErasureSignature());
}
diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java
index 0f9ca3410..f16077487 100644
--- a/weaver/src/org/aspectj/weaver/World.java
+++ b/weaver/src/org/aspectj/weaver/World.java
@@ -1,5 +1,6 @@
/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 2005 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
@@ -7,10 +8,10 @@
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
- * PARC initial implementation
+ * PARC initial implementation
+ * Adrian Colyer, Andy Clement, overhaul for generics
* ******************************************************************/
-
package org.aspectj.weaver;
import java.util.ArrayList;
@@ -28,30 +29,57 @@ import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.bridge.IMessage.Kind;
+import org.aspectj.weaver.UnresolvedType.TypeKind;
import org.aspectj.weaver.patterns.DeclarePrecedence;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.Pointcut;
+/**
+ * A World is a collection of known types and crosscutting members.
+ */
public abstract class World implements Dump.INode {
- protected IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR;
- protected ICrossReferenceHandler xrefHandler = null;
+ /** handler for any messages produced during resolution etc. */
+ private IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR;
+
+ /** handler for cross-reference information produced during the weaving process */
+ private ICrossReferenceHandler xrefHandler = null;
+ /** The heart of the world, a map from type signatures to resolved types */
protected TypeMap typeMap = new TypeMap(); // Signature to ResolvedType
+
+ /** Calculator for working out aspect precedence */
+ private AspectPrecedenceCalculator precedenceCalculator;
- protected CrosscuttingMembersSet crosscuttingMembersSet = new CrosscuttingMembersSet(this);
+ /** All of the type and shadow mungers known to us */
+ private CrosscuttingMembersSet crosscuttingMembersSet =
+ new CrosscuttingMembersSet(this);
- protected IHierarchy model = null;
+ /** Model holds ASM relationships */
+ private IHierarchy model = null;
- protected Lint lint = new Lint(this);
+ /** for processing Xlint messages */
+ private Lint lint = new Lint(this);
- protected boolean XnoInline;
- protected boolean XlazyTjp;
-
- public boolean behaveInJava5Way = false;
+ /** XnoInline option setting passed down to weaver */
+ private boolean XnoInline;
+ /** XlazyTjp option setting passed down to weaver */
+ private boolean XlazyTjp;
+ /** When behaving in a Java 5 way autoboxing is considered */
+ private boolean behaveInJava5Way = false;
+
+ /**
+ * A list of RuntimeExceptions containing full stack information for every
+ * type we couldn't find.
+ */
private List dumpState_cantFindTypeExceptions = null;
+ /**
+ * Play God.
+ * On the first day, God created the primitive types and put them in the type
+ * map.
+ */
protected World() {
super();
Dump.registerNode(this.getClass(),this);
@@ -64,8 +92,12 @@ public abstract class World implements Dump.INode {
typeMap.put("C", ResolvedType.CHAR);
typeMap.put("Z", ResolvedType.BOOLEAN);
typeMap.put("V", ResolvedType.VOID);
+ precedenceCalculator = new AspectPrecedenceCalculator(this);
}
+ /**
+ * Dump processing when a fatal error occurs
+ */
public void accept (Dump.IVisitor visitor) {
visitor.visitString("Shadow mungers:");
visitor.visitList(crosscuttingMembersSet.getShadowMungers());
@@ -79,17 +111,18 @@ public abstract class World implements Dump.INode {
dumpState_cantFindTypeExceptions = null;
}
}
+
+ // =============================================================================
+ // T Y P E R E S O L U T I O N
+ // =============================================================================
- public ResolvedType[] resolve(UnresolvedType[] types) {
- if (types == null) return new ResolvedType[0];
- int len = types.length;
- ResolvedType[] ret = new ResolvedType[len];
- for (int i=0; i<len; i++) {
- ret[i] = resolve(types[i]);
- }
- return ret;
+ /**
+ * Resolve a type that we require to be present in the world
+ */
+ public ResolvedType resolve(UnresolvedType ty) {
+ return resolve(ty, false);
}
-
+
/**
* Attempt to resolve a type - the source location gives you some context in which
* resolution is taking place. In the case of an error where we can't find the
@@ -109,197 +142,228 @@ public abstract class World implements Dump.INode {
return ret;
}
- public ResolvedType resolve(UnresolvedType ty) {
- return resolve(ty, false);
- }
-
- // if we already have an rtx, don't re-resolve it
- public ResolvedType resolve(ResolvedType ty) {
- if (ty.isTypeVariableReference()) return ty; // until type variables have proper sigs...
- ResolvedType resolved = typeMap.get(ty.getSignature());
- if (resolved == null) {
- typeMap.put(ty.getSignature(), ty);
- resolved = ty;
- }
- return resolved;
- }
-
- public ResolvedType getCoreType(UnresolvedType tx) {
- ResolvedType coreTy = resolve(tx,true);
- if (coreTy == ResolvedType.MISSING) {
- MessageUtil.error(messageHandler,
- WeaverMessages.format(WeaverMessages.CANT_FIND_CORE_TYPE,tx.getName()));
- }
- return coreTy;
- }
-
/**
- * Attempt to resolve a type that should be a generic type.
+ * Convenience method for resolving an array of unresolved types
+ * in one hit. Useful for e.g. resolving type parameters in signatures.
*/
- public ResolvedType resolveTheGenericType(UnresolvedType ty, boolean allowMissing) {
- // Look up the raw type by signature
- String signature = ty.getRawType().getSignature();
- ResolvedType ret = (ResolvedType) typeMap.get(signature);
- if (ret==null) {
- ret = resolve(UnresolvedType.forSignature(signature));
- typeMap.put(signature,ret);
- }
- //TODO asc temporary guard - can this ever happen?
- if (ret==null) throw new RuntimeException("RAW TYPE IS missing for "+ty);
+ public ResolvedType[] resolve(UnresolvedType[] types) {
+ if (types == null) return new ResolvedType[0];
- // Does the raw type know its generic form? (It will if we created the
- // raw type from a source type, it won't if its been created just through
- // being referenced, e.g. java.util.List
- ResolvedType generic = ret.getGenericType();
- if (generic != null) {
- generic.world = this;
- return generic;
- }
-
- // Fault in the generic that underpins the raw type ;)
- ReferenceTypeDelegate thegen = resolveObjectType((ReferenceType)ret);
- ReferenceType genericRefType = new ReferenceType(
- UnresolvedType.forGenericTypeSignature(ret.getSignature(),thegen.getDeclaredGenericSignature()),this);
- ((ReferenceType)ret).setGenericType(genericRefType);
- genericRefType.delegate=thegen;
- ((ReferenceType)ret).delegate=thegen;
- return genericRefType;
+ ResolvedType[] ret = new ResolvedType[types.length];
+ for (int i=0; i<types.length; i++) {
+ ret[i] = resolve(types[i]);
+ }
+ return ret;
}
+ /**
+ * Resolve a type. This the hub of type resolution. The resolved type is added
+ * to the type map by signature.
+ */
public ResolvedType resolve(UnresolvedType ty, boolean allowMissing) {
+
+ // special resolution processing for already resolved types.
if (ty instanceof ResolvedType) {
ResolvedType rty = (ResolvedType) ty;
rty = resolve(rty);
- rty.world = this;
return rty;
}
- //System.out.println("resolve: " + ty + " world " + typeMap.keySet());
- if (ty instanceof UnresolvedTypeVariableReferenceType) {
- // AMC - don't like this instanceof test, suggests some refactoring needed...
- return ((UnresolvedTypeVariableReferenceType)ty).resolve(this);
+
+ // dispatch back to the type variable reference to resolve its constituent parts
+ // don't do this for other unresolved types otherwise you'll end up in a loop
+ if (ty.isTypeVariableReference()) {
+ return ty.resolve(this);
}
+
+ // if we've already got a resolved type for the signature, just return it
+ // after updating the world
String signature = ty.getSignature();
ResolvedType ret = typeMap.get(signature);
if (ret != null) {
ret.world = this; // Set the world for the RTX
return ret;
- }
+ }
+ // no existing resolved type, create one
if (ty.isArray()) {
- ret = new ResolvedType.Array(signature, this, resolve(ty.getComponentType(), allowMissing));
+ ret = new ResolvedType.Array(signature,
+ this,
+ resolve(ty.getComponentType(),
+ allowMissing));
} else {
- ret = resolveObjectType(ty);
+ ret = resolveToReferenceType(ty);
if (!allowMissing && ret == ResolvedType.MISSING) {
- MessageUtil.error(messageHandler,
- WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()));
- if (dumpState_cantFindTypeExceptions==null) {
- dumpState_cantFindTypeExceptions = new ArrayList();
- }
- dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type "+ty.getName()));
+ handleRequiredMissingTypeDuringResolution(ty);
}
- }
- if (ty.isParameterizedType()) {
- for (int i = 0; i < ty.typeParameters.length; i++) {
- ty.typeParameters[i] = resolve(ty.typeParameters[i],allowMissing);
- }
- }
- //System.out.println("ret: " + ret);
- // Pulling in the type may have already put the right entry in the map
- if (typeMap.get(signature)==null && !ResolvedType.MISSING.equals(ret)) {
+ }
+
+ // Pulling in the type may have already put the right entry in the map
+ if (typeMap.get(signature)==null && ret != ResolvedType.MISSING) {
typeMap.put(signature, ret);
}
return ret;
}
+
+ /**
+ * We tried to resolve a type and couldn't find it...
+ */
+ private void handleRequiredMissingTypeDuringResolution(UnresolvedType ty) {
+ MessageUtil.error(messageHandler,
+ WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()));
+ if (dumpState_cantFindTypeExceptions==null) {
+ dumpState_cantFindTypeExceptions = new ArrayList();
+ }
+ dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type "+ty.getName()));
+ }
- //XXX helper method might be bad
+ /**
+ * Some TypeFactory operations create resolved types directly, but these won't be
+ * in the typeMap - this resolution process puts them there. Resolved types are
+ * also told their world which is needed for the special autoboxing resolved types.
+ */
+ public ResolvedType resolve(ResolvedType ty) {
+ if (ty.isTypeVariableReference()) return ty; // until type variables have proper sigs...
+ ResolvedType resolved = typeMap.get(ty.getSignature());
+ if (resolved == null) {
+ typeMap.put(ty.getSignature(), ty);
+ resolved = ty;
+ }
+ resolved.world = this;
+ return resolved;
+ }
+
+ /**
+ * Convenience method for finding a type by name and resolving it in one step.
+ */
public ResolvedType resolve(String name) {
return resolve(UnresolvedType.forName(name));
}
-
- /*
- * Copes with parameterized types. When it sees one then it discovers the
- * base type and reuses the delegate
+ /**
+ * Resolve to a ReferenceType - simple, raw, parameterized, or generic.
+ * Raw, parmeterized, and generic versions of a type share a delegate.
*/
- protected final ResolvedType resolveObjectType(UnresolvedType ty) {
+ private final ResolvedType resolveToReferenceType(UnresolvedType ty) {
if (ty.isParameterizedType()) {
- ReferenceType genericType = (ReferenceType)resolveTheGenericType(ty,false);
+ // ======= parameterized types ================
+ ReferenceType genericType = (ReferenceType)resolveGenericTypeFor(ty,false);
ReferenceType parameterizedType =
TypeFactory.createParameterizedType(genericType, ty.typeParameters, this);
return parameterizedType;
+
} else if (ty.isGenericType()) {
- ReferenceType genericType = (ReferenceType)resolveTheGenericType(ty,false);
+ // ======= generic types ======================
+ ReferenceType genericType = (ReferenceType)resolveGenericTypeFor(ty,false);
return genericType;
+
} else {
- String signature = ty.getRawTypeSignature();
- ReferenceType name = new ReferenceType(signature/*was ty.getSignature()*/, this);
- ReferenceTypeDelegate concreteName = resolveObjectType(name);
- if (concreteName == null) return ResolvedType.MISSING;
- if (concreteName.isGeneric()) {
- // During resolution we have discovered that the underlying type is in fact generic,
- // so the thing we thought was a simple type is in fact a raw type.
-
- ReferenceType genericRefType = new ReferenceType(
- UnresolvedType.forGenericTypeSignature(signature,concreteName.getDeclaredGenericSignature()),this);
+ // ======= simple and raw types ===============
+ String erasedSignature = ty.getErasureSignature();
+ ReferenceType simpleOrRawType = new ReferenceType(erasedSignature, this);
+ ReferenceTypeDelegate delegate = resolveDelegate(simpleOrRawType);
+ if (delegate == null) return ResolvedType.MISSING;
+
+ if (delegate.isGeneric()) {
+ // ======== raw type ===========
+ simpleOrRawType.typeKind = TypeKind.RAW;
+ ReferenceType genericType = new ReferenceType(
+ UnresolvedType.forGenericTypeSignature(erasedSignature,delegate.getDeclaredGenericSignature()),this);
// name = ReferenceType.fromTypeX(UnresolvedType.forRawTypeNames(ty.getName()),this);
- name.setDelegate(concreteName);
- genericRefType.setDelegate(concreteName);
- name.setGenericType(genericRefType);
- return name;
+ simpleOrRawType.setDelegate(delegate);
+ genericType.setDelegate(delegate);
+ simpleOrRawType.setGenericType(genericType);
+ return simpleOrRawType;
+
} else {
- name.setDelegate(concreteName);
- return name;
+ // ======== simple type =========
+ simpleOrRawType.setDelegate(delegate);
+ return simpleOrRawType;
}
}
}
-
- protected abstract ReferenceTypeDelegate resolveObjectType(ReferenceType ty);
-
- protected final boolean isCoerceableFrom(ResolvedType type, ResolvedType other) {
- return type.isCoerceableFrom(other);
- }
-
- protected final boolean isAssignableFrom(ResolvedType type, ResolvedType other) {
- return type.isAssignableFrom(other);
+ /**
+ * Attempt to resolve a type that should be a generic type.
+ */
+ public ResolvedType resolveGenericTypeFor(UnresolvedType anUnresolvedType, boolean allowMissing) {
+ // Look up the raw type by signature
+ String rawSignature = anUnresolvedType.getRawType().getSignature();
+ ResolvedType rawType = (ResolvedType) typeMap.get(rawSignature);
+ if (rawType==null) {
+ rawType = resolve(UnresolvedType.forSignature(rawSignature),false);
+ typeMap.put(rawSignature,rawType);
+ }
+
+ // Does the raw type know its generic form? (It will if we created the
+ // raw type from a source type, it won't if its been created just through
+ // being referenced, e.g. java.util.List
+ ResolvedType genericType = rawType.getGenericType();
+ if (genericType != null) {
+ genericType.world = this;
+ return genericType;
+ } else {
+ // Fault in the generic that underpins the raw type ;)
+ ReferenceTypeDelegate delegate = resolveDelegate((ReferenceType)rawType);
+ ReferenceType genericRefType = new ReferenceType(
+ UnresolvedType.forGenericTypeSignature(rawType.getSignature(),delegate.getDeclaredGenericSignature()),this);
+ ((ReferenceType)rawType).setGenericType(genericRefType);
+ genericRefType.setDelegate(delegate);
+ ((ReferenceType)rawType).setDelegate(delegate);
+ return genericRefType;
+ }
}
- public boolean needsNoConversionFrom(ResolvedType type, ResolvedType other) {
- return type.needsNoConversionFrom(other);
- }
+ /**
+ * Find the ReferenceTypeDelegate behind this reference type so that it can
+ * fulfill its contract.
+ */
+ protected abstract ReferenceTypeDelegate resolveDelegate(ReferenceType ty);
- protected final boolean isInterface(UnresolvedType type) {
- return resolve(type).isInterface();
- }
-
- protected final ResolvedType getSuperclass(UnresolvedType type) {
- return resolve(type).getSuperclass();
- }
-
- protected final UnresolvedType[] getDeclaredInterfaces(UnresolvedType type) {
- return resolve(type).getDeclaredInterfaces();
- }
-
- protected final int getModifiers(UnresolvedType type) {
- return resolve(type).getModifiers();
- }
-
- protected final ResolvedMember[] getDeclaredFields(UnresolvedType type) {
- return resolve(type).getDeclaredFields();
- }
-
- protected final ResolvedMember[] getDeclaredMethods(UnresolvedType type) {
- return resolve(type).getDeclaredMethods();
+ /**
+ * Special resolution for "core" types like OBJECT. These are resolved just like
+ * any other type, but if they are not found it is more serious and we issue an
+ * error message immediately.
+ */
+ public ResolvedType getCoreType(UnresolvedType tx) {
+ ResolvedType coreTy = resolve(tx,true);
+ if (coreTy == ResolvedType.MISSING) {
+ MessageUtil.error(messageHandler,
+ WeaverMessages.format(WeaverMessages.CANT_FIND_CORE_TYPE,tx.getName()));
+ }
+ return coreTy;
}
- protected final ResolvedMember[] getDeclaredPointcuts(UnresolvedType type) {
- return resolve(type).getDeclaredPointcuts();
- }
+ /**
+ * Lookup a type by signature, if not found then build one and put it in the
+ * map.
+ */
+ public ReferenceType lookupOrCreateName(UnresolvedType ty) {
+ String signature = ty.getSignature();
+ ReferenceType ret = lookupBySignature(signature);
+ if (ret == null) {
+ ret = ReferenceType.fromTypeX(ty, this);
+ typeMap.put(signature, ret);
+ }
+ return ret;
+ }
- // ---- members
+ /**
+ * Lookup a reference type in the world by its signature. Returns
+ * null if not found.
+ */
+ public ReferenceType lookupBySignature(String signature) {
+ return (ReferenceType) typeMap.get(signature);
+ }
+
+ // =============================================================================
+ // T Y P E R E S O L U T I O N -- E N D
+ // =============================================================================
- // XXX should we worry about dealing with context and looking up access?
+ /**
+ * Member resolution is achieved by resolving the declaring type and then
+ * looking up the member in the resolved declaring type.
+ */
public ResolvedMember resolve(Member member) {
ResolvedType declaring = member.getDeclaringType().resolve(this);
ResolvedMember ret;
@@ -313,56 +377,22 @@ public abstract class World implements Dump.INode {
return declaring.lookupSyntheticMember(member);
}
-
- protected int getModifiers(Member member) {
- ResolvedMember r = resolve(member);
- if (r == null) throw new BCException("bad resolve of " + member);
- return r.getModifiers();
- }
-
- protected String[] getParameterNames(Member member) {
- return resolve(member).getParameterNames();
- }
-
- protected UnresolvedType[] getExceptions(Member member) {
- return resolve(member).getExceptions();
- }
-
- // ---- pointcuts
-
- public ResolvedPointcutDefinition findPointcut(UnresolvedType typeX, String name) {
- throw new RuntimeException("not implemented yet");
- }
-
- /**
- * Get the shadow mungers of this world.
- *
- * @return a list of {@link IShadowMunger}s appropriate for this world.
- */
- //public abstract List getShadowMungers();
-
- // ---- empty world
-
-// public static final World EMPTY = new World() {
-// public List getShadowMungers() { return Collections.EMPTY_LIST; }
-// public ResolvedType.ConcreteName resolveObjectType(ResolvedType.Name ty) {
-// return null;
-// }
-// public Advice concreteAdvice(AjAttribute.AdviceAttribute attribute, Pointcut p, Member m) {
-// throw new RuntimeException("unimplemented");
-// }
-// public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
-// throw new RuntimeException("unimplemented");
-// }
-// };
+ // Methods for creating various cross-cutting members...
+ // ===========================================================
- public abstract Advice concreteAdvice(
+ /**
+ * Create an advice shadow munger from the given advice attribute
+ */
+ public abstract Advice createAdviceMunger(
AjAttribute.AdviceAttribute attribute,
Pointcut pointcut,
Member signature);
- public final Advice concreteAdvice(
+ /**
+ * Create an advice shadow munger for the given advice kind
+ */
+ public final Advice createAdviceMunger(
AdviceKind kind,
Pointcut p,
Member signature,
@@ -371,34 +401,40 @@ public abstract class World implements Dump.INode {
{
AjAttribute.AdviceAttribute attribute =
new AjAttribute.AdviceAttribute(kind, p, extraParameterFlags, loc.getStart(), loc.getEnd(), loc.getSourceContext());
- return concreteAdvice(attribute, p, signature);
+ return createAdviceMunger(attribute, p, signature);
}
-
-
- public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) {
- throw new RuntimeException("unimplemented");
- }
+ public abstract ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField);
- public ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField) {
- throw new RuntimeException("unimplemented");
- }
+ public abstract ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField);
/**
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed
* @see org.aspectj.weaver.bcel.BcelWorld#makePerClauseAspect(ResolvedType, org.aspectj.weaver.patterns.PerClause.Kind)
- *
- * @param aspect
- * @param kind
- * @return
*/
- public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind) {
- throw new RuntimeException("unimplemented");
- }
+ public abstract ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind);
public abstract ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType);
/**
+ * Same signature as org.aspectj.util.PartialOrder.PartialComparable.compareTo
+ */
+ public int compareByPrecedence(ResolvedType aspect1, ResolvedType aspect2) {
+ return precedenceCalculator.compareByPrecedence(aspect1, aspect2);
+ }
+
+ /**
+ * compares by precedence with the additional rule that a super-aspect is
+ * sorted before its sub-aspects
+ */
+ public int compareByPrecedenceAndHierarchy(ResolvedType aspect1, ResolvedType aspect2) {
+ return precedenceCalculator.compareByPrecedenceAndHierarchy(aspect1, aspect2);
+ }
+
+ // simple property getter and setters
+ // ===========================================================
+
+ /**
* Nobody should hold onto a copy of this message handler, or setMessageHandler won't
* work right.
*/
@@ -409,106 +445,38 @@ public abstract class World implements Dump.INode {
public void setMessageHandler(IMessageHandler messageHandler) {
this.messageHandler = messageHandler;
}
-
- public void setXRefHandler(ICrossReferenceHandler xrefHandler) {
- this.xrefHandler = xrefHandler;
- }
-
- public void showMessage(
- Kind kind,
- String message,
- ISourceLocation loc1,
- ISourceLocation loc2)
- {
- if (loc1 != null) {
- messageHandler.handleMessage(new Message(message, kind, null, loc1));
- if (loc2 != null) {
- messageHandler.handleMessage(new Message(message, kind, null, loc2));
- }
- } else {
- messageHandler.handleMessage(new Message(message, kind, null, loc2));
- }
- }
-
-
-
-
-// public void addDeclare(ResolvedType onType, Declare declare, boolean forWeaving) {
-// // this is not extensible, oh well
-// if (declare instanceof DeclareErrorOrWarning) {
-// ShadowMunger m = new Checker((DeclareErrorOrWarning)declare);
-// onType.addShadowMunger(m);
-// } else if (declare instanceof DeclareDominates) {
-// declareDominates.add(declare);
-// } else if (declare instanceof DeclareParents) {
-// declareParents.add(declare);
-// } else if (declare instanceof DeclareSoft) {
-// DeclareSoft d = (DeclareSoft)declare;
-// declareSoft.add(d);
-// if (forWeaving) {
-// ShadowMunger m = Advice.makeSoftener(this, d.getPointcut().concretize(onType, 0), d.getException());
-// onType.addShadowMunger(m);
-// }
-// } else {
-// throw new RuntimeException("unimplemented");
-// }
-// }
-
/**
- * Same signature as org.aspectj.util.PartialOrder.PartialComparable.compareTo
+ * convenenience method for creating and issuing messages via the message handler
*/
- public int compareByDominates(ResolvedType aspect1, ResolvedType aspect2) {
- //System.out.println("dom compare: " + aspect1 + " with " + aspect2);
- //System.out.println(crosscuttingMembersSet.getDeclareDominates());
-
- //??? We probably want to cache this result. This is order N where N is the
- //??? number of dominates declares in the whole system.
- //??? This method can be called a large number of times.
- int order = 0;
- DeclarePrecedence orderer = null; // Records the declare precedence statement that gives the first ordering
- for (Iterator i = crosscuttingMembersSet.getDeclareDominates().iterator(); i.hasNext(); ) {
- DeclarePrecedence d = (DeclarePrecedence)i.next();
- int thisOrder = d.compare(aspect1, aspect2);
- //System.out.println("comparing: " + thisOrder + ": " + d);
- if (thisOrder != 0) {
- if (orderer==null) orderer = d;
- if (order != 0 && order != thisOrder) {
- ISourceLocation[] isls = new ISourceLocation[2];
- isls[0]=orderer.getSourceLocation();
- isls[1]=d.getSourceLocation();
- Message m =
- new Message("conflicting declare precedence orderings for aspects: "+
- aspect1.getName()+" and "+aspect2.getName(),null,true,isls);
- messageHandler.handleMessage(m);
- // throw new BCException("conflicting dominates orders"+d.getSourceLocation());
- } else {
- order = thisOrder;
+ public void showMessage(
+ Kind kind,
+ String message,
+ ISourceLocation loc1,
+ ISourceLocation loc2)
+ {
+ if (loc1 != null) {
+ messageHandler.handleMessage(new Message(message, kind, null, loc1));
+ if (loc2 != null) {
+ messageHandler.handleMessage(new Message(message, kind, null, loc2));
}
+ } else {
+ messageHandler.handleMessage(new Message(message, kind, null, loc2));
}
}
-
-
- return order;
- }
-
-
- public int comparePrecedence(ResolvedType aspect1, ResolvedType aspect2) {
- //System.err.println("compare precedence " + aspect1 + ", " + aspect2);
- if (aspect1.equals(aspect2)) return 0;
-
- int ret = compareByDominates(aspect1, aspect2);
- if (ret != 0) return ret;
-
- if (aspect1.isAssignableFrom(aspect2)) return -1;
- else if (aspect2.isAssignableFrom(aspect1)) return +1;
- return 0;
+
+ public void setCrossReferenceHandler(ICrossReferenceHandler xrefHandler) {
+ this.xrefHandler = xrefHandler;
}
+ /**
+ * Get the cross-reference handler for the world, may be null.
+ */
+ public ICrossReferenceHandler getCrossReferenceHandler() {
+ return this.xrefHandler;
+ }
-
-
public List getDeclareParents() {
return crosscuttingMembersSet.getDeclareParents();
}
@@ -565,63 +533,26 @@ public abstract class World implements Dump.INode {
XlazyTjp = b;
}
- public ReferenceType lookupOrCreateName(UnresolvedType ty) {
- String signature = ty.getSignature();
- ReferenceType ret = (ReferenceType)typeMap.get(signature);
- if (ret == null) {
- ret = ReferenceType.fromTypeX(ty, this);
- typeMap.put(signature, ret);
- }
- return ret;
- }
+ public void setBehaveInJava5Way(boolean b) {
+ behaveInJava5Way = b;
+ }
- public ReferenceType lookupBySignature(String signature) {
- return (ReferenceType) typeMap.get(signature);
+ public boolean isInJava5Mode() {
+ return behaveInJava5Way;
}
-
-// public void clearUnexposed() {
-// List toRemove = new ArrayList();
-// for (Iterator iter = typeMap.keySet().iterator(); iter.hasNext();) {
-// String sig = (String) iter.next();
-// ResolvedType x = (ResolvedType) typeMap.get(sig);
-// if (!x.isExposedToWeaver() && (!x.isPrimitive())) toRemove.add(sig);
-// }
-// for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
-// typeMap.remove(iter.next());
-// }
-// }
-//
-// // for testing...
-// public void dumpTypeMap() {
-// int exposed = 0;
-// for (Iterator iter = typeMap.keySet().iterator(); iter.hasNext();) {
-// String sig = (String) iter.next();
-// ResolvedType x = (ResolvedType) typeMap.get(sig);
-// if (x.isExposedToWeaver()) exposed++;
-// }
-// System.out.println("type map contains " + typeMap.size() + " entries, " + exposed + " exposed to weaver");
-// }
-//
-// public void deepDumpTypeMap() {
-// for (Iterator iter = typeMap.keySet().iterator(); iter.hasNext();) {
-// String sig = (String) iter.next();
-// ResolvedType x = (ResolvedType) typeMap.get(sig);
-// if (! (x instanceof ResolvedType.Name)) {
-// System.out.println(sig + " -> " + x.getClass().getName() + ", " + x.getClassName());
-// } else {
-// ResolvedType.ConcreteName cname = ((ResolvedType.Name)x).getDelegate();
-// System.out.println(sig + " -> " + cname.getClass().getName() + ", " + cname.toString());
-// }
-// }
-//
-// }
-
- // Map of types in the world, with soft links to expendable ones
+ /*
+ * Map of types in the world, with soft links to expendable ones.
+ * An expendable type is a reference type that is not exposed to the weaver (ie
+ * just pulled in for type resolution purposes).
+ */
protected static class TypeMap {
+ /** Map of types that never get thrown away */
private Map tMap = new HashMap();
+ /** Map of types that may be ejected from the cache if we need space */
private Map expendableMap = new WeakHashMap();
+ /** Add a new type into the map, the key is the type signature */
public ResolvedType put(String key, ResolvedType type) {
if (isExpendable(type)) {
return (ResolvedType) expendableMap.put(key,type);
@@ -630,18 +561,23 @@ public abstract class World implements Dump.INode {
}
}
+ /** Lookup a type by its signature */
public ResolvedType get(String key) {
ResolvedType ret = (ResolvedType) tMap.get(key);
if (ret == null) ret = (ResolvedType) expendableMap.get(key);
return ret;
}
+ /** Remove a type from the map */
public ResolvedType remove(String key) {
ResolvedType ret = (ResolvedType) tMap.remove(key);
if (ret == null) ret = (ResolvedType) expendableMap.remove(key);
return ret;
}
+ /** Reference types we don't intend to weave may be ejected from
+ * the cache if we need the space.
+ */
private boolean isExpendable(ResolvedType type) {
return (
(type != null) &&
@@ -669,8 +605,87 @@ public abstract class World implements Dump.INode {
return sb.toString();
}
}
-
- public void setBehaveInJava5Way(boolean b) {
- behaveInJava5Way = b;
- }
+
+ /**
+ * This class is used to compute and store precedence relationships between
+ * aspects.
+ */
+ private static class AspectPrecedenceCalculator {
+
+ private World world;
+ private Map cachedResults;
+
+ public AspectPrecedenceCalculator(World forSomeWorld) {
+ this.world = forSomeWorld;
+ this.cachedResults = new HashMap();
+ }
+
+ /**
+ * Ask every declare precedence in the world to order the two aspects.
+ * If more than one declare precedence gives an ordering, and the orderings
+ * conflict, then that's an error.
+ */
+ public int compareByPrecedence(ResolvedType firstAspect, ResolvedType secondAspect) {
+ PrecedenceCacheKey key = new PrecedenceCacheKey(firstAspect,secondAspect);
+ if (cachedResults.containsKey(key)) {
+ return ((Integer) cachedResults.get(key)).intValue();
+ } else {
+ int order = 0;
+ DeclarePrecedence orderer = null; // Records the declare precedence statement that gives the first ordering
+ for (Iterator i = world.getCrosscuttingMembersSet().getDeclareDominates().iterator(); i.hasNext(); ) {
+ DeclarePrecedence d = (DeclarePrecedence)i.next();
+ int thisOrder = d.compare(firstAspect, secondAspect);
+ if (thisOrder != 0) {
+ if (orderer==null) orderer = d;
+ if (order != 0 && order != thisOrder) {
+ ISourceLocation[] isls = new ISourceLocation[2];
+ isls[0]=orderer.getSourceLocation();
+ isls[1]=d.getSourceLocation();
+ Message m =
+ new Message("conflicting declare precedence orderings for aspects: "+
+ firstAspect.getName()+" and "+secondAspect.getName(),null,true,isls);
+ world.getMessageHandler().handleMessage(m);
+ } else {
+ order = thisOrder;
+ }
+ }
+ }
+ cachedResults.put(key, new Integer(order));
+ return order;
+ }
+ }
+
+ public int compareByPrecedenceAndHierarchy(ResolvedType firstAspect, ResolvedType secondAspect) {
+ if (firstAspect.equals(secondAspect)) return 0;
+
+ int ret = compareByPrecedence(firstAspect, secondAspect);
+ if (ret != 0) return ret;
+
+ if (firstAspect.isAssignableFrom(secondAspect)) return -1;
+ else if (secondAspect.isAssignableFrom(firstAspect)) return +1;
+
+ return 0;
+ }
+
+
+ private static class PrecedenceCacheKey {
+ public ResolvedType aspect1;
+ public ResolvedType aspect2;
+
+ public PrecedenceCacheKey(ResolvedType a1, ResolvedType a2) {
+ this.aspect1 = a1;
+ this.aspect2 = a2;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof PrecedenceCacheKey)) return false;
+ PrecedenceCacheKey other = (PrecedenceCacheKey) obj;
+ return (aspect1 == other.aspect1 && aspect2 == other.aspect2);
+ }
+
+ public int hashCode() {
+ return aspect1.hashCode() + aspect2.hashCode();
+ }
+ }
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java
index cca258800..859531650 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java
@@ -509,7 +509,7 @@ public class BcelAdvice extends Advice {
World world = concreteAspect.getWorld();
int ret =
- concreteAspect.getWorld().compareByDominates(
+ concreteAspect.getWorld().compareByPrecedence(
concreteAspect,
o.concreteAspect);
if (ret != 0) return ret;
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
index f0521dd69..790cefee0 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
@@ -737,7 +737,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
// pr98901
// For copying the annotations across, we have to discover the real member in the aspect
// which is holding them.
- if (weaver.getWorld().behaveInJava5Way && !onInterface && munger.getSignature().isPublic() && !munger.getSignature().isAbstract()) {
+ if (weaver.getWorld().isInJava5Mode() && !onInterface && munger.getSignature().isPublic() && !munger.getSignature().isAbstract()) {
ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,dispatchMethod);
if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+
dispatchMethod+"' on aspect "+aspectType);
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
index 009af6499..ffda5ab9a 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
@@ -1000,7 +1000,7 @@ public class BcelWeaver implements IWeaver {
// FIXME asc Should be factored out into Xlint code and done automatically for all xlint messages, ideally.
// if a piece of advice hasn't matched anywhere and we are in -1.5 mode, put out a warning
- if (world.behaveInJava5Way &&
+ if (world.isInJava5Mode() &&
world.getLint().adviceDidNotMatch.isEnabled()) {
List l = world.getCrosscuttingMembersSet().getShadowMungers();
for (Iterator iter = l.iterator(); iter.hasNext();) {
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java
index 4de177e33..3cb228677 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java
@@ -96,7 +96,7 @@ public class BcelWorld extends World implements Repository {
//this.aspectPath = new ClassPathManager(aspectPath, handler);
this.classPath = new ClassPathManager(classPath, handler);
setMessageHandler(handler);
- setXRefHandler(xrefHandler);
+ setCrossReferenceHandler(xrefHandler);
// Tell BCEL to use us for resolving any classes
delegate = this;
// TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
@@ -106,7 +106,7 @@ public class BcelWorld extends World implements Repository {
public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
this.classPath = cpm;
setMessageHandler(handler);
- setXRefHandler(xrefHandler);
+ setCrossReferenceHandler(xrefHandler);
// Tell BCEL to use us for resolving any classes
delegate = this;
// TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
@@ -123,7 +123,7 @@ public class BcelWorld extends World implements Repository {
public BcelWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
this.classPath = null;
setMessageHandler(handler);
- setXRefHandler(xrefHandler);
+ setCrossReferenceHandler(xrefHandler);
// Tell BCEL to use us for resolving any classes
delegate = new ClassLoaderRepository(loader);
// TODO Alex do we need to call org.aspectj.apache.bcel.Repository.setRepository(delegate);
@@ -220,7 +220,7 @@ public class BcelWorld extends World implements Repository {
}
- protected ReferenceTypeDelegate resolveObjectType(ReferenceType ty) {
+ protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
String name = ty.getName();
JavaClass jc = null;
//UnwovenClassFile classFile = (UnwovenClassFile)sourceJavaClasses.get(name);
@@ -275,7 +275,7 @@ public class BcelWorld extends World implements Repository {
if (nameTypeX == null) {
if (jc.isGeneric()) {
- nameTypeX = ReferenceType.fromTypeX(UnresolvedType.forRawTypeNames(jc.getClassName()),this);
+ nameTypeX = ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()),this);
ret = makeBcelObjectType(nameTypeX, jc, true);
ReferenceType genericRefType = new ReferenceType(
UnresolvedType.forGenericTypeSignature(signature,ret.getDeclaredGenericSignature()),this);
@@ -413,7 +413,7 @@ public class BcelWorld extends World implements Repository {
return buf.toString();
}
- public Advice concreteAdvice(
+ public Advice createAdviceMunger(
AjAttribute.AdviceAttribute attribute,
Pointcut pointcut,
Member signature)
diff --git a/weaver/src/org/aspectj/weaver/bcel/Utility.java b/weaver/src/org/aspectj/weaver/bcel/Utility.java
index d83f39f17..6f1f86a58 100644
--- a/weaver/src/org/aspectj/weaver/bcel/Utility.java
+++ b/weaver/src/org/aspectj/weaver/bcel/Utility.java
@@ -310,7 +310,7 @@ public class Utility {
throw new BCException("can't convert from " + fromType + " to " + toType);
}
// XXX I'm sure this test can be simpler but my brain hurts and this works
- if (!toType.getWorld().behaveInJava5Way) {
+ if (!toType.getWorld().isInJava5Mode()) {
if (toType.needsNoConversionFrom(fromType)) return;
} else {
if (toType.needsNoConversionFrom(fromType) && !(toType.isPrimitiveType()^fromType.isPrimitiveType())) return;
@@ -347,7 +347,7 @@ public class Utility {
Type.OBJECT,
new Type[] { from },
Constants.INVOKESTATIC));
- } else if (toType.getWorld().behaveInJava5Way && validBoxing.get(toType.getSignature()+fromType.getSignature())!=null) {
+ } else if (toType.getWorld().isInJava5Mode() && validBoxing.get(toType.getSignature()+fromType.getSignature())!=null) {
// XXX could optimize by using any java boxing code that may be just before the call...
Type from = BcelWorld.makeBcelType(fromType);
Type to = BcelWorld.makeBcelType(toType);
diff --git a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java
index 25e0b0465..d4e1de80d 100644
--- a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java
+++ b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java
@@ -125,7 +125,7 @@ public class KindedPointcut extends Pointcut {
if (shadow.getIWorld().getLint().noJoinpointsForBridgeMethods.isEnabled()) {
ResolvedMember rm = shadow.getSignature().resolve(shadow.getIWorld());
if (rm!=null) {
- int shadowModifiers = shadow.getSignature().getModifiers(shadow.getIWorld());
+ int shadowModifiers = rm.getModifiers(); //shadow.getSignature().getModifiers(shadow.getIWorld());
if (ResolvedType.hasBridgeModifier(shadowModifiers)) {
shadow.getIWorld().getLint().noJoinpointsForBridgeMethods.signal(new String[]{},getSourceLocation(),
new ISourceLocation[]{shadow.getSourceLocation()});
@@ -189,7 +189,7 @@ public class KindedPointcut extends Pointcut {
// if the method in the declaring type is *not* visible to the
// exact declaring type then warning not needed.
- int shadowModifiers = shadow.getSignature().getModifiers(world);
+ int shadowModifiers = shadow.getSignature().resolve(world).getModifiers();
if (!ResolvedType
.isVisible(
shadowModifiers,
diff --git a/weaver/src/org/aspectj/weaver/raw types.txt b/weaver/src/org/aspectj/weaver/raw types.txt
new file mode 100644
index 000000000..7cd2dccb1
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/raw types.txt
@@ -0,0 +1,40 @@
+
+Current situation with respect to raw types...
+
+* We can create an unresolved type (typeKind = SIMPLE) by
+ UnresolvedType.forSignature or forName
+
+* We can create an unresolved type (typeKind = RAW) by calling
+ UnresolvedType.forRawTypeName
+
+ This method is called by...
+
+ BcelWorld.addSourceObjectType when types in jar files or on the classpath are added to
+ the weaver for processing. If the JavaClass is determined to be generic then a raw
+ UnresolvedType is built and a ReferenceType constructed from that. A BcelObjectType is
+ built using the Resolved raw type (and when it's generic signature is unpacked later that will
+ be swapped out for the generic type). Then a generic type is created, the delegates of
+ the generic and raw types are set to point to the BcelObjectType, and the generic type
+ of the raw type is set to point to the generic type. The raw type is explicitly added into
+ the typeMap.
+
+ EclipseFactory.addSourceTypeBinding when adding a binding for a generic type during
+ completeTypeBindings. This is put into the world by calling world.lookupOrCreateName.
+ Then a generic type is created and the raw type's generic type is set to refer to it.
+
+ EclipseFactory.fromBinding when processing a RawTypeBinding. A later call to resolve
+ is responsible for adding this to the type map.
+
+* World.resolve processing works as follows:
+
+ in resolveObjectType, if the typeKind of the UnresolvedType is neither parameterized
+ nor generic, then a new ReferenceType is created using the rawTypeSignature of the
+ unresolved type. Then the delegate is created, and if this turns out to be generic then a
+ generic type is also built and set as the generic type of the reference type (but nothing
+ sets the type of the reference type to raw???).
+
+ in resolveTheGenericType the rawTypeSignature is looked up in the typeMap. If it
+ is not found, then a new UnresolvedType is created forSignature, resolved (see above),
+ and put in the type map. The generic type is then created and set as the generic type
+ of the raw type.
+
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java
index 494999562..83efcc26d 100644
--- a/weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/WorldTestCase.java
@@ -96,7 +96,7 @@ public class WorldTestCase extends AbstractWorldTestCase {
public void testIterator() {
int abstractPublic = Modifier.ABSTRACT | Modifier.PUBLIC;
- ResolvedType iter = world.getCoreType(UnresolvedType.forRawTypeNames("java.util.Iterator"));
+ ResolvedType iter = world.getCoreType(UnresolvedType.forRawTypeName("java.util.Iterator"));
modifiersTest(iter, abstractPublic | Modifier.INTERFACE);
fieldsTest(iter, ResolvedMember.NONE);