using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Specialized;
namespace AnticipatingMinds.Genesis.CodeDOM{
/// <summary>
/// Represents a reference to a type.
/// </summary>
[Serializable]
public class CodeTypeReference : CodeElement
{
#region Instance constructors
/// <summary>
/// Initializes a new instance of the CodeTypeReference class using the System.Void data type.
/// </summary>
public CodeTypeReference(): this(typeof(void)){}
/// <summary>
/// Initializes a new instance of the CodeTypeReference class using the specified data type.
/// </summary>
/// <param name="type">The data type to reference.</param>
public CodeTypeReference(Type type)
{
if (type.IsArray)
{
this.arrayRank = type.GetArrayRank();
this.arrayElementType = new CodeTypeReference(type.GetElementType());
this.baseType = null;
}
else
{
this.arrayRank = 0;
this.arrayElementType = null;
this.baseType = type.FullName;
}
}
/// <summary>
/// Initializes a new instance of the CodeTypeReference class using the specified data type name.
/// </summary>
/// <param name="typeName">The name of the type to reference. </param>
public CodeTypeReference(string typeName)
{
TypeName = typeName;
}
#endregion Instance constructors
#region Public instance properties
/// <summary>
/// Gets the name of the data type being referenced.
/// </summary>
public string TypeName
{
get
{
if(isPointer)
return pointerType.TypeName;
if (arrayRank > 0 && arrayElementType != null)
{
return arrayElementType.TypeName;
}
return (baseType == null) ? string.Empty : baseType;
}
set
{
if (value == null || value.Length == 0)
{
value = typeof(void).FullName;
}
if(value[value.Length-1] == '*')
{
this.baseType = null;
this.isPointer = true;
this.pointerType = new CodeTypeReference(value.Substring(0, value.Length-1));
}
else
{
// See if this ends with standard array tail. If is is not an exact match, we pass it through verbatim.
//we need to track inner square brackts too
//string a[b,c[0]] is really string[,] for our purposes
//string a[b[0]][] is string[][]
//so, the firsth thing that we do is stripping stuff in between last brackates.
isArray = false;
int lastArrayClose = -1;
int lastArrayOpen = -1;
lastArrayClose = value.LastIndexOf(']');
lastArrayOpen = -1;
if(lastArrayClose >=0)
{
int closebrackets = 0;
int pos = lastArrayClose;
while(pos >= 0)
{
if(value[pos] == ']')
closebrackets++;
if(value[pos] == '[')
{
closebrackets--;
if(closebrackets == 0)
{
lastArrayOpen = pos;
break;
}
}
pos--;
}
}
int arrayRank = 0;
isArray = lastArrayOpen >= 0 && lastArrayClose == (value.Length - 1) && lastArrayOpen < lastArrayClose;
if (isArray)
{
arrayRank = 1;
for (int index = lastArrayOpen + 1; index < lastArrayClose; index++)
{
if (value[index] == ',')
{
arrayRank++;
}
}
}
if (isArray)
{
this.baseType = null;
this.arrayRank = arrayRank;
this.arrayElementType = new CodeTypeReference(value.Substring(0, lastArrayOpen));
this.isPointer = false;
this.pointerType = null;
}
else
{
this.baseType = value;
this.arrayRank = 0;
this.arrayElementType = null;
this.isPointer = false;
this.pointerType = null;
}
}
}
}
/// <summary>
/// Returns an array element type if type is an array.
/// </summary>
public CodeTypeReference ArrayElementType
{
get
{
return arrayElementType;
}
set
{
arrayElementType = value;
}
}
/// <summary>
/// Returns a pointer element type if type is a pointer.
/// </summary>
public CodeTypeReference PointerType
{
get
{
return pointerType;
}
set
{
pointerType = value;
}
}
/// <summary>
/// Returns true if it is a reference to an array type.
/// </summary>
public bool IsArray
{
get
{
return isArray;
}
}
/// <summary>
/// Returns true if it is a reference to a pointer type.
/// </summary>
public bool IsPointer
{
get
{
return isPointer;
}
}
/// <summary>
/// Gets an array rank if it is reference to an array type.
/// </summary>
public int ArrayRank
{
get
{
return arrayRank;
}
set
{
arrayRank = value;
}
}
/// <summary>
/// Gets code metadata type information if available.
/// </summary>
public CodeTypeInfo TypeInfo
{
get
{
return typeInfo;
}
set
{
typeInfo = value;
}
}
#endregion Public instance properties
#region Private instance fields
private string baseType;
private int arrayRank;
private bool isArray = false;
private bool isPointer = false;
private CodeTypeReference arrayElementType;
private CodeTypeReference pointerType;
private CodeTypeInfo typeInfo;
#endregion Private instance fields
}
}
|