/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser;
import gw.lang.parser.IExpression;
import gw.lang.parser.exceptions.ParseResultsException;
import gw.lang.reflect.AbstractType;
import gw.lang.reflect.DefaultNonLoadableArrayType;
import gw.lang.reflect.IConstructorType;
import gw.lang.reflect.IErrorType;
import gw.lang.reflect.IFunctionType;
import gw.lang.reflect.IType;
import gw.lang.reflect.ITypeInfo;
import gw.lang.reflect.ITypeLoader;
import gw.lang.reflect.Modifier;
import gw.util.GosuClassUtil;
import java.io.ObjectStreamException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A type representing the Error state in the type system. This is used when
* we are unable to determine the type for a particular expression due to
* errors and wish to assign a universally-compatible type to it that will
* not cascade the compilation error.
*/
public class ErrorType extends AbstractType implements IErrorType
{
private static final ErrorType INSTANCE = new ErrorType();
private static final Map<String, ErrorType> ERROR_TYPE_POOL = new HashMap<String, ErrorType>();
private static final GenericTypeVariable[] EMPTY_GENERIC_TYPE_VARIABLE_ARR = new GenericTypeVariable[0];
private String _strErrantTypeName;
private ParseResultsException _error;
public static ErrorType getInstance()
{
return INSTANCE;
}
private ErrorType()
{
this( NAME );
}
private ErrorType( String strErrantTypeName )
{
_strErrantTypeName = strErrantTypeName;
}
public static ErrorType getInstance(String strErrantTypeName) {
ErrorType errorType = ERROR_TYPE_POOL.get(strErrantTypeName);
if (errorType == null) {
errorType = new ErrorType(strErrantTypeName);
ERROR_TYPE_POOL.put(strErrantTypeName, errorType);
}
return errorType;
}
public ErrorType(ParseResultsException e) {
this(NAME);
_error = e;
}
public String getName()
{
return _strErrantTypeName;
}
public String getErrantTypeName()
{
return _strErrantTypeName;
}
public ParseResultsException getError() {
return _error;
}
public String getDisplayName()
{
return getName();
}
public String getRelativeName()
{
return GosuClassUtil.getNameNoPackage( _strErrantTypeName );
}
public String getNamespace()
{
return "";
}
public ITypeLoader getTypeLoader()
{
return DefaultTypeLoader.instance();
}
public boolean isInterface()
{
return false;
}
public boolean isEnum()
{
return false;
}
public IType[] getInterfaces()
{
return EMPTY_TYPE_ARRAY;
}
public IType getSupertype()
{
return null;
}
public IType getEnclosingType()
{
return null;
}
public IType getGenericType()
{
return null;
}
public boolean isFinal()
{
return true;
}
public boolean isParameterizedType()
{
return false;
}
public boolean isGenericType()
{
return false;
}
public GenericTypeVariable[] getGenericTypeVariables()
{
return EMPTY_GENERIC_TYPE_VARIABLE_ARR;
}
public IType getParameterizedType( IType... ofType )
{
return null;
}
public IType[] getTypeParameters()
{
return EMPTY_ARRAY;
}
public Set<? extends IType> getAllTypesInHierarchy()
{
return Collections.emptySet();
}
public boolean isArray()
{
return false;
}
public boolean isPrimitive()
{
return false;
}
public IType getArrayType()
{
return new DefaultNonLoadableArrayType( this, null, getTypeLoader() );
}
public Object makeArrayInstance( int iLength )
{
throw new UnsupportedOperationException( "makeArrayInstance not implemented by gw.internal.gosu.parser.ErrorType" );
}
public Object getArrayComponent( Object array, int iIndex ) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
{
throw new UnsupportedOperationException( "getArrayComponent not implemented by gw.internal.gosu.parser.ErrorType" );
}
public void setArrayComponent( Object array, int iIndex, Object value ) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
{
throw new UnsupportedOperationException( "setArrayComponent not implemented by gw.internal.gosu.parser.ErrorType" );
}
public int getArrayLength( Object array ) throws IllegalArgumentException
{
throw new UnsupportedOperationException( "getArrayLength not implemented by gw.internal.gosu.parser.ErrorType" );
}
public IType getComponentType()
{
return this;
}
public boolean isAssignableFrom( IType type )
{
return true;
}
public boolean isMutable()
{
return true;
}
public ITypeInfo getTypeInfo()
{
return ErrorTypeInfo.INSTANCE;
}
public void unloadTypeInfo()
{
//No-op
}
public Object readResolve() throws ObjectStreamException
{
return getInstance();
}
public boolean isValid()
{
return true;
}
public int getModifiers()
{
return Modifier.PUBLIC;
}
public boolean isAbstract()
{
return false;
}
public static boolean shouldHandleAsErrorType( IType type )
{
boolean isErrorType = false;
//if this is a meta intrinsic type, examine it's composite type to determine
//if it is an error type
if( type instanceof MetaType)
{
MetaType metaType = (MetaType)type;
type = metaType.getType();
}
if( type instanceof ErrorType )
{
isErrorType = true;
}
return isErrorType;
}
public IFunctionType getErrorTypeFunctionType( IExpression[] eArgs, String strMethod, List listAllMatchingMethods )
{
ErrorTypeInfo errorTypeInfo = (ErrorTypeInfo)getTypeInfo();
if( eArgs == null )
{
List functionTypes = errorTypeInfo.getUniversalFunctionTypes( strMethod );
for( int i = 0; i < functionTypes.size(); i++ )
{
IFunctionType info = (IFunctionType)functionTypes.get( i );
if( listAllMatchingMethods != null )
{
listAllMatchingMethods.add( info );
}
}
return (IFunctionType)functionTypes.get( 0 );
}
else
{
IFunctionType info = errorTypeInfo.getUniversalFunctionType( strMethod, eArgs.length );
if( listAllMatchingMethods != null )
{
listAllMatchingMethods.add( info );
}
return info;
}
}
public IConstructorType getErrorTypeConstructorType( IExpression[] eArgs, List listAllMatchingMethods )
{
ErrorTypeInfo errorTypeInfo = (ErrorTypeInfo)getTypeInfo();
if( eArgs == null )
{
List constructorTypes = errorTypeInfo.getUniversalConstructors();
for( int i = 0; i < constructorTypes.size(); i++ )
{
IConstructorType info = (IConstructorType)constructorTypes.get( i );
if( listAllMatchingMethods != null )
{
listAllMatchingMethods.add( info );
}
}
return (IConstructorType)constructorTypes.get( 0 );
}
else
{
IConstructorType info = errorTypeInfo.getUniversalConstructor( eArgs.length );
if( listAllMatchingMethods != null )
{
listAllMatchingMethods.add( info );
}
return info;
}
}
@Override
public String toString()
{
return "[error type - " + _strErrantTypeName + "]";
}
public boolean isDiscarded()
{
return false;
}
public void setDiscarded( boolean bDiscarded )
{
}
public boolean isCompoundType()
{
return false;
}
public Set<IType> getCompoundTypeComponents()
{
return null;
}
}