}
}
+ // // 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;
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("(");
--- /dev/null
+/* *******************************************************************
+ * 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;
+ }
+
+}