2
// <copyright see="prj:///doc/copyright.txt"/>
3
// <license see="prj:///doc/license.txt"/>
4
// <owner name="Mike KrĆ¼ger" email="mike@icsharpcode.net"/>
5
// <version>$Revision: 4482 $</version>
9
using System.Collections.Generic;
10
using System.Diagnostics;
11
using System.Globalization;
12
using System.Runtime.InteropServices;
15
namespace ICSharpCode.OldNRefactory.Ast
17
public class TypeReference : AbstractNode, INullable, ICloneable
19
public static readonly TypeReference StructConstraint = new TypeReference("constraint: struct");
20
public static readonly TypeReference ClassConstraint = new TypeReference("constraint: class");
21
public static readonly TypeReference NewConstraint = new TypeReference("constraint: new");
24
int pointerNestingLevel;
26
List<TypeReference> genericTypes = new List<TypeReference>();
28
#region Static primitive type list
29
static Dictionary<string, string> types = new Dictionary<string, string>();
30
static Dictionary<string, string> vbtypes = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
31
static Dictionary<string, string> typesReverse = new Dictionary<string, string>();
32
static Dictionary<string, string> vbtypesReverse = new Dictionary<string, string>();
34
static TypeReference()
37
types.Add("bool", "System.Boolean");
38
types.Add("byte", "System.Byte");
39
types.Add("char", "System.Char");
40
types.Add("decimal", "System.Decimal");
41
types.Add("double", "System.Double");
42
types.Add("float", "System.Single");
43
types.Add("int", "System.Int32");
44
types.Add("long", "System.Int64");
45
types.Add("object", "System.Object");
46
types.Add("sbyte", "System.SByte");
47
types.Add("short", "System.Int16");
48
types.Add("string", "System.String");
49
types.Add("uint", "System.UInt32");
50
types.Add("ulong", "System.UInt64");
51
types.Add("ushort", "System.UInt16");
52
types.Add("void", "System.Void");
55
vbtypes.Add("Boolean", "System.Boolean");
56
vbtypes.Add("Byte", "System.Byte");
57
vbtypes.Add("SByte", "System.SByte");
58
vbtypes.Add("Date", "System.DateTime");
59
vbtypes.Add("Char", "System.Char");
60
vbtypes.Add("Decimal", "System.Decimal");
61
vbtypes.Add("Double", "System.Double");
62
vbtypes.Add("Single", "System.Single");
63
vbtypes.Add("Integer", "System.Int32");
64
vbtypes.Add("Long", "System.Int64");
65
vbtypes.Add("UInteger","System.UInt32");
66
vbtypes.Add("ULong", "System.UInt64");
67
vbtypes.Add("Object", "System.Object");
68
vbtypes.Add("Short", "System.Int16");
69
vbtypes.Add("UShort", "System.UInt16");
70
vbtypes.Add("String", "System.String");
72
foreach (KeyValuePair<string, string> pair in types) {
73
typesReverse.Add(pair.Value, pair.Key);
75
foreach (KeyValuePair<string, string> pair in vbtypes) {
76
vbtypesReverse.Add(pair.Value, pair.Key);
81
/// Gets a shortname=>full name dictionary of C# types.
83
public static IDictionary<string, string> PrimitiveTypesCSharp {
88
/// Gets a shortname=>full name dictionary of VB types.
90
public static IDictionary<string, string> PrimitiveTypesVB {
91
get { return vbtypes; }
95
/// Gets a full name=>shortname dictionary of C# types.
97
public static IDictionary<string, string> PrimitiveTypesCSharpReverse {
98
get { return typesReverse; }
102
/// Gets a full name=>shortname dictionary of VB types.
104
public static IDictionary<string, string> PrimitiveTypesVBReverse {
105
get { return vbtypesReverse; }
109
static string GetSystemType(string type)
111
if (types == null) return type;
114
if (types.TryGetValue(type, out systemType)) {
117
if (vbtypes.TryGetValue(type, out systemType)) {
124
object ICloneable.Clone()
129
public virtual TypeReference Clone()
131
TypeReference c = new TypeReference(type);
137
/// Copies the pointerNestingLevel, RankSpecifier, GenericTypes and IsGlobal flag
138
/// from <paramref name="from"/> to <paramref name="to"/>.
141
/// If <paramref name="to"/> already contains generics, the new generics are appended to the list.
143
protected static void CopyFields(TypeReference from, TypeReference to)
145
to.pointerNestingLevel = from.pointerNestingLevel;
146
if (from.rankSpecifier != null) {
147
to.rankSpecifier = (int[])from.rankSpecifier.Clone();
149
foreach (TypeReference r in from.genericTypes) {
150
to.genericTypes.Add(r.Clone());
152
to.IsGlobal = from.IsGlobal;
153
to.IsKeyword = from.IsKeyword;
161
Debug.Assert(value != null);
167
/// Removes the last identifier from the type.
168
/// e.g. "System.String.Length" becomes "System.String" or
169
/// "System.Collections.IEnumerable(of string).Current" becomes "System.Collections.IEnumerable(of string)"
170
/// This is used for explicit interface implementation in VB.
172
public static string StripLastIdentifierFromType(ref TypeReference tr)
174
if (tr is InnerClassTypeReference && ((InnerClassTypeReference)tr).Type.IndexOf('.') < 0) {
175
string ident = ((InnerClassTypeReference)tr).Type;
176
tr = ((InnerClassTypeReference)tr).BaseType;
179
int pos = tr.Type.LastIndexOf('.');
182
string ident = tr.Type.Substring(pos + 1);
183
tr.Type = tr.Type.Substring(0, pos);
188
[Obsolete("Use 'Type' instead - it now contains the SystemType for primitive types.")]
189
public string SystemType {
195
public int PointerNestingLevel {
197
return pointerNestingLevel;
200
Debug.Assert(this.IsNull == false);
201
pointerNestingLevel = value;
206
/// The rank of the array type.
207
/// For "object[]", this is { 0 }; for "object[,]", it is {1}.
208
/// For "object[,][,,][]", it is {1, 2, 0}.
209
/// For non-array types, this property is null or {}.
211
public int[] RankSpecifier {
213
return rankSpecifier;
216
Debug.Assert(this.IsNull == false);
217
rankSpecifier = value;
221
public List<TypeReference> GenericTypes {
227
public bool IsArrayType {
229
return rankSpecifier != null && rankSpecifier.Length > 0;
233
public static TypeReference CheckNull(TypeReference typeReference)
235
return typeReference ?? NullTypeReference.Instance;
238
public static TypeReference Null {
240
return NullTypeReference.Instance;
244
public virtual bool IsNull {
251
/// Gets/Sets if the type reference had a "global::" prefix.
253
public bool IsGlobal {
258
/// Gets/Sets if the type reference was using a language keyword.
260
public bool IsKeyword {
264
public TypeReference(string type)
269
[Obsolete("Type and SystemType are no longer distinguished - use the (string type, bool isKeyword) constructor instead!")]
270
public TypeReference(string type, string systemType)
272
this.Type = systemType;
273
this.IsKeyword = type != systemType;
276
public TypeReference(string type, bool isKeyword)
279
this.IsKeyword = isKeyword;
282
public TypeReference(string type, List<TypeReference> genericTypes) : this(type)
284
if (genericTypes != null) {
285
this.genericTypes = genericTypes;
289
public TypeReference(string type, int[] rankSpecifier) : this(type, 0, rankSpecifier)
293
public TypeReference(string type, int pointerNestingLevel, int[] rankSpecifier) : this(type, pointerNestingLevel, rankSpecifier, null)
297
public TypeReference(string type, int pointerNestingLevel, int[] rankSpecifier, List<TypeReference> genericTypes)
299
Debug.Assert(type != null);
301
this.pointerNestingLevel = pointerNestingLevel;
302
this.rankSpecifier = rankSpecifier;
303
if (genericTypes != null) {
304
this.genericTypes = genericTypes;
308
protected TypeReference()
311
public override object AcceptVisitor(IAstVisitor visitor, object data)
313
return visitor.VisitTypeReference(this, data);
316
public override string ToString()
318
StringBuilder b = new StringBuilder(type);
319
if (genericTypes != null && genericTypes.Count > 0) {
321
for (int i = 0; i < genericTypes.Count; i++) {
322
if (i > 0) b.Append(',');
323
b.Append(genericTypes[i].ToString());
327
if (pointerNestingLevel > 0) {
328
b.Append('*', pointerNestingLevel);
331
foreach (int rank in rankSpecifier) {
334
b.Append('`', -rank);
343
public static bool AreEqualReferences(TypeReference a, TypeReference b)
345
if (a == b) return true;
346
if (a == null || b == null) return false;
347
if (a is InnerClassTypeReference) a = ((InnerClassTypeReference)a).CombineToNormalTypeReference();
348
if (b is InnerClassTypeReference) b = ((InnerClassTypeReference)b).CombineToNormalTypeReference();
349
if (a.type != b.type) return false;
350
if (a.IsKeyword != b.IsKeyword) return false;
351
if (a.IsGlobal != b.IsGlobal) return false;
352
if (a.pointerNestingLevel != b.pointerNestingLevel) return false;
353
if (a.IsArrayType != b.IsArrayType) return false;
355
if (a.rankSpecifier.Length != b.rankSpecifier.Length) return false;
356
for (int i = 0; i < a.rankSpecifier.Length; i++) {
357
if (a.rankSpecifier[i] != b.rankSpecifier[i]) return false;
360
if (a.genericTypes.Count != b.genericTypes.Count) return false;
361
for (int i = 0; i < a.genericTypes.Count; i++) {
362
if (!AreEqualReferences(a.genericTypes[i], b.genericTypes[i]))
369
internal sealed class NullTypeReference : TypeReference
371
public static readonly NullTypeReference Instance = new NullTypeReference();
372
public override bool IsNull {
377
public override TypeReference Clone()
381
public override object AcceptVisitor(IAstVisitor visitor, object data)
386
public override string ToString()
388
return String.Format("[NullTypeReference]");
393
/// We need this special type reference for cases like
394
/// OuterClass(Of T1).InnerClass(Of T2) (in expression or type context)
395
/// or Dictionary(Of String, NamespaceStruct).KeyCollection (in type context, otherwise it's a
396
/// MemberReferenceExpression)
398
public class InnerClassTypeReference: TypeReference
400
TypeReference baseType;
402
public TypeReference BaseType {
403
get { return baseType; }
404
set { baseType = value; }
407
public override TypeReference Clone()
409
InnerClassTypeReference c = new InnerClassTypeReference(baseType.Clone(), Type, new List<TypeReference>());
414
public InnerClassTypeReference(TypeReference outerClass, string innerType, List<TypeReference> innerGenericTypes)
415
: base(innerType, innerGenericTypes)
417
this.baseType = outerClass;
420
public override object AcceptVisitor(IAstVisitor visitor, object data)
422
return visitor.VisitInnerClassTypeReference(this, data);
426
/// Creates a type reference where all type parameters are specified for the innermost class.
427
/// Namespace.OuterClass(of string).InnerClass(of integer).InnerInnerClass
428
/// becomes Namespace.OuterClass.InnerClass.InnerInnerClass(of string, integer)
430
public TypeReference CombineToNormalTypeReference()
432
TypeReference tr = (baseType is InnerClassTypeReference)
433
? ((InnerClassTypeReference)baseType).CombineToNormalTypeReference()
435
CopyFields(this, tr);
436
tr.Type += "." + Type;
440
public override string ToString()
442
return "[InnerClassTypeReference: (" + baseType.ToString() + ")." + base.ToString() + "]";