Package org.aspectj.weaver.bcel

Source Code of org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter$FTPHolder

/* *******************************************************************
* Copyright (c) 2005 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://eclipse.org/legal/epl-v10.html
* Contributors:
*   Adrian Colyer      Initial implementation
* ******************************************************************/
package org.aspectj.weaver.bcel;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.util.GenericSignature;
import org.aspectj.util.GenericSignature.SimpleClassTypeSignature;
import org.aspectj.weaver.BoundedReferenceType;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.TypeFactory;
import org.aspectj.weaver.TypeVariable;
import org.aspectj.weaver.TypeVariableReferenceType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.tools.Trace;
import org.aspectj.weaver.tools.TraceFactory;

/**
* A utility class that assists in unpacking constituent parts of generic signature attributes and returning their equivalents in
* UnresolvedType world.
*/
public class BcelGenericSignatureToTypeXConverter {

  private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelGenericSignatureToTypeXConverter.class);

  public static ResolvedType classTypeSignature2TypeX(GenericSignature.ClassTypeSignature aClassTypeSignature,
      GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
    Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<GenericSignature.FormalTypeParameter, ReferenceType>();
    ResolvedType ret = classTypeSignature2TypeX(aClassTypeSignature, typeParams, world, typeMap);
    fixUpCircularDependencies(ret, typeMap);
    return ret;
  }

  private static ResolvedType classTypeSignature2TypeX(GenericSignature.ClassTypeSignature aClassTypeSignature,
      GenericSignature.FormalTypeParameter[] typeParams, World world,
      Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
      throws GenericSignatureFormatException {
    // class type sig consists of an outer type, and zero or more nested types
    // the fully qualified name is outer-type.nested-type1.nested-type2....
    // each type in the hierarchy may have type arguments

    // first build the 'raw type' signature
    StringBuffer sig = new StringBuffer();
    sig.append(aClassTypeSignature.outerType.identifier.replace(';', ' ').trim());
    for (int i = 0; i < aClassTypeSignature.nestedTypes.length; i++) {
      sig.append("$");
      sig.append(aClassTypeSignature.nestedTypes[i].identifier.replace(';', ' ').trim());
    }
    sig.append(";");

    // now look for any type parameters.
    // I *think* we only need to worry about the 'right-most' type...
    SimpleClassTypeSignature innerType = aClassTypeSignature.outerType;
    if (aClassTypeSignature.nestedTypes.length > 0) {
      innerType = aClassTypeSignature.nestedTypes[aClassTypeSignature.nestedTypes.length - 1];
    }
    if (innerType.typeArguments.length > 0) {
      // we have to create a parameterized type
      // type arguments may be array types, class types, or typevariable types
      ResolvedType theBaseType = UnresolvedType.forSignature(sig.toString()).resolve(world);

      // Sometimes we may find that when the code is being load-time woven that the types have changed.
      // Perhaps an old form of a library jar is being used - this can mean we discover right here
      // that a type is not parameterizable (is that a word?). I think in these cases it is ok to
      // just return with what we know (the base type). (see pr152848)
      if (!(theBaseType.isGenericType() || theBaseType.isRawType())) {
        if (trace.isTraceEnabled()) {
          trace.event("classTypeSignature2TypeX: this type is not a generic type:", null, new Object[] { theBaseType });
        }
        return theBaseType;
      }

      ResolvedType[] typeArgumentTypes = new ResolvedType[innerType.typeArguments.length];
      for (int i = 0; i < typeArgumentTypes.length; i++) {
        typeArgumentTypes[i] = typeArgument2TypeX(innerType.typeArguments[i], typeParams, world,
            inProgressTypeVariableResolutions);
      }
      return TypeFactory.createParameterizedType(theBaseType, typeArgumentTypes, world);

      // world.resolve(UnresolvedType.forParameterizedTypes(
      // UnresolvedType.forSignature(sig.toString()).resolve(world),
      // typeArgumentTypes));
    } else {
      // we have a non-parameterized type
      return world.resolve(UnresolvedType.forSignature(sig.toString()));
    }
  }

  public static ResolvedType fieldTypeSignature2TypeX(GenericSignature.FieldTypeSignature aFieldTypeSignature,
      GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
    Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<GenericSignature.FormalTypeParameter, ReferenceType>();
    ResolvedType ret = fieldTypeSignature2TypeX(aFieldTypeSignature, typeParams, world, typeMap);
    fixUpCircularDependencies(ret, typeMap);
    return ret;
  }

  private static ResolvedType fieldTypeSignature2TypeX(GenericSignature.FieldTypeSignature aFieldTypeSignature,
      GenericSignature.FormalTypeParameter[] typeParams, World world,
      Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
      throws GenericSignatureFormatException {
    if (aFieldTypeSignature.isClassTypeSignature()) {
      return classTypeSignature2TypeX((GenericSignature.ClassTypeSignature) aFieldTypeSignature, typeParams, world,
          inProgressTypeVariableResolutions);
    } else if (aFieldTypeSignature.isArrayTypeSignature()) {
      int dims = 0;
      GenericSignature.TypeSignature ats = aFieldTypeSignature;
      while (ats instanceof GenericSignature.ArrayTypeSignature) {
        dims++;
        ats = ((GenericSignature.ArrayTypeSignature) ats).typeSig;
      }
      return world.resolve(UnresolvedType.makeArray(
          typeSignature2TypeX(ats, typeParams, world, inProgressTypeVariableResolutions), dims));
    } else if (aFieldTypeSignature.isTypeVariableSignature()) {
      ResolvedType rtx = typeVariableSignature2TypeX((GenericSignature.TypeVariableSignature) aFieldTypeSignature,
          typeParams, world, inProgressTypeVariableResolutions);
      return rtx;
    } else {
      throw new GenericSignatureFormatException("Cant understand field type signature: " + aFieldTypeSignature);
    }
  }

  public static TypeVariable formalTypeParameter2TypeVariable(GenericSignature.FormalTypeParameter aFormalTypeParameter,
      GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
    Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<GenericSignature.FormalTypeParameter, ReferenceType>();
    return formalTypeParameter2TypeVariable(aFormalTypeParameter, typeParams, world, typeMap);
  }

  private static TypeVariable formalTypeParameter2TypeVariable(GenericSignature.FormalTypeParameter aFormalTypeParameter,
      GenericSignature.FormalTypeParameter[] typeParams, World world,
      Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
      throws GenericSignatureFormatException {
    UnresolvedType upperBound = fieldTypeSignature2TypeX(aFormalTypeParameter.classBound, typeParams, world,
        inProgressTypeVariableResolutions);
    UnresolvedType[] ifBounds = new UnresolvedType[aFormalTypeParameter.interfaceBounds.length];
    for (int i = 0; i < ifBounds.length; i++) {
      ifBounds[i] = fieldTypeSignature2TypeX(aFormalTypeParameter.interfaceBounds[i], typeParams, world,
          inProgressTypeVariableResolutions);
    }
    return new TypeVariable(aFormalTypeParameter.identifier, upperBound, ifBounds);
  }

  private static ResolvedType typeArgument2TypeX(GenericSignature.TypeArgument aTypeArgument,
      GenericSignature.FormalTypeParameter[] typeParams, World world,
      Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
      throws GenericSignatureFormatException {
    if (aTypeArgument.isWildcard) {
      return UnresolvedType.SOMETHING.resolve(world);
    }
    if (aTypeArgument.isMinus) {
      UnresolvedType bound = fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world,
          inProgressTypeVariableResolutions);
      ResolvedType resolvedBound = world.resolve(bound);
      if (resolvedBound.isMissing()) {
        world.getLint().cantFindType.signal("Unable to find type (for bound): " + resolvedBound.getName(), null);
        resolvedBound = world.resolve(UnresolvedType.OBJECT);
      }
      ReferenceType rBound = (ReferenceType) resolvedBound;
      return new BoundedReferenceType(rBound, false, world);
    } else if (aTypeArgument.isPlus) {
      UnresolvedType bound = fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world,
          inProgressTypeVariableResolutions);
      ResolvedType resolvedBound = world.resolve(bound);
      if (resolvedBound.isMissing()) {
        world.getLint().cantFindType.signal("Unable to find type (for bound): " + resolvedBound.getName(), null);
        resolvedBound = world.resolve(UnresolvedType.OBJECT);
      }
      ReferenceType rBound = (ReferenceType) resolvedBound;
      return new BoundedReferenceType(rBound, true, world);
    } else {
      return fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world, inProgressTypeVariableResolutions);
    }
  }

  public static ResolvedType typeSignature2TypeX(GenericSignature.TypeSignature aTypeSig,
      GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
    Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<GenericSignature.FormalTypeParameter, ReferenceType>();
    ResolvedType ret = typeSignature2TypeX(aTypeSig, typeParams, world, typeMap);
    fixUpCircularDependencies(ret, typeMap);
    return ret;
  }

  private static ResolvedType typeSignature2TypeX(GenericSignature.TypeSignature aTypeSig,
      GenericSignature.FormalTypeParameter[] typeParams, World world,
      Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
      throws GenericSignatureFormatException {
    if (aTypeSig.isBaseType()) {
      return world.resolve(UnresolvedType.forSignature(((GenericSignature.BaseTypeSignature) aTypeSig).toString()));
    } else {
      return fieldTypeSignature2TypeX((GenericSignature.FieldTypeSignature) aTypeSig, typeParams, world,
          inProgressTypeVariableResolutions);
    }
  }

  private static ResolvedType typeVariableSignature2TypeX(GenericSignature.TypeVariableSignature aTypeVarSig,
      GenericSignature.FormalTypeParameter[] typeParams, World world,
      Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
      throws GenericSignatureFormatException {
    GenericSignature.FormalTypeParameter typeVarBounds = null;
    for (int i = 0; i < typeParams.length; i++) {
      if (typeParams[i].identifier.equals(aTypeVarSig.typeVariableName)) {
        typeVarBounds = typeParams[i];
        break;
      }
    }
    if (typeVarBounds == null) {
      // blowing up here breaks the situation with ITDs where the type variable is mentioned in the
      // declaring type and used somewhere in the signature. Temporary change to allow it to return just a
      // 'dumb' typevariablereference.
      return new TypeVariableReferenceType(new TypeVariable(aTypeVarSig.typeVariableName), world);
      // throw new GenericSignatureFormatException("Undeclared type variable in signature: " + aTypeVarSig.typeVariableName);
    }
    if (inProgressTypeVariableResolutions.containsKey(typeVarBounds)) {
      return inProgressTypeVariableResolutions.get(typeVarBounds);
    }
    inProgressTypeVariableResolutions.put(typeVarBounds, new FTPHolder(typeVarBounds, world));
    ReferenceType ret = new TypeVariableReferenceType(formalTypeParameter2TypeVariable(typeVarBounds, typeParams, world,
        inProgressTypeVariableResolutions), world);
    inProgressTypeVariableResolutions.put(typeVarBounds, ret);
    return ret;
  }

  private static void fixUpCircularDependencies(ResolvedType aTypeX,
      Map<GenericSignature.FormalTypeParameter, ReferenceType> typeVariableResolutions) {
    if (!(aTypeX instanceof ReferenceType)) {
      return;
    }

    ReferenceType rt = (ReferenceType) aTypeX;
    TypeVariable[] typeVars = rt.getTypeVariables();
    if (typeVars != null) {
      for (int i = 0; i < typeVars.length; i++) {
        if (typeVars[i].getUpperBound() instanceof FTPHolder) {
          GenericSignature.FormalTypeParameter key = ((FTPHolder) typeVars[i].getUpperBound()).ftpToBeSubstituted;
          typeVars[i].setUpperBound(typeVariableResolutions.get(key));
        }
      }
    }
  }

  private static class FTPHolder extends ReferenceType {
    public GenericSignature.FormalTypeParameter ftpToBeSubstituted;

    public FTPHolder(GenericSignature.FormalTypeParameter ftp, World world) {
      super("Ljava/lang/Object;", world);
      this.ftpToBeSubstituted = ftp;
    }

    public String toString() {
      return "placeholder for TypeVariable of " + ftpToBeSubstituted.toString();
    }

    public ResolvedType resolve(World world) {
      return this;
    }

    public boolean isCacheable() {
      return false;
    }
  }

  public static class GenericSignatureFormatException extends Exception {
    public GenericSignatureFormatException(String explanation) {
      super(explanation);
    }
  }
}
TOP

Related Classes of org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter$FTPHolder

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.