From: acolyer Date: Wed, 8 Dec 2004 13:43:57 +0000 (+0000) Subject: @annotation parsing and matching X-Git-Tag: Root_AspectJ5_Development~182 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4c20738fbb3560cccf1bc7e5bc0a21618c9559c7;p=aspectj.git @annotation parsing and matching --- diff --git a/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java new file mode 100644 index 000000000..b6c549c45 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java @@ -0,0 +1,199 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM Corporation. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * ******************************************************************/ + +package org.aspectj.weaver.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.bridge.Message; +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.AnnotatedElement; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.IntMap; +import org.aspectj.weaver.Member; +import org.aspectj.weaver.NameMangler; +import org.aspectj.weaver.ResolvedMember; +import org.aspectj.weaver.ResolvedTypeX; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.ShadowMunger; +import org.aspectj.weaver.TypeX; +import org.aspectj.weaver.ast.Literal; +import org.aspectj.weaver.ast.Test; +import org.aspectj.weaver.ast.Var; + +/** + * @annotation(@Foo) or @annotation(foo) + * + * Matches any join point where the subject of the join point has an + * annotation matching the annotationTypePattern: + * + * Join Point Kind Subject + * ================================ + * method call the target method + * method execution the method + * constructor call the constructor + * constructor execution the constructor + * get the target field + * set the target field + * adviceexecution the advice + * initialization the constructor + * preinitialization the constructor + * staticinitialization the type being initialized + * handler the declared type of the handled exception + */ +public class AnnotationPointcut extends NameBindingPointcut { + + private ExactAnnotationTypePattern annotationTypePattern; + private ShadowMunger munger = null; // only set after concretization + + public AnnotationPointcut(ExactAnnotationTypePattern type) { + super(); + this.annotationTypePattern = type; + this.pointcutKind = Pointcut.ANNOTATION; + } + + public AnnotationPointcut(ExactAnnotationTypePattern type, ShadowMunger munger) { + this(type); + this.munger = munger; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) + */ + public FuzzyBoolean fastMatch(FastMatchInfo info) { + if (info.getKind() == Shadow.StaticInitialization) { + return annotationTypePattern.matches(info.getType()); + } else { + return FuzzyBoolean.MAYBE; + } + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) + */ + public FuzzyBoolean match(Shadow shadow) { + AnnotatedElement toMatchAgainst = null; + Member member = shadow.getSignature(); + ResolvedMember rMember = member.resolve(shadow.getIWorld()); + + if (rMember == null) { + if (member.getName().startsWith(NameMangler.PREFIX)) { + return FuzzyBoolean.NO; + } + shadow.getIWorld().getLint().unresolvableMember.signal(member.toString(), getSourceLocation()); + return FuzzyBoolean.NO; + } + + Shadow.Kind kind = shadow.getKind(); + if (kind == Shadow.StaticInitialization) { + toMatchAgainst = rMember.getType(); + } else if ( (kind == Shadow.ExceptionHandler)) { + toMatchAgainst = TypeX.forName(rMember.getSignature()).resolve(shadow.getIWorld()); + } else { + toMatchAgainst = rMember; + } + + return annotationTypePattern.matches(toMatchAgainst); + } + + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings) + */ + protected void resolveBindings(IScope scope, Bindings bindings) { + annotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern.resolveBindings(scope,bindings,true); + // must be either a Var, or an annotation type pattern + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindingsFromRTTI() + */ + protected void resolveBindingsFromRTTI() { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap) + */ + protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { + ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings); + Pointcut ret = new AnnotationPointcut(newType, bindings.getEnclosingAdvice()); + ret.copyLocationFrom(this); + return ret; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) + */ + public Test findResidue(Shadow shadow, ExposedState state) { + + if (annotationTypePattern instanceof BindingAnnotationTypePattern) { + BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern; + TypeX annotationType = btp.annotationType; + Var var = shadow.getKindedAnnotationVar(annotationType); + if (var == null) return Literal.FALSE; + // Check if we have already bound something to this formal + if (state.get(btp.getFormalIndex())!=null) { + ISourceLocation pcdSloc = getSourceLocation(); + ISourceLocation shadowSloc = shadow.getSourceLocation(); + Message errorMessage = new Message( + "Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+ + "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+ + ". The secondary source location points to the problematic binding.", + shadowSloc,true,new ISourceLocation[]{pcdSloc}); + shadow.getIWorld().getMessageHandler().handleMessage(errorMessage); + state.setErroneousVar(btp.getFormalIndex()); + } + state.set(btp.getFormalIndex(),var); + } + return Literal.TRUE; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + s.writeByte(Pointcut.ANNOTATION); + annotationTypePattern.write(s); + writeLocation(s); + } + + public static Pointcut read(DataInputStream s, ISourceContext context) throws IOException { + AnnotationTypePattern type = AnnotationTypePattern.read(s, context); + AnnotationPointcut ret = new AnnotationPointcut((ExactAnnotationTypePattern)type); + ret.readLocation(context, s); + return ret; + } + + public boolean equals(Object other) { + if (!(other instanceof AnnotationPointcut)) return false; + AnnotationPointcut o = (AnnotationPointcut)other; + return o.annotationTypePattern.equals(this.annotationTypePattern); + } + + public int hashCode() { + int result = 17; + result = 37*result + annotationTypePattern.hashCode(); + return result; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("@annotation("); + buf.append(annotationTypePattern.toString()); + buf.append(")"); + return buf.toString(); + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java deleted file mode 100644 index 6dc0c556d..000000000 --- a/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java +++ /dev/null @@ -1,198 +0,0 @@ -/* ******************************************************************* - * Copyright (c) 2004 IBM Corporation. - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Common Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * ******************************************************************/ - -package org.aspectj.weaver.patterns; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -import org.aspectj.bridge.ISourceLocation; -import org.aspectj.bridge.Message; -import org.aspectj.util.FuzzyBoolean; -import org.aspectj.weaver.ISourceContext; -import org.aspectj.weaver.IntMap; -import org.aspectj.weaver.Member; -import org.aspectj.weaver.NameMangler; -import org.aspectj.weaver.ResolvedMember; -import org.aspectj.weaver.ResolvedTypeX; -import org.aspectj.weaver.Shadow; -import org.aspectj.weaver.ShadowMunger; -import org.aspectj.weaver.TypeX; -import org.aspectj.weaver.ast.Literal; -import org.aspectj.weaver.ast.Test; -import org.aspectj.weaver.ast.Var; - -/** - * A KindedAnnotationPointcut matches iff the kind of a join point - * matches the kind of the pointcut (with no distinction between - * method and constructor for call and execution), AND if the - * member (field, method or constructor) has an annotation of the - * given type. - */ -public class KindedAnnotationPointcut extends NameBindingPointcut { - - private Shadow.Kind kind; - private AnnotationTypePattern type; - private ShadowMunger munger = null; // only set after concretization - - public KindedAnnotationPointcut(Shadow.Kind kind, AnnotationTypePattern type) { - super(); - this.kind = kind; - this.type = type; - this.pointcutKind = Pointcut.ATKINDED; - } - - public KindedAnnotationPointcut(Shadow.Kind kind, AnnotationTypePattern type, ShadowMunger munger) { - this(kind,type); - this.munger = munger; - } - - /* (non-Javadoc) - * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) - */ - public FuzzyBoolean fastMatch(FastMatchInfo info) { - if (info.getKind() != null) { - if (info.getKind() != kind) { - // no distinction between method and constructors - if ((info.getKind() == Shadow.ConstructorExecution) && - kind == Shadow.MethodExecution) { - return FuzzyBoolean.MAYBE; - } - if ((info.getKind() == Shadow.ConstructorCall) && - kind == Shadow.MethodCall) { - return FuzzyBoolean.MAYBE; - } - } else { - return FuzzyBoolean.NO; - } - } - return FuzzyBoolean.MAYBE; - } - - /* (non-Javadoc) - * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) - */ - public FuzzyBoolean match(Shadow shadow) { - if (!couldMatch(shadow)) return FuzzyBoolean.NO; - Member member = shadow.getSignature(); - ResolvedMember rMember = member.resolve(shadow.getIWorld()); - if (rMember == null) { - if (member.getName().startsWith(NameMangler.PREFIX)) { - return FuzzyBoolean.NO; - } - shadow.getIWorld().getLint().unresolvableMember.signal(member.toString(), getSourceLocation()); - return FuzzyBoolean.NO; - } - return type.matches(rMember); - } - - private boolean couldMatch(Shadow shadow) { - Shadow.Kind kindToMatch = shadow.getKind(); - if (kindToMatch == Shadow.ConstructorExecution) kindToMatch = Shadow.MethodExecution; - if (kindToMatch == Shadow.ConstructorCall) kindToMatch = Shadow.MethodCall; - return (kindToMatch == kind); - } - - /* (non-Javadoc) - * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings) - */ - protected void resolveBindings(IScope scope, Bindings bindings) { - type = type.resolveBindings(scope,bindings,true); - // must be either a Var, or an annotation type pattern - } - - /* (non-Javadoc) - * @see org.aspectj.weaver.patterns.Pointcut#resolveBindingsFromRTTI() - */ - protected void resolveBindingsFromRTTI() { - // TODO Auto-generated method stub - - } - - /* (non-Javadoc) - * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap) - */ - protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { - AnnotationTypePattern newType = type.remapAdviceFormals(bindings); - Pointcut ret = new KindedAnnotationPointcut(kind, newType, bindings.getEnclosingAdvice()); - ret.copyLocationFrom(this); - return ret; - } - - /* (non-Javadoc) - * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) - */ - public Test findResidue(Shadow shadow, ExposedState state) { - if (!couldMatch(shadow)) return Literal.FALSE; - - if (type instanceof BindingAnnotationTypePattern) { - BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)type; - TypeX annotationType = btp.annotationType; - Var var = shadow.getKindedAnnotationVar(annotationType); - if (var == null) return Literal.FALSE; - // Check if we have already bound something to this formal - if (state.get(btp.getFormalIndex())!=null) { - ISourceLocation pcdSloc = getSourceLocation(); - ISourceLocation shadowSloc = shadow.getSourceLocation(); - Message errorMessage = new Message( - "Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+ - "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+ - ". The secondary source location points to the problematic binding.", - shadowSloc,true,new ISourceLocation[]{pcdSloc}); - shadow.getIWorld().getMessageHandler().handleMessage(errorMessage); - state.setErroneousVar(btp.getFormalIndex()); - } - state.set(btp.getFormalIndex(),var); - } - return Literal.TRUE; - } - - /* (non-Javadoc) - * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) - */ - public void write(DataOutputStream s) throws IOException { - s.writeByte(Pointcut.ATKINDED); - kind.write(s); - type.write(s); - writeLocation(s); - } - - public static Pointcut read(DataInputStream s, ISourceContext context) throws IOException { - Shadow.Kind kind = Shadow.Kind.read(s); - AnnotationTypePattern type = AnnotationTypePattern.read(s, context); - KindedAnnotationPointcut ret = new KindedAnnotationPointcut(kind, type); - ret.readLocation(context, s); - return ret; - } - - public boolean equals(Object other) { - if (!(other instanceof KindedAnnotationPointcut)) return false; - KindedAnnotationPointcut o = (KindedAnnotationPointcut)other; - return o.kind == this.kind && o.type.equals(this.type); - } - - public int hashCode() { - int result = 17; - result = 37*result + kind.hashCode(); - result = 37*result + type.hashCode(); - return result; - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append(kind.getSimpleName()); - buf.append("("); - buf.append(type.toString()); - buf.append(")"); - return buf.toString(); - } - -} diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java index 0cb850d3e..fd1ab22e3 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java @@ -270,13 +270,8 @@ public class PatternParser { IToken t = tokenSource.peek(); String kind = parseIdentifier(); tokenSource.setIndex(start); - if (kind.equals("execution") || kind.equals("call") || - kind.equals("get") || kind.equals("set") || - kind.equals("adviceexecution") || - kind.equals("initialization") || - kind.equals("preinitialization") || - kind.equals("staticinitialization")) { - return parseKindedAnnotationPointcut(); + if (kind.equals("annotation")) { + return parseAtAnnotationPointcut(); } else if (kind.equals("args")) { return parseArgsAnnotationPointcut(); } else if (kind.equals("this") || kind.equals("target")) { @@ -288,35 +283,15 @@ public class PatternParser { } throw new ParserException("@pointcut name expected, but found " + kind, t); } - private Pointcut parseKindedAnnotationPointcut() { - String kind = parseIdentifier(); - Shadow.Kind shadowKind = null; - if (kind.equals("execution")) { - shadowKind = Shadow.MethodExecution; // also matches cons execution - } else if (kind.equals("call")) { - shadowKind = Shadow.MethodCall; // also matches cons call - } else if (kind.equals("get")) { - shadowKind = Shadow.FieldGet; - } else if (kind.equals("set")) { - shadowKind = Shadow.FieldSet; - } else if (kind.equals("adviceexecution")) { - shadowKind = Shadow.AdviceExecution; - } else if (kind.equals("initialization")) { - shadowKind = Shadow.Initialization; - } else if (kind.equals("preinitialization")) { - shadowKind = Shadow.PreInitialization; - } else if (kind.equals("staticinitialization")) { - shadowKind = Shadow.StaticInitialization; - } else { - throw new ParserException(("bad kind: " + kind), tokenSource.peek()); - } + private Pointcut parseAtAnnotationPointcut() { + parseIdentifier(); eat("("); if (maybeEat(")")) { - throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek()); + throw new ParserException("@AnnotationName or parameter", tokenSource.peek()); } - AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); + ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); eat(")"); - return new KindedAnnotationPointcut(shadowKind,type); + return new AnnotationPointcut(type); } @@ -648,8 +623,8 @@ public class PatternParser { // } - protected AnnotationTypePattern parseAnnotationNameOrVarTypePattern() { - AnnotationTypePattern p = null; + protected ExactAnnotationTypePattern parseAnnotationNameOrVarTypePattern() { + ExactAnnotationTypePattern p = null; int startPos = tokenSource.peek().getStart(); if (maybeEat("@")) { p = parseSimpleAnnotationName(); @@ -666,9 +641,9 @@ public class PatternParser { /** * @return */ - private AnnotationTypePattern parseSimpleAnnotationName() { + private ExactAnnotationTypePattern parseSimpleAnnotationName() { // the @ has already been eaten... - AnnotationTypePattern p; + ExactAnnotationTypePattern p; StringBuffer annotationName = new StringBuffer(); annotationName.append(parseIdentifier()); while (maybeEat(".")) { diff --git a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java index 2babd0c33..e85db612f 100644 --- a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java @@ -124,7 +124,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression public static final byte HANDLER = 13; public static final byte IF_TRUE = 14; public static final byte IF_FALSE = 15; - public static final byte ATKINDED = 16; + public static final byte ANNOTATION = 16; public static final byte NONE = 20; @@ -242,7 +242,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression case HANDLER: ret = HandlerPointcut.read(s, context); break; case IF_TRUE: ret = IfPointcut.makeIfTruePointcut(RESOLVED); break; case IF_FALSE: ret = IfPointcut.makeIfFalsePointcut(RESOLVED); break; - case ATKINDED: ret = KindedAnnotationPointcut.read(s, context); break; + case ANNOTATION: ret = AnnotationPointcut.read(s, context); break; case NONE: ret = makeMatchesNothing(RESOLVED); break; default: throw new BCException("unknown kind: " + kind);