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

public Object visit(TypeVariablePatternList node, Object data) { public Object visit(TypeVariablePatternList node, Object data) {
return node; return node;
} }
public Object visit(HasMemberTypePattern node, Object data) {
return node;
}
} }

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

/* *******************************************************************
* 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

/* *******************************************************************
* 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

public Object visit(TypeVariablePatternList node, Object data) { public Object visit(TypeVariablePatternList node, Object data) {
return node; return node;
} }
public Object visit(HasMemberTypePattern node, Object data) {
return node;
}
} }

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

Object visit(OrTypePattern node, Object data); Object visit(OrTypePattern node, Object data);
Object visit(WildTypePattern node, Object data); Object visit(WildTypePattern node, Object data);
Object visit(TypePatternList node, Object data); Object visit(TypePatternList node, Object data);
Object visit(HasMemberTypePattern node, Object data);


// Pointcuts // Pointcuts
Object visit(AndPointcut node, Object data); Object visit(AndPointcut node, Object data);
return null; return null;
} }


public Object visit(HasMemberTypePattern node, Object data) {
append(node);
return null;
}

public static void check(String s) { public static void check(String s) {
check(Pointcut.fromString(s), false); check(Pointcut.fromString(s), false);
} }

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

private ITokenSource tokenSource; private ITokenSource tokenSource;
private ISourceContext sourceContext; 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. * Constructor for PatternParser.
} }
public DeclareAnnotation parseDeclareAtType() { 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) { public DeclareAnnotation parseDeclareAtMethod(boolean isMethod) {
* String[] typeParameters = maybeParseSimpleTypeVariableList(); * String[] typeParameters = maybeParseSimpleTypeVariableList();
*/ */
eat(":"); eat(":");
if (HASMEMBER_PATTERNS_ENABLED) allowHasTypePatterns = true;
TypePattern p = parseTypePattern(false); TypePattern p = parseTypePattern(false);
allowHasTypePatterns = false;
IToken t = tokenSource.next(); IToken t = tokenSource.next();
if (!(t.getString().equals("extends") || t.getString().equals("implements"))) { if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
throw new ParserException("extends or implements", t); throw new ParserException("extends or implements", t);
public TypePattern parseSingleTypePattern(boolean insideTypeParameters) { public TypePattern parseSingleTypePattern(boolean insideTypeParameters) {
if (insideTypeParameters && maybeEat("?")) return parseGenericsWildcardTypePattern(); if (insideTypeParameters && maybeEat("?")) return parseGenericsWildcardTypePattern();
if (allowHasTypePatterns) {
if (maybeEatIdentifier("hasmethod")) return parseHasMethodTypePattern();
if (maybeEatIdentifier("hasfield")) return parseHasFieldTypePattern();
}
List names = parseDottedNamePattern(); List names = parseDottedNamePattern();
return new WildTypePattern(names, includeSubtypes, dim+(isVarArgs?1:0), endPos,isVarArgs,typeParameters); 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() { public TypePattern parseGenericsWildcardTypePattern() {
List names = new ArrayList(); List names = new ArrayList();
names.add(new NamePattern("?")); names.add(new NamePattern("?"));

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

public static final byte AND = 8; public static final byte AND = 8;
public static final byte NO_KEY = 9; public static final byte NO_KEY = 9;
public static final byte ANY_WITH_ANNO = 10; 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 { public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
byte key = s.readByte(); byte key = s.readByte();
case OR: return OrTypePattern.read(s, context); case OR: return OrTypePattern.read(s, context);
case AND: return AndTypePattern.read(s, context); case AND: return AndTypePattern.read(s, context);
case ANY_WITH_ANNO: return AnyWithAnnotationTypePattern.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); throw new BCException("unknown TypePattern kind: " + key);
} }

Loading…
Cancel
Save