| /* ******************************************************************* |
| * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). |
| * 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 |
| * |
| * Contributors: |
| * PARC initial implementation |
| * ******************************************************************/ |
| |
| package org.aspectj.weaver.patterns; |
| |
| import java.io.IOException; |
| import java.util.Map; |
| |
| import org.aspectj.bridge.ISourceLocation; |
| import org.aspectj.bridge.MessageUtil; |
| import org.aspectj.util.FuzzyBoolean; |
| import org.aspectj.weaver.CompressingDataOutputStream; |
| import org.aspectj.weaver.ISourceContext; |
| import org.aspectj.weaver.IntMap; |
| import org.aspectj.weaver.ResolvedType; |
| import org.aspectj.weaver.Shadow; |
| import org.aspectj.weaver.VersionedDataInputStream; |
| import org.aspectj.weaver.WeaverMessages; |
| import org.aspectj.weaver.UnresolvedType; |
| import org.aspectj.weaver.World; |
| import org.aspectj.weaver.ast.Literal; |
| import org.aspectj.weaver.ast.Test; |
| |
| public class WithinPointcut extends Pointcut { |
| private TypePattern typePattern; |
| |
| public WithinPointcut(TypePattern type) { |
| this.typePattern = type; |
| this.pointcutKind = WITHIN; |
| } |
| |
| public TypePattern getTypePattern() { |
| return typePattern; |
| } |
| |
| private FuzzyBoolean isWithinType(ResolvedType type) { |
| while (type != null) { |
| if (typePattern.matchesStatically(type)) { |
| return FuzzyBoolean.YES; |
| } |
| type = type.getDeclaringType(); |
| } |
| return FuzzyBoolean.NO; |
| } |
| |
| public int couldMatchKinds() { |
| return Shadow.ALL_SHADOW_KINDS_BITS; |
| } |
| |
| @Override |
| public Pointcut parameterizeWith(Map<String,UnresolvedType> typeVariableMap, World w) { |
| WithinPointcut ret = new WithinPointcut(this.typePattern.parameterizeWith(typeVariableMap, w)); |
| ret.copyLocationFrom(this); |
| return ret; |
| } |
| |
| public FuzzyBoolean fastMatch(FastMatchInfo info) { |
| if (typePattern.annotationPattern instanceof AnyAnnotationTypePattern) { |
| return isWithinType(info.getType()); |
| } |
| return FuzzyBoolean.MAYBE; |
| // Possible alternative implementation that fast matches even annotation patterns: '@Foo *' |
| // typePattern.resolve(info.world); |
| // return isWithinType(info.getType()); |
| } |
| |
| protected FuzzyBoolean matchInternal(Shadow shadow) { |
| ResolvedType enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(), true); |
| if (enclosingType.isMissing()) { |
| shadow.getIWorld().getLint().cantFindType.signal(new String[] { WeaverMessages.format( |
| WeaverMessages.CANT_FIND_TYPE_WITHINPCD, shadow.getEnclosingType().getName()) }, shadow.getSourceLocation(), |
| new ISourceLocation[] { getSourceLocation() }); |
| } |
| typePattern.resolve(shadow.getIWorld()); |
| return isWithinType(enclosingType); |
| } |
| |
| public void write(CompressingDataOutputStream s) throws IOException { |
| s.writeByte(Pointcut.WITHIN); |
| typePattern.write(s); |
| writeLocation(s); |
| } |
| |
| public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException { |
| TypePattern type = TypePattern.read(s, context); |
| WithinPointcut ret = new WithinPointcut(type); |
| ret.readLocation(context, s); |
| return ret; |
| } |
| |
| public void resolveBindings(IScope scope, Bindings bindings) { |
| typePattern = typePattern.resolveBindings(scope, bindings, false, false); |
| |
| // look for parameterized type patterns which are not supported... |
| HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor(); |
| typePattern.traverse(visitor, null); |
| if (visitor.wellHasItThen/* ? */()) { |
| scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.WITHIN_PCD_DOESNT_SUPPORT_PARAMETERS), |
| getSourceLocation())); |
| } |
| } |
| |
| public void postRead(ResolvedType enclosingType) { |
| typePattern.postRead(enclosingType); |
| } |
| |
| public boolean couldEverMatchSameJoinPointsAs(WithinPointcut other) { |
| return typePattern.couldEverMatchSameTypesAs(other.typePattern); |
| } |
| |
| public boolean equals(Object other) { |
| if (!(other instanceof WithinPointcut)) { |
| return false; |
| } |
| WithinPointcut o = (WithinPointcut) other; |
| return o.typePattern.equals(this.typePattern); |
| } |
| |
| public int hashCode() { |
| return typePattern.hashCode(); |
| } |
| |
| public String toString() { |
| return "within(" + typePattern + ")"; |
| } |
| |
| protected Test findResidueInternal(Shadow shadow, ExposedState state) { |
| return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE; |
| } |
| |
| public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) { |
| Pointcut ret = new WithinPointcut(typePattern); |
| ret.copyLocationFrom(this); |
| return ret; |
| } |
| |
| public Object accept(PatternNodeVisitor visitor, Object data) { |
| return visitor.visit(this, data); |
| } |
| } |