diff options
author | aclement <aclement> | 2009-02-20 20:57:59 +0000 |
---|---|---|
committer | aclement <aclement> | 2009-02-20 20:57:59 +0000 |
commit | 5d5accd13723457fa8f1501f7c20f21af5e697fb (patch) | |
tree | 37cc30eb9e2eac3e7c5bd400d016d84e0bc4d94d /org.aspectj.matcher | |
parent | e8309925eb9c0a86d3cf6a786cb95fc4be349242 (diff) | |
download | aspectj-5d5accd13723457fa8f1501f7c20f21af5e697fb.tar.gz aspectj-5d5accd13723457fa8f1501f7c20f21af5e697fb.zip |
265695: inherited anno matching
Diffstat (limited to 'org.aspectj.matcher')
-rw-r--r-- | org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java | 879 |
1 files changed, 460 insertions, 419 deletions
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java index 0643b480c..80ee4474c 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java @@ -10,7 +10,6 @@ * PARC initial implementation * ******************************************************************/ - package org.aspectj.weaver.patterns; import java.io.DataOutputStream; @@ -25,7 +24,7 @@ import java.util.Set; import org.aspectj.bridge.ISourceLocation; import org.aspectj.util.FuzzyBoolean; -import org.aspectj.weaver.AjAttribute; +import org.aspectj.weaver.AjAttribute; import org.aspectj.weaver.AjcMemberMaker; import org.aspectj.weaver.AnnotationTargetKind; import org.aspectj.weaver.ConcreteTypeMunger; @@ -40,23 +39,19 @@ import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.VersionedDataInputStream; import org.aspectj.weaver.World; - public class SignaturePattern extends PatternNode { private MemberKind kind; private ModifiersPattern modifiers; private TypePattern returnType; - private TypePattern declaringType; + private TypePattern declaringType; private NamePattern name; - private TypePatternList parameterTypes; - private ThrowsPattern throwsPattern; - private AnnotationTypePattern annotationPattern; - private transient int hashcode = -1; - - public SignaturePattern(MemberKind kind, ModifiersPattern modifiers, - TypePattern returnType, TypePattern declaringType, - NamePattern name, TypePatternList parameterTypes, - ThrowsPattern throwsPattern, - AnnotationTypePattern annotationPattern) { + private TypePatternList parameterTypes; + private ThrowsPattern throwsPattern; + private AnnotationTypePattern annotationPattern; + private transient int hashcode = -1; + + public SignaturePattern(MemberKind kind, ModifiersPattern modifiers, TypePattern returnType, TypePattern declaringType, + NamePattern name, TypePatternList parameterTypes, ThrowsPattern throwsPattern, AnnotationTypePattern annotationPattern) { this.kind = kind; this.modifiers = modifiers; this.returnType = returnType; @@ -66,84 +61,84 @@ public class SignaturePattern extends PatternNode { this.throwsPattern = throwsPattern; this.annotationPattern = annotationPattern; } - - - public SignaturePattern resolveBindings(IScope scope, Bindings bindings) { + + public SignaturePattern resolveBindings(IScope scope, Bindings bindings) { if (returnType != null) { returnType = returnType.resolveBindings(scope, bindings, false, false); - checkForIncorrectTargetKind(returnType,scope,false); - } + checkForIncorrectTargetKind(returnType, scope, false); + } if (declaringType != null) { declaringType = declaringType.resolveBindings(scope, bindings, false, false); - checkForIncorrectTargetKind(declaringType,scope,false); + checkForIncorrectTargetKind(declaringType, scope, false); } if (parameterTypes != null) { parameterTypes = parameterTypes.resolveBindings(scope, bindings, false, false); - checkForIncorrectTargetKind(parameterTypes,scope,false,true); + checkForIncorrectTargetKind(parameterTypes, scope, false, true); } if (throwsPattern != null) { throwsPattern = throwsPattern.resolveBindings(scope, bindings); - if (throwsPattern.getForbidden().getTypePatterns().length > 0 + if (throwsPattern.getForbidden().getTypePatterns().length > 0 || throwsPattern.getRequired().getTypePatterns().length > 0) { - checkForIncorrectTargetKind(throwsPattern,scope,false); + checkForIncorrectTargetKind(throwsPattern, scope, false); } } if (annotationPattern != null) { - annotationPattern = annotationPattern.resolveBindings(scope,bindings,false); - checkForIncorrectTargetKind(annotationPattern,scope,true); - } - hashcode =-1; - return this; - } - private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed) { - checkForIncorrectTargetKind(patternNode, scope, targetsOtherThanTypeAllowed, false); - - } - - // bug 115252 - adding an xlint warning if the annnotation target type is - // wrong. This logic, or similar, may have to be applied elsewhere in the case - // of pointcuts which don't go through SignaturePattern.resolveBindings(..) - private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed, boolean parameterTargettingAnnotationsAllowed) { - // return if we're not in java5 mode, if the unmatchedTargetKind Xlint - // warning has been turned off, or if the patternNode is * - if (!scope.getWorld().isInJava5Mode() - || scope.getWorld().getLint().unmatchedTargetKind == null - || (patternNode instanceof AnyTypePattern)) { + annotationPattern = annotationPattern.resolveBindings(scope, bindings, false); + checkForIncorrectTargetKind(annotationPattern, scope, true); + } + hashcode = -1; + return this; + } + + private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed) { + checkForIncorrectTargetKind(patternNode, scope, targetsOtherThanTypeAllowed, false); + + } + + // bug 115252 - adding an xlint warning if the annnotation target type is + // wrong. This logic, or similar, may have to be applied elsewhere in the case + // of pointcuts which don't go through SignaturePattern.resolveBindings(..) + private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed, + boolean parameterTargettingAnnotationsAllowed) { + // return if we're not in java5 mode, if the unmatchedTargetKind Xlint + // warning has been turned off, or if the patternNode is * + if (!scope.getWorld().isInJava5Mode() || scope.getWorld().getLint().unmatchedTargetKind == null + || (patternNode instanceof AnyTypePattern)) { return; } if (patternNode instanceof ExactAnnotationTypePattern) { - ResolvedType resolvedType = ((ExactAnnotationTypePattern)patternNode).getAnnotationType().resolve(scope.getWorld()); + ResolvedType resolvedType = ((ExactAnnotationTypePattern) patternNode).getAnnotationType().resolve(scope.getWorld()); if (targetsOtherThanTypeAllowed) { AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds(); - if (targetKinds == null) return; - reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,true); + if (targetKinds == null) + return; + reportUnmatchedTargetKindMessage(targetKinds, patternNode, scope, true); } else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) { // everything is incorrect since we've already checked whether we have the TYPE target annotation AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds(); - if (targetKinds == null) return; - reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,false); + if (targetKinds == null) + return; + reportUnmatchedTargetKindMessage(targetKinds, patternNode, scope, false); } } else { - TypePatternVisitor visitor = new TypePatternVisitor(scope,targetsOtherThanTypeAllowed,parameterTargettingAnnotationsAllowed); - patternNode.traverse(visitor,null); + TypePatternVisitor visitor = new TypePatternVisitor(scope, targetsOtherThanTypeAllowed, + parameterTargettingAnnotationsAllowed); + patternNode.traverse(visitor, null); if (visitor.containedIncorrectTargetKind()) { - Set keys = visitor.getIncorrectTargetKinds().keySet(); + Set keys = visitor.getIncorrectTargetKinds().keySet(); for (Iterator iter = keys.iterator(); iter.hasNext();) { - PatternNode node = (PatternNode)iter.next(); - AnnotationTargetKind[] targetKinds = (AnnotationTargetKind[]) visitor.getIncorrectTargetKinds().get(node); - reportUnmatchedTargetKindMessage(targetKinds,node,scope,false); + PatternNode node = (PatternNode) iter.next(); + AnnotationTargetKind[] targetKinds = (AnnotationTargetKind[]) visitor.getIncorrectTargetKinds().get(node); + reportUnmatchedTargetKindMessage(targetKinds, node, scope, false); } } } - } - - private void reportUnmatchedTargetKindMessage( - AnnotationTargetKind[] annotationTargetKinds, - PatternNode node, - IScope scope, - boolean checkMatchesMemberKindName) { - StringBuffer targetNames = new StringBuffer("{"); - for (int i = 0; i < annotationTargetKinds.length; i++) { + } + + private void reportUnmatchedTargetKindMessage(AnnotationTargetKind[] annotationTargetKinds, PatternNode node, IScope scope, + boolean checkMatchesMemberKindName) { + StringBuffer targetNames = new StringBuffer("{"); + for (int i = 0; i < annotationTargetKinds.length; i++) { AnnotationTargetKind targetKind = annotationTargetKinds[i]; if (checkMatchesMemberKindName && kind.getName().equals(targetKind.getName())) { return; @@ -154,112 +149,112 @@ public class SignaturePattern extends PatternNode { targetNames.append("ElementType." + targetKind.getName() + "}"); } } - scope.getWorld().getLint().unmatchedTargetKind.signal(new String[] {node.toString(),targetNames.toString()}, getSourceLocation(), new ISourceLocation[0]); - } - - /** - * Class which visits the nodes in the TypePattern tree until an - * ExactTypePattern is found. Once this is found it creates a new - * ExactAnnotationTypePattern and checks whether the targetKind - * (created via the @Target annotation) matches ElementType.TYPE if - * this is the only target kind which is allowed, or matches the - * signature pattern kind if there is no restriction. - */ - private class TypePatternVisitor extends AbstractPatternNodeVisitor { - - private IScope scope; - private Map incorrectTargetKinds /* PatternNode -> AnnotationTargetKind[] */ = new HashMap(); - private boolean targetsOtherThanTypeAllowed; + scope.getWorld().getLint().unmatchedTargetKind.signal(new String[] { node.toString(), targetNames.toString() }, + getSourceLocation(), new ISourceLocation[0]); + } + + /** + * Class which visits the nodes in the TypePattern tree until an ExactTypePattern is found. Once this is found it creates a new + * ExactAnnotationTypePattern and checks whether the targetKind (created via the @Target annotation) matches ElementType.TYPE if + * this is the only target kind which is allowed, or matches the signature pattern kind if there is no restriction. + */ + private class TypePatternVisitor extends AbstractPatternNodeVisitor { + + private IScope scope; + private Map incorrectTargetKinds /* PatternNode -> AnnotationTargetKind[] */= new HashMap(); + private boolean targetsOtherThanTypeAllowed; private boolean parameterTargettingAnnotationsAllowed; - /** - * @param requiredTarget - the signature pattern Kind - * @param scope - * @param parameterTargettingAnnotationsAllowed - */ - public TypePatternVisitor(IScope scope, boolean targetsOtherThanTypeAllowed, boolean parameterTargettingAnnotationsAllowed) { - this.scope = scope; - this.targetsOtherThanTypeAllowed = targetsOtherThanTypeAllowed; - this.parameterTargettingAnnotationsAllowed = parameterTargettingAnnotationsAllowed; - } - - public Object visit(WildAnnotationTypePattern node, Object data) { - node.getTypePattern().accept(this,data); - return node; - } - - /** - * Do the ExactAnnotationTypePatterns have the incorrect target? - */ - public Object visit(ExactAnnotationTypePattern node, Object data) { - ResolvedType resolvedType = node.getAnnotationType().resolve(scope.getWorld()); + /** + * @param requiredTarget - the signature pattern Kind + * @param scope + * @param parameterTargettingAnnotationsAllowed + */ + public TypePatternVisitor(IScope scope, boolean targetsOtherThanTypeAllowed, boolean parameterTargettingAnnotationsAllowed) { + this.scope = scope; + this.targetsOtherThanTypeAllowed = targetsOtherThanTypeAllowed; + this.parameterTargettingAnnotationsAllowed = parameterTargettingAnnotationsAllowed; + } + + public Object visit(WildAnnotationTypePattern node, Object data) { + node.getTypePattern().accept(this, data); + return node; + } + + /** + * Do the ExactAnnotationTypePatterns have the incorrect target? + */ + public Object visit(ExactAnnotationTypePattern node, Object data) { + ResolvedType resolvedType = node.getAnnotationType().resolve(scope.getWorld()); if (targetsOtherThanTypeAllowed) { AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds(); - if (targetKinds == null) return data; + if (targetKinds == null) + return data; List incorrectTargets = new ArrayList(); for (int i = 0; i < targetKinds.length; i++) { - if (targetKinds[i].getName().equals(kind.getName()) || - (targetKinds[i].getName().equals("PARAMETER") && node.isForParameterAnnotationMatch()) - ) { + if (targetKinds[i].getName().equals(kind.getName()) + || (targetKinds[i].getName().equals("PARAMETER") && node.isForParameterAnnotationMatch())) { return data; } incorrectTargets.add(targetKinds[i]); } - if (incorrectTargets.isEmpty()) return data; + if (incorrectTargets.isEmpty()) + return data; AnnotationTargetKind[] kinds = new AnnotationTargetKind[incorrectTargets.size()]; - incorrectTargetKinds.put(node,(AnnotationTargetKind[]) incorrectTargets.toArray(kinds)); + incorrectTargetKinds.put(node, (AnnotationTargetKind[]) incorrectTargets.toArray(kinds)); } else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) { AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds(); - if (targetKinds == null) return data; + if (targetKinds == null) + return data; // exception here is if parameter annotations are allowed if (parameterTargettingAnnotationsAllowed) { for (int i = 0; i < targetKinds.length; i++) { AnnotationTargetKind annotationTargetKind = targetKinds[i]; - if (annotationTargetKind.getName().equals("PARAMETER") && node.isForParameterAnnotationMatch()) return data; + if (annotationTargetKind.getName().equals("PARAMETER") && node.isForParameterAnnotationMatch()) + return data; } } - incorrectTargetKinds.put(node,targetKinds); + incorrectTargetKinds.put(node, targetKinds); } - return data; - } - - public Object visit(ExactTypePattern node, Object data) { - ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(node.getExactType().resolve(scope.getWorld()),null); - eatp.accept(this,data); - return data; - } - - public Object visit(AndTypePattern node, Object data) { - node.getLeft().accept(this,data); - node.getRight().accept(this,data); - return node; - } - - public Object visit(OrTypePattern node, Object data) { - node.getLeft().accept(this,data); - node.getRight().accept(this,data); - return node; - } - - public Object visit(AnyWithAnnotationTypePattern node, Object data) { - node.getAnnotationPattern().accept(this,data); - return node; - } - - public boolean containedIncorrectTargetKind() { - return (incorrectTargetKinds.size() != 0); - } - - public Map getIncorrectTargetKinds() { - return incorrectTargetKinds; - } - } - - + return data; + } + + public Object visit(ExactTypePattern node, Object data) { + ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(node.getExactType().resolve(scope.getWorld()), null); + eatp.accept(this, data); + return data; + } + + public Object visit(AndTypePattern node, Object data) { + node.getLeft().accept(this, data); + node.getRight().accept(this, data); + return node; + } + + public Object visit(OrTypePattern node, Object data) { + node.getLeft().accept(this, data); + node.getRight().accept(this, data); + return node; + } + + public Object visit(AnyWithAnnotationTypePattern node, Object data) { + node.getAnnotationPattern().accept(this, data); + return node; + } + + public boolean containedIncorrectTargetKind() { + return (incorrectTargetKinds.size() != 0); + } + + public Map getIncorrectTargetKinds() { + return incorrectTargetKinds; + } + } + public void postRead(ResolvedType enclosingType) { if (returnType != null) { returnType.postRead(enclosingType); - } + } if (declaringType != null) { declaringType.postRead(enclosingType); } @@ -267,103 +262,127 @@ public class SignaturePattern extends PatternNode { parameterTypes.postRead(enclosingType); } } - + /** - * return a copy of this signature pattern in which every type variable reference - * is replaced by the corresponding entry in the map. + * return a copy of this signature pattern in which every type variable reference is replaced by the corresponding entry in the + * map. */ - public SignaturePattern parameterizeWith(Map typeVariableMap,World w) { - SignaturePattern ret = new SignaturePattern( - kind, - modifiers, - returnType.parameterizeWith(typeVariableMap,w), - declaringType.parameterizeWith(typeVariableMap,w), - name, - parameterTypes.parameterizeWith(typeVariableMap,w), - throwsPattern.parameterizeWith(typeVariableMap,w), - annotationPattern.parameterizeWith(typeVariableMap,w)); + public SignaturePattern parameterizeWith(Map typeVariableMap, World w) { + SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType.parameterizeWith(typeVariableMap, w), declaringType + .parameterizeWith(typeVariableMap, w), name, parameterTypes.parameterizeWith(typeVariableMap, w), throwsPattern + .parameterizeWith(typeVariableMap, w), annotationPattern.parameterizeWith(typeVariableMap, w)); ret.copyLocationFrom(this); return ret; } - + public boolean matches(Member joinPointSignature, World world, boolean allowBridgeMethods) { // fail (or succeed!) fast tests... - if (joinPointSignature == null) return false; - if (kind != joinPointSignature.getKind()) return false; - if (kind == Member.ADVICE) return true; - + if (joinPointSignature == null) + return false; + if (kind != joinPointSignature.getKind()) + return false; + if (kind == Member.ADVICE) + return true; + // do the hard work then... boolean subjectMatch = true; + boolean wantsAnnotationMatch = wantToMatchAnnotationPattern(); Iterator candidateMatches = joinPointSignature.getJoinPointSignatures(world); - while(candidateMatches.hasNext()) { + while (candidateMatches.hasNext()) { JoinPointSignature aSig = (JoinPointSignature) candidateMatches.next(); - FuzzyBoolean matchResult = matchesExactly(aSig,world,allowBridgeMethods,subjectMatch); + // System.out.println(aSig); + FuzzyBoolean matchResult = matchesExactly(aSig, world, allowBridgeMethods, subjectMatch); if (matchResult.alwaysTrue()) { return true; } else if (matchResult.alwaysFalse()) { return false; } // if we got a "MAYBE" it's worth looking at the other signatures + // The first signature is the subject signature - and against it we must match modifiers/annotations/throws + // see http://www.eclipse.org/aspectj/doc/next/adk15notebook/join-point-modifiers.html subjectMatch = false; + // Early exit + if (wantsAnnotationMatch) { + return false; + } } return false; } - + // Does this pattern match this exact signature (no declaring type mucking about // or chasing up the hierarchy) // return YES if it does, NO if it doesn't and no ancester member could match either, // and MAYBE if it doesn't but an ancester member could. - private FuzzyBoolean matchesExactly(JoinPointSignature aMember, World inAWorld, boolean allowBridgeMethods,boolean subjectMatch) { + private FuzzyBoolean matchesExactly(JoinPointSignature aMember, World inAWorld, boolean allowBridgeMethods, boolean subjectMatch) { // Java5 introduces bridge methods, we match a call to them but nothing else... if (aMember.isBridgeMethod() && !allowBridgeMethods) { return FuzzyBoolean.MAYBE; } - - // modifiers match on the *subject* + + // Only the subject is checked for modifiers + // see http://www.eclipse.org/aspectj/doc/next/adk15notebook/join-point-modifiers.html if (subjectMatch && !modifiers.matches(aMember.getModifiers())) { return FuzzyBoolean.NO; -// if (aMember.isPrivate()) return FuzzyBoolean.NO; -// else return FuzzyBoolean.MAYBE; } - - + FuzzyBoolean matchesIgnoringAnnotations = FuzzyBoolean.YES; if (kind == Member.STATIC_INITIALIZATION) { matchesIgnoringAnnotations = matchesExactlyStaticInitialization(aMember, inAWorld); } else if (kind == Member.FIELD) { - matchesIgnoringAnnotations = matchesExactlyField(aMember,inAWorld); + matchesIgnoringAnnotations = matchesExactlyField(aMember, inAWorld); } else if (kind == Member.METHOD) { - matchesIgnoringAnnotations = matchesExactlyMethod(aMember,inAWorld, subjectMatch); + matchesIgnoringAnnotations = matchesExactlyMethod(aMember, inAWorld, subjectMatch); } else if (kind == Member.CONSTRUCTOR) { matchesIgnoringAnnotations = matchesExactlyConstructor(aMember, inAWorld); } - if (matchesIgnoringAnnotations.alwaysFalse()) return FuzzyBoolean.NO; - - // why did Adrian put this comment in: - // annotations match on the *subject* - // surely you never want execution(@Something * *(..)) to match something just because - // it is a secondary join point signature for a join point and doesn't have the annotation? - // pr239441 - if (matchesIgnoringAnnotations.alwaysTrue()) { - return matchesAnnotations(aMember,inAWorld); + if (matchesIgnoringAnnotations.alwaysFalse()) { + return FuzzyBoolean.NO; + } + + // Only the subject is checked for annotations (239441/119749) + // see http://www.eclipse.org/aspectj/doc/next/adk15notebook/join-point-modifiers.html + if (subjectMatch) { + // The annotations must match if specified + if (!matchesAnnotations(aMember, inAWorld).alwaysTrue()) { + return FuzzyBoolean.NO; + } else { + return matchesIgnoringAnnotations; + } } else { - return matchesIgnoringAnnotations; + // Unless they specified any annotation then it is a failure + if (annotationPattern instanceof AnyAnnotationTypePattern) { + return matchesIgnoringAnnotations; + } else { + return FuzzyBoolean.NO; + } } - + + // if (subjectMatch && !matchesAnnotations(aMember, inAWorld).alwaysTrue()) { + // return FuzzyBoolean.NO; + // } else { + // + // return matchesIgnoringAnnotations; + // } + } - + + private boolean wantToMatchAnnotationPattern() { + return !(annotationPattern instanceof AnyAnnotationTypePattern); + } + /** * Matches on declaring type */ - private FuzzyBoolean matchesExactlyStaticInitialization(JoinPointSignature aMember,World world) { + private FuzzyBoolean matchesExactlyStaticInitialization(JoinPointSignature aMember, World world) { return FuzzyBoolean.fromBoolean(declaringType.matchesStatically(aMember.getDeclaringType().resolve(world))); } - + /** * Matches on name, declaring type, field type */ private FuzzyBoolean matchesExactlyField(JoinPointSignature aField, World world) { - if (!name.matches(aField.getName())) return FuzzyBoolean.NO; + if (!name.matches(aField.getName())) + return FuzzyBoolean.NO; ResolvedType fieldDeclaringType = aField.getDeclaringType().resolve(world); if (!declaringType.matchesStatically(fieldDeclaringType)) { return FuzzyBoolean.MAYBE; @@ -378,16 +397,19 @@ public class SignaturePattern extends PatternNode { // passed all the guards... return FuzzyBoolean.YES; } - + /** * Matches on name, declaring type, return type, parameter types, throws types */ private FuzzyBoolean matchesExactlyMethod(JoinPointSignature aMethod, World world, boolean subjectMatch) { - if (!name.matches(aMethod.getName())) return FuzzyBoolean.NO; + if (!name.matches(aMethod.getName())) + return FuzzyBoolean.NO; // Check the throws pattern - if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) return FuzzyBoolean.NO; - - if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) return FuzzyBoolean.MAYBE; + if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) + return FuzzyBoolean.NO; + + if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) + return FuzzyBoolean.MAYBE; if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) { // looking bad, but there might be parameterization to consider... if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) { @@ -395,276 +417,297 @@ public class SignaturePattern extends PatternNode { return FuzzyBoolean.MAYBE; } } - if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) return FuzzyBoolean.NO; + if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) + return FuzzyBoolean.NO; ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes()); ResolvedType[][] parameterAnnotationTypes = aMethod.getParameterAnnotationTypes(); - if (parameterAnnotationTypes==null || parameterAnnotationTypes.length==0) parameterAnnotationTypes=null; - if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) { + if (parameterAnnotationTypes == null || parameterAnnotationTypes.length == 0) + parameterAnnotationTypes = null; + if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC, parameterAnnotationTypes).alwaysTrue()) { // It could still be a match based on the generic sig parameter types of a parameterized type - if (!parameterTypes.matches(world.resolve(aMethod.getGenericParameterTypes()),TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) { + if (!parameterTypes.matches(world.resolve(aMethod.getGenericParameterTypes()), TypePattern.STATIC, + parameterAnnotationTypes).alwaysTrue()) { return FuzzyBoolean.MAYBE; // It could STILL be a match based on the erasure of the parameter types?? // to be determined via test cases... } } - + // check that varargs specifications match - if (!matchesVarArgs(aMethod,world)) return FuzzyBoolean.MAYBE; - + if (!matchesVarArgs(aMethod, world)) + return FuzzyBoolean.MAYBE; + // passed all the guards.. return FuzzyBoolean.YES; } - - /** * match on declaring type, parameter types, throws types */ private FuzzyBoolean matchesExactlyConstructor(JoinPointSignature aConstructor, World world) { - if (!declaringType.matchesStatically(aConstructor.getDeclaringType().resolve(world))) return FuzzyBoolean.NO; + if (!declaringType.matchesStatically(aConstructor.getDeclaringType().resolve(world))) + return FuzzyBoolean.NO; - if (!parameterTypes.canMatchSignatureWithNParameters(aConstructor.getParameterTypes().length)) return FuzzyBoolean.NO; + if (!parameterTypes.canMatchSignatureWithNParameters(aConstructor.getParameterTypes().length)) + return FuzzyBoolean.NO; ResolvedType[] resolvedParameters = world.resolve(aConstructor.getParameterTypes()); - + ResolvedType[][] parameterAnnotationTypes = aConstructor.getParameterAnnotationTypes(); - if (parameterAnnotationTypes==null || parameterAnnotationTypes.length==0) parameterAnnotationTypes=null; + if (parameterAnnotationTypes == null || parameterAnnotationTypes.length == 0) + parameterAnnotationTypes = null; - if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) { + if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC, parameterAnnotationTypes).alwaysTrue()) { // It could still be a match based on the generic sig parameter types of a parameterized type - if (!parameterTypes.matches(world.resolve(aConstructor.getGenericParameterTypes()),TypePattern.STATIC).alwaysTrue()) { + if (!parameterTypes.matches(world.resolve(aConstructor.getGenericParameterTypes()), TypePattern.STATIC).alwaysTrue()) { return FuzzyBoolean.MAYBE; // It could STILL be a match based on the erasure of the parameter types?? // to be determined via test cases... } } - + // check that varargs specifications match - if (!matchesVarArgs(aConstructor,world)) return FuzzyBoolean.NO; - + if (!matchesVarArgs(aConstructor, world)) + return FuzzyBoolean.NO; + // Check the throws pattern - if (!throwsPattern.matches(aConstructor.getExceptions(), world)) return FuzzyBoolean.NO; - + if (!throwsPattern.matches(aConstructor.getExceptions(), world)) + return FuzzyBoolean.NO; + // passed all the guards.. - return FuzzyBoolean.YES; + return FuzzyBoolean.YES; } - + /** - * We've matched against this method or constructor so far, but without considering - * varargs (which has been matched as a simple array thus far). Now we do the additional - * checks to see if the parties agree on whether the last parameter is varargs or a - * straight array. + * We've matched against this method or constructor so far, but without considering varargs (which has been matched as a simple + * array thus far). Now we do the additional checks to see if the parties agree on whether the last parameter is varargs or a + * straight array. */ private boolean matchesVarArgs(JoinPointSignature aMethodOrConstructor, World inAWorld) { - if (parameterTypes.size() == 0) return true; - - TypePattern lastPattern = parameterTypes.get(parameterTypes.size()-1); - boolean canMatchVarArgsSignature = lastPattern.isStar() || - lastPattern.isVarArgs() || - (lastPattern == TypePattern.ELLIPSIS); - + if (parameterTypes.size() == 0) + return true; + + TypePattern lastPattern = parameterTypes.get(parameterTypes.size() - 1); + boolean canMatchVarArgsSignature = lastPattern.isStar() || lastPattern.isVarArgs() || (lastPattern == TypePattern.ELLIPSIS); + if (aMethodOrConstructor.isVarargsMethod()) { // we have at least one parameter in the pattern list, and the method has a varargs signature if (!canMatchVarArgsSignature) { // XXX - Ideally the shadow would be included in the msg but we don't know it... - inAWorld.getLint().cantMatchArrayTypeOnVarargs.signal(aMethodOrConstructor.toString(),getSourceLocation()); + inAWorld.getLint().cantMatchArrayTypeOnVarargs.signal(aMethodOrConstructor.toString(), getSourceLocation()); return false; } } else { // the method ends with an array type, check that we don't *require* a varargs - if (lastPattern.isVarArgs()) return false; + if (lastPattern.isVarArgs()) + return false; } return true; } - - private FuzzyBoolean matchesAnnotations(ResolvedMember member,World world) { - if (member == null) { - // world.getLint().unresolvableMember.signal(member.toString(), getSourceLocation()); + + private FuzzyBoolean matchesAnnotations(ResolvedMember member, World world) { + if (member == null) { + // world.getLint().unresolvableMember.signal(member.toString(), getSourceLocation()); return FuzzyBoolean.NO; - } - annotationPattern.resolve(world); - - // optimization before we go digging around for annotations on ITDs - if (annotationPattern instanceof AnyAnnotationTypePattern) return FuzzyBoolean.YES; - - // fake members represent ITD'd fields - for their annotations we should go and look up the - // relevant member in the original aspect - if (member.isAnnotatedElsewhere() && member.getKind()==Member.FIELD) { - // FIXME asc duplicate of code in AnnotationPointcut.matchInternal()? same fixmes apply here. -// ResolvedMember [] mems = member.getDeclaringType().resolve(world).getDeclaredFields(); // FIXME asc should include supers with getInterTypeMungersIncludingSupers? - List mungers = member.getDeclaringType().resolve(world).getInterTypeMungers(); - for (Iterator iter = mungers.iterator(); iter.hasNext();) { - ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) iter.next(); - if (typeMunger.getMunger() instanceof NewFieldTypeMunger) { - ResolvedMember fakerm = typeMunger.getSignature(); - ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm,typeMunger.getAspectType()); - ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod); - if (fakerm.equals(member)) { - member = rmm; - } + } + annotationPattern.resolve(world); + + // optimization before we go digging around for annotations on ITDs + if (annotationPattern instanceof AnyAnnotationTypePattern) { + return FuzzyBoolean.YES; + } + + // fake members represent ITD'd fields - for their annotations we should go and look up the + // relevant member in the original aspect + if (member.isAnnotatedElsewhere() && member.getKind() == Member.FIELD) { + // FIXME asc duplicate of code in AnnotationPointcut.matchInternal()? same fixmes apply here. + // ResolvedMember [] mems = member.getDeclaringType().resolve(world).getDeclaredFields(); // FIXME asc should include + // supers with getInterTypeMungersIncludingSupers? + List mungers = member.getDeclaringType().resolve(world).getInterTypeMungers(); + for (Iterator iter = mungers.iterator(); iter.hasNext();) { + ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) iter.next(); + if (typeMunger.getMunger() instanceof NewFieldTypeMunger) { + ResolvedMember fakerm = typeMunger.getSignature(); + ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm, typeMunger.getAspectType()); + ResolvedMember rmm = findMethod(typeMunger.getAspectType(), ajcMethod); + if (fakerm.equals(member)) { + member = rmm; + } + } } } - } - - if (annotationPattern.matches(member).alwaysTrue()) { - return FuzzyBoolean.YES; - } else { - return FuzzyBoolean.NO; // do NOT look at ancestor members... - } + + if (annotationPattern.matches(member).alwaysTrue()) { + return FuzzyBoolean.YES; + } else { + // do NOT look at ancestor members... only the subject can have an annotation match + // see http://www.eclipse.org/aspectj/doc/next/adk15notebook/join-point-modifiers.html + return FuzzyBoolean.NO; + } } - + private ResolvedMember findMethod(ResolvedType aspectType, ResolvedMember ajcMethod) { - ResolvedMember decMethods[] = aspectType.getDeclaredMethods(); - for (int i = 0; i < decMethods.length; i++) { + ResolvedMember decMethods[] = aspectType.getDeclaredMethods(); + for (int i = 0; i < decMethods.length; i++) { ResolvedMember member = decMethods[i]; - if (member.equals(ajcMethod)) return member; - } - return null; + if (member.equals(ajcMethod)) + return member; + } + return null; } - - public boolean declaringTypeMatchAllowingForCovariance(Member member, UnresolvedType shadowDeclaringType, World world,TypePattern returnTypePattern,ResolvedType sigReturn) { - + + public boolean declaringTypeMatchAllowingForCovariance(Member member, UnresolvedType shadowDeclaringType, World world, + TypePattern returnTypePattern, ResolvedType sigReturn) { + ResolvedType onType = shadowDeclaringType.resolve(world); - + // fastmatch - if (declaringType.matchesStatically(onType) && returnTypePattern.matchesStatically(sigReturn)) + if (declaringType.matchesStatically(onType) && returnTypePattern.matchesStatically(sigReturn)) return true; - + Collection declaringTypes = member.getDeclaringTypes(world); - + boolean checkReturnType = true; - // XXX Possible enhancement? Doesn't seem to speed things up - // if (returnTypePattern.isStar()) { - // if (returnTypePattern instanceof WildTypePattern) { - // if (((WildTypePattern)returnTypePattern).getDimensions()==0) checkReturnType = false; - // } - // } - + // XXX Possible enhancement? Doesn't seem to speed things up + // if (returnTypePattern.isStar()) { + // if (returnTypePattern instanceof WildTypePattern) { + // if (((WildTypePattern)returnTypePattern).getDimensions()==0) checkReturnType = false; + // } + // } + // Sometimes that list includes types that don't explicitly declare the member we are after - // they are on the list because their supertype is on the list, that's why we use // lookupMethod rather than lookupMemberNoSupers() - for (Iterator i = declaringTypes.iterator(); i.hasNext(); ) { - ResolvedType type = (ResolvedType)i.next(); + for (Iterator i = declaringTypes.iterator(); i.hasNext();) { + ResolvedType type = (ResolvedType) i.next(); if (declaringType.matchesStatically(type)) { - if (!checkReturnType) return true; - ResolvedMember rm = type.lookupMethod(member); - if (rm==null) rm = type.lookupMethodInITDs(member); // It must be in here, or we have *real* problems - if (rm==null) continue; // might be currently looking at the generic type and we need to continue searching in case we hit a parameterized version of this same type... - UnresolvedType returnTypeX = rm.getReturnType(); - ResolvedType returnType = returnTypeX.resolve(world); - if (returnTypePattern.matchesStatically(returnType)) return true; + if (!checkReturnType) + return true; + ResolvedMember rm = type.lookupMethod(member); + if (rm == null) + rm = type.lookupMethodInITDs(member); // It must be in here, or we have *real* problems + if (rm == null) + continue; // might be currently looking at the generic type and we need to continue searching in case we hit a + // parameterized version of this same type... + UnresolvedType returnTypeX = rm.getReturnType(); + ResolvedType returnType = returnTypeX.resolve(world); + if (returnTypePattern.matchesStatically(returnType)) + return true; } } return false; } - -// private Collection getDeclaringTypes(Signature sig) { -// List l = new ArrayList(); -// Class onType = sig.getDeclaringType(); -// String memberName = sig.getName(); -// if (sig instanceof FieldSignature) { -// Class fieldType = ((FieldSignature)sig).getFieldType(); -// Class superType = onType; -// while(superType != null) { -// try { -// Field f = (superType.getDeclaredField(memberName)); -// if (f.getType() == fieldType) { -// l.add(superType); -// } -// } catch (NoSuchFieldException nsf) {} -// superType = superType.getSuperclass(); -// } -// } else if (sig instanceof MethodSignature) { -// Class[] paramTypes = ((MethodSignature)sig).getParameterTypes(); -// Class superType = onType; -// while(superType != null) { -// try { -// superType.getDeclaredMethod(memberName,paramTypes); -// l.add(superType); -// } catch (NoSuchMethodException nsm) {} -// superType = superType.getSuperclass(); -// } -// } -// return l; -// } - - public NamePattern getName() { return name; } - public TypePattern getDeclaringType() { return declaringType; } - - public MemberKind getKind() { - return kind; - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - - if (annotationPattern != AnnotationTypePattern.ANY) { + + // private Collection getDeclaringTypes(Signature sig) { + // List l = new ArrayList(); + // Class onType = sig.getDeclaringType(); + // String memberName = sig.getName(); + // if (sig instanceof FieldSignature) { + // Class fieldType = ((FieldSignature)sig).getFieldType(); + // Class superType = onType; + // while(superType != null) { + // try { + // Field f = (superType.getDeclaredField(memberName)); + // if (f.getType() == fieldType) { + // l.add(superType); + // } + // } catch (NoSuchFieldException nsf) {} + // superType = superType.getSuperclass(); + // } + // } else if (sig instanceof MethodSignature) { + // Class[] paramTypes = ((MethodSignature)sig).getParameterTypes(); + // Class superType = onType; + // while(superType != null) { + // try { + // superType.getDeclaredMethod(memberName,paramTypes); + // l.add(superType); + // } catch (NoSuchMethodException nsm) {} + // superType = superType.getSuperclass(); + // } + // } + // return l; + // } + + public NamePattern getName() { + return name; + } + + public TypePattern getDeclaringType() { + return declaringType; + } + + public MemberKind getKind() { + return kind; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + + if (annotationPattern != AnnotationTypePattern.ANY) { buf.append(annotationPattern.toString()); buf.append(' '); - } - - if (modifiers != ModifiersPattern.ANY) { - buf.append(modifiers.toString()); - buf.append(' '); - } - - if (kind == Member.STATIC_INITIALIZATION) { - buf.append(declaringType.toString()); - buf.append(".<clinit>()");//FIXME AV - bad, cannot be parsed again - } else if (kind == Member.HANDLER) { - buf.append("handler("); - buf.append(parameterTypes.get(0)); - buf.append(")"); - } else { - if (!(kind == Member.CONSTRUCTOR)) { - buf.append(returnType.toString()); - buf.append(' '); - } - if (declaringType != TypePattern.ANY) { - buf.append(declaringType.toString()); - buf.append('.'); - } - if (kind == Member.CONSTRUCTOR) { - buf.append("new"); - } else { - buf.append(name.toString()); - } - if (kind == Member.METHOD || kind == Member.CONSTRUCTOR) { - buf.append(parameterTypes.toString()); - } - //FIXME AV - throws is not printed here, weird - } - return buf.toString(); - } - - public boolean equals(Object other) { - if (!(other instanceof SignaturePattern)) return false; - SignaturePattern o = (SignaturePattern)other; - return o.kind.equals(this.kind) - && o.modifiers.equals(this.modifiers) - && o.returnType.equals(this.returnType) - && o.declaringType.equals(this.declaringType) - && o.name.equals(this.name) - && o.parameterTypes.equals(this.parameterTypes) - && o.throwsPattern.equals(this.throwsPattern) - && o.annotationPattern.equals(this.annotationPattern); - } - public int hashCode() { - if (hashcode==-1) { - hashcode = 17; - hashcode = 37*hashcode + kind.hashCode(); - hashcode = 37*hashcode + modifiers.hashCode(); - hashcode = 37*hashcode + returnType.hashCode(); - hashcode = 37*hashcode + declaringType.hashCode(); - hashcode = 37*hashcode + name.hashCode(); - hashcode = 37*hashcode + parameterTypes.hashCode(); - hashcode = 37*hashcode + throwsPattern.hashCode(); - hashcode = 37*hashcode + annotationPattern.hashCode(); - } - return hashcode; - } - + } + + if (modifiers != ModifiersPattern.ANY) { + buf.append(modifiers.toString()); + buf.append(' '); + } + + if (kind == Member.STATIC_INITIALIZATION) { + buf.append(declaringType.toString()); + buf.append(".<clinit>()");// FIXME AV - bad, cannot be parsed again + } else if (kind == Member.HANDLER) { + buf.append("handler("); + buf.append(parameterTypes.get(0)); + buf.append(")"); + } else { + if (!(kind == Member.CONSTRUCTOR)) { + buf.append(returnType.toString()); + buf.append(' '); + } + if (declaringType != TypePattern.ANY) { + buf.append(declaringType.toString()); + buf.append('.'); + } + if (kind == Member.CONSTRUCTOR) { + buf.append("new"); + } else { + buf.append(name.toString()); + } + if (kind == Member.METHOD || kind == Member.CONSTRUCTOR) { + buf.append(parameterTypes.toString()); + } + // FIXME AV - throws is not printed here, weird + } + return buf.toString(); + } + + public boolean equals(Object other) { + if (!(other instanceof SignaturePattern)) + return false; + SignaturePattern o = (SignaturePattern) other; + return o.kind.equals(this.kind) && o.modifiers.equals(this.modifiers) && o.returnType.equals(this.returnType) + && o.declaringType.equals(this.declaringType) && o.name.equals(this.name) + && o.parameterTypes.equals(this.parameterTypes) && o.throwsPattern.equals(this.throwsPattern) + && o.annotationPattern.equals(this.annotationPattern); + } + + public int hashCode() { + if (hashcode == -1) { + hashcode = 17; + hashcode = 37 * hashcode + kind.hashCode(); + hashcode = 37 * hashcode + modifiers.hashCode(); + hashcode = 37 * hashcode + returnType.hashCode(); + hashcode = 37 * hashcode + declaringType.hashCode(); + hashcode = 37 * hashcode + name.hashCode(); + hashcode = 37 * hashcode + parameterTypes.hashCode(); + hashcode = 37 * hashcode + throwsPattern.hashCode(); + hashcode = 37 * hashcode + annotationPattern.hashCode(); + } + return hashcode; + } + public void write(DataOutputStream s) throws IOException { kind.write(s); modifiers.write(s); @@ -685,15 +728,15 @@ public class SignaturePattern extends PatternNode { NamePattern name = NamePattern.read(s); TypePatternList parameterTypes = TypePatternList.read(s, context); ThrowsPattern throwsPattern = ThrowsPattern.read(s, context); - + AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY; - - if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) { - annotationPattern = AnnotationTypePattern.read(s,context); + + if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) { + annotationPattern = AnnotationTypePattern.read(s, context); } - SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, - name, parameterTypes, throwsPattern,annotationPattern); + SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, + throwsPattern, annotationPattern); ret.readLocation(context, s); return ret; } @@ -725,30 +768,28 @@ public class SignaturePattern extends PatternNode { public ThrowsPattern getThrowsPattern() { return throwsPattern; } - + /** - * return true if last argument in params is an Object[] but the modifiers say this method - * was declared with varargs (Object...). We shouldn't be matching if this is the case. + * return true if last argument in params is an Object[] but the modifiers say this method was declared with varargs + * (Object...). We shouldn't be matching if this is the case. */ -// private boolean matchedArrayAgainstVarArgs(TypePatternList params,int modifiers) { -// if (params.size()>0 && (modifiers & Constants.ACC_VARARGS)!=0) { -// // we have at least one parameter in the pattern list, and the method has a varargs signature -// TypePattern lastPattern = params.get(params.size()-1); -// if (lastPattern.isArray() && !lastPattern.isVarArgs) return true; -// } -// return false; -// } - + // private boolean matchedArrayAgainstVarArgs(TypePatternList params,int modifiers) { + // if (params.size()>0 && (modifiers & Constants.ACC_VARARGS)!=0) { + // // we have at least one parameter in the pattern list, and the method has a varargs signature + // TypePattern lastPattern = params.get(params.size()-1); + // if (lastPattern.isArray() && !lastPattern.isVarArgs) return true; + // } + // return false; + // } public AnnotationTypePattern getAnnotationPattern() { return annotationPattern; } - public boolean isStarAnnotation() { return annotationPattern == AnnotationTypePattern.ANY; } - public Object accept(PatternNodeVisitor visitor, Object data) { - return visitor.visit(this, data); - } + public Object accept(PatternNodeVisitor visitor, Object data) { + return visitor.visit(this, data); + } } |