Package org.aspectj.weaver

Source Code of org.aspectj.weaver.ResolvedType$Array

/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* Contributors:
*     PARC     initial implementation
*     Alexandre Vasseur    @AspectJ ITDs
* ******************************************************************/


package org.aspectj.weaver;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.patterns.Declare;
import org.aspectj.weaver.patterns.PerClause;

public abstract class ResolvedType extends UnresolvedType implements AnnotatedElement {

  private static final ResolvedType[] EMPTY_RESOLVED_TYPE_ARRAY  = new ResolvedType[0];
  public static final String PARAMETERIZED_TYPE_IDENTIFIER = "P";
 
  private ResolvedType[] resolvedTypeParams;
 
    protected World world;
     
    protected ResolvedType(String signature, World world) {
        super(signature);
        this.world = world;
    }
       
    protected ResolvedType(String signature, String signatureErasure, World world) {
        super(signature,signatureErasure);
        this.world = world;
    }

    // ---- things that don't require a world
   
    /**
     * Returns an iterator through ResolvedType objects representing all the direct
     * supertypes of this type.  That is, through the superclass, if any, and
     * all declared interfaces.
     */
    public final Iterator getDirectSupertypes() {
        Iterator ifacesIterator = Iterators.array(getDeclaredInterfaces());
        ResolvedType superclass = getSuperclass();
        if (superclass == null) {
            return ifacesIterator;
        } else {
            return Iterators.snoc(ifacesIterator, superclass);
        }
    }

    public abstract ResolvedMember[] getDeclaredFields();
    public abstract ResolvedMember[] getDeclaredMethods();
    public abstract ResolvedType[] getDeclaredInterfaces();
    public abstract ResolvedMember[] getDeclaredPointcuts();
    /**
     * Returns a ResolvedType object representing the superclass of this type, or null.
     * If this represents a java.lang.Object, a primitive type, or void, this
     * method returns null. 
     */
    public abstract ResolvedType getSuperclass();

    /**
     * Returns the modifiers for this type. 
     * <p/>
     * See {@link Class#getModifiers()} for a description
     * of the weirdness of this methods on primitives and arrays.
     *
     * @param world the {@link World} in which the lookup is made.
     * @return an int representing the modifiers for this type
     * @see     java.lang.reflect.Modifier
     */
    public abstract int getModifiers();

    // return true if this resolved type couldn't be found (but we know it's name maybe)
    public boolean isMissing() {
        return false;
    }
   
    // FIXME asc I wonder if in some circumstances MissingWithKnownSignature should not be considered
    // 'really' missing as some code can continue based solely on the signature
    public static boolean isMissing (UnresolvedType unresolved) {
      if (unresolved instanceof ResolvedType) {
        ResolvedType resolved = (ResolvedType)unresolved;
        return resolved.isMissing();
      }
      else return (unresolved == MISSING);
    }
   
    public ResolvedType[] getAnnotationTypes() {
      return EMPTY_RESOLVED_TYPE_ARRAY;
    }
   
    public final UnresolvedType getSuperclass(World world) {
        return getSuperclass();
    }

   
    // This set contains pairs of types whose signatures are concatenated
    // together, this means with a fast lookup we can tell if two types
    // are equivalent.
    static Set validBoxing = new HashSet();
   
    static {
      validBoxing.add("Ljava/lang/Byte;B");
      validBoxing.add("Ljava/lang/Character;C");
      validBoxing.add("Ljava/lang/Double;D");
      validBoxing.add("Ljava/lang/Float;F");
      validBoxing.add("Ljava/lang/Integer;I");
      validBoxing.add("Ljava/lang/Long;J");
      validBoxing.add("Ljava/lang/Short;S");
      validBoxing.add("Ljava/lang/Boolean;Z");
      validBoxing.add("BLjava/lang/Byte;");
      validBoxing.add("CLjava/lang/Character;");
      validBoxing.add("DLjava/lang/Double;");
      validBoxing.add("FLjava/lang/Float;");
      validBoxing.add("ILjava/lang/Integer;");
      validBoxing.add("JLjava/lang/Long;");
      validBoxing.add("SLjava/lang/Short;");
      validBoxing.add("ZLjava/lang/Boolean;");
    }
   


    // utilities               
    public ResolvedType getResolvedComponentType() {
      return null;
    }

  public World getWorld() {
    return world;
  }

    // ---- things from object

    public final boolean equals(Object other) {
        if (other instanceof ResolvedType) {
            return this == other;
        } else {
            return super.equals(other);
        }
    }
    // ---- difficult things
   
    /**
     * returns an iterator through all of the fields of this type, in order
     * for checking from JVM spec 2ed 5.4.3.2.  This means that the order is
     * <p/>
     * <ul><li> fields from current class </li>
     *     <li> recur into direct superinterfaces </li>
     *     <li> recur into superclass </li>
     * </ul>
     * <p/>
     * We keep a hashSet of interfaces that we've visited so we don't spiral
     * out into 2^n land.
     */
    public Iterator getFields() {
        final Iterators.Filter dupFilter = Iterators.dupFilter();
        Iterators.Getter typeGetter = new Iterators.Getter() {
            public Iterator get(Object o) {
                return
                    dupFilter.filter(
                        ((ResolvedType)o).getDirectSupertypes());
            }
        };
        Iterators.Getter fieldGetter = new Iterators.Getter() {
            public Iterator get(Object o) {
                return Iterators.array(((ResolvedType)o).getDeclaredFields());
            }
        };
        return
            Iterators.mapOver(
                Iterators.recur(this, typeGetter),
                fieldGetter);
    }

    /**
     * returns an iterator through all of the methods of this type, in order
     * for checking from JVM spec 2ed 5.4.3.3.  This means that the order is
     * <p/>
     * <ul><li> methods from current class </li>
     *     <li> recur into superclass, all the way up, not touching interfaces </li>
     *     <li> recur into all superinterfaces, in some unspecified order </li>
     * </ul>
     * <p/>
     * We keep a hashSet of interfaces that we've visited so we don't spiral
     * out into 2^n land.
     * NOTE: Take a look at the javadoc on getMethodsWithoutIterator() to see if
     * you are sensitive to a quirk in getMethods()
     */
    public Iterator getMethods() {
        final Iterators.Filter dupFilter = Iterators.dupFilter();
        Iterators.Getter ifaceGetter = new Iterators.Getter() {
            public Iterator get(Object o) {
                return
                    dupFilter.filter(
                        Iterators.array(((ResolvedType)o).getDeclaredInterfaces())
                        );                      
            }
        };
        Iterators.Getter methodGetter = new Iterators.Getter() {
            public Iterator get(Object o) {
                return Iterators.array(((ResolvedType)o).getDeclaredMethods());
            }
        };
        return
            Iterators.mapOver(
                Iterators.append(
                    new Iterator() {
                        ResolvedType curr = ResolvedType.this;
                        public boolean hasNext() {
                            return curr != null;
                        }
                        public Object next() {
                            ResolvedType ret = curr;
                            curr = curr.getSuperclass();
                            return ret;
                        }
                        public void remove() {
                            throw new UnsupportedOperationException();
                        }
                    },
                    Iterators.recur(this, ifaceGetter)),
                methodGetter);
    }
   
    /**
     * Return a list of methods, first those declared on this class, then those declared on the superclass (recurse) and then those declared
     * on the superinterfaces.  The getMethods() call above doesn't quite work the same as it will (through the iterator) return methods
     * declared on *this* class twice, once at the start and once at the end - I couldn't debug that problem, so created this alternative.
     */
    public List getMethodsWithoutIterator(boolean includeITDs, boolean allowMissing) {
        List methods = new ArrayList();
        Set knowninterfaces = new HashSet();
        addAndRecurse(knowninterfaces,methods,this,includeITDs,allowMissing);
        return methods;
    }
   
