aboutsummaryrefslogtreecommitdiffstats
path: root/org.aspectj.matcher
diff options
context:
space:
mode:
authoraclement <aclement>2010-03-19 15:42:00 +0000
committeraclement <aclement>2010-03-19 15:42:00 +0000
commite60f463f95845f92f62f02958f25505e4d401e5a (patch)
treef5556863f07545376977f52d8f30e9ca8e60a8f6 /org.aspectj.matcher
parent21d98b094385d277919b71f685bc50c75784d58b (diff)
downloadaspectj-e60f463f95845f92f62f02958f25505e4d401e5a.tar.gz
aspectj-e60f463f95845f92f62f02958f25505e4d401e5a.zip
44365: is() support in type patterns
Diffstat (limited to 'org.aspectj.matcher')
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java4
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java1
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java105
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeCategoryTypePattern.java129
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java13
-rw-r--r--org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java5
6 files changed, 252 insertions, 5 deletions
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java
index 14234438c..6558c3c21 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java
@@ -464,4 +464,8 @@ public abstract class AbstractPatternNodeVisitor implements PatternNodeVisitor {
public Object visit(HasMemberTypePattern node, Object data) {
return node;
}
+
+ public Object visit(TypeCategoryTypePattern node, Object data) {
+ return node;
+ }
}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java
index 3fedd718e..336a33e51 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java
@@ -44,6 +44,7 @@ public interface PatternNodeVisitor {
Object visit(WildTypePattern node, Object data);
Object visit(TypePatternList node, Object data);
Object visit(HasMemberTypePattern node, Object data);
+ Object visit(TypeCategoryTypePattern node, Object data);
// Pointcuts
Object visit(AndPointcut node, Object data);
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java
index 93dfeee51..48d6c9674 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java
@@ -868,6 +868,42 @@ public class PatternParser {
}
}
+ // // Check for a type category
+ // IToken token = tokenSource.peek();
+ // if (token.isIdentifier()) {
+ // String category = token.getString();
+ // TypeCategoryTypePattern typeIsPattern = null;
+ // if (category.equals("isClass")) {
+ // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.CLASS);
+ // } else if (category.equals("isAspect")) {
+ // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ASPECT);
+ // } else if (category.equals("isInterface")) {
+ // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INTERFACE);
+ // } else if (category.equals("isInner")) {
+ // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INNER);
+ // } else if (category.equals("isAnonymous")) {
+ // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANONYMOUS);
+ // } else if (category.equals("isEnum")) {
+ // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ENUM);
+ // } else if (category.equals("isAnnotation")) {
+ // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION);
+ // }
+ // if (typeIsPattern != null) {
+ // tokenSource.next();
+ // typeIsPattern.setLocation(tokenSource.getSourceContext(), token.getStart(), token.getEnd());
+ // return typeIsPattern;
+ // }
+ // }
+ if (maybeEatIdentifier("is")) {
+ int pos = tokenSource.getIndex() - 1;
+ TypePattern typeIsPattern = parseIsTypePattern();
+ if (typeIsPattern != null) {
+ return typeIsPattern;
+ }
+ // rewind as if we never tried to parse it as a typeIs
+ tokenSource.setIndex(pos);
+ }
+
List<NamePattern> names = parseDottedNamePattern();
int dim = 0;
@@ -914,6 +950,75 @@ public class PatternParser {
return ret;
}
+ /**
+ * Attempt to parse a typeIs(<category>) construct. If it cannot be parsed we just return null and that should cause the caller
+ * to reset their position and attempt to consume it in another way. This means we won't have problems here: execution(*
+ * typeIs(..)) because someone has decided to call a method the same as our construct.
+ *
+ * @return a TypeIsTypePattern or null if could not be parsed
+ */
+ public TypePattern parseIsTypePattern() {
+ int startPos = tokenSource.peek(-1).getStart(); // that will be the start of the 'typeIs'
+ if (!maybeEatAdjacent("(")) {
+ return null;
+ }
+ IToken token = tokenSource.next();
+ TypeCategoryTypePattern typeIsPattern = null;
+ if (token.isIdentifier()) {
+ String category = token.getString();
+ if (category.equals("ClassType")) {
+ typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.CLASS);
+ } else if (category.equals("AspectType")) {
+ typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ASPECT);
+ } else if (category.equals("InterfaceType")) {
+ typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INTERFACE);
+ } else if (category.equals("InnerType")) {
+ typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INNER);
+ } else if (category.equals("AnonymousType")) {
+ typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANONYMOUS);
+ } else if (category.equals("EnumType")) {
+ typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ENUM);
+ } else if (category.equals("AnnotationType")) {
+ typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION);
+ }
+ }
+ if (typeIsPattern == null) {
+ throw new ParserException("ClassType/AspectType/InterfaceType/InnerType/EnumType/AnnotationType/AnonymousType", token);
+ }
+ if (!maybeEat(")")) {
+ throw new ParserException(")", tokenSource.peek());
+ }
+ int endPos = tokenSource.peek(-1).getEnd();
+ typeIsPattern.setLocation(tokenSource.getSourceContext(), startPos, endPos);
+ return typeIsPattern;
+ }
+
+ // if (names.size() == 1 && !names.get(0).isAny()) {
+ // if (maybeEatAdjacent("(")) {
+ // if (maybeEat(")")) {
+ // // likely to be one of isClass()/isInterface()/isInner()/isAnonymous()/isAspect()
+ // if (names.size() == 1) {
+ // NamePattern np = names.get(0);
+ // String simpleName = np.maybeGetSimpleName();
+ // if (simpleName != null) {
+
+ // return new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION, np);
+ // } else {
+ // throw new ParserException(
+ // "not a supported type category, supported are isClass/isInterface/isEnum/isAnnotation/isInner/isAnonymous",
+ // tokenSource.peek(-3));
+ // }
+ // }
+ // int stop = 1;
+ // // return new WildTypePattern(names, includeSubtypes, dim + (isVarArgs ? 1 : 0), endPos, isVarArgs,
+ // // typeParameters);
+ // }
+ // } else {
+ // throw new ParserException("category type pattern is missing closing parentheses", tokenSource.peek(-2));
+ // }
+ // }
+ // }
+
public TypePattern parseHasFieldTypePattern() {
int startPos = tokenSource.peek(-1).getStart();
eat("(");
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeCategoryTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeCategoryTypePattern.java
new file mode 100644
index 000000000..06c51dbf2
--- /dev/null
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypeCategoryTypePattern.java
@@ -0,0 +1,129 @@
+/* *******************************************************************
+ * Copyright (c) 2010 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://www.eclipse.org/legal/epl-v10.html
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+
+/**
+ * A TypeCategoryTypePattern matches on the category of a type, one of class/interface/aspect/inner/anonymous/enum/annotation, and
+ * these are specified in the pointcut via isClass() isInterface() isAspect() isInner() isAnonymous() isEnum() isAnnotation().
+ *
+ * @author Andy Clement
+ * @since 1.6.9
+ */
+public class TypeCategoryTypePattern extends TypePattern {
+
+ public static final int CLASS = 1;
+ public static final int INTERFACE = 2;
+ public static final int ASPECT = 3;
+ public static final int INNER = 4;
+ public static final int ANONYMOUS = 5;
+ public static final int ENUM = 6;
+ public static final int ANNOTATION = 7;
+
+ private int category;
+
+ private int VERSION = 1;
+
+ public TypeCategoryTypePattern(int category) {
+ super(false);
+ this.category = category;
+ }
+
+ @Override
+ protected boolean matchesExactly(ResolvedType type) {
+ return isRightCategory(type);
+ }
+
+ @Override
+ protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
+ return isRightCategory(type);
+ }
+
+ @Override
+ public FuzzyBoolean matchesInstanceof(ResolvedType type) {
+ return FuzzyBoolean.fromBoolean(isRightCategory(type));
+ }
+
+ @Override
+ public TypePattern parameterizeWith(Map typeVariableMap, World w) {
+ return this;
+ }
+
+ @Override
+ public Object accept(PatternNodeVisitor visitor, Object data) {
+ return visitor.visit(this, data);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof TypeCategoryTypePattern)) {
+ return false;
+ }
+ TypeCategoryTypePattern o = (TypeCategoryTypePattern) other;
+ return o.category == category;
+ }
+
+ // TODO is sourcelocation part of the identity or just a 'nice to have' - if important it should be in hashcode/equals
+ // TODO but if that is the case it needs addressing for all type patterns
+
+ @Override
+ public int hashCode() {
+ return category * 37;
+ }
+
+ @Override
+ public void write(DataOutputStream s) throws IOException {
+ s.writeByte(TypePattern.TYPE_CATEGORY);
+ s.writeInt(VERSION);
+ s.writeInt(category);
+ writeLocation(s);
+ }
+
+ public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+ int version = s.readInt();
+ int category = s.readInt();
+ TypeCategoryTypePattern tp = new TypeCategoryTypePattern(category);
+ tp.readLocation(context, s);
+ return tp;
+ }
+
+ /**
+ * @return true if the supplied type is of the category specified for this type pattern
+ */
+ private boolean isRightCategory(ResolvedType type) {
+ switch (category) {
+ case CLASS:
+ return type.isClass();
+ case INTERFACE:
+ return type.isInterface();
+ case ASPECT:
+ return type.isAspect();
+ case ANONYMOUS:
+ return type.isAnonymous();
+ case INNER:
+ return type.isNested();
+ case ENUM:
+ return type.isEnum();
+ case ANNOTATION:
+ return type.isAnnotation();
+ }
+ return false;
+ }
+
+}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java
index eb2020234..f77352fcc 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java
@@ -300,6 +300,7 @@ public abstract class TypePattern extends PatternNode {
public static final byte NO_KEY = 9;
public static final byte ANY_WITH_ANNO = 10;
public static final byte HAS_MEMBER = 11;
+ public static final byte TYPE_CATEGORY = 12;
public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
byte key = s.readByte();
@@ -326,6 +327,8 @@ public abstract class TypePattern extends PatternNode {
return AnyWithAnnotationTypePattern.read(s, context);
case HAS_MEMBER:
return HasMemberTypePattern.read(s, context);
+ case TYPE_CATEGORY:
+ return TypeCategoryTypePattern.read(s, context);
}
throw new BCException("unknown TypePattern kind: " + key);
}
@@ -335,15 +338,15 @@ public abstract class TypePattern extends PatternNode {
}
/**
- * For quickly recognizing the pattern '!void'
- */
+ * For quickly recognizing the pattern '!void'
+ */
public boolean isBangVoid() {
return false;
}
- /**
- * for quickly recognizing the pattern 'void'
- */
+ /**
+ * for quickly recognizing the pattern 'void'
+ */
public boolean isVoid() {
return false;
}
diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java
index 621e5f30e..665f4bdda 100644
--- a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java
+++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java
@@ -512,6 +512,11 @@ public class DumpPointcutVisitor implements PatternNodeVisitor {
return null;
}
+ public Object visit(TypeCategoryTypePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
public static void check(String s) {
check(Pointcut.fromString(s), false);
}