/* *******************************************************************
 * Copyright (c) 2002 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: 
 *     PARC     initial implementation 
 *     Andy Clement - June 2005 - separated out from ResolvedType
 * ******************************************************************/
package org.aspectj.weaver;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.World.TypeMap;
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 { public static final ReferenceType[] EMPTY_ARRAY = new ReferenceType[0];
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 final List<WeakReference<ReferenceType>> derivativeTypes = new ArrayList<WeakReference<ReferenceType>>();
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; ReferenceType rawType = null; // generic types have a pointer back to their // raw variant (prevents GC of the raw from // the typemap!) ReferenceTypeDelegate delegate = null; int startPos = 0; int endPos = 0; // cached values for members ResolvedMember[] parameterizedMethods = null; ResolvedMember[] parameterizedFields = null; ResolvedMember[] parameterizedPointcuts = null; WeakReference<ResolvedType[]> parameterizedInterfaces = new WeakReference<ResolvedType[]>( null); Collection<Declare> parameterizedDeclares = null; // Collection parameterizedTypeMungers = null; // During matching it can be necessary to temporary mark types as annotated. // For example // a declare @type may trigger a separate declare parents to match, and so // the annotation // is temporarily held against the referencetype, the annotation will be // properly // added to the class during weaving. private ResolvedType[] annotationTypes = null; private AnnotationAJ[] annotations = null; // Similarly these are temporary replacements and additions for the // superclass and // superinterfaces private ResolvedType newSuperclass; private ResolvedType[] newInterfaces; public ReferenceType(String signature, World world) { super(signature, world); } public ReferenceType(String signature, String signatureErasure, World world) { super(signature, signatureErasure, world); } public static ReferenceType fromTypeX(UnresolvedType tx, World world) { ReferenceType rt = new ReferenceType(tx.getErasureSignature(), world); rt.typeKind = tx.typeKind; return rt; }
Constructor used when creating a parameterized type.
/** * Constructor used when creating a parameterized type. */
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; this.typeKind = TypeKind.PARAMETERIZED; this.delegate = genericReferenceType.getDelegate(); genericReferenceType.addDependentType(this); } synchronized void addDependentType(ReferenceType dependent) { // checkDuplicates(dependent); synchronized (derivativeTypes) { this.derivativeTypes .add(new WeakReference<ReferenceType>(dependent)); } } public void checkDuplicates(ReferenceType newRt) { synchronized (derivativeTypes) { List<WeakReference<ReferenceType>> forRemoval = new ArrayList<WeakReference<ReferenceType>>(); for (WeakReference<ReferenceType> derivativeTypeReference : derivativeTypes) { ReferenceType derivativeType = derivativeTypeReference.get(); if (derivativeType == null) { forRemoval.add(derivativeTypeReference); } else { if (derivativeType.getTypekind() != newRt.getTypekind()) { continue; // cannot be this one } if (equal2(newRt.getTypeParameters(), derivativeType.getTypeParameters())) { if (TypeMap.useExpendableMap) { throw new IllegalStateException(); } } } } derivativeTypes.removeAll(forRemoval); } } private boolean equal2(UnresolvedType[] typeParameters, UnresolvedType[] resolvedParameters) { if (typeParameters.length != resolvedParameters.length) { return false; } int len = typeParameters.length; for (int p = 0; p < len; p++) { if (!typeParameters[p].equals(resolvedParameters[p])) { return false; } } return true; } @Override public String getSignatureForAttribute() { if (genericType == null || typeParameters == null) { return getSignature(); } return makeDeclaredSignature(genericType, typeParameters); }
Create a reference type for a generic type
/** * Create a reference type for a generic type */
public ReferenceType(UnresolvedType genericType, World world) { super(genericType.getSignature(), world); typeKind = TypeKind.GENERIC; this.typeVariables = genericType.typeVariables; } @Override public boolean isClass() { return getDelegate().isClass(); } @Override public int getCompilerVersion() { return getDelegate().getCompilerVersion(); } @Override public boolean isGenericType() { return !isParameterizedType() && !isRawType() && getDelegate().isGeneric(); } public String getGenericSignature() { String sig = getDelegate().getDeclaredGenericSignature(); return (sig == null) ? "" : sig; } @Override public AnnotationAJ[] getAnnotations() { return getDelegate().getAnnotations(); } @Override public boolean hasAnnotations() { return getDelegate().hasAnnotations(); } @Override public void addAnnotation(AnnotationAJ annotationX) { if (annotations == null) { annotations = new AnnotationAJ[] { annotationX }; } else { AnnotationAJ[] newAnnotations = new AnnotationAJ[annotations.length + 1]; System.arraycopy(annotations, 0, newAnnotations, 1, annotations.length); newAnnotations[0] = annotationX; annotations = newAnnotations; } addAnnotationType(annotationX.getType()); } public boolean hasAnnotation(UnresolvedType ofType) { boolean onDelegate = getDelegate().hasAnnotation(ofType); if (onDelegate) { return true; } if (annotationTypes != null) { for (int i = 0; i < annotationTypes.length; i++) { if (annotationTypes[i].equals(ofType)) { return true; } } } return false; } private void addAnnotationType(ResolvedType ofType) { if (annotationTypes == null) { annotationTypes = new ResolvedType[1]; annotationTypes[0] = ofType; } else { ResolvedType[] newAnnotationTypes = new ResolvedType[annotationTypes.length + 1]; System.arraycopy(annotationTypes, 0, newAnnotationTypes, 1, annotationTypes.length); newAnnotationTypes[0] = ofType; annotationTypes = newAnnotationTypes; } } @Override public ResolvedType[] getAnnotationTypes() { if (getDelegate() == null) { throw new BCException("Unexpected null delegate for type " + this.getName()); } if (annotationTypes == null) { // there are no extras: return getDelegate().getAnnotationTypes(); } else { ResolvedType[] delegateAnnotationTypes = getDelegate() .getAnnotationTypes(); ResolvedType[] result = new ResolvedType[annotationTypes.length + delegateAnnotationTypes.length]; System.arraycopy(delegateAnnotationTypes, 0, result, 0, delegateAnnotationTypes.length); System.arraycopy(annotationTypes, 0, result, delegateAnnotationTypes.length, annotationTypes.length); return result; } } @Override public String getNameAsIdentifier() { return getRawName().replace('.', '_'); } @Override public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { AnnotationAJ[] axs = getDelegate().getAnnotations(); if (axs != null) { for (int i = 0; i < axs.length; i++) { if (axs[i].getTypeSignature().equals(ofType.getSignature())) { return axs[i]; } } } if (annotations != null) { String searchSig = ofType.getSignature(); for (int i = 0; i < annotations.length; i++) { if (annotations[i].getTypeSignature().equals(searchSig)) { return annotations[i]; } } } return null; } @Override public boolean isAspect() { return getDelegate().isAspect(); } @Override public boolean isAnnotationStyleAspect() { return getDelegate().isAnnotationStyleAspect(); } @Override public boolean isEnum() { return getDelegate().isEnum(); } @Override public boolean isAnnotation() { return getDelegate().isAnnotation(); } @Override public boolean isAnonymous() { return getDelegate().isAnonymous(); } @Override public boolean isNested() { return getDelegate().isNested(); } public ResolvedType getOuterClass() { return getDelegate().getOuterClass(); } public String getRetentionPolicy() { return getDelegate().getRetentionPolicy(); } @Override public boolean isAnnotationWithRuntimeRetention() { return getDelegate().isAnnotationWithRuntimeRetention(); } @Override public boolean canAnnotationTargetType() { return getDelegate().canAnnotationTargetType(); } @Override public AnnotationTargetKind[] getAnnotationTargetKinds() { return getDelegate().getAnnotationTargetKinds(); } // true iff the statement "this = (ThisType) other" would compile @Override public boolean isCoerceableFrom(ResolvedType o) { ResolvedType other = o.resolve(world); if (this.isAssignableFrom(other) || other.isAssignableFrom(this)) { return true; } if (this.isParameterizedType() && other.isParameterizedType()) { return isCoerceableFromParameterizedType(other); } if (this.isParameterizedType() && other.isRawType()) { return ((ReferenceType) this.getRawType()).isCoerceableFrom(other .getGenericType()); } if (this.isRawType() && other.isParameterizedType()) { return this.getGenericType().isCoerceableFrom((other.getRawType())); } if (!this.isInterface() && !other.isInterface()) { return false; } if (this.isFinal() || other.isFinal()) { return false; } // 20170927: What is the block of code for? It mentions jls5.5 which isn't on this topic (old version of jls?) // Some possible references: http://docs.oracle.com/javase/specs/jls/se9/jls9.pdf 5.1.6 (narrowing reference conversion) // On Java 9 the test GenericsTests.testAfterReturningWithWildcardVar will fail because this code below // used to find Set and List were the same, but now finds they are not. (so it doesn't put out the unchecked // conversion message). However the code "List l = (List)someSet;" still compiles on 9 - so is this code bogus? // ??? needs to be Methods, not just declared methods? JLS 5.5 unclear ResolvedMember[] a = getDeclaredMethods(); ResolvedMember[] b = other.getDeclaredMethods(); 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])) { return false; } } } return true; } private final boolean isCoerceableFromParameterizedType(ResolvedType other) { if (!other.isParameterizedType()) { return false; } ResolvedType myRawType = getRawType(); ResolvedType theirRawType = other.getRawType(); if (myRawType == theirRawType || myRawType.isCoerceableFrom(theirRawType)) { if (getTypeParameters().length == other.getTypeParameters().length) { // there's a chance it can be done ResolvedType[] myTypeParameters = 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> if (myTypeParameters[i].isGenericWildcard()) { BoundedReferenceType wildcard = (BoundedReferenceType) myTypeParameters[i]; if (!wildcard .canBeCoercedTo(theirTypeParameters[i])) { return false; } } 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()) { TypeVariableReferenceType tvrt = (TypeVariableReferenceType) theirTypeParameters[i]; TypeVariable tv = tvrt.getTypeVariable(); tv.resolve(world); if (!tv.canBeBoundTo(myTypeParameters[i])) { return false; } } else if (theirTypeParameters[i].isGenericWildcard()) { BoundedReferenceType wildcard = (BoundedReferenceType) theirTypeParameters[i]; if (!wildcard.canBeCoercedTo(myTypeParameters[i])) { return false; } } else { return false; } } } return true; } // } else { // // we do this walk for situations like the following: // // Base<T>, Sub<S,T> extends Base<S> // // is Sub<Y,Z> coerceable from Base<X> ??? // for (Iterator i = getDirectSupertypes(); i.hasNext();) { // ReferenceType parent = (ReferenceType) i.next(); // if (parent.isCoerceableFromParameterizedType(other)) // return true; // } } return false; } @Override public boolean isAssignableFrom(ResolvedType other) { return isAssignableFrom(other, false); } // TODO rewrite this method - it is a terrible mess // true iff the statement "this = other" would compile. @Override public boolean isAssignableFrom(ResolvedType other, boolean allowMissing) { if (other.isPrimitiveType()) { if (!world.isInJava5Mode()) { return false; } if (ResolvedType.validBoxing.contains(this.getSignature() + other.getSignature())) { return true; } } if (this == other) { return true; } if (this.getSignature().equals("Ljava/lang/Object;")) { return true; } if (!isTypeVariableReference() && other.getSignature().equals("Ljava/lang/Object;")) { return false; } boolean thisRaw = this.isRawType(); if (thisRaw && other.isParameterizedOrGenericType()) { return isAssignableFrom(other.getRawType()); } boolean thisGeneric = this.isGenericType(); if (thisGeneric && other.isParameterizedOrRawType()) { return isAssignableFrom(other.getGenericType()); } if (this.isParameterizedType()) { // look at wildcards... if (((ReferenceType) this.getRawType()).isAssignableFrom(other)) { boolean wildcardsAllTheWay = true; ResolvedType[] myParameters = this.getResolvedTypeParameters(); for (int i = 0; i < myParameters.length; i++) { if (!myParameters[i].isGenericWildcard()) { wildcardsAllTheWay = false; } else { BoundedReferenceType boundedRT = (BoundedReferenceType) myParameters[i]; if (boundedRT.isExtends() || boundedRT.isSuper()) { wildcardsAllTheWay = false; } } } if (wildcardsAllTheWay && !other.isParameterizedType()) { return true; } // we have to match by parameters one at a time ResolvedType[] theirParameters = other .getResolvedTypeParameters(); boolean parametersAssignable = true; if (myParameters.length == theirParameters.length) { for (int i = 0; i < myParameters.length && parametersAssignable; i++) { if (myParameters[i] == theirParameters[i]) { continue; } // dont do this: pr253109 // if // (myParameters[i].isAssignableFrom(theirParameters[i], // allowMissing)) { // continue; // } ResolvedType mp = myParameters[i]; ResolvedType tp = theirParameters[i]; if (mp.isParameterizedType() && tp.isParameterizedType()) { if (mp.getGenericType().equals(tp.getGenericType())) { UnresolvedType[] mtps = mp.getTypeParameters(); UnresolvedType[] ttps = tp.getTypeParameters(); for (int ii = 0; ii < mtps.length; ii++) { if (mtps[ii].isTypeVariableReference() && ttps[ii] .isTypeVariableReference()) { TypeVariable mtv = ((TypeVariableReferenceType) mtps[ii]) .getTypeVariable(); boolean b = mtv .canBeBoundTo((ResolvedType) ttps[ii]); if (!b) {// TODO incomplete testing here // I think parametersAssignable = false; break; } } else { parametersAssignable = false; break; } } continue; } else { parametersAssignable = false; break; } } if (myParameters[i].isTypeVariableReference() && theirParameters[i].isTypeVariableReference()) { TypeVariable myTV = ((TypeVariableReferenceType) myParameters[i]) .getTypeVariable(); // TypeVariable theirTV = // ((TypeVariableReferenceType) // theirParameters[i]).getTypeVariable(); boolean b = myTV.canBeBoundTo(theirParameters[i]); if (!b) {// TODO incomplete testing here I think parametersAssignable = false; break; } else { continue; } } if (!myParameters[i].isGenericWildcard()) { parametersAssignable = false; break; } else { BoundedReferenceType wildcardType = (BoundedReferenceType) myParameters[i]; if (!wildcardType.alwaysMatches(theirParameters[i])) { parametersAssignable = false; break; } } } } else { parametersAssignable = false; } if (parametersAssignable) { return true; } } } // eg this=T other=Ljava/lang/Object; if (isTypeVariableReference() && !other.isTypeVariableReference()) { 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(); } else { // FIXME asc should this say canBeBoundTo?? return this.isAssignableFrom(otherType.getTypeVariable() .getFirstBound().resolve(world)); } } if (allowMissing && other.isMissing()) { return false; } ResolvedType[] interfaces = other.getDeclaredInterfaces(); for (ResolvedType intface : interfaces) { boolean b; if (thisRaw && intface.isParameterizedOrGenericType()) { b = this.isAssignableFrom(intface.getRawType(), allowMissing); } else { b = this.isAssignableFrom(intface, allowMissing); } if (b) { return true; } } ResolvedType superclass = other.getSuperclass(); if (superclass != null) { boolean b; if (thisRaw && superclass.isParameterizedOrGenericType()) { b = this.isAssignableFrom(superclass.getRawType(), allowMissing); } else { b = this.isAssignableFrom(superclass, allowMissing); } if (b) { return true; } } return false; } @Override public ISourceContext getSourceContext() { return getDelegate().getSourceContext(); } @Override public ISourceLocation getSourceLocation() { ISourceContext isc = getDelegate().getSourceContext(); return isc.makeSourceLocation(new Position(startPos, endPos)); } @Override public boolean isExposedToWeaver() { return (getDelegate() == null) || delegate.isExposedToWeaver(); } @Override public WeaverStateInfo getWeaverState() { return getDelegate().getWeaverState(); } @Override public ResolvedMember[] getDeclaredFields() { if (parameterizedFields != null) { return parameterizedFields; } if (isParameterizedType() || isRawType()) { ResolvedMember[] delegateFields = getDelegate().getDeclaredFields(); parameterizedFields = new ResolvedMember[delegateFields.length]; for (int i = 0; i < delegateFields.length; i++) { parameterizedFields[i] = delegateFields[i].parameterizedWith( getTypesForMemberParameterization(), this, isParameterizedType()); } return parameterizedFields; } else { return getDelegate().getDeclaredFields(); } }
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. */
@Override public ResolvedType[] getDeclaredInterfaces() { ResolvedType[] interfaces = parameterizedInterfaces.get(); if (interfaces != null) { return interfaces; } ResolvedType[] delegateInterfaces = getDelegate() .getDeclaredInterfaces(); if (isRawType()) { if (newInterfaces != null) {// debug 375777 throw new IllegalStateException( "The raw type should never be accumulating new interfaces, they should be on the generic type. Type is " + this.getName()); } ResolvedType[] newInterfacesFromGenericType = genericType.newInterfaces; if (newInterfacesFromGenericType != null) { ResolvedType[] extraInterfaces = new ResolvedType[delegateInterfaces.length + newInterfacesFromGenericType.length]; System.arraycopy(delegateInterfaces, 0, extraInterfaces, 0, delegateInterfaces.length); System.arraycopy(newInterfacesFromGenericType, 0, extraInterfaces, delegateInterfaces.length, newInterfacesFromGenericType.length); delegateInterfaces = extraInterfaces; } } else if (newInterfaces != null) { // OPTIMIZE does this part of the method trigger often? ResolvedType[] extraInterfaces = new ResolvedType[delegateInterfaces.length + newInterfaces.length]; System.arraycopy(delegateInterfaces, 0, extraInterfaces, 0, delegateInterfaces.length); System.arraycopy(newInterfaces, 0, extraInterfaces, delegateInterfaces.length, newInterfaces.length); delegateInterfaces = extraInterfaces; } if (isParameterizedType()) { // UnresolvedType[] paramTypes = // getTypesForMemberParameterization(); interfaces = 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 // needs more or less than this type does. (pr124803/pr125080) if (delegateInterfaces[i].isParameterizedType()) { interfaces[i] = delegateInterfaces[i].parameterize( getMemberParameterizationMap()).resolve(world); } else { interfaces[i] = delegateInterfaces[i]; } } parameterizedInterfaces = new WeakReference<ResolvedType[]>( interfaces); return interfaces; } else if (isRawType()) { UnresolvedType[] paramTypes = getTypesForMemberParameterization(); interfaces = new ResolvedType[delegateInterfaces.length]; for (int i = 0, max = interfaces.length; i < max; i++) { interfaces[i] = delegateInterfaces[i]; if (interfaces[i].isGenericType()) { // a generic supertype of a raw type is replaced by its raw // equivalent interfaces[i] = interfaces[i].getRawType().resolve( getWorld()); } else if (interfaces[i].isParameterizedType()) { // a parameterized supertype collapses any type vars to // their upper bounds UnresolvedType[] toUseForParameterization = determineThoseTypesToUse( interfaces[i], paramTypes); interfaces[i] = interfaces[i] .parameterizedWith(toUseForParameterization); } } parameterizedInterfaces = new WeakReference<ResolvedType[]>( interfaces); return interfaces; } if (getDelegate().isCacheable()) { parameterizedInterfaces = new WeakReference<ResolvedType[]>( delegateInterfaces); } return delegateInterfaces; }
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: class Foo implements SuperInterface {} where interface SuperInterface {} In that example, a use of the 'Foo' raw type should know that it implements the SuperInterface.
/** * 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>. */
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 // 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. 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) if (rank != -1) { retVal[i] = paramTypes[rank]; } else { retVal[i] = tParms[i]; } } else { retVal[i] = tParms[i]; } } return retVal; }
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(); for (int i = 0; i < thisTypesTVars.length; i++) { TypeVariable tv = thisTypesTVars[i]; if (tv.getName().equals(tvname)) { return i; } } return -1; } @Override public ResolvedMember[] getDeclaredMethods() { if (parameterizedMethods != null) { return parameterizedMethods; } if (isParameterizedType() || isRawType()) { ResolvedMember[] delegateMethods = getDelegate() .getDeclaredMethods(); UnresolvedType[] parameters = getTypesForMemberParameterization(); parameterizedMethods = new ResolvedMember[delegateMethods.length]; for (int i = 0; i < delegateMethods.length; i++) { parameterizedMethods[i] = delegateMethods[i].parameterizedWith( parameters, this, isParameterizedType()); } return parameterizedMethods; } else { return getDelegate().getDeclaredMethods(); } } @Override public ResolvedMember[] getDeclaredPointcuts() { if (parameterizedPointcuts != null) { return parameterizedPointcuts; } if (isParameterizedType()) { ResolvedMember[] delegatePointcuts = getDelegate() .getDeclaredPointcuts(); parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length]; for (int i = 0; i < delegatePointcuts.length; i++) { parameterizedPointcuts[i] = delegatePointcuts[i] .parameterizedWith(getTypesForMemberParameterization(), this, isParameterizedType()); } return parameterizedPointcuts; } else { return getDelegate().getDeclaredPointcuts(); } } private UnresolvedType[] getTypesForMemberParameterization() { UnresolvedType[] parameters = null; if (isParameterizedType()) { parameters = getTypeParameters(); } else if (isRawType()) { // raw type, use upper bounds of type variables on generic type TypeVariable[] tvs = getGenericType().getTypeVariables(); parameters = new UnresolvedType[tvs.length]; for (int i = 0; i < tvs.length; i++) { parameters[i] = tvs[i].getFirstBound(); } } return parameters; } @Override public TypeVariable[] getTypeVariables() { if (typeVariables == null) { typeVariables = getDelegate().getTypeVariables(); for (int i = 0; i < this.typeVariables.length; i++) { typeVariables[i].resolve(world); } } return typeVariables; } @Override public PerClause getPerClause() { PerClause pclause = getDelegate().getPerClause(); if (pclause != null && isParameterizedType()) { // could cache the // result here... Map<String, UnresolvedType> parameterizationMap = getAjMemberParameterizationMap(); pclause = (PerClause) pclause.parameterizeWith(parameterizationMap, world); } return pclause; } @Override public Collection<Declare> getDeclares() { if (parameterizedDeclares != null) { return parameterizedDeclares; } Collection<Declare> declares = null; if (ajMembersNeedParameterization()) { Collection<Declare> genericDeclares = getDelegate().getDeclares(); parameterizedDeclares = new ArrayList<Declare>(); Map<String, UnresolvedType> parameterizationMap = getAjMemberParameterizationMap(); for (Declare declareStatement : genericDeclares) { parameterizedDeclares.add(declareStatement.parameterizeWith( parameterizationMap, world)); } declares = parameterizedDeclares; } else { declares = getDelegate().getDeclares(); } for (Declare d : declares) { d.setDeclaringType(this); } return declares; } @Override public Collection<ConcreteTypeMunger> getTypeMungers() { return getDelegate().getTypeMungers(); } @Override public Collection<ResolvedMember> getPrivilegedAccesses() { return getDelegate().getPrivilegedAccesses(); } @Override public int getModifiers() { return getDelegate().getModifiers(); } WeakReference<ResolvedType> superclassReference = new WeakReference<ResolvedType>( null); @Override public ResolvedType getSuperclass() { ResolvedType ret = null;// superclassReference.get(); // if (ret != null) { // return ret; // } if (newSuperclass != null) { if (this.isParameterizedType() && newSuperclass.isParameterizedType()) { return newSuperclass.parameterize( getMemberParameterizationMap()).resolve(getWorld()); } if (getDelegate().isCacheable()) { superclassReference = new WeakReference<ResolvedType>(ret); } return newSuperclass; } try { world.setTypeVariableLookupScope(this); ret = getDelegate().getSuperclass(); } finally { world.setTypeVariableLookupScope(null); } if (this.isParameterizedType() && ret.isParameterizedType()) { ret = ret.parameterize(getMemberParameterizationMap()).resolve( getWorld()); } if (getDelegate().isCacheable()) { superclassReference = new WeakReference<ResolvedType>(ret); } return ret; } public ReferenceTypeDelegate getDelegate() { return delegate; } 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.copySourceContext() && this.delegate.getSourceContext() != SourceContextImpl.UNKNOWN_SOURCE_CONTEXT) { ((AbstractReferenceTypeDelegate) delegate) .setSourceContext(this.delegate.getSourceContext()); } this.delegate = delegate; synchronized (derivativeTypes) { List<WeakReference<ReferenceType>> forRemoval = new ArrayList<WeakReference<ReferenceType>>(); for (WeakReference<ReferenceType> derivativeRef : derivativeTypes) { ReferenceType derivative = derivativeRef.get(); if (derivative != null) { derivative.setDelegate(delegate); } else { forRemoval.add(derivativeRef); } } derivativeTypes.removeAll(forRemoval); } // If we are raw, we have a generic type - we should ensure it uses the // same delegate if (isRawType() && getGenericType() != null) { ReferenceType genType = (ReferenceType) getGenericType(); if (genType.getDelegate() != delegate) { // avoids circular updates genType.setDelegate(delegate); } } clearParameterizationCaches(); ensureConsistent(); } private void clearParameterizationCaches() { parameterizedFields = null; parameterizedInterfaces.clear(); parameterizedMethods = null; parameterizedPointcuts = null; superclassReference = new WeakReference<ResolvedType>(null); } public int getEndPos() { return endPos; } public int getStartPos() { return startPos; } public void setEndPos(int endPos) { this.endPos = endPos; } public void setStartPos(int startPos) { this.startPos = startPos; } @Override public boolean doesNotExposeShadowMungers() { return getDelegate().doesNotExposeShadowMungers(); } public String getDeclaredGenericSignature() { return getDelegate().getDeclaredGenericSignature(); } public void setGenericType(ReferenceType rt) { genericType = rt; // Should we 'promote' this reference type from simple to raw? // makes sense if someone is specifying that it has a generic form if (typeKind == TypeKind.SIMPLE) { typeKind = TypeKind.RAW; signatureErasure = signature; if (newInterfaces != null) { // debug 375777 throw new IllegalStateException( "Simple type promoted to raw, but simple type had new interfaces/superclass. Type is " + this.getName()); } } if (typeKind == TypeKind.RAW) { genericType.addDependentType(this); } if (isRawType()) { genericType.rawType = this; } if (this.isRawType() && rt.isRawType()) { new RuntimeException( "PR341926 diagnostics: Incorrect setup for a generic type, raw type should not point to raw: " + this.getName()).printStackTrace(); } } public void demoteToSimpleType() { genericType = null; typeKind = TypeKind.SIMPLE; signatureErasure = null; } @Override public ReferenceType getGenericType() { if (isGenericType()) { return this; } return genericType; }
a parameterized signature starts with a "P" in place of the "L", see the comment on signatures in UnresolvedType.
Params:
  • aGenericType –
  • someParameters –
Returns:
/** * 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) { String rawSignature = aGenericType.getErasureSignature(); StringBuffer ret = new StringBuffer(); ret.append(PARAMETERIZED_TYPE_IDENTIFIER); ret.append(rawSignature.substring(1, rawSignature.length() - 1)); ret.append("<"); for (int i = 0; i < someParameters.length; i++) { ret.append(someParameters[i].getSignature()); } ret.append(">;"); return ret.toString(); } 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++) { if (someParameters[i] instanceof ReferenceType) { ret.append(((ReferenceType) someParameters[i]) .getSignatureForAttribute()); } else if (someParameters[i] instanceof Primitive) { ret.append(((Primitive) someParameters[i]) .getSignatureForAttribute()); } else { throw new IllegalStateException( "DebugFor325731: expected a ReferenceType or Primitive but was " + someParameters[i] + " of type " + someParameters[i].getClass().getName()); } } ret.append(">;"); return ret.toString(); } @Override public void ensureConsistent() { annotations = null; annotationTypes = null; newSuperclass = null; bits = 0; // clears the hierarchy complete tag (amongst other things) newInterfaces = null; typeVariables = null; parameterizedInterfaces.clear(); superclassReference = new WeakReference<ResolvedType>(null); if (getDelegate() != null) { delegate.ensureConsistent(); } if (isParameterizedOrRawType()) { ReferenceType genericType = getGenericType(); if (genericType != null) { genericType.ensureConsistent(); } } } @Override public void addParent(ResolvedType newParent) { if (this.isRawType()) { throw new IllegalStateException( "The raw type should never be accumulating new interfaces, they should be on the generic type. Type is " + this.getName()); } if (newParent.isClass()) { newSuperclass = newParent; superclassReference = new WeakReference<ResolvedType>(null); } else { if (newInterfaces == null) { newInterfaces = new ResolvedType[1]; newInterfaces[0] = newParent; } else { ResolvedType[] existing = getDelegate().getDeclaredInterfaces(); if (existing != null) { for (int i = 0; i < existing.length; i++) { if (existing[i].equals(newParent)) { return; // already has this interface } } } ResolvedType[] newNewInterfaces = new ResolvedType[newInterfaces.length + 1]; System.arraycopy(newInterfaces, 0, newNewInterfaces, 1, newInterfaces.length); newNewInterfaces[0] = newParent; newInterfaces = newNewInterfaces; } if (this.isGenericType()) { synchronized (derivativeTypes) { for (WeakReference<ReferenceType> derivativeTypeRef : derivativeTypes) { ReferenceType derivativeType = derivativeTypeRef.get(); if (derivativeType != null) { derivativeType.parameterizedInterfaces.clear(); } } } } parameterizedInterfaces.clear(); } } private boolean equal(UnresolvedType[] typeParameters, ResolvedType[] resolvedParameters) { if (typeParameters.length != resolvedParameters.length) { return false; } int len = typeParameters.length; for (int p = 0; p < len; p++) { if (!typeParameters[p].equals(resolvedParameters[p])) { return false; } } return true; }
Look for a derivative type with the specified type parameters. This can avoid creating an unnecessary new (duplicate) with the same information in it. This method also cleans up any reference entries that have been null'd by a GC.
Params:
  • typeParameters – the type parameters to use when searching for the derivative type.
Returns:an existing derivative type or null if there isn't one
/** * Look for a derivative type with the specified type parameters. This can * avoid creating an unnecessary new (duplicate) with the same information * in it. This method also cleans up any reference entries that have been * null'd by a GC. * * @param typeParameters * the type parameters to use when searching for the derivative * type. * @return an existing derivative type or null if there isn't one */
public ReferenceType findDerivativeType(ResolvedType[] typeParameters) { synchronized (derivativeTypes) { List<WeakReference<ReferenceType>> forRemoval = new ArrayList<WeakReference<ReferenceType>>(); for (WeakReference<ReferenceType> derivativeTypeRef : derivativeTypes) { ReferenceType derivativeType = derivativeTypeRef.get(); if (derivativeType == null) { forRemoval.add(derivativeTypeRef); } else { if (derivativeType.isRawType()) { continue; } if (equal(derivativeType.typeParameters, typeParameters)) { return derivativeType; // this escape route wont remove // the empty refs } } } derivativeTypes.removeAll(forRemoval); } return null; } public boolean hasNewInterfaces() { return newInterfaces != null; } }