//
using System.Runtime.InteropServices;
+using System.Text;
namespace System.CodeDom
{
[Serializable]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
- public class CodeTypeReference
- : CodeObject
+ public class CodeTypeReference : CodeObject
{
private string baseType;
- private CodeTypeReference arrayType;
- private int rank;
+ private CodeTypeReference arrayElementType;
+ private int arrayRank;
+ private bool isInterface;
+ //bool needsFixup;
#if NET_2_0
CodeTypeReferenceCollection typeArguments;
- CodeTypeReferenceOptions codeTypeReferenceOption;
+ CodeTypeReferenceOptions referenceOptions;
#endif
//
// Constructors
//
- public CodeTypeReference( string baseType )
- {
- if (baseType.Length == 0) {
- this.baseType = typeof (void).FullName;
- return;
- }
-
- int array_start = baseType.LastIndexOf ('[');
- if (array_start == -1) {
- this.baseType = baseType;
- return;
- }
- string[] args = baseType.Split (',');
- int array_end = baseType.LastIndexOf (']');
+#if NET_2_0
+ public CodeTypeReference ()
+ {
+ }
+#endif
#if NET_2_0
- if ((array_end - array_start) != args.Length) {
- arrayType = new CodeTypeReference (baseType.Substring (0, array_start));
- array_start++;
- TypeArguments.Add (new CodeTypeReference (baseType.Substring (array_start, array_end - array_start)));
- } else
+ [MonoTODO("We should parse basetype from right to left in 2.0 profile.")]
#endif
- arrayType = new CodeTypeReference (baseType.Substring (0, array_start), args.Length);
+ public CodeTypeReference (string baseType)
+ {
+ Parse (baseType);
}
-
- public CodeTypeReference( Type baseType )
+
+#if NET_2_0
+ [MonoTODO("We should parse basetype from right to left in 2.0 profile.")]
+#endif
+ public CodeTypeReference (Type baseType)
{
+#if NET_2_0
+ if (baseType == null) {
+ throw new ArgumentNullException ("baseType");
+ }
+
+ if (baseType.IsGenericParameter) {
+ this.baseType = baseType.Name;
+ this.referenceOptions = CodeTypeReferenceOptions.GenericTypeParameter;
+ }
+ else if (baseType.IsGenericTypeDefinition)
+ this.baseType = baseType.FullName;
+ else if (baseType.IsGenericType) {
+ this.baseType = baseType.GetGenericTypeDefinition ().FullName;
+ foreach (Type arg in baseType.GetGenericArguments ()) {
+ if (arg.IsGenericParameter)
+ TypeArguments.Add (new CodeTypeReference (new CodeTypeParameter (arg.Name)));
+ else
+ TypeArguments.Add (new CodeTypeReference (arg));
+ }
+ }
+ else
+#endif
if (baseType.IsArray) {
- this.rank = baseType.GetArrayRank ();
- this.arrayType = new CodeTypeReference (baseType.GetElementType ());
- this.baseType = arrayType.BaseType;
- return;
+ this.arrayRank = baseType.GetArrayRank ();
+ this.arrayElementType = new CodeTypeReference (baseType.GetElementType ());
+ this.baseType = arrayElementType.BaseType;
+ } else {
+ Parse (baseType.FullName);
}
- this.baseType = baseType.FullName;
+ this.isInterface = baseType.IsInterface;
}
- public CodeTypeReference( CodeTypeReference arrayType, int rank )
+ public CodeTypeReference( CodeTypeReference arrayElementType, int arrayRank )
{
this.baseType = null;
- this.rank = rank;
- this.arrayType = arrayType;
+ this.arrayRank = arrayRank;
+ this.arrayElementType = arrayElementType;
}
- public CodeTypeReference( string baseType, int rank )
- : this (new CodeTypeReference (baseType), rank)
+#if NET_2_0
+ [MonoTODO("We should parse basetype from right to left in 2.0 profile.")]
+#endif
+ public CodeTypeReference( string baseType, int arrayRank )
+ : this (new CodeTypeReference (baseType), arrayRank)
{
}
-
+
#if NET_2_0
public CodeTypeReference( CodeTypeParameter typeParameter ) :
this (typeParameter.Name)
{
+ this.referenceOptions = CodeTypeReferenceOptions.GenericTypeParameter;
}
- public CodeTypeReference( string typeName, CodeTypeReferenceOptions codeTypeReferenceOption ) :
+ public CodeTypeReference( string typeName, CodeTypeReferenceOptions referenceOptions ) :
this (typeName)
{
- this.codeTypeReferenceOption = codeTypeReferenceOption;
+ this.referenceOptions = referenceOptions;
}
- public CodeTypeReference( Type type, CodeTypeReferenceOptions codeTypeReferenceOption ) :
+ public CodeTypeReference( Type type, CodeTypeReferenceOptions referenceOptions ) :
this (type)
{
- this.codeTypeReferenceOption = codeTypeReferenceOption;
+ this.referenceOptions = referenceOptions;
}
public CodeTypeReference( string typeName, params CodeTypeReference[] typeArguments ) :
this (typeName)
{
TypeArguments.AddRange (typeArguments);
+ if (this.baseType.IndexOf ('`') < 0)
+ this.baseType += "`" + TypeArguments.Count;
}
#endif
public CodeTypeReference ArrayElementType
{
get {
- return arrayType;
+ return arrayElementType;
}
set {
- arrayType = value;
+ arrayElementType = value;
}
}
public int ArrayRank {
get {
- return rank;
+ return arrayRank;
}
set {
- rank = value;
+ arrayRank = value;
}
}
public string BaseType {
get {
+ if (arrayElementType != null && arrayRank > 0) {
+ return arrayElementType.BaseType;
+ }
+
if (baseType == null)
return String.Empty;
}
}
+ internal bool IsInterface {
+ get { return isInterface; }
+ }
+
+ private void Parse (string baseType)
+ {
+ if (baseType == null || baseType.Length == 0) {
+ this.baseType = typeof (void).FullName;
+ return;
+ }
+
+#if NET_2_0
+ int array_start = baseType.IndexOf ('[');
+ if (array_start == -1) {
+ this.baseType = baseType;
+ return;
+ }
+
+ int array_end = baseType.LastIndexOf (']');
+ if (array_end < array_start) {
+ this.baseType = baseType;
+ return;
+ }
+
+ int lastAngle = baseType.LastIndexOf ('>');
+ if (lastAngle != -1 && lastAngle > array_end) {
+ this.baseType = baseType;
+ return;
+ }
+
+ string[] args = baseType.Substring (array_start + 1, array_end - array_start - 1).Split (',');
+
+ if ((array_end - array_start) != args.Length) {
+ this.baseType = baseType.Substring (0, array_start);
+ int escapeCount = 0;
+ int scanPos = array_start;
+ StringBuilder tb = new StringBuilder();
+ while (scanPos < baseType.Length) {
+ char currentChar = baseType[scanPos];
+
+ switch (currentChar) {
+ case '[':
+ if (escapeCount > 1 && tb.Length > 0) {
+ tb.Append (currentChar);
+ }
+ escapeCount++;
+ break;
+ case ']':
+ escapeCount--;
+ if (escapeCount > 1 && tb.Length > 0) {
+ tb.Append (currentChar);
+ }
+
+ if (tb.Length != 0 && (escapeCount % 2) == 0) {
+ TypeArguments.Add (tb.ToString ());
+ tb.Length = 0;
+ }
+ break;
+ case ',':
+ if (escapeCount > 1) {
+ // skip anything after the type name until we
+ // reach the next separator
+ while (scanPos + 1 < baseType.Length) {
+ if (baseType[scanPos + 1] == ']') {
+ break;
+ }
+ scanPos++;
+ }
+ } else if (tb.Length > 0) {
+ CodeTypeReference typeArg = new CodeTypeReference (tb.ToString ());
+ TypeArguments.Add (typeArg);
+ tb.Length = 0;
+ }
+ break;
+ default:
+ tb.Append (currentChar);
+ break;
+ }
+ scanPos++;
+ }
+ } else {
+ arrayElementType = new CodeTypeReference (baseType.Substring (0, array_start));
+ arrayRank = args.Length;
+ }
+#else
+ int array_start = baseType.LastIndexOf ('[');
+ if (array_start == -1) {
+ this.baseType = baseType;
+ return;
+ }
+
+ int array_end = baseType.LastIndexOf (']');
+ if (array_end < array_start) {
+ this.baseType = baseType;
+ return;
+ }
+
+ string[] args = baseType.Substring (array_start + 1, array_end - array_start - 1).Split (',');
+
+ bool isArray = true;
+ foreach (string arg in args) {
+ if (arg.Length != 0) {
+ isArray = false;
+ break;
+ }
+ }
+ if (isArray) {
+ arrayElementType = new CodeTypeReference (baseType.Substring (0, array_start));
+ arrayRank = args.Length;
+ } else {
+ this.baseType = baseType;
+ }
+#endif
+ }
+
#if NET_2_0
[ComVisible (false)]
public CodeTypeReferenceOptions Options {
get {
- return codeTypeReferenceOption;
+ return referenceOptions;
}
set {
- codeTypeReferenceOption = value;
+ referenceOptions = value;
}
}
}
}
#endif
+
}
}