@@ -0,0 +1,158 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.Set; | |||
public abstract class AbstractAnnotationAJ implements AnnotationAJ { | |||
protected final ResolvedType type; | |||
private Set supportedTargets = null; // @target meta annotation | |||
public AbstractAnnotationAJ(ResolvedType type) { | |||
this.type = type; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final ResolvedType getType() { | |||
return type; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final String getTypeSignature() { | |||
return type.getSignature(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final String getTypeName() { | |||
return type.getName(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final boolean allowedOnAnnotationType() { | |||
ensureAtTargetInitialized(); | |||
if (supportedTargets.isEmpty()) { | |||
return true; | |||
} | |||
return supportedTargets.contains("ANNOTATION_TYPE"); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final boolean allowedOnField() { | |||
ensureAtTargetInitialized(); | |||
if (supportedTargets.isEmpty()) { | |||
return true; | |||
} | |||
return supportedTargets.contains("FIELD"); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final boolean allowedOnRegularType() { | |||
ensureAtTargetInitialized(); | |||
if (supportedTargets.isEmpty()) { | |||
return true; | |||
} | |||
return supportedTargets.contains("TYPE"); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final void ensureAtTargetInitialized() { | |||
if (supportedTargets == null) { | |||
AnnotationAJ atTargetAnnotation = retrieveAnnotationOnAnnotation(UnresolvedType.AT_TARGET); | |||
if (atTargetAnnotation == null) { | |||
supportedTargets = Collections.EMPTY_SET; | |||
} else { | |||
supportedTargets = atTargetAnnotation.getTargets(); | |||
} | |||
} | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final String getValidTargets() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("{"); | |||
for (Iterator iter = supportedTargets.iterator(); iter.hasNext();) { | |||
String evalue = (String) iter.next(); | |||
sb.append(evalue); | |||
if (iter.hasNext()) { | |||
sb.append(","); | |||
} | |||
} | |||
sb.append("}"); | |||
return sb.toString(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public final boolean specifiesTarget() { | |||
ensureAtTargetInitialized(); | |||
return !supportedTargets.isEmpty(); | |||
} | |||
/** | |||
* Helper method to retrieve an annotation on an annotation e.g. retrieveAnnotationOnAnnotation(UnresolvedType.AT_TARGET) | |||
*/ | |||
private final AnnotationAJ retrieveAnnotationOnAnnotation(UnresolvedType requiredAnnotationSignature) { | |||
AnnotationAJ[] annos = type.getAnnotations(); | |||
for (int i = 0; i < annos.length; i++) { | |||
AnnotationAJ a = annos[i]; | |||
if (a.getTypeSignature().equals(requiredAnnotationSignature.getSignature())) { | |||
return annos[i]; | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract boolean isRuntimeVisible(); | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract Set getTargets(); | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract boolean hasNameValuePair(String name, String value); | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract boolean hasNamedValue(String name); | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public abstract String stringify(); | |||
} |
@@ -14,8 +14,8 @@ package org.aspectj.weaver; | |||
*/ | |||
public interface AnnotatedElement { | |||
boolean hasAnnotation(UnresolvedType ofType); | |||
ResolvedType[] getAnnotationTypes(); | |||
AnnotationX getAnnotationOfType(UnresolvedType ofType); | |||
AnnotationAJ getAnnotationOfType(UnresolvedType ofType); | |||
} |
@@ -1,121 +1,93 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 Contributors | |||
* Copyright (c) 2006-2008 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 | |||
* | |||
* Contributors: | |||
* Andy Clement IBM initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
/** | |||
* This type represents the weavers abstraction of an annotation - it is | |||
* not tied to any underlying BCI toolkit. The weaver actualy handles these | |||
* through AnnotationX wrapper objects - until we start transforming the | |||
* BCEL annotations into this form (expensive) or offer a clever | |||
* visitor mechanism over the BCEL annotation stuff that builds these | |||
* annotation types directly. | |||
* | |||
* Simple representation of an annotation that the weaver can work with. | |||
* | |||
* @author AndyClement | |||
*/ | |||
public class AnnotationAJ { | |||
private String type; | |||
private boolean isRuntimeVisible; | |||
private List /*of AnnotationNVPair*/ nvPairs = null; | |||
public AnnotationAJ(String type,boolean isRuntimeVisible) { | |||
this.type = type; | |||
this.isRuntimeVisible = isRuntimeVisible; | |||
} | |||
public String getTypeSignature() { | |||
return type; | |||
} | |||
public List getNameValuePairs() { | |||
return nvPairs; | |||
} | |||
public boolean hasNameValuePairs() { | |||
return nvPairs!=null && nvPairs.size()!=0; | |||
} | |||
public boolean isRuntimeVisible() { | |||
return isRuntimeVisible; | |||
} | |||
public String stringify() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("@").append(UnresolvedType.forSignature(type).getClassName()); | |||
if (hasNameValuePairs()) { | |||
sb.append("("); | |||
for (Iterator iter = nvPairs.iterator(); iter.hasNext();) { | |||
AnnotationNameValuePair element = (AnnotationNameValuePair) iter.next(); | |||
sb.append(element.stringify()); | |||
} | |||
sb.append(")"); | |||
} | |||
return sb.toString(); | |||
} | |||
public String getStringValueOf(Object name) { | |||
if (!hasNameValuePairs()) return null; | |||
for (Iterator iter = nvPairs.iterator(); iter.hasNext();) { | |||
AnnotationNameValuePair nvpair = (AnnotationNameValuePair) iter.next(); | |||
if (nvpair.getName().equals(name)) return nvpair.getValue().stringify(); | |||
} | |||
return null; | |||
} | |||
public void addNameValuePair(AnnotationNameValuePair pair) { | |||
if (nvPairs==null) nvPairs=new ArrayList(); | |||
nvPairs.add(pair); | |||
} | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("ANNOTATION ["+getTypeSignature()+"] ["+ | |||
(isRuntimeVisible?"runtimeVisible":"runtimeInvisible")+"] ["); | |||
if (nvPairs!=null) { | |||
for (Iterator iter = nvPairs.iterator(); iter.hasNext();) { | |||
AnnotationNameValuePair element = (AnnotationNameValuePair) iter.next(); | |||
sb.append(element.toString()); | |||
if (iter.hasNext()) sb.append(","); | |||
} | |||
} | |||
sb.append("]"); | |||
return sb.toString(); | |||
} | |||
public boolean hasNamedValue(String n) { | |||
if (nvPairs==null) return false; | |||
for (int i=0;i<nvPairs.size();i++) { | |||
AnnotationNameValuePair pair = (AnnotationNameValuePair)nvPairs.get(i); | |||
if (pair.getName().equals(n)) return true; | |||
} | |||
return false; | |||
} | |||
public interface AnnotationAJ { | |||
public static final AnnotationAJ[] EMPTY_ARRAY = new AnnotationAJ[0]; | |||
/** | |||
* @return the signature for the annotation type, eg. Lcom/foo/MyAnno; | |||
*/ | |||
public String getTypeSignature(); | |||
/** | |||
* @return the type name for the annotation, eg. com.foo.MyAnno | |||
*/ | |||
public String getTypeName(); | |||
/** | |||
* @return the type of the annotation | |||
*/ | |||
public ResolvedType getType(); | |||
/** | |||
* return true if this annotation can target an annotation type | |||
*/ | |||
public boolean allowedOnAnnotationType(); | |||
/** | |||
* @return true if this annotation can be put on a field | |||
*/ | |||
public boolean allowedOnField(); | |||
/** | |||
* @return true if this annotation can target a 'regular' type. A 'regular' type is enum/class/interface - it is *not* | |||
* annotation. | |||
*/ | |||
public boolean allowedOnRegularType(); | |||
/** | |||
* Return true if the annotation has a value with the specified name (n) and value (v) | |||
*/ | |||
public boolean hasNameValuePair(String n, String v) { | |||
if (nvPairs==null) return false; | |||
for (int i=0;i<nvPairs.size();i++) { | |||
AnnotationNameValuePair pair = (AnnotationNameValuePair)nvPairs.get(i); | |||
if (pair.getName().equals(n)) { | |||
if (pair.getValue().stringify().equals(v)) return true; | |||
} | |||
} | |||
return false; | |||
} | |||
* @return for the @target annotation, this will return a set of the element-types it can be applied to. For other annotations , | |||
* it returns the empty set. | |||
*/ | |||
public Set getTargets(); | |||
/** | |||
* @param name the name of the value | |||
* @return true if there is a value with that name | |||
*/ | |||
public boolean hasNamedValue(String name); | |||
/** | |||
* @param name the name of the annotation field | |||
* @param value the value of the annotation field | |||
* @return true if there is a value with the specified name and value | |||
*/ | |||
public boolean hasNameValuePair(String name, String value); | |||
/** | |||
* @return String representation of the valid targets for this annotation, eg. "{TYPE,FIELD}" | |||
*/ | |||
public String getValidTargets(); | |||
/** | |||
* @return String form of the annotation and any values, eg. @Foo(a=b,c=d) | |||
*/ | |||
public String stringify(); | |||
/** | |||
* @return true if this annotation is marked with @target | |||
*/ | |||
public boolean specifiesTarget(); | |||
/** | |||
* @return true if the annotation is marked for runtime visibility | |||
*/ | |||
public boolean isRuntimeVisible(); | |||
} |
@@ -10,7 +10,6 @@ | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
@@ -20,10 +19,10 @@ import java.io.IOException; | |||
* Represents adding an annotation to a type | |||
*/ | |||
public class AnnotationOnTypeMunger extends ResolvedTypeMunger { | |||
AnnotationX newAnnotation; | |||
public AnnotationOnTypeMunger(AnnotationX anno) { | |||
super(AnnotationOnType,null); | |||
AnnotationAJ newAnnotation; | |||
public AnnotationOnTypeMunger(AnnotationAJ anno) { | |||
super(AnnotationOnType, null); | |||
newAnnotation = anno; | |||
} | |||
@@ -31,25 +30,28 @@ public class AnnotationOnTypeMunger extends ResolvedTypeMunger { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
public AnnotationX getNewAnnotation() { | |||
public AnnotationAJ getNewAnnotation() { | |||
return newAnnotation; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof AnnotationOnTypeMunger)) return false; | |||
AnnotationOnTypeMunger o = (AnnotationOnTypeMunger)other; | |||
return newAnnotation.getSignature().equals(o.newAnnotation.getSignature()); | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37*result + newAnnotation.getSignature().hashCode(); | |||
hashCode = result; | |||
public boolean equals(Object other) { | |||
if (!(other instanceof AnnotationOnTypeMunger)) | |||
return false; | |||
AnnotationOnTypeMunger o = (AnnotationOnTypeMunger) other; | |||
// TODO does not check equality of annotation values | |||
return newAnnotation.getTypeSignature().equals( | |||
o.newAnnotation.getTypeSignature()); | |||
} | |||
private volatile int hashCode = 0; | |||
public int hashCode() { | |||
if (hashCode == 0) { | |||
int result = 17; | |||
result = 37 * result + newAnnotation.getTypeSignature().hashCode(); | |||
hashCode = result; | |||
} | |||
return hashCode; | |||
} | |||
return hashCode; | |||
} | |||
} |
@@ -1,224 +0,0 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2005 IBM | |||
* 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: | |||
* Andy Clement initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.aspectj.apache.bcel.classfile.Utility; | |||
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValueGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.ElementValueGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.EnumElementValueGen; | |||
/** | |||
* AnnotationX instances are holders for an annotation from either Bcel or eclipse. We have this holder so that types about the bcel | |||
* weaver package can work with something not bytecode toolkit specific. | |||
*/ | |||
public class AnnotationX { | |||
public static final AnnotationX[] NONE = new AnnotationX[0]; | |||
private AnnotationGen theRealBcelAnnotation; | |||
private AnnotationAJ theRealEclipseAnnotation; // OPTIMIZE push out into compiler, not ever used if purely binary weaving ? | |||
private int mode = -1; | |||
private final static int MODE_ECLIPSE = 1; | |||
private final static int MODE_BCEL = 2; | |||
private ResolvedType signature = null; | |||
// @target meta-annotation related stuff, built lazily | |||
private boolean lookedForAtTargetAnnotation = false; | |||
private AnnotationX atTargetAnnotation = null; | |||
private Set supportedTargets = null; | |||
public AnnotationX(AnnotationGen a, World world) { | |||
theRealBcelAnnotation = a; | |||
signature = UnresolvedType.forSignature(theRealBcelAnnotation.getTypeSignature()).resolve(world); | |||
mode = MODE_BCEL; | |||
} | |||
public AnnotationX(AnnotationAJ a, World world) { | |||
theRealEclipseAnnotation = a; | |||
signature = UnresolvedType.forSignature(theRealEclipseAnnotation.getTypeSignature()).resolve(world); | |||
mode = MODE_ECLIPSE; | |||
} | |||
public AnnotationGen getBcelAnnotation() { | |||
return theRealBcelAnnotation; | |||
} | |||
public UnresolvedType getSignature() { | |||
return signature; | |||
} | |||
public String toString() { | |||
if (mode == MODE_BCEL) | |||
return theRealBcelAnnotation.toString(); | |||
else | |||
return theRealEclipseAnnotation.toString(); | |||
} | |||
public String getTypeName() { | |||
if (mode == MODE_BCEL) | |||
return theRealBcelAnnotation.getTypeName(); | |||
else | |||
return Utility.signatureToString(theRealEclipseAnnotation.getTypeSignature()); | |||
} | |||
public String getTypeSignature() { | |||
if (mode == MODE_BCEL) | |||
return theRealBcelAnnotation.getTypeSignature(); | |||
else | |||
return theRealEclipseAnnotation.getTypeSignature(); | |||
} | |||
// @target related helpers | |||
/** | |||
* return true if this annotation can target an annotation type | |||
*/ | |||
public boolean allowedOnAnnotationType() { | |||
ensureAtTargetInitialized(); | |||
if (atTargetAnnotation == null) | |||
return true; // if no target specified, then return true | |||
return supportedTargets.contains("ANNOTATION_TYPE"); | |||
} | |||
/** | |||
* return true if this annotation is marked with @target() | |||
*/ | |||
public boolean specifiesTarget() { | |||
ensureAtTargetInitialized(); | |||
return atTargetAnnotation != null; | |||
} | |||
/** | |||
* return true if this annotation can target a 'regular' type. A 'regular' type is enum/class/interface - it is *not* | |||
* annotation. | |||
*/ | |||
public boolean allowedOnRegularType() { | |||
ensureAtTargetInitialized(); | |||
if (atTargetAnnotation == null) | |||
return true; // if no target specified, then return true | |||
return supportedTargets.contains("TYPE"); | |||
} | |||
/** | |||
* Use in messages about this annotation | |||
*/ | |||
public String stringify() { | |||
return signature.getName(); | |||
} | |||
public String getValidTargets() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("{"); | |||
for (Iterator iter = supportedTargets.iterator(); iter.hasNext();) { | |||
String evalue = (String) iter.next(); | |||
sb.append(evalue); | |||
if (iter.hasNext()) | |||
sb.append(","); | |||
} | |||
sb.append("}"); | |||
return sb.toString(); | |||
} | |||
// privates | |||
/** | |||
* Helper method to retrieve an annotation on an annotation e.g. retrieveAnnotationOnAnnotation(UnresolvedType.AT_TARGET) | |||
*/ | |||
private AnnotationX retrieveAnnotationOnAnnotation(UnresolvedType requiredAnnotationSignature) { | |||
AnnotationX[] annos = signature.getAnnotations(); | |||
for (int i = 0; i < annos.length; i++) { | |||
AnnotationX annotationX = annos[i]; | |||
if (annotationX.getSignature().equals(requiredAnnotationSignature)) | |||
return annos[i]; | |||
} | |||
return null; | |||
} | |||
/** | |||
* Makes sure we have looked for the @target() annotation on this annotation. Calling this method initializes (and caches) the | |||
* information for later use. | |||
*/ | |||
private void ensureAtTargetInitialized() { | |||
if (!lookedForAtTargetAnnotation) { | |||
lookedForAtTargetAnnotation = true; | |||
atTargetAnnotation = retrieveAnnotationOnAnnotation(UnresolvedType.AT_TARGET); | |||
if (atTargetAnnotation != null) { | |||
supportedTargets = atTargetAnnotation.getTargets(); | |||
} | |||
} | |||
} | |||
/** | |||
* For the @Target annotation, this will return a set of the elementtypes it can be applied to. For non @Target annotations, it | |||
* returns null. | |||
*/ | |||
public Set /* of String */getTargets() { | |||
if (!signature.equals(UnresolvedType.AT_TARGET)) | |||
return null; | |||
Set supportedTargets = new HashSet(); | |||
if (mode == MODE_BCEL) { | |||
List values = getBcelAnnotation().getValues(); | |||
ElementNameValuePairGen envp = (ElementNameValuePairGen) values.get(0); | |||
ArrayElementValueGen aev = (ArrayElementValueGen) envp.getValue(); | |||
ElementValueGen[] evs = aev.getElementValuesArray(); | |||
for (int i = 0; i < evs.length; i++) { | |||
EnumElementValueGen ev = (EnumElementValueGen) evs[i]; | |||
supportedTargets.add(ev.getEnumValueString()); | |||
} | |||
} else { | |||
List values = theRealEclipseAnnotation.getNameValuePairs(); | |||
AnnotationNameValuePair nvp = (AnnotationNameValuePair) values.get(0); | |||
ArrayAnnotationValue aav = (ArrayAnnotationValue) nvp.getValue(); | |||
AnnotationValue[] avs = aav.getValues(); | |||
for (int i = 0; i < avs.length; i++) { | |||
AnnotationValue value = avs[i]; | |||
supportedTargets.add(value.stringify()); | |||
} | |||
} | |||
return supportedTargets; | |||
} | |||
/** | |||
* @return true if this annotation can be put on a field | |||
*/ | |||
public boolean allowedOnField() { | |||
ensureAtTargetInitialized(); | |||
if (atTargetAnnotation == null) | |||
return true; // if no target specified, then return true | |||
return supportedTargets.contains("FIELD"); | |||
} | |||
public boolean isRuntimeVisible() { | |||
return theRealBcelAnnotation.isRuntimeVisible(); | |||
} | |||
public boolean hasNameValuePair(String n, String v) { | |||
if (mode == MODE_BCEL) | |||
return theRealBcelAnnotation.hasNameValuePair(n, v); | |||
else | |||
return theRealEclipseAnnotation.hasNameValuePair(n, v); | |||
} | |||
public boolean hasNamedValue(String n) { | |||
if (mode == MODE_BCEL) | |||
return theRealBcelAnnotation.hasNamedValue(n); | |||
else | |||
return theRealEclipseAnnotation.hasNamedValue(n); | |||
} | |||
} |
@@ -18,8 +18,8 @@ import java.util.Map; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
/** | |||
* A BoundedReferenceType is the result of a generics wildcard expression | |||
* ? extends String, ? super Foo etc.. | |||
* A BoundedReferenceType is the result of a generics wildcard expression ? | |||
* extends String, ? super Foo etc.. | |||
* | |||
* The "signature" for a bounded reference type follows the generic signature | |||
* specification in section 4.4 of JVM spec: *,+,- plus signature strings. | |||
@@ -28,110 +28,134 @@ import org.aspectj.weaver.patterns.PerClause; | |||
*/ | |||
public class BoundedReferenceType extends ReferenceType { | |||
private ResolvedType lowerBound; | |||
private ResolvedType lowerBound; | |||
private ResolvedType upperBound; | |||
private ResolvedType upperBound; | |||
protected ReferenceType[] additionalInterfaceBounds = new ReferenceType[0]; | |||
protected ReferenceType[] additionalInterfaceBounds = new ReferenceType[0]; | |||
protected boolean isExtends = true; | |||
protected boolean isExtends = true; | |||
protected boolean isSuper = false; | |||
protected boolean isSuper = false; | |||
public UnresolvedType getUpperBound() { | |||
return upperBound; | |||
} | |||
public UnresolvedType getUpperBound() { | |||
return upperBound; | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return lowerBound; | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return lowerBound; | |||
} | |||
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world) { | |||
super((isExtends ? "+" : "-") + aBound.signature,aBound.signatureErasure,world); | |||
this.isExtends = isExtends; | |||
this.isSuper = !isExtends; | |||
if (isExtends) { | |||
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, | |||
World world) { | |||
super((isExtends ? "+" : "-") + aBound.signature, | |||
aBound.signatureErasure, world); | |||
this.isExtends = isExtends; | |||
this.isSuper = !isExtends; | |||
if (isExtends) { | |||
upperBound = aBound; | |||
} else { | |||
lowerBound = aBound; | |||
upperBound = world.resolve(UnresolvedType.OBJECT); | |||
upperBound = world.resolve(UnresolvedType.OBJECT); | |||
} | |||
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)getUpperBound())); | |||
setDelegate(new ReferenceTypeReferenceTypeDelegate( | |||
(ReferenceType) getUpperBound())); | |||
} | |||
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world, ReferenceType[] additionalInterfaces) { | |||
this(aBound,isExtends,world); | |||
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, | |||
World world, ReferenceType[] additionalInterfaces) { | |||
this(aBound, isExtends, world); | |||
this.additionalInterfaceBounds = additionalInterfaces; | |||
} | |||
public ReferenceType[] getAdditionalBounds() { | |||
return additionalInterfaceBounds; | |||
} | |||
public UnresolvedType parameterize(Map typeBindings) { | |||
ReferenceType[] parameterizedAdditionalInterfaces = new ReferenceType[additionalInterfaceBounds==null?0:additionalInterfaceBounds.length]; | |||
for (int i=0; i<parameterizedAdditionalInterfaces.length;i++) { | |||
parameterizedAdditionalInterfaces[i] = (ReferenceType)additionalInterfaceBounds[i].parameterize(typeBindings); | |||
ReferenceType[] parameterizedAdditionalInterfaces = new ReferenceType[additionalInterfaceBounds == null ? 0 | |||
: additionalInterfaceBounds.length]; | |||
for (int i = 0; i < parameterizedAdditionalInterfaces.length; i++) { | |||
parameterizedAdditionalInterfaces[i] = (ReferenceType) additionalInterfaceBounds[i] | |||
.parameterize(typeBindings); | |||
} | |||
if (isExtends) { | |||
return new BoundedReferenceType((ReferenceType)getUpperBound().parameterize(typeBindings),isExtends,world,parameterizedAdditionalInterfaces); | |||
return new BoundedReferenceType((ReferenceType) getUpperBound() | |||
.parameterize(typeBindings), isExtends, world, | |||
parameterizedAdditionalInterfaces); | |||
} else { | |||
return new BoundedReferenceType((ReferenceType)getLowerBound().parameterize(typeBindings),isExtends,world,parameterizedAdditionalInterfaces); | |||
return new BoundedReferenceType((ReferenceType) getLowerBound() | |||
.parameterize(typeBindings), isExtends, world, | |||
parameterizedAdditionalInterfaces); | |||
} | |||
} | |||
/** | |||
* only for use when resolving GenericsWildcardTypeX or a TypeVariableReferenceType | |||
* only for use when resolving GenericsWildcardTypeX or a | |||
* TypeVariableReferenceType | |||
*/ | |||
protected BoundedReferenceType(String sig, String sigErasure, World world) { | |||
super(sig, sigErasure, world); | |||
upperBound = world.resolve(UnresolvedType.OBJECT); | |||
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)getUpperBound())); | |||
setDelegate(new ReferenceTypeReferenceTypeDelegate( | |||
(ReferenceType) getUpperBound())); | |||
} | |||
public ReferenceType[] getInterfaceBounds() { | |||
return additionalInterfaceBounds; | |||
public ReferenceType[] getInterfaceBounds() { | |||
return additionalInterfaceBounds; | |||
} | |||
public boolean hasLowerBound() { | |||
return getLowerBound() != null; | |||
} | |||
public boolean isExtends() { return (isExtends && !getUpperBound().getSignature().equals("Ljava/lang/Object;")); } | |||
public boolean isSuper() { return isSuper; } | |||
public boolean isExtends() { | |||
return (isExtends && !getUpperBound().getSignature().equals( | |||
"Ljava/lang/Object;")); | |||
} | |||
public boolean isSuper() { | |||
return isSuper; | |||
} | |||
public boolean alwaysMatches(ResolvedType aCandidateType) { | |||
if (isExtends()) { | |||
// aCandidateType must be a subtype of upperBound | |||
return ((ReferenceType)getUpperBound()).isAssignableFrom(aCandidateType); | |||
return ((ReferenceType) getUpperBound()) | |||
.isAssignableFrom(aCandidateType); | |||
} else if (isSuper()) { | |||
// aCandidateType must be a supertype of lowerBound | |||
return aCandidateType.isAssignableFrom((ReferenceType)getLowerBound()); | |||
return aCandidateType | |||
.isAssignableFrom((ReferenceType) getLowerBound()); | |||
} else { | |||
return true; // straight '?' | |||
} | |||
} | |||
// this "maybe matches" that | |||
public boolean canBeCoercedTo(ResolvedType aCandidateType) { | |||
if (alwaysMatches(aCandidateType)) return true; | |||
if (alwaysMatches(aCandidateType)) | |||
return true; | |||
if (aCandidateType.isGenericWildcard()) { | |||
BoundedReferenceType boundedRT = (BoundedReferenceType) aCandidateType; | |||
BoundedReferenceType boundedRT = (BoundedReferenceType) aCandidateType; | |||
ResolvedType myUpperBound = (ResolvedType) getUpperBound(); | |||
ResolvedType myLowerBound = (ResolvedType) getLowerBound(); | |||
if (isExtends()) { | |||
if (boundedRT.isExtends()) { | |||
return myUpperBound.isAssignableFrom((ResolvedType) boundedRT.getUpperBound()); | |||
} else if (boundedRT.isSuper()) { | |||
return myUpperBound == boundedRT.getLowerBound(); | |||
return myUpperBound | |||
.isAssignableFrom((ResolvedType) boundedRT | |||
.getUpperBound()); | |||
} else if (boundedRT.isSuper()) { | |||
return myUpperBound == boundedRT.getLowerBound(); | |||
} else { | |||
return true; // it's '?' | |||
return true; // it's '?' | |||
} | |||
} else if (isSuper()) { | |||
if (boundedRT.isSuper()) { | |||
return ((ResolvedType) boundedRT.getLowerBound()).isAssignableFrom(myLowerBound); | |||
} else if (boundedRT.isExtends()) { | |||
return myLowerBound == boundedRT.getUpperBound(); | |||
return ((ResolvedType) boundedRT.getLowerBound()) | |||
.isAssignableFrom(myLowerBound); | |||
} else if (boundedRT.isExtends()) { | |||
return myLowerBound == boundedRT.getUpperBound(); | |||
} else { | |||
return true; | |||
} | |||
@@ -142,42 +166,48 @@ public class BoundedReferenceType extends ReferenceType { | |||
return false; | |||
} | |||
} | |||
public String getSimpleName() { | |||
if (!isExtends() && !isSuper()) return "?"; | |||
if (!isExtends() && !isSuper()) | |||
return "?"; | |||
if (isExtends()) { | |||
return ("? extends " + getUpperBound().getSimpleName()); | |||
} else { | |||
return ("? super " + getLowerBound().getSimpleName()); | |||
} | |||
} | |||
// override to include additional interface bounds... | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
ResolvedType[] interfaces = super.getDeclaredInterfaces(); | |||
if (additionalInterfaceBounds.length > 0) { | |||
ResolvedType[] allInterfaces = | |||
new ResolvedType[interfaces.length + additionalInterfaceBounds.length]; | |||
System.arraycopy(interfaces, 0, allInterfaces, 0, interfaces.length); | |||
System.arraycopy(additionalInterfaceBounds,0,allInterfaces,interfaces.length,additionalInterfaceBounds.length); | |||
ResolvedType[] allInterfaces = new ResolvedType[interfaces.length | |||
+ additionalInterfaceBounds.length]; | |||
System | |||
.arraycopy(interfaces, 0, allInterfaces, 0, | |||
interfaces.length); | |||
System.arraycopy(additionalInterfaceBounds, 0, allInterfaces, | |||
interfaces.length, additionalInterfaceBounds.length); | |||
return allInterfaces; | |||
} else { | |||
return interfaces; | |||
} | |||
} | |||
public boolean isGenericWildcard() { | |||
return true; | |||
} | |||
protected static class ReferenceTypeReferenceTypeDelegate extends AbstractReferenceTypeDelegate { | |||
protected static class ReferenceTypeReferenceTypeDelegate extends | |||
AbstractReferenceTypeDelegate { | |||
public ReferenceTypeReferenceTypeDelegate(ReferenceType backing) { | |||
super(backing,false); | |||
super(backing, false); | |||
} | |||
public void addAnnotation(AnnotationX annotationX) { | |||
throw new UnsupportedOperationException("What on earth do you think you are doing???"); | |||
public void addAnnotation(AnnotationAJ annotationX) { | |||
throw new UnsupportedOperationException( | |||
"What on earth do you think you are doing???"); | |||
} | |||
public boolean isAspect() { | |||
@@ -203,19 +233,19 @@ public class BoundedReferenceType extends ReferenceType { | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
return resolvedTypeX.isAnnotationWithRuntimeRetention(); | |||
} | |||
public boolean isAnonymous() { | |||
return resolvedTypeX.isAnonymous(); | |||
} | |||
public boolean isNested() { | |||
return resolvedTypeX.isNested(); | |||
} | |||
public ResolvedType getOuterClass() { | |||
return resolvedTypeX.getOuterClass(); | |||
} | |||
public String getRetentionPolicy() { | |||
return resolvedTypeX.getRetentionPolicy(); | |||
} | |||
@@ -223,11 +253,11 @@ public class BoundedReferenceType extends ReferenceType { | |||
public boolean canAnnotationTargetType() { | |||
return resolvedTypeX.canAnnotationTargetType(); | |||
} | |||
public AnnotationTargetKind[] getAnnotationTargetKinds() { | |||
return resolvedTypeX.getAnnotationTargetKinds(); | |||
} | |||
public boolean isGeneric() { | |||
return resolvedTypeX.isGenericType(); | |||
} | |||
@@ -235,12 +265,12 @@ public class BoundedReferenceType extends ReferenceType { | |||
public String getDeclaredGenericSignature() { | |||
return resolvedTypeX.getDeclaredGenericSignature(); | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
return resolvedTypeX.hasAnnotation(ofType); | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
return resolvedTypeX.getAnnotations(); | |||
} | |||
@@ -22,10 +22,12 @@ import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute; | |||
/** | |||
* @author colyer Instances of this class are created by ResolvedMember.getSignatures() when collating all of the signatures for a | |||
* member. We need to create entries in the set for the "gaps" in the hierarchy. For example: | |||
* @author colyer Instances of this class are created by | |||
* ResolvedMember.getSignatures() when collating all of the signatures | |||
* for a member. We need to create entries in the set for the "gaps" in | |||
* the hierarchy. For example: | |||
* | |||
* class A { void foo(); } | |||
* class A { void foo(); } | |||
* | |||
* class B extends A {} | |||
* | |||
@@ -33,7 +35,8 @@ import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute; | |||
* | |||
* has signatures: | |||
* | |||
* B.foo() AND A.foo() B.foo() will be created as a ResolvedMemberWithSubstituteDeclaringType | |||
* B.foo() AND A.foo() B.foo() will be created as a | |||
* ResolvedMemberWithSubstituteDeclaringType | |||
* | |||
* Oh for a JDK 1.4 dynamic proxy.... we have to run on 1.3 :( | |||
*/ | |||
@@ -87,7 +90,7 @@ public class JoinPointSignature implements ResolvedMember { | |||
return realMember.getAnnotationTypes(); | |||
} | |||
public AnnotationX getAnnotationOfType(UnresolvedType ofType) { | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
return realMember.getAnnotationOfType(ofType); | |||
} | |||
@@ -95,7 +98,7 @@ public class JoinPointSignature implements ResolvedMember { | |||
realMember.setAnnotationTypes(annotationtypes); | |||
} | |||
public void addAnnotation(AnnotationX annotation) { | |||
public void addAnnotation(AnnotationAJ annotation) { | |||
realMember.addAnnotation(annotation); | |||
} | |||
@@ -203,14 +206,18 @@ public class JoinPointSignature implements ResolvedMember { | |||
return realMember.getGenericParameterTypes(); | |||
} | |||
public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized) { | |||
return realMember.parameterizedWith(typeParameters, newDeclaringType, isParameterized); | |||
return realMember.parameterizedWith(typeParameters, newDeclaringType, | |||
isParameterized); | |||
} | |||
public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized, List aliases) { | |||
return realMember.parameterizedWith(typeParameters, newDeclaringType, isParameterized, aliases); | |||
return realMember.parameterizedWith(typeParameters, newDeclaringType, | |||
isParameterized, aliases); | |||
} | |||
public void setTypeVariables(TypeVariable[] types) { | |||
@@ -257,7 +264,7 @@ public class JoinPointSignature implements ResolvedMember { | |||
return realMember.getParameterTypes(); | |||
} | |||
public AnnotationX[][] getParameterAnnotations() { | |||
public AnnotationAJ[][] getParameterAnnotations() { | |||
return realMember.getParameterAnnotations(); | |||
} | |||
@@ -297,12 +304,13 @@ public class JoinPointSignature implements ResolvedMember { | |||
return realMember.canBeParameterized(); | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
return realMember.getAnnotations(); | |||
} | |||
public Collection getDeclaringTypes(World world) { | |||
throw new UnsupportedOperationException("Adrian doesn't think you should be calling this..."); | |||
throw new UnsupportedOperationException( | |||
"Adrian doesn't think you should be calling this..."); | |||
} | |||
public Iterator getJoinPointSignatures(World world) { | |||
@@ -367,7 +375,8 @@ public class JoinPointSignature implements ResolvedMember { | |||
} | |||
public int hashCode() { | |||
return 17 + (37 * realMember.hashCode()) + (37 * substituteDeclaringType.hashCode()); | |||
return 17 + (37 * realMember.hashCode()) | |||
+ (37 * substituteDeclaringType.hashCode()); | |||
} | |||
public boolean hasBackingGenericMember() { |
@@ -24,29 +24,33 @@ public interface Member extends Comparable { | |||
public static final Member[] NONE = new Member[0]; | |||
public static final MemberKind METHOD = new MemberKind("METHOD", 1); | |||
public static final MemberKind FIELD = new MemberKind("FIELD", 2); | |||
public static final MemberKind CONSTRUCTOR = new MemberKind("CONSTRUCTOR", 3); | |||
public static final MemberKind STATIC_INITIALIZATION = new MemberKind("STATIC_INITIALIZATION", 4); | |||
public static final MemberKind CONSTRUCTOR = new MemberKind("CONSTRUCTOR", | |||
3); | |||
public static final MemberKind STATIC_INITIALIZATION = new MemberKind( | |||
"STATIC_INITIALIZATION", 4); | |||
public static final MemberKind POINTCUT = new MemberKind("POINTCUT", 5); | |||
public static final MemberKind ADVICE = new MemberKind("ADVICE", 6); | |||
public static final MemberKind HANDLER = new MemberKind("HANDLER", 7); | |||
public static final MemberKind MONITORENTER = new MemberKind("MONITORENTER", 8); | |||
public static final MemberKind MONITOREXIT = new MemberKind("MONITOREXIT", 9); | |||
public static final MemberKind MONITORENTER = new MemberKind( | |||
"MONITORENTER", 8); | |||
public static final MemberKind MONITOREXIT = new MemberKind("MONITOREXIT", | |||
9); | |||
public static final AnnotationAJ[][] NO_PARAMETER_ANNOTATIONXS = new AnnotationAJ[][] {}; | |||
public static final ResolvedType[][] NO_PARAMETER_ANNOTATION_TYPES = new ResolvedType[][] {}; | |||
public static final AnnotationX[][] NO_PARAMETER_ANNOTATIONXS = new AnnotationX[][]{}; | |||
public static final ResolvedType[][] NO_PARAMETER_ANNOTATION_TYPES = new ResolvedType[][]{}; | |||
public MemberKind getKind(); | |||
public ResolvedMember resolve(World world); | |||
public int compareTo(Object other); | |||
public int compareTo(Object other); | |||
public UnresolvedType getDeclaringType(); | |||
public UnresolvedType getReturnType(); | |||
public UnresolvedType getGenericReturnType(); | |||
public UnresolvedType[] getGenericParameterTypes(); | |||
public UnresolvedType getType(); | |||
@@ -56,28 +60,30 @@ public interface Member extends Comparable { | |||
public UnresolvedType[] getParameterTypes(); | |||
/** | |||
* Return full signature, including return type, e.g. "()LFastCar;". For a signature without the return type, | |||
* use getParameterSignature() - it is important to choose the right one in the face of covariance. | |||
* Return full signature, including return type, e.g. "()LFastCar;". For a | |||
* signature without the return type, use getParameterSignature() - it is | |||
* important to choose the right one in the face of covariance. | |||
*/ | |||
public String getSignature(); | |||
public Iterator getJoinPointSignatures(World world); | |||
public Iterator getJoinPointSignatures(World world); | |||
public int getArity(); | |||
/** | |||
* Return signature without return type, e.g. "()" for a signature *with* the return type, | |||
* use getSignature() - it is important to choose the right one in the face of covariance. | |||
* Return signature without return type, e.g. "()" for a signature *with* | |||
* the return type, use getSignature() - it is important to choose the right | |||
* one in the face of covariance. | |||
*/ | |||
public String getParameterSignature(); | |||
public int getModifiers(World world); | |||
public int getModifiers(); | |||
public boolean isStatic(); | |||
public boolean isStatic(); | |||
public boolean isInterface(); | |||
public boolean isInterface(); | |||
public boolean isPrivate(); | |||
@@ -86,11 +92,11 @@ public interface Member extends Comparable { | |||
*/ | |||
public boolean canBeParameterized(); | |||
public AnnotationX[] getAnnotations(); | |||
public Collection/* ResolvedType */getDeclaringTypes(World world); | |||
public AnnotationAJ[] getAnnotations(); | |||
public Collection/* ResolvedType */getDeclaringTypes(World world); | |||
public String[] getParameterNames(World world); | |||
public UnresolvedType[] getExceptions(World world); | |||
public UnresolvedType[] getExceptions(World world); | |||
} |
@@ -35,11 +35,13 @@ public class MemberImpl implements Member { | |||
private boolean reportedUnresolvableMember = false; | |||
/** | |||
* All the signatures that a join point with this member as its signature has. | |||
* All the signatures that a join point with this member as its signature | |||
* has. | |||
*/ | |||
private JoinPointSignatureIterator joinPointSignatures = null; | |||
public MemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, String name, String signature) { | |||
public MemberImpl(MemberKind kind, UnresolvedType declaringType, | |||
int modifiers, String name, String signature) { | |||
this.kind = kind; | |||
this.declaringType = declaringType; | |||
this.modifiers = modifiers; | |||
@@ -58,7 +60,8 @@ public class MemberImpl implements Member { | |||
} | |||
} | |||
public MemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name, | |||
public MemberImpl(MemberKind kind, UnresolvedType declaringType, | |||
int modifiers, UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes) { | |||
this.kind = kind; | |||
this.declaringType = declaringType; | |||
@@ -80,9 +83,10 @@ public class MemberImpl implements Member { | |||
// ---- utility methods | |||
/** | |||
* returns an Object[] pair of UnresolvedType, UnresolvedType[] representing return type, argument types parsed from the JVM | |||
* bytecode signature of a method. Yes, this should actually return a nice statically-typed pair object, but we don't have one | |||
* of those. | |||
* returns an Object[] pair of UnresolvedType, UnresolvedType[] representing | |||
* return type, argument types parsed from the JVM bytecode signature of a | |||
* method. Yes, this should actually return a nice statically-typed pair | |||
* object, but we don't have one of those. | |||
* | |||
* <blockquote> | |||
* | |||
@@ -94,11 +98,15 @@ public class MemberImpl implements Member { | |||
* | |||
* </blockquote> | |||
* | |||
* @param signature the JVM bytecode method signature string we want to break apart | |||
* @return a pair of UnresolvedType, UnresolvedType[] representing the return types and parameter types. | |||
* @param signature | |||
* the JVM bytecode method signature string we want to break | |||
* apart | |||
* @return a pair of UnresolvedType, UnresolvedType[] representing the | |||
* return types and parameter types. | |||
*/ | |||
// OPTIMIZE move static util methods out into a memberutils class | |||
public static String typesToSignature(UnresolvedType returnType, UnresolvedType[] paramTypes, boolean useRawTypes) { | |||
public static String typesToSignature(UnresolvedType returnType, | |||
UnresolvedType[] paramTypes, boolean useRawTypes) { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("("); | |||
for (int i = 0, len = paramTypes.length; i < len; i++) { | |||
@@ -120,8 +128,9 @@ public class MemberImpl implements Member { | |||
} | |||
/** | |||
* Returns "(<signaturesOfParamTypes>,...)" - unlike the other typesToSignature that also includes the return type, this one | |||
* just deals with the parameter types. | |||
* Returns "(<signaturesOfParamTypes>,...)" - unlike the other | |||
* typesToSignature that also includes the return type, this one just deals | |||
* with the parameter types. | |||
*/ | |||
public static String typesToSignature(UnresolvedType[] paramTypes) { | |||
StringBuffer buf = new StringBuffer(); | |||
@@ -134,9 +143,10 @@ public class MemberImpl implements Member { | |||
} | |||
/** | |||
* returns an Object[] pair of UnresolvedType, UnresolvedType[] representing return type, argument types parsed from the JVM | |||
* bytecode signature of a method. Yes, this should actually return a nice statically-typed pair object, but we don't have one | |||
* of those. | |||
* returns an Object[] pair of UnresolvedType, UnresolvedType[] representing | |||
* return type, argument types parsed from the JVM bytecode signature of a | |||
* method. Yes, this should actually return a nice statically-typed pair | |||
* object, but we don't have one of those. | |||
* | |||
* <blockquote> | |||
* | |||
@@ -148,10 +158,14 @@ public class MemberImpl implements Member { | |||
* | |||
* </blockquote> | |||
* | |||
* @param signature the JVM bytecode method signature string we want to break apart | |||
* @return a pair of UnresolvedType, UnresolvedType[] representing the return types and parameter types. | |||
* @param signature | |||
* the JVM bytecode method signature string we want to break | |||
* apart | |||
* @return a pair of UnresolvedType, UnresolvedType[] representing the | |||
* return types and parameter types. | |||
*/ | |||
private static Object[] signatureToTypes(String sig, boolean keepParameterizationInfo) { | |||
private static Object[] signatureToTypes(String sig, | |||
boolean keepParameterizationInfo) { | |||
boolean hasParameters = sig.charAt(1) != ')'; | |||
if (hasParameters) { | |||
List l = new ArrayList(); | |||
@@ -166,10 +180,13 @@ public class MemberImpl implements Member { | |||
c = sig.charAt(++i); | |||
if (c == 'L' || c == 'P') { | |||
int nextSemicolon = sig.indexOf(';', start); | |||
int firstAngly = (hasAnyAnglies ? sig.indexOf('<', start) : -1); | |||
if (!hasAnyAnglies || firstAngly == -1 || firstAngly > nextSemicolon) { | |||
int firstAngly = (hasAnyAnglies ? sig.indexOf('<', start) | |||
: -1); | |||
if (!hasAnyAnglies || firstAngly == -1 | |||
|| firstAngly > nextSemicolon) { | |||
i = nextSemicolon + 1; | |||
l.add(UnresolvedType.forSignature(sig.substring(start, i))); | |||
l.add(UnresolvedType.forSignature(sig.substring(start, | |||
i))); | |||
} else { | |||
// generics generics generics | |||
// Have to skip to the *correct* ';' | |||
@@ -194,9 +211,11 @@ public class MemberImpl implements Member { | |||
} | |||
// posn now points to the correct nextSemicolon :) | |||
i = posn; | |||
l.add(UnresolvedType.forSignature(sig.substring(start, i))); | |||
l.add(UnresolvedType.forSignature(sig.substring(start, | |||
i))); | |||
} | |||
} else if (c == 'T') { // assumed 'reference' to a type variable, so just "Tname;" | |||
} else if (c == 'T') { // assumed 'reference' to a type | |||
// variable, so just "Tname;" | |||
int nextSemicolon = sig.indexOf(';', start); | |||
String nextbit = sig.substring(start, nextSemicolon); | |||
l.add(UnresolvedType.forSignature(nextbit)); | |||
@@ -206,74 +225,97 @@ public class MemberImpl implements Member { | |||
l.add(UnresolvedType.forSignature(sig.substring(start, i))); | |||
} | |||
} | |||
UnresolvedType[] paramTypes = (UnresolvedType[]) l.toArray(new UnresolvedType[l.size()]); | |||
UnresolvedType returnType = UnresolvedType.forSignature(sig.substring(i + 1, sig.length())); | |||
UnresolvedType[] paramTypes = (UnresolvedType[]) l | |||
.toArray(new UnresolvedType[l.size()]); | |||
UnresolvedType returnType = UnresolvedType.forSignature(sig | |||
.substring(i + 1, sig.length())); | |||
return new Object[] { returnType, paramTypes }; | |||
} else { | |||
UnresolvedType returnType = UnresolvedType.forSignature(sig.substring(2)); | |||
UnresolvedType returnType = UnresolvedType.forSignature(sig | |||
.substring(2)); | |||
return new Object[] { returnType, UnresolvedType.NONE }; | |||
} | |||
} | |||
// ---- factory methods | |||
public static MemberImpl field(String declaring, int mods, String name, String signature) { | |||
return field(declaring, mods, UnresolvedType.forSignature(signature), name); | |||
public static MemberImpl field(String declaring, int mods, String name, | |||
String signature) { | |||
return field(declaring, mods, UnresolvedType.forSignature(signature), | |||
name); | |||
} | |||
// public static Member field(UnresolvedType declaring, int mods, String name, UnresolvedType type) { | |||
// return new MemberImpl(FIELD, declaring, mods, type, name, UnresolvedType.NONE); | |||
// public static Member field(UnresolvedType declaring, int mods, String | |||
// name, UnresolvedType type) { | |||
// return new MemberImpl(FIELD, declaring, mods, type, name, | |||
// UnresolvedType.NONE); | |||
// } | |||
// OPTIMIZE do we need to call this? unless necessary the signatureToTypes() call smacks of laziness on the behalf of the caller | |||
// OPTIMIZE do we need to call this? unless necessary the signatureToTypes() | |||
// call smacks of laziness on the behalf of the caller | |||
// of this method | |||
public static MemberImpl method(UnresolvedType declaring, int mods, String name, String signature) { | |||
public static MemberImpl method(UnresolvedType declaring, int mods, | |||
String name, String signature) { | |||
Object[] pair = signatureToTypes(signature, false); | |||
return method(declaring, mods, (UnresolvedType) pair[0], name, (UnresolvedType[]) pair[1]); | |||
return method(declaring, mods, (UnresolvedType) pair[0], name, | |||
(UnresolvedType[]) pair[1]); | |||
} | |||
public static MemberImpl monitorEnter() { | |||
return new MemberImpl(MONITORENTER, UnresolvedType.OBJECT, Modifier.STATIC, ResolvedType.VOID, "<lock>", | |||
return new MemberImpl(MONITORENTER, UnresolvedType.OBJECT, | |||
Modifier.STATIC, ResolvedType.VOID, "<lock>", | |||
UnresolvedType.ARRAY_WITH_JUST_OBJECT); | |||
} | |||
public static MemberImpl monitorExit() { | |||
return new MemberImpl(MONITOREXIT, UnresolvedType.OBJECT, Modifier.STATIC, ResolvedType.VOID, "<unlock>", | |||
return new MemberImpl(MONITOREXIT, UnresolvedType.OBJECT, | |||
Modifier.STATIC, ResolvedType.VOID, "<unlock>", | |||
UnresolvedType.ARRAY_WITH_JUST_OBJECT); | |||
} | |||
public static Member pointcut(UnresolvedType declaring, String name, String signature) { | |||
public static Member pointcut(UnresolvedType declaring, String name, | |||
String signature) { | |||
Object[] pair = signatureToTypes(signature, false); | |||
return pointcut(declaring, 0, (UnresolvedType) pair[0], name, (UnresolvedType[]) pair[1]); | |||
return pointcut(declaring, 0, (UnresolvedType) pair[0], name, | |||
(UnresolvedType[]) pair[1]); | |||
} | |||
private static MemberImpl field(String declaring, int mods, UnresolvedType ty, String name) { | |||
return new MemberImpl(FIELD, UnresolvedType.forName(declaring), mods, ty, name, UnresolvedType.NONE); | |||
private static MemberImpl field(String declaring, int mods, | |||
UnresolvedType ty, String name) { | |||
return new MemberImpl(FIELD, UnresolvedType.forName(declaring), mods, | |||
ty, name, UnresolvedType.NONE); | |||
} | |||
public static MemberImpl method(UnresolvedType declTy, int mods, UnresolvedType rTy, String name, UnresolvedType[] paramTys) { | |||
public static MemberImpl method(UnresolvedType declTy, int mods, | |||
UnresolvedType rTy, String name, UnresolvedType[] paramTys) { | |||
return new MemberImpl( | |||
// ??? this calls <clinit> a method | |||
name.equals("<init>") ? CONSTRUCTOR : METHOD, declTy, mods, rTy, name, paramTys); | |||
// ??? this calls <clinit> a method | |||
name.equals("<init>") ? CONSTRUCTOR : METHOD, declTy, mods, | |||
rTy, name, paramTys); | |||
} | |||
private static Member pointcut(UnresolvedType declTy, int mods, UnresolvedType rTy, String name, UnresolvedType[] paramTys) { | |||
private static Member pointcut(UnresolvedType declTy, int mods, | |||
UnresolvedType rTy, String name, UnresolvedType[] paramTys) { | |||
return new MemberImpl(POINTCUT, declTy, mods, rTy, name, paramTys); | |||
} | |||
public static ResolvedMemberImpl makeExceptionHandlerSignature(UnresolvedType inType, UnresolvedType catchType) { | |||
return new ResolvedMemberImpl(HANDLER, inType, Modifier.STATIC, "<catch>", "(" + catchType.getSignature() + ")V"); | |||
public static ResolvedMemberImpl makeExceptionHandlerSignature( | |||
UnresolvedType inType, UnresolvedType catchType) { | |||
return new ResolvedMemberImpl(HANDLER, inType, Modifier.STATIC, | |||
"<catch>", "(" + catchType.getSignature() + ")V"); | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof Member)) | |||
return false; | |||
Member o = (Member) other; | |||
return (getKind() == o.getKind() && getName().equals(o.getName()) && getSignature().equals(o.getSignature()) && getDeclaringType() | |||
return (getKind() == o.getKind() && getName().equals(o.getName()) | |||
&& getSignature().equals(o.getSignature()) && getDeclaringType() | |||
.equals(o.getDeclaringType())); | |||
} | |||
/** | |||
* Equality is checked based on the underlying signature, so the hash code of a member is based on its kind, name, signature, | |||
* and declaring type. The algorithm for this was taken from page 38 of effective java. | |||
* Equality is checked based on the underlying signature, so the hash code | |||
* of a member is based on its kind, name, signature, and declaring type. | |||
* The algorithm for this was taken from page 38 of effective java. | |||
*/ | |||
private volatile int hashCode = 0; | |||
@@ -372,7 +414,8 @@ public class MemberImpl implements Member { | |||
return paramSignature; | |||
} | |||
// OPTIMIZE see next line. Why the hell are they in here if we only know it once resolution has occurred... | |||
// OPTIMIZE see next line. Why the hell are they in here if we only know it | |||
// once resolution has occurred... | |||
// ---- things we know only with resolution | |||
public int getModifiers(World world) { | |||
@@ -413,9 +456,10 @@ public class MemberImpl implements Member { | |||
return modifiers; | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
throw new UnsupportedOperationException("You should resolve this member '" + this | |||
+ "' and call getAnnotations() on the result..."); | |||
public AnnotationAJ[] getAnnotations() { | |||
throw new UnsupportedOperationException( | |||
"You should resolve this member '" + this | |||
+ "' and call getAnnotations() on the result..."); | |||
} | |||
// ---- fields 'n' stuff | |||
@@ -424,7 +468,8 @@ public class MemberImpl implements Member { | |||
ResolvedType myType = getDeclaringType().resolve(world); | |||
Collection ret = new HashSet(); | |||
if (kind == CONSTRUCTOR) { | |||
// this is wrong if the member doesn't exist, but that doesn't matter | |||
// this is wrong if the member doesn't exist, but that doesn't | |||
// matter | |||
ret.add(myType); | |||
} else if (isStatic() || kind == FIELD) { | |||
walkUpStatic(ret, myType); | |||
@@ -484,7 +529,8 @@ public class MemberImpl implements Member { | |||
} | |||
/** | |||
* All the signatures that a join point with this member as its signature has. | |||
* All the signatures that a join point with this member as its signature | |||
* has. | |||
*/ | |||
public Iterator getJoinPointSignatures(World inAWorld) { | |||
if (joinPointSignatures == null) { | |||
@@ -495,15 +541,17 @@ public class MemberImpl implements Member { | |||
} | |||
/** | |||
* Raises an [Xlint:cantFindType] message if the declaring type cannot be found or an [Xlint:unresolvableMember] message if the | |||
* type can be found (bug 149908) | |||
* Raises an [Xlint:cantFindType] message if the declaring type cannot be | |||
* found or an [Xlint:unresolvableMember] message if the type can be found | |||
* (bug 149908) | |||
*/ | |||
private void reportDidntFindMember(World world) { | |||
if (reportedCantFindDeclaringType || reportedUnresolvableMember) | |||
return; | |||
ResolvedType rType = getDeclaringType().resolve(world); | |||
if (rType.isMissing()) { | |||
world.getLint().cantFindType.signal(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE, rType.getName()), null); | |||
world.getLint().cantFindType.signal(WeaverMessages.format( | |||
WeaverMessages.CANT_FIND_TYPE, rType.getName()), null); | |||
reportedCantFindDeclaringType = true; | |||
} else { | |||
world.getLint().unresolvableMember.signal(getName(), null); |
@@ -24,21 +24,27 @@ import org.aspectj.weaver.patterns.Declare; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
/** | |||
* A reference type represents some 'real' type, not a primitive, not an array - but a real type, for example java.util.List. Each | |||
* ReferenceType has a delegate that is the underlying artifact - either an eclipse artifact or a bcel artifact. If the type | |||
* represents a raw type (i.e. there is a generic form) then the genericType field is set to point to the generic type. If it is for | |||
* a parameterized type then the generic type is also set to point to the generic form. | |||
* A reference type represents some 'real' type, not a primitive, not an array - | |||
* but a real type, for example java.util.List. Each ReferenceType has a | |||
* delegate that is the underlying artifact - either an eclipse artifact or a | |||
* bcel artifact. If the type represents a raw type (i.e. there is a generic | |||
* form) then the genericType field is set to point to the generic type. If it | |||
* is for a parameterized type then the generic type is also set to point to the | |||
* generic form. | |||
*/ | |||
public class ReferenceType extends ResolvedType { | |||
/** | |||
* For generic types, this list holds references to all the derived raw and parameterized versions. We need this so that if the | |||
* generic delegate is swapped during incremental compilation, the delegate of the derivatives is swapped also. | |||
* For generic types, this list holds references to all the derived raw and | |||
* parameterized versions. We need this so that if the generic delegate is | |||
* swapped during incremental compilation, the delegate of the derivatives | |||
* is swapped also. | |||
*/ | |||
private List/* ReferenceType */derivativeTypes = new ArrayList(); | |||
/** | |||
* For parameterized types (or the raw type) - this field points to the actual reference type from which they are derived. | |||
* For parameterized types (or the raw type) - this field points to the | |||
* actual reference type from which they are derived. | |||
*/ | |||
ReferenceType genericType = null; | |||
@@ -72,8 +78,10 @@ public class ReferenceType extends ResolvedType { | |||
/** | |||
* Constructor used when creating a parameterized type. | |||
*/ | |||
public ReferenceType(ResolvedType theGenericType, ResolvedType[] theParameters, World aWorld) { | |||
super(makeParameterizedSignature(theGenericType, theParameters), theGenericType.signatureErasure, aWorld); | |||
public ReferenceType(ResolvedType theGenericType, | |||
ResolvedType[] theParameters, World aWorld) { | |||
super(makeParameterizedSignature(theGenericType, theParameters), | |||
theGenericType.signatureErasure, aWorld); | |||
ReferenceType genericReferenceType = (ReferenceType) theGenericType; | |||
this.typeParameters = theParameters; | |||
this.genericType = genericReferenceType; | |||
@@ -129,11 +137,11 @@ public class ReferenceType extends ResolvedType { | |||
return (sig == null) ? "" : sig; | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
return delegate.getAnnotations(); | |||
} | |||
public void addAnnotation(AnnotationX annotationX) { | |||
public void addAnnotation(AnnotationAJ annotationX) { | |||
delegate.addAnnotation(annotationX); | |||
} | |||
@@ -145,12 +153,13 @@ public class ReferenceType extends ResolvedType { | |||
return delegate.getAnnotationTypes(); | |||
} | |||
public AnnotationX getAnnotationOfType(UnresolvedType ofType) { | |||
AnnotationX[] axs = delegate.getAnnotations(); | |||
if (axs == null) | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
AnnotationAJ[] axs = delegate.getAnnotations(); | |||
if (axs == null) { | |||
return null; | |||
} | |||
for (int i = 0; i < axs.length; i++) { | |||
if (axs[i].getSignature().equals(ofType)) { | |||
if (axs[i].getTypeSignature().equals(ofType.getSignature())) { | |||
return axs[i]; | |||
} | |||
} | |||
@@ -221,7 +230,8 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
// ??? needs to be Methods, not just declared methods? JLS 5.5 unclear | |||
ResolvedMember[] a = getDeclaredMethods(); | |||
ResolvedMember[] b = other.getDeclaredMethods(); // ??? is this cast always safe | |||
ResolvedMember[] b = other.getDeclaredMethods(); // ??? is this cast | |||
// always safe | |||
for (int ai = 0, alen = a.length; ai < alen; ai++) { | |||
for (int bi = 0, blen = b.length; bi < blen; bi++) { | |||
if (!b[bi].isCompatibleWith(a[ai])) | |||
@@ -240,21 +250,26 @@ public class ReferenceType extends ResolvedType { | |||
if (getTypeParameters().length == other.getTypeParameters().length) { | |||
// there's a chance it can be done | |||
ResolvedType[] myTypeParameters = getResolvedTypeParameters(); | |||
ResolvedType[] theirTypeParameters = other.getResolvedTypeParameters(); | |||
ResolvedType[] theirTypeParameters = other | |||
.getResolvedTypeParameters(); | |||
for (int i = 0; i < myTypeParameters.length; i++) { | |||
if (myTypeParameters[i] != theirTypeParameters[i]) { | |||
// thin ice now... but List<String> may still be coerceable from e.g. List<T> | |||
// thin ice now... but List<String> may still be | |||
// coerceable from e.g. List<T> | |||
if (myTypeParameters[i].isGenericWildcard()) { | |||
BoundedReferenceType wildcard = (BoundedReferenceType) myTypeParameters[i]; | |||
if (!wildcard.canBeCoercedTo(theirTypeParameters[i])) | |||
if (!wildcard | |||
.canBeCoercedTo(theirTypeParameters[i])) | |||
return false; | |||
} else if (myTypeParameters[i].isTypeVariableReference()) { | |||
} else if (myTypeParameters[i] | |||
.isTypeVariableReference()) { | |||
TypeVariableReferenceType tvrt = (TypeVariableReferenceType) myTypeParameters[i]; | |||
TypeVariable tv = tvrt.getTypeVariable(); | |||
tv.resolve(world); | |||
if (!tv.canBeBoundTo(theirTypeParameters[i])) | |||
return false; | |||
} else if (theirTypeParameters[i].isTypeVariableReference()) { | |||
} else if (theirTypeParameters[i] | |||
.isTypeVariableReference()) { | |||
TypeVariableReferenceType tvrt = (TypeVariableReferenceType) theirTypeParameters[i]; | |||
TypeVariable tv = tvrt.getTypeVariable(); | |||
tv.resolve(world); | |||
@@ -289,7 +304,8 @@ public class ReferenceType extends ResolvedType { | |||
if (other.isPrimitiveType()) { | |||
if (!world.isInJava5Mode()) | |||
return false; | |||
if (ResolvedType.validBoxing.contains(this.getSignature() + other.getSignature())) | |||
if (ResolvedType.validBoxing.contains(this.getSignature() | |||
+ other.getSignature())) | |||
return true; | |||
} | |||
if (this == other) | |||
@@ -297,7 +313,8 @@ public class ReferenceType extends ResolvedType { | |||
if (this.getSignature().equals(ResolvedType.OBJECT.getSignature())) | |||
return true; | |||
if ((this.isRawType() || this.isGenericType()) && other.isParameterizedType()) { | |||
if ((this.isRawType() || this.isGenericType()) | |||
&& other.isParameterizedType()) { | |||
if (isAssignableFrom((ResolvedType) other.getRawType())) | |||
return true; | |||
} | |||
@@ -328,13 +345,15 @@ public class ReferenceType extends ResolvedType { | |||
if (wildcardsAllTheWay && !other.isParameterizedType()) | |||
return true; | |||
// we have to match by parameters one at a time | |||
ResolvedType[] theirParameters = other.getResolvedTypeParameters(); | |||
ResolvedType[] theirParameters = other | |||
.getResolvedTypeParameters(); | |||
boolean parametersAssignable = true; | |||
if (myParameters.length == theirParameters.length) { | |||
for (int i = 0; i < myParameters.length; i++) { | |||
if (myParameters[i] == theirParameters[i]) | |||
continue; | |||
if (myParameters[i].isAssignableFrom(theirParameters[i], allowMissing)) { | |||
if (myParameters[i].isAssignableFrom( | |||
theirParameters[i], allowMissing)) { | |||
continue; | |||
} | |||
if (!myParameters[i].isGenericWildcard()) { | |||
@@ -356,20 +375,38 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
} | |||
if (isTypeVariableReference() && !other.isTypeVariableReference()) { // eg. this=T other=Ljava/lang/Object; | |||
TypeVariable aVar = ((TypeVariableReference) this).getTypeVariable(); | |||
if (isTypeVariableReference() && !other.isTypeVariableReference()) { // eg | |||
// . | |||
// this | |||
// = | |||
// T | |||
// other | |||
// = | |||
// Ljava | |||
// / | |||
// lang | |||
// / | |||
// Object | |||
// ; | |||
TypeVariable aVar = ((TypeVariableReference) this) | |||
.getTypeVariable(); | |||
return aVar.resolve(world).canBeBoundTo(other); | |||
} | |||
if (other.isTypeVariableReference()) { | |||
TypeVariableReferenceType otherType = (TypeVariableReferenceType) other; | |||
if (this instanceof TypeVariableReference) { | |||
return ((TypeVariableReference) this).getTypeVariable().resolve(world).canBeBoundTo( | |||
otherType.getTypeVariable().getFirstBound().resolve(world));// pr171952 | |||
// return ((TypeVariableReference)this).getTypeVariable()==otherType.getTypeVariable(); | |||
return ((TypeVariableReference) this).getTypeVariable() | |||
.resolve(world).canBeBoundTo( | |||
otherType.getTypeVariable().getFirstBound() | |||
.resolve(world));// pr171952 | |||
// return | |||
// ((TypeVariableReference)this).getTypeVariable()==otherType | |||
// .getTypeVariable(); | |||
} else { | |||
// FIXME asc should this say canBeBoundTo?? | |||
return this.isAssignableFrom(otherType.getTypeVariable().getFirstBound().resolve(world)); | |||
return this.isAssignableFrom(otherType.getTypeVariable() | |||
.getFirstBound().resolve(world)); | |||
} | |||
} | |||
@@ -393,7 +430,9 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
public boolean isExposedToWeaver() { | |||
return (delegate == null) || delegate.isExposedToWeaver(); // ??? where does this belong | |||
return (delegate == null) || delegate.isExposedToWeaver(); // ??? where | |||
// does this | |||
// belong | |||
} | |||
public WeaverStateInfo getWeaverState() { | |||
@@ -407,7 +446,8 @@ public class ReferenceType extends ResolvedType { | |||
ResolvedMember[] delegateFields = delegate.getDeclaredFields(); | |||
parameterizedFields = new ResolvedMember[delegateFields.length]; | |||
for (int i = 0; i < delegateFields.length; i++) { | |||
parameterizedFields[i] = delegateFields[i].parameterizedWith(getTypesForMemberParameterization(), this, | |||
parameterizedFields[i] = delegateFields[i].parameterizedWith( | |||
getTypesForMemberParameterization(), this, | |||
isParameterizedType()); | |||
} | |||
return parameterizedFields; | |||
@@ -417,40 +457,52 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
/** | |||
* Find out from the generic signature the true signature of any interfaces I implement. If I am parameterized, these may then | |||
* need to be parameterized before returning. | |||
* Find out from the generic signature the true signature of any interfaces | |||
* I implement. If I am parameterized, these may then need to be | |||
* parameterized before returning. | |||
*/ | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
if (parameterizedInterfaces != null) | |||
return parameterizedInterfaces; | |||
if (isParameterizedType()) { | |||
ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces(); | |||
// UnresolvedType[] paramTypes = getTypesForMemberParameterization(); | |||
ResolvedType[] delegateInterfaces = delegate | |||
.getDeclaredInterfaces(); | |||
// UnresolvedType[] paramTypes = | |||
// getTypesForMemberParameterization(); | |||
parameterizedInterfaces = new ResolvedType[delegateInterfaces.length]; | |||
for (int i = 0; i < delegateInterfaces.length; i++) { | |||
// We may have to sub/super set the set of parametertypes if the implemented interface | |||
// We may have to sub/super set the set of parametertypes if the | |||
// implemented interface | |||
// needs more or less than this type does. (pr124803/pr125080) | |||
if (delegateInterfaces[i].isParameterizedType()) { | |||
parameterizedInterfaces[i] = delegateInterfaces[i].parameterize(getMemberParameterizationMap()).resolve(world); | |||
parameterizedInterfaces[i] = delegateInterfaces[i] | |||
.parameterize(getMemberParameterizationMap()) | |||
.resolve(world); | |||
} else { | |||
parameterizedInterfaces[i] = delegateInterfaces[i]; | |||
} | |||
} | |||
return parameterizedInterfaces; | |||
} else if (isRawType()) { | |||
ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces(); | |||
ResolvedType[] delegateInterfaces = delegate | |||
.getDeclaredInterfaces(); | |||
UnresolvedType[] paramTypes = getTypesForMemberParameterization(); | |||
parameterizedInterfaces = new ResolvedType[delegateInterfaces.length]; | |||
for (int i = 0; i < parameterizedInterfaces.length; i++) { | |||
parameterizedInterfaces[i] = delegateInterfaces[i]; | |||
if (parameterizedInterfaces[i].isGenericType()) { | |||
// a generic supertype of a raw type is replaced by its raw equivalent | |||
parameterizedInterfaces[i] = parameterizedInterfaces[i].getRawType().resolve(getWorld()); | |||
// a generic supertype of a raw type is replaced by its raw | |||
// equivalent | |||
parameterizedInterfaces[i] = parameterizedInterfaces[i] | |||
.getRawType().resolve(getWorld()); | |||
} else if (parameterizedInterfaces[i].isParameterizedType()) { | |||
// a parameterized supertype collapses any type vars to their upper bounds | |||
UnresolvedType[] toUseForParameterization = determineThoseTypesToUse(parameterizedInterfaces[i], paramTypes); | |||
parameterizedInterfaces[i] = parameterizedInterfaces[i].parameterizedWith(toUseForParameterization); | |||
// a parameterized supertype collapses any type vars to | |||
// their upper bounds | |||
UnresolvedType[] toUseForParameterization = determineThoseTypesToUse( | |||
parameterizedInterfaces[i], paramTypes); | |||
parameterizedInterfaces[i] = parameterizedInterfaces[i] | |||
.parameterizedWith(toUseForParameterization); | |||
} | |||
} | |||
return parameterizedInterfaces; | |||
@@ -459,10 +511,12 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
/** | |||
* Locates the named type variable in the list of those on this generic type and returns the type parameter from the second list | |||
* supplied. Returns null if it can't be found | |||
* Locates the named type variable in the list of those on this generic type | |||
* and returns the type parameter from the second list supplied. Returns | |||
* null if it can't be found | |||
*/ | |||
// private UnresolvedType findTypeParameterInList(String name, TypeVariable[] tvarsOnThisGenericType, UnresolvedType[] | |||
// private UnresolvedType findTypeParameterInList(String name, | |||
// TypeVariable[] tvarsOnThisGenericType, UnresolvedType[] | |||
// paramTypes) { | |||
// int position = -1; | |||
// for (int i = 0; i < tvarsOnThisGenericType.length; i++) { | |||
@@ -473,31 +527,38 @@ public class ReferenceType extends ResolvedType { | |||
// return paramTypes[position]; | |||
// } | |||
/** | |||
* It is possible this type has multiple type variables but the interface we are about to parameterize only uses a subset - this | |||
* method determines the subset to use by looking at the type variable names used. For example: <code> | |||
* It is possible this type has multiple type variables but the interface we | |||
* are about to parameterize only uses a subset - this method determines the | |||
* subset to use by looking at the type variable names used. For example: | |||
* <code> | |||
* class Foo<T extends String,E extends Number> implements SuperInterface<T> {} | |||
* </code> where <code> | |||
* interface SuperInterface<Z> {} | |||
* </code> In that | |||
* example, a use of the 'Foo' raw type should know that it implements the SuperInterface<String>. | |||
* </code> In that example, a use of the 'Foo' raw type should | |||
* know that it implements the SuperInterface<String>. | |||
*/ | |||
private UnresolvedType[] determineThoseTypesToUse(ResolvedType parameterizedInterface, UnresolvedType[] paramTypes) { | |||
private UnresolvedType[] determineThoseTypesToUse( | |||
ResolvedType parameterizedInterface, UnresolvedType[] paramTypes) { | |||
// What are the type parameters for the supertype? | |||
UnresolvedType[] tParms = parameterizedInterface.getTypeParameters(); | |||
UnresolvedType[] retVal = new UnresolvedType[tParms.length]; | |||
// Go through the supertypes type parameters, if any of them is a type variable, use the | |||
// Go through the supertypes type parameters, if any of them is a type | |||
// variable, use the | |||
// real type variable on the declaring type. | |||
// it is possibly overkill to look up the type variable - ideally the entry in the type parameter list for the | |||
// interface should be the a ref to the type variable in the current type ... but I'm not 100% confident right now. | |||
// it is possibly overkill to look up the type variable - ideally the | |||
// entry in the type parameter list for the | |||
// interface should be the a ref to the type variable in the current | |||
// type ... but I'm not 100% confident right now. | |||
for (int i = 0; i < tParms.length; i++) { | |||
UnresolvedType tParm = tParms[i]; | |||
if (tParm.isTypeVariableReference()) { | |||
TypeVariableReference tvrt = (TypeVariableReference) tParm; | |||
TypeVariable tv = tvrt.getTypeVariable(); | |||
int rank = getRank(tv.getName()); | |||
// -1 probably means it is a reference to a type variable on the outer generic type (see pr129566) | |||
// -1 probably means it is a reference to a type variable on the | |||
// outer generic type (see pr129566) | |||
if (rank != -1) { | |||
retVal[i] = paramTypes[rank]; | |||
} else { | |||
@@ -512,8 +573,9 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
/** | |||
* Returns the position within the set of type variables for this type for the specified type variable name. Returns -1 if there | |||
* is no type variable with the specified name. | |||
* Returns the position within the set of type variables for this type for | |||
* the specified type variable name. Returns -1 if there is no type variable | |||
* with the specified name. | |||
*/ | |||
private int getRank(String tvname) { | |||
TypeVariable[] thisTypesTVars = getGenericType().getTypeVariables(); | |||
@@ -533,7 +595,8 @@ public class ReferenceType extends ResolvedType { | |||
UnresolvedType[] parameters = getTypesForMemberParameterization(); | |||
parameterizedMethods = new ResolvedMember[delegateMethods.length]; | |||
for (int i = 0; i < delegateMethods.length; i++) { | |||
parameterizedMethods[i] = delegateMethods[i].parameterizedWith(parameters, this, isParameterizedType()); | |||
parameterizedMethods[i] = delegateMethods[i].parameterizedWith( | |||
parameters, this, isParameterizedType()); | |||
} | |||
return parameterizedMethods; | |||
} else { | |||
@@ -545,11 +608,13 @@ public class ReferenceType extends ResolvedType { | |||
if (parameterizedPointcuts != null) | |||
return parameterizedPointcuts; | |||
if (isParameterizedType()) { | |||
ResolvedMember[] delegatePointcuts = delegate.getDeclaredPointcuts(); | |||
ResolvedMember[] delegatePointcuts = delegate | |||
.getDeclaredPointcuts(); | |||
parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length]; | |||
for (int i = 0; i < delegatePointcuts.length; i++) { | |||
parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypesForMemberParameterization(), this, | |||
isParameterizedType()); | |||
parameterizedPointcuts[i] = delegatePointcuts[i] | |||
.parameterizedWith(getTypesForMemberParameterization(), | |||
this, isParameterizedType()); | |||
} | |||
return parameterizedPointcuts; | |||
} else { | |||
@@ -590,7 +655,8 @@ public class ReferenceType extends ResolvedType { | |||
PerClause pclause = delegate.getPerClause(); | |||
if (isParameterizedType()) { // could cache the result here... | |||
Map parameterizationMap = getAjMemberParameterizationMap(); | |||
pclause = (PerClause) pclause.parameterizeWith(parameterizationMap, world); | |||
pclause = (PerClause) pclause.parameterizeWith(parameterizationMap, | |||
world); | |||
} | |||
return pclause; | |||
} | |||
@@ -605,7 +671,8 @@ public class ReferenceType extends ResolvedType { | |||
Map parameterizationMap = getAjMemberParameterizationMap(); | |||
for (Iterator iter = genericDeclares.iterator(); iter.hasNext();) { | |||
Declare declareStatement = (Declare) iter.next(); | |||
parameterizedDeclares.add(declareStatement.parameterizeWith(parameterizationMap, world)); | |||
parameterizedDeclares.add(declareStatement.parameterizeWith( | |||
parameterizationMap, world)); | |||
} | |||
declares = parameterizedDeclares; | |||
} else { | |||
@@ -633,7 +700,8 @@ public class ReferenceType extends ResolvedType { | |||
// Map parameterizationMap = getAjMemberParameterizationMap(); | |||
// for (Iterator iter = genericDeclares.iterator(); iter.hasNext();) { | |||
// ConcreteTypeMunger munger = (ConcreteTypeMunger)iter.next(); | |||
// parameterizedTypeMungers.add(munger.parameterizeWith(parameterizationMap,world)); | |||
// parameterizedTypeMungers.add(munger.parameterizeWith(parameterizationMap, | |||
// world)); | |||
// } | |||
// ret = parameterizedTypeMungers; | |||
// } else { | |||
@@ -659,7 +727,8 @@ public class ReferenceType extends ResolvedType { | |||
world.setTypeVariableLookupScope(null); | |||
} | |||
if (this.isParameterizedType() && ret.isParameterizedType()) { | |||
ret = ret.parameterize(getMemberParameterizationMap()).resolve(getWorld()); | |||
ret = ret.parameterize(getMemberParameterizationMap()).resolve( | |||
getWorld()); | |||
} | |||
return ret; | |||
} | |||
@@ -669,10 +738,13 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
public void setDelegate(ReferenceTypeDelegate delegate) { | |||
// Don't copy from BcelObjectType to EclipseSourceType - the context may be tidied (result null'd) after previous weaving | |||
if (this.delegate != null && !(this.delegate instanceof BcelObjectType) | |||
// Don't copy from BcelObjectType to EclipseSourceType - the context may | |||
// be tidied (result null'd) after previous weaving | |||
if (this.delegate != null | |||
&& !(this.delegate instanceof BcelObjectType) | |||
&& this.delegate.getSourceContext() != SourceContextImpl.UNKNOWN_SOURCE_CONTEXT) | |||
((AbstractReferenceTypeDelegate) delegate).setSourceContext(this.delegate.getSourceContext()); | |||
((AbstractReferenceTypeDelegate) delegate) | |||
.setSourceContext(this.delegate.getSourceContext()); | |||
this.delegate = delegate; | |||
for (Iterator it = this.derivativeTypes.iterator(); it.hasNext();) { | |||
ReferenceType dependent = (ReferenceType) it.next(); | |||
@@ -744,13 +816,15 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
/** | |||
* a parameterized signature starts with a "P" in place of the "L", see the comment on signatures in UnresolvedType. | |||
* a parameterized signature starts with a "P" in place of the "L", see the | |||
* comment on signatures in UnresolvedType. | |||
* | |||
* @param aGenericType | |||
* @param someParameters | |||
* @return | |||
*/ | |||
private static String makeParameterizedSignature(ResolvedType aGenericType, ResolvedType[] someParameters) { | |||
private static String makeParameterizedSignature(ResolvedType aGenericType, | |||
ResolvedType[] someParameters) { | |||
String rawSignature = aGenericType.getErasureSignature(); | |||
StringBuffer ret = new StringBuffer(); | |||
ret.append(PARAMETERIZED_TYPE_IDENTIFIER); | |||
@@ -763,13 +837,15 @@ public class ReferenceType extends ResolvedType { | |||
return ret.toString(); | |||
} | |||
private static String makeDeclaredSignature(ResolvedType aGenericType, UnresolvedType[] someParameters) { | |||
private static String makeDeclaredSignature(ResolvedType aGenericType, | |||
UnresolvedType[] someParameters) { | |||
StringBuffer ret = new StringBuffer(); | |||
String rawSig = aGenericType.getErasureSignature(); | |||
ret.append(rawSig.substring(0, rawSig.length() - 1)); | |||
ret.append("<"); | |||
for (int i = 0; i < someParameters.length; i++) { | |||
ret.append(((ReferenceType) someParameters[i]).getSignatureForAttribute()); | |||
ret.append(((ReferenceType) someParameters[i]) | |||
.getSignatureForAttribute()); | |||
} | |||
ret.append(">;"); | |||
return ret.toString(); |
@@ -17,55 +17,88 @@ import java.util.Collection; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
/** | |||
* Abstraction over a type - a reference type is Object and a descendant of Object, other types (int/etc) are | |||
* considered primitive types. Abstract implementation provided by AbstractReferenceTypeDelegate. | |||
* Abstraction over a type - a reference type is Object and a descendant of | |||
* Object, other types (int/etc) are considered primitive types. Abstract | |||
* implementation provided by AbstractReferenceTypeDelegate. | |||
*/ | |||
public interface ReferenceTypeDelegate { | |||
// TODO asc move to proxy | |||
public void addAnnotation(AnnotationX annotationX); | |||
public void ensureDelegateConsistent(); // Required evil because of mutator methods in delegates :( (see pr85132) | |||
public void addAnnotation(AnnotationAJ annotationX); | |||
public void ensureDelegateConsistent(); // Required evil because of mutator | |||
// methods in delegates :( (see | |||
// pr85132) | |||
public boolean isAspect(); | |||
public boolean isAnnotationStyleAspect(); | |||
public boolean isInterface(); | |||
public boolean isEnum(); | |||
public boolean isAnnotation(); | |||
public String getRetentionPolicy(); | |||
public boolean canAnnotationTargetType(); | |||
public AnnotationTargetKind[] getAnnotationTargetKinds(); | |||
public boolean isAnnotationWithRuntimeRetention(); | |||
public boolean isAnnotationStyleAspect(); | |||
public boolean isInterface(); | |||
public boolean isEnum(); | |||
public boolean isAnnotation(); | |||
public String getRetentionPolicy(); | |||
public boolean canAnnotationTargetType(); | |||
public AnnotationTargetKind[] getAnnotationTargetKinds(); | |||
public boolean isAnnotationWithRuntimeRetention(); | |||
public boolean isClass(); | |||
public boolean isGeneric(); | |||
public boolean isAnonymous(); | |||
public boolean isNested(); | |||
public boolean isExposedToWeaver(); | |||
public boolean hasAnnotation(UnresolvedType ofType); | |||
public AnnotationX[] getAnnotations(); | |||
public ResolvedType[] getAnnotationTypes(); | |||
public AnnotationAJ[] getAnnotations(); | |||
public ResolvedType[] getAnnotationTypes(); | |||
public ResolvedMember[] getDeclaredFields(); | |||
public ResolvedType[] getDeclaredInterfaces(); | |||
public ResolvedType[] getDeclaredInterfaces(); | |||
public ResolvedMember[] getDeclaredMethods(); | |||
public ResolvedMember[] getDeclaredPointcuts(); | |||
public TypeVariable[] getTypeVariables(); | |||
public PerClause getPerClause(); | |||
public Collection getDeclares() ; | |||
public PerClause getPerClause(); | |||
public Collection getDeclares(); | |||
public Collection getTypeMungers(); | |||
public Collection getPrivilegedAccesses(); | |||
public int getModifiers(); | |||
public ResolvedType getSuperclass(); | |||
public ResolvedType getSuperclass(); | |||
public WeaverStateInfo getWeaverState(); | |||
public ReferenceType getResolvedTypeX(); | |||
public boolean doesNotExposeShadowMungers(); | |||
public ISourceContext getSourceContext(); | |||
public String getSourcefilename(); | |||
public String getDeclaredGenericSignature(); | |||
public ResolvedType getOuterClass(); | |||
} |
@@ -20,7 +20,8 @@ import java.util.Map; | |||
import org.aspectj.bridge.ISourceLocation; | |||
public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDeclaringElement { | |||
public interface ResolvedMember extends Member, AnnotatedElement, | |||
TypeVariableDeclaringElement { | |||
public static final ResolvedMember[] NONE = new ResolvedMember[0]; | |||
@@ -42,13 +43,13 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe | |||
public boolean hasAnnotation(UnresolvedType ofType); | |||
public AnnotationX[] getAnnotations(); | |||
public AnnotationAJ[] getAnnotations(); | |||
public ResolvedType[] getAnnotationTypes(); | |||
public void setAnnotationTypes(UnresolvedType[] annotationtypes); | |||
public void addAnnotation(AnnotationX annotation); | |||
public void addAnnotation(AnnotationAJ annotation); | |||
public boolean isBridgeMethod(); | |||
@@ -64,7 +65,7 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe | |||
public void setParameterNames(String[] names); | |||
public AnnotationX[][] getParameterAnnotations(); | |||
public AnnotationAJ[][] getParameterAnnotations(); | |||
public ResolvedType[][] getParameterAnnotationTypes(); | |||
@@ -118,26 +119,34 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe | |||
public ResolvedMember getBackingGenericMember(); | |||
/** | |||
* Get the UnresolvedType for the return type, taking generic signature into account | |||
* Get the UnresolvedType for the return type, taking generic signature into | |||
* account | |||
*/ | |||
public UnresolvedType getGenericReturnType(); | |||
/** | |||
* Get the TypeXs of the parameter types, taking generic signature into account | |||
* Get the TypeXs of the parameter types, taking generic signature into | |||
* account | |||
*/ | |||
public UnresolvedType[] getGenericParameterTypes(); | |||
// return a resolved member in which all type variables in the signature of this | |||
// return a resolved member in which all type variables in the signature of | |||
// this | |||
// member have been replaced with the given bindings. | |||
// the isParameterized flag tells us whether we are creating a raw type version or not | |||
// the isParameterized flag tells us whether we are creating a raw type | |||
// version or not | |||
// if isParameterized List<T> will turn into List<String> (for example), | |||
// but if !isParameterized List<T> will turn into List. | |||
public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized); | |||
// this variant allows for aliases for type variables (i.e. allowing them to have another name) | |||
// this is used for processing ITDs that share type variables with their target generic type | |||
public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
// this variant allows for aliases for type variables (i.e. allowing them to | |||
// have another name) | |||
// this is used for processing ITDs that share type variables with their | |||
// target generic type | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized, List aliases); | |||
public void setTypeVariables(TypeVariable[] types); | |||
@@ -145,7 +154,8 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe | |||
public TypeVariable[] getTypeVariables(); | |||
// /** | |||
// * If this member is defined by a parameterized super-type, return the erasure | |||
// * If this member is defined by a parameterized super-type, return the | |||
// erasure | |||
// * of that member. | |||
// * For example: | |||
// * interface I<T> { T foo(T aTea); } | |||
@@ -160,8 +170,10 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe | |||
// public ResolvedMember getErasure(); | |||
/** | |||
* Returns true if this member matches the other. The matching takes into account name and parameter types only. When comparing | |||
* parameter types, we allow any type variable to match any other type variable regardless of bounds. | |||
* Returns true if this member matches the other. The matching takes into | |||
* account name and parameter types only. When comparing parameter types, we | |||
* allow any type variable to match any other type variable regardless of | |||
* bounds. | |||
*/ | |||
public boolean matches(ResolvedMember aCandidateMatch); | |||
@@ -26,27 +26,32 @@ import java.util.Set; | |||
import org.aspectj.bridge.ISourceLocation; | |||
/** | |||
* This is the declared member, i.e. it will always correspond to an actual method/... declaration | |||
* This is the declared member, i.e. it will always correspond to an actual | |||
* method/... declaration | |||
*/ | |||
public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, AnnotatedElement, TypeVariableDeclaringElement, | |||
ResolvedMember { | |||
public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, | |||
AnnotatedElement, TypeVariableDeclaringElement, ResolvedMember { | |||
private String[] parameterNames = null; | |||
protected UnresolvedType[] checkedExceptions = UnresolvedType.NONE; | |||
/** | |||
* if this member is a parameterized version of a member in a generic type, then this field holds a reference to the member we | |||
* parameterize. | |||
* if this member is a parameterized version of a member in a generic type, | |||
* then this field holds a reference to the member we parameterize. | |||
*/ | |||
protected ResolvedMember backingGenericMember = null; | |||
protected Set annotationTypes = null; | |||
protected ResolvedType[][] parameterAnnotationTypes = null; | |||
// Some members are 'created' to represent other things (for example ITDs). These | |||
// members have their annotations stored elsewhere, and this flag indicates that is | |||
// Some members are 'created' to represent other things (for example ITDs). | |||
// These | |||
// members have their annotations stored elsewhere, and this flag indicates | |||
// that is | |||
// the case. It is up to the caller to work out where that is! | |||
// Once determined the caller may choose to stash the annotations in this member... | |||
private boolean isAnnotatedElsewhere = false; // this field is not serialized. | |||
// Once determined the caller may choose to stash the annotations in this | |||
// member... | |||
private boolean isAnnotatedElsewhere = false; // this field is not | |||
// serialized. | |||
private boolean isAjSynthetic = false; | |||
// generic methods have type variables | |||
@@ -57,33 +62,43 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
protected ISourceContext sourceContext = null; | |||
// XXX deprecate this in favor of the constructor below | |||
public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name, | |||
public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, | |||
int modifiers, UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes) { | |||
super(kind, declaringType, modifiers, returnType, name, parameterTypes); | |||
} | |||
public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name, | |||
public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, | |||
int modifiers, UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions) { | |||
super(kind, declaringType, modifiers, returnType, name, parameterTypes); | |||
this.checkedExceptions = checkedExceptions; | |||
} | |||
public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions, ResolvedMember backingGenericMember) { | |||
this(kind, declaringType, modifiers, returnType, name, parameterTypes, checkedExceptions); | |||
public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, | |||
int modifiers, UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes, | |||
UnresolvedType[] checkedExceptions, | |||
ResolvedMember backingGenericMember) { | |||
this(kind, declaringType, modifiers, returnType, name, parameterTypes, | |||
checkedExceptions); | |||
this.backingGenericMember = backingGenericMember; | |||
this.isAjSynthetic = backingGenericMember.isAjSynthetic(); | |||
} | |||
public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, String name, String signature) { | |||
public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, | |||
int modifiers, String name, String signature) { | |||
super(kind, declaringType, modifiers, name, signature); | |||
} | |||
/** | |||
* Compute the full set of signatures for a member. This walks up the hierarchy giving the ResolvedMember in each defining type | |||
* in the hierarchy. A shadowMember can be created with a target type (declaring type) that does not actually define the member. | |||
* This is ok as long as the member is inherited in the declaring type. Each declaring type in the line to the actual declaring | |||
* type is added as an additional signature. For example: | |||
* Compute the full set of signatures for a member. This walks up the | |||
* hierarchy giving the ResolvedMember in each defining type in the | |||
* hierarchy. A shadowMember can be created with a target type (declaring | |||
* type) that does not actually define the member. This is ok as long as the | |||
* member is inherited in the declaring type. Each declaring type in the | |||
* line to the actual declaring type is added as an additional signature. | |||
* For example: | |||
* | |||
* class A { void foo(); } class B extends A {} | |||
* | |||
@@ -94,19 +109,26 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
* @param joinPointSignature | |||
* @param inAWorld | |||
*/ | |||
public static JoinPointSignature[] getJoinPointSignatures(Member joinPointSignature, World inAWorld) { | |||
public static JoinPointSignature[] getJoinPointSignatures( | |||
Member joinPointSignature, World inAWorld) { | |||
// Walk up hierarchy creating one member for each type up to and including the | |||
// Walk up hierarchy creating one member for each type up to and | |||
// including the | |||
// first defining type | |||
ResolvedType originalDeclaringType = joinPointSignature.getDeclaringType().resolve(inAWorld); | |||
ResolvedMemberImpl firstDefiningMember = (ResolvedMemberImpl) joinPointSignature.resolve(inAWorld); | |||
ResolvedType originalDeclaringType = joinPointSignature | |||
.getDeclaringType().resolve(inAWorld); | |||
ResolvedMemberImpl firstDefiningMember = (ResolvedMemberImpl) joinPointSignature | |||
.resolve(inAWorld); | |||
if (firstDefiningMember == null) { | |||
return new JoinPointSignature[0]; | |||
} | |||
// declaringType can be unresolved if we matched a synthetic member generated by Aj... | |||
// should be fixed elsewhere but add this resolve call on the end for now so that we can | |||
// declaringType can be unresolved if we matched a synthetic member | |||
// generated by Aj... | |||
// should be fixed elsewhere but add this resolve call on the end for | |||
// now so that we can | |||
// focus on one problem at a time... | |||
ResolvedType firstDefiningType = firstDefiningMember.getDeclaringType().resolve(inAWorld); | |||
ResolvedType firstDefiningType = firstDefiningMember.getDeclaringType() | |||
.resolve(inAWorld); | |||
if (firstDefiningType != originalDeclaringType) { | |||
if (joinPointSignature.getKind() == Member.CONSTRUCTOR) { | |||
return new JoinPointSignature[0]; | |||
@@ -117,23 +139,30 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
List declaringTypes = new ArrayList(); | |||
accumulateTypesInBetween(originalDeclaringType, firstDefiningType, declaringTypes); | |||
accumulateTypesInBetween(originalDeclaringType, firstDefiningType, | |||
declaringTypes); | |||
Set memberSignatures = new HashSet(); | |||
for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) { | |||
ResolvedType declaringType = (ResolvedType) iter.next(); | |||
ResolvedMember member = firstDefiningMember.withSubstituteDeclaringType(declaringType); | |||
ResolvedMember member = firstDefiningMember | |||
.withSubstituteDeclaringType(declaringType); | |||
memberSignatures.add(member); | |||
} | |||
if (shouldWalkUpHierarchyFor(firstDefiningMember)) { | |||
// now walk up the hierarchy from the firstDefiningMember and include the signature for | |||
// every type between the firstDefiningMember and the root defining member. | |||
Iterator superTypeIterator = firstDefiningType.getDirectSupertypes(); | |||
// now walk up the hierarchy from the firstDefiningMember and | |||
// include the signature for | |||
// every type between the firstDefiningMember and the root defining | |||
// member. | |||
Iterator superTypeIterator = firstDefiningType | |||
.getDirectSupertypes(); | |||
List typesAlreadyVisited = new ArrayList(); | |||
accumulateMembersMatching(firstDefiningMember, superTypeIterator, typesAlreadyVisited, memberSignatures); | |||
accumulateMembersMatching(firstDefiningMember, superTypeIterator, | |||
typesAlreadyVisited, memberSignatures); | |||
} | |||
JoinPointSignature[] ret = new JoinPointSignature[memberSignatures.size()]; | |||
JoinPointSignature[] ret = new JoinPointSignature[memberSignatures | |||
.size()]; | |||
memberSignatures.toArray(ret); | |||
return ret; | |||
} | |||
@@ -149,9 +178,11 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
/** | |||
* Build a list containing every type between subtype and supertype, inclusively. | |||
* Build a list containing every type between subtype and supertype, | |||
* inclusively. | |||
*/ | |||
private static void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List types) { | |||
private static void accumulateTypesInBetween(ResolvedType subType, | |||
ResolvedType superType, List types) { | |||
types.add(subType); | |||
if (subType == superType) { | |||
return; | |||
@@ -166,48 +197,67 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
/** | |||
* We have a resolved member, possibly with type parameter references as parameters or return type. We need to find all its | |||
* ancestor members. When doing this, a type parameter matches regardless of bounds (bounds can be narrowed down the hierarchy). | |||
* We have a resolved member, possibly with type parameter references as | |||
* parameters or return type. We need to find all its ancestor members. When | |||
* doing this, a type parameter matches regardless of bounds (bounds can be | |||
* narrowed down the hierarchy). | |||
*/ | |||
private static void accumulateMembersMatching(ResolvedMemberImpl memberToMatch, Iterator typesToLookIn, | |||
private static void accumulateMembersMatching( | |||
ResolvedMemberImpl memberToMatch, Iterator typesToLookIn, | |||
List typesAlreadyVisited, Set foundMembers) { | |||
while (typesToLookIn.hasNext()) { | |||
ResolvedType toLookIn = (ResolvedType) typesToLookIn.next(); | |||
if (!typesAlreadyVisited.contains(toLookIn)) { | |||
typesAlreadyVisited.add(toLookIn); | |||
ResolvedMemberImpl foundMember = (ResolvedMemberImpl) toLookIn.lookupResolvedMember(memberToMatch, true); | |||
if (foundMember != null && isVisibleTo(memberToMatch, foundMember)) { | |||
ResolvedMemberImpl foundMember = (ResolvedMemberImpl) toLookIn | |||
.lookupResolvedMember(memberToMatch, true); | |||
if (foundMember != null | |||
&& isVisibleTo(memberToMatch, foundMember)) { | |||
List declaringTypes = new ArrayList(); | |||
// declaring type can be unresolved if the member can from an ITD... | |||
ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(toLookIn.getWorld()); | |||
accumulateTypesInBetween(toLookIn, resolvedDeclaringType, declaringTypes); | |||
for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) { | |||
// declaring type can be unresolved if the member can from | |||
// an ITD... | |||
ResolvedType resolvedDeclaringType = foundMember | |||
.getDeclaringType().resolve(toLookIn.getWorld()); | |||
accumulateTypesInBetween(toLookIn, resolvedDeclaringType, | |||
declaringTypes); | |||
for (Iterator iter = declaringTypes.iterator(); iter | |||
.hasNext();) { | |||
ResolvedType declaringType = (ResolvedType) iter.next(); | |||
// typesAlreadyVisited.add(declaringType); | |||
ResolvedMember member = foundMember.withSubstituteDeclaringType(declaringType); | |||
ResolvedMember member = foundMember | |||
.withSubstituteDeclaringType(declaringType); | |||
foundMembers.add(member); | |||
} | |||
if (toLookIn.isParameterizedType() && (foundMember.backingGenericMember != null)) { | |||
foundMembers.add(new JoinPointSignature(foundMember.backingGenericMember, foundMember.declaringType | |||
.resolve(toLookIn.getWorld()))); | |||
if (toLookIn.isParameterizedType() | |||
&& (foundMember.backingGenericMember != null)) { | |||
foundMembers.add(new JoinPointSignature( | |||
foundMember.backingGenericMember, | |||
foundMember.declaringType.resolve(toLookIn | |||
.getWorld()))); | |||
} | |||
accumulateMembersMatching(foundMember, toLookIn.getDirectSupertypes(), typesAlreadyVisited, foundMembers); | |||
// if this was a parameterized type, look in the generic type that backs it too | |||
accumulateMembersMatching(foundMember, toLookIn | |||
.getDirectSupertypes(), typesAlreadyVisited, | |||
foundMembers); | |||
// if this was a parameterized type, look in the generic | |||
// type that backs it too | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Returns true if the parent member is visible to the child member In the same declaring type this is always true, otherwise if | |||
* parent is private it is false. | |||
* Returns true if the parent member is visible to the child member In the | |||
* same declaring type this is always true, otherwise if parent is private | |||
* it is false. | |||
* | |||
* @param childMember | |||
* @param parentMember | |||
* @return | |||
*/ | |||
private static boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) { | |||
if (childMember.getDeclaringType().equals(parentMember.getDeclaringType())) | |||
private static boolean isVisibleTo(ResolvedMember childMember, | |||
ResolvedMember parentMember) { | |||
if (childMember.getDeclaringType().equals( | |||
parentMember.getDeclaringType())) | |||
return true; | |||
if (Modifier.isPrivate(parentMember.getModifiers())) { | |||
return false; | |||
@@ -254,12 +304,15 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
/** | |||
* Check if this member has an annotation of the specified type. If the member has a backing generic member then this member | |||
* represents a parameterization of a member in a generic type and the annotations available on the backing generic member | |||
* should be used. | |||
* Check if this member has an annotation of the specified type. If the | |||
* member has a backing generic member then this member represents a | |||
* parameterization of a member in a generic type and the annotations | |||
* available on the backing generic member should be used. | |||
* | |||
* @param ofType the type of the annotation being searched for | |||
* @return true if the annotation is found on this member or its backing generic member | |||
* @param ofType | |||
* the type of the annotation being searched for | |||
* @return true if the annotation is found on this member or its backing | |||
* generic member | |||
*/ | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
// The ctors don't allow annotations to be specified ... yet - but | |||
@@ -268,7 +321,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
// this type - BcelField/BcelMethod | |||
if (backingGenericMember != null) { | |||
if (annotationTypes != null) { | |||
throw new BCException("Unexpectedly found a backing generic member and a local set of annotations"); | |||
throw new BCException( | |||
"Unexpectedly found a backing generic member and a local set of annotations"); | |||
} | |||
return backingGenericMember.hasAnnotation(ofType); | |||
} | |||
@@ -285,7 +339,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
// this type - BcelField/BcelMethod | |||
if (backingGenericMember != null) { | |||
if (annotationTypes != null) { | |||
throw new BCException("Unexpectedly found a backing generic member and a local set of annotations"); | |||
throw new BCException( | |||
"Unexpectedly found a backing generic member and a local set of annotations"); | |||
} | |||
return backingGenericMember.getAnnotationTypes(); | |||
} | |||
@@ -299,7 +354,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
"You should resolve this member and call getAnnotationDefaultValue() on the result..."); | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
if (backingGenericMember != null) | |||
return backingGenericMember.getAnnotations(); | |||
return super.getAnnotations(); | |||
@@ -320,22 +375,25 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
return parameterAnnotationTypes; | |||
} | |||
public AnnotationX[][] getParameterAnnotations() { | |||
public AnnotationAJ[][] getParameterAnnotations() { | |||
if (backingGenericMember != null) | |||
return backingGenericMember.getParameterAnnotations(); | |||
throw new BCException("Cannot return parameter annotations for a " + this.getClass().getName() + " member"); | |||
throw new BCException("Cannot return parameter annotations for a " | |||
+ this.getClass().getName() + " member"); | |||
// return super.getParameterAnnotations(); | |||
} | |||
public void addAnnotation(AnnotationX annotation) { | |||
// FIXME asc only allows for annotation types, not instances - should it? | |||
public void addAnnotation(AnnotationAJ annotation) { | |||
// FIXME asc only allows for annotation types, not instances - should | |||
// it? | |||
if (annotationTypes == null) | |||
annotationTypes = new HashSet(); | |||
annotationTypes.add(annotation.getSignature()); | |||
annotationTypes.add(annotation.getType()); | |||
} | |||
public boolean isBridgeMethod() { | |||
return (modifiers & Constants.ACC_BRIDGE) != 0 && getKind().equals(METHOD); | |||
return (modifiers & Constants.ACC_BRIDGE) != 0 | |||
&& getKind().equals(METHOD); | |||
} | |||
public boolean isVarargsMethod() { | |||
@@ -347,7 +405,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
public boolean isSynthetic() { | |||
// See Bcelmethod.isSynthetic() which takes account of preJava5 Synthetic modifier | |||
// See Bcelmethod.isSynthetic() which takes account of preJava5 | |||
// Synthetic modifier | |||
return (modifiers & 4096) != 0; // do we know better? | |||
} | |||
@@ -387,17 +446,22 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
/** | |||
* Return the member generic signature that would be suitable for inclusion in a class file Signature attribute. For: <T> | |||
* List<String> getThem(T t) {} we would create: <T:Ljava/lang/Object;>(TT;)Ljava/util/List<Ljava/lang/String;>;; | |||
* Return the member generic signature that would be suitable for inclusion | |||
* in a class file Signature attribute. For: <T> List<String> getThem(T t) | |||
* {} we would create: | |||
* <T:Ljava/lang/Object;>(TT;)Ljava/util/List<Ljava/lang/String;>;; | |||
* | |||
* @return the generic signature for the member that could be inserted into a class file | |||
* @return the generic signature for the member that could be inserted into | |||
* a class file | |||
*/ | |||
public String getSignatureForAttribute() { | |||
StringBuffer sb = new StringBuffer(); | |||
if (typeVariables != null) { | |||
sb.append("<"); | |||
for (int i = 0; i < typeVariables.length; i++) { | |||
sb.append(typeVariables[i].getSignatureForAttribute()); // need a 'getSignatureForAttribute()' | |||
sb.append(typeVariables[i].getSignatureForAttribute()); // need | |||
// a | |||
// 'getSignatureForAttribute()' | |||
} | |||
sb.append(">"); | |||
} | |||
@@ -430,18 +494,20 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
return sb.toString(); | |||
} | |||
public static void writeArray(ResolvedMember[] members, DataOutputStream s) throws IOException { | |||
public static void writeArray(ResolvedMember[] members, DataOutputStream s) | |||
throws IOException { | |||
s.writeInt(members.length); | |||
for (int i = 0, len = members.length; i < len; i++) { | |||
members[i].write(s); | |||
} | |||
} | |||
public static ResolvedMemberImpl readResolvedMember(VersionedDataInputStream s, ISourceContext sourceContext) | |||
public static ResolvedMemberImpl readResolvedMember( | |||
VersionedDataInputStream s, ISourceContext sourceContext) | |||
throws IOException { | |||
ResolvedMemberImpl m = new ResolvedMemberImpl(MemberKind.read(s), UnresolvedType.read(s), s.readInt(), s.readUTF(), s | |||
.readUTF()); | |||
ResolvedMemberImpl m = new ResolvedMemberImpl(MemberKind.read(s), | |||
UnresolvedType.read(s), s.readInt(), s.readUTF(), s.readUTF()); | |||
m.checkedExceptions = UnresolvedType.readArray(s); | |||
m.start = s.readInt(); | |||
@@ -470,9 +536,11 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
int ps = s.readInt(); | |||
UnresolvedType[] params = new UnresolvedType[ps]; | |||
for (int i = 0; i < params.length; i++) { | |||
params[i] = TypeFactory.createTypeFromSignature(s.readUTF()); | |||
params[i] = TypeFactory.createTypeFromSignature(s | |||
.readUTF()); | |||
} | |||
UnresolvedType rt = TypeFactory.createTypeFromSignature(s.readUTF()); | |||
UnresolvedType rt = TypeFactory.createTypeFromSignature(s | |||
.readUTF()); | |||
m.parameterTypes = params; | |||
m.returnType = rt; | |||
} | |||
@@ -481,7 +549,9 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
return m; | |||
} | |||
public static ResolvedMember[] readResolvedMemberArray(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
public static ResolvedMember[] readResolvedMemberArray( | |||
VersionedDataInputStream s, ISourceContext context) | |||
throws IOException { | |||
int len = s.readInt(); | |||
ResolvedMember[] members = new ResolvedMember[len]; | |||
for (int i = 0; i < len; i++) { | |||
@@ -490,7 +560,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
return members; | |||
} | |||
// OPTIMIZE dont like how resolve(world) on ResolvedMemberImpl does something different to world.resolve(member) | |||
// OPTIMIZE dont like how resolve(world) on ResolvedMemberImpl does | |||
// something different to world.resolve(member) | |||
public ResolvedMember resolve(World world) { | |||
// make sure all the pieces of a resolvedmember really are resolved | |||
try { | |||
@@ -510,7 +581,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
declaringType = declaringType.resolve(world); | |||
if (declaringType.isRawType()) | |||
declaringType = ((ReferenceType) declaringType).getGenericType(); | |||
declaringType = ((ReferenceType) declaringType) | |||
.getGenericType(); | |||
if (parameterTypes != null && parameterTypes.length > 0) { | |||
for (int i = 0; i < parameterTypes.length; i++) { | |||
@@ -602,7 +674,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
public boolean isVisible(ResolvedType fromType) { | |||
World world = fromType.getWorld(); | |||
return ResolvedType.isVisible(getModifiers(), getDeclaringType().resolve(world), fromType); | |||
return ResolvedType.isVisible(getModifiers(), getDeclaringType() | |||
.resolve(world), fromType); | |||
} | |||
public void setCheckedExceptions(UnresolvedType[] checkedExceptions) { | |||
@@ -618,70 +691,89 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
/** | |||
* Get the UnresolvedType for the return type, taking generic signature into account | |||
* Get the UnresolvedType for the return type, taking generic signature into | |||
* account | |||
*/ | |||
public UnresolvedType getGenericReturnType() { | |||
return getReturnType(); | |||
} | |||
/** | |||
* Get the TypeXs of the parameter types, taking generic signature into account | |||
* Get the TypeXs of the parameter types, taking generic signature into | |||
* account | |||
*/ | |||
public UnresolvedType[] getGenericParameterTypes() { | |||
return getParameterTypes(); | |||
} | |||
public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized) { | |||
return parameterizedWith(typeParameters, newDeclaringType, isParameterized, null); | |||
return parameterizedWith(typeParameters, newDeclaringType, | |||
isParameterized, null); | |||
} | |||
/** | |||
* Return a resolvedmember in which all the type variables in the signature have been replaced with the given bindings. The | |||
* 'isParameterized' flag tells us whether we are creating a raw type version or not. if (isParameterized) then List<T> will | |||
* turn into List<String> (for example) - if (!isParameterized) then List<T> will turn into List. | |||
* Return a resolvedmember in which all the type variables in the signature | |||
* have been replaced with the given bindings. The 'isParameterized' flag | |||
* tells us whether we are creating a raw type version or not. if | |||
* (isParameterized) then List<T> will turn into List<String> (for example) | |||
* - if (!isParameterized) then List<T> will turn into List. | |||
*/ | |||
public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
public ResolvedMemberImpl parameterizedWith( | |||
UnresolvedType[] typeParameters, ResolvedType newDeclaringType, | |||
boolean isParameterized, List aliases) { | |||
if (// isParameterized && <-- might need this bit... | |||
!getDeclaringType().isGenericType()) { | |||
throw new IllegalStateException("Can't ask to parameterize a member of non-generic type: " + getDeclaringType() | |||
+ " kind(" + getDeclaringType().typeKind + ")"); | |||
throw new IllegalStateException( | |||
"Can't ask to parameterize a member of non-generic type: " | |||
+ getDeclaringType() + " kind(" | |||
+ getDeclaringType().typeKind + ")"); | |||
} | |||
TypeVariable[] typeVariables = getDeclaringType().getTypeVariables(); | |||
if (isParameterized && (typeVariables.length != typeParameters.length)) { | |||
throw new IllegalStateException("Wrong number of type parameters supplied"); | |||
throw new IllegalStateException( | |||
"Wrong number of type parameters supplied"); | |||
} | |||
Map typeMap = new HashMap(); | |||
boolean typeParametersSupplied = typeParameters != null && typeParameters.length > 0; | |||
boolean typeParametersSupplied = typeParameters != null | |||
&& typeParameters.length > 0; | |||
if (typeVariables != null) { | |||
// If no 'replacements' were supplied in the typeParameters array then collapse | |||
// If no 'replacements' were supplied in the typeParameters array | |||
// then collapse | |||
// type variables to their first bound. | |||
for (int i = 0; i < typeVariables.length; i++) { | |||
UnresolvedType ut = (!typeParametersSupplied ? typeVariables[i].getFirstBound() : typeParameters[i]); | |||
UnresolvedType ut = (!typeParametersSupplied ? typeVariables[i] | |||
.getFirstBound() : typeParameters[i]); | |||
typeMap.put(typeVariables[i].getName(), ut); | |||
} | |||
} | |||
// For ITDs on generic types that use type variables from the target type, the aliases | |||
// record the alternative names used throughout the ITD expression that must map to | |||
// For ITDs on generic types that use type variables from the target | |||
// type, the aliases | |||
// record the alternative names used throughout the ITD expression that | |||
// must map to | |||
// the same value as the type variables real name. | |||
if (aliases != null) { | |||
int posn = 0; | |||
for (Iterator iter = aliases.iterator(); iter.hasNext();) { | |||
String typeVariableAlias = (String) iter.next(); | |||
typeMap.put(typeVariableAlias, (!typeParametersSupplied ? typeVariables[posn].getFirstBound() | |||
: typeParameters[posn])); | |||
typeMap.put(typeVariableAlias, | |||
(!typeParametersSupplied ? typeVariables[posn] | |||
.getFirstBound() : typeParameters[posn])); | |||
posn++; | |||
} | |||
} | |||
UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(), typeMap, isParameterized); | |||
UnresolvedType parameterizedReturnType = parameterize( | |||
getGenericReturnType(), typeMap, isParameterized); | |||
UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length]; | |||
UnresolvedType[] genericParameterTypes = getGenericParameterTypes(); | |||
for (int i = 0; i < parameterizedParameterTypes.length; i++) { | |||
parameterizedParameterTypes[i] = parameterize(genericParameterTypes[i], typeMap, isParameterized); | |||
parameterizedParameterTypes[i] = parameterize( | |||
genericParameterTypes[i], typeMap, isParameterized); | |||
} | |||
ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), newDeclaringType, getModifiers(), parameterizedReturnType, | |||
ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), | |||
newDeclaringType, getModifiers(), parameterizedReturnType, | |||
getName(), parameterizedParameterTypes, getExceptions(), this); | |||
ret.setTypeVariables(getTypeVariables()); | |||
ret.setSourceContext(getSourceContext()); | |||
@@ -691,51 +783,67 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
/** | |||
* Replace occurrences of type variables in the signature with values contained in the map. The map is of the form | |||
* A=String,B=Integer and so a signature List<A> Foo.m(B i) {} would become List<String> Foo.m(Integer i) {} | |||
* Replace occurrences of type variables in the signature with values | |||
* contained in the map. The map is of the form A=String,B=Integer and so a | |||
* signature List<A> Foo.m(B i) {} would become List<String> Foo.m(Integer | |||
* i) {} | |||
*/ | |||
public ResolvedMember parameterizedWith(Map m, World w) { | |||
// if (//isParameterized && <-- might need this bit... | |||
// !getDeclaringType().isGenericType()) { | |||
// throw new IllegalStateException("Can't ask to parameterize a member of non-generic type: "+getDeclaringType()+" kind("+ | |||
// throw new IllegalStateException( | |||
// "Can't ask to parameterize a member of non-generic type: " | |||
// +getDeclaringType()+" kind("+ | |||
// getDeclaringType().typeKind+")"); | |||
// } | |||
declaringType = declaringType.resolve(w); | |||
if (declaringType.isRawType()) | |||
declaringType = ((ResolvedType) declaringType).getGenericType(); | |||
// TypeVariable[] typeVariables = getDeclaringType().getTypeVariables(); | |||
// if (isParameterized && (typeVariables.length != typeParameters.length)) { | |||
// throw new IllegalStateException("Wrong number of type parameters supplied"); | |||
// if (isParameterized && (typeVariables.length != | |||
// typeParameters.length)) { | |||
// throw new | |||
// IllegalStateException("Wrong number of type parameters supplied"); | |||
// } | |||
// Map typeMap = new HashMap(); | |||
// boolean typeParametersSupplied = typeParameters!=null && typeParameters.length>0; | |||
// boolean typeParametersSupplied = typeParameters!=null && | |||
// typeParameters.length>0; | |||
// if (typeVariables!=null) { | |||
// // If no 'replacements' were supplied in the typeParameters array then collapse | |||
// // If no 'replacements' were supplied in the typeParameters array | |||
// then collapse | |||
// // type variables to their first bound. | |||
// for (int i = 0; i < typeVariables.length; i++) { | |||
// UnresolvedType ut = (!typeParametersSupplied?typeVariables[i].getFirstBound():typeParameters[i]); | |||
// UnresolvedType ut = | |||
// (!typeParametersSupplied?typeVariables[i].getFirstBound | |||
// ():typeParameters[i]); | |||
// typeMap.put(typeVariables[i].getName(),ut); | |||
// } | |||
// } | |||
// // For ITDs on generic types that use type variables from the target type, the aliases | |||
// // record the alternative names used throughout the ITD expression that must map to | |||
// // For ITDs on generic types that use type variables from the target | |||
// type, the aliases | |||
// // record the alternative names used throughout the ITD expression | |||
// that must map to | |||
// // the same value as the type variables real name. | |||
// if (aliases!=null) { | |||
// int posn = 0; | |||
// for (Iterator iter = aliases.iterator(); iter.hasNext();) { | |||
// String typeVariableAlias = (String) iter.next(); | |||
// typeMap.put(typeVariableAlias,(!typeParametersSupplied?typeVariables[posn].getFirstBound():typeParameters[posn])); | |||
// typeMap.put(typeVariableAlias,(!typeParametersSupplied?typeVariables[ | |||
// posn].getFirstBound():typeParameters[posn])); | |||
// posn++; | |||
// } | |||
// } | |||
UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(), m, true, w); | |||
UnresolvedType parameterizedReturnType = parameterize( | |||
getGenericReturnType(), m, true, w); | |||
UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length]; | |||
UnresolvedType[] genericParameterTypes = getGenericParameterTypes(); | |||
for (int i = 0; i < parameterizedParameterTypes.length; i++) { | |||
parameterizedParameterTypes[i] = parameterize(genericParameterTypes[i], m, true, w); | |||
parameterizedParameterTypes[i] = parameterize( | |||
genericParameterTypes[i], m, true, w); | |||
} | |||
ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), declaringType, getModifiers(), parameterizedReturnType, | |||
ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), | |||
declaringType, getModifiers(), parameterizedReturnType, | |||
getName(), parameterizedParameterTypes, getExceptions(), this); | |||
ret.setTypeVariables(getTypeVariables()); | |||
ret.setSourceContext(getSourceContext()); | |||
@@ -752,15 +860,19 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
return typeVariables; | |||
} | |||
protected UnresolvedType parameterize(UnresolvedType aType, Map typeVariableMap, boolean inParameterizedType) { | |||
protected UnresolvedType parameterize(UnresolvedType aType, | |||
Map typeVariableMap, boolean inParameterizedType) { | |||
return parameterize(aType, typeVariableMap, inParameterizedType, null); | |||
} | |||
protected UnresolvedType parameterize(UnresolvedType aType, Map typeVariableMap, boolean inParameterizedType, World w) { | |||
protected UnresolvedType parameterize(UnresolvedType aType, | |||
Map typeVariableMap, boolean inParameterizedType, World w) { | |||
if (aType instanceof TypeVariableReference) { | |||
String variableName = ((TypeVariableReference) aType).getTypeVariable().getName(); | |||
String variableName = ((TypeVariableReference) aType) | |||
.getTypeVariable().getName(); | |||
if (!typeVariableMap.containsKey(variableName)) { | |||
return aType; // if the type variable comes from the method (and not the type) thats OK | |||
return aType; // if the type variable comes from the method (and | |||
// not the type) thats OK | |||
} | |||
return (UnresolvedType) typeVariableMap.get(variableName); | |||
} else if (aType.isParameterizedType()) { | |||
@@ -772,7 +884,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
if (w != null) | |||
aType = aType.resolve(w); | |||
else { | |||
aType = aType.resolve(((ResolvedType) getDeclaringType()).getWorld()); | |||
aType = aType.resolve(((ResolvedType) getDeclaringType()) | |||
.getWorld()); | |||
} | |||
// } | |||
return aType.parameterize(typeVariableMap); | |||
@@ -785,19 +898,22 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
String sig = aType.getSignature(); | |||
while (sig.charAt(dims) == '[') | |||
dims++; | |||
UnresolvedType componentSig = UnresolvedType.forSignature(sig.substring(dims)); | |||
UnresolvedType arrayType = ResolvedType.makeArray(parameterize(componentSig, typeVariableMap, inParameterizedType), | |||
dims); | |||
UnresolvedType componentSig = UnresolvedType.forSignature(sig | |||
.substring(dims)); | |||
UnresolvedType arrayType = ResolvedType.makeArray(parameterize( | |||
componentSig, typeVariableMap, inParameterizedType), dims); | |||
return arrayType; | |||
} | |||
return aType; | |||
} | |||
/** | |||
* If this member is defined by a parameterized super-type, return the erasure of that member. For example: interface I<T> { T | |||
* foo(T aTea); } class C implements I<String> { String foo(String aString) { return "something"; } } The resolved member for | |||
* C.foo has signature String foo(String). The erasure of that member is Object foo(Object) -- use upper bound of type variable. | |||
* A type is a supertype of itself. | |||
* If this member is defined by a parameterized super-type, return the | |||
* erasure of that member. For example: interface I<T> { T foo(T aTea); } | |||
* class C implements I<String> { String foo(String aString) { return | |||
* "something"; } } The resolved member for C.foo has signature String | |||
* foo(String). The erasure of that member is Object foo(Object) -- use | |||
* upper bound of type variable. A type is a supertype of itself. | |||
*/ | |||
// public ResolvedMember getErasure() { | |||
// if (calculatedMyErasure) return myErasure; | |||
@@ -809,14 +925,17 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
// } else { | |||
// // we have one or more parameterized super types. | |||
// // this member may be defined by one of them... we need to find out. | |||
// Collection declaringTypes = this.getDeclaringTypes(resolvedDeclaringType.getWorld()); | |||
// Collection declaringTypes = | |||
// this.getDeclaringTypes(resolvedDeclaringType.getWorld()); | |||
// for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) { | |||
// ResolvedType aDeclaringType = (ResolvedType) iter.next(); | |||
// if (aDeclaringType.isParameterizedType()) { | |||
// // we've found the (a?) parameterized type that defines this member. | |||
// // now get the erasure of it | |||
// ResolvedMemberImpl matchingMember = (ResolvedMemberImpl) aDeclaringType.lookupMemberNoSupers(this); | |||
// if (matchingMember != null && matchingMember.backingGenericMember != null) { | |||
// ResolvedMemberImpl matchingMember = (ResolvedMemberImpl) | |||
// aDeclaringType.lookupMemberNoSupers(this); | |||
// if (matchingMember != null && matchingMember.backingGenericMember != | |||
// null) { | |||
// myErasure = matchingMember.backingGenericMember; | |||
// return myErasure; | |||
// } | |||
@@ -837,8 +956,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
/** | |||
* For ITDs, we use the default factory methods to build a resolved member, then alter a couple of characteristics using this | |||
* method - this is safe. | |||
* For ITDs, we use the default factory methods to build a resolved member, | |||
* then alter a couple of characteristics using this method - this is safe. | |||
*/ | |||
public void resetName(String newName) { | |||
this.name = newName; | |||
@@ -857,41 +976,49 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
} | |||
/** | |||
* Returns a copy of this member but with the declaring type swapped. Copy only needs to be shallow. | |||
* Returns a copy of this member but with the declaring type swapped. Copy | |||
* only needs to be shallow. | |||
* | |||
* @param newDeclaringType | |||
*/ | |||
public JoinPointSignature withSubstituteDeclaringType(ResolvedType newDeclaringType) { | |||
public JoinPointSignature withSubstituteDeclaringType( | |||
ResolvedType newDeclaringType) { | |||
JoinPointSignature ret = new JoinPointSignature(this, newDeclaringType); | |||
return ret; | |||
} | |||
/** | |||
* Returns true if this member matches the other. The matching takes into account name and parameter types only. When comparing | |||
* parameter types, we allow any type variable to match any other type variable regardless of bounds. | |||
* Returns true if this member matches the other. The matching takes into | |||
* account name and parameter types only. When comparing parameter types, we | |||
* allow any type variable to match any other type variable regardless of | |||
* bounds. | |||
*/ | |||
public boolean matches(ResolvedMember aCandidateMatch) { | |||
ResolvedMemberImpl candidateMatchImpl = (ResolvedMemberImpl) aCandidateMatch; | |||
if (!getName().equals(aCandidateMatch.getName())) | |||
return false; | |||
UnresolvedType[] myParameterTypes = getGenericParameterTypes(); | |||
UnresolvedType[] candidateParameterTypes = aCandidateMatch.getGenericParameterTypes(); | |||
UnresolvedType[] candidateParameterTypes = aCandidateMatch | |||
.getGenericParameterTypes(); | |||
if (myParameterTypes.length != candidateParameterTypes.length) | |||
return false; | |||
String myParameterSignature = getParameterSigWithBoundsRemoved(); | |||
String candidateParameterSignature = candidateMatchImpl.getParameterSigWithBoundsRemoved(); | |||
String candidateParameterSignature = candidateMatchImpl | |||
.getParameterSigWithBoundsRemoved(); | |||
if (myParameterSignature.equals(candidateParameterSignature)) { | |||
return true; | |||
} else { | |||
// try erasure | |||
myParameterSignature = getParameterSignatureErased(); | |||
candidateParameterSignature = candidateMatchImpl.getParameterSignatureErased(); | |||
candidateParameterSignature = candidateMatchImpl | |||
.getParameterSignatureErased(); | |||
return myParameterSignature.equals(candidateParameterSignature); | |||
} | |||
} | |||
/** | |||
* converts e.g. <T extends Number>.... List<T> to just Ljava/util/List<T;>; whereas the full signature would be | |||
* converts e.g. <T extends Number>.... List<T> to just Ljava/util/List<T;>; | |||
* whereas the full signature would be | |||
* Ljava/util/List<T:Ljava/lang/Number;>; | |||
*/ | |||
private String myParameterSignatureWithBoundsRemoved = null; | |||
@@ -900,7 +1027,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
*/ | |||
private String myParameterSignatureErasure = null; | |||
// does NOT produce a meaningful java signature, but does give a unique string suitable for | |||
// does NOT produce a meaningful java signature, but does give a unique | |||
// string suitable for | |||
// comparison. | |||
private String getParameterSigWithBoundsRemoved() { | |||
if (myParameterSignatureWithBoundsRemoved != null) | |||
@@ -908,15 +1036,16 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
StringBuffer sig = new StringBuffer(); | |||
UnresolvedType[] myParameterTypes = getGenericParameterTypes(); | |||
for (int i = 0; i < myParameterTypes.length; i++) { | |||
appendSigWithTypeVarBoundsRemoved(myParameterTypes[i], sig, new HashSet()); | |||
appendSigWithTypeVarBoundsRemoved(myParameterTypes[i], sig, | |||
new HashSet()); | |||
} | |||
myParameterSignatureWithBoundsRemoved = sig.toString(); | |||
return myParameterSignatureWithBoundsRemoved; | |||
} | |||
/** | |||
* Return the erased form of the signature with bounds collapsed for type variables, etc. Does not include the return type, @see | |||
* getParam | |||
* Return the erased form of the signature with bounds collapsed for type | |||
* variables, etc. Does not include the return type, @see getParam | |||
*/ | |||
public String getParameterSignatureErased() { | |||
if (myParameterSignatureErasure != null) | |||
@@ -945,9 +1074,11 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
return sb.toString(); | |||
} | |||
// does NOT produce a meaningful java signature, but does give a unique string suitable for | |||
// does NOT produce a meaningful java signature, but does give a unique | |||
// string suitable for | |||
// comparison. | |||
public static void appendSigWithTypeVarBoundsRemoved(UnresolvedType aType, StringBuffer toBuffer, Set alreadyUsedTypeVars) { | |||
public static void appendSigWithTypeVarBoundsRemoved(UnresolvedType aType, | |||
StringBuffer toBuffer, Set alreadyUsedTypeVars) { | |||
if (aType.isTypeVariableReference()) { | |||
TypeVariableReferenceType typeVariableRT = (TypeVariableReferenceType) aType; | |||
// pr204505 | |||
@@ -955,14 +1086,16 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
toBuffer.append("..."); | |||
} else { | |||
alreadyUsedTypeVars.add(aType); | |||
appendSigWithTypeVarBoundsRemoved(typeVariableRT.getUpperBound(), toBuffer, alreadyUsedTypeVars); | |||
appendSigWithTypeVarBoundsRemoved(typeVariableRT | |||
.getUpperBound(), toBuffer, alreadyUsedTypeVars); | |||
} | |||
// toBuffer.append("T;"); | |||
} else if (aType.isParameterizedType()) { | |||
toBuffer.append(aType.getRawType().getSignature()); | |||
toBuffer.append("<"); | |||
for (int i = 0; i < aType.getTypeParameters().length; i++) { | |||
appendSigWithTypeVarBoundsRemoved(aType.getTypeParameters()[i], toBuffer, alreadyUsedTypeVars); | |||
appendSigWithTypeVarBoundsRemoved(aType.getTypeParameters()[i], | |||
toBuffer, alreadyUsedTypeVars); | |||
} | |||
toBuffer.append(">;"); | |||
} else { | |||
@@ -979,11 +1112,14 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
// modifiers | |||
int mods = modifiers; | |||
if ((mods & 4096) > 0) | |||
mods = mods - 4096; // remove synthetic (added in the ASM case but not in the BCEL case...) | |||
mods = mods - 4096; // remove synthetic (added in the ASM case but | |||
// not in the BCEL case...) | |||
if ((mods & 512) > 0) | |||
mods = mods - 512; // remove interface (added in the BCEL case but not in the ASM case...) | |||
mods = mods - 512; // remove interface (added in the BCEL case but | |||
// not in the ASM case...) | |||
if ((mods & 131072) > 0) | |||
mods = mods - 131072; // remove deprecated (added in the ASM case but not in the BCEL case...) | |||
mods = mods - 131072; // remove deprecated (added in the ASM case | |||
// but not in the BCEL case...) | |||
String modsStr = Modifier.toString(mods); | |||
if (modsStr.length() != 0) | |||
r.append(modsStr).append("(" + mods + ")").append(" "); | |||
@@ -1013,7 +1149,9 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
if (kind != FIELD) { | |||
r.append("("); | |||
UnresolvedType[] params = getGenericParameterTypes(); | |||
boolean parameterNamesExist = showParameterNames && parameterNames != null && parameterNames.length == params.length; | |||
boolean parameterNamesExist = showParameterNames | |||
&& parameterNames != null | |||
&& parameterNames.length == params.length; | |||
if (params.length != 0) { | |||
for (int i = 0, len = params.length; i < len; i++) { | |||
if (i > 0) | |||
@@ -1028,7 +1166,8 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
return r.toString(); | |||
} | |||
// SECRETAPI - controlling whether parameter names come out in the debug string (for testing purposes) | |||
// SECRETAPI - controlling whether parameter names come out in the debug | |||
// string (for testing purposes) | |||
public static boolean showParameterNames = true; | |||
public String toGenericString() { | |||
@@ -1085,14 +1224,16 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
// check the declaring type! | |||
return declaringType.getTypeVariableNamed(name); | |||
// Do generic aspects with ITDs that share type variables with the aspect and the target type and have their own tvars cause | |||
// Do generic aspects with ITDs that share type variables with the | |||
// aspect and the target type and have their own tvars cause | |||
// this to be messier? | |||
} | |||
public void evictWeavingState() { | |||
} | |||
public AnnotationX getAnnotationOfType(UnresolvedType ofType) { | |||
throw new UnsupportedOperationException("You should resolve this member and call getAnnotationOfType() on the result..."); | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
throw new UnsupportedOperationException( | |||
"You should resolve this member and call getAnnotationOfType() on the result..."); | |||
} | |||
} |
@@ -0,0 +1,139 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
/** | |||
* This type represents the weavers abstraction of an annotation - it is not tied to any underlying BCI toolkit. The weaver actualy | |||
* handles these through AnnotationX wrapper objects - until we start transforming the BCEL annotations into this form (expensive) | |||
* or offer a clever visitor mechanism over the BCEL annotation stuff that builds these annotation types directly. | |||
* | |||
* @author AndyClement | |||
*/ | |||
public class StandardAnnotation extends AbstractAnnotationAJ { | |||
private final boolean isRuntimeVisible; | |||
private List /* of AnnotationNVPair */nvPairs = null; | |||
public StandardAnnotation(ResolvedType type, boolean isRuntimeVisible) { | |||
super(type); | |||
this.isRuntimeVisible = isRuntimeVisible; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean isRuntimeVisible() { | |||
return isRuntimeVisible; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public String stringify() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("@").append(type.getClassName()); | |||
if (hasNameValuePairs()) { | |||
sb.append("("); | |||
for (Iterator iter = nvPairs.iterator(); iter.hasNext();) { | |||
AnnotationNameValuePair element = (AnnotationNameValuePair) iter.next(); | |||
sb.append(element.stringify()); | |||
} | |||
sb.append(")"); | |||
} | |||
return sb.toString(); | |||
} | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("ANNOTATION [" + getTypeSignature() + "] [" + (isRuntimeVisible ? "runtimeVisible" : "runtimeInvisible") + "] ["); | |||
if (nvPairs != null) { | |||
for (Iterator iter = nvPairs.iterator(); iter.hasNext();) { | |||
AnnotationNameValuePair element = (AnnotationNameValuePair) iter.next(); | |||
sb.append(element.toString()); | |||
if (iter.hasNext()) | |||
sb.append(","); | |||
} | |||
} | |||
sb.append("]"); | |||
return sb.toString(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean hasNamedValue(String n) { | |||
if (nvPairs == null) | |||
return false; | |||
for (int i = 0; i < nvPairs.size(); i++) { | |||
AnnotationNameValuePair pair = (AnnotationNameValuePair) nvPairs.get(i); | |||
if (pair.getName().equals(n)) | |||
return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean hasNameValuePair(String n, String v) { | |||
if (nvPairs == null) | |||
return false; | |||
for (int i = 0; i < nvPairs.size(); i++) { | |||
AnnotationNameValuePair pair = (AnnotationNameValuePair) nvPairs.get(i); | |||
if (pair.getName().equals(n)) { | |||
if (pair.getValue().stringify().equals(v)) | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public Set /* <String> */getTargets() { | |||
if (!type.equals(UnresolvedType.AT_TARGET)) { | |||
return Collections.EMPTY_SET; | |||
} | |||
AnnotationNameValuePair nvp = (AnnotationNameValuePair) nvPairs.get(0); | |||
ArrayAnnotationValue aav = (ArrayAnnotationValue) nvp.getValue(); | |||
AnnotationValue[] avs = aav.getValues(); | |||
Set targets = new HashSet(); | |||
for (int i = 0; i < avs.length; i++) { | |||
AnnotationValue value = avs[i]; | |||
targets.add(value.stringify()); | |||
} | |||
return targets; | |||
} | |||
public List getNameValuePairs() { | |||
return nvPairs; | |||
} | |||
public boolean hasNameValuePairs() { | |||
return nvPairs != null && nvPairs.size() != 0; | |||
} | |||
public void addNameValuePair(AnnotationNameValuePair pair) { | |||
if (nvPairs == null) { | |||
nvPairs = new ArrayList(); | |||
} | |||
nvPairs.add(pair); | |||
} | |||
} |
@@ -20,7 +20,7 @@ import org.aspectj.apache.bcel.classfile.annotation.EnumElementValueGen; | |||
import org.aspectj.apache.bcel.generic.InstructionFactory; | |||
import org.aspectj.apache.bcel.generic.InstructionList; | |||
import org.aspectj.apache.bcel.generic.Type; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedType; | |||
@@ -45,16 +45,18 @@ class AnnotationAccessFieldVar extends BcelVar { | |||
} | |||
public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) { | |||
// Only possible to do annotation field value extraction at MethodExecution | |||
// Only possible to do annotation field value extraction at | |||
// MethodExecution | |||
if (annoAccessor.getKind() != Shadow.MethodExecution) { | |||
return; | |||
} | |||
String annotationOfInterestSignature = annoAccessor.getType().getSignature(); | |||
// So we have an entity that has an annotation on and within it is the value we want | |||
// So we have an entity that has an annotation on and within it is the | |||
// value we want | |||
Member holder = annoAccessor.getMember(); | |||
AnnotationX[] annos = holder.getAnnotations(); | |||
AnnotationAJ[] annos = holder.getAnnotations(); | |||
for (int i = 0; i < annos.length; i++) { | |||
AnnotationGen annotation = annos[i].getBcelAnnotation(); | |||
AnnotationGen annotation = ((BcelAnnotation) annos[i]).getBcelAnnotation(); | |||
if (annotation.getTypeSignature().equals(annotationOfInterestSignature)) { | |||
List vals = annotation.getValues(); | |||
boolean doneAndDusted = false; | |||
@@ -76,7 +78,8 @@ class AnnotationAccessFieldVar extends BcelVar { | |||
for (int ii = 0; ii < annotationFields.length; ii++) { | |||
if (annotationFields[ii].getType().equals(annoFieldOfInterest)) { | |||
String dvalue = annotationFields[ii].getAnnotationDefaultValue(); | |||
// form will be LBLAHBLAHBLAH;X where X is the field within X | |||
// form will be LBLAHBLAHBLAH;X where X is the field | |||
// within X | |||
String typename = dvalue.substring(0, dvalue.lastIndexOf(';') + 1); | |||
String field = dvalue.substring(dvalue.lastIndexOf(';') + 1); | |||
ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(typename)); |
@@ -0,0 +1,107 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 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.bcel; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValueGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.ElementValueGen; | |||
import org.aspectj.apache.bcel.classfile.annotation.EnumElementValueGen; | |||
import org.aspectj.weaver.AbstractAnnotationAJ; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.World; | |||
/** | |||
* Wraps a Bcel Annotation object and uses it to answer AnnotationAJ method calls. This is cheaper than translating all Bcel | |||
* annotations into AnnotationAJ objects. | |||
* | |||
* @author AndyClement | |||
*/ | |||
public class BcelAnnotation extends AbstractAnnotationAJ { | |||
private final AnnotationGen bcelAnnotation; | |||
public BcelAnnotation(AnnotationGen theBcelAnnotation, World world) { | |||
super(UnresolvedType.forSignature(theBcelAnnotation.getTypeSignature()).resolve(world)); | |||
this.bcelAnnotation = theBcelAnnotation; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public Set /* of String */getTargets() { | |||
if (!type.equals(UnresolvedType.AT_TARGET)) { | |||
return Collections.EMPTY_SET; | |||
} | |||
List values = bcelAnnotation.getValues(); | |||
ElementNameValuePairGen envp = (ElementNameValuePairGen) values.get(0); | |||
ArrayElementValueGen aev = (ArrayElementValueGen) envp.getValue(); | |||
ElementValueGen[] evs = aev.getElementValuesArray(); | |||
Set targets = new HashSet(); | |||
for (int i = 0; i < evs.length; i++) { | |||
EnumElementValueGen ev = (EnumElementValueGen) evs[i]; | |||
targets.add(ev.getEnumValueString()); | |||
} | |||
return targets; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean hasNameValuePair(String name, String value) { | |||
return bcelAnnotation.hasNameValuePair(name, value); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean hasNamedValue(String name) { | |||
return bcelAnnotation.hasNamedValue(name); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public String stringify() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("@").append(type.getClassName()); | |||
List values = bcelAnnotation.getValues(); | |||
if (values != null && values.size() != 0) { | |||
sb.append("("); | |||
for (Iterator iterator = values.iterator(); iterator.hasNext();) { | |||
ElementNameValuePairGen nvPair = (ElementNameValuePairGen) iterator.next(); | |||
sb.append(nvPair.getNameString()).append("=").append(nvPair.getValue().stringifyValue()); | |||
} | |||
sb.append(")"); | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public boolean isRuntimeVisible() { | |||
return this.bcelAnnotation.isRuntimeVisible(); | |||
} | |||
/** | |||
* @return return the real bcel annotation being wrapped | |||
*/ | |||
public AnnotationGen getBcelAnnotation() { | |||
return bcelAnnotation; | |||
} | |||
} |
@@ -26,7 +26,7 @@ import org.aspectj.apache.bcel.classfile.Synthetic; | |||
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; | |||
import org.aspectj.apache.bcel.generic.FieldGen; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ResolvedMemberImpl; | |||
import org.aspectj.weaver.ResolvedType; | |||
@@ -42,7 +42,7 @@ final class BcelField extends ResolvedMemberImpl { | |||
private Field field; | |||
private boolean isAjSynthetic; | |||
private boolean isSynthetic = false; | |||
private AnnotationX[] annotations; | |||
private AnnotationAJ[] annotations; | |||
private World world; | |||
private BcelObjectType bcelObjectType; | |||
private UnresolvedType genericFieldType = null; | |||
@@ -129,12 +129,12 @@ final class BcelField extends ResolvedMemberImpl { | |||
return ret; | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
ensureAnnotationTypesRetrieved(); | |||
return annotations; | |||
} | |||
public AnnotationX getAnnotationOfType(UnresolvedType ofType) { | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
ensureAnnotationTypesRetrieved(); | |||
for (int i = 0; i < annotations.length; i++) { | |||
if (annotations[i].getTypeName().equals(ofType.getName())) | |||
@@ -148,24 +148,24 @@ final class BcelField extends ResolvedMemberImpl { | |||
AnnotationGen annos[] = field.getAnnotations(); | |||
if (annos == null || annos.length == 0) { | |||
annotationTypes = Collections.EMPTY_SET; | |||
annotations = AnnotationX.NONE; | |||
annotations = AnnotationAJ.EMPTY_ARRAY; | |||
} else { | |||
annotationTypes = new HashSet(); | |||
annotations = new AnnotationX[annos.length]; | |||
annotations = new AnnotationAJ[annos.length]; | |||
for (int i = 0; i < annos.length; i++) { | |||
AnnotationGen annotation = annos[i]; | |||
annotationTypes.add(world.resolve(UnresolvedType.forSignature(annotation.getTypeSignature()))); | |||
annotations[i] = new AnnotationX(annotation, world); | |||
annotations[i] = new BcelAnnotation(annotation, world); | |||
} | |||
} | |||
} | |||
} | |||
public void addAnnotation(AnnotationX annotation) { | |||
public void addAnnotation(AnnotationAJ annotation) { | |||
ensureAnnotationTypesRetrieved(); | |||
// Add it to the set of annotations | |||
int len = annotations.length; | |||
AnnotationX[] ret = new AnnotationX[len + 1]; | |||
AnnotationAJ[] ret = new AnnotationAJ[len + 1]; | |||
System.arraycopy(annotations, 0, ret, 0, len); | |||
ret[len] = annotation; | |||
annotations = ret; | |||
@@ -200,7 +200,7 @@ final class BcelField extends ResolvedMemberImpl { | |||
AnnotationGen[] alreadyHas = fg.getAnnotations(); | |||
if (annotations != null) { | |||
for (int i = 0; i < annotations.length; i++) { | |||
AnnotationX array_element = annotations[i]; | |||
AnnotationAJ array_element = annotations[i]; | |||
boolean alreadyHasIt = false; | |||
for (int j = 0; j < alreadyHas.length; j++) { | |||
AnnotationGen gen = alreadyHas[j]; | |||
@@ -208,7 +208,7 @@ final class BcelField extends ResolvedMemberImpl { | |||
alreadyHasIt = true; | |||
} | |||
if (!alreadyHasIt) | |||
fg.addAnnotation(new AnnotationGen(array_element.getBcelAnnotation(), cpg, true)); | |||
fg.addAnnotation(new AnnotationGen(((BcelAnnotation) array_element).getBcelAnnotation(), cpg, true)); | |||
} | |||
} | |||
field = fg.getField(); |
@@ -37,7 +37,7 @@ import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.SourceLocation; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.MemberKind; | |||
@@ -56,12 +56,15 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
// these fields are not set for many BcelMethods... | |||
private ShadowMunger associatedShadowMunger; | |||
private ResolvedPointcutDefinition preResolvedPointcut; // used when ajc has pre-resolved the pointcut of some @Advice | |||
private ResolvedPointcutDefinition preResolvedPointcut; // used when ajc has | |||
// pre-resolved the | |||
// pointcut of some | |||
// @Advice | |||
private AjAttribute.EffectiveSignatureAttribute effectiveSignature; | |||
private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber; | |||
private AnnotationX[] annotations = null; | |||
private AnnotationX[][] parameterAnnotations = null; | |||
private AnnotationAJ[] annotations = null; | |||
private AnnotationAJ[][] parameterAnnotations = null; | |||
private BcelObjectType bcelObjectType; | |||
private int bitflags; | |||
@@ -71,7 +74,9 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
private static final int UNPACKED_GENERIC_SIGNATURE = 0x0008; | |||
private static final int IS_AJ_SYNTHETIC = 0x0040; | |||
private static final int IS_SYNTHETIC = 0x0080; | |||
private static final int IS_SYNTHETIC_INVERSE = 0x7f7f; // all bits but IS_SYNTHETIC (and topmost bit) | |||
private static final int IS_SYNTHETIC_INVERSE = 0x7f7f; // all bits but | |||
// IS_SYNTHETIC (and | |||
// topmost bit) | |||
private static final int HAS_ANNOTATIONS = 0x0400; | |||
private static final int HAVE_DETERMINED_ANNOTATIONS = 0x0800; | |||
@@ -123,15 +128,15 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
if (varTable == null) { | |||
// do we have an annotation with the argNames value specified... | |||
if (hasAnnotations()) { | |||
AnnotationX[] axs = getAnnotations(); | |||
AnnotationAJ[] axs = getAnnotations(); | |||
for (int i = 0; i < axs.length; i++) { | |||
AnnotationX annotationX = axs[i]; | |||
AnnotationAJ annotationX = axs[i]; | |||
String typename = annotationX.getTypeName(); | |||
if (typename.equals("org.aspectj.lang.annotation.Pointcut") | |||
|| typename.equals("org.aspectj.lang.annotation.Before") | |||
|| typename.equals("org.aspectj.lang.annotation.Around") | |||
|| typename.startsWith("org.aspectj.lang.annotation.After")) { | |||
AnnotationGen a = annotationX.getBcelAnnotation(); | |||
AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation(); | |||
if (a != null) { | |||
List values = a.getValues(); | |||
for (Iterator iterator = values.iterator(); iterator.hasNext();) { | |||
@@ -198,7 +203,8 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
// System.out.println("found effective: " + this); | |||
effectiveSignature = (AjAttribute.EffectiveSignatureAttribute) a; | |||
} else if (a instanceof AjAttribute.PointcutDeclarationAttribute) { | |||
// this is an @AspectJ annotated advice method, with pointcut pre-resolved by ajc | |||
// this is an @AspectJ annotated advice method, with pointcut | |||
// pre-resolved by ajc | |||
preResolvedPointcut = ((AjAttribute.PointcutDeclarationAttribute) a).reify(); | |||
} else { | |||
throw new BCException("weird method attribute " + a); | |||
@@ -206,7 +212,8 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
} | |||
} | |||
// for testing - if we have this attribute, return it - will return null if it doesnt know anything | |||
// for testing - if we have this attribute, return it - will return null if | |||
// it doesnt know anything | |||
public AjAttribute[] getAttributes(String name) { | |||
List results = new ArrayList(); | |||
List l = Utility.readAjAttributes(getDeclaringType().getClassName(), method.getAttributes(), | |||
@@ -247,7 +254,10 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
} | |||
public boolean isAjSynthetic() { | |||
return (bitflags & IS_AJ_SYNTHETIC) != 0;// isAjSynthetic; // || getName().startsWith(NameMangler.PREFIX); | |||
return (bitflags & IS_AJ_SYNTHETIC) != 0;// isAjSynthetic; // || | |||
// getName( | |||
// ).startsWith(NameMangler | |||
// .PREFIX); | |||
} | |||
// FIXME ??? needs an isSynthetic method | |||
@@ -311,12 +321,12 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
return false; | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
ensureAnnotationsRetrieved(); | |||
if ((bitflags & HAS_ANNOTATIONS) != 0) { | |||
return annotations; | |||
} else { | |||
return AnnotationX.NONE; | |||
return AnnotationAJ.EMPTY_ARRAY; | |||
} | |||
} | |||
@@ -327,7 +337,7 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
return ret; | |||
} | |||
public AnnotationX getAnnotationOfType(UnresolvedType ofType) { | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
ensureAnnotationsRetrieved(); | |||
if ((bitflags & HAS_ANNOTATIONS) == 0) | |||
return null; | |||
@@ -338,15 +348,15 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
return null; | |||
} | |||
public void addAnnotation(AnnotationX annotation) { | |||
public void addAnnotation(AnnotationAJ annotation) { | |||
ensureAnnotationsRetrieved(); | |||
if ((bitflags & HAS_ANNOTATIONS) == 0) { | |||
annotations = new AnnotationX[1]; | |||
annotations = new AnnotationAJ[1]; | |||
annotations[0] = annotation; | |||
} else { | |||
// Add it to the set of annotations | |||
int len = annotations.length; | |||
AnnotationX[] ret = new AnnotationX[len + 1]; | |||
AnnotationAJ[] ret = new AnnotationAJ[len + 1]; | |||
System.arraycopy(annotations, 0, ret, 0, len); | |||
ret[len] = annotation; | |||
annotations = ret; | |||
@@ -357,7 +367,8 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
if (annotationTypes == Collections.EMPTY_SET) | |||
annotationTypes = new HashSet(); | |||
annotationTypes.add(UnresolvedType.forName(annotation.getTypeName()).resolve(bcelObjectType.getWorld())); | |||
// FIXME asc looks like we are managing two 'bunches' of annotations, one | |||
// FIXME asc looks like we are managing two 'bunches' of annotations, | |||
// one | |||
// here and one in the real 'method' - should we reduce it to one layer? | |||
// method.addAnnotation(annotation.getBcelAnnotation()); | |||
} | |||
@@ -372,11 +383,11 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
AnnotationGen annos[] = method.getAnnotations(); | |||
if (annos.length != 0) { | |||
annotationTypes = new HashSet(); | |||
annotations = new AnnotationX[annos.length]; | |||
annotations = new AnnotationAJ[annos.length]; | |||
for (int i = 0; i < annos.length; i++) { | |||
AnnotationGen annotation = annos[i]; | |||
annotationTypes.add(bcelObjectType.getWorld().resolve(UnresolvedType.forSignature(annotation.getTypeSignature()))); | |||
annotations[i] = new AnnotationX(annotation, bcelObjectType.getWorld()); | |||
annotations[i] = new BcelAnnotation(annotation, bcelObjectType.getWorld()); | |||
} | |||
bitflags |= HAS_ANNOTATIONS; | |||
} else { | |||
@@ -394,13 +405,13 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
parameterAnnotations = BcelMethod.NO_PARAMETER_ANNOTATIONXS; | |||
} else { | |||
AnnotationGen annos[][] = method.getParameterAnnotations(); | |||
parameterAnnotations = new AnnotationX[annos.length][]; | |||
parameterAnnotations = new AnnotationAJ[annos.length][]; | |||
parameterAnnotationTypes = new ResolvedType[annos.length][]; | |||
for (int i = 0; i < annos.length; i++) { | |||
parameterAnnotations[i] = new AnnotationX[annos[i].length]; | |||
parameterAnnotations[i] = new AnnotationAJ[annos[i].length]; | |||
parameterAnnotationTypes[i] = new ResolvedType[annos[i].length]; | |||
for (int j = 0; j < annos[i].length; j++) { | |||
parameterAnnotations[i][j] = new AnnotationX(annos[i][j], bcelObjectType.getWorld()); | |||
parameterAnnotations[i][j] = new BcelAnnotation(annos[i][j], bcelObjectType.getWorld()); | |||
parameterAnnotationTypes[i][j] = bcelObjectType.getWorld().resolve( | |||
UnresolvedType.forSignature(annos[i][j].getTypeSignature())); | |||
} | |||
@@ -409,7 +420,7 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
} | |||
} | |||
public AnnotationX[][] getParameterAnnotations() { | |||
public AnnotationAJ[][] getParameterAnnotations() { | |||
ensureParameterAnnotationsRetrieved(); | |||
return parameterAnnotations; | |||
} | |||
@@ -482,7 +493,8 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
Signature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals(); | |||
Signature.FormalTypeParameter[] formals = new Signature.FormalTypeParameter[parentFormals.length | |||
+ mSig.formalTypeParameters.length]; | |||
// put method formal in front of type formals for overriding in lookup | |||
// put method formal in front of type formals for overriding in | |||
// lookup | |||
System.arraycopy(mSig.formalTypeParameters, 0, formals, 0, mSig.formalTypeParameters.length); | |||
System.arraycopy(parentFormals, 0, formals, mSig.formalTypeParameters.length, parentFormals.length); | |||
Signature.TypeSignature returnTypeSignature = mSig.returnType; | |||
@@ -534,7 +546,8 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
return (bitflags & IS_SYNTHETIC) != 0;// isSynthetic; | |||
} | |||
// Pre Java5 synthetic is an attribute 'Synthetic', post Java5 it is a modifier (4096 or 0x1000) | |||
// Pre Java5 synthetic is an attribute 'Synthetic', post Java5 it is a | |||
// modifier (4096 or 0x1000) | |||
private void workOutIfSynthetic() { | |||
if ((bitflags & KNOW_IF_SYNTHETIC) != 0) | |||
return; |
@@ -37,8 +37,8 @@ import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.weaver.AbstractReferenceTypeDelegate; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.AjcMemberMaker; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.AnnotationTargetKind; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.ReferenceType; | |||
@@ -73,7 +73,7 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
private ResolvedMember[] fields = null; | |||
private ResolvedMember[] methods = null; | |||
private ResolvedType[] annotationTypes = null; | |||
private AnnotationX[] annotations = null; | |||
private AnnotationAJ[] annotations = null; | |||
private TypeVariable[] typeVars = null; | |||
private String retentionPolicy; | |||
private AnnotationTargetKind[] annotationTargetKinds; | |||
@@ -99,14 +99,16 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
private boolean isNested; | |||
private boolean isObject = false; // set upon construction | |||
private boolean isAnnotationStyleAspect = false;// set upon construction | |||
private boolean isCodeStyleAspect = false; // not redundant with field above! | |||
private boolean isCodeStyleAspect = false; // not redundant with field | |||
// above! | |||
private int bitflag = 0x0000; | |||
// discovery bits | |||
private static final int DISCOVERED_ANNOTATION_RETENTION_POLICY = 0x0001; | |||
private static final int UNPACKED_GENERIC_SIGNATURE = 0x0002; | |||
private static final int UNPACKED_AJATTRIBUTES = 0x0004; // see note(1) below | |||
private static final int UNPACKED_AJATTRIBUTES = 0x0004; // see note(1) | |||
// below | |||
private static final int DISCOVERED_ANNOTATION_TARGET_KINDS = 0x0008; | |||
private static final int DISCOVERED_DECLARED_SIGNATURE = 0x0010; | |||
private static final int DISCOVERED_WHETHER_ANNOTATION_STYLE = 0x0020; | |||
@@ -128,7 +130,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
this.javaClass = javaClass; | |||
initializeFromJavaclass(); | |||
// ATAJ: set the delegate right now for @AJ pointcut, else it is done too late to lookup | |||
// ATAJ: set the delegate right now for @AJ pointcut, else it is done | |||
// too late to lookup | |||
// @AJ pc refs annotation in class hierarchy | |||
resolvedTypeX.setDelegate(this); | |||
@@ -143,7 +146,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
isObject = (javaClass.getSuperclassNameIndex() == 0); | |||
ensureAspectJAttributesUnpacked(); | |||
// if (sourceContext instanceof SourceContextImpl) { | |||
// ((SourceContextImpl)sourceContext).setSourceFileName(javaClass.getSourceFileName()); | |||
// ((SourceContextImpl)sourceContext).setSourceFileName(javaClass. | |||
// getSourceFileName()); | |||
// } | |||
setSourcefilename(javaClass.getSourceFileName()); | |||
} | |||
@@ -274,7 +278,12 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
return TypeVariable.NONE; | |||
if (typeVars == null) { | |||
Signature.ClassSignature classSig = getGenericClassTypeSignature();// cachedGenericClassTypeSignature;//javaClass. | |||
Signature.ClassSignature classSig = getGenericClassTypeSignature();// cachedGenericClassTypeSignature | |||
// ; | |||
// / | |||
// / | |||
// javaClass | |||
// . | |||
// getGenericClassTypeSignature(); | |||
typeVars = new TypeVariable[classSig.formalTypeParameters.length]; | |||
for (int i = 0; i < typeVars.length; i++) { | |||
@@ -398,7 +407,9 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
setSourcefilename(sca.getSourceFileName()); | |||
} | |||
} else if (a instanceof AjAttribute.WeaverVersionInfo) { | |||
wvInfo = (AjAttribute.WeaverVersionInfo) a; // Set the weaver version used to build this type | |||
wvInfo = (AjAttribute.WeaverVersionInfo) a; // Set the weaver | |||
// version used to | |||
// build this type | |||
} else { | |||
throw new BCException("bad attribute " + a); | |||
} | |||
@@ -444,7 +455,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
public void resetState() { | |||
if (javaClass == null) { | |||
// we might store the classname and allow reloading? | |||
// At this point we are relying on the world to not evict if it might want to reweave multiple times | |||
// At this point we are relying on the world to not evict if it | |||
// might want to reweave multiple times | |||
throw new BCException("can't weave evicted type"); | |||
} | |||
@@ -478,7 +490,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
// this.perClause = null; | |||
// this.weaverState = null; | |||
// this.lazyClassGen = null; | |||
// this next line frees up memory, but need to understand incremental implications | |||
// this next line frees up memory, but need to understand incremental | |||
// implications | |||
// before leaving it in. | |||
// getResolvedTypeX().setSourceContext(null); | |||
} | |||
@@ -508,7 +521,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
// System.err.println("creating lazy class gen for: " + this); | |||
ret = new LazyClassGen(this); | |||
// ret.print(System.err); | |||
// System.err.println("made LCG from : " + this.getJavaClass().getSuperclassName ); | |||
// System.err.println("made LCG from : " + | |||
// this.getJavaClass().getSuperclassName ); | |||
if (isAspect()) { | |||
lazyClassGen = ret; | |||
} | |||
@@ -549,7 +563,9 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
interfaceSignatures = newInterfaceSignatures; | |||
} | |||
} | |||
// System.err.println("javaClass: " + Arrays.asList(javaClass.getInterfaceNames()) + " super " + superclassName); | |||
// System.err.println("javaClass: " + | |||
// Arrays.asList(javaClass.getInterfaceNames()) + " super " + | |||
// superclassName); | |||
// if (lazyClassGen != null) lazyClassGen.print(); | |||
} | |||
@@ -560,7 +576,7 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
return annotationTypes; | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
ensureAnnotationsUnpacked(); | |||
return annotations; | |||
} | |||
@@ -576,10 +592,10 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
} | |||
// evil mutator - adding state not stored in the java class | |||
public void addAnnotation(AnnotationX annotation) { | |||
public void addAnnotation(AnnotationAJ annotation) { | |||
bitflag |= DAMAGED; | |||
int len = annotations.length; | |||
AnnotationX[] ret = new AnnotationX[len + 1]; | |||
AnnotationAJ[] ret = new AnnotationAJ[len + 1]; | |||
System.arraycopy(annotations, 0, ret, 0, len); | |||
ret[len] = annotation; | |||
annotations = ret; | |||
@@ -602,9 +618,9 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
if (isAnnotation()) { | |||
ensureAnnotationsUnpacked(); | |||
for (int i = annotations.length - 1; i >= 0; i--) { | |||
AnnotationX ax = annotations[i]; | |||
AnnotationAJ ax = annotations[i]; | |||
if (ax.getTypeName().equals(UnresolvedType.AT_RETENTION.getName())) { | |||
List values = ax.getBcelAnnotation().getValues(); | |||
List values = ((BcelAnnotation) ax).getBcelAnnotation().getValues(); | |||
for (Iterator it = values.iterator(); it.hasNext();) { | |||
ElementNameValuePairGen element = (ElementNameValuePairGen) it.next(); | |||
EnumElementValueGen v = (EnumElementValueGen) element.getValue(); | |||
@@ -634,7 +650,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
if ((bitflag & DISCOVERED_ANNOTATION_TARGET_KINDS) != 0) | |||
return annotationTargetKinds; | |||
bitflag |= DISCOVERED_ANNOTATION_TARGET_KINDS; | |||
annotationTargetKinds = null; // null means we have no idea or the @Target annotation hasn't been used | |||
annotationTargetKinds = null; // null means we have no idea or the | |||
// @Target annotation hasn't been used | |||
List targetKinds = new ArrayList(); | |||
if (isAnnotation()) { | |||
AnnotationGen[] annotationsOnThisType = javaClass.getAnnotations(); | |||
@@ -683,15 +700,15 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
AnnotationGen annos[] = javaClass.getAnnotations(); | |||
if (annos == null || annos.length == 0) { | |||
annotationTypes = ResolvedType.NONE; | |||
annotations = AnnotationX.NONE; | |||
annotations = AnnotationAJ.EMPTY_ARRAY; | |||
} else { | |||
World w = getResolvedTypeX().getWorld(); | |||
annotationTypes = new ResolvedType[annos.length]; | |||
annotations = new AnnotationX[annos.length]; | |||
annotations = new AnnotationAJ[annos.length]; | |||
for (int i = 0; i < annos.length; i++) { | |||
AnnotationGen annotation = annos[i]; | |||
annotationTypes[i] = w.resolve(UnresolvedType.forSignature(annotation.getTypeSignature())); | |||
annotations[i] = new AnnotationX(annotation, w); | |||
annotations[i] = new BcelAnnotation(annotation, w); | |||
} | |||
} | |||
} | |||
@@ -714,7 +731,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
if (cSig != null) { | |||
formalsForResolution = cSig.formalTypeParameters; | |||
if (isNested()) { | |||
// we have to find any type variables from the outer type before proceeding with resolution. | |||
// we have to find any type variables from the outer type before | |||
// proceeding with resolution. | |||
Signature.FormalTypeParameter[] extraFormals = getFormalTypeParametersFromOuterClass(); | |||
if (extraFormals.length > 0) { | |||
List allFormals = new ArrayList(); | |||
@@ -732,7 +750,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
try { | |||
// this.superClass = | |||
// BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX( | |||
// superSig, formalsForResolution, getResolvedTypeX().getWorld()); | |||
// superSig, formalsForResolution, | |||
// getResolvedTypeX().getWorld()); | |||
ResolvedType rt = BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX(superSig, formalsForResolution, | |||
getResolvedTypeX().getWorld()); | |||
@@ -745,7 +764,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
+ " with generic signature " + getDeclaredGenericSignature() + " the following error was detected: " | |||
+ e.getMessage()); | |||
} | |||
// this.interfaces = new ResolvedType[cSig.superInterfaceSignatures.length]; | |||
// this.interfaces = new | |||
// ResolvedType[cSig.superInterfaceSignatures.length]; | |||
if (cSig.superInterfaceSignatures.length == 0) { | |||
this.interfaceSignatures = NO_INTERFACE_SIGS; | |||
} else { | |||
@@ -753,7 +773,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
for (int i = 0; i < cSig.superInterfaceSignatures.length; i++) { | |||
try { | |||
// this.interfaces[i] = | |||
// BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX( | |||
// BcelGenericSignatureToTypeXConverter. | |||
// classTypeSignature2TypeX( | |||
// cSig.superInterfaceSignatures[i], | |||
// formalsForResolution, | |||
// getResolvedTypeX().getWorld()); | |||
@@ -772,7 +793,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
if (isGeneric()) { | |||
// update resolved typex to point at generic type not raw type. | |||
ReferenceType genericType = (ReferenceType) this.resolvedTypeX.getGenericType(); | |||
// genericType.setSourceContext(this.resolvedTypeX.getSourceContext()); | |||
// genericType.setSourceContext(this.resolvedTypeX.getSourceContext() | |||
// ); | |||
genericType.setStartPos(this.resolvedTypeX.getStartPos()); | |||
this.resolvedTypeX = genericType; | |||
} | |||
@@ -830,9 +852,12 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
getDeclaredInterfaces(); | |||
getDeclaredFields(); | |||
getDeclaredMethods(); | |||
// The lazyClassGen is preserved for aspects - it exists to enable around advice | |||
// inlining since the method will need 'injecting' into the affected class. If | |||
// XnoInline is on, we can chuck away the lazyClassGen since it won't be required | |||
// The lazyClassGen is preserved for aspects - it exists to enable | |||
// around advice | |||
// inlining since the method will need 'injecting' into the affected | |||
// class. If | |||
// XnoInline is on, we can chuck away the lazyClassGen since it | |||
// won't be required | |||
// later. | |||
if (getResolvedTypeX().getWorld().isXnoInline()) | |||
lazyClassGen = null; | |||
@@ -847,8 +872,10 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
for (int i = fields.length - 1; i >= 0; i--) | |||
fields[i].evictWeavingState(); | |||
javaClass = null; | |||
// setSourceContext(SourceContextImpl.UNKNOWN_SOURCE_CONTEXT); // bit naughty | |||
// interfaces=null; // force reinit - may get us the right instances! | |||
// setSourceContext(SourceContextImpl.UNKNOWN_SOURCE_CONTEXT); // | |||
// bit naughty | |||
// interfaces=null; // force reinit - may get us the right | |||
// instances! | |||
// superClass=null; | |||
} | |||
} | |||
@@ -863,11 +890,15 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
// --- methods for testing | |||
// for testing - if we have this attribute, return it - will return null if it doesnt know anything | |||
// for testing - if we have this attribute, return it - will return null if | |||
// it doesnt know anything | |||
// public AjAttribute[] getAttributes(String name) { | |||
// List results = new ArrayList(); | |||
// List l = BcelAttributes.readAjAttributes(javaClass.getClassName(),javaClass.getAttributes(), | |||
// getResolvedTypeX().getSourceContext(),getResolvedTypeX().getWorld(),AjAttribute.WeaverVersionInfo.UNKNOWN); | |||
// List l = | |||
// BcelAttributes.readAjAttributes(javaClass.getClassName(),javaClass | |||
// .getAttributes(), | |||
// getResolvedTypeX().getSourceContext(),getResolvedTypeX().getWorld(), | |||
// AjAttribute.WeaverVersionInfo.UNKNOWN); | |||
// for (Iterator iter = l.iterator(); iter.hasNext();) { | |||
// AjAttribute element = (AjAttribute) iter.next(); | |||
// if (element.getNameString().equals(name)) results.add(element); | |||
@@ -878,7 +909,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
// return null; | |||
// } | |||
// | |||
// // for testing - use with the method above - this returns *all* including those that are not Aj attributes | |||
// // for testing - use with the method above - this returns *all* including | |||
// those that are not Aj attributes | |||
// public String[] getAttributeNames() { | |||
// Attribute[] as = javaClass.getAttributes(); | |||
// String[] strs = new String[as.length]; |
@@ -41,8 +41,8 @@ import org.aspectj.apache.bcel.util.Repository; | |||
import org.aspectj.bridge.IMessageHandler; | |||
import org.aspectj.weaver.Advice; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.AnnotationOnTypeMunger; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ConcreteTypeMunger; | |||
import org.aspectj.weaver.ICrossReferenceHandler; | |||
@@ -75,7 +75,8 @@ public class BcelWorld extends World implements Repository { | |||
// private ClassPathManager aspectPath = null; | |||
// private List aspectPathEntries; | |||
private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelWorld.class); | |||
private static Trace trace = TraceFactory.getTraceFactory().getTrace( | |||
BcelWorld.class); | |||
// ---- constructors | |||
@@ -106,7 +107,8 @@ public class BcelWorld extends World implements Repository { | |||
return ret; | |||
} | |||
public BcelWorld(List classPath, IMessageHandler handler, ICrossReferenceHandler xrefHandler) { | |||
public BcelWorld(List classPath, IMessageHandler handler, | |||
ICrossReferenceHandler xrefHandler) { | |||
// this.aspectPath = new ClassPathManager(aspectPath, handler); | |||
this.classPath = new ClassPathManager(classPath, handler); | |||
setMessageHandler(handler); | |||
@@ -115,7 +117,8 @@ public class BcelWorld extends World implements Repository { | |||
delegate = this; | |||
} | |||
public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) { | |||
public BcelWorld(ClassPathManager cpm, IMessageHandler handler, | |||
ICrossReferenceHandler xrefHandler) { | |||
this.classPath = cpm; | |||
setMessageHandler(handler); | |||
setCrossReferenceHandler(xrefHandler); | |||
@@ -130,7 +133,8 @@ public class BcelWorld extends World implements Repository { | |||
* @param handler | |||
* @param xrefHandler | |||
*/ | |||
public BcelWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) { | |||
public BcelWorld(ClassLoader loader, IMessageHandler handler, | |||
ICrossReferenceHandler xrefHandler) { | |||
this.classPath = null; | |||
this.loaderRef = new WeakClassLoaderReference(loader); | |||
setMessageHandler(handler); | |||
@@ -206,8 +210,10 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
} | |||
public BcelObjectType buildBcelDelegate(ReferenceType resolvedTypeX, JavaClass jc, boolean exposedToWeaver) { | |||
BcelObjectType ret = new BcelObjectType(resolvedTypeX, jc, exposedToWeaver); | |||
public BcelObjectType buildBcelDelegate(ReferenceType resolvedTypeX, | |||
JavaClass jc, boolean exposedToWeaver) { | |||
BcelObjectType ret = new BcelObjectType(resolvedTypeX, jc, | |||
exposedToWeaver); | |||
return ret; | |||
} | |||
@@ -217,21 +223,25 @@ public class BcelWorld extends World implements Repository { | |||
ensureRepositorySetup(); | |||
JavaClass jc = delegate.loadClass(name); | |||
if (trace.isTraceEnabled()) | |||
trace.event("lookupJavaClass", this, new Object[] { name, jc }); | |||
trace.event("lookupJavaClass", this, new Object[] { name, | |||
jc }); | |||
return jc; | |||
} catch (ClassNotFoundException e) { | |||
if (trace.isTraceEnabled()) | |||
trace.error("Unable to find class '" + name + "' in repository", e); | |||
trace.error("Unable to find class '" + name | |||
+ "' in repository", e); | |||
return null; | |||
} | |||
} | |||
try { | |||
ClassPathManager.ClassFile file = classPath.find(UnresolvedType.forName(name)); | |||
ClassPathManager.ClassFile file = classPath.find(UnresolvedType | |||
.forName(name)); | |||
if (file == null) | |||
return null; | |||
ClassParser parser = new ClassParser(file.getInputStream(), file.getPath()); | |||
ClassParser parser = new ClassParser(file.getInputStream(), file | |||
.getPath()); | |||
JavaClass jc = parser.parse(); | |||
file.close(); | |||
@@ -243,15 +253,18 @@ public class BcelWorld extends World implements Repository { | |||
public BcelObjectType addSourceObjectType(JavaClass jc) { | |||
BcelObjectType ret = null; | |||
String signature = UnresolvedType.forName(jc.getClassName()).getSignature(); | |||
String signature = UnresolvedType.forName(jc.getClassName()) | |||
.getSignature(); | |||
Object fromTheMap = typeMap.get(signature); | |||
if (fromTheMap != null && !(fromTheMap instanceof ReferenceType)) { | |||
// what on earth is it then? See pr 112243 | |||
StringBuffer exceptionText = new StringBuffer(); | |||
exceptionText.append("Found invalid (not a ReferenceType) entry in the type map. "); | |||
exceptionText.append("Signature=[" + signature + "] Found=[" + fromTheMap + "] Class=[" + fromTheMap.getClass() + "]"); | |||
exceptionText | |||
.append("Found invalid (not a ReferenceType) entry in the type map. "); | |||
exceptionText.append("Signature=[" + signature + "] Found=[" | |||
+ fromTheMap + "] Class=[" + fromTheMap.getClass() + "]"); | |||
throw new BCException(exceptionText.toString()); | |||
} | |||
@@ -260,10 +273,12 @@ public class BcelWorld extends World implements Repository { | |||
if (nameTypeX == null) { | |||
if (jc.isGeneric() && isInJava5Mode()) { | |||
nameTypeX = ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()), this); | |||
nameTypeX = ReferenceType.fromTypeX(UnresolvedType | |||
.forRawTypeName(jc.getClassName()), this); | |||
ret = buildBcelDelegate(nameTypeX, jc, true); | |||
ReferenceType genericRefType = new ReferenceType(UnresolvedType.forGenericTypeSignature(signature, ret | |||
.getDeclaredGenericSignature()), this); | |||
ReferenceType genericRefType = new ReferenceType(UnresolvedType | |||
.forGenericTypeSignature(signature, ret | |||
.getDeclaredGenericSignature()), this); | |||
nameTypeX.setDelegate(ret); | |||
genericRefType.setDelegate(ret); | |||
nameTypeX.setGenericType(genericRefType); | |||
@@ -283,21 +298,26 @@ public class BcelWorld extends World implements Repository { | |||
typeMap.remove(ty.getSignature()); | |||
} | |||
public static Member makeFieldJoinPointSignature(LazyClassGen cg, FieldInstruction fi) { | |||
public static Member makeFieldJoinPointSignature(LazyClassGen cg, | |||
FieldInstruction fi) { | |||
ConstantPool cpg = cg.getConstantPool(); | |||
return MemberImpl.field(fi.getClassName(cpg), | |||
(fi.opcode == Constants.GETSTATIC || fi.opcode == Constants.PUTSTATIC) ? Modifier.STATIC : 0, fi.getName(cpg), fi | |||
.getSignature(cpg)); | |||
return MemberImpl | |||
.field( | |||
fi.getClassName(cpg), | |||
(fi.opcode == Constants.GETSTATIC || fi.opcode == Constants.PUTSTATIC) ? Modifier.STATIC | |||
: 0, fi.getName(cpg), fi.getSignature(cpg)); | |||
} | |||
public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, MemberKind kind) { | |||
public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, | |||
MemberKind kind) { | |||
Member ret = mg.getMemberView(); | |||
if (ret == null) { | |||
int mods = mg.getAccessFlags(); | |||
if (mg.getEnclosingClass().isInterface()) { | |||
mods |= Modifier.INTERFACE; | |||
} | |||
return new ResolvedMemberImpl(kind, UnresolvedType.forName(mg.getClassName()), mods, fromBcel(mg.getReturnType()), mg | |||
return new ResolvedMemberImpl(kind, UnresolvedType.forName(mg | |||
.getClassName()), mods, fromBcel(mg.getReturnType()), mg | |||
.getName(), fromBcel(mg.getArgumentTypes())); | |||
} else { | |||
return ret; | |||
@@ -305,15 +325,18 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
public Member makeJoinPointSignatureForMonitorEnter(LazyClassGen cg, InstructionHandle h) { | |||
public Member makeJoinPointSignatureForMonitorEnter(LazyClassGen cg, | |||
InstructionHandle h) { | |||
return MemberImpl.monitorEnter(); | |||
} | |||
public Member makeJoinPointSignatureForMonitorExit(LazyClassGen cg, InstructionHandle h) { | |||
public Member makeJoinPointSignatureForMonitorExit(LazyClassGen cg, | |||
InstructionHandle h) { | |||
return MemberImpl.monitorExit(); | |||
} | |||
public Member makeJoinPointSignatureForArrayConstruction(LazyClassGen cg, InstructionHandle handle) { | |||
public Member makeJoinPointSignatureForArrayConstruction(LazyClassGen cg, | |||
InstructionHandle handle) { | |||
Instruction i = handle.getInstruction(); | |||
ConstantPool cpg = cg.getConstantPool(); | |||
Member retval = null; | |||
@@ -323,7 +346,8 @@ public class BcelWorld extends World implements Repository { | |||
Type ot = i.getType(cpg); | |||
UnresolvedType ut = fromBcel(ot); | |||
ut = UnresolvedType.makeArray(ut, 1); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", new ResolvedType[] { ResolvedType.INT }); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, | |||
"<init>", new ResolvedType[] { ResolvedType.INT }); | |||
} else if (i instanceof MULTIANEWARRAY) { | |||
MULTIANEWARRAY arrayInstruction = (MULTIANEWARRAY) i; | |||
UnresolvedType ut = null; | |||
@@ -339,20 +363,25 @@ public class BcelWorld extends World implements Repository { | |||
ResolvedType[] parms = new ResolvedType[dimensions]; | |||
for (int ii = 0; ii < dimensions; ii++) | |||
parms[ii] = ResolvedType.INT; | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", parms); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, | |||
"<init>", parms); | |||
} else if (i.opcode == Constants.NEWARRAY) { | |||
// NEWARRAY arrayInstruction = (NEWARRAY)i; | |||
Type ot = i.getType(); | |||
UnresolvedType ut = fromBcel(ot); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", new ResolvedType[] { ResolvedType.INT }); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, | |||
"<init>", new ResolvedType[] { ResolvedType.INT }); | |||
} else { | |||
throw new BCException("Cannot create array construction signature for this non-array instruction:" + i); | |||
throw new BCException( | |||
"Cannot create array construction signature for this non-array instruction:" | |||
+ i); | |||
} | |||
return retval; | |||
} | |||
public Member makeJoinPointSignatureForMethodInvocation(LazyClassGen cg, InvokeInstruction ii) { | |||
public Member makeJoinPointSignatureForMethodInvocation(LazyClassGen cg, | |||
InvokeInstruction ii) { | |||
ConstantPool cpg = cg.getConstantPool(); | |||
String name = ii.getName(cpg); | |||
String declaring = ii.getClassName(cpg); | |||
@@ -361,19 +390,23 @@ public class BcelWorld extends World implements Repository { | |||
String signature = ii.getSignature(cpg); | |||
int modifier = (ii instanceof INVOKEINTERFACE) ? Modifier.INTERFACE | |||
: (ii.opcode == Constants.INVOKESTATIC) ? Modifier.STATIC : (ii.opcode == Constants.INVOKESPECIAL && !name | |||
.equals("<init>")) ? Modifier.PRIVATE : 0; | |||
: (ii.opcode == Constants.INVOKESTATIC) ? Modifier.STATIC | |||
: (ii.opcode == Constants.INVOKESPECIAL && !name | |||
.equals("<init>")) ? Modifier.PRIVATE : 0; | |||
// in Java 1.4 and after, static method call of super class within subclass method appears | |||
// in Java 1.4 and after, static method call of super class within | |||
// subclass method appears | |||
// as declared by the subclass in the bytecode - but they are not | |||
// see #104212 | |||
if (ii.opcode == Constants.INVOKESTATIC) { | |||
ResolvedType appearsDeclaredBy = resolve(declaring); | |||
// look for the method there | |||
for (Iterator iterator = appearsDeclaredBy.getMethods(); iterator.hasNext();) { | |||
for (Iterator iterator = appearsDeclaredBy.getMethods(); iterator | |||
.hasNext();) { | |||
ResolvedMember method = (ResolvedMember) iterator.next(); | |||
if (method.isStatic()) { | |||
if (name.equals(method.getName()) && signature.equals(method.getSignature())) { | |||
if (name.equals(method.getName()) | |||
&& signature.equals(method.getSignature())) { | |||
// we found it | |||
declaringType = method.getDeclaringType(); | |||
break; | |||
@@ -400,12 +433,15 @@ public class BcelWorld extends World implements Repository { | |||
return buf.toString(); | |||
} | |||
public Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature) { | |||
// System.err.println("concrete advice: " + signature + " context " + sourceContext); | |||
public Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, | |||
Pointcut pointcut, Member signature) { | |||
// System.err.println("concrete advice: " + signature + " context " + | |||
// sourceContext); | |||
return new BcelAdvice(attribute, pointcut, signature, null); | |||
} | |||
public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) { | |||
public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, | |||
ResolvedType aspectType) { | |||
return new BcelTypeMunger(munger, aspectType); | |||
} | |||
@@ -413,27 +449,32 @@ public class BcelWorld extends World implements Repository { | |||
return new BcelCflowStackFieldAdder(cflowField); | |||
} | |||
public ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField) { | |||
public ConcreteTypeMunger makeCflowCounterFieldAdder( | |||
ResolvedMember cflowField) { | |||
return new BcelCflowCounterFieldAdder(cflowField); | |||
} | |||
/** | |||
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed | |||
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to | |||
* them as needed | |||
* | |||
* @param aspect | |||
* @param kind | |||
* @return munger | |||
*/ | |||
public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind) { | |||
public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, | |||
PerClause.Kind kind) { | |||
return new BcelPerClauseAspectAdder(aspect, kind); | |||
} | |||
/** | |||
* Retrieve a bcel delegate for an aspect - this will return NULL if the delegate is an EclipseSourceType and not a | |||
* BcelObjectType - this happens quite often when incrementally compiling. | |||
* Retrieve a bcel delegate for an aspect - this will return NULL if the | |||
* delegate is an EclipseSourceType and not a BcelObjectType - this happens | |||
* quite often when incrementally compiling. | |||
*/ | |||
public static BcelObjectType getBcelObjectType(ResolvedType concreteAspect) { | |||
ReferenceTypeDelegate rtDelegate = ((ReferenceType) concreteAspect).getDelegate(); | |||
ReferenceTypeDelegate rtDelegate = ((ReferenceType) concreteAspect) | |||
.getDelegate(); | |||
if (rtDelegate instanceof BcelObjectType) { | |||
return (BcelObjectType) rtDelegate; | |||
} else { | |||
@@ -442,7 +483,8 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
public void tidyUp() { | |||
// At end of compile, close any open files so deletion of those archives is possible | |||
// At end of compile, close any open files so deletion of those archives | |||
// is possible | |||
classPath.closeArchives(); | |||
typeMap.report(); | |||
ResolvedType.resetPrimitives(); | |||
@@ -477,8 +519,9 @@ public class BcelWorld extends World implements Repository { | |||
// @Override | |||
/** | |||
* The aim of this method is to make sure a particular type is 'ok'. Some operations on the delegate for a type modify it and | |||
* this method is intended to undo that... see pr85132 | |||
* The aim of this method is to make sure a particular type is 'ok'. Some | |||
* operations on the delegate for a type modify it and this method is | |||
* intended to undo that... see pr85132 | |||
*/ | |||
public void validateType(UnresolvedType type) { | |||
ResolvedType result = typeMap.get(type.getSignature()); | |||
@@ -489,7 +532,8 @@ public class BcelWorld extends World implements Repository { | |||
ReferenceType rt = (ReferenceType) result; | |||
rt.getDelegate().ensureDelegateConsistent(); | |||
// If we want to rebuild it 'from scratch' then: | |||
// ClassParser cp = new ClassParser(new ByteArrayInputStream(newbytes),new String(cs)); | |||
// ClassParser cp = new ClassParser(new | |||
// ByteArrayInputStream(newbytes),new String(cs)); | |||
// try { | |||
// rt.setDelegate(makeBcelObjectType(rt,cp.parse(),true)); | |||
// } catch (ClassFormatException e) { | |||
@@ -512,14 +556,19 @@ public class BcelWorld extends World implements Repository { | |||
for (Iterator j = newParents.iterator(); j.hasNext();) { | |||
ResolvedType newParent = (ResolvedType) j.next(); | |||
// We set it here so that the imminent matching for ITDs can succeed - we | |||
// still haven't done the necessary changes to the class file itself | |||
// (like transform super calls) - that is done in BcelTypeMunger.mungeNewParent() | |||
// We set it here so that the imminent matching for ITDs can | |||
// succeed - we | |||
// still haven't done the necessary changes to the class file | |||
// itself | |||
// (like transform super calls) - that is done in | |||
// BcelTypeMunger.mungeNewParent() | |||
classType.addParent(newParent); | |||
ResolvedTypeMunger newParentMunger = new NewParentTypeMunger(newParent); | |||
ResolvedTypeMunger newParentMunger = new NewParentTypeMunger( | |||
newParent); | |||
newParentMunger.setSourceLocation(p.getSourceLocation()); | |||
onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, getCrosscuttingMembersSet() | |||
.findAspectDeclaringParents(p))); | |||
onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, | |||
getCrosscuttingMembersSet().findAspectDeclaringParents( | |||
p))); | |||
} | |||
} | |||
return didSomething; | |||
@@ -528,25 +577,28 @@ public class BcelWorld extends World implements Repository { | |||
/** | |||
* Apply a declare @type - return true if we change the type | |||
*/ | |||
private boolean applyDeclareAtType(DeclareAnnotation decA, ResolvedType onType, boolean reportProblems) { | |||
private boolean applyDeclareAtType(DeclareAnnotation decA, | |||
ResolvedType onType, boolean reportProblems) { | |||
boolean didSomething = false; | |||
if (decA.matches(onType)) { | |||
if (onType.hasAnnotation(decA.getAnnotationX().getSignature())) { | |||
if (onType.hasAnnotation(decA.getAnnotationX().getType())) { | |||
// already has it | |||
return false; | |||
} | |||
AnnotationX annoX = decA.getAnnotationX(); | |||
AnnotationAJ annoX = decA.getAnnotationX(); | |||
// check the annotation is suitable for the target | |||
boolean isOK = checkTargetOK(decA, onType, annoX); | |||
if (isOK) { | |||
didSomething = true; | |||
ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger(annoX); | |||
ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger( | |||
annoX); | |||
newAnnotationTM.setSourceLocation(decA.getSourceLocation()); | |||
onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM, decA.getAspect().resolve(this))); | |||
onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM, | |||
decA.getAspect().resolve(this))); | |||
decA.copyAnnotationTo(onType); | |||
} | |||
} | |||
@@ -554,23 +606,28 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
/** | |||
* Checks for an @target() on the annotation and if found ensures it allows the annotation to be attached to the target type | |||
* that matched. | |||
* Checks for an @target() on the annotation and if found ensures it allows | |||
* the annotation to be attached to the target type that matched. | |||
*/ | |||
private boolean checkTargetOK(DeclareAnnotation decA, ResolvedType onType, AnnotationX annoX) { | |||
private boolean checkTargetOK(DeclareAnnotation decA, ResolvedType onType, | |||
AnnotationAJ annoX) { | |||
if (annoX.specifiesTarget()) { | |||
if ((onType.isAnnotation() && !annoX.allowedOnAnnotationType()) || (!annoX.allowedOnRegularType())) { | |||
if ((onType.isAnnotation() && !annoX.allowedOnAnnotationType()) | |||
|| (!annoX.allowedOnRegularType())) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
// Hmmm - very similar to the code in BcelWeaver.weaveParentTypeMungers - this code | |||
// doesn't need to produce errors/warnings though as it won't really be weaving. | |||
// Hmmm - very similar to the code in BcelWeaver.weaveParentTypeMungers - | |||
// this code | |||
// doesn't need to produce errors/warnings though as it won't really be | |||
// weaving. | |||
protected void weaveInterTypeDeclarations(ResolvedType onType) { | |||
List declareParentsList = getCrosscuttingMembersSet().getDeclareParents(); | |||
List declareParentsList = getCrosscuttingMembersSet() | |||
.getDeclareParents(); | |||
if (onType.isRawType()) | |||
onType = onType.getGenericType(); | |||
onType.clearInterTypeMungers(); | |||
@@ -585,14 +642,16 @@ public class BcelWorld extends World implements Repository { | |||
boolean typeChanged = applyDeclareParents(decp, onType); | |||
if (typeChanged) { | |||
aParentChangeOccurred = true; | |||
} else { // Perhaps it would have matched if a 'dec @type' had modified the type | |||
} else { // Perhaps it would have matched if a 'dec @type' had | |||
// modified the type | |||
if (!decp.getChild().isStarAnnotation()) | |||
decpToRepeat.add(decp); | |||
} | |||
} | |||
// Still first pass - apply all dec @type mungers | |||
for (Iterator i = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator(); i.hasNext();) { | |||
for (Iterator i = getCrosscuttingMembersSet() | |||
.getDeclareAnnotationOnTypes().iterator(); i.hasNext();) { | |||
DeclareAnnotation decA = (DeclareAnnotation) i.next(); | |||
boolean typeChanged = applyDeclareAtType(decA, onType, true); | |||
if (typeChanged) { | |||
@@ -600,7 +659,8 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
} | |||
while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) { | |||
while ((aParentChangeOccurred || anAnnotationChangeOccurred) | |||
&& !decpToRepeat.isEmpty()) { | |||
anAnnotationChangeOccurred = aParentChangeOccurred = false; | |||
List decpToRepeatNextTime = new ArrayList(); | |||
for (Iterator iter = decpToRepeat.iterator(); iter.hasNext();) { | |||
@@ -613,7 +673,8 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
} | |||
for (Iterator iter = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator(); iter.hasNext();) { | |||
for (Iterator iter = getCrosscuttingMembersSet() | |||
.getDeclareAnnotationOnTypes().iterator(); iter.hasNext();) { | |||
DeclareAnnotation decA = (DeclareAnnotation) iter.next(); | |||
boolean typeChanged = applyDeclareAtType(decA, onType, false); | |||
if (typeChanged) { |
@@ -51,7 +51,7 @@ import org.aspectj.apache.bcel.generic.Type; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.MemberImpl; | |||
@@ -134,8 +134,10 @@ public final class LazyMethodGen implements Traceable { | |||
public LazyMethodGen(int accessFlags, Type returnType, String name, Type[] paramTypes, String[] declaredExceptions, | |||
LazyClassGen enclosingClass) { | |||
// System.err.println("raw create of: " + name + ", " + enclosingClass.getName() + ", " + returnType); | |||
this.memberView = null; // ??? should be okay, since constructed ones aren't woven into | |||
// System.err.println("raw create of: " + name + ", " + | |||
// enclosingClass.getName() + ", " + returnType); | |||
this.memberView = null; // ??? should be okay, since constructed ones | |||
// aren't woven into | |||
this.accessFlags = accessFlags; | |||
this.returnType = returnType; | |||
this.name = name; | |||
@@ -154,8 +156,10 @@ public final class LazyMethodGen implements Traceable { | |||
// @AJ advice are not inlined by default since requires further analysis | |||
// and weaving ordering control | |||
// TODO AV - improve - note: no room for improvement as long as aspects are reweavable | |||
// since the inlined version with wrappers and an to be done annotation to keep | |||
// TODO AV - improve - note: no room for improvement as long as aspects | |||
// are reweavable | |||
// since the inlined version with wrappers and an to be done annotation | |||
// to keep | |||
// inline state will be garbaged due to reweavable impl | |||
if (memberView != null && isAdviceMethod()) { | |||
if (enclosingClass.getType().isAnnotationStyleAspect()) { | |||
@@ -177,7 +181,8 @@ public final class LazyMethodGen implements Traceable { | |||
private Method savedMethod = null; | |||
// build from an existing method, lazy build saves most work for initialization | |||
// build from an existing method, lazy build saves most work for | |||
// initialization | |||
public LazyMethodGen(Method m, LazyClassGen enclosingClass) { | |||
savedMethod = m; | |||
@@ -195,8 +200,10 @@ public final class LazyMethodGen implements Traceable { | |||
// @AJ advice are not inlined by default since requires further analysis | |||
// and weaving ordering control | |||
// TODO AV - improve - note: no room for improvement as long as aspects are reweavable | |||
// since the inlined version with wrappers and an to be done annotation to keep | |||
// TODO AV - improve - note: no room for improvement as long as aspects | |||
// are reweavable | |||
// since the inlined version with wrappers and an to be done annotation | |||
// to keep | |||
// inline state will be garbaged due to reweavable impl | |||
if (memberView != null && isAdviceMethod()) { | |||
if (enclosingClass.getType().isAnnotationStyleAspect()) { | |||
@@ -215,15 +222,18 @@ public final class LazyMethodGen implements Traceable { | |||
if ((m.isAbstract() || m.isNative()) && savedMethod.getCode() != null) { | |||
throw new RuntimeException("bad abstract method with code: " + m + " on " + enclosingClass); | |||
} | |||
// this.memberView = new BcelMethod(enclosingClass.getBcelObjectType(), m); | |||
// this.memberView = new BcelMethod(enclosingClass.getBcelObjectType(), | |||
// m); | |||
this.memberView = m; | |||
this.accessFlags = savedMethod.getModifiers(); | |||
this.name = m.getName(); | |||
// @AJ advice are not inlined by default since requires further analysis | |||
// and weaving ordering control | |||
// TODO AV - improve - note: no room for improvement as long as aspects are reweavable | |||
// since the inlined version with wrappers and an to be done annotation to keep | |||
// TODO AV - improve - note: no room for improvement as long as aspects | |||
// are reweavable | |||
// since the inlined version with wrappers and an to be done annotation | |||
// to keep | |||
// inline state will be garbaged due to reweavable impl | |||
if (memberView != null && isAdviceMethod()) { | |||
if (enclosingClass.getType().isAnnotationStyleAspect()) { | |||
@@ -254,7 +264,7 @@ public final class LazyMethodGen implements Traceable { | |||
} | |||
} | |||
public void addAnnotation(AnnotationX ax) { | |||
public void addAnnotation(AnnotationAJ ax) { | |||
initialize(); | |||
if (memberView == null) { | |||
// If member view is null, we manage them in newAnnotations | |||
@@ -272,9 +282,10 @@ public final class LazyMethodGen implements Traceable { | |||
// Check local annotations first | |||
if (newAnnotations != null) { | |||
for (Iterator iter = newAnnotations.iterator(); iter.hasNext();) { | |||
AnnotationX element = (AnnotationX) iter.next(); | |||
if (element.getBcelAnnotation().getTypeName().equals(annotationTypeX.getName())) | |||
AnnotationAJ element = (AnnotationAJ) iter.next(); | |||
if (element.getTypeSignature().equals(annotationTypeX.getSignature())) { | |||
return true; | |||
} | |||
} | |||
} | |||
memberView = new BcelMethod(getEnclosingClass().getBcelObjectType(), getMethod()); | |||
@@ -287,7 +298,8 @@ public final class LazyMethodGen implements Traceable { | |||
if (returnType != null) | |||
return; | |||
// System.err.println("initializing: " + getName() + ", " + enclosingClass.getName() + ", " + returnType + ", " + | |||
// System.err.println("initializing: " + getName() + ", " + | |||
// enclosingClass.getName() + ", " + returnType + ", " + | |||
// savedMethod); | |||
MethodGen gen = new MethodGen(savedMethod, enclosingClass.getName(), enclosingClass.getConstantPool(), true); | |||
@@ -301,9 +313,12 @@ public final class LazyMethodGen implements Traceable { | |||
this.maxLocals = gen.getMaxLocals(); | |||
// this.returnType = BcelWorld.makeBcelType(memberView.getReturnType()); | |||
// this.argumentTypes = BcelWorld.makeBcelTypes(memberView.getParameterTypes()); | |||
// this.argumentTypes = | |||
// BcelWorld.makeBcelTypes(memberView.getParameterTypes()); | |||
// | |||
// this.declaredExceptions = UnresolvedType.getNames(memberView.getExceptions()); //gen.getExceptions(); | |||
// this.declaredExceptions = | |||
// UnresolvedType.getNames(memberView.getExceptions()); | |||
// //gen.getExceptions(); | |||
// this.attributes = new Attribute[0]; //gen.getAttributes(); | |||
// this.maxLocals = savedMethod.getCode().getMaxLocals(); | |||
@@ -321,13 +336,17 @@ public final class LazyMethodGen implements Traceable { | |||
} | |||
assertGoodBody(); | |||
// System.err.println("initialized: " + this.getClassName() + "." + this.getName()); | |||
// System.err.println("initialized: " + this.getClassName() + "." + | |||
// this.getName()); | |||
} | |||
// XXX we're relying on the javac promise I've just made up that we won't have an early exception | |||
// XXX we're relying on the javac promise I've just made up that we won't | |||
// have an early exception | |||
// in the list mask a later exception: That is, for two exceptions E and F, | |||
// if E preceeds F, then either E \cup F = {}, or E \nonstrictsubset F. So when we add F, | |||
// we add it on the _OUTSIDE_ of any handlers that share starts or ends with it. | |||
// if E preceeds F, then either E \cup F = {}, or E \nonstrictsubset F. So | |||
// when we add F, | |||
// we add it on the _OUTSIDE_ of any handlers that share starts or ends with | |||
// it. | |||
// with that in mind, we merrily go adding ranges for exceptions. | |||
@@ -412,7 +431,8 @@ public final class LazyMethodGen implements Traceable { | |||
public Method getMethod() { | |||
if (savedMethod != null) | |||
return savedMethod; // ??? this relies on gentle treatment of constant pool | |||
return savedMethod; // ??? this relies on gentle treatment of | |||
// constant pool | |||
try { | |||
MethodGen gen = pack(); | |||
@@ -423,7 +443,8 @@ public final class LazyMethodGen implements Traceable { | |||
IMessage.ERROR, | |||
WeaverMessages.format(WeaverMessages.PROBLEM_GENERATING_METHOD, this.getClassName(), this.getName(), e | |||
.getMessage()), this.getMemberView() == null ? null : this.getMemberView().getSourceLocation(), null); | |||
// throw e; PR 70201.... let the normal problem reporting infrastructure deal with this rather than crashing. | |||
// throw e; PR 70201.... let the normal problem reporting | |||
// infrastructure deal with this rather than crashing. | |||
body = null; | |||
MethodGen gen = pack(); | |||
return gen.getMethod(); | |||
@@ -517,7 +538,8 @@ public final class LazyMethodGen implements Traceable { | |||
List as = Utility.readAjAttributes(getClassName(), (Attribute[]) attributes.toArray(new Attribute[] {}), context, null, | |||
weaverVersion); | |||
if (!as.isEmpty()) { | |||
out.println(" " + as.get(0)); // XXX assuming exactly one attribute, munger... | |||
out.println(" " + as.get(0)); // XXX assuming exactly one | |||
// attribute, munger... | |||
} | |||
} | |||
@@ -555,7 +577,11 @@ public final class LazyMethodGen implements Traceable { | |||
for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) { | |||
Iterator tIter = ih.getTargeters().iterator(); | |||
while (tIter.hasNext()) { | |||
InstructionTargeter t = (InstructionTargeter) tIter.next();// targeters[i]; | |||
InstructionTargeter t = (InstructionTargeter) tIter.next();// targeters | |||
// [ | |||
// i | |||
// ] | |||
// ; | |||
if (t instanceof ExceptionRange) { | |||
// assert isRangeHandle(h); | |||
ExceptionRange r = (ExceptionRange) t; | |||
@@ -594,13 +620,15 @@ public final class LazyMethodGen implements Traceable { | |||
bodyPrint: for (InstructionHandle ih = body.getStart(); ih != null; ih = ih.getNext()) { | |||
if (Range.isRangeHandle(ih)) { | |||
Range r = Range.getRange(ih); | |||
// don't print empty ranges, that is, ranges who contain no actual instructions | |||
// don't print empty ranges, that is, ranges who contain no | |||
// actual instructions | |||
for (InstructionHandle xx = r.getStart(); Range.isRangeHandle(xx); xx = xx.getNext()) { | |||
if (xx == r.getEnd()) | |||
continue bodyPrint; | |||
} | |||
// doesn't handle nested: if (r.getStart().getNext() == r.getEnd()) continue; | |||
// doesn't handle nested: if (r.getStart().getNext() == | |||
// r.getEnd()) continue; | |||
if (r.getStart() == ih) { | |||
printRangeString(r, depth++); | |||
} else { | |||
@@ -691,7 +719,8 @@ public final class LazyMethodGen implements Traceable { | |||
out.print(" "); | |||
out.print(labelMap.get(brinst.getTarget())); | |||
} else if (inst.isLocalVariableInstruction()) { | |||
// LocalVariableInstruction lvinst = (LocalVariableInstruction) inst; | |||
// LocalVariableInstruction lvinst = (LocalVariableInstruction) | |||
// inst; | |||
out.print(inst.toString(false).toUpperCase()); | |||
int index = inst.getIndex(); | |||
LocalVariableTag tag = getLocalVariableTag(h, index); | |||
@@ -864,15 +893,15 @@ public final class LazyMethodGen implements Traceable { | |||
if (newAnnotations != null) { | |||
for (Iterator iter = newAnnotations.iterator(); iter.hasNext();) { | |||
AnnotationX element = (AnnotationX) iter.next(); | |||
gen.addAnnotation(new AnnotationGen(element.getBcelAnnotation(), gen.getConstantPool(), true)); | |||
AnnotationAJ element = (AnnotationAJ) iter.next(); | |||
gen.addAnnotation(new AnnotationGen(((BcelAnnotation)element).getBcelAnnotation(), gen.getConstantPool(), true)); | |||
} | |||
} | |||
if (memberView != null && memberView.getAnnotations() != null && memberView.getAnnotations().length != 0) { | |||
AnnotationX[] ans = memberView.getAnnotations(); | |||
AnnotationAJ[] ans = memberView.getAnnotations(); | |||
for (int i = 0, len = ans.length; i < len; i++) { | |||
AnnotationGen a = ans[i].getBcelAnnotation(); | |||
AnnotationGen a = ((BcelAnnotation) ans[i]).getBcelAnnotation(); | |||
gen.addAnnotation(new AnnotationGen(a, gen.getConstantPool(), true)); | |||
} | |||
} | |||
@@ -881,7 +910,8 @@ public final class LazyMethodGen implements Traceable { | |||
if (enclosingClass.getWorld().isInJava5Mode()) { | |||
gen.setModifiers(gen.getModifiers() | ACC_SYNTHETIC); | |||
} | |||
// belt and braces, do the attribute even on Java 5 in addition to the modifier flag | |||
// belt and braces, do the attribute even on Java 5 in addition to | |||
// the modifier flag | |||
ConstantPool cpg = gen.getConstantPool(); | |||
int index = cpg.addUtf8("Synthetic"); | |||
gen.addAttribute(new Synthetic(index, 0, new byte[0], cpg)); | |||
@@ -950,7 +980,8 @@ public final class LazyMethodGen implements Traceable { | |||
while (oldInstructionHandle != null) { | |||
if (map.get(oldInstructionHandle) == null) { | |||
// must be a range instruction since they're the only things we didn't copy across | |||
// must be a range instruction since they're the only things we | |||
// didn't copy across | |||
handleRangeInstruction(oldInstructionHandle, exceptionList); | |||
// just increment ih. | |||
oldInstructionHandle = oldInstructionHandle.getNext(); | |||
@@ -977,7 +1008,8 @@ public final class LazyMethodGen implements Traceable { | |||
} else if (targeter instanceof LocalVariableTag) { | |||
LocalVariableTag lvt = (LocalVariableTag) targeter; | |||
LVPosition p = (LVPosition) localVariables.get(lvt); | |||
// If we don't know about it, create a new position and store | |||
// If we don't know about it, create a new position and | |||
// store | |||
// If we do know about it - update its end position | |||
if (p == null) { | |||
LVPosition newp = new LVPosition(); | |||
@@ -998,10 +1030,13 @@ public final class LazyMethodGen implements Traceable { | |||
addExceptionHandlers(gen, map, exceptionList); | |||
addLocalVariables(gen, localVariables); | |||
// JAVAC adds line number tables (with just one entry) to generated accessor methods - this | |||
// keeps some tools that rely on finding at least some form of linenumbertable happy. | |||
// JAVAC adds line number tables (with just one entry) to generated | |||
// accessor methods - this | |||
// keeps some tools that rely on finding at least some form of | |||
// linenumbertable happy. | |||
// Let's check if we have one - if we don't then let's add one. | |||
// TODO Could be made conditional on whether line debug info is being produced | |||
// TODO Could be made conditional on whether line debug info is being | |||
// produced | |||
if (gen.getLineNumbers().length == 0) { | |||
gen.addLineNumber(gen.getInstructionList().getStart(), 1); | |||
} | |||
@@ -1021,18 +1056,21 @@ public final class LazyMethodGen implements Traceable { | |||
LinkedList exceptionList = new LinkedList(); | |||
Set forDeletion = new HashSet(); | |||
Set branchInstructions = new HashSet(); | |||
// OPTIMIZE sort out in here: getRange()/insertHandler() and type of exceptionList | |||
// OPTIMIZE sort out in here: getRange()/insertHandler() and type of | |||
// exceptionList | |||
while (iHandle != null) { | |||
Instruction inst = iHandle.getInstruction(); | |||
// InstructionHandle nextInst = iHandle.getNext(); | |||
// OPTIMIZE remove this instructionhandle as it now points to nowhere? | |||
// OPTIMIZE remove this instructionhandle as it now points to | |||
// nowhere? | |||
if (inst == Range.RANGEINSTRUCTION) { | |||
Range r = Range.getRange(iHandle); | |||
if (r instanceof ExceptionRange) { | |||
ExceptionRange er = (ExceptionRange) r; | |||
if (er.getStart() == iHandle) { | |||
if (!er.isEmpty()) { | |||
// order is important, insert handlers in order of start | |||
// order is important, insert handlers in order of | |||
// start | |||
insertHandler(er, exceptionList); | |||
} | |||
} | |||
@@ -1056,7 +1094,8 @@ public final class LazyMethodGen implements Traceable { | |||
} else if (targeter instanceof LocalVariableTag) { | |||
LocalVariableTag lvt = (LocalVariableTag) targeter; | |||
LVPosition p = (LVPosition) localVariables.get(lvt); | |||
// If we don't know about it, create a new position and store | |||
// If we don't know about it, create a new position | |||
// and store | |||
// If we do know about it - update its end position | |||
if (p == null) { | |||
LVPosition newp = new LVPosition(); | |||
@@ -1095,10 +1134,13 @@ public final class LazyMethodGen implements Traceable { | |||
gen.setInstructionList(theBody); | |||
addLocalVariables(gen, localVariables); | |||
// JAVAC adds line number tables (with just one entry) to generated accessor methods - this | |||
// keeps some tools that rely on finding at least some form of linenumbertable happy. | |||
// JAVAC adds line number tables (with just one entry) to generated | |||
// accessor methods - this | |||
// keeps some tools that rely on finding at least some form of | |||
// linenumbertable happy. | |||
// Let's check if we have one - if we don't then let's add one. | |||
// TODO Could be made conditional on whether line debug info is being produced | |||
// TODO Could be made conditional on whether line debug info is being | |||
// produced | |||
if (gen.getLineNumbers().length == 0) { | |||
gen.addLineNumber(gen.getInstructionList().getStart(), 1); | |||
} | |||
@@ -1117,7 +1159,8 @@ public final class LazyMethodGen implements Traceable { | |||
Map duplicatedLocalMap = new HashMap(); | |||
for (Iterator iter = localVariables.keySet().iterator(); iter.hasNext();) { | |||
LocalVariableTag tag = (LocalVariableTag) iter.next(); | |||
// have we already added one with the same slot number and start location? | |||
// have we already added one with the same slot number and start | |||
// location? | |||
// if so, just continue. | |||
LVPosition lvpos = (LVPosition) localVariables.get(tag); | |||
InstructionHandle start = lvpos.start; | |||
@@ -1155,7 +1198,8 @@ public final class LazyMethodGen implements Traceable { | |||
private void handleBranchInstruction(Map map, Instruction oldInstruction, Instruction newInstruction) { | |||
InstructionBranch oldBranchInstruction = (InstructionBranch) oldInstruction; | |||
InstructionBranch newBranchInstruction = (InstructionBranch) newInstruction; | |||
InstructionHandle oldTarget = oldBranchInstruction.getTarget(); // old target | |||
InstructionHandle oldTarget = oldBranchInstruction.getTarget(); // old | |||
// target | |||
// New target is in hash map | |||
newBranchInstruction.setTarget(remap(oldTarget, map)); | |||
@@ -1301,18 +1345,24 @@ public final class LazyMethodGen implements Traceable { | |||
// block (pr78021,pr79554). | |||
// exception ordering. | |||
// What we should be doing is dealing with priority inversions way earlier than we are | |||
// and counting on the tree structure. In which case, the below code is in fact right. | |||
// What we should be doing is dealing with priority inversions way earlier | |||
// than we are | |||
// and counting on the tree structure. In which case, the below code is in | |||
// fact right. | |||
// XXX THIS COMMENT BELOW IS CURRENTLY WRONG. | |||
// An exception A preceeds an exception B in the exception table iff: | |||
// * A and B were in the original method, and A preceeded B in the original exception table | |||
// * A and B were in the original method, and A preceeded B in the original | |||
// exception table | |||
// * If A has a higher priority than B, than it preceeds B. | |||
// * If A and B have the same priority, then the one whose START happens EARLIEST has LEAST priority. | |||
// * If A and B have the same priority, then the one whose START happens | |||
// EARLIEST has LEAST priority. | |||
// in short, the outermost exception has least priority. | |||
// we implement this with a LinkedList. We could possibly implement this with a java.util.SortedSet, | |||
// but I don't trust the only implementation, TreeSet, to do the right thing. | |||
// we implement this with a LinkedList. We could possibly implement this | |||
// with a java.util.SortedSet, | |||
// but I don't trust the only implementation, TreeSet, to do the right | |||
// thing. | |||
/* private */static void insertHandler(ExceptionRange fresh, LinkedList l) { | |||
// Old implementation, simply: l.add(0,fresh); | |||
@@ -1369,8 +1419,11 @@ public final class LazyMethodGen implements Traceable { | |||
public void assertGoodBody() { | |||
if (true) | |||
return; // only enable for debugging, consider using cheaper toString() | |||
assertGoodBody(getBody(), toString()); // definingType.getNameAsIdentifier() + "." + getName()); //toString()); | |||
return; // only enable for debugging, consider using cheaper | |||
// toString() | |||
assertGoodBody(getBody(), toString()); // definingType.getNameAsIdentifier | |||
// () + "." + getName()); | |||
// //toString()); | |||
} | |||
public static void assertGoodBody(InstructionList il, String from) { |
@@ -54,7 +54,7 @@ import org.aspectj.apache.bcel.generic.TargetLostException; | |||
import org.aspectj.apache.bcel.generic.Type; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.Lint; | |||
@@ -112,7 +112,8 @@ public class Utility { | |||
if (isl == null || isl.getSourceFile() == null || isl.getSourceFile().getName().indexOf("no debug info available") != -1) { | |||
nice.append("no debug info available"); | |||
} else { | |||
// can't use File.getName() as this fails when a Linux box encounters a path created on Windows and vice-versa | |||
// can't use File.getName() as this fails when a Linux box | |||
// encounters a path created on Windows and vice-versa | |||
int takeFrom = isl.getSourceFile().getPath().lastIndexOf('/'); | |||
if (takeFrom == -1) { | |||
takeFrom = isl.getSourceFile().getPath().lastIndexOf('\\'); | |||
@@ -268,7 +269,8 @@ public class Utility { | |||
private static String[] argNames = new String[] { "arg0", "arg1", "arg2", "arg3", "arg4" }; | |||
// ??? these should perhaps be cached. Remember to profile this to see if it's a problem. | |||
// ??? these should perhaps be cached. Remember to profile this to see if | |||
// it's a problem. | |||
public static String[] makeArgNames(int n) { | |||
String[] ret = new String[n]; | |||
for (int i = 0; i < n; i++) { | |||
@@ -308,7 +310,8 @@ public class Utility { | |||
if (!toType.isConvertableFrom(fromType) && !fromType.isConvertableFrom(toType)) { | |||
throw new BCException("can't convert from " + fromType + " to " + toType); | |||
} | |||
// XXX I'm sure this test can be simpler but my brain hurts and this works | |||
// XXX I'm sure this test can be simpler but my brain hurts and this | |||
// works | |||
if (!toType.getWorld().isInJava5Mode()) { | |||
if (toType.needsNoConversionFrom(fromType)) | |||
return; | |||
@@ -339,7 +342,8 @@ public class Utility { | |||
il.append(fact.createInvoke("org.aspectj.runtime.internal.Conversions", name, Type.OBJECT, new Type[] { from }, | |||
Constants.INVOKESTATIC)); | |||
} else if (toType.getWorld().isInJava5Mode() && validBoxing.get(toType.getSignature() + fromType.getSignature()) != null) { | |||
// XXX could optimize by using any java boxing code that may be just before the call... | |||
// XXX could optimize by using any java boxing code that may be just | |||
// before the call... | |||
Type from = BcelWorld.makeBcelType(fromType); | |||
Type to = BcelWorld.makeBcelType(toType); | |||
String name = (String) validBoxing.get(toType.getSignature() + fromType.getSignature()); | |||
@@ -598,7 +602,8 @@ public class Utility { | |||
} | |||
/** returns -1 if no source line attribute */ | |||
// this naive version overruns the JVM stack size, if only Java understood tail recursion... | |||
// this naive version overruns the JVM stack size, if only Java understood | |||
// tail recursion... | |||
// public static int getSourceLine(InstructionHandle ih) { | |||
// if (ih == null) return -1; | |||
// | |||
@@ -613,9 +618,11 @@ public class Utility { | |||
// } | |||
// return getSourceLine(ih.getNext()); | |||
// } | |||
public static int getSourceLine(InstructionHandle ih) {// ,boolean goforwards) { | |||
public static int getSourceLine(InstructionHandle ih) {// ,boolean | |||
// goforwards) { | |||
int lookahead = 0; | |||
// arbitrary rule that we will never lookahead more than 100 instructions for a line # | |||
// arbitrary rule that we will never lookahead more than 100 | |||
// instructions for a line # | |||
while (lookahead++ < 100) { | |||
if (ih == null) | |||
return -1; | |||
@@ -637,9 +644,11 @@ public class Utility { | |||
// return getSourceLine(ih,false); | |||
// } | |||
// assumes that there is no already extant source line tag. Otherwise we'll have to be better. | |||
// assumes that there is no already extant source line tag. Otherwise we'll | |||
// have to be better. | |||
public static void setSourceLine(InstructionHandle ih, int lineNumber) { | |||
// OPTIMIZE LineNumberTag instances for the same line could be shared throughout a method... | |||
// OPTIMIZE LineNumberTag instances for the same line could be shared | |||
// throughout a method... | |||
ih.addTargeter(new LineNumberTag(lineNumber)); | |||
} | |||
@@ -687,18 +696,19 @@ public class Utility { | |||
* (identified by its key) should be ignored. | |||
* | |||
*/ | |||
public static boolean isSuppressing(AnnotationX[] anns, String lintkey) { | |||
public static boolean isSuppressing(AnnotationAJ[] anns, String lintkey) { | |||
if (anns == null) | |||
return false; | |||
boolean suppressed = false; | |||
// Go through the annotation types on the advice | |||
for (int i = 0; !suppressed && i < anns.length; i++) { | |||
// Check for the SuppressAjWarnings annotation | |||
if (UnresolvedType.SUPPRESS_AJ_WARNINGS.getSignature().equals(anns[i].getBcelAnnotation().getTypeSignature())) { | |||
if (UnresolvedType.SUPPRESS_AJ_WARNINGS.getSignature().equals(anns[i].getTypeSignature())) { | |||
// Two possibilities: | |||
// 1. there are no values specified (i.e. @SuppressAjWarnings) | |||
// 2. there are values specified (i.e. @SuppressAjWarnings("A") or @SuppressAjWarnings({"A","B"}) | |||
List vals = anns[i].getBcelAnnotation().getValues(); | |||
// 2. there are values specified (i.e. @SuppressAjWarnings("A") | |||
// or @SuppressAjWarnings({"A","B"}) | |||
List vals = ((BcelAnnotation) anns[i]).getBcelAnnotation().getValues(); | |||
if (vals == null || vals.isEmpty()) { // (1) | |||
suppressed = true; | |||
} else { // (2) | |||
@@ -718,7 +728,7 @@ public class Utility { | |||
return suppressed; | |||
} | |||
public static List/* Lint.Kind */getSuppressedWarnings(AnnotationX[] anns, Lint lint) { | |||
public static List/* Lint.Kind */getSuppressedWarnings(AnnotationAJ[] anns, Lint lint) { | |||
if (anns == null) | |||
return Collections.EMPTY_LIST; | |||
// Go through the annotation types | |||
@@ -726,12 +736,14 @@ public class Utility { | |||
boolean found = false; | |||
for (int i = 0; !found && i < anns.length; i++) { | |||
// Check for the SuppressAjWarnings annotation | |||
if (UnresolvedType.SUPPRESS_AJ_WARNINGS.getSignature().equals(anns[i].getBcelAnnotation().getTypeSignature())) { | |||
if (UnresolvedType.SUPPRESS_AJ_WARNINGS.getSignature().equals( | |||
((BcelAnnotation) anns[i]).getBcelAnnotation().getTypeSignature())) { | |||
found = true; | |||
// Two possibilities: | |||
// 1. there are no values specified (i.e. @SuppressAjWarnings) | |||
// 2. there are values specified (i.e. @SuppressAjWarnings("A") or @SuppressAjWarnings({"A","B"}) | |||
List vals = anns[i].getBcelAnnotation().getValues(); | |||
// 2. there are values specified (i.e. @SuppressAjWarnings("A") | |||
// or @SuppressAjWarnings({"A","B"}) | |||
List vals = ((BcelAnnotation) anns[i]).getBcelAnnotation().getValues(); | |||
if (vals == null || vals.isEmpty()) { // (1) | |||
suppressedWarnings.addAll(lint.allKinds()); | |||
} else { // (2) | |||
@@ -755,18 +767,21 @@ public class Utility { | |||
// public static boolean isSimple(Method method) { | |||
// if (method.getCode()==null) return true; | |||
// if (method.getCode().getCode().length>10) return false; | |||
// InstructionList instrucs = new InstructionList(method.getCode().getCode()); // expensive! | |||
// InstructionList instrucs = new | |||
// InstructionList(method.getCode().getCode()); // expensive! | |||
// InstructionHandle InstrHandle = instrucs.getStart(); | |||
// while (InstrHandle != null) { | |||
// Instruction Instr = InstrHandle.getInstruction(); | |||
// int opCode = Instr.opcode; | |||
// // if current instruction is a branch instruction, see if it's a backward branch. | |||
// // if current instruction is a branch instruction, see if it's a backward | |||
// branch. | |||
// // if it is return immediately (can't be trivial) | |||
// if (Instr instanceof InstructionBranch) { | |||
// // InstructionBranch BI = (InstructionBranch) Instr; | |||
// if (Instr.getIndex() < 0) return false; | |||
// } else if (Instr instanceof InvokeInstruction) { | |||
// // if current instruction is an invocation, indicate that it can't be trivial | |||
// // if current instruction is an invocation, indicate that it can't be | |||
// trivial | |||
// return false; | |||
// } | |||
// InstrHandle = InstrHandle.getNext(); |
@@ -18,7 +18,7 @@ import java.util.Iterator; | |||
import java.util.Map; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedType; | |||
@@ -28,111 +28,124 @@ import org.aspectj.weaver.WeaverMessages; | |||
import org.aspectj.weaver.World; | |||
public class DeclareAnnotation extends Declare { | |||
public static final Kind AT_TYPE = new Kind(1,"type"); | |||
public static final Kind AT_FIELD = new Kind(2,"field"); | |||
public static final Kind AT_METHOD = new Kind(3,"method"); | |||
public static final Kind AT_CONSTRUCTOR = new Kind(4,"constructor"); | |||
public static final Kind AT_TYPE = new Kind(1, "type"); | |||
public static final Kind AT_FIELD = new Kind(2, "field"); | |||
public static final Kind AT_METHOD = new Kind(3, "method"); | |||
public static final Kind AT_CONSTRUCTOR = new Kind(4, "constructor"); | |||
private Kind kind; | |||
private TypePattern typePattern; // for declare @type | |||
private SignaturePattern sigPattern; // for declare @field,@method,@constructor | |||
private TypePattern typePattern; // for declare @type | |||
private SignaturePattern sigPattern; // for declare | |||
// @field,@method,@constructor | |||
private String annotationMethod = "unknown"; | |||
private String annotationString = "@<annotation>"; | |||
private ResolvedType containingAspect; | |||
private AnnotationX annotation; | |||
/** | |||
* Captures type of declare annotation (method/type/field/constructor) | |||
*/ | |||
private AnnotationAJ annotation; | |||
/** | |||
* Captures type of declare annotation (method/type/field/constructor) | |||
*/ | |||
public static class Kind { | |||
private final int id; | |||
private String s; | |||
private Kind(int n,String name) { | |||
private Kind(int n, String name) { | |||
id = n; | |||
s = name; | |||
} | |||
public int hashCode() { | |||
return (19 + 37*id); | |||
return (19 + 37 * id); | |||
} | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof Kind)) return false; | |||
Kind other = (Kind) obj; | |||
return other.id == id; | |||
} | |||
public String toString() { | |||
return "at_"+s; | |||
} | |||
} | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof Kind)) | |||
return false; | |||
Kind other = (Kind) obj; | |||
return other.id == id; | |||
} | |||
public String toString() { | |||
return "at_" + s; | |||
} | |||
} | |||
public DeclareAnnotation(Kind kind, TypePattern typePattern) { | |||
this.typePattern = typePattern; | |||
this.kind = kind; | |||
} | |||
/** | |||
* Returns the string, useful before the real annotation has been resolved | |||
*/ | |||
public String getAnnotationString() { return annotationString;} | |||
/** | |||
* Returns the string, useful before the real annotation has been resolved | |||
*/ | |||
public String getAnnotationString() { | |||
return annotationString; | |||
} | |||
public DeclareAnnotation(Kind kind, SignaturePattern sigPattern) { | |||
this.sigPattern = sigPattern; | |||
this.kind = kind; | |||
} | |||
public boolean isExactPattern() { | |||
return typePattern instanceof ExactTypePattern; | |||
} | |||
public String getAnnotationMethod() { return annotationMethod;} | |||
public String getAnnotationMethod() { | |||
return annotationMethod; | |||
} | |||
public String toString() { | |||
StringBuffer ret = new StringBuffer(); | |||
ret.append("declare @"); | |||
ret.append(kind); | |||
ret.append(" : "); | |||
ret.append(typePattern != null ? typePattern.toString() : sigPattern.toString()); | |||
ret.append(typePattern != null ? typePattern.toString() : sigPattern | |||
.toString()); | |||
ret.append(" : "); | |||
ret.append(annotationString); | |||
return ret.toString(); | |||
} | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this,data); | |||
return visitor.visit(this, data); | |||
} | |||
public void resolve(IScope scope) { | |||
if (!scope.getWorld().isInJava5Mode()) { | |||
String msg = null; | |||
if (kind == AT_TYPE) { msg = WeaverMessages.DECLARE_ATTYPE_ONLY_SUPPORTED_AT_JAVA5_LEVEL; } | |||
else if (kind == AT_METHOD) { msg = WeaverMessages.DECLARE_ATMETHOD_ONLY_SUPPORTED_AT_JAVA5_LEVEL;} | |||
else if (kind == AT_FIELD) { msg = WeaverMessages.DECLARE_ATFIELD_ONLY_SUPPORTED_AT_JAVA5_LEVEL;} | |||
else if (kind == AT_CONSTRUCTOR) { msg = WeaverMessages.DECLARE_ATCONS_ONLY_SUPPORTED_AT_JAVA5_LEVEL;} | |||
if (kind == AT_TYPE) { | |||
msg = WeaverMessages.DECLARE_ATTYPE_ONLY_SUPPORTED_AT_JAVA5_LEVEL; | |||
} else if (kind == AT_METHOD) { | |||
msg = WeaverMessages.DECLARE_ATMETHOD_ONLY_SUPPORTED_AT_JAVA5_LEVEL; | |||
} else if (kind == AT_FIELD) { | |||
msg = WeaverMessages.DECLARE_ATFIELD_ONLY_SUPPORTED_AT_JAVA5_LEVEL; | |||
} else if (kind == AT_CONSTRUCTOR) { | |||
msg = WeaverMessages.DECLARE_ATCONS_ONLY_SUPPORTED_AT_JAVA5_LEVEL; | |||
} | |||
scope.message(MessageUtil.error(WeaverMessages.format(msg), | |||
getSourceLocation())); | |||
return; | |||
} | |||
if (typePattern != null) { | |||
typePattern = typePattern.resolveBindings(scope,Bindings.NONE,false,false); | |||
typePattern = typePattern.resolveBindings(scope, Bindings.NONE, | |||
false, false); | |||
} | |||
if (sigPattern != null) { | |||
sigPattern = sigPattern.resolveBindings(scope,Bindings.NONE); | |||
sigPattern = sigPattern.resolveBindings(scope, Bindings.NONE); | |||
} | |||
this.containingAspect = scope.getEnclosingType(); | |||
} | |||
public Declare parameterizeWith(Map typeVariableBindingMap,World w) { | |||
public Declare parameterizeWith(Map typeVariableBindingMap, World w) { | |||
DeclareAnnotation ret; | |||
if (this.kind == AT_TYPE) { | |||
ret = new DeclareAnnotation(kind,this.typePattern.parameterizeWith(typeVariableBindingMap,w)); | |||
ret = new DeclareAnnotation(kind, this.typePattern | |||
.parameterizeWith(typeVariableBindingMap, w)); | |||
} else { | |||
ret = new DeclareAnnotation(kind, this.sigPattern.parameterizeWith(typeVariableBindingMap,w)); | |||
ret = new DeclareAnnotation(kind, this.sigPattern.parameterizeWith( | |||
typeVariableBindingMap, w)); | |||
} | |||
ret.annotationMethod = this.annotationMethod; | |||
ret.annotationString = this.annotationString; | |||
@@ -141,7 +154,7 @@ public class DeclareAnnotation extends Declare { | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} | |||
public boolean isAdviceLike() { | |||
return false; | |||
} | |||
@@ -149,49 +162,60 @@ public class DeclareAnnotation extends Declare { | |||
public void setAnnotationString(String as) { | |||
this.annotationString = as; | |||
} | |||
public void setAnnotationMethod(String methName){ | |||
public void setAnnotationMethod(String methName) { | |||
this.annotationMethod = methName; | |||
} | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof DeclareAnnotation)) return false; | |||
if (!(obj instanceof DeclareAnnotation)) | |||
return false; | |||
DeclareAnnotation other = (DeclareAnnotation) obj; | |||
if (!this.kind.equals(other.kind)) return false; | |||
if (!this.annotationString.equals(other.annotationString)) return false; | |||
if (!this.annotationMethod.equals(other.annotationMethod)) return false; | |||
if (!this.kind.equals(other.kind)) | |||
return false; | |||
if (!this.annotationString.equals(other.annotationString)) | |||
return false; | |||
if (!this.annotationMethod.equals(other.annotationMethod)) | |||
return false; | |||
if (this.typePattern != null) { | |||
if (!typePattern.equals(other.typePattern)) return false; | |||
if (!typePattern.equals(other.typePattern)) | |||
return false; | |||
} | |||
if (this.sigPattern != null) { | |||
if (!sigPattern.equals(other.sigPattern)) return false; | |||
if (!sigPattern.equals(other.sigPattern)) | |||
return false; | |||
} | |||
return true; | |||
} | |||
public int hashCode() { | |||
int result = 19; | |||
result = 37*result + kind.hashCode(); | |||
result = 37*result + annotationString.hashCode(); | |||
result = 37*result + annotationMethod.hashCode(); | |||
if (typePattern != null) result = 37*result + typePattern.hashCode(); | |||
if (sigPattern != null) result = 37*result + sigPattern.hashCode(); | |||
return result; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) | |||
int result = 19; | |||
result = 37 * result + kind.hashCode(); | |||
result = 37 * result + annotationString.hashCode(); | |||
result = 37 * result + annotationMethod.hashCode(); | |||
if (typePattern != null) | |||
result = 37 * result + typePattern.hashCode(); | |||
if (sigPattern != null) | |||
result = 37 * result + sigPattern.hashCode(); | |||
return result; | |||
} | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) | |||
*/ | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeByte(Declare.ANNOTATION); | |||
s.writeInt(kind.id); | |||
s.writeUTF(annotationString); | |||
s.writeUTF(annotationMethod); | |||
if (typePattern != null) typePattern.write(s); | |||
if (sigPattern != null) sigPattern.write(s); | |||
writeLocation(s); | |||
if (typePattern != null) | |||
typePattern.write(s); | |||
if (sigPattern != null) | |||
sigPattern.write(s); | |||
writeLocation(s); | |||
} | |||
public static Declare read(VersionedDataInputStream s, | |||
@@ -203,61 +227,60 @@ public class DeclareAnnotation extends Declare { | |||
TypePattern tp = null; | |||
SignaturePattern sp = null; | |||
switch (kind) { | |||
case 1: | |||
tp = TypePattern.read(s,context); | |||
ret = new DeclareAnnotation(AT_TYPE,tp); | |||
case 1: | |||
tp = TypePattern.read(s, context); | |||
ret = new DeclareAnnotation(AT_TYPE, tp); | |||
break; | |||
case 2: | |||
sp = SignaturePattern.read(s,context); | |||
ret = new DeclareAnnotation(AT_FIELD,sp); | |||
case 2: | |||
sp = SignaturePattern.read(s, context); | |||
ret = new DeclareAnnotation(AT_FIELD, sp); | |||
break; | |||
case 3: | |||
sp = SignaturePattern.read(s,context); | |||
ret = new DeclareAnnotation(AT_METHOD,sp); | |||
case 3: | |||
sp = SignaturePattern.read(s, context); | |||
ret = new DeclareAnnotation(AT_METHOD, sp); | |||
break; | |||
case 4: | |||
sp = SignaturePattern.read(s,context); | |||
ret = new DeclareAnnotation(AT_CONSTRUCTOR,sp); | |||
case 4: | |||
sp = SignaturePattern.read(s, context); | |||
ret = new DeclareAnnotation(AT_CONSTRUCTOR, sp); | |||
break; | |||
} | |||
// if (kind==AT_TYPE.id) { | |||
// tp = TypePattern.read(s,context); | |||
// ret = new DeclareAnnotation(AT_TYPE,tp); | |||
// } else { | |||
// sp = SignaturePattern.read(s,context); | |||
// ret = new DeclareAnnotation(kind,sp); | |||
// } | |||
// if (kind==AT_TYPE.id) { | |||
// tp = TypePattern.read(s,context); | |||
// ret = new DeclareAnnotation(AT_TYPE,tp); | |||
// } else { | |||
// sp = SignaturePattern.read(s,context); | |||
// ret = new DeclareAnnotation(kind,sp); | |||
// } | |||
ret.setAnnotationString(annotationString); | |||
ret.setAnnotationMethod(annotationMethod); | |||
ret.readLocation(context,s); | |||
ret.readLocation(context, s); | |||
return ret; | |||
} | |||
// public boolean getAnnotationIfMatches(ResolvedType onType) { | |||
// return (match(onType)); | |||
// } | |||
// public boolean getAnnotationIfMatches(ResolvedType onType) { | |||
// return (match(onType)); | |||
// } | |||
/** | |||
* For @constructor, @method, @field | |||
*/ | |||
public boolean matches(ResolvedMember rm,World world) { | |||
return sigPattern.matches(rm,world,false); | |||
/** | |||
* For @constructor, @method, @field | |||
*/ | |||
public boolean matches(ResolvedMember rm, World world) { | |||
return sigPattern.matches(rm, world, false); | |||
} | |||
/** | |||
* For @type | |||
*/ | |||
/** | |||
* For @type | |||
*/ | |||
public boolean matches(ResolvedType typeX) { | |||
if (!typePattern.matchesStatically(typeX)) return false; | |||
if (typeX.getWorld().getLint().typeNotExposedToWeaver.isEnabled() && | |||
!typeX.isExposedToWeaver()) | |||
{ | |||
typeX.getWorld().getLint().typeNotExposedToWeaver.signal(typeX.getName(), getSourceLocation()); | |||
if (!typePattern.matchesStatically(typeX)) | |||
return false; | |||
if (typeX.getWorld().getLint().typeNotExposedToWeaver.isEnabled() | |||
&& !typeX.isExposedToWeaver()) { | |||
typeX.getWorld().getLint().typeNotExposedToWeaver.signal(typeX | |||
.getName(), getSourceLocation()); | |||
} | |||
return true; | |||
return true; | |||
} | |||
public void setAspect(ResolvedType typeX) { | |||
@@ -270,47 +293,49 @@ public class DeclareAnnotation extends Declare { | |||
public void copyAnnotationTo(ResolvedType onType) { | |||
ensureAnnotationDiscovered(); | |||
if (!onType.hasAnnotation(annotation.getSignature())) { | |||
onType.addAnnotation(annotation); | |||
if (!onType.hasAnnotation(annotation.getType())) { | |||
onType.addAnnotation(annotation); | |||
} | |||
} | |||
public AnnotationX getAnnotationX() { | |||
public AnnotationAJ getAnnotationX() { | |||
ensureAnnotationDiscovered(); | |||
return annotation; | |||
} | |||
/** | |||
* The annotation specified in the declare @type is stored against | |||
* a simple method of the form "ajc$declare_<NN>", this method | |||
* finds that method and retrieves the annotation | |||
* The annotation specified in the declare @type is stored against a simple | |||
* method of the form "ajc$declare_<NN>", this method finds that method and | |||
* retrieves the annotation | |||
*/ | |||
private void ensureAnnotationDiscovered() { | |||
if (annotation!=null) return; | |||
if (annotation != null) | |||
return; | |||
for (Iterator iter = containingAspect.getMethods(); iter.hasNext();) { | |||
ResolvedMember member = (ResolvedMember) iter.next(); | |||
if (member.getName().equals(annotationMethod)) { | |||
annotation = member.getAnnotations()[0]; | |||
} | |||
} | |||
} | |||
} | |||
public TypePattern getTypePattern() { | |||
return typePattern; | |||
} | |||
public SignaturePattern getSignaturePattern() { | |||
return sigPattern; | |||
} | |||
public boolean isStarredAnnotationPattern() { | |||
if (typePattern!=null) return typePattern.isStarAnnotation(); | |||
if (sigPattern!=null) return sigPattern.isStarAnnotation(); | |||
throw new RuntimeException("Impossible! what kind of deca is this: "+this); | |||
if (typePattern != null) | |||
return typePattern.isStarAnnotation(); | |||
if (sigPattern != null) | |||
return sigPattern.isStarAnnotation(); | |||
throw new RuntimeException("Impossible! what kind of deca is this: " | |||
+ this); | |||
} | |||
public Kind getKind() { | |||
return kind; | |||
} | |||
@@ -318,61 +343,66 @@ public class DeclareAnnotation extends Declare { | |||
public boolean isDeclareAtConstuctor() { | |||
return kind.equals(AT_CONSTRUCTOR); | |||
} | |||
public boolean isDeclareAtMethod() { | |||
return kind.equals(AT_METHOD); | |||
} | |||
public boolean isDeclareAtType() { | |||
return kind.equals(AT_TYPE); | |||
} | |||
public boolean isDeclareAtField() { | |||
return kind.equals(AT_FIELD); | |||
} | |||
/** | |||
* @return UnresolvedType for the annotation | |||
*/ | |||
/** | |||
* @return UnresolvedType for the annotation | |||
*/ | |||
public UnresolvedType getAnnotationTypeX() { | |||
ensureAnnotationDiscovered(); | |||
return this.annotation.getSignature(); | |||
ensureAnnotationDiscovered(); | |||
return this.annotation.getType(); | |||
} | |||
/** | |||
* @return true if the annotation specified is allowed on a field | |||
*/ | |||
public boolean isAnnotationAllowedOnField() { | |||
ensureAnnotationDiscovered(); | |||
ensureAnnotationDiscovered(); | |||
return annotation.allowedOnField(); | |||
} | |||
public String getPatternAsString() { | |||
if (sigPattern!=null) return sigPattern.toString(); | |||
if (typePattern!=null) return typePattern.toString(); | |||
return "DONT KNOW"; | |||
if (sigPattern != null) | |||
return sigPattern.toString(); | |||
if (typePattern != null) | |||
return typePattern.toString(); | |||
return "DONT KNOW"; | |||
} | |||
/** | |||
* Return true if this declare annotation could ever match something | |||
* in the specified type - only really able to make intelligent | |||
* decision if a type was specified in the sig/type pattern | |||
* signature. | |||
* Return true if this declare annotation could ever match something in the | |||
* specified type - only really able to make intelligent decision if a type | |||
* was specified in the sig/type pattern signature. | |||
*/ | |||
public boolean couldEverMatch(ResolvedType type) { | |||
// Haven't implemented variant for typePattern (doesn't seem worth it!) | |||
// BUGWARNING This test might not be sufficient for funny cases relating | |||
// Haven't implemented variant for typePattern (doesn't seem worth it!) | |||
// BUGWARNING This test might not be sufficient for funny cases relating | |||
// to interfaces and the use of '+' - but it seems really important to | |||
// do something here so we don't iterate over all fields and all methods | |||
// in all types exposed to the weaver! So look out for bugs here and | |||
// in all types exposed to the weaver! So look out for bugs here and | |||
// we can update the test as appropriate. | |||
if (sigPattern!=null) | |||
return sigPattern.getDeclaringType().matches(type,TypePattern.STATIC).maybeTrue(); | |||
if (sigPattern != null) | |||
return sigPattern.getDeclaringType().matches(type, | |||
TypePattern.STATIC).maybeTrue(); | |||
return true; | |||
} | |||
/** | |||
* Provide a name suffix so that we can tell the different declare annotations | |||
* forms apart in the AjProblemReporter | |||
* Provide a name suffix so that we can tell the different declare | |||
* annotations forms apart in the AjProblemReporter | |||
*/ | |||
public String getNameSuffix() { | |||
return getKind().toString(); | |||
return getKind().toString(); | |||
} | |||
} |
@@ -20,7 +20,7 @@ import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.util.FuzzyBoolean; | |||
import org.aspectj.weaver.AnnotatedElement; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.ReferenceType; | |||
@@ -43,14 +43,16 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
protected boolean resolved = false; | |||
protected boolean bindingPattern = false; | |||
private Map annotationValues; | |||
// OPTIMIZE is annotationtype really unresolved???? surely it is resolved by now... | |||
public ExactAnnotationTypePattern(UnresolvedType annotationType, Map annotationValues) { | |||
// OPTIMIZE is annotationtype really unresolved???? surely it is resolved by | |||
// now... | |||
public ExactAnnotationTypePattern(UnresolvedType annotationType, | |||
Map annotationValues) { | |||
this.annotationType = annotationType; | |||
this.annotationValues = annotationValues; | |||
this.resolved = (annotationType instanceof ResolvedType); | |||
} | |||
// Used when deserializing, values will be added | |||
private ExactAnnotationTypePattern(UnresolvedType annotationType) { | |||
this.annotationType = annotationType; | |||
@@ -65,114 +67,144 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
} | |||
public ResolvedType getResolvedAnnotationType() { | |||
if (!resolved) throw new IllegalStateException("I need to be resolved first!"); | |||
if (!resolved) | |||
throw new IllegalStateException("I need to be resolved first!"); | |||
return (ResolvedType) annotationType; | |||
} | |||
public UnresolvedType getAnnotationType() { | |||
return annotationType; | |||
} | |||
public Map getAnnotationValues() { | |||
return annotationValues; | |||
} | |||
public UnresolvedType getAnnotationType() { | |||
return annotationType; | |||
} | |||
public Map getAnnotationValues() { | |||
return annotationValues; | |||
} | |||
public FuzzyBoolean fastMatches(AnnotatedElement annotated) { | |||
if (annotated.hasAnnotation(annotationType) && annotationValues == null) { | |||
return FuzzyBoolean.YES; | |||
} else { | |||
// could be inherited, but we don't know that until we are | |||
// could be inherited, but we don't know that until we are | |||
// resolved, and we're not yet... | |||
return FuzzyBoolean.MAYBE; | |||
} | |||
} | |||
public FuzzyBoolean matches(AnnotatedElement annotated) { | |||
return matches(annotated,null); | |||
return matches(annotated, null); | |||
} | |||
public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) { | |||
public FuzzyBoolean matches(AnnotatedElement annotated, | |||
ResolvedType[] parameterAnnotations) { | |||
if (!isForParameterAnnotationMatch()) { | |||
boolean checkSupers = false; | |||
if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) { | |||
if (getResolvedAnnotationType().hasAnnotation( | |||
UnresolvedType.AT_INHERITED)) { | |||
if (annotated instanceof ResolvedType) { | |||
checkSupers = true; | |||
} | |||
} | |||
if (annotated.hasAnnotation(annotationType)) { | |||
if (annotationType instanceof ReferenceType) { | |||
ReferenceType rt = (ReferenceType)annotationType; | |||
if (rt.getRetentionPolicy()!=null && rt.getRetentionPolicy().equals("SOURCE")) { | |||
rt.getWorld().getMessageHandler().handleMessage( | |||
MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,annotationType,annotated),getSourceLocation())); | |||
ReferenceType rt = (ReferenceType) annotationType; | |||
if (rt.getRetentionPolicy() != null | |||
&& rt.getRetentionPolicy().equals("SOURCE")) { | |||
rt | |||
.getWorld() | |||
.getMessageHandler() | |||
.handleMessage( | |||
MessageUtil | |||
.warn( | |||
WeaverMessages | |||
.format( | |||
WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION, | |||
annotationType, | |||
annotated), | |||
getSourceLocation())); | |||
return FuzzyBoolean.NO; | |||
} | |||
} | |||
// Are we also matching annotation values? | |||
if (annotationValues!=null) { | |||
AnnotationX theAnnotation = annotated.getAnnotationOfType(annotationType); | |||
if (annotationValues != null) { | |||
AnnotationAJ theAnnotation = annotated | |||
.getAnnotationOfType(annotationType); | |||
// Check each one | |||
Set keys = annotationValues.keySet(); | |||
for (Iterator keyIter = keys.iterator(); keyIter.hasNext();) { | |||
String k = (String) keyIter.next(); | |||
String v = (String)annotationValues.get(k); | |||
String v = (String) annotationValues.get(k); | |||
if (theAnnotation.hasNamedValue(k)) { | |||
// Simple case, value is 'name=value' and the annotation specified the same thing | |||
if (!theAnnotation.hasNameValuePair(k,v)) { | |||
// Simple case, value is 'name=value' and the | |||
// annotation specified the same thing | |||
if (!theAnnotation.hasNameValuePair(k, v)) { | |||
return FuzzyBoolean.NO; | |||
} | |||
} | |||
} else { | |||
// Complex case, look at the default value | |||
ResolvedMember[] ms = ((ResolvedType)annotationType).getDeclaredMethods(); | |||
ResolvedMember[] ms = ((ResolvedType) annotationType) | |||
.getDeclaredMethods(); | |||
boolean foundMatch = false; | |||
for (int i=0; i<ms.length && !foundMatch;i++) { | |||
if (ms[i].isAbstract() && ms[i].getParameterTypes().length==0 && ms[i].getName().equals(k)) { | |||
for (int i = 0; i < ms.length && !foundMatch; i++) { | |||
if (ms[i].isAbstract() | |||
&& ms[i].getParameterTypes().length == 0 | |||
&& ms[i].getName().equals(k)) { | |||
// we might be onto something | |||
String s= ms[i].getAnnotationDefaultValue(); | |||
if (s!=null && s.equals(v)) foundMatch=true; | |||
String s = ms[i] | |||
.getAnnotationDefaultValue(); | |||
if (s != null && s.equals(v)) | |||
foundMatch = true; | |||
} | |||
} | |||
if (!foundMatch) | |||
return FuzzyBoolean.NO; | |||
return FuzzyBoolean.NO; | |||
} | |||
} | |||
} | |||
return FuzzyBoolean.YES; | |||
} else if (checkSupers) { | |||
ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass(); | |||
ResolvedType toMatchAgainst = ((ResolvedType) annotated) | |||
.getSuperclass(); | |||
while (toMatchAgainst != null) { | |||
if (toMatchAgainst.hasAnnotation(annotationType)) { | |||
// Are we also matching annotation values? | |||
if (annotationValues!=null) { | |||
AnnotationX theAnnotation = toMatchAgainst.getAnnotationOfType(annotationType); | |||
if (annotationValues != null) { | |||
AnnotationAJ theAnnotation = toMatchAgainst | |||
.getAnnotationOfType(annotationType); | |||
// Check each one | |||
Set keys = annotationValues.keySet(); | |||
for (Iterator keyIter = keys.iterator(); keyIter.hasNext();) { | |||
for (Iterator keyIter = keys.iterator(); keyIter | |||
.hasNext();) { | |||
String k = (String) keyIter.next(); | |||
String v = (String)annotationValues.get(k); | |||
String v = (String) annotationValues.get(k); | |||
if (theAnnotation.hasNamedValue(k)) { | |||
// Simple case, value is 'name=value' and the annotation specified the same thing | |||
if (!theAnnotation.hasNameValuePair(k,v)) { | |||
// Simple case, value is 'name=value' and | |||
// the annotation specified the same thing | |||
if (!theAnnotation.hasNameValuePair(k, v)) { | |||
return FuzzyBoolean.NO; | |||
} | |||
} | |||
} else { | |||
// Complex case, look at the default value | |||
ResolvedMember[] ms = ((ResolvedType)annotationType).getDeclaredMethods(); | |||
ResolvedMember[] ms = ((ResolvedType) annotationType) | |||
.getDeclaredMethods(); | |||
boolean foundMatch = false; | |||
for (int i=0; i<ms.length && !foundMatch;i++) { | |||
if (ms[i].isAbstract() && ms[i].getParameterTypes().length==0 && ms[i].getName().equals(k)) { | |||
for (int i = 0; i < ms.length | |||
&& !foundMatch; i++) { | |||
if (ms[i].isAbstract() | |||
&& ms[i].getParameterTypes().length == 0 | |||
&& ms[i].getName().equals(k)) { | |||
// we might be onto something | |||
String s= ms[i].getAnnotationDefaultValue(); | |||
if (s!=null && s.equals(v)) foundMatch=true; | |||
String s = ms[i] | |||
.getAnnotationDefaultValue(); | |||
if (s != null && s.equals(v)) | |||
foundMatch = true; | |||
} | |||
} | |||
if (!foundMatch) | |||
return FuzzyBoolean.NO; | |||
return FuzzyBoolean.NO; | |||
} | |||
} | |||
} | |||
@@ -180,40 +212,44 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
} | |||
toMatchAgainst = toMatchAgainst.getSuperclass(); | |||
} | |||
} | |||
} | |||
} else { | |||
// check parameter annotations | |||
if (parameterAnnotations==null) return FuzzyBoolean.NO; | |||
if (parameterAnnotations == null) | |||
return FuzzyBoolean.NO; | |||
for (int i = 0; i < parameterAnnotations.length; i++) { | |||
if (annotationType.equals(parameterAnnotations[i])) { | |||
// Are we also matching annotation values? | |||
if (annotationValues!=null) { | |||
parameterAnnotations[i].getWorld().getMessageHandler().handleMessage( | |||
MessageUtil.error("Compiler limitation: annotation value matching for parameter annotations not yet supported")); | |||
if (annotationValues != null) { | |||
parameterAnnotations[i] | |||
.getWorld() | |||
.getMessageHandler() | |||
.handleMessage( | |||
MessageUtil | |||
.error("Compiler limitation: annotation value matching for parameter annotations not yet supported")); | |||
return FuzzyBoolean.NO; | |||
} | |||
return FuzzyBoolean.YES; | |||
} | |||
} | |||
} | |||
return FuzzyBoolean.NO; | |||
} | |||
// this version should be called for @this, @target, @args | |||
public FuzzyBoolean matchesRuntimeType(AnnotatedElement annotated) { | |||
if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) { | |||
if (getResolvedAnnotationType().hasAnnotation( | |||
UnresolvedType.AT_INHERITED)) { | |||
// a static match is good enough | |||
if (matches(annotated).alwaysTrue()) { | |||
return FuzzyBoolean.YES; | |||
} | |||
} | |||
} | |||
// a subtype could match at runtime | |||
return FuzzyBoolean.MAYBE; | |||
} | |||
public void resolve(World world) { | |||
if (!resolved) { | |||
annotationType = annotationType.resolve(world); | |||
@@ -221,59 +257,73 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
resolved = true; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, boolean) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org | |||
* .aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, | |||
* boolean) | |||
*/ | |||
public AnnotationTypePattern resolveBindings(IScope scope, | |||
Bindings bindings, boolean allowBinding) { | |||
if (resolved) return this; | |||
if (resolved) | |||
return this; | |||
resolved = true; | |||
String simpleName = maybeGetSimpleName(); | |||
if (simpleName != null) { | |||
FormalBinding formalBinding = scope.lookupFormal(simpleName); | |||
if (formalBinding != null) { | |||
if (bindings == null) { | |||
scope.message(IMessage.ERROR, this, "negation doesn't allow binding"); | |||
scope.message(IMessage.ERROR, this, | |||
"negation doesn't allow binding"); | |||
return this; | |||
} | |||
if (!allowBinding) { | |||
scope.message(IMessage.ERROR, this, | |||
"name binding only allowed in @pcds, args, this, and target"); | |||
scope | |||
.message(IMessage.ERROR, this, | |||
"name binding only allowed in @pcds, args, this, and target"); | |||
return this; | |||
} | |||
formalName = simpleName; | |||
bindingPattern = true; | |||
verifyIsAnnotationType(formalBinding.getType().resolve(scope.getWorld()),scope); | |||
BindingAnnotationTypePattern binding = new BindingAnnotationTypePattern(formalBinding); | |||
verifyIsAnnotationType(formalBinding.getType().resolve( | |||
scope.getWorld()), scope); | |||
BindingAnnotationTypePattern binding = new BindingAnnotationTypePattern( | |||
formalBinding); | |||
binding.copyLocationFrom(this); | |||
bindings.register(binding, scope); | |||
binding.resolveBinding(scope.getWorld()); | |||
if (isForParameterAnnotationMatch()) binding.setForParameterAnnotationMatch(); | |||
if (isForParameterAnnotationMatch()) | |||
binding.setForParameterAnnotationMatch(); | |||
return binding; | |||
} | |||
} | |||
} | |||
// Non binding case | |||
String cleanname = annotationType.getName(); | |||
annotationType = scope.getWorld().resolve(annotationType,true); | |||
annotationType = scope.getWorld().resolve(annotationType, true); | |||
// We may not have found it if it is in a package, lets look it up... | |||
if (ResolvedType.isMissing(annotationType)) { | |||
UnresolvedType type = null; | |||
while (ResolvedType.isMissing(type = scope.lookupType(cleanname,this))) { | |||
while (ResolvedType.isMissing(type = scope.lookupType(cleanname, | |||
this))) { | |||
int lastDot = cleanname.lastIndexOf('.'); | |||
if (lastDot == -1) break; | |||
cleanname = cleanname.substring(0,lastDot)+"$"+cleanname.substring(lastDot+1); | |||
if (lastDot == -1) | |||
break; | |||
cleanname = cleanname.substring(0, lastDot) + "$" | |||
+ cleanname.substring(lastDot + 1); | |||
} | |||
annotationType = scope.getWorld().resolve(type,true); | |||
annotationType = scope.getWorld().resolve(type, true); | |||
} | |||
verifyIsAnnotationType((ResolvedType)annotationType,scope); | |||
verifyIsAnnotationType((ResolvedType) annotationType, scope); | |||
return this; | |||
} | |||
public AnnotationTypePattern parameterizeWith(Map typeVariableMap,World w) { | |||
public AnnotationTypePattern parameterizeWith(Map typeVariableMap, World w) { | |||
UnresolvedType newAnnotationType = annotationType; | |||
if (annotationType.isTypeVariableReference()) { | |||
TypeVariableReference t = (TypeVariableReference) annotationType; | |||
@@ -284,33 +334,40 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
} else if (annotationType.isParameterizedType()) { | |||
newAnnotationType = annotationType.parameterize(typeVariableMap); | |||
} | |||
ExactAnnotationTypePattern ret = new ExactAnnotationTypePattern(newAnnotationType,annotationValues); | |||
ExactAnnotationTypePattern ret = new ExactAnnotationTypePattern( | |||
newAnnotationType, annotationValues); | |||
ret.formalName = formalName; | |||
ret.bindingPattern = bindingPattern; | |||
ret.copyLocationFrom(this); | |||
if (isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch(); | |||
if (isForParameterAnnotationMatch()) | |||
ret.setForParameterAnnotationMatch(); | |||
return ret; | |||
} | |||
protected String maybeGetSimpleName() { | |||
if (formalName != null) return formalName; | |||
if (formalName != null) | |||
return formalName; | |||
String ret = annotationType.getName(); | |||
return (ret.indexOf('.') == -1) ? ret : null; | |||
} | |||
protected void verifyIsAnnotationType(ResolvedType type, IScope scope) { | |||
if (!type.isAnnotation()) { | |||
IMessage m = MessageUtil.error( | |||
WeaverMessages.format(WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE,type.getName()), | |||
getSourceLocation()); | |||
IMessage m = MessageUtil.error(WeaverMessages.format( | |||
WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE, type | |||
.getName()), getSourceLocation()); | |||
scope.getWorld().getMessageHandler().handleMessage(m); | |||
resolved = false; | |||
} | |||
} | |||
private static byte VERSION = 1; // rev if serialisation form changes | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) | |||
*/ | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeByte(AnnotationTypePattern.EXACT); | |||
@@ -323,7 +380,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
} | |||
writeLocation(s); | |||
s.writeBoolean(isForParameterAnnotationMatch()); | |||
if (annotationValues==null) { | |||
if (annotationValues == null) { | |||
s.writeInt(0); | |||
} else { | |||
s.writeInt(annotationValues.size()); | |||
@@ -331,67 +388,82 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
for (Iterator keys = key.iterator(); keys.hasNext();) { | |||
String k = (String) keys.next(); | |||
s.writeUTF(k); | |||
s.writeUTF((String)annotationValues.get(k)); | |||
s.writeUTF((String) annotationValues.get(k)); | |||
} | |||
} | |||
} | |||
public static AnnotationTypePattern read(VersionedDataInputStream s,ISourceContext context) throws IOException { | |||
public static AnnotationTypePattern read(VersionedDataInputStream s, | |||
ISourceContext context) throws IOException { | |||
ExactAnnotationTypePattern ret; | |||
byte version = s.readByte(); | |||
if (version > VERSION) { | |||
throw new BCException("ExactAnnotationTypePattern was written by a newer version of AspectJ"); | |||
throw new BCException( | |||
"ExactAnnotationTypePattern was written by a newer version of AspectJ"); | |||
} | |||
boolean isBindingPattern = s.readBoolean(); | |||
if (isBindingPattern) { | |||
ret = new ExactAnnotationTypePattern(s.readUTF()); | |||
} else { | |||
ret = new ExactAnnotationTypePattern(UnresolvedType.read(s)); | |||
ret = new ExactAnnotationTypePattern(UnresolvedType.read(s)); | |||
} | |||
ret.readLocation(context,s); | |||
if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) { | |||
if (s.readBoolean()) ret.setForParameterAnnotationMatch(); | |||
ret.readLocation(context, s); | |||
if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) { | |||
if (s.readBoolean()) | |||
ret.setForParameterAnnotationMatch(); | |||
} | |||
if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160M2) { | |||
if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160M2) { | |||
int annotationValueCount = s.readInt(); | |||
if (annotationValueCount>0) { | |||
if (annotationValueCount > 0) { | |||
Map aValues = new HashMap(); | |||
for (int i=0;i<annotationValueCount;i++) { | |||
for (int i = 0; i < annotationValueCount; i++) { | |||
String key = s.readUTF(); | |||
String val = s.readUTF(); | |||
aValues.put(key,val); | |||
aValues.put(key, val); | |||
} | |||
ret.annotationValues = aValues; | |||
} | |||
} | |||
return ret; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see java.lang.Object#equals(java.lang.Object) | |||
*/ | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof ExactAnnotationTypePattern)) return false; | |||
if (!(obj instanceof ExactAnnotationTypePattern)) | |||
return false; | |||
ExactAnnotationTypePattern other = (ExactAnnotationTypePattern) obj; | |||
return (other.annotationType.equals(annotationType)) && isForParameterAnnotationMatch()==other.isForParameterAnnotationMatch() && | |||
(annotationValues==null?other.annotationValues==null:annotationValues.equals(other.annotationValues)); | |||
return (other.annotationType.equals(annotationType)) | |||
&& isForParameterAnnotationMatch() == other | |||
.isForParameterAnnotationMatch() | |||
&& (annotationValues == null ? other.annotationValues == null | |||
: annotationValues.equals(other.annotationValues)); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see java.lang.Object#hashCode() | |||
*/ | |||
public int hashCode() { | |||
return (((annotationType.hashCode())*37+(isForParameterAnnotationMatch()?0:1))*37)+(annotationValues==null?0:annotationValues.hashCode()); | |||
return (((annotationType.hashCode()) * 37 + (isForParameterAnnotationMatch() ? 0 | |||
: 1)) * 37) | |||
+ (annotationValues == null ? 0 : annotationValues.hashCode()); | |||
} | |||
public String toString() { | |||
if (!resolved && formalName != null) return formalName; | |||
if (!resolved && formalName != null) | |||
return formalName; | |||
String ret = "@" + annotationType.toString(); | |||
if (formalName != null) ret = ret + " " + formalName; | |||
if (formalName != null) | |||
ret = ret + " " + formalName; | |||
return ret; | |||
} | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this, data); | |||
} | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this, data); | |||
} | |||
} |
@@ -14,31 +14,32 @@ package org.aspectj.weaver.reflect; | |||
import java.lang.reflect.Member; | |||
import java.util.Set; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.World; | |||
/** | |||
* @author colyer | |||
* Used in 1.4 code to access annotations safely | |||
* @author colyer Used in 1.4 code to access annotations safely | |||
*/ | |||
public interface AnnotationFinder { | |||
void setClassLoader(ClassLoader annotationLoader); | |||
void setWorld(World aWorld); | |||
Object getAnnotation(ResolvedType annotationType, Object onObject); | |||
Object getAnnotationFromMember(ResolvedType annotationType, Member aMember); | |||
public AnnotationX getAnnotationOfType(UnresolvedType ofType,Member onMember); | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType, | |||
Member onMember); | |||
public String getAnnotationDefaultValue(Member onMember); | |||
Object getAnnotationFromClass(ResolvedType annotationType, Class aClass); | |||
Set/*ResolvedType*/ getAnnotations(Member onMember); | |||
Set/* ResolvedType */getAnnotations(Member onMember); | |||
ResolvedType[][] getParameterAnnotationTypes(Member onMember); | |||
} |
@@ -20,8 +20,8 @@ import java.net.URLClassLoader; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.AnnotationTargetKind; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.ReferenceType; | |||
import org.aspectj.weaver.ReferenceTypeDelegate; | |||
@@ -36,15 +36,18 @@ import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
/** | |||
* @author colyer | |||
* A delegate for a resolved type that uses runtime type information (java.lang.reflect) | |||
* to answer questions. This class uses only Java 1.4 features to answer questions. | |||
* In a Java 1.5 environment use the Java5ReflectionBasedReferenceTypeDelegate subtype. | |||
* @author colyer A delegate for a resolved type that uses runtime type | |||
* information (java.lang.reflect) to answer questions. This class uses | |||
* only Java 1.4 features to answer questions. In a Java 1.5 environment | |||
* use the Java5ReflectionBasedReferenceTypeDelegate subtype. | |||
*/ | |||
public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelegate { | |||
public class ReflectionBasedReferenceTypeDelegate implements | |||
ReferenceTypeDelegate { | |||
private static final ClassLoader BootClassLoader = new URLClassLoader( | |||
new URL[0]);// ReflectionBasedReferenceTypeDelegate.class. | |||
// getClassLoader(); | |||
private static final ClassLoader BootClassLoader = new URLClassLoader(new URL[0]);// ReflectionBasedReferenceTypeDelegate.class.getClassLoader(); | |||
protected Class myClass = null; | |||
protected WeakClassLoaderReference classLoaderReference = null; | |||
private World world; | |||
@@ -52,64 +55,84 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
private ResolvedMember[] fields = null; | |||
private ResolvedMember[] methods = null; | |||
private ResolvedType[] interfaces = null; | |||
public ReflectionBasedReferenceTypeDelegate(Class forClass, ClassLoader aClassLoader, World inWorld, ReferenceType resolvedType) { | |||
initialize(resolvedType,forClass, aClassLoader, inWorld); | |||
public ReflectionBasedReferenceTypeDelegate(Class forClass, | |||
ClassLoader aClassLoader, World inWorld, ReferenceType resolvedType) { | |||
initialize(resolvedType, forClass, aClassLoader, inWorld); | |||
} | |||
/** for reflective construction only */ | |||
public ReflectionBasedReferenceTypeDelegate() {} | |||
public void initialize(ReferenceType aType, Class aClass, ClassLoader aClassLoader, World aWorld) { | |||
public ReflectionBasedReferenceTypeDelegate() { | |||
} | |||
public void initialize(ReferenceType aType, Class aClass, | |||
ClassLoader aClassLoader, World aWorld) { | |||
this.myClass = aClass; | |||
this.resolvedType = aType; | |||
this.world = aWorld; | |||
this.classLoaderReference = new WeakClassLoaderReference((aClassLoader != null) ? aClassLoader : BootClassLoader); | |||
this.classLoaderReference = new WeakClassLoaderReference( | |||
(aClassLoader != null) ? aClassLoader : BootClassLoader); | |||
} | |||
protected Class getBaseClass() { | |||
protected Class getBaseClass() { | |||
return this.myClass; | |||
} | |||
protected World getWorld() { | |||
return this.world; | |||
} | |||
public ReferenceType buildGenericType() { | |||
throw new UnsupportedOperationException("Shouldn't be asking for generic type at 1.4 source level or lower"); | |||
throw new UnsupportedOperationException( | |||
"Shouldn't be asking for generic type at 1.4 source level or lower"); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#addAnnotation(org.aspectj.weaver.AnnotationX) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* org.aspectj.weaver.ReferenceTypeDelegate#addAnnotation(org.aspectj.weaver | |||
* .AnnotationX) | |||
*/ | |||
public void addAnnotation(AnnotationX annotationX) { | |||
throw new UnsupportedOperationException("Cannot add an annotation to a reflection based delegate"); | |||
public void addAnnotation(AnnotationAJ annotationX) { | |||
throw new UnsupportedOperationException( | |||
"Cannot add an annotation to a reflection based delegate"); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isAspect() | |||
*/ | |||
public boolean isAspect() { | |||
// we could do better than this in Java 5 by looking at the annotations on the type... | |||
// we could do better than this in Java 5 by looking at the annotations | |||
// on the type... | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isAnnotationStyleAspect() | |||
*/ | |||
public boolean isAnnotationStyleAspect() { | |||
// we could do better than this in Java 5 by looking at the annotations on the type... | |||
// we could do better than this in Java 5 by looking at the annotations | |||
// on the type... | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isInterface() | |||
*/ | |||
public boolean isInterface() { | |||
return this.myClass.isInterface(); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isEnum() | |||
*/ | |||
public boolean isEnum() { | |||
@@ -117,7 +140,9 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isAnnotation() | |||
*/ | |||
public boolean isAnnotation() { | |||
@@ -125,14 +150,18 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isAnnotationWithRuntimeRetention() | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* org.aspectj.weaver.ReferenceTypeDelegate#isAnnotationWithRuntimeRetention | |||
* () | |||
*/ | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
// cant be an annotation in Java 1.4 or prior | |||
return false; | |||
} | |||
public String getRetentionPolicy() { | |||
// cant be an annotation in Java 1.4 or prior | |||
return null; | |||
@@ -141,44 +170,54 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
public boolean canAnnotationTargetType() { | |||
return false; | |||
} | |||
public AnnotationTargetKind[] getAnnotationTargetKinds() { | |||
return null; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isClass() | |||
*/ | |||
public boolean isClass() { | |||
return !this.myClass.isInterface() && !this.myClass.isPrimitive() && !this.myClass.isArray(); | |||
return !this.myClass.isInterface() && !this.myClass.isPrimitive() | |||
&& !this.myClass.isArray(); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isGeneric() | |||
*/ | |||
public boolean isGeneric() { | |||
// cant be generic in 1.4 | |||
return false; | |||
} | |||
public boolean isAnonymous() { | |||
return false; | |||
} | |||
public boolean isNested() { | |||
// FIXME this is *wrong* but isMemberClass() doesnt exist in pre-1.5... (same deal as isAnonymous above...) | |||
// FIXME this is *wrong* but isMemberClass() doesnt exist in pre-1.5... | |||
// (same deal as isAnonymous above...) | |||
return true; | |||
// boolean member = this.myClass.isMemberClass(); | |||
// return member; | |||
// boolean member = this.myClass.isMemberClass(); | |||
// return member; | |||
} | |||
public ResolvedType getOuterClass() { | |||
// FIXME getEnclosingClass() is Java5 ... dammit | |||
// return ReflectionBasedReferenceTypeDelegateFactory.resolveTypeInWorld(myClass.getEnclosingClass(),world); | |||
// return | |||
// ReflectionBasedReferenceTypeDelegateFactory.resolveTypeInWorld( | |||
// myClass.getEnclosingClass(),world); | |||
return null; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#isExposedToWeaver() | |||
*/ | |||
public boolean isExposedToWeaver() { | |||
@@ -186,23 +225,31 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#hasAnnotation(org.aspectj.weaver.UnresolvedType) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* org.aspectj.weaver.ReferenceTypeDelegate#hasAnnotation(org.aspectj.weaver | |||
* .UnresolvedType) | |||
*/ | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
// in Java 1.4 we cant have an annotation | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getAnnotations() | |||
*/ | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
// no annotations in Java 1.4 | |||
return new AnnotationX[0]; | |||
return AnnotationAJ.EMPTY_ARRAY; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getAnnotationTypes() | |||
*/ | |||
public ResolvedType[] getAnnotationTypes() { | |||
@@ -210,7 +257,9 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return new ResolvedType[0]; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredFields() | |||
*/ | |||
public ResolvedMember[] getDeclaredFields() { | |||
@@ -218,15 +267,17 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
Field[] reflectFields = this.myClass.getDeclaredFields(); | |||
ResolvedMember[] rFields = new ResolvedMember[reflectFields.length]; | |||
for (int i = 0; i < reflectFields.length; i++) { | |||
rFields[i] = | |||
ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(reflectFields[i], world); | |||
rFields[i] = ReflectionBasedReferenceTypeDelegateFactory | |||
.createResolvedMember(reflectFields[i], world); | |||
} | |||
this.fields = rFields; | |||
} | |||
return fields; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredInterfaces() | |||
*/ | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
@@ -235,42 +286,49 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
ResolvedType[] rInterfaces = new ResolvedType[reflectInterfaces.length]; | |||
for (int i = 0; i < reflectInterfaces.length; i++) { | |||
rInterfaces[i] = ReflectionBasedReferenceTypeDelegateFactory | |||
.resolveTypeInWorld(reflectInterfaces[i],world); | |||
.resolveTypeInWorld(reflectInterfaces[i], world); | |||
} | |||
this.interfaces = rInterfaces; | |||
} | |||
return interfaces; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredMethods() | |||
*/ | |||
public ResolvedMember[] getDeclaredMethods() { | |||
if (methods == null) { | |||
Method[] reflectMethods = this.myClass.getDeclaredMethods(); | |||
Constructor[] reflectCons = this.myClass.getDeclaredConstructors(); | |||
ResolvedMember[] rMethods = new ResolvedMember[reflectMethods.length + reflectCons.length]; | |||
ResolvedMember[] rMethods = new ResolvedMember[reflectMethods.length | |||
+ reflectCons.length]; | |||
for (int i = 0; i < reflectMethods.length; i++) { | |||
rMethods[i] = | |||
ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(reflectMethods[i], world); | |||
rMethods[i] = ReflectionBasedReferenceTypeDelegateFactory | |||
.createResolvedMember(reflectMethods[i], world); | |||
} | |||
for (int i = 0; i < reflectCons.length; i++) { | |||
rMethods[i + reflectMethods.length] = | |||
ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(reflectCons[i], world); | |||
rMethods[i + reflectMethods.length] = ReflectionBasedReferenceTypeDelegateFactory | |||
.createResolvedMember(reflectCons[i], world); | |||
} | |||
this.methods = rMethods; | |||
} | |||
return methods; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredPointcuts() | |||
*/ | |||
public ResolvedMember[] getDeclaredPointcuts() { | |||
return new ResolvedMember[0]; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getTypeVariables() | |||
*/ | |||
public TypeVariable[] getTypeVariables() { | |||
@@ -278,7 +336,9 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return new TypeVariable[0]; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getPerClause() | |||
*/ | |||
public PerClause getPerClause() { | |||
@@ -286,7 +346,9 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return null; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclares() | |||
*/ | |||
public Collection getDeclares() { | |||
@@ -294,7 +356,9 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return Collections.EMPTY_SET; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getTypeMungers() | |||
*/ | |||
public Collection getTypeMungers() { | |||
@@ -302,7 +366,9 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return Collections.EMPTY_SET; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getPrivilegedAccesses() | |||
*/ | |||
public Collection getPrivilegedAccesses() { | |||
@@ -310,50 +376,64 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
return Collections.EMPTY_SET; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getModifiers() | |||
*/ | |||
public int getModifiers() { | |||
return this.myClass.getModifiers(); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getSuperclass() | |||
*/ | |||
public ResolvedType getSuperclass() { | |||
if (this.myClass.getSuperclass() == null) { | |||
if (myClass==Object.class) { | |||
if (myClass == Object.class) { | |||
return null; | |||
} | |||
return world.resolve(UnresolvedType.OBJECT); | |||
} | |||
return ReflectionBasedReferenceTypeDelegateFactory | |||
.resolveTypeInWorld(this.myClass.getSuperclass(),world); | |||
return ReflectionBasedReferenceTypeDelegateFactory.resolveTypeInWorld( | |||
this.myClass.getSuperclass(), world); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getWeaverState() | |||
*/ | |||
public WeaverStateInfo getWeaverState() { | |||
return null; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getResolvedTypeX() | |||
*/ | |||
public ReferenceType getResolvedTypeX() { | |||
return this.resolvedType; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#doesNotExposeShadowMungers() | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* org.aspectj.weaver.ReferenceTypeDelegate#doesNotExposeShadowMungers() | |||
*/ | |||
public boolean doesNotExposeShadowMungers() { | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredGenericSignature() | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* org.aspectj.weaver.ReferenceTypeDelegate#getDeclaredGenericSignature() | |||
*/ | |||
public String getDeclaredGenericSignature() { | |||
// no generic sig in 1.4 | |||
@@ -361,16 +441,18 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega | |||
} | |||
public void ensureDelegateConsistent() { | |||
// Nothing to do - a reflection based delegate can't become inconsistent... | |||
// Nothing to do - a reflection based delegate can't become | |||
// inconsistent... | |||
} | |||
public ReflectionBasedResolvedMemberImpl createResolvedMemberFor(Member aMember) { | |||
public ReflectionBasedResolvedMemberImpl createResolvedMemberFor( | |||
Member aMember) { | |||
return null; | |||
} | |||
public String getSourcefilename() { | |||
// crappy guess.. | |||
return resolvedType.getName() + ".class"; | |||
// crappy guess.. | |||
return resolvedType.getName() + ".class"; | |||
} | |||
public ISourceContext getSourceContext() { |
@@ -14,27 +14,25 @@ package org.aspectj.weaver.reflect; | |||
import java.lang.reflect.Member; | |||
import java.util.Iterator; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.MemberKind; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedMemberImpl; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
/** | |||
* Subtype of ResolvedMemberImpl used in reflection world. | |||
* Knows how to get annotations from a java.lang.reflect.Member | |||
* | |||
* Subtype of ResolvedMemberImpl used in reflection world. Knows how to get | |||
* annotations from a java.lang.reflect.Member | |||
* | |||
*/ | |||
public class ReflectionBasedResolvedMemberImpl extends ResolvedMemberImpl { | |||
private AnnotationFinder annotationFinder = null; | |||
private GenericSignatureInformationProvider gsigInfoProvider = | |||
new Java14GenericSignatureInformationProvider(); | |||
private GenericSignatureInformationProvider gsigInfoProvider = new Java14GenericSignatureInformationProvider(); | |||
private Member reflectMember; | |||
/** | |||
* @param kind | |||
* @param declaringType | |||
@@ -46,8 +44,7 @@ public class ReflectionBasedResolvedMemberImpl extends ResolvedMemberImpl { | |||
public ReflectionBasedResolvedMemberImpl(MemberKind kind, | |||
UnresolvedType declaringType, int modifiers, | |||
UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes, | |||
Member reflectMember) { | |||
UnresolvedType[] parameterTypes, Member reflectMember) { | |||
super(kind, declaringType, modifiers, returnType, name, parameterTypes); | |||
this.reflectMember = reflectMember; | |||
} | |||
@@ -64,8 +61,8 @@ public class ReflectionBasedResolvedMemberImpl extends ResolvedMemberImpl { | |||
public ReflectionBasedResolvedMemberImpl(MemberKind kind, | |||
UnresolvedType declaringType, int modifiers, | |||
UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions, | |||
Member reflectMember) { | |||
UnresolvedType[] parameterTypes, | |||
UnresolvedType[] checkedExceptions, Member reflectMember) { | |||
super(kind, declaringType, modifiers, returnType, name, parameterTypes, | |||
checkedExceptions); | |||
this.reflectMember = reflectMember; | |||
@@ -86,8 +83,7 @@ public class ReflectionBasedResolvedMemberImpl extends ResolvedMemberImpl { | |||
UnresolvedType returnType, String name, | |||
UnresolvedType[] parameterTypes, | |||
UnresolvedType[] checkedExceptions, | |||
ResolvedMember backingGenericMember, | |||
Member reflectMember) { | |||
ResolvedMember backingGenericMember, Member reflectMember) { | |||
super(kind, declaringType, modifiers, returnType, name, parameterTypes, | |||
checkedExceptions, backingGenericMember); | |||
this.reflectMember = reflectMember; | |||
@@ -110,93 +106,108 @@ public class ReflectionBasedResolvedMemberImpl extends ResolvedMemberImpl { | |||
public Member getMember() { | |||
return this.reflectMember; | |||
} | |||
// generic signature support | |||
public void setGenericSignatureInformationProvider(GenericSignatureInformationProvider gsigProvider) { | |||
public void setGenericSignatureInformationProvider( | |||
GenericSignatureInformationProvider gsigProvider) { | |||
this.gsigInfoProvider = gsigProvider; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ResolvedMemberImpl#getGenericParameterTypes() | |||
*/ | |||
public UnresolvedType[] getGenericParameterTypes() { | |||
return this.gsigInfoProvider.getGenericParameterTypes(this); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ResolvedMemberImpl#getGenericReturnType() | |||
*/ | |||
public UnresolvedType getGenericReturnType() { | |||
return this.gsigInfoProvider.getGenericReturnType(this); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ResolvedMemberImpl#isSynthetic() | |||
*/ | |||
public boolean isSynthetic() { | |||
return this.gsigInfoProvider.isSynthetic(this); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ResolvedMemberImpl#isVarargsMethod() | |||
*/ | |||
public boolean isVarargsMethod() { | |||
return this.gsigInfoProvider.isVarArgs(this); | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.ResolvedMemberImpl#isBridgeMethod() | |||
*/ | |||
public boolean isBridgeMethod() { | |||
return this.gsigInfoProvider.isBridge(this); | |||
} | |||
// annotation support | |||
public void setAnnotationFinder(AnnotationFinder finder) { | |||
this.annotationFinder = finder; | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
unpackAnnotations(); | |||
return super.hasAnnotation(ofType); | |||
} | |||
public boolean hasAnnotations() { | |||
unpackAnnotations(); | |||
return super.hasAnnotations(); | |||
} | |||
public ResolvedType[] getAnnotationTypes() { | |||
unpackAnnotations(); | |||
return super.getAnnotationTypes(); | |||
} | |||
public AnnotationX getAnnotationOfType(UnresolvedType ofType) { | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
unpackAnnotations(); | |||
if (annotationFinder==null) return null; | |||
if (annotationFinder == null) | |||
return null; | |||
for (Iterator iterator = annotationTypes.iterator(); iterator.hasNext();) { | |||
ResolvedType type = (ResolvedType) iterator.next(); | |||
if (type.getSignature().equals(ofType.getSignature())) { | |||
return annotationFinder.getAnnotationOfType(ofType, reflectMember); | |||
return annotationFinder.getAnnotationOfType(ofType, | |||
reflectMember); | |||
} | |||
} | |||
return null; | |||
} | |||
public String getAnnotationDefaultValue() { | |||
if (annotationFinder==null) return null; | |||
if (annotationFinder == null) | |||
return null; | |||
return annotationFinder.getAnnotationDefaultValue(reflectMember); | |||
} | |||
public ResolvedType[][] getParameterAnnotationTypes() { | |||
if (parameterAnnotationTypes==null && annotationFinder!=null) { | |||
parameterAnnotationTypes = annotationFinder.getParameterAnnotationTypes(reflectMember); | |||
} | |||
return parameterAnnotationTypes; | |||
} | |||
if (parameterAnnotationTypes == null && annotationFinder != null) { | |||
parameterAnnotationTypes = annotationFinder | |||
.getParameterAnnotationTypes(reflectMember); | |||
} | |||
return parameterAnnotationTypes; | |||
} | |||
private void unpackAnnotations() { | |||
if (annotationTypes == null && annotationFinder != null) { | |||
annotationTypes = annotationFinder.getAnnotations(reflectMember); |
@@ -14,344 +14,396 @@ import junit.framework.TestCase; | |||
import org.aspectj.bridge.AbortException; | |||
import org.aspectj.util.LangUtil; | |||
import org.aspectj.weaver.AnnotatedElement; | |||
import org.aspectj.weaver.AnnotationX; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.BcweaverTests; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.bcel.BcelWorld; | |||
public class AnnotationPatternTestCase extends TestCase { | |||
public void testParseSimpleAnnotationPattern() { | |||
PatternParser p = new PatternParser("@Foo"); | |||
AnnotationTypePattern foo = p.maybeParseAnnotationPattern(); | |||
foo = foo.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
assertTrue("ExactAnnotationTypePattern",foo instanceof ExactAnnotationTypePattern); | |||
assertEquals("Foo", UnresolvedType.forSignature("LFoo;"), ((ExactAnnotationTypePattern) foo).annotationType); | |||
foo = foo.resolveBindings(makeSimpleScope(), new Bindings(3), true); | |||
assertTrue("ExactAnnotationTypePattern", | |||
foo instanceof ExactAnnotationTypePattern); | |||
assertEquals("Foo", UnresolvedType.forSignature("LFoo;"), | |||
((ExactAnnotationTypePattern) foo).annotationType); | |||
} | |||
public void testParseAndAnnotationPattern() { | |||
PatternParser p = new PatternParser("@Foo @Goo"); | |||
AnnotationTypePattern fooAndGoo = p.maybeParseAnnotationPattern(); | |||
assertTrue("AndAnnotationTypePattern",fooAndGoo instanceof AndAnnotationTypePattern); | |||
assertEquals("@(Foo) @(Goo)",fooAndGoo.toString()); | |||
fooAndGoo = fooAndGoo.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
assertEquals("@Foo @Goo",fooAndGoo.toString()); | |||
AnnotationTypePattern left = ((AndAnnotationTypePattern)fooAndGoo).getLeft(); | |||
AnnotationTypePattern right = ((AndAnnotationTypePattern)fooAndGoo).getRight(); | |||
assertEquals("Foo", UnresolvedType.forSignature("LFoo;"), ((ExactAnnotationTypePattern) left).annotationType); | |||
assertEquals("Goo", UnresolvedType.forSignature("LGoo;"), ((ExactAnnotationTypePattern) right).annotationType); | |||
assertTrue("AndAnnotationTypePattern", | |||
fooAndGoo instanceof AndAnnotationTypePattern); | |||
assertEquals("@(Foo) @(Goo)", fooAndGoo.toString()); | |||
fooAndGoo = fooAndGoo.resolveBindings(makeSimpleScope(), | |||
new Bindings(3), true); | |||
assertEquals("@Foo @Goo", fooAndGoo.toString()); | |||
AnnotationTypePattern left = ((AndAnnotationTypePattern) fooAndGoo) | |||
.getLeft(); | |||
AnnotationTypePattern right = ((AndAnnotationTypePattern) fooAndGoo) | |||
.getRight(); | |||
assertEquals("Foo", UnresolvedType.forSignature("LFoo;"), | |||
((ExactAnnotationTypePattern) left).annotationType); | |||
assertEquals("Goo", UnresolvedType.forSignature("LGoo;"), | |||
((ExactAnnotationTypePattern) right).annotationType); | |||
} | |||
// | |||
// public void testParseOrAnnotationPattern() { | |||
// PatternParser p = new PatternParser("@Foo || @Goo"); | |||
// AnnotationTypePattern fooOrGoo = p.parseAnnotationTypePattern(); | |||
// assertTrue("OrAnnotationTypePattern",fooOrGoo instanceof OrAnnotationTypePattern); | |||
// assertEquals("(@Foo || @Goo)",fooOrGoo.toString()); | |||
// AnnotationTypePattern left = ((OrAnnotationTypePattern)fooOrGoo).getLeft(); | |||
// AnnotationTypePattern right = ((OrAnnotationTypePattern)fooOrGoo).getRight(); | |||
// assertEquals("Foo",UnresolvedType.forName("Foo"),((ExactAnnotationTypePattern)left).annotationType); | |||
// assertEquals("Goo",UnresolvedType.forName("Goo"),((ExactAnnotationTypePattern)right).annotationType); | |||
// } | |||
// | |||
// | |||
// public void testParseOrAnnotationPattern() { | |||
// PatternParser p = new PatternParser("@Foo || @Goo"); | |||
// AnnotationTypePattern fooOrGoo = p.parseAnnotationTypePattern(); | |||
// assertTrue("OrAnnotationTypePattern",fooOrGoo instanceof | |||
// OrAnnotationTypePattern); | |||
// assertEquals("(@Foo || @Goo)",fooOrGoo.toString()); | |||
// AnnotationTypePattern left = | |||
// ((OrAnnotationTypePattern)fooOrGoo).getLeft(); | |||
// AnnotationTypePattern right = | |||
// ((OrAnnotationTypePattern)fooOrGoo).getRight(); | |||
// assertEquals("Foo",UnresolvedType.forName("Foo"),(( | |||
// ExactAnnotationTypePattern)left).annotationType); | |||
// assertEquals("Goo",UnresolvedType.forName("Goo"),(( | |||
// ExactAnnotationTypePattern)right).annotationType); | |||
// } | |||
// | |||
public void testParseNotAnnotationPattern() { | |||
PatternParser p = new PatternParser("!@Foo"); | |||
AnnotationTypePattern notFoo = p.maybeParseAnnotationPattern(); | |||
assertTrue("NotAnnotationTypePattern",notFoo instanceof NotAnnotationTypePattern); | |||
notFoo = notFoo.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
assertEquals("!@Foo",notFoo.toString()); | |||
AnnotationTypePattern body = ((NotAnnotationTypePattern)notFoo).getNegatedPattern(); | |||
assertEquals("Foo",UnresolvedType.forName("Foo"),((ExactAnnotationTypePattern)body).annotationType); | |||
assertTrue("NotAnnotationTypePattern", | |||
notFoo instanceof NotAnnotationTypePattern); | |||
notFoo = notFoo.resolveBindings(makeSimpleScope(), new Bindings(3), | |||
true); | |||
assertEquals("!@Foo", notFoo.toString()); | |||
AnnotationTypePattern body = ((NotAnnotationTypePattern) notFoo) | |||
.getNegatedPattern(); | |||
assertEquals("Foo", UnresolvedType.forName("Foo"), | |||
((ExactAnnotationTypePattern) body).annotationType); | |||
} | |||
public void testParseBracketedAnnotationPattern() { | |||
PatternParser p = new PatternParser("(@Foo)"); | |||
AnnotationTypePattern foo = p.maybeParseAnnotationPattern(); | |||
// cannot start with ( so, we get ANY | |||
assertEquals("ANY",AnnotationTypePattern.ANY,foo); | |||
assertEquals("ANY", AnnotationTypePattern.ANY, foo); | |||
} | |||
public void testParseFQAnnPattern() { | |||
PatternParser p = new PatternParser("@org.aspectj.Foo"); | |||
AnnotationTypePattern foo = p.maybeParseAnnotationPattern(); | |||
assertEquals("@(org.aspectj.Foo)",foo.toString()); | |||
assertEquals("@(org.aspectj.Foo)", foo.toString()); | |||
} | |||
public void testParseComboPattern() { | |||
// PatternParser p = new PatternParser("!((@Foo || @Goo) && !@Boo)"); | |||
// PatternParser p = new PatternParser("!((@Foo || @Goo) && !@Boo)"); | |||
PatternParser p = new PatternParser("@(Foo || Goo)!@Boo"); | |||
AnnotationTypePattern ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
ap = ap.resolveBindings(makeSimpleScope(), new Bindings(3), true); | |||
AndAnnotationTypePattern atp = (AndAnnotationTypePattern) ap; | |||
NotAnnotationTypePattern notBoo = (NotAnnotationTypePattern) atp.getRight(); | |||
// ExactAnnotationTypePattern boo = (ExactAnnotationTypePattern) | |||
notBoo.getNegatedPattern(); | |||
// AnnotationTypePattern fooOrGoo = (AnnotationTypePattern) | |||
atp.getLeft(); | |||
assertEquals("@((Foo || Goo)) !@Boo",ap.toString()); | |||
NotAnnotationTypePattern notBoo = (NotAnnotationTypePattern) atp | |||
.getRight(); | |||
// ExactAnnotationTypePattern boo = (ExactAnnotationTypePattern) | |||
notBoo.getNegatedPattern(); | |||
// AnnotationTypePattern fooOrGoo = (AnnotationTypePattern) | |||
atp.getLeft(); | |||
assertEquals("@((Foo || Goo)) !@Boo", ap.toString()); | |||
} | |||
// public void testParseAndOrPattern() { | |||
// PatternParser p = new PatternParser("@Foo && @Boo || @Goo"); | |||
// AnnotationTypePattern andOr = p.parseAnnotationTypePattern(); | |||
// assertTrue("Should be or pattern",andOr instanceof OrAnnotationTypePattern); | |||
// } | |||
// | |||
// public void testParseAndOrPattern() { | |||
// PatternParser p = new PatternParser("@Foo && @Boo || @Goo"); | |||
// AnnotationTypePattern andOr = p.parseAnnotationTypePattern(); | |||
// assertTrue("Should be or pattern",andOr instanceof | |||
// OrAnnotationTypePattern); | |||
// } | |||
// | |||
public void testParseBadPattern() { | |||
PatternParser p = new PatternParser("@@Foo"); | |||
try { | |||
p.maybeParseAnnotationPattern(); | |||
fail("ParserException expected"); | |||
} catch(ParserException pEx) { | |||
assertEquals("name pattern",pEx.getMessage()); | |||
} catch (ParserException pEx) { | |||
assertEquals("name pattern", pEx.getMessage()); | |||
} | |||
} | |||
public void testParseBadPattern2() { | |||
PatternParser p = new PatternParser("Foo"); | |||
AnnotationTypePattern bad = p.maybeParseAnnotationPattern(); | |||
assertEquals("ANY",AnnotationTypePattern.ANY,bad); | |||
assertEquals("ANY", AnnotationTypePattern.ANY, bad); | |||
} | |||
public void testParseNameOrVarAnnotationPattern() { | |||
PatternParser p = new PatternParser("Foo"); | |||
AnnotationTypePattern foo = p.parseAnnotationNameOrVarTypePattern(); | |||
assertTrue("ExactAnnotationTypePattern expected",foo!=null); | |||
assertEquals("Foo",UnresolvedType.forName("Foo"),((ExactAnnotationTypePattern)foo).annotationType); | |||
assertTrue("ExactAnnotationTypePattern expected", foo != null); | |||
assertEquals("Foo", UnresolvedType.forName("Foo"), | |||
((ExactAnnotationTypePattern) foo).annotationType); | |||
} | |||
public void testParseNameOrVarAnnotationPatternWithNot() { | |||
PatternParser p = new PatternParser("!@Foo"); | |||
try { | |||
// AnnotationTypePattern bad = | |||
p.parseAnnotationNameOrVarTypePattern(); | |||
// AnnotationTypePattern bad = | |||
p.parseAnnotationNameOrVarTypePattern(); | |||
fail("ParserException expected"); | |||
} catch(ParserException pEx) { | |||
assertEquals("identifier",pEx.getMessage()); | |||
} | |||
} catch (ParserException pEx) { | |||
assertEquals("identifier", pEx.getMessage()); | |||
} | |||
} | |||
public void testParseNameOrVarAnnotationPatternWithOr() { | |||
PatternParser p = new PatternParser("Foo || Boo"); | |||
AnnotationTypePattern foo = p.parseAnnotationNameOrVarTypePattern(); | |||
// rest of pattern not consumed... | |||
assertTrue("ExactAnnotationTypePattern",foo instanceof ExactAnnotationTypePattern); | |||
assertEquals("Foo",UnresolvedType.forName("Foo"),((ExactAnnotationTypePattern)foo).annotationType); | |||
assertTrue("ExactAnnotationTypePattern", | |||
foo instanceof ExactAnnotationTypePattern); | |||
assertEquals("Foo", UnresolvedType.forName("Foo"), | |||
((ExactAnnotationTypePattern) foo).annotationType); | |||
} | |||
public void testParseNameOrVarAnnotationWithBinding() { | |||
PatternParser p = new PatternParser("foo"); | |||
AnnotationTypePattern foo = p.parseAnnotationNameOrVarTypePattern(); | |||
assertTrue("ExactAnnotationTypePattern",foo instanceof ExactAnnotationTypePattern); | |||
assertEquals("@foo",((ExactAnnotationTypePattern)foo).toString()); | |||
assertTrue("ExactAnnotationTypePattern", | |||
foo instanceof ExactAnnotationTypePattern); | |||
assertEquals("@foo", ((ExactAnnotationTypePattern) foo).toString()); | |||
} | |||
public void testParseNameOrVarAnnotationPatternWithAnd() { | |||
PatternParser p = new PatternParser("Foo Boo"); | |||
AnnotationTypePattern foo = p.parseAnnotationNameOrVarTypePattern(); | |||
// rest of pattern not consumed... | |||
assertEquals("@Foo",foo.toString()); | |||
assertEquals("@Foo", foo.toString()); | |||
} | |||
public void testMaybeParseAnnotationPattern() { | |||
PatternParser p = new PatternParser("@Foo"); | |||
AnnotationTypePattern a = p.maybeParseAnnotationPattern(); | |||
assertNotNull("Should find annotation pattern",a); | |||
assertNotNull("Should find annotation pattern", a); | |||
p = new PatternParser("Foo && Boo"); | |||
a = p.maybeParseAnnotationPattern(); | |||
assertEquals("Should be ANY pattern for a non-match",AnnotationTypePattern.ANY,a); | |||
assertEquals("Should be ANY pattern for a non-match", | |||
AnnotationTypePattern.ANY, a); | |||
} | |||
public void testParseTypePatternsWithAnnotations() { | |||
PatternParser p = new PatternParser("@Foo *"); | |||
TypePattern t = p.parseTypePattern(); | |||
assertTrue("WildTypePattern",t instanceof WildTypePattern); | |||
assertTrue("WildTypePattern", t instanceof WildTypePattern); | |||
AnnotationTypePattern atp = t.annotationPattern; | |||
assertEquals("@(Foo)",atp.toString()); | |||
assertEquals("(@(Foo) *)",t.toString()); | |||
assertEquals("@(Foo)", atp.toString()); | |||
assertEquals("(@(Foo) *)", t.toString()); | |||
} | |||
public void testParseTypePatternsWithAnnotationsComplex() { | |||
PatternParser p = new PatternParser("(@(Foo || Boo) (Foo || Boo))"); | |||
TypePattern t = p.parseTypePattern(); | |||
assertTrue("OrTypePattern",t instanceof OrTypePattern); | |||
assertEquals("((@((Foo || Boo)) Foo) || (@((Foo || Boo)) Boo))",t.toString()); | |||
assertTrue("OrTypePattern", t instanceof OrTypePattern); | |||
assertEquals("((@((Foo || Boo)) Foo) || (@((Foo || Boo)) Boo))", t | |||
.toString()); | |||
} | |||
public void testNotSyntax() { | |||
PatternParser p = new PatternParser("!@Foo (Foo || Boo))"); | |||
TypePattern t = p.parseTypePattern(); | |||
assertTrue("OrTypePattern",t instanceof OrTypePattern); | |||
assertEquals("((!@(Foo) Foo) || (!@(Foo) Boo))",t.toString()); | |||
assertTrue("OrTypePattern", t instanceof OrTypePattern); | |||
assertEquals("((!@(Foo) Foo) || (!@(Foo) Boo))", t.toString()); | |||
} | |||
public void testParseMethodOrConstructorSigNoAP() { | |||
PatternParser p = new PatternParser("* *.*(..)"); | |||
SignaturePattern s = p.parseMethodOrConstructorSignaturePattern(); | |||
assertEquals("Any annotation",AnnotationTypePattern.ANY,s.getAnnotationPattern()); | |||
assertEquals("Any return","*",s.getReturnType().toString()); | |||
assertEquals("Any dec type","*",s.getDeclaringType().toString()); | |||
assertEquals("Any name","*",s.getName().toString()); | |||
assertEquals("* *.*(..)",s.toString()); | |||
assertEquals("Any annotation", AnnotationTypePattern.ANY, s | |||
.getAnnotationPattern()); | |||
assertEquals("Any return", "*", s.getReturnType().toString()); | |||
assertEquals("Any dec type", "*", s.getDeclaringType().toString()); | |||
assertEquals("Any name", "*", s.getName().toString()); | |||
assertEquals("* *.*(..)", s.toString()); | |||
} | |||
public void testParseMethodOrConstructorSigSimpleAP() { | |||
PatternParser p = new PatternParser("@Foo * *.*(..)"); | |||
SignaturePattern s = p.parseMethodOrConstructorSignaturePattern(); | |||
assertEquals("@(Foo) annotation","@(Foo)",s.getAnnotationPattern().toString()); | |||
assertEquals("Any return","*",s.getReturnType().toString()); | |||
assertEquals("Any dec type","*",s.getDeclaringType().toString()); | |||
assertEquals("Any name","*",s.getName().toString()); | |||
assertEquals("@(Foo) * *.*(..)",s.toString()); | |||
assertEquals("@(Foo) annotation", "@(Foo)", s.getAnnotationPattern() | |||
.toString()); | |||
assertEquals("Any return", "*", s.getReturnType().toString()); | |||
assertEquals("Any dec type", "*", s.getDeclaringType().toString()); | |||
assertEquals("Any name", "*", s.getName().toString()); | |||
assertEquals("@(Foo) * *.*(..)", s.toString()); | |||
} | |||
public void testParseMethodOrConstructorSigComplexAP() { | |||
PatternParser p = new PatternParser("!@(Foo || Goo) * *.*(..)"); | |||
SignaturePattern s = p.parseMethodOrConstructorSignaturePattern(); | |||
assertEquals("complex annotation","!@((Foo || Goo))",s.getAnnotationPattern().toString()); | |||
assertEquals("Any return","*",s.getReturnType().toString()); | |||
assertEquals("Any dec type","*",s.getDeclaringType().toString()); | |||
assertEquals("Any name","*",s.getName().toString()); | |||
assertEquals("!@((Foo || Goo)) * *.*(..)",s.toString()); | |||
assertEquals("complex annotation", "!@((Foo || Goo))", s | |||
.getAnnotationPattern().toString()); | |||
assertEquals("Any return", "*", s.getReturnType().toString()); | |||
assertEquals("Any dec type", "*", s.getDeclaringType().toString()); | |||
assertEquals("Any name", "*", s.getName().toString()); | |||
assertEquals("!@((Foo || Goo)) * *.*(..)", s.toString()); | |||
} | |||
public void testParseMethodFieldSigNoAP() { | |||
PatternParser p = new PatternParser("* *.*"); | |||
SignaturePattern s = p.parseFieldSignaturePattern(); | |||
assertEquals("Any annotation",AnnotationTypePattern.ANY,s.getAnnotationPattern()); | |||
assertEquals("Any field type","*",s.getReturnType().toString()); | |||
assertEquals("Any dec type","*",s.getDeclaringType().toString()); | |||
assertEquals("Any name","*",s.getName().toString()); | |||
assertEquals("* *.*",s.toString()); | |||
assertEquals("Any annotation", AnnotationTypePattern.ANY, s | |||
.getAnnotationPattern()); | |||
assertEquals("Any field type", "*", s.getReturnType().toString()); | |||
assertEquals("Any dec type", "*", s.getDeclaringType().toString()); | |||
assertEquals("Any name", "*", s.getName().toString()); | |||
assertEquals("* *.*", s.toString()); | |||
} | |||
public void testParseFieldSigSimpleAP() { | |||
PatternParser p = new PatternParser("@Foo * *.*"); | |||
SignaturePattern s = p.parseFieldSignaturePattern(); | |||
assertEquals("@Foo annotation","@(Foo)",s.getAnnotationPattern().toString()); | |||
assertEquals("Any field type","*",s.getReturnType().toString()); | |||
assertEquals("Any dec type","*",s.getDeclaringType().toString()); | |||
assertEquals("Any name","*",s.getName().toString()); | |||
assertEquals("@(Foo) * *.*",s.toString()); | |||
assertEquals("@Foo annotation", "@(Foo)", s.getAnnotationPattern() | |||
.toString()); | |||
assertEquals("Any field type", "*", s.getReturnType().toString()); | |||
assertEquals("Any dec type", "*", s.getDeclaringType().toString()); | |||
assertEquals("Any name", "*", s.getName().toString()); | |||
assertEquals("@(Foo) * *.*", s.toString()); | |||
} | |||
public void testParseFieldSigComplexAP() { | |||
PatternParser p = new PatternParser("!@(Foo || Goo) * *.*"); | |||
SignaturePattern s = p.parseFieldSignaturePattern(); | |||
assertEquals("complex annotation","!@((Foo || Goo))",s.getAnnotationPattern().toString()); | |||
assertEquals("Any field type","*",s.getReturnType().toString()); | |||
assertEquals("Any dec type","*",s.getDeclaringType().toString()); | |||
assertEquals("Any name","*",s.getName().toString()); | |||
assertEquals("!@((Foo || Goo)) * *.*",s.toString()); | |||
assertEquals("complex annotation", "!@((Foo || Goo))", s | |||
.getAnnotationPattern().toString()); | |||
assertEquals("Any field type", "*", s.getReturnType().toString()); | |||
assertEquals("Any dec type", "*", s.getDeclaringType().toString()); | |||
assertEquals("Any name", "*", s.getName().toString()); | |||
assertEquals("!@((Foo || Goo)) * *.*", s.toString()); | |||
} | |||
public void testExactAnnotationPatternMatching() { | |||
if (LangUtil.is15VMOrGreater()) { | |||
PatternParser p = new PatternParser("@Foo"); | |||
AnnotationTypePattern ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[]{"Foo"}); | |||
assertTrue("matches element with Foo",ap.matches(ae).alwaysTrue()); | |||
AnnotatedElementImpl ae2 = new AnnotatedElementImpl(new String[]{"Boo"}); | |||
assertTrue("does not match element with Boo",ap.matches(ae2).alwaysFalse()); | |||
PatternParser p = new PatternParser("@Foo"); | |||
AnnotationTypePattern ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(), new Bindings(3), true); | |||
AnnotatedElementImpl ae = new AnnotatedElementImpl( | |||
new String[] { "Foo" }); | |||
assertTrue("matches element with Foo", ap.matches(ae).alwaysTrue()); | |||
AnnotatedElementImpl ae2 = new AnnotatedElementImpl( | |||
new String[] { "Boo" }); | |||
assertTrue("does not match element with Boo", ap.matches(ae2) | |||
.alwaysFalse()); | |||
} | |||
} | |||
public void testBindingAnnotationPatternMatching() { | |||
if (LangUtil.is15VMOrGreater()) { | |||
PatternParser p = new PatternParser("foo"); | |||
AnnotationTypePattern ap = p.parseAnnotationNameOrVarTypePattern(); | |||
try { | |||
ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
} catch(AbortException abEx) { | |||
assertEquals("Binding not supported in @pcds (1.5.0 M1 limitation): null",abEx.getMessage()); | |||
} | |||
// uncomment these next lines once binding is supported | |||
// AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[]{"Foo"}); | |||
// assertTrue("matches element with Foo",ap.matches(ae).alwaysTrue()); | |||
// AnnotatedElementImpl ae2 = new AnnotatedElementImpl(new String[]{"Boo"}); | |||
// assertTrue("does not match element with Boo",ap.matches(ae2).alwaysFalse()); | |||
PatternParser p = new PatternParser("foo"); | |||
AnnotationTypePattern ap = p.parseAnnotationNameOrVarTypePattern(); | |||
try { | |||
ap = ap.resolveBindings(makeSimpleScope(), new Bindings(3), | |||
true); | |||
} catch (AbortException abEx) { | |||
assertEquals( | |||
"Binding not supported in @pcds (1.5.0 M1 limitation): null", | |||
abEx.getMessage()); | |||
} | |||
// uncomment these next lines once binding is supported | |||
// AnnotatedElementImpl ae = new AnnotatedElementImpl(new | |||
// String[]{"Foo"}); | |||
//assertTrue("matches element with Foo",ap.matches(ae).alwaysTrue()) | |||
// ; | |||
// AnnotatedElementImpl ae2 = new AnnotatedElementImpl(new | |||
// String[]{"Boo"}); | |||
// assertTrue("does not match element with Boo",ap.matches(ae2). | |||
// alwaysFalse()); | |||
} | |||
} | |||
public void testAndAnnotationPatternMatching() { | |||
if (LangUtil.is15VMOrGreater()) { | |||
PatternParser p = new PatternParser("@Foo @Boo"); | |||
AnnotationTypePattern ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] {"Foo","Boo"}); | |||
assertTrue("matches foo and boo",ap.matches(ae).alwaysTrue()); | |||
ae = new AnnotatedElementImpl(new String[] {"Foo"}); | |||
assertTrue("does not match foo",ap.matches(ae).alwaysFalse()); | |||
ae = new AnnotatedElementImpl(new String[] {"Boo"}); | |||
assertTrue("does not match boo",ap.matches(ae).alwaysFalse()); | |||
ae = new AnnotatedElementImpl(new String[] {"Goo"}); | |||
assertTrue("does not match goo",ap.matches(ae).alwaysFalse()); | |||
PatternParser p = new PatternParser("@Foo @Boo"); | |||
AnnotationTypePattern ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(), new Bindings(3), true); | |||
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] { | |||
"Foo", "Boo" }); | |||
assertTrue("matches foo and boo", ap.matches(ae).alwaysTrue()); | |||
ae = new AnnotatedElementImpl(new String[] { "Foo" }); | |||
assertTrue("does not match foo", ap.matches(ae).alwaysFalse()); | |||
ae = new AnnotatedElementImpl(new String[] { "Boo" }); | |||
assertTrue("does not match boo", ap.matches(ae).alwaysFalse()); | |||
ae = new AnnotatedElementImpl(new String[] { "Goo" }); | |||
assertTrue("does not match goo", ap.matches(ae).alwaysFalse()); | |||
} | |||
} | |||
// | |||
// public void testOrAnnotationPatternMatching() { | |||
// PatternParser p = new PatternParser("@Foo || @Boo"); | |||
// AnnotationTypePattern ap = p.parseAnnotationTypePattern(); | |||
// ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
// AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] {"Foo","Boo"}); | |||
// assertTrue("matches foo and boo",ap.matches(ae).alwaysTrue()); | |||
// ae = new AnnotatedElementImpl(new String[] {"Foo"}); | |||
// assertTrue("matches foo",ap.matches(ae).alwaysTrue()); | |||
// ae = new AnnotatedElementImpl(new String[] {"Boo"}); | |||
// assertTrue("matches boo",ap.matches(ae).alwaysTrue()); | |||
// ae = new AnnotatedElementImpl(new String[] {"Goo"}); | |||
// assertTrue("does not match goo",ap.matches(ae).alwaysFalse()); | |||
// } | |||
// | |||
// | |||
// public void testOrAnnotationPatternMatching() { | |||
// PatternParser p = new PatternParser("@Foo || @Boo"); | |||
// AnnotationTypePattern ap = p.parseAnnotationTypePattern(); | |||
// ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
// AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] | |||
// {"Foo","Boo"}); | |||
// assertTrue("matches foo and boo",ap.matches(ae).alwaysTrue()); | |||
// ae = new AnnotatedElementImpl(new String[] {"Foo"}); | |||
// assertTrue("matches foo",ap.matches(ae).alwaysTrue()); | |||
// ae = new AnnotatedElementImpl(new String[] {"Boo"}); | |||
// assertTrue("matches boo",ap.matches(ae).alwaysTrue()); | |||
// ae = new AnnotatedElementImpl(new String[] {"Goo"}); | |||
// assertTrue("does not match goo",ap.matches(ae).alwaysFalse()); | |||
// } | |||
// | |||
public void testNotAnnotationPatternMatching() { | |||
if (LangUtil.is15VMOrGreater()) { | |||
PatternParser p = new PatternParser("!@Foo"); | |||
AnnotationTypePattern ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] {"Foo","Boo"}); | |||
assertTrue("does not match foo and boo",ap.matches(ae).alwaysFalse()); | |||
ae = new AnnotatedElementImpl(new String[] {"Boo"}); | |||
assertTrue("matches boo",ap.matches(ae).alwaysTrue()); | |||
PatternParser p = new PatternParser("!@Foo"); | |||
AnnotationTypePattern ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(), new Bindings(3), true); | |||
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] { | |||
"Foo", "Boo" }); | |||
assertTrue("does not match foo and boo", ap.matches(ae) | |||
.alwaysFalse()); | |||
ae = new AnnotatedElementImpl(new String[] { "Boo" }); | |||
assertTrue("matches boo", ap.matches(ae).alwaysTrue()); | |||
} | |||
} | |||
public void testAnyAnnotationPatternMatching() { | |||
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] {"Foo","Boo"}); | |||
assertTrue("always matches",AnnotationTypePattern.ANY.matches(ae).alwaysTrue()); | |||
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] { | |||
"Foo", "Boo" }); | |||
assertTrue("always matches", AnnotationTypePattern.ANY.matches(ae) | |||
.alwaysTrue()); | |||
ae = new AnnotatedElementImpl(new String[] {}); | |||
assertTrue("always matches",AnnotationTypePattern.ANY.matches(ae).alwaysTrue()); | |||
assertTrue("always matches", AnnotationTypePattern.ANY.matches(ae) | |||
.alwaysTrue()); | |||
} | |||
public TestScope makeSimpleScope() { | |||
BcelWorld bWorld = new BcelWorld(BcweaverTests.TESTDATA_PATH + "/testcode.jar"); // testcode contains Foo/Boo/Goo/etc | |||
BcelWorld bWorld = new BcelWorld(BcweaverTests.TESTDATA_PATH | |||
+ "/testcode.jar"); // testcode contains Foo/Boo/Goo/etc | |||
bWorld.setBehaveInJava5Way(true); | |||
return new TestScope(new String[] {"int", "java.lang.String","Foo","Boo","Goo"}, | |||
new String[] {"a", "b","foo","boo","goo"}, | |||
bWorld); | |||
return new TestScope(new String[] { "int", "java.lang.String", "Foo", | |||
"Boo", "Goo" }, new String[] { "a", "b", "foo", "boo", "goo" }, | |||
bWorld); | |||
} | |||
// put test cases for AnnotationPatternList matching in separate test class... | |||
// put test cases for AnnotationPatternList matching in separate test | |||
// class... | |||
static class AnnotatedElementImpl implements AnnotatedElement { | |||
private String[] annotationTypes; | |||
public AnnotatedElementImpl(String[] annotationTypes) { | |||
public AnnotatedElementImpl(String[] annotationTypes) { | |||
this.annotationTypes = annotationTypes; | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
for (int i = 0; i < annotationTypes.length; i++) { | |||
if (annotationTypes[i].equals(ofType.getName())) return true; | |||
if (annotationTypes[i].equals(ofType.getName())) | |||
return true; | |||
} | |||
return false; | |||
} | |||
/* (non-Javadoc) | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see org.aspectj.weaver.AnnotatedElement#getAnnotationTypes() | |||
*/ | |||
public ResolvedType[] getAnnotationTypes() { | |||
@@ -359,10 +411,10 @@ public class AnnotationPatternTestCase extends TestCase { | |||
return null; | |||
} | |||
public AnnotationX getAnnotationOfType(UnresolvedType ofType) { | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
} | |||
} |