Browse Source

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!

tags/V1_5_0M3
acolyer 19 years ago
parent
commit
44425d3eea

+ 4
- 0
weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java View File

@@ -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;
}
}

+ 151
- 0
weaver/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java View File

@@ -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);
}

}

+ 33
- 0
weaver/src/org/aspectj/weaver/patterns/HasMemberTypePatternFinder.java View File

@@ -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; }

}

+ 4
- 0
weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java View File

@@ -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;
}
}

+ 6
- 0
weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java View File

@@ -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);
}

+ 36
- 1
weaver/src/org/aspectj/weaver/patterns/PatternParser.java View File

@@ -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("?"));

+ 2
- 0
weaver/src/org/aspectj/weaver/patterns/TypePattern.java View File

@@ -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);
}

Loading…
Cancel
Save