    private void addAndRecurse(Set knowninterfaces,List collector, ResolvedType rtx, boolean includeITDs, boolean allowMissing) {
      collector.addAll(Arrays.asList(rtx.getDeclaredMethods())); // Add the methods declared on this type
      // now add all the inter-typed members too
      if (includeITDs && rtx.interTypeMungers != null) {
        for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
        ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next()
        ResolvedMember rm = tm.getSignature();
        if (rm != null) {  // new parent type munger can have null signature...
          collector.add(tm.getSignature());
        }
      }
      }
      if (!rtx.equals(ResolvedType.OBJECT)) {
        ResolvedType superType = rtx.getSuperclass();
        if (superType != null && !superType.isMissing()) {
          addAndRecurse(knowninterfaces,collector,superType,includeITDs,allowMissing); // Recurse if we aren't at the top
        }
      }
      ResolvedType[] interfaces = rtx.getDeclaredInterfaces(); // Go through the interfaces on the way back down
      for (int i = 0; i < interfaces.length; i++) {
    ResolvedType iface = interfaces[i];

            // we need to know if it is an interface from Parent kind munger
            // as those are used for @AJ ITD and we precisely want to skip those
            boolean shouldSkip = false;
            for (int j = 0; j < rtx.interTypeMungers.size(); j++) {
                ConcreteTypeMunger munger = (ConcreteTypeMunger) rtx.interTypeMungers.get(j);
                if (munger.getMunger().getKind() == ResolvedTypeMunger.Parent) {
                    shouldSkip = true;
                    break;
                }
            }

            if (!shouldSkip && !knowninterfaces.contains(iface)) { // Dont do interfaces more than once
          knowninterfaces.add(iface);
          if (allowMissing && iface.isMissing()) {
          if (iface instanceof MissingResolvedTypeWithKnownSignature) {
            ((MissingResolvedTypeWithKnownSignature)iface).raiseWarningOnMissingInterfaceWhilstFindingMethods();
          }
          } else {
            addAndRecurse(knowninterfaces,collector,iface,includeITDs,allowMissing);
          }
        }
    }
    }

    public ResolvedType[] getResolvedTypeParameters() {
      if (resolvedTypeParams == null) {
        resolvedTypeParams = world.resolve(typeParameters);
      }
      return resolvedTypeParams;
    }
   
    /**
     * described in JVM spec 2ed 5.4.3.2
     */
    public ResolvedMember lookupField(Member m) {
        return lookupMember(m, getFields());
    }

    /**
     * described in JVM spec 2ed 5.4.3.3.
     * Doesnt check ITDs.
     */
    public ResolvedMember lookupMethod(Member m) {
        return lookupMember(m, getMethods());
    }
   
    public ResolvedMember lookupMethodInITDs(Member m) {
      if (interTypeMungers != null) {
      for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
        ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
        if (matches(tm.getSignature(), m)) {
          return tm.getSignature();
        }
      }
    }
      return null;
    }
   
    /**
     * return null if not found
     */
    private ResolvedMember lookupMember(Member m, Iterator i) {
        while (i.hasNext()) {
            ResolvedMember f = (ResolvedMember) i.next();
            if (matches(f, m)) return f;
        }
        return null; //ResolvedMember.Missing;
        //throw new BCException("can't find " + m);
   
   
    /**
     * return null if not found
     */
    private ResolvedMember lookupMember(Member m, ResolvedMember[] a) {
    for (int i = 0; i < a.length; i++) {
      ResolvedMember f = a[i];
            if (matches(f, m)) return f; 
    }
    return null;
    }     
   
   
    /**
     * Looks for the first member in the hierarchy matching aMember. This method
     * differs from lookupMember(Member) in that it takes into account parameters
     * which are type variables - which clearly an unresolved Member cannot do since
     * it does not know anything about type variables.
     */
     public ResolvedMember lookupResolvedMember(ResolvedMember aMember,boolean allowMissing) {
      Iterator toSearch = null;
      ResolvedMember found = null;
      if ((aMember.getKind() == Member.METHOD) || (aMember.getKind() == Member.CONSTRUCTOR)) {
        toSearch = getMethodsWithoutIterator(true,allowMissing).iterator();
      } else {
        if (aMember.getKind() != Member.FIELD)
          throw new IllegalStateException("I didn't know you would look for members of kind " + aMember.getKind());
        toSearch = getFields();
      }
      while(toSearch.hasNext()) {
      ResolvedMemberImpl candidate = (ResolvedMemberImpl) toSearch.next();     
      if (candidate.matches(aMember)) {
        found = candidate;
        break;
      }
    }
     
      return found;
    }
   
    public static boolean matches(Member m1, Member m2) {
        if (m1 == null) return m2 == null;
        if (m2 == null) return false;
       
        // Check the names
        boolean equalNames = m1.getName().equals(m2.getName());
        if (!equalNames) return false;
       
        // Check the signatures
        boolean equalSignatures = m1.getSignature().equals(m2.getSignature());
        if (equalSignatures) return true;

        // If they aren't the same, we need to allow for covariance ... where one sig might be ()LCar; and
        // the subsig might be ()LFastCar; - where FastCar is a subclass of Car
        boolean equalCovariantSignatures = m1.getParameterSignature().equals(m2.getParameterSignature());
        if (equalCovariantSignatures) return true;
       
        return false;
    }
   
    public static boolean conflictingSignature(Member m1, Member m2) {
      if (m1 == null || m2 == null) return false;
     
        if (!m1.getName().equals(m2.getName())) {
            return false;
        }
        if (m1.getKind() != m2.getKind()) {
            return false;
        }
     
      if (m1.getKind() == Member.FIELD) {
        return m1.getDeclaringType().equals(m2.getDeclaringType());
      } else if (m1.getKind() == Member.POINTCUT) {
        return true;
      }
     
      UnresolvedType[] p1 = m1.getParameterTypes();
      UnresolvedType[] p2 = m2.getParameterTypes();
      int n = p1.length;
      if (n != p2.length) return false;
     
      for (int i=0; i < n; i++) {
        if (!p1[i].equals(p2[i])) return false;
      }
      return true;
    }
   
   
    /**
     * returns an iterator through all of the pointcuts of this type, in order
     * for checking from JVM spec 2ed 5.4.3.2 (as for fields).  This means that the order is
     * <p/>
     * <ul><li> pointcuts from current class </li>
     *     <li> recur into direct superinterfaces </li>
     *     <li> recur into superclass </li>
     * </ul>
     * <p/>
     * We keep a hashSet of interfaces that we've visited so we don't spiral
     * out into 2^n land.
     */
    public Iterator getPointcuts() {
        final Iterators.Filter dupFilter = Iterators.dupFilter();
        // same order as fields
        Iterators.Getter typeGetter = new Iterators.Getter() {
            public Iterator get(Object o) {
                return
                    dupFilter.filter(
                        ((ResolvedType)o).getDirectSupertypes());
            }
        };
        Iterators.Getter pointcutGetter = new Iterators.Getter() {
            public Iterator get(Object o) {
                //System.err.println("getting for " + o);
                return Iterators.array(((ResolvedType)o).getDeclaredPointcuts());
            }
        };
        return
            Iterators.mapOver(
                Iterators.recur(this, typeGetter),
                pointcutGetter);
    }
   
    public ResolvedPointcutDefinition findPointcut(String name) {
        //System.err.println("looking for pointcuts " + this);
        for (Iterator i = getPointcuts(); i.hasNext(); ) {
            ResolvedPointcutDefinition f = (ResolvedPointcutDefinition) i.next();
            //System.err.println(f);
            if (name.equals(f.getName())) {
                return f;
            }
        }
        // pr120521
        if (!getOutermostType().equals(this)) {
          ResolvedType outerType = getOutermostType().resolve(world);
          ResolvedPointcutDefinition rpd = outerType.findPointcut(name);
          return rpd;
        }
        return null; // should we throw an exception here?
    }
   
   
    // all about collecting CrosscuttingMembers

  //??? collecting data-structure, shouldn't really be a field
    public CrosscuttingMembers crosscuttingMembers;

  public CrosscuttingMembers collectCrosscuttingMembers() {
    crosscuttingMembers = new CrosscuttingMembers(this);
    crosscuttingMembers.setPerClause(getPerClause());
    crosscuttingMembers.addShadowMungers(collectShadowMungers());
    crosscuttingMembers.addTypeMungers(getTypeMungers());
        //FIXME AV - skip but needed ?? or  ?? crosscuttingMembers.addLateTypeMungers(getLateTypeMungers());
    crosscuttingMembers.addDeclares(collectDeclares(!this.doesNotExposeShadowMungers()));
    crosscuttingMembers.addPrivilegedAccesses(getPrivilegedAccesses());
   
   
    //System.err.println("collected cc members: " + this + ", " + collectDeclares());
    return crosscuttingMembers;
  }
 
  public final Collection collectDeclares(boolean includeAdviceLike) {
    if (! this.isAspect() ) return Collections.EMPTY_LIST;
   
    ArrayList ret = new ArrayList();
    //if (this.isAbstract()) {
//    for (Iterator i = getDeclares().iterator(); i.hasNext();) {
//      Declare dec = (Declare) i.next();
//      if (!dec.isAdviceLike()) ret.add(dec);
//    }
//       
//        if (!includeAdviceLike) return ret;
       
    if (!this.isAbstract()) {
      //ret.addAll(getDeclares());
      final Iterators.Filter dupFilter = Iterators.dupFilter();
          Iterators.Getter typeGetter = new Iterators.Getter() {
              public Iterator get(Object o) {
                  return
                      dupFilter.filter(
                          ((ResolvedType)o).getDirectSupertypes());
              }
          };
          Iterator typeIterator = Iterators.recur(this, typeGetter);
 
          while (typeIterator.hasNext()) {
            ResolvedType ty = (ResolvedType) typeIterator.next();
            //System.out.println("super: " + ty + ", " + );
            for (Iterator i = ty.getDeclares().iterator(); i.hasNext();) {
          Declare dec = (Declare) i.next();
          if (dec.isAdviceLike()) {
            if (includeAdviceLike) ret.add(dec);
          } else {
            ret.add(dec);
          }
        }
          }
    }
   
    return ret;
    }
   
 
 
 
    private final Collection collectShadowMungers() {
        if (! this.isAspect() || this.isAbstract() || this.doesNotExposeShadowMungers()) return Collections.EMPTY_LIST;

    ArrayList acc = new ArrayList();
        final Iterators.Filter dupFilter = Iterators.dupFilter();
        Iterators.Getter typeGetter = new Iterators.Getter() {
            public Iterator get(Object o) {
                return
                    dupFilter.filter(
                        ((ResolvedType)o).getDirectSupertypes());
            }
        };
        Iterator typeIterator = Iterators.recur(this, typeGetter);

        while (typeIterator.hasNext()) {
            ResolvedType ty = (ResolvedType) typeIterator.next();
            acc.addAll(ty.getDeclaredShadowMungers());    
        }
       
        return acc;
    }
   
  protected boolean doesNotExposeShadowMungers() {
    return false;
  }

    public PerClause getPerClause() {
        return null;
    }

  protected Collection getDeclares() {
    return Collections.EMPTY_LIST;
  }
 
    protected Collection getTypeMungers() {
        return Collections.EMPTY_LIST;
    }
 
    protected Collection getPrivilegedAccesses() {
        return Collections.EMPTY_LIST;
    }
 

    // ---- useful things
   
    public final boolean isInterface() {      
        return Modifier.isInterface(getModifiers());
    }
   
    public final boolean isAbstract() {      
        return Modifier.isAbstract(getModifiers());
    }
   
    public boolean isClass() {
      return false;
    }
   
    public boolean isAspect() {
      return false;
    }

    public boolean isAnnotationStyleAspect() {
      return false;
    }

    /**
     * Note: Only overridden by Name subtype.
     */
    public boolean isEnum() {
      return false;
    }
   
    /**
     * Note: Only overridden by Name subtype.
     */
    public boolean isAnnotation() {
      return false;
    }
   
    public boolean isAnonymous() {
        return false;
    }
   
    public boolean isNested() {
        return false;
    }
   
    /**
     * Note: Only overridden by Name subtype
     */
  public void addAnnotation(AnnotationX annotationX) {
    throw new RuntimeException("ResolvedType.addAnnotation() should never be called");
  }
 
  /**
   * Note: Only overridden by Name subtype
   */
  public AnnotationX[] getAnnotations() {
    throw new RuntimeException("ResolvedType.getAnnotations() should never be called");
  }
   
  /**
   * Note: Only overridden by ReferenceType subtype
   */
  public boolean canAnnotationTargetType() {
    return false;
  }
 
  /**
   * Note: Only overridden by ReferenceType subtype
   */ 
  public AnnotationTargetKind[] getAnnotationTargetKinds() {
    return null;
  }
 
    /**
     * Note: Only overridden by Name subtype.
     */
    public boolean isAnnotationWithRuntimeRetention() {
        return false;
    }
   
    public boolean isSynthetic() {
      return signature.indexOf("$ajc") != -1;
    }
   
    public final boolean isFinal() {
        return Modifier.isFinal(getModifiers());
    }

  protected Map /*Type variable name -> UnresolvedType*/ getMemberParameterizationMap() {
    if (!isParameterizedType()) return Collections.EMPTY_MAP;
    TypeVariable[] tvs = getGenericType().getTypeVariables();
    Map parameterizationMap = new HashMap();
    for (int i = 0; i < tvs.length; i++) {
      parameterizationMap.put(tvs[i].getName(), typeParameters[i]);
    }
    return parameterizationMap;
  }

 
  public Collection getDeclaredAdvice() {
    List l = new ArrayList();
    ResolvedMember[] methods = getDeclaredMethods();
    if (isParameterizedType()) methods = getGenericType().getDeclaredMethods();
    Map typeVariableMap = getAjMemberParameterizationMap();
    for (int i=0, len = methods.length; i < len; i++) {
      ShadowMunger munger = methods[i].getAssociatedShadowMunger();
      if (munger != null) {
        if (ajMembersNeedParameterization()) {
          //munger.setPointcut(munger.getPointcut().parameterizeWith(typeVariableMap));
          munger = munger.parameterizeWith(this,typeVariableMap);
          if (munger instanceof Advice) {
            Advice advice = (Advice) munger;
            // update to use the parameterized signature...
            UnresolvedType[] ptypes = methods[i].getGenericParameterTypes()  ;
            UnresolvedType[] newPTypes = new UnresolvedType[ptypes.length];
            for (int j = 0; j < ptypes.length; j++) {
              if (ptypes[j] instanceof TypeVariableReferenceType) {
                TypeVariableReferenceType tvrt = (TypeVariableReferenceType) ptypes[j];
                if (typeVariableMap.containsKey(tvrt.getTypeVariable().getName())) {
                  newPTypes[j] = (UnresolvedType) typeVariableMap.get(tvrt.getTypeVariable().getName());
                } else {
                  newPTypes[j] = ptypes[j];
                }
              } else {
                newPTypes[j] = ptypes[j];
              }
            }
            advice.setBindingParameterTypes(newPTypes);
          }
        }
        munger.setDeclaringType(this);
        l.add(munger);
      }
    }
    return l;
  }
 
  public Collection getDeclaredShadowMungers() {
    Collection c = getDeclaredAdvice();
    return c;
  }
 
  // ---- only for testing!


  public ResolvedMember[] getDeclaredJavaFields() {
    return filterInJavaVisible(getDeclaredFields());
  }
  public ResolvedMember[] getDeclaredJavaMethods() {
    return filterInJavaVisible(getDeclaredMethods());
  }
  public ShadowMunger[] getDeclaredShadowMungersArray() {
    List l = (List) getDeclaredShadowMungers();
    return (ShadowMunger[]) l.toArray(new ShadowMunger[l.size()]);
  }
  private ResolvedMember[] filterInJavaVisible(ResolvedMember[] ms) {
    List l = new ArrayList();
    for (int i=0, len = ms.length; i < len; i++) {
      if (! ms[i].isAjSynthetic() && ms[i].getAssociatedShadowMunger() == null) {
        l.add(ms[i]);
      }
    }
    return (ResolvedMember[]) l.toArray(new ResolvedMember[l.size()]);
  }
 
  public abstract ISourceContext getSourceContext();


    // ---- fields
   
    public static final ResolvedType[] NONE = new ResolvedType[0];

    public static final Primitive BYTE    = new Primitive("B", 1, 0);
    public static final Primitive CHAR    = new Primitive("C", 1, 1);
    public static final Primitive DOUBLE  = new Primitive("D", 2, 2);
    public static final Primitive FLOAT   = new Primitive("F", 1, 3);
    public static final Primitive INT     = new Primitive("I", 1, 4);
    public static final Primitive LONG    = new Primitive("J", 2, 5);
    public static final Primitive SHORT   = new Primitive("S", 1, 6);
    public static final Primitive VOID    = new Primitive("V", 0, 8);
    public static final Primitive BOOLEAN = new Primitive("Z", 1, 7);
    public static final Missing   MISSING = new Missing();
   
    // ---- types
    public static ResolvedType makeArray(ResolvedType type, int dim) {
      if (dim == 0) return type;
      ResolvedType array = new Array("[" + type.getSignature(),"["+type.getErasureSignature(),type.getWorld(),type);
      return makeArray(array,dim-1);
    }
   
    static class Array extends ResolvedType {
        ResolvedType componentType;
      
       
        // Sometimes the erasure is different, eg.  [TT;  and [Ljava/lang/Object;
        Array(String sig, String erasureSig,World world, ResolvedType componentType) {
            super(sig,erasureSig, world);
            this.componentType = componentType;
        }
        public final ResolvedMember[] getDeclaredFields() {
            return ResolvedMember.NONE;
        }
        public final ResolvedMember[] getDeclaredMethods() {
            // ??? should this return clone?  Probably not...
            // If it ever does, here is the code:
            //  ResolvedMember cloneMethod =
            //    new ResolvedMember(Member.METHOD,this,Modifier.PUBLIC,UnresolvedType.OBJECT,"clone",new UnresolvedType[]{});
            //  return new ResolvedMember[]{cloneMethod};
          return ResolvedMember.NONE;
        }
        public final ResolvedType[] getDeclaredInterfaces() {
            return
                new ResolvedType[] {
                    world.getCoreType(CLONEABLE),
                    world.getCoreType(SERIALIZABLE)
                };
        }
        public final ResolvedMember[] getDeclaredPointcuts() {
            return ResolvedMember.NONE;
        }
       
        public boolean hasAnnotation(UnresolvedType ofType) {
          return false;
        }
       
        public final ResolvedType getSuperclass() {
            return world.getCoreType(OBJECT);
        }
        public final boolean isAssignableFrom(ResolvedType o) {
            if (! o.isArray()) return false;
            if (o.getComponentType().isPrimitiveType()) {
                return o.equals(this);
            } else {
                return getComponentType().resolve(world).isAssignableFrom(o.getComponentType().resolve(world));
            }
        }
       
        public boolean isAssignableFrom(ResolvedType o, boolean allowMissing) {
          return isAssignableFrom(o);
        }
       
        public final boolean isCoerceableFrom(ResolvedType o) {
            if (o.equals(UnresolvedType.OBJECT) ||
                    o.equals(UnresolvedType.SERIALIZABLE) ||
                    o.equals(UnresolvedType.CLONEABLE)) {
                return true;
            }
            if (! o.isArray()) return false;
            if (o.getComponentType().isPrimitiveType()) {
                return o.equals(this);
            } else {
                return getComponentType().resolve(world).isCoerceableFrom(o.getComponentType().resolve(world));
            }
        }
        public final int getModifiers() {
            int mask = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
            return (componentType.getModifiers() & mask) | Modifier.FINAL;
        }
        public UnresolvedType getComponentType() {
            return componentType;
        }
        public ResolvedType getResolvedComponentType() {
            return componentType;
        }
        public ISourceContext getSourceContext() {
          return getResolvedComponentType().getSourceContext();
        }
    }
   
    static class Primitive extends ResolvedType {
        private int size;
        private int index;
        Primitive(String signature, int size, int index) {
            super(signature, null);
            this.size = size;
            this.index = index;
            this.typeKind=TypeKind.PRIMITIVE;
        }
        public final int getSize() {
            return size;
        }
        public final int getModifiers() {
            return Modifier.PUBLIC | Modifier.FINAL;
        }
        public final boolean isPrimitiveType() {
            return true;
        }
        public boolean hasAnnotation(UnresolvedType ofType) {
          return false;
        }
        public final boolean isAssignableFrom(ResolvedType other) {
            if (!other.isPrimitiveType()) {
              if (!world.isInJava5Mode()) return false;
              return validBoxing.contains(this.getSignature()+other.getSignature());
            }
            return assignTable[((Primitive)other).index][index];
        }
        public final boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
          return isAssignableFrom(other);
        }       
        public final boolean isCoerceableFrom(ResolvedType other) {
            if (this == other) return true;
            if (! other.isPrimitiveType()) return false;
            if (index > 6 || ((Primitive)other).index > 6) return false;
            return true;
        }
        public ResolvedType resolve(World world) {
            this.world = world;
            return super.resolve(world);
        }
        public final boolean needsNoConversionFrom(ResolvedType other) {
            if (! other.isPrimitiveType()) return false;
            return noConvertTable[((Primitive)other).index][index];
        }          
        private static final boolean[][] assignTable =
            {// to: B     C      D       F      I       J       S      V       Z        from
                { true , true , true , true , true , true , true , false, false }, // B
                { false, true , true , true , true , true , false, false, false }, // C
                { false, false, true , false, false, false, false, false, false }, // D
                { false, false, true , true , false, false, false, false, false }, // F
                { false, false, true , true , true , true , false, false, false }, // I
                { false, false, true , true , false, true , false, false, false }, // J
                { false, false, true , true , true , true , true , false, false }, // S
                { false, false, false, false, false, false, false, true , false }, // V
                { false, false, false, false, false, false, false, false, true  }, // Z
            };            
        private static final boolean[][] noConvertTable =
            {// to: B     C      D       F      I       J       S      V       Z        from
                { true , true , false, false, true , false, true , false, false }, // B
                { false, true , false, false, true , false, false, false, false }, // C
                { false, false, true , false, false, false, false, false, false }, // D
                { false, false, false, true , false, false, false, false, false }, // F
                { false, false, false, false, true , false, false, false, false }, // I
                { false, false, false, false, false, true , false, false, false }, // J
                { false, false, false, false, true , false, true , false, false }, // S
                { false, false, false, false, false, false, false, true , false }, // V
                { false, false, false, false, false, false, false, false, true  }, // Z
            };            
               
        // ----
        public final ResolvedMember[] getDeclaredFields() {
            return ResolvedMember.NONE;
        }
        public final ResolvedMember[] getDeclaredMethods() {
            return ResolvedMember.NONE;
        }
        public final ResolvedType[] getDeclaredInterfaces() {
            return ResolvedType.NONE;
        }
        public final ResolvedMember[] getDeclaredPointcuts() {
            return ResolvedMember.NONE;
        }

        public final ResolvedType getSuperclass() {
            return null;
        }
       
        public ISourceContext getSourceContext() {
          return null;
        }
  
    }

    static class Missing extends ResolvedType {
        Missing() {
            super(MISSING_NAME, null);
        }      
//        public final String toString() {
//            return "<missing>";
//        }     
        public final String getName() {
          return MISSING_NAME;
        }
       
        public final boolean isMissing() {
            return true;
        }
       
        public boolean hasAnnotation(UnresolvedType ofType) {
          return false;
        }
        public final ResolvedMember[] getDeclaredFields() {
            return ResolvedMember.NONE;
        }
        public final ResolvedMember[] getDeclaredMethods() {
            return ResolvedMember.NONE;
        }
        public final ResolvedType[] getDeclaredInterfaces() {
            return ResolvedType.NONE;
        }

        public final ResolvedMember[] getDeclaredPointcuts() {
            return ResolvedMember.NONE;
        }
        public final ResolvedType getSuperclass() {
            return null;
        }
        public final int getModifiers() {
            return 0;
        }
        public final boolean isAssignableFrom(ResolvedType other) {
            return false;
        }  
        public final boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
            return false;
        }  
        public final boolean isCoerceableFrom(ResolvedType other) {
            return false;
        }       
        public boolean needsNoConversionFrom(ResolvedType other) {
            return false;
        }
        public ISourceContext getSourceContext() {
          return null;
        }

    }

    /**
     * Look up a member, takes into account any ITDs on this type.
     * return null if not found
     */
  public ResolvedMember lookupMemberNoSupers(Member member) {
    ResolvedMember ret = lookupDirectlyDeclaredMemberNoSupers(member);
    if (ret == null && interTypeMungers != null) {
      for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
        ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
        if (matches(tm.getSignature(), member)) {
          return tm.getSignature();
        }
      }
    }
    return ret;
  }
 
  public ResolvedMember lookupMemberWithSupersAndITDs(Member member) {
    ResolvedMember ret = lookupMemberNoSupers(member);
    if (ret != null) return ret;
   
    ResolvedType supert = getSuperclass();
    if (supert != null) {
      ret = supert.lookupMemberNoSupers(member);
    }
   
    return ret;
  }
 
  /**
   * as lookupMemberNoSupers, but does not include ITDs
     *
   * @param member
   * @return
   */
  public ResolvedMember lookupDirectlyDeclaredMemberNoSupers(Member member) {
    ResolvedMember ret;
    if (member.getKind() == Member.FIELD) {
      ret = lookupMember(member, getDeclaredFields());
    } else {
      // assert member.getKind() == Member.METHOD || member.getKind() == Member.CONSTRUCTOR
      ret = lookupMember(member, getDeclaredMethods());
    }
    return ret;
  }
 
  /**
   * This lookup has specialized behaviour - a null result tells the
   * EclipseTypeMunger that it should make a default implementation of a
   * method on this type.
     *
   * @param member
   * @return
   */
  public ResolvedMember lookupMemberIncludingITDsOnInterfaces(Member member) {
    return lookupMemberIncludingITDsOnInterfaces(member, this);
  }
 
  private ResolvedMember lookupMemberIncludingITDsOnInterfaces(Member member, ResolvedType onType) {
    ResolvedMember ret = onType.lookupMemberNoSupers(member);
    if (ret != null) {
      return ret;
    } else {
      ResolvedType superType = onType.getSuperclass();
      if (superType != null) {
        ret = lookupMemberIncludingITDsOnInterfaces(member,superType);
      }
      if (ret == null) {
        // try interfaces then, but only ITDs now...
        ResolvedType[] superInterfaces = onType.getDeclaredInterfaces();
        for (int i = 0; i < superInterfaces.length; i++) {
          ret = superInterfaces[i].lookupMethodInITDs(member);
          if (ret != null) return ret;
        }
      }
    }
    return ret;
  }
 
  protected List interTypeMungers = new ArrayList(0);
 
  public List getInterTypeMungers() {
    return interTypeMungers;
  }
   
    public List getInterTypeParentMungers() {
      List l = new ArrayList();
      for (Iterator iter = interTypeMungers.iterator(); iter.hasNext();) {
    ConcreteTypeMunger element = (ConcreteTypeMunger) iter.next();
    if (element.getMunger() instanceof NewParentTypeMunger) l.add(element);
  }
      return l;
    }
   
  /**
   * ??? This method is O(N*M) where N = number of methods and M is number of
   * inter-type declarations in my super
   */
     public List getInterTypeMungersIncludingSupers() {
        ArrayList ret = new ArrayList();
        collectInterTypeMungers(ret);
        return ret;
    }

    
    public List getInterTypeParentMungersIncludingSupers() {
      ArrayList ret = new ArrayList();
      collectInterTypeParentMungers(ret);
      return ret;
    }
   
    private void collectInterTypeParentMungers(List collector) {
        for (Iterator iter = getDirectSupertypes(); iter.hasNext();) {
            ResolvedType superType = (ResolvedType) iter.next();
            superType.collectInterTypeParentMungers(collector);
        }
        collector.addAll(getInterTypeParentMungers());
    }
       
       
    protected void collectInterTypeMungers(List collector) {
        for (Iterator iter = getDirectSupertypes(); iter.hasNext();) {
      ResolvedType superType = (ResolvedType) iter.next();
            superType.collectInterTypeMungers(collector);
    }
       
        outer:
        for (Iterator iter1 = collector.iterator(); iter1.hasNext();) {
            ConcreteTypeMunger superMunger = (ConcreteTypeMunger) iter1.next();
            if ( superMunger.getSignature() == null) continue;
           
            if ( !superMunger.getSignature().isAbstract()) continue;
           
            for (Iterator iter = getInterTypeMungers().iterator(); iter.hasNext();) {
                ConcreteTypeMunger  myMunger = (ConcreteTypeMunger) iter.next();
                if (conflictingSignature(myMunger.getSignature(), superMunger.getSignature())) {
                    iter1.remove();
                    continue outer;
                }
            }
           
            if (!superMunger.getSignature().isPublic()) continue;
           
            for (Iterator iter = getMethods(); iter.hasNext(); ) {
                ResolvedMember method = (ResolvedMember)iter.next();
                if (conflictingSignature(method, superMunger.getSignature())) {
                    iter1.remove();
                    continue outer;
                }
            }
        }
       
        collector.addAll(getInterTypeMungers());
    }
   
   
    /**
     * Check:
     * 1) That we don't have any abstract type mungers unless this type is abstract.
     * 2) That an abstract ITDM on an interface is declared public. (Compiler limitation) (PR70794)
     */
    public void checkInterTypeMungers() {
        if (isAbstract()) return;
       
        boolean itdProblem = false;
       
        for (Iterator iter = getInterTypeMungersIncludingSupers().iterator(); iter.hasNext();) {
      ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
      itdProblem = checkAbstractDeclaration(munger) || itdProblem; // Rule 2

        }
       
        if (itdProblem) return; // If the rules above are broken, return right now
       
    for (Iterator iter = getInterTypeMungersIncludingSupers().iterator(); iter.hasNext();) {
      ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
            if (munger.getSignature() != null && munger.getSignature().isAbstract()) { // Rule 1
                if (munger.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate) {
                    ;//ignore for @AJ ITD as munger.getSignature() is the interface method hence abstract
                } else {
                world.getMessageHandler().handleMessage(
                    new Message("must implement abstract inter-type declaration: " + munger.getSignature(),
                        "", IMessage.ERROR, getSourceLocation(), null,
                        new ISourceLocation[] { getMungerLocation(munger) }));
            }
    }
    }
    }
   
    /**
     * See PR70794.  This method checks that if an abstract inter-type method declaration is made on
     * an interface then it must also be public.
     * This is a compiler limitation that could be made to work in the future (if someone
     * provides a worthwhile usecase)
     *
     * @return indicates if the munger failed the check
     */
    private boolean checkAbstractDeclaration(ConcreteTypeMunger munger) {
    if (munger.getMunger()!=null && (munger.getMunger() instanceof NewMethodTypeMunger)) {
      ResolvedMember itdMember = munger.getSignature();
      ResolvedType onType = itdMember.getDeclaringType().resolve(world);
      if (onType.isInterface() && itdMember.isAbstract() && !itdMember.isPublic()) {
          world.getMessageHandler().handleMessage(
              new Message(WeaverMessages.format(WeaverMessages.ITD_ABSTRACT_MUST_BE_PUBLIC_ON_INTERFACE,munger.getSignature(),onType),"",
                  Message.ERROR,getSourceLocation(),null,
                  new ISourceLocation[]{getMungerLocation(munger)}) 
            );
          return true;
        }     
    }
    return false;
    }
   
    /**
     * Get a source location for the munger.
     * Until intertype mungers remember where they came from, the source location
     * for the munger itself is null.  In these cases use the
     * source location for the aspect containing the ITD.
     */
    private ISourceLocation getMungerLocation(ConcreteTypeMunger munger) {
      ISourceLocation sloc = munger.getSourceLocation();
      if (sloc == null) {
        sloc = munger.getAspectType().getSourceLocation();
      }
      return sloc;
    }
 
    /**
     * Returns a ResolvedType object representing the declaring type of this type, or
     * null if this type does not represent a non-package-level-type.
     * <p/>
     * <strong>Warning</strong>:  This is guaranteed to work for all member types.
     * For anonymous/local types, the only guarantee is given in JLS 13.1, where
     * it guarantees that if you call getDeclaringType() repeatedly, you will eventually
     * get the top-level class, but it does not say anything about classes in between.
     *
     * @return the declaring UnresolvedType object, or null.
     */
    public ResolvedType getDeclaringType() {
      if (isArray()) return null;
    String name = getName();
    int lastDollar = name.lastIndexOf('$');
    while (lastDollar >0) { // allow for classes starting '$' (pr120474)
      ResolvedType ret = world.resolve(UnresolvedType.forName(name.substring(0, lastDollar)), true);
      if (!ResolvedType.isMissing(ret)) return ret;
      lastDollar = name.lastIndexOf('$', lastDollar-1);
    }
    return null;
    }
 
 
  public static boolean isVisible(int modifiers, ResolvedType targetType, ResolvedType fromType) {
    //System.err.println("mod: " + modifiers + ", " + targetType + " and " + fromType);
   
    if (Modifier.isPublic(modifiers)) {
      return true;
    } else if (Modifier.isPrivate(modifiers)) {
      return targetType.getOutermostType().equals(fromType.getOutermostType());
    } else if (Modifier.isProtected(modifiers)) {
      return samePackage(targetType, fromType) || targetType.isAssignableFrom(fromType);
    } else { // package-visible
      return samePackage(targetType, fromType);
   
  }
 
  public static boolean hasBridgeModifier(int modifiers) {
    return (modifiers & Constants.ACC_BRIDGE)!=0;
  }

  private static boolean samePackage(
    ResolvedType targetType,
            ResolvedType fromType) {
    String p1 = targetType.getPackageName();
    String p2 = fromType.getPackageName();
    if (p1 == null) return p2 == null;
    if (p2 == null) return false;
    return p1.equals(p2);
  }

  /**
   * Checks if the generic type for 'this' and the generic type for 'other' are the same -
   * it can be passed raw or parameterized versions and will just compare the underlying
   * generic type.
   */
    private boolean genericTypeEquals(ResolvedType other) {
        ResolvedType rt = other;
        if (rt.isParameterizedType() || rt.isRawType()) rt.getGenericType();
        if (( (isParameterizedType() || isRawType()) && getGenericType().equals(rt)) ||
                (this.equals(other))) return true;
        return false;
    }
 
   /**
     * Look up the actual occurence of a particular type in the hierarchy for
     * 'this' type.  The input is going to be a generic type, and the caller
     * wants to know if it was used in its RAW or a PARAMETERIZED form in this
     * hierarchy.
     *
     * returns null if it can't be found.
     */
    public ResolvedType discoverActualOccurrenceOfTypeInHierarchy(ResolvedType lookingFor) {
            if (!lookingFor.isGenericType())
                    throw new BCException("assertion failed: method should only be called with generic type, but "+lookingFor+" is "+lookingFor.typeKind);

            if (this.equals(ResolvedType.OBJECT)) return null;

            if (genericTypeEquals(lookingFor)) return this;

            ResolvedType superT = getSuperclass();
            if (superT.genericTypeEquals(lookingFor)) return superT;

            ResolvedType[] superIs = getDeclaredInterfaces();
            for (int i = 0; i < superIs.length; i++) {
                    ResolvedType superI = superIs[i];
                    if (superI.genericTypeEquals(lookingFor)) return superI;
                    ResolvedType checkTheSuperI = superI.discoverActualOccurrenceOfTypeInHierarchy(lookingFor);
                    if (checkTheSuperI!=null) return checkTheSuperI;
            }
            return superT.discoverActualOccurrenceOfTypeInHierarchy(lookingFor);
    }

    /**
     * Called for all type mungers but only does something if they share type variables
     * with a generic type which they target.  When this happens this routine will check
     * for the target type in the target hierarchy and 'bind' any type parameters as
     * appropriate.  For example, for the ITD "List<T> I<T>.x" against a type like this:
     * "class A implements I<String>" this routine will return a parameterized form of
     * the ITD "List<String> I.x"
     */
    public ConcreteTypeMunger fillInAnyTypeParameters(ConcreteTypeMunger munger) {
      boolean debug = false;
    ResolvedMember member = munger.getSignature();
    if (munger.isTargetTypeParameterized()) {
      if (debug) System.err.println("Processing attempted parameterization of "+munger+" targetting type "+this);
      if (debug) System.err.println("  This type is "+this+"  ("+typeKind+")");
          // need to tailor this munger instance for the particular target...
          if (debug) System.err.println("  Signature that needs parameterizing: "+member);
          // Retrieve the generic type
          ResolvedType onType = world.resolve(member.getDeclaringType()).getGenericType();
          member.resolve(world); // Ensure all parts of the member are resolved
          if (debug) System.err.println("  Actual target ontype: "+onType+"  ("+onType.typeKind+")");
          // quickly find the targettype in the type hierarchy for this type (it will be either RAW or PARAMETERIZED)
          ResolvedType actualTarget = discoverActualOccurrenceOfTypeInHierarchy(onType);
          if (actualTarget==null)
                  throw new BCException("assertion failed: asked "+this+" for occurrence of "+onType+" in its hierarchy??");
 
          // only bind the tvars if its a parameterized type or the raw type (in which case they collapse to bounds) - don't do it for generic types ;)
          if (!actualTarget.isGenericType()) {
              if (debug) System.err.println("Occurrence in "+this+" is actually "+actualTarget+"  ("+actualTarget.typeKind+")");
              // parameterize the signature
              // ResolvedMember newOne = member.parameterizedWith(actualTarget.getTypeParameters(),onType,actualTarget.isParameterizedType());
          }
         //if (!actualTarget.isRawType())
        munger = munger.parameterizedFor(actualTarget);
          if (debug) System.err.println("New sig: "+munger.getSignature());
             
         
          if (debug) System.err.println("=====================================");
    }
    return munger;
    }

   
   
  public void addInterTypeMunger(ConcreteTypeMunger munger) {
    ResolvedMember sig = munger.getSignature();
    if (sig == null || munger.getMunger() == null ||
        munger.getMunger().getKind() == ResolvedTypeMunger.PrivilegedAccess)
    {
      interTypeMungers.add(munger);
      return;
    }
   
    ConcreteTypeMunger originalMunger = munger;
    // we will use the 'parameterized' ITD for all the comparisons but we say the original
        // one passed in actually matched as it will be added to the intertype member finder
    // for the target type.  It is possible we only want to do this if a generic type
    // is discovered and the tvar is collapsed to a bound?
    munger = fillInAnyTypeParameters(munger);
    sig = munger.getSignature(); // possibly changed when type parms filled in

   
    //System.err.println("add: " + munger + " to " + this.getClassName() + " with " + interTypeMungers);
    if (sig.getKind() == Member.METHOD) {
      if (!compareToExistingMembers(munger, getMethodsWithoutIterator(false,true) /*getMethods()*/)) return;
      if (this.isInterface()) {
        if (!compareToExistingMembers(munger,
            Arrays.asList(world.getCoreType(OBJECT).getDeclaredMethods()).iterator())) return;
      }
    } else if (sig.getKind() == Member.FIELD) {
      if (!compareToExistingMembers(munger, Arrays.asList(getDeclaredFields()).iterator())) return;
    } else {
      if (!compareToExistingMembers(munger, Arrays.asList(getDeclaredMethods()).iterator())) return;
    }

   
    // now compare to existingMungers
    for (Iterator i = interTypeMungers.iterator(); i.hasNext(); ) {
      ConcreteTypeMunger existingMunger = (ConcreteTypeMunger)i.next();
      if (conflictingSignature(existingMunger.getSignature(), munger.getSignature())) {
        //System.err.println("match " + munger + " with " + existingMunger);
        if (isVisible(munger.getSignature().getModifiers(),
              munger.getAspectType(), existingMunger.getAspectType()))
        {
          //System.err.println("    is visible");
          int c = compareMemberPrecedence(sig, existingMunger.getSignature());
          if (c == 0) {
            c = getWorld().compareByPrecedenceAndHierarchy(munger.getAspectType(), existingMunger.getAspectType());
          }
          //System.err.println("       compare: " + c);
          if (c < 0) {
            // the existing munger dominates the new munger
            checkLegalOverride(munger.getSignature(), existingMunger.getSignature());
            return;
          } else if (c > 0) {
            // the new munger dominates the existing one
            checkLegalOverride(existingMunger.getSignature(), munger.getSignature());
            i.remove();
            break;
          } else {
            interTypeConflictError(munger, existingMunger);
            interTypeConflictError(existingMunger, munger);
            return;
          }         
        }
      }
    }
    //System.err.println("adding: " + munger + " to " + this);
    // we are adding the parameterized form of the ITD to the list of
    // mungers.  Within it, the munger knows the original declared
    // signature for the ITD so it can be retrieved.
    interTypeMungers.add(munger);
  }
 
  private boolean compareToExistingMembers(ConcreteTypeMunger munger, List existingMembersList) {
    return compareToExistingMembers(munger,existingMembersList.iterator());
  }
 
  //??? returning too soon
  private boolean compareToExistingMembers(ConcreteTypeMunger munger, Iterator existingMembers) {
    ResolvedMember sig = munger.getSignature();
    while (existingMembers.hasNext()) {
     
      ResolvedMember existingMember = (ResolvedMember)existingMembers.next();
      // don't worry about clashing with bridge methods
      if (existingMember.isBridgeMethod()) continue;
      //System.err.println("Comparing munger: "+sig+" with member "+existingMember);
      if (conflictingSignature(existingMember, munger.getSignature())) {
        //System.err.println("conflict: existingMember=" + existingMember + "   typeMunger=" + munger);
        //System.err.println(munger.getSourceLocation() + ", " + munger.getSignature() + ", " + munger.getSignature().getSourceLocation());
       
        if (isVisible(existingMember.getModifiers(), this, munger.getAspectType())) {
          int c = compareMemberPrecedence(sig, existingMember);
          //System.err.println("   c: " + c);
          if (c < 0) {
            // existingMember dominates munger
            checkLegalOverride(munger.getSignature(), existingMember);
            return false;
          } else if (c > 0) {
            // munger dominates existingMember
            checkLegalOverride(existingMember, munger.getSignature());
            //interTypeMungers.add(munger); 
            //??? might need list of these overridden abstracts
            continue;
          } else {
            // bridge methods can differ solely in return type.
            // FIXME this whole method seems very hokey - unaware of covariance/varargs/bridging - it
            // could do with a rewrite !
            boolean sameReturnTypes = (existingMember.getReturnType().equals(sig.getReturnType()));
            if (sameReturnTypes)
              getWorld().getMessageHandler().handleMessage(
              MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT,munger.getAspectType().getName(),
                  existingMember),
              munger.getSourceLocation())
              );
          }
        } else if (isDuplicateMemberWithinTargetType(existingMember,this,sig)) {
              getWorld().getMessageHandler().handleMessage(
              MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT,munger.getAspectType().getName(),
                  existingMember),
              munger.getSourceLocation())
                    );
                    ;
        }
        //return;
      }
    }
    return true;
  }
 
  // we know that the member signature matches, but that the member in the target type is not visible to the aspect.
  // this may still be disallowed if it would result in two members within the same declaring type with the same
  // signature AND more than one of them is concrete AND they are both visible within the target type.
  private boolean isDuplicateMemberWithinTargetType(ResolvedMember existingMember, ResolvedType targetType,ResolvedMember itdMember) {
      if ( (existingMember.isAbstract() || itdMember.isAbstract())) return false;
      UnresolvedType declaringType = existingMember.getDeclaringType();
      if (!targetType.equals(declaringType)) return false;
      // now have to test that itdMember is visible from targetType
      if (itdMember.isPrivate()) return false;
      if (itdMember.isPublic()) return true;
      // must be in same package to be visible then...
      if (!targetType.getPackageName().equals(itdMember.getDeclaringType().getPackageName())) return false;
     
      // trying to put two members with the same signature into the exact same type..., and both visible in that type.
      return true;
  }
 
  /**
   * @return true if the override is legal
   * note: calling showMessage with two locations issues TWO messages, not ONE message
   * with an additional source location.
   */
  public boolean checkLegalOverride(ResolvedMember parent, ResolvedMember child) {
    //System.err.println("check: " + child.getDeclaringType() + " overrides " + parent.getDeclaringType());
    if (Modifier.isFinal(parent.getModifiers())) {
      world.showMessage(Message.ERROR,
          WeaverMessages.format(WeaverMessages.CANT_OVERRIDE_FINAL_MEMBER,parent),
          child.getSourceLocation(),null);
      return false;
    }
   
    boolean incompatibleReturnTypes = false;
    // In 1.5 mode, allow for covariance on return type
    if (world.isInJava5Mode() && parent.getKind()==Member.METHOD) {
     
      // Look at the generic types when doing this comparison
        ResolvedType rtParentReturnType = parent.getGenericReturnType().resolve(world);
      ResolvedType rtChildReturnType  = child.getGenericReturnType().resolve(world);
      incompatibleReturnTypes = !rtParentReturnType.isAssignableFrom(rtChildReturnType);
      if (incompatibleReturnTypes) {
        incompatibleReturnTypes = !rtParentReturnType.isAssignableFrom(rtChildReturnType);
      }
    } else {
      incompatibleReturnTypes =!parent.getReturnType().equals(child.getReturnType());
    }
   
    if (incompatibleReturnTypes) {
      world.showMessage(IMessage.ERROR,
          WeaverMessages.format(WeaverMessages.ITD_RETURN_TYPE_MISMATCH,parent,child),
          child.getSourceLocation(), parent.getSourceLocation());
      return false;
    }   
    if (parent.getKind() == Member.POINTCUT) {
      UnresolvedType[] pTypes = parent.getParameterTypes();
      UnresolvedType[] cTypes = child.getParameterTypes();
      if (!Arrays.equals(pTypes, cTypes)) {
        world.showMessage(IMessage.ERROR,
            WeaverMessages.format(WeaverMessages.ITD_PARAM_TYPE_MISMATCH,parent,child),
            child.getSourceLocation(), parent.getSourceLocation());
        return false;
      }
    }   
    //System.err.println("check: " + child.getModifiers() + " more visible " + parent.getModifiers());
    if (isMoreVisible(parent.getModifiers(), child.getModifiers())) {
      world.showMessage(IMessage.ERROR,
          WeaverMessages.format(WeaverMessages.ITD_VISIBILITY_REDUCTION,parent,child),
          child.getSourceLocation(), parent.getSourceLocation());
      return false;
    }
   
    // check declared exceptions
    ResolvedType[] childExceptions = world.resolve(child.getExceptions());
    ResolvedType[] parentExceptions = world.resolve(parent.getExceptions());
    ResolvedType runtimeException = world.resolve("java.lang.RuntimeException");
    ResolvedType error = world.resolve("java.lang.Error");
   
        outer:
        for (int i = 0, leni = childExceptions.length; i < leni; i++) {
      //System.err.println("checking: " + childExceptions[i]);
      if (runtimeException.isAssignableFrom(childExceptions[i])) continue;
      if (error.isAssignableFrom(childExceptions[i])) continue;
     
      for (int j = 0, lenj = parentExceptions.length; j < lenj; j++) {
        if (parentExceptions[j].isAssignableFrom(childExceptions[i])) continue outer;
      }
     
      // this message is now better handled my MethodVerifier in JDT core.
//      world.showMessage(IMessage.ERROR,
//          WeaverMessages.format(WeaverMessages.ITD_DOESNT_THROW,childExceptions[i].getName()),
//          child.getSourceLocation(), null);
           
      return false;
    }
    if (parent.isStatic() && !child.isStatic()) {
      world.showMessage(IMessage.ERROR,
          WeaverMessages.format(WeaverMessages.ITD_OVERRIDDEN_STATIC,child,parent),
          child.getSourceLocation(),null);
      return false;
    } else if (child.isStatic() && !parent.isStatic()) {
      world.showMessage(IMessage.ERROR,
          WeaverMessages.format(WeaverMessages.ITD_OVERIDDING_STATIC,child,parent),
          child.getSourceLocation(),null);
      return false;
    }
    return true;
   
  }
 
  private int compareMemberPrecedence(ResolvedMember m1, ResolvedMember m2) {
    //if (!m1.getReturnType().equals(m2.getReturnType())) return 0;
   
    // need to allow for the special case of 'clone' - which is like abstract but is
    // not marked abstract.  The code below this next line seems to make assumptions
    // about what will have gotten through the compiler based on the normal
    // java rules.  clone goes against these...
    if (m2.isProtected() && m2.getName().charAt(0)=='c') {
      UnresolvedType declaring = m2.getDeclaringType();
      if (declaring!=null) {
        if (declaring.getName().equals("java.lang.Object") && m2.getName().equals("clone")) return +1;
      }
    }

    if (Modifier.isAbstract(m1.getModifiers())) return -1;
    if (Modifier.isAbstract(m2.getModifiers())) return +1;
 
    if (m1.getDeclaringType().equals(m2.getDeclaringType())) return 0;
   
    ResolvedType t1 = m1.getDeclaringType().resolve(world);
    ResolvedType t2 = m2.getDeclaringType().resolve(world);
    if (t1.isAssignableFrom(t2)) {
      return -1;
    }
    if (t2.isAssignableFrom(t1)) {
      return +1;
    }
    return 0;
  }
 

  public static boolean isMoreVisible(int m1, int m2) {
    if (Modifier.isPrivate(m1)) return false;
    if (isPackage(m1)) return Modifier.isPrivate(m2);
    if (Modifier.isProtected(m1)) return /* private package */ (Modifier.isPrivate(m2) || isPackage(m2));
    if (Modifier.isPublic(m1)) return /* private package protected */ ! Modifier.isPublic(m2);
    throw new RuntimeException("bad modifier: " + m1);
  }

  private static boolean isPackage(int i) {
    return (0 == (i & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)));
  }

  private void interTypeConflictError(
    ConcreteTypeMunger m1,
            ConcreteTypeMunger m2) {
    //XXX this works only if we ignore separate compilation issues
    //XXX dual errors possible if (this instanceof BcelObjectType) return;
   
    //System.err.println("conflict at " + m2.getSourceLocation());
    getWorld().showMessage(IMessage.ERROR,
        WeaverMessages.format(WeaverMessages.ITD_CONFLICT,m1.getAspectType().getName(),
                  m2.getSignature(),m2.getAspectType().getName()),
            m2.getSourceLocation(), getSourceLocation());
  }
 
 
  public ResolvedMember lookupSyntheticMember(Member member) {
    //??? horribly inefficient
    //for (Iterator i =
    //System.err.println("lookup " + member + " in " + interTypeMungers);
    for (Iterator i = interTypeMungers.iterator(); i.hasNext(); ) {
      ConcreteTypeMunger m = (ConcreteTypeMunger)i.next();
      ResolvedMember ret = m.getMatchingSyntheticMember(member);
      if (ret != null) {
        //System.err.println("   found: " + ret);
        return ret;
      }
    }
   
//    if (this.getSuperclass() != ResolvedType.OBJECT && this.getSuperclass() != null) {
//      return getSuperclass().lookupSyntheticMember(member);
//    }
   
    return null;
  }

  public void clearInterTypeMungers() {
    if (isRawType()) getGenericType().clearInterTypeMungers();
    interTypeMungers = new ArrayList();
  }


  public boolean isTopmostImplementor(ResolvedType interfaceType) {
    if (isInterface()) return false;
    if (!interfaceType.isAssignableFrom(this,true)) return false;
    // check that I'm truly the topmost implementor
    if (this.getSuperclass().isMissing()) return true; // we don't know anything about supertype, and it can't be exposed to weaver
    if (interfaceType.isAssignableFrom(this.getSuperclass(),true)) {
      return false;
    }
    return true;
  }
 
  public ResolvedType getTopmostImplementor(ResolvedType interfaceType) {
    if (isInterface()) return null;
    if (!interfaceType.isAssignableFrom(this)) return null;
    // Check if my super class is an implementor?
    ResolvedType higherType  = this.getSuperclass().getTopmostImplementor(interfaceType);
    if (higherType!=null) return higherType;
    return this;
  }
 
  private ResolvedType findHigher(ResolvedType other) {
   if (this == other) return this;
     for(Iterator i = other.getDirectSupertypes(); i.hasNext(); ) {
       ResolvedType rtx = (ResolvedType)i.next();
       boolean b = this.isAssignableFrom(rtx);
       if (b) return rtx;
     }      
     return null;
  }
 
  public List getExposedPointcuts() {
    List ret = new ArrayList();
    if (getSuperclass() != null) ret.addAll(getSuperclass().getExposedPointcuts());
   
    for (Iterator i = Arrays.asList(getDeclaredInterfaces()).iterator(); i.hasNext(); ) {
      ResolvedType t = (ResolvedType)i.next();
      addPointcutsResolvingConflicts(ret, Arrays.asList(t.getDeclaredPointcuts()), false);
    }
    addPointcutsResolvingConflicts(ret, Arrays.asList(getDeclaredPointcuts()), true);
    for (Iterator i = ret.iterator(); i.hasNext(); ) {
      ResolvedPointcutDefinition inherited = (ResolvedPointcutDefinition)i.next();
//      System.err.println("looking at: " + inherited + " in " + this);
//      System.err.println("            " + inherited.isAbstract() + " in " + this.isAbstract());
      if (inherited.isAbstract()) {
        if (!this.isAbstract()) {
          getWorld().showMessage(IMessage.ERROR,
              WeaverMessages.format(WeaverMessages.POINCUT_NOT_CONCRETE,inherited,this.getName()),
              inherited.getSourceLocation(), this.getSourceLocation());
        }
      }
    }   
   
   
    return ret;
  }
 
  private void addPointcutsResolvingConflicts(List acc, List added, boolean isOverriding) {
    for (Iterator i = added.iterator(); i.hasNext();) {
      ResolvedPointcutDefinition toAdd =
        (ResolvedPointcutDefinition) i.next();
        //System.err.println("adding: " + toAdd);
      for (Iterator j = acc.iterator(); j.hasNext();) {
        ResolvedPointcutDefinition existing =
          (ResolvedPointcutDefinition) j.next();
        if (existing == toAdd) continue;
        if (!isVisible(existing.getModifiers(),
          existing.getDeclaringType().resolve(getWorld()),
          this)) {
          continue;
        }
        if (conflictingSignature(existing, toAdd)) {
          if (isOverriding) {
            checkLegalOverride(existing, toAdd);
            j.remove();
          } else {
            getWorld().showMessage(
              IMessage.ERROR,
              WeaverMessages.format(WeaverMessages.CONFLICTING_INHERITED_POINTCUTS,this.getName() + toAdd.getSignature()),
              existing.getSourceLocation(),
              toAdd.getSourceLocation());
            j.remove();
          }
        }
      }
      acc.add(toAdd);
    }
  }
 
    public ISourceLocation getSourceLocation() {
        return null;
    }

    public boolean isExposedToWeaver() {
        return false;
    }

  public WeaverStateInfo getWeaverState() {
    return null;
  }
 
  /**
   * Overridden by ReferenceType to return a sensible answer for parameterized and raw types.
     *
   * @return
   */
  public ResolvedType getGenericType() {
    if (!(isParameterizedType() || isRawType()))
      throw new BCException("The type "+getBaseName()+" is not parameterized or raw - it has no generic type");
    return null;
  }
 
  public ResolvedType parameterizedWith(UnresolvedType[] typeParameters) {
    if (!(isGenericType() || isParameterizedType())) return this;
    return TypeFactory.createParameterizedType(this.getGenericType(), typeParameters, getWorld());
  }
 
  /**
   * Iff I am a parameterized type, and any of my parameters are type variable
   * references, return a version with those type parameters replaced in accordance
   * with the passed bindings.
   */
  public UnresolvedType parameterize(Map typeBindings) {
      if (!isParameterizedType()) throw new IllegalStateException("Can't parameterize a type that is not a parameterized type");
      boolean workToDo = false;
      for (int i = 0; i < typeParameters.length; i++) {
      if (typeParameters[i].isTypeVariableReference()) {
        workToDo = true;
      }
    }
      if (!workToDo) {
        return this;
      } else {
        UnresolvedType[] newTypeParams = new UnresolvedType[typeParameters.length];
        for (int i = 0; i < newTypeParams.length; i++) {
        newTypeParams[i] = typeParameters[i];
        if (newTypeParams[i].isTypeVariableReference()) {
          TypeVariableReferenceType tvrt = (TypeVariableReferenceType) newTypeParams[i];
          UnresolvedType binding = (UnresolvedType) typeBindings.get(tvrt.getTypeVariable().getName());
          if (binding != null) newTypeParams[i] = binding;
        }
      }
        return TypeFactory.createParameterizedType(getGenericType(), newTypeParams, getWorld());
      }
    }
 
  public boolean hasParameterizedSuperType() {
    getParameterizedSuperTypes();
    return parameterizedSuperTypes.length > 0;
  }
 
  public boolean hasGenericSuperType() {
    ResolvedType[] superTypes = getDeclaredInterfaces();
    for (int i = 0; i < superTypes.length; i++) {
      if (superTypes[i].isGenericType()) return true;
    }
    return false;
  }
 
  private ResolvedType[] parameterizedSuperTypes = null;
  /**
   * Similar to the above method, but accumulates the super types
     *
   * @return
   */
  public ResolvedType[] getParameterizedSuperTypes() {
    if (parameterizedSuperTypes != null) return parameterizedSuperTypes;
    List accumulatedTypes = new ArrayList();
    accumulateParameterizedSuperTypes(this,accumulatedTypes);
    ResolvedType[] ret = new ResolvedType[accumulatedTypes.size()];
    parameterizedSuperTypes = (ResolvedType[]) accumulatedTypes.toArray(ret);
    return parameterizedSuperTypes;
  }
 
  private void accumulateParameterizedSuperTypes(ResolvedType forType, List parameterizedTypeList) {
    if (forType.isParameterizedType()) {
      parameterizedTypeList.add(forType);
    }
    if (forType.getSuperclass() != null) {
      accumulateParameterizedSuperTypes(forType.getSuperclass(), parameterizedTypeList);
    }
    ResolvedType[] interfaces = forType.getDeclaredInterfaces();
    for (int i = 0; i < interfaces.length; i++) {
      accumulateParameterizedSuperTypes(interfaces[i], parameterizedTypeList);
    }
  }

  /**
   * Types may have pointcuts just as they have methods and fields.
   */
  public ResolvedPointcutDefinition findPointcut(String name, World world) {
      throw new UnsupportedOperationException("Not yet implemenented");
  }
 
  /**
   * @return true if assignable to java.lang.Exception
   */
  public boolean isException() {
    return (world.getCoreType(UnresolvedType.JAVA_LANG_EXCEPTION).isAssignableFrom(this));
  }
 
  /**
   * @return true if it is an exception and it is a checked one, false otherwise.
   */
  public boolean isCheckedException() {
    if (!isException()) return false;
    if (world.getCoreType(UnresolvedType.RUNTIME_EXCEPTION).isAssignableFrom(this)) return false;
    return true;
  }

  /**
   * Determines if variables of this type could be assigned values of another
   * with lots of help. 
   * java.lang.Object is convertable from all types.
   * A primitive type is convertable from X iff it's assignable from X.
   * A reference type is convertable from X iff it's coerceable from X.
   * In other words, X isConvertableFrom Y iff the compiler thinks that _some_ value of Y
   * could be assignable to a variable of type X without loss of precision.
   *
   * @param other the other type
   * @param world the {@link World} in which the possible assignment should be checked.
   * @return true iff variables of this type could be assigned values of other with possible conversion
   */
     public final boolean isConvertableFrom(ResolvedType other) {

//       // version from TypeX
//       if (this.equals(OBJECT)) return true;
//       if (this.isPrimitiveType() || other.isPrimitiveType()) return this.isAssignableFrom(other);
//       return this.isCoerceableFrom(other);
//      
      
       // version from ResolvedTypeX
       if (this.equals(OBJECT)) return true;
       if (world.isInJava5Mode()) {
          if (this.isPrimitiveType()^other.isPrimitiveType()) { // If one is primitive and the other isnt
            if (validBoxing.contains(this.getSignature()+other.getSignature())) return true;
          }
       }
       if (this.isPrimitiveType() || other.isPrimitiveType()) return this.isAssignableFrom(other);
       return this.isCoerceableFrom(other);
   }

  /**
   * Determines if the variables of this type could be assigned values
   * of another type without casting.  This still allows for assignment conversion
   * as per JLS 2ed 5.2.  For object types, this means supertypeOrEqual(THIS, OTHER).
   *
   * @param other the other type
   * @param world the {@link World} in which the possible assignment should be checked.
   * @return true iff variables of this type could be assigned values of other without casting
     * @throws NullPointerException if other is null
   */
  public abstract boolean isAssignableFrom(ResolvedType other);
 
  public abstract boolean isAssignableFrom(ResolvedType other, boolean allowMissing);

  /**
   * Determines if values of another type could possibly be cast to
   * this type.  The rules followed are from JLS 2ed 5.5, "Casting Conversion".
     * <p/>
   * <p> This method should be commutative, i.e., for all UnresolvedType a, b and all World w:
     * <p/>
   * <blockquote><pre>
   *    a.isCoerceableFrom(b, w) == b.isCoerceableFrom(a, w)
   * </pre></blockquote>
   *
   * @param other the other type
   * @param world the {@link World} in which the possible coersion should be checked.
   * @return true iff values of other could possibly be cast to this type.
     * @throws NullPointerException if other is null.
   */
  public abstract boolean isCoerceableFrom(ResolvedType other);
 
  public boolean needsNoConversionFrom(ResolvedType o) {
      return isAssignableFrom(o);
  }
 
  /**
     * Implemented by ReferenceTypes
     */
  public String getSignatureForAttribute() {
    throw new RuntimeException("Cannot ask this type "+this+" for a generic sig attribute");
  }
 
  private FuzzyBoolean parameterizedWithAMemberTypeVariable = FuzzyBoolean.MAYBE;
 
  /**
   * return true if the parameterization of this type includes a member type variable.  Member
   * type variables occur in generic methods/ctors.
   */
  public boolean isParameterizedWithAMemberTypeVariable() {
    // MAYBE means we haven't worked it out yet...
    if (parameterizedWithAMemberTypeVariable==FuzzyBoolean.MAYBE) {
     
      // if there are no type parameters then we cant be...
      if (typeParameters==null || typeParameters.length==0) {
        parameterizedWithAMemberTypeVariable = FuzzyBoolean.NO;
        return false;
      }
     
      for (int i = 0; i < typeParameters.length; i++) {
        UnresolvedType aType = (ResolvedType)typeParameters[i];
        if (aType.isTypeVariableReference()  &&
        // assume the worst - if its definetly not a type declared one, it could be anything
            ((TypeVariableReference)aType).getTypeVariable().getDeclaringElementKind()!=TypeVariable.TYPE) {
          parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
          return true;
        }
        if (aType.isParameterizedType()) {
          boolean b = aType.isParameterizedWithAMemberTypeVariable();
          if (b) {
            parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
            return true;
          }
        }
        if (aType.isGenericWildcard()) {
          if (aType.isExtends()) {
            boolean b = false;
            UnresolvedType upperBound = aType.getUpperBound();
            if (upperBound.isParameterizedType()) {
              b = upperBound.isParameterizedWithAMemberTypeVariable();
            } else if (upperBound.isTypeVariableReference() && ((TypeVariableReference)upperBound).getTypeVariable().getDeclaringElementKind()==TypeVariable.METHOD) {
              b = true;
            }
            if (b) {
              parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
              return true;
            }
            // FIXME asc need to check additional interface bounds
          }
          if (aType.isSuper()) {
            boolean b = false;
            UnresolvedType lowerBound = aType.getLowerBound();
            if (lowerBound.isParameterizedType()) {
              b = lowerBound.isParameterizedWithAMemberTypeVariable();
            } else if (lowerBound.isTypeVariableReference() && ((TypeVariableReference)lowerBound).getTypeVariable().getDeclaringElementKind()==TypeVariable.METHOD) {
              b = true;
            }
            if (b) {
              parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
              return true;
            }
          }
        }
      }
      parameterizedWithAMemberTypeVariable=FuzzyBoolean.NO;
    }
    return parameterizedWithAMemberTypeVariable.alwaysTrue();
  }

  protected boolean ajMembersNeedParameterization() {
    if (isParameterizedType()) return true;
    if (getSuperclass() != null) return ((ReferenceType)getSuperclass()).ajMembersNeedParameterization();
    return false;
  }

  protected Map getAjMemberParameterizationMap() {
    Map myMap = getMemberParameterizationMap();
    if (myMap.size() == 0) {
      // might extend a parameterized aspect that we also need to consider...
      if (getSuperclass() != null) return ((ReferenceType)getSuperclass()).getAjMemberParameterizationMap();
    }
    return myMap;
  }
     
}
TOP

Related Classes of org.aspectj.weaver.ResolvedType$Array

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.