diff options
author | acolyer <acolyer> | 2005-08-21 19:55:02 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2005-08-21 19:55:02 +0000 |
commit | 44425d3eeaf0c4a29ef3336c6112e56ad5f7bb49 (patch) | |
tree | 649cae77cf3db9ca355db902465be1dcce89ba7c | |
parent | 262edc95da3a65bb4c86024abf531ac0ddf8bd69 (diff) | |
download | aspectj-44425d3eeaf0c4a29ef3336c6112e56ad5f7bb49.tar.gz aspectj-44425d3eeaf0c4a29ef3336c6112e56ad5f7bb49.zip |
support for hasmember / hasfield type patterns. currently disabled via static final boolean flag in PatternParser. If re-enabling, see HasMemberTests class and don't forget to figure out behaviour wrt. itds!
7 files changed, 236 insertions, 1 deletions
diff --git a/weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java b/weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java index 5c93d020a..22eac78bb 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java +++ b/weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java @@ -404,4 +404,8 @@ public abstract class AbstractPatternNodeVisitor implements PatternNodeVisitor { public Object visit(TypeVariablePatternList node, Object data) { return node; } + + public Object visit(HasMemberTypePattern node, Object data) { + return node; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java new file mode 100644 index 000000000..ef1d9274d --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java @@ -0,0 +1,151 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.weaver.patterns; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.lang.reflect.Modifier; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.ConcreteTypeMunger; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.Member; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.VersionedDataInputStream; +import org.aspectj.weaver.World; + +/** + * @author colyer + * Matches types that have a certain method / constructor / field + * Currently only allowed within declare parents and declare @type + */ +public class HasMemberTypePattern extends TypePattern { + + private SignaturePattern signaturePattern; + + public HasMemberTypePattern(SignaturePattern aSignaturePattern) { + super(false,false); + this.signaturePattern = aSignaturePattern; + } + + protected boolean matchesExactly(ResolvedType type) { + if (signaturePattern.getKind() == Member.FIELD) { + return hasField(type); + } else { + return hasMethod(type); + } + } + + private boolean hasField(ResolvedType type) { + // TODO what about ITDs + World world = type.getWorld(); + for (Iterator iter = type.getFields(); iter.hasNext();) { + Member field = (Member) iter.next(); + if (signaturePattern.matches(field, type.getWorld(), false)) { + if (field.getDeclaringType().resolve(world) != type) { + if (Modifier.isPrivate(field.getModifiers())) continue; + } + return true; + } + } + return false; + } + + private boolean hasMethod(ResolvedType type) { + // TODO what about ITDs + World world = type.getWorld(); + for (Iterator iter = type.getMethods(); iter.hasNext();) { + Member method = (Member) iter.next(); + if (signaturePattern.matches(method, type.getWorld(), false)) { + if (method.getDeclaringType().resolve(world) != type) { + if (Modifier.isPrivate(method.getModifiers())) continue; + } + return true; + } + } + // try itds before we give up + List mungers = type.getInterTypeMungersIncludingSupers(); + for (Iterator iter = mungers.iterator(); iter.hasNext();) { + ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next(); + Member member = munger.getSignature(); + if (signaturePattern.matches(member, type.getWorld(), false)) { + if (!Modifier.isPublic(member.getModifiers())) continue; + return true; + } + } + return false; + } + + protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) { + return matchesExactly(type); + } + + public FuzzyBoolean matchesInstanceof(ResolvedType type) { + throw new UnsupportedOperationException("hasmethod/field do not support instanceof matching"); + } + + public FuzzyBoolean matchesInstanceof(Class toMatch) { + return FuzzyBoolean.NO; + } + + protected boolean matchesExactly(Class toMatch) { + return false; + } + + public TypePattern parameterizeWith(Map typeVariableMap) { + HasMemberTypePattern ret = new HasMemberTypePattern(signaturePattern.parameterizeWith(typeVariableMap)); + ret.copyLocationFrom(this); + return ret; + } + + public boolean equals(Object obj) { + if (!(obj instanceof HasMemberTypePattern)) return false; + if (this == obj) return true; + return signaturePattern.equals(((HasMemberTypePattern)obj).signaturePattern); + } + + public int hashCode() { + return signaturePattern.hashCode(); + } + + public String toString() { + StringBuffer buff = new StringBuffer(); + if (signaturePattern.getKind() == Member.FIELD) { + buff.append("hasfield("); + } else { + buff.append("hasmethod("); + } + buff.append(signaturePattern.toString()); + buff.append(")"); + return buff.toString(); + } + + public void write(DataOutputStream s) throws IOException { + s.writeByte(TypePattern.HAS_MEMBER); + signaturePattern.write(s); + writeLocation(s); + } + + public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException { + SignaturePattern sp = SignaturePattern.read(s, context); + HasMemberTypePattern ret = new HasMemberTypePattern(sp); + ret.readLocation(context,s); + return ret; + } + + public Object accept(PatternNodeVisitor visitor, Object data) { + return visitor.visit(this, data); + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/HasMemberTypePatternFinder.java b/weaver/src/org/aspectj/weaver/patterns/HasMemberTypePatternFinder.java new file mode 100644 index 000000000..5fb59503f --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/HasMemberTypePatternFinder.java @@ -0,0 +1,33 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.weaver.patterns; + +/** + * @author colyer + * usage : new HasMemberTypePatternFinder(pattern).hasMemberTypePattern() + */ +public class HasMemberTypePatternFinder extends AbstractPatternNodeVisitor { + + private boolean hasMemberTypePattern = false; + + public HasMemberTypePatternFinder(TypePattern aPattern) { + aPattern.traverse(this, null); + } + + public Object visit(HasMemberTypePattern node, Object data) { + hasMemberTypePattern = true; + return null; + } + + public boolean hasMemberTypePattern() { return hasMemberTypePattern; } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java b/weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java index bd1269ef0..1042ddcc2 100644 --- a/weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java +++ b/weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java @@ -239,4 +239,8 @@ public class IdentityPointcutVisitor implements PatternNodeVisitor { public Object visit(TypeVariablePatternList node, Object data) { return node; } + + public Object visit(HasMemberTypePattern node, Object data) { + return node; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java b/weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java index 4e97357d0..74105dcb0 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java @@ -44,6 +44,7 @@ public interface PatternNodeVisitor { Object visit(OrTypePattern node, Object data); Object visit(WildTypePattern node, Object data); Object visit(TypePatternList node, Object data); + Object visit(HasMemberTypePattern node, Object data); // Pointcuts Object visit(AndPointcut node, Object data); @@ -559,6 +560,11 @@ public interface PatternNodeVisitor { return null; } + public Object visit(HasMemberTypePattern node, Object data) { + append(node); + return null; + } + public static void check(String s) { check(Pointcut.fromString(s), false); } diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java index f0d1057e5..63dcd0095 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java @@ -28,6 +28,10 @@ public class PatternParser { private ITokenSource tokenSource; private ISourceContext sourceContext; + + private static final boolean HASMEMBER_PATTERNS_ENABLED = false; + /** not thread-safe, but this class is not intended to be... */ + private boolean allowHasTypePatterns = false; /** * Constructor for PatternParser. @@ -154,7 +158,10 @@ public class PatternParser { } public DeclareAnnotation parseDeclareAtType() { - return new DeclareAnnotation(DeclareAnnotation.AT_TYPE,parseTypePattern()); + if (HASMEMBER_PATTERNS_ENABLED) allowHasTypePatterns = true; + TypePattern p = parseTypePattern(); + allowHasTypePatterns = false; + return new DeclareAnnotation(DeclareAnnotation.AT_TYPE,p); } public DeclareAnnotation parseDeclareAtMethod(boolean isMethod) { @@ -189,7 +196,9 @@ public class PatternParser { * String[] typeParameters = maybeParseSimpleTypeVariableList(); */ eat(":"); + if (HASMEMBER_PATTERNS_ENABLED) allowHasTypePatterns = true; TypePattern p = parseTypePattern(false); + allowHasTypePatterns = false; IToken t = tokenSource.next(); if (!(t.getString().equals("extends") || t.getString().equals("implements"))) { throw new ParserException("extends or implements", t); @@ -678,6 +687,10 @@ public class PatternParser { public TypePattern parseSingleTypePattern(boolean insideTypeParameters) { if (insideTypeParameters && maybeEat("?")) return parseGenericsWildcardTypePattern(); + if (allowHasTypePatterns) { + if (maybeEatIdentifier("hasmethod")) return parseHasMethodTypePattern(); + if (maybeEatIdentifier("hasfield")) return parseHasFieldTypePattern(); + } List names = parseDottedNamePattern(); @@ -707,6 +720,28 @@ public class PatternParser { return new WildTypePattern(names, includeSubtypes, dim+(isVarArgs?1:0), endPos,isVarArgs,typeParameters); } + public TypePattern parseHasMethodTypePattern() { + int startPos = tokenSource.peek(-1).getStart(); + eat("("); + SignaturePattern sp = parseMethodOrConstructorSignaturePattern(); + eat(")"); + int endPos = tokenSource.peek(-1).getEnd(); + HasMemberTypePattern ret = new HasMemberTypePattern(sp); + ret.setLocation(sourceContext, startPos, endPos); + return ret; + } + + public TypePattern parseHasFieldTypePattern() { + int startPos = tokenSource.peek(-1).getStart(); + eat("("); + SignaturePattern sp = parseFieldSignaturePattern(); + eat(")"); + int endPos = tokenSource.peek(-1).getEnd(); + HasMemberTypePattern ret = new HasMemberTypePattern(sp); + ret.setLocation(sourceContext, startPos, endPos); + return ret; + } + public TypePattern parseGenericsWildcardTypePattern() { List names = new ArrayList(); names.add(new NamePattern("?")); diff --git a/weaver/src/org/aspectj/weaver/patterns/TypePattern.java b/weaver/src/org/aspectj/weaver/patterns/TypePattern.java index fb6f94639..6d77c7ac0 100644 --- a/weaver/src/org/aspectj/weaver/patterns/TypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/TypePattern.java @@ -328,6 +328,7 @@ public abstract class TypePattern extends PatternNode { public static final byte AND = 8; public static final byte NO_KEY = 9; public static final byte ANY_WITH_ANNO = 10; + public static final byte HAS_MEMBER = 11; public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException { byte key = s.readByte(); @@ -342,6 +343,7 @@ public abstract class TypePattern extends PatternNode { case OR: return OrTypePattern.read(s, context); case AND: return AndTypePattern.read(s, context); case ANY_WITH_ANNO: return AnyWithAnnotationTypePattern.read(s,context); + case HAS_MEMBER: return HasMemberTypePattern.read(s,context); } throw new BCException("unknown TypePattern kind: " + key); } |