/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.ir.transform.util;
import gw.internal.gosu.compiler.FunctionClassUtil;
import gw.internal.gosu.ir.nodes.GosuClassIRType;
import gw.internal.gosu.ir.nodes.JavaClassIRType;
import gw.internal.gosu.ir.transform.AbstractElementTransformer;
import gw.internal.gosu.parser.IGosuClassInternal;
import gw.internal.gosu.parser.MetaType;
import gw.internal.gosu.parser.TypeLord;
import gw.internal.gosu.parser.TypeVariableType;
import gw.lang.ir.IRType;
import gw.lang.reflect.IFunctionType;
import gw.lang.reflect.IMetaType;
import gw.lang.reflect.IType;
import gw.lang.reflect.gs.IGosuClass;
import gw.lang.reflect.java.IJavaBackedType;
import gw.lang.reflect.java.IJavaClassInfo;
import gw.lang.reflect.java.IJavaType;
import gw.util.GosuExceptionUtil;
import java.util.ArrayList;
import java.util.List;
public class IRTypeResolver {
public static IRType getDescriptor( IType type)
{
return getDescriptor( type, false );
}
public static IRType getDescriptor( IType type, boolean getConcreteTypeForMetaType )
{
type = type instanceof IMetaType ? type : TypeLord.getPureGenericType( type );
if( type instanceof IJavaType ) // handles primitives too
{
try
{
return JavaClassIRType.get( ((IJavaType)type).getBackingClassInfo() );
}
catch( Exception e )
{
throw GosuExceptionUtil.forceThrow( e, type.getName() );
}
}
else if( type instanceof IGosuClassInternal )
{
if( IGosuClass.ProxyUtil.isProxy( type ) )
{
return getDescriptor( IGosuClass.ProxyUtil.getProxiedType( type ), getConcreteTypeForMetaType );
}
else
{
return GosuClassIRType.get( type );
}
}
else if( getJavaBackedClass( type ) != null )
{
return getDescriptor( getJavaBackedClass( type ) );
}
else if( type.isArray() )
{
// Array types NEVER use concrete types for meta types
return getDescriptor(type.getComponentType(), false).getArrayType();
}
else if( type instanceof TypeVariableType)
{
return getDescriptor( ((TypeVariableType)type).getBoundingType(), getConcreteTypeForMetaType );
}
else if( type instanceof IFunctionType)
{
return getDescriptor( FunctionClassUtil.getFunctionInterfaceForArity( ((IFunctionType)type).getParameterTypes().length ) );
}
else if( type instanceof MetaType)
{
if (getConcreteTypeForMetaType) {
return getConcreteIRTypeForMetaType((MetaType) type);
} else {
return getDescriptor( IType.class );
}
}
else
{
return getDescriptor( Object.class );
}
}
public static IRType getDescriptor( Class cls )
{
return JavaClassIRType.get( cls );
}
public static IRType getDescriptor( IJavaClassInfo cls )
{
return JavaClassIRType.get( cls );
}
public static IRType getConcreteIRTypeForMetaType( MetaType metaType ) {
if( MetaType.DEFAULT_TYPE_TYPE.get().getName().equals( metaType.getName() ) ||
MetaType.ROOT_TYPE_TYPE.get().getName().equals( metaType.getName() ) )
{
return getDescriptor( IType.class );
}
IType underlyingType = metaType.getType();
if( AbstractElementTransformer.isBytecodeType( underlyingType ) )
{
return getDescriptor( underlyingType.getClass() );
}
else
{
return getDescriptor( IType.class );
}
}
public static IJavaClassInfo getJavaBackedClass( IType arg )
{
if( arg instanceof IJavaBackedType)
{
IJavaClassInfo cls = ((IJavaBackedType)arg).getBackingClassInfo();
if( cls == null )
{
throw new IllegalStateException( "Type: " + arg.getName() + " returned null Class from IJavaBackedType.getBackingClassInfo()" );
}
return cls;
}
return null;
}
public static List<IRType> getDescriptors( IJavaClassInfo[] classes )
{
List<IRType> irTypes = new ArrayList<IRType>( classes.length );
for (IJavaClassInfo parameterClass : classes) {
irTypes.add( getDescriptor( parameterClass ) );
}
return irTypes;
}
public static List<IRType> getDescriptors( Class[] classes )
{
List<IRType> irTypes = new ArrayList<IRType>( classes.length );
for (Class parameterClass : classes) {
irTypes.add( getDescriptor( parameterClass ) );
}
return irTypes;
}
public static List<IRType> getDescriptors( List<IType> types )
{
List<IRType> irTypes = new ArrayList<IRType>( types.size() );
for (IType type : types) {
irTypes.add( getDescriptor( type ) );
}
return irTypes;
}
}