/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser.expressions;
import gw.internal.gosu.parser.Expression;
import gw.internal.gosu.parser.GosuClassCompilingStack;
import gw.internal.gosu.parser.GosuParser;
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.parser.exceptions.ParseWarningForDeprecatedMember;
import gw.lang.parser.expressions.ITypeLiteralExpression;
import gw.lang.reflect.IType;
import gw.lang.reflect.ITypeInfo;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.gs.IGosuClass;
/**
* Represents a Type literal expression as defined in the Gosu grammar.
*
* @see gw.lang.parser.IGosuParser
*/
public class TypeLiteral extends Literal implements ITypeLiteralExpression
{
private static final ThreadLocal<Boolean> _isComputingIsDeprecated = new ThreadLocal<Boolean>();
private Expression _packageExpr;
private boolean _ignoreTypeDeprecation;
public TypeLiteral( IType type, boolean ignoreTypeDeprecation )
{
_ignoreTypeDeprecation = ignoreTypeDeprecation;
setType( type );
}
public TypeLiteral( IType type )
{
setType( type );
}
public TypeLiteral()
{
}
/**
* This expression is of NamespaceType. It will be either an Identifier or a MemberAccess.
*/
public Expression getPackageExpression()
{
return _packageExpr;
}
public void setPackageExpression( Expression packageExpr )
{
_packageExpr = packageExpr;
}
@Override
public void setType( IType type )
{
if( type instanceof MetaType)
{
if( !((MetaType)type).isLiteral() )
{
type = MetaType.getLiteral( ((MetaType)type).getType() );
}
super.setType( type );
}
else
{
super.setType( MetaType.getLiteral( type ) );
}
IType gosuClass = GosuClassCompilingStack.getCurrentCompilingType();
if( !_ignoreTypeDeprecation && (!(gosuClass instanceof IGosuClass) || ((IGosuClass)gosuClass).isCompilingDefinitions()) )
{
Boolean isComputing = _isComputingIsDeprecated.get();
if( isComputing != Boolean.TRUE && getType() != null && !isEnclosureDeprecated( gosuClass ) )
{
IType thisType = getType().getType();
if( thisType != null )
{
_isComputingIsDeprecated.set( Boolean.TRUE );
try
{
ITypeInfo typeInfo = thisType.getTypeInfo();
if( typeInfo != null && typeInfo.isDeprecated() )
{
//noinspection ThrowableInstanceNeverThrown
addParseWarning( new ParseWarningForDeprecatedMember(null, thisType.getDisplayName(), thisType.getDisplayName() ) );
}
}
finally
{
_isComputingIsDeprecated.set(Boolean.FALSE);
}
}
}
}
}
private boolean isEnclosureDeprecated( IType type )
{
if( !(type instanceof IGosuClass) )
{
return false;
}
IGosuClassInternal gsClass = (IGosuClassInternal)type;
GosuParser parser = (GosuParser)gsClass.getParser();
return parser != null && parser.isIgnoreTypeDeprecation();
}
/**
* @param types If this is a parameterized type, these are the parameter types.
*/
public void setParameterTypes( IType[] types )
{
if( types.length == 0 )
{
return;
}
IType parameterizedType = getType().getType().getParameterizedType( types );
setType( MetaType.getLiteral( parameterizedType ) );
}
@SuppressWarnings({"CloneDoesntCallSuperClone", "CloneDoesntDeclareCloneNotSupportedException"})
@Override
public Object clone()
{
TypeLiteral clone = new TypeLiteral( getType() );
clone.setLocation( getLocation() );
return clone;
}
public boolean isCompileTimeConstant()
{
IType type = getType().getType();
return !type.isParameterizedType() && !(type instanceof TypeVariableType);
}
public IType evaluate()
{
return getType().getType();
}
@Override
public String toString()
{
return TypeLord.getPureGenericType( getType().getType() ).getName();
}
public MetaType getType()
{
MetaType type = getTypeImpl();
if( type != null && TypeSystem.isDeleted( type.getType() ) ) {
type = (MetaType) TypeSystem.getErrorType().getMetaType();
}
return type;
}
@Override
protected MetaType getTypeImpl() {
return (MetaType)super.getTypeImpl();
}
}