summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoracolyer <acolyer>2005-08-21 19:55:02 +0000
committeracolyer <acolyer>2005-08-21 19:55:02 +0000
commit44425d3eeaf0c4a29ef3336c6112e56ad5f7bb49 (patch)
tree649cae77cf3db9ca355db902465be1dcce89ba7c
parent262edc95da3a65bb4c86024abf531ac0ddf8bd69 (diff)
downloadaspectj-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!
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java4
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java151
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/HasMemberTypePatternFinder.java33
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java4
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java6
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PatternParser.java37
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/TypePattern.java2
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);
}