//import org.aspectj.weaver.ResolvedType.Name;
+/**
+ * The AjcMemberMaker is responsible for creating the representations of methods/fields/etc that are placed in both aspects and
+ * affected target types. It uses the NameMangler class to create the actual names that will be used.
+ */
public class AjcMemberMaker {
+
private static final int PUBLIC_STATIC_FINAL = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
private static final int PRIVATE_STATIC = Modifier.PRIVATE | Modifier.STATIC;
private static final int VISIBILITY = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
public static final UnresolvedType CFLOW_STACK_TYPE = UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE);
+
public static final UnresolvedType AROUND_CLOSURE_TYPE = UnresolvedType
.forSignature("Lorg/aspectj/runtime/internal/AroundClosure;");
public static ResolvedMember privilegedAccessMethodForMethod(UnresolvedType aspectType, ResolvedMember method) {
return new ResolvedMemberImpl(Member.METHOD, method.getDeclaringType(), Modifier.PUBLIC
- | (Modifier.isStatic(method.getModifiers()) ? Modifier.STATIC : 0), method.getReturnType(), NameMangler.privilegedAccessMethodForMethod(
- method.getName(), method.getDeclaringType(), aspectType), method.getParameterTypes(), method.getExceptions());
+ | (Modifier.isStatic(method.getModifiers()) ? Modifier.STATIC : 0), method.getReturnType(), NameMangler
+ .privilegedAccessMethodForMethod(method.getName(), method.getDeclaringType(), aspectType), method
+ .getParameterTypes(), method.getExceptions());
}
- public static ResolvedMember privilegedAccessMethodForFieldGet(UnresolvedType aspectType, Member field) {
- String sig;
- if (Modifier.isStatic(field.getModifiers())) {
- sig = "()" + field.getReturnType().getSignature();
+ /**
+ * Return a resolvedmember representing the synthetic getter for the field. The old style (<1.6.9) is a heavyweight static
+ * method with a long name. The new style (1.6.9 and later) is short, and reusable across aspects.
+ *
+ * @param aspectType the aspect attempting the access
+ * @param field the field to be accessed
+ * @param shortSyntax is the old (long) or new (short) style format being used
+ * @return a resolvedmember representing the synthetic getter
+ */
+ public static ResolvedMember privilegedAccessMethodForFieldGet(UnresolvedType aspectType, Member field, boolean shortSyntax) {
+ UnresolvedType fieldDeclaringType = field.getDeclaringType();
+ if (shortSyntax) {
+ UnresolvedType[] args = null;
+ if (Modifier.isStatic(field.getModifiers())) {
+ args = ResolvedType.NONE;
+ } else {
+ args = new UnresolvedType[] { fieldDeclaringType };
+ }
+ StringBuffer name = new StringBuffer("ajc$get$");
+ name.append(field.getName());
+ return new ResolvedMemberImpl(Member.METHOD, fieldDeclaringType, PUBLIC_STATIC, field.getReturnType(), name.toString(),
+ args);
} else {
- sig = "(" + field.getDeclaringType().getSignature() + ")" + field.getReturnType().getSignature();
+ String getterName = NameMangler.privilegedAccessMethodForFieldGet(field.getName(), fieldDeclaringType, aspectType);
+ String sig;
+ if (Modifier.isStatic(field.getModifiers())) {
+ sig = "()" + field.getReturnType().getSignature();
+ } else {
+ sig = "(" + fieldDeclaringType.getSignature() + ")" + field.getReturnType().getSignature();
+ }
+ return new ResolvedMemberImpl(Member.METHOD, fieldDeclaringType, PUBLIC_STATIC, getterName, sig);
}
-
- return new ResolvedMemberImpl(Member.METHOD, field.getDeclaringType(), PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic()
- // ? Modifier.STATIC : 0),
- NameMangler.privilegedAccessMethodForFieldGet(field.getName(), field.getDeclaringType(), aspectType), sig);
}
- public static ResolvedMember privilegedAccessMethodForFieldSet(UnresolvedType aspectType, Member field) {
- String sig;
- if (Modifier.isStatic(field.getModifiers())) {
- sig = "(" + field.getReturnType().getSignature() + ")V";
+ /**
+ * Return a resolvedmember representing the synthetic setter for the field. The old style (<1.6.9) is a heavyweight static
+ * method with a long name. The new style (1.6.9 and later) is short, not always static, and reusable across aspects.
+ *
+ * @param aspectType the aspect attempting the access
+ * @param field the field to be accessed
+ * @param shortSyntax is the old or new style format being used
+ * @return a resolvedmember representing the synthetic setter
+ */
+ public static ResolvedMember privilegedAccessMethodForFieldSet(UnresolvedType aspectType, Member field, boolean shortSyntax) {
+ UnresolvedType fieldDeclaringType = field.getDeclaringType();
+ if (shortSyntax) {
+ UnresolvedType[] args = null;
+ if (Modifier.isStatic(field.getModifiers())) {
+ args = new UnresolvedType[] { field.getType() };
+ } else {
+ args = new UnresolvedType[] { fieldDeclaringType, field.getType() };
+ }
+ StringBuffer name = new StringBuffer("ajc$set$");
+ name.append(field.getName());
+ return new ResolvedMemberImpl(Member.METHOD, fieldDeclaringType, PUBLIC_STATIC, ResolvedType.VOID, name.toString(),
+ args);
} else {
- sig = "(" + field.getDeclaringType().getSignature() + field.getReturnType().getSignature() + ")V";
+ String setterName = NameMangler.privilegedAccessMethodForFieldSet(field.getName(), fieldDeclaringType, aspectType);
+ String sig;
+ if (Modifier.isStatic(field.getModifiers())) {
+ sig = "(" + field.getReturnType().getSignature() + ")V";
+ } else {
+ sig = "(" + fieldDeclaringType.getSignature() + field.getReturnType().getSignature() + ")V";
+ }
+ return new ResolvedMemberImpl(Member.METHOD, fieldDeclaringType, PUBLIC_STATIC, setterName, sig);
}
-
- return new ResolvedMemberImpl(Member.METHOD, field.getDeclaringType(), PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic()
- // ? Modifier.STATIC : 0),
- NameMangler.privilegedAccessMethodForFieldSet(field.getName(), field.getDeclaringType(), aspectType), sig);
}
// --- inline accessors
ResolvedMember ret = new ResolvedMemberImpl(Member.CONSTRUCTOR, targetType, Modifier.PUBLIC, ResolvedType.VOID, "<init>",
constructor.getParameterTypes(), constructor.getExceptions());
// System.out.println("ret: " + ret + " mods: " + Modifier.toString(modifiers));
- if (Modifier.isPublic(constructor.getModifiers()))
+ if (Modifier.isPublic(constructor.getModifiers())) {
return ret;
+ }
while (true) {
ret = addCookieTo(ret, aspectType);
- if (targetType.lookupMemberNoSupers(ret) == null)
+ if (targetType.lookupMemberNoSupers(ret) == null) {
return ret;
+ }
}
}
public static ResolvedMember interFieldInitializer(ResolvedMember field, UnresolvedType aspectType) {
return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, NameMangler.interFieldInitializer(aspectType, field
- .getDeclaringType(), field.getName()), Modifier.isStatic(field.getModifiers()) ? "()V" : "(" + field.getDeclaringType().getSignature()
- + ")V");
+ .getDeclaringType(), field.getName()), Modifier.isStatic(field.getModifiers()) ? "()V" : "("
+ + field.getDeclaringType().getSignature() + ")V");
}
- /**
- * Makes public and non-final
- */
private static int makePublicNonFinal(int modifiers) {
return (modifiers & ~VISIBILITY & ~Modifier.FINAL) | Modifier.PUBLIC;
}
+ private static int makeNonFinal(int modifiers) {
+ return (modifiers & ~Modifier.FINAL);
+ }
+
/**
* This static method goes on the aspect that declares the inter-type field
*/
public static ResolvedMember interFieldSetDispatcher(ResolvedMember field, UnresolvedType aspectType) {
ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, ResolvedType.VOID, NameMangler
- .interFieldSetDispatcher(aspectType, field.getDeclaringType(), field.getName()),
- Modifier.isStatic(field.getModifiers()) ? new UnresolvedType[] { field.getReturnType() } : new UnresolvedType[] {
- field.getDeclaringType(), field.getReturnType() });
+ .interFieldSetDispatcher(aspectType, field.getDeclaringType(), field.getName()), Modifier.isStatic(field
+ .getModifiers()) ? new UnresolvedType[] { field.getReturnType() } : new UnresolvedType[] {
+ field.getDeclaringType(), field.getReturnType() });
rm.setTypeVariables(field.getTypeVariables());
return rm;
}
*/
public static ResolvedMember interFieldGetDispatcher(ResolvedMember field, UnresolvedType aspectType) {
ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, field.getReturnType(), NameMangler
- .interFieldGetDispatcher(aspectType, field.getDeclaringType(), field.getName()),
- Modifier.isStatic(field.getModifiers()) ? UnresolvedType.NONE : new UnresolvedType[] { field.getDeclaringType() }, UnresolvedType.NONE);
+ .interFieldGetDispatcher(aspectType, field.getDeclaringType(), field.getName()), Modifier.isStatic(field
+ .getModifiers()) ? UnresolvedType.NONE : new UnresolvedType[] { field.getDeclaringType() }, UnresolvedType.NONE);
rm.setTypeVariables(field.getTypeVariables());
return rm;
}
// }
/**
- * This field goes on the class the field is declared onto
+ * This field goes on the class the field is declared onto. Field names for ITDs onto interfaces are handled below.
*/
- public static ResolvedMember interFieldClassField(ResolvedMember field, UnresolvedType aspectType) {
- return new ResolvedMemberImpl(Member.FIELD, field.getDeclaringType(), makePublicNonFinal(field.getModifiers()), field
- .getReturnType(), NameMangler.interFieldClassField(field.getModifiers(), aspectType, field.getDeclaringType(),
- field.getName()), UnresolvedType.NONE, UnresolvedType.NONE);
+ public static ResolvedMember interFieldClassField(ResolvedMember field, UnresolvedType aspectType, boolean newStyle) {
+ int modifiers = (newStyle ? makeNonFinal(field.getModifiers()) : makePublicNonFinal(field.getModifiers()));
+ String name = null;
+ if (newStyle) {
+ name = field.getName();
+ } else {
+ name = NameMangler.interFieldClassField(field.getModifiers(), aspectType, field.getDeclaringType(), field.getName());
+ }
+ return new ResolvedMemberImpl(Member.FIELD, field.getDeclaringType(), modifiers, field.getReturnType(), name,
+ UnresolvedType.NONE, UnresolvedType.NONE);
}
/**
*/
public static ResolvedMember interFieldInterfaceSetter(ResolvedMember field, ResolvedType onType, UnresolvedType aspectType) {
int modifiers = Modifier.PUBLIC;
- if (onType.isInterface())
+ if (onType.isInterface()) {
modifiers |= Modifier.ABSTRACT;
+ }
ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, onType, modifiers, ResolvedType.VOID, NameMangler
.interFieldInterfaceSetter(aspectType, field.getDeclaringType(), field.getName()), new UnresolvedType[] { field
.getReturnType() }, UnresolvedType.NONE);
*/
public static ResolvedMember interFieldInterfaceGetter(ResolvedMember field, ResolvedType onType, UnresolvedType aspectType) {
int modifiers = Modifier.PUBLIC;
- if (onType.isInterface())
+ if (onType.isInterface()) {
modifiers |= Modifier.ABSTRACT;
+ }
ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, onType, modifiers, field.getReturnType(), NameMangler
.interFieldInterfaceGetter(aspectType, field.getDeclaringType(), field.getName()), UnresolvedType.NONE,
UnresolvedType.NONE);
* an interface). The implementation will call the interMethodDispatch method on the aspect.
*/
public static ResolvedMember interMethod(ResolvedMember meth, UnresolvedType aspectType, boolean onInterface) {
- if (Modifier.isPublic(meth.getModifiers()) && !onInterface)
+ if (Modifier.isPublic(meth.getModifiers()) && !onInterface) {
return meth;
+ }
int modifiers = makePublicNonFinal(meth.getModifiers());
- if (onInterface)
+ if (onInterface) {
modifiers |= Modifier.ABSTRACT;
+ }
ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, meth.getDeclaringType(), modifiers, meth.getReturnType(),
NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth
// return meth;
int modifiers = makePublicNonFinal(meth.getModifiers()) | BRIDGE;
- if (onInterface)
+ if (onInterface) {
modifiers |= Modifier.ABSTRACT;
+ }
ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, meth.getDeclaringType(), modifiers, meth.getReturnType(),
NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth
public static Member interfaceConstructor(ResolvedType resolvedTypeX) {
// AMC next two lines should not be needed when sig for generic type is changed
ResolvedType declaringType = resolvedTypeX;
- if (declaringType.isRawType())
+ if (declaringType.isRawType()) {
declaringType = declaringType.getGenericType();
+ }
return new ResolvedMemberImpl(Member.CONSTRUCTOR, declaringType, Modifier.PUBLIC, "<init>", "()V");
}
import org.aspectj.bridge.Message;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
import org.aspectj.weaver.Iterators.Getter;
import org.aspectj.weaver.patterns.Declare;
import org.aspectj.weaver.patterns.PerClause;
return munger;
}
- public void addInterTypeMunger(ConcreteTypeMunger munger) {
+ /**
+ * Add an intertype munger to this type. isDuringCompilation tells us if we should be checking for an error scenario where two
+ * ITD fields are trying to use the same name. When this happens during compilation one of them is altered to get mangled name
+ * but when it happens during weaving it is too late and we need to put out an error asking them to recompile.
+ */
+ public void addInterTypeMunger(ConcreteTypeMunger munger, boolean isDuringCompilation) {
ResolvedMember sig = munger.getSignature();
bits = (bits & ~MungersAnalyzed); // clear the bit - as the mungers have changed
if (sig == null || munger.getMunger() == null || munger.getMunger().getKind() == ResolvedTypeMunger.PrivilegedAccess) {
if (clashesWithExistingMember(munger, Arrays.asList(getDeclaredFields()).iterator())) {
return;
}
+ // Cannot cope with two version '2' style mungers for the same field on the same type
+ // Must error and request the user recompile at least one aspect with the
+ // -Xset:itdStyle=1 option
+ if (!isDuringCompilation) {
+ ResolvedTypeMunger thisRealMunger = munger.getMunger();
+ if (thisRealMunger instanceof NewFieldTypeMunger) {
+ NewFieldTypeMunger newFieldTypeMunger = (NewFieldTypeMunger) thisRealMunger;
+ if (newFieldTypeMunger.version == NewFieldTypeMunger.VersionTwo) {
+ String thisRealMungerSignatureName = newFieldTypeMunger.getSignature().getName();
+ for (ConcreteTypeMunger typeMunger : interTypeMungers) {
+ if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
+ if (typeMunger.getSignature().getKind() == Member.FIELD) {
+ NewFieldTypeMunger existing = (NewFieldTypeMunger) typeMunger.getMunger();
+ if (existing.getSignature().getName().equals(thisRealMungerSignatureName)
+ && existing.version == NewFieldTypeMunger.VersionTwo
+ // this check ensures no problem for a clash with an ITD on an interface
+ && existing.getSignature().getDeclaringType().equals(
+ newFieldTypeMunger.getSignature().getDeclaringType())) {
+
+ // report error on the aspect
+ StringBuffer sb = new StringBuffer();
+ sb
+ .append("Cannot handle two aspects both attempting to use new style ITDs for the same named field ");
+ sb
+ .append("on the same target type. Please recompile at least one aspect with '-Xset:itdVersion=1'.");
+ sb.append(" Aspects involved: " + munger.getAspectType().getName() + " and "
+ + typeMunger.getAspectType().getName() + ".");
+ sb.append(" Field is named '" + existing.getSignature().getName() + "'");
+ getWorld().getMessageHandler().handleMessage(
+ new Message(sb.toString(), getSourceLocation(), true));
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
} else {
if (clashesWithExistingMember(munger, Arrays.asList(getDeclaredMethods()).iterator())) {
return;
public ResolvedType next() {
ResolvedType next = delegate.next();
// BUG should check for generics and erase?
-// if (!visited.contains(next)) {
-// visited.add(next);
+ // if (!visited.contains(next)) {
+ // visited.add(next);
if (visited.add(next)) {
toPersue.add(next); // pushes on interfaces already visited?
}
return (bits & TypeHierarchyCompleteBit) != 0;
}
+ /**
+ * return the weaver version used to build this type - defaults to the most recent version unless discovered otherwise.
+ *
+ * @return the (major) version, {@link WeaverVersionInfo}
+ */
+ public int getCompilerVersion() {
+ return WeaverVersionInfo.getCurrentWeaverMajorVersion();
+ }
}