From 037bb06b37960d5facbd0e701d48af5b5a22133c Mon Sep 17 00:00:00 2001 From: aclement Date: Mon, 30 Nov 2009 21:04:12 +0000 Subject: [PATCH] 296484:296501: annotationbinding --- .../src/org/aspectj/weaver/NameMangler.java | 16 +- .../org/aspectj/weaver/ResolvedMember.java | 16 - .../src/org/aspectj/weaver/ResolvedType.java | 2 +- .../ExactAnnotationFieldTypePattern.java | 356 ++++++++++-------- 4 files changed, 202 insertions(+), 188 deletions(-) diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NameMangler.java b/org.aspectj.matcher/src/org/aspectj/weaver/NameMangler.java index e655101f9..201fd352d 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/NameMangler.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/NameMangler.java @@ -58,6 +58,8 @@ public class NameMangler { public static final String INITFAILURECAUSE_FIELD_NAME = PREFIX + "initFailureCause"; + public static final String ANNOTATION_CACHE_FIELD_NAME = PREFIX + "anno$"; + public static boolean isSyntheticMethod(String methodName, boolean declaredInAspect) { if (methodName.startsWith(PREFIX)) { // it's synthetic unless it is an advice method @@ -179,8 +181,10 @@ public class NameMangler { * This field goes on the class the field is declared onto */ public static String interFieldClassField(int modifiers, UnresolvedType aspectType, UnresolvedType classType, String name) { - if (Modifier.isPublic(modifiers)) + // return name; + if (Modifier.isPublic(modifiers)) { return name; + } // ??? might want to handle case where aspect and class are in same package similar to public return makeName("interField", makeVisibilityName(modifiers, aspectType), name); } @@ -221,8 +225,9 @@ public class NameMangler { * interface) */ public static String interMethod(int modifiers, UnresolvedType aspectType, UnresolvedType classType, String name) { - if (Modifier.isPublic(modifiers)) + if (Modifier.isPublic(modifiers)) { return name; + } // ??? might want to handle case where aspect and class are in same package similar to public return makeName("interMethodDispatch2", makeVisibilityName(modifiers, aspectType), name); } @@ -326,12 +331,13 @@ public class NameMangler { public static String getExtractableName(Member shadowSignature) { String name = shadowSignature.getName(); MemberKind kind = shadowSignature.getKind(); - if (kind == Member.CONSTRUCTOR) + if (kind == Member.CONSTRUCTOR) { return "init$"; - else if (kind == Member.STATIC_INITIALIZATION) + } else if (kind == Member.STATIC_INITIALIZATION) { return "clinit$"; - else + } else { return name; + } } public static String proceedMethodName(String adviceMethodName) { diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java index fa887eb95..1f82713e4 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java @@ -144,22 +144,6 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe public TypeVariable[] getTypeVariables(); - // /** - // * If this member is defined by a parameterized super-type, return the - // erasure - // * of that member. - // * For example: - // * interface I { T foo(T aTea); } - // * class C implements I { - // * String foo(String aString) { return "something"; } - // * } - // * The resolved member for C.foo has signature String foo(String). The - // * erasure of that member is Object foo(Object) -- use upper bound of type - // * variable. - // * A type is a supertype of itself. - // */ - // public ResolvedMember getErasure(); - /** * Returns true if this member matches the other. The matching takes into account name and parameter types only. When comparing * parameter types, we allow any type variable to match any other type variable regardless of bounds. diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java index 8f793f8d0..963b0a86b 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java @@ -2266,7 +2266,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl ResolvedPointcutDefinition toAdd = (ResolvedPointcutDefinition) i.next(); for (Iterator j = acc.iterator(); j.hasNext();) { ResolvedPointcutDefinition existing = (ResolvedPointcutDefinition) j.next(); - if (toAdd==null || existing == toAdd) { + if (toAdd==null || existing==null || existing == toAdd) { continue; } UnresolvedType pointcutDeclaringTypeUT = existing.getDeclaringType(); diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationFieldTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationFieldTypePattern.java index 0263035eb..ea2ec2a70 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationFieldTypePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationFieldTypePattern.java @@ -36,171 +36,195 @@ import org.aspectj.weaver.World; */ public class ExactAnnotationFieldTypePattern extends ExactAnnotationTypePattern { - UnresolvedType annotationType; - private ResolvedMember field; - - public ExactAnnotationFieldTypePattern(ExactAnnotationTypePattern p, String formalName) { - super(formalName); - this.annotationType = p.annotationType; - this.copyLocationFrom(p); - } - - public ExactAnnotationFieldTypePattern(UnresolvedType annotationType, String formalName) { - super(formalName); - this.annotationType = annotationType; - } - - /** - * resolve one of these funky things. Need to:
- * (a) Check the formal is bound
- * (b) Check the annotation type is valid - */ - public AnnotationTypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding) { - if (resolved) return this; - resolved = true; - FormalBinding formalBinding = scope.lookupFormal(formalName); - if (formalBinding == null) { - scope.message(IMessage.ERROR, this, "When using @annotation(()), must be bound"); - return this; - } - - annotationType = scope.getWorld().resolve(annotationType, true); - - // May not be directly found if in a package, so go looking if that is the case: - if (ResolvedType.isMissing(annotationType)) { - String cleanname = annotationType.getName(); - UnresolvedType type = null; - while (ResolvedType.isMissing(type = scope.lookupType(cleanname, this))) { - int lastDot = cleanname.lastIndexOf('.'); - if (lastDot == -1) break; - cleanname = cleanname.substring(0, lastDot) + "$" + cleanname.substring(lastDot + 1); - } - annotationType = scope.getWorld().resolve(type, true); - if (ResolvedType.isMissing(annotationType)) { - // there are likely to be other errors around that have led to us being unable to - // resolve the annotation type, let's quit now - return this; - } - } - - verifyIsAnnotationType((ResolvedType) annotationType, scope); - - if (!formalBinding.getType().resolve(scope.getWorld()).isEnum()) { - scope.message(IMessage.ERROR, this, "The field within the annotation must be an Enum. '" + formalBinding.getType() - + "' is not an Enum (compiler limitation)"); - } - bindingPattern = true; - - // Check that the formal is bound to a type that is represented by one field in the annotation type - ReferenceType theAnnotationType = (ReferenceType) annotationType; - ResolvedMember[] annotationFields = theAnnotationType.getDeclaredMethods(); - field = null; - for (int i = 0; i < annotationFields.length; i++) { - ResolvedMember resolvedMember = annotationFields[i]; - if (resolvedMember.getReturnType().equals(formalBinding.getType())) { - if (field != null) { - scope.message(IMessage.ERROR, this, "The field type '" + formalBinding.getType() + "' is ambiguous for annotation type '" - + theAnnotationType.getName() + "'"); - } - field = resolvedMember; - } - } - if (field == null) { - scope.message(IMessage.ERROR, this, "No field of type '" + formalBinding.getType() + "' exists on annotation type '" - + theAnnotationType.getName() + "'"); - } - - BindingAnnotationFieldTypePattern binding = new BindingAnnotationFieldTypePattern(formalBinding.getType(), formalBinding.getIndex(), - theAnnotationType); - binding.copyLocationFrom(this); - bindings.register(binding, scope); - binding.resolveBinding(scope.getWorld()); - return binding; - } - - public void write(DataOutputStream s) throws IOException { - s.writeByte(AnnotationTypePattern.EXACTFIELD); - s.writeUTF(formalName); - annotationType.write(s); - writeLocation(s); - } - - public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException { - ExactAnnotationFieldTypePattern ret; - String formalName = s.readUTF(); - UnresolvedType annotationType = UnresolvedType.read(s); - ret = new ExactAnnotationFieldTypePattern(annotationType, formalName); - ret.readLocation(context, s); - return ret; - } - - // --- - - public Object accept(PatternNodeVisitor visitor, Object data) { - return visitor.visit(this, data); - } - - public boolean equals(Object obj) { - if (!(obj instanceof ExactAnnotationFieldTypePattern)) return false; - ExactAnnotationFieldTypePattern other = (ExactAnnotationFieldTypePattern) obj; - return - (other.annotationType.equals(annotationType)) && - (other.field.equals(field)) && (other.formalName.equals(this.formalName)); - } - - public int hashCode() { - int hashcode = annotationType.hashCode(); - hashcode = hashcode * 37 + field.hashCode(); - hashcode = hashcode * 37 + formalName.hashCode(); - return hashcode; - } - - // TODO these are currently unimplemented as I believe it resolves to a Binding form *always* and so they don't get - // called - - public FuzzyBoolean fastMatches(AnnotatedElement annotated) { - throw new BCException("unimplemented"); - } - - public UnresolvedType getAnnotationType() { - throw new BCException("unimplemented"); - } - - public Map getAnnotationValues() { - throw new BCException("unimplemented"); - } - - public ResolvedType getResolvedAnnotationType() { - throw new BCException("unimplemented"); - } - - - public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) { - throw new BCException("unimplemented"); - } - - public FuzzyBoolean matches(AnnotatedElement annotated) { - throw new BCException("unimplemented"); - } - - public FuzzyBoolean matchesRuntimeType(AnnotatedElement annotated) { - throw new BCException("unimplemented"); - } - - public AnnotationTypePattern parameterizeWith(Map typeVariableMap, World w) { - throw new BCException("unimplemented"); - } - - public void resolve(World world) { - throw new BCException("unimplemented"); - } - - public String toString() { - if (!resolved && formalName != null) return formalName; - StringBuffer ret = new StringBuffer(); - ret.append("@").append(annotationType.toString()); - ret.append("(").append(formalName).append(")"); - return ret.toString(); - } + UnresolvedType annotationType; + private ResolvedMember field; + + public ExactAnnotationFieldTypePattern(ExactAnnotationTypePattern p, String formalName) { + super(formalName); + this.annotationType = p.annotationType; + this.copyLocationFrom(p); + } + + public ExactAnnotationFieldTypePattern(UnresolvedType annotationType, String formalName) { + super(formalName); + this.annotationType = annotationType; + } + + /** + * resolve one of these funky things. Need to:
+ * (a) Check the formal is bound
+ * (b) Check the annotation type is valid + */ + @Override + public AnnotationTypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding) { + if (resolved) { + return this; + } + resolved = true; + FormalBinding formalBinding = scope.lookupFormal(formalName); + if (formalBinding == null) { + scope.message(IMessage.ERROR, this, + "When using @annotation(()), must be bound"); + return this; + } + + annotationType = scope.getWorld().resolve(annotationType, true); + + // May not be directly found if in a package, so go looking if that is the case: + if (ResolvedType.isMissing(annotationType)) { + String cleanname = annotationType.getName(); + UnresolvedType type = null; + while (ResolvedType.isMissing(type = scope.lookupType(cleanname, this))) { + int lastDot = cleanname.lastIndexOf('.'); + if (lastDot == -1) { + break; + } + cleanname = cleanname.substring(0, lastDot) + "$" + cleanname.substring(lastDot + 1); + } + annotationType = scope.getWorld().resolve(type, true); + if (ResolvedType.isMissing(annotationType)) { + // there are likely to be other errors around that have led to us being unable to + // resolve the annotation type, let's quit now + return this; + } + } + + verifyIsAnnotationType((ResolvedType) annotationType, scope); + + ResolvedType formalBindingType = formalBinding.getType().resolve(scope.getWorld()); + + if (!(formalBindingType.isEnum() || formalBindingType.getSignature().equals("Ljava/lang/String;"))) { + scope.message(IMessage.ERROR, this, "The field within the annotation must be an enum or string. '" + + formalBinding.getType() + "' is not (compiler limitation)"); + } + bindingPattern = true; + + // Check that the formal is bound to a type that is represented by one field in the annotation type + ReferenceType theAnnotationType = (ReferenceType) annotationType; + ResolvedMember[] annotationFields = theAnnotationType.getDeclaredMethods(); + field = null; + for (int i = 0; i < annotationFields.length; i++) { + ResolvedMember resolvedMember = annotationFields[i]; + if (resolvedMember.getReturnType().equals(formalBinding.getType())) { + if (field != null) { + scope.message(IMessage.ERROR, this, "The field type '" + formalBinding.getType() + + "' is ambiguous for annotation type '" + theAnnotationType.getName() + "'"); + } + field = resolvedMember; + } + } + if (field == null) { + scope.message(IMessage.ERROR, this, "No field of type '" + formalBinding.getType() + "' exists on annotation type '" + + theAnnotationType.getName() + "'"); + } + + BindingAnnotationFieldTypePattern binding = new BindingAnnotationFieldTypePattern(formalBinding.getType(), formalBinding + .getIndex(), theAnnotationType); + binding.copyLocationFrom(this); + bindings.register(binding, scope); + binding.resolveBinding(scope.getWorld()); + return binding; + } + + @Override + public void write(DataOutputStream s) throws IOException { + s.writeByte(AnnotationTypePattern.EXACTFIELD); + s.writeUTF(formalName); + annotationType.write(s); + writeLocation(s); + } + + public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException { + ExactAnnotationFieldTypePattern ret; + String formalName = s.readUTF(); + UnresolvedType annotationType = UnresolvedType.read(s); + ret = new ExactAnnotationFieldTypePattern(annotationType, formalName); + ret.readLocation(context, s); + return ret; + } + + // --- + + @Override + public Object accept(PatternNodeVisitor visitor, Object data) { + return visitor.visit(this, data); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ExactAnnotationFieldTypePattern)) { + return false; + } + ExactAnnotationFieldTypePattern other = (ExactAnnotationFieldTypePattern) obj; + return (other.annotationType.equals(annotationType)) && (other.field.equals(field)) + && (other.formalName.equals(this.formalName)); + } + + @Override + public int hashCode() { + int hashcode = annotationType.hashCode(); + hashcode = hashcode * 37 + field.hashCode(); + hashcode = hashcode * 37 + formalName.hashCode(); + return hashcode; + } + + // TODO these are currently unimplemented as I believe it resolves to a Binding form *always* and so they don't get + // called + + @Override + public FuzzyBoolean fastMatches(AnnotatedElement annotated) { + throw new BCException("unimplemented"); + } + + @Override + public UnresolvedType getAnnotationType() { + throw new BCException("unimplemented"); + } + + @Override + public Map getAnnotationValues() { + throw new BCException("unimplemented"); + } + + @Override + public ResolvedType getResolvedAnnotationType() { + throw new BCException("unimplemented"); + } + + @Override + public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) { + throw new BCException("unimplemented"); + } + + @Override + public FuzzyBoolean matches(AnnotatedElement annotated) { + throw new BCException("unimplemented"); + } + + @Override + public FuzzyBoolean matchesRuntimeType(AnnotatedElement annotated) { + throw new BCException("unimplemented"); + } + + @Override + public AnnotationTypePattern parameterizeWith(Map typeVariableMap, World w) { + throw new BCException("unimplemented"); + } + + @Override + public void resolve(World world) { + throw new BCException("unimplemented"); + } + + @Override + public String toString() { + if (!resolved && formalName != null) { + return formalName; + } + StringBuffer ret = new StringBuffer(); + ret.append("@").append(annotationType.toString()); + ret.append("(").append(formalName).append(")"); + return ret.toString(); + } } -- 2.39.5