Package org.aspectj.weaver.bcel

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

/* *******************************************************************
* 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.apache.bcel.classfile.Signature;
import org.aspectj.apache.bcel.classfile.Signature.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;

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

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

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

  private static TypeVariable formalTypeParameter2TypeVariable(
      Signature.FormalTypeParameter aFormalTypeParameter,
      Signature.FormalTypeParameter[] typeParams,
      World world,
      Map 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(
      Signature.TypeArgument aTypeArgument,
      Signature.FormalTypeParameter[] typeParams,
      World world,
      Map inProgressTypeVariableResolutions)
  throws GenericSignatureFormatException
  {
    if (aTypeArgument.isWildcard) return UnresolvedType.SOMETHING.resolve(world);
    if (aTypeArgument.isMinus) {
      UnresolvedType bound = fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams,world,inProgressTypeVariableResolutions);
      ReferenceType rBound = (ReferenceType) world.resolve(bound);
      return new BoundedReferenceType(rBound,false,world);
    } else if (aTypeArgument.isPlus) {
      UnresolvedType bound = fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams,world,inProgressTypeVariableResolutions);
      ReferenceType rBound = (ReferenceType) world.resolve(bound);
      return new BoundedReferenceType(rBound,true,world);
    } else {
      return fieldTypeSignature2TypeX(aTypeArgument.signature,typeParams,world,inProgressTypeVariableResolutions);
    }
  }
 

  public static ResolvedType typeSignature2TypeX(
      Signature.TypeSignature aTypeSig,
      Signature.FormalTypeParameter[] typeParams,
      World world)
  throws GenericSignatureFormatException
  {
    Map typeMap = new HashMap();
    ResolvedType ret = typeSignature2TypeX(aTypeSig,typeParams,world,typeMap);
    fixUpCircularDependencies(ret, typeMap);
    return ret;
  }
 
  private static ResolvedType typeSignature2TypeX(
      Signature.TypeSignature aTypeSig,
      Signature.FormalTypeParameter[] typeParams,
      World world,
      Map inProgressTypeVariableResolutions)
  throws GenericSignatureFormatException
  {
    if (aTypeSig.isBaseType()) {
      return world.resolve(UnresolvedType.forSignature(((Signature.BaseTypeSignature)aTypeSig).toString()));
    } else {
      return fieldTypeSignature2TypeX((Signature.FieldTypeSignature)aTypeSig,typeParams,world,inProgressTypeVariableResolutions);
    }
  }
 
  private static ResolvedType typeVariableSignature2TypeX(
      Signature.TypeVariableSignature aTypeVarSig,
      Signature.FormalTypeParameter[] typeParams,
      World world,
      Map inProgressTypeVariableResolutions)
  throws GenericSignatureFormatException
  {
    Signature.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 (ResolvedType) inProgressTypeVariableResolutions.get(typeVarBounds);
    }
    inProgressTypeVariableResolutions.put(typeVarBounds,new FTPHolder(typeVarBounds,world));
    ResolvedType ret = new TypeVariableReferenceType(
        formalTypeParameter2TypeVariable(typeVarBounds,typeParams,world,inProgressTypeVariableResolutions),
        world);
    inProgressTypeVariableResolutions.put(typeVarBounds,ret);
    return ret;
  }
 
  private static void fixUpCircularDependencies(ResolvedType aTypeX, Map typeVariableResolutions) {
    if (! (aTypeX instanceof ReferenceType)) return;
   
    ReferenceType rt = (ReferenceType) aTypeX;
    TypeVariable[] typeVars = rt.getTypeVariables();
    for (int i = 0; i < typeVars.length; i++) {
      if (typeVars[i].getUpperBound() instanceof FTPHolder) {
        Signature.FormalTypeParameter key = ((FTPHolder) typeVars[i].getUpperBound()).ftpToBeSubstituted;
        typeVars[i].setUpperBound((UnresolvedType)typeVariableResolutions.get(key));
      }
    }
  }
 
  private static class FTPHolder extends ReferenceType {
    public Signature.FormalTypeParameter ftpToBeSubstituted;
    public FTPHolder(Signature.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 static class GenericSignatureFormatException extends Exception {
    public GenericSignatureFormatException(String explanation) {
      super(explanation);
    }
  }
}
TOP

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

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.