PageRenderTime 37ms CodeModel.GetById 17ms app.highlight 16ms RepoModel.GetById 0ms app.codeStats 0ms

/main/contrib/NRefactory/Project/Src/Ast/TypeReference.cs

https://github.com/jfcantin/monodevelop
C# | 445 lines | 340 code | 49 blank | 56 comment | 57 complexity | 55d0633fddb7621d20454a405a962aaa MD5 | raw file
  1// <file>
  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>
  6// </file>
  7
  8using System;
  9using System.Collections.Generic;
 10using System.Diagnostics;
 11using System.Globalization;
 12using System.Runtime.InteropServices;
 13using System.Text;
 14
 15namespace ICSharpCode.OldNRefactory.Ast
 16{
 17	public class TypeReference : AbstractNode, INullable, ICloneable
 18	{
 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");
 22		
 23		string type = "";
 24		int    pointerNestingLevel;
 25		int[]  rankSpecifier;
 26		List<TypeReference> genericTypes = new List<TypeReference>();
 27		
 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>();
 33		
 34		static TypeReference()
 35		{
 36			// C# types
 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");
 53			
 54			// VB.NET types
 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");
 71			
 72			foreach (KeyValuePair<string, string> pair in types) {
 73				typesReverse.Add(pair.Value, pair.Key);
 74			}
 75			foreach (KeyValuePair<string, string> pair in vbtypes) {
 76				vbtypesReverse.Add(pair.Value, pair.Key);
 77			}
 78		}
 79		
 80		/// <summary>
 81		/// Gets a shortname=>full name dictionary of C# types.
 82		/// </summary>
 83		public static IDictionary<string, string> PrimitiveTypesCSharp {
 84			get { return types; }
 85		}
 86		
 87		/// <summary>
 88		/// Gets a shortname=>full name dictionary of VB types.
 89		/// </summary>
 90		public static IDictionary<string, string> PrimitiveTypesVB {
 91			get { return vbtypes; }
 92		}
 93		
 94		/// <summary>
 95		/// Gets a full name=>shortname dictionary of C# types.
 96		/// </summary>
 97		public static IDictionary<string, string> PrimitiveTypesCSharpReverse {
 98			get { return typesReverse; }
 99		}
100		
101		/// <summary>
102		/// Gets a full name=>shortname dictionary of VB types.
103		/// </summary>
104		public static IDictionary<string, string> PrimitiveTypesVBReverse {
105			get { return vbtypesReverse; }
106		}
107		
108		
109		static string GetSystemType(string type)
110		{
111			if (types == null) return type;
112			
113			string systemType;
114			if (types.TryGetValue(type, out systemType)) {
115				return systemType;
116			}
117			if (vbtypes.TryGetValue(type, out systemType)) {
118				return systemType;
119			}
120			return type;
121		}
122		#endregion
123		
124		object ICloneable.Clone()
125		{
126			return this.Clone();
127		}
128		
129		public virtual TypeReference Clone()
130		{
131			TypeReference c = new TypeReference(type);
132			CopyFields(this, c);
133			return c;
134		}
135		
136		/// <summary>
137		/// Copies the pointerNestingLevel, RankSpecifier, GenericTypes and IsGlobal flag
138		/// from <paramref name="from"/> to <paramref name="to"/>.
139		/// </summary>
140		/// <remarks>
141		/// If <paramref name="to"/> already contains generics, the new generics are appended to the list.
142		/// </remarks>
143		protected static void CopyFields(TypeReference from, TypeReference to)
144		{
145			to.pointerNestingLevel = from.pointerNestingLevel;
146			if (from.rankSpecifier != null) {
147				to.rankSpecifier = (int[])from.rankSpecifier.Clone();
148			}
149			foreach (TypeReference r in from.genericTypes) {
150				to.genericTypes.Add(r.Clone());
151			}
152			to.IsGlobal = from.IsGlobal;
153			to.IsKeyword = from.IsKeyword;
154		}
155		
156		public string Type {
157			get {
158				return type;
159			}
160			set {
161				Debug.Assert(value != null);
162				type = value ?? "?";
163			}
164		}
165		
166		/// <summary>
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.
171		/// </summary>
172		public static string StripLastIdentifierFromType(ref TypeReference tr)
173		{
174			if (tr is InnerClassTypeReference && ((InnerClassTypeReference)tr).Type.IndexOf('.') < 0) {
175				string ident = ((InnerClassTypeReference)tr).Type;
176				tr = ((InnerClassTypeReference)tr).BaseType;
177				return ident;
178			} else {
179				int pos = tr.Type.LastIndexOf('.');
180				if (pos < 0)
181					return tr.Type;
182				string ident = tr.Type.Substring(pos + 1);
183				tr.Type = tr.Type.Substring(0, pos);
184				return ident;
185			}
186		}
187		
188		[Obsolete("Use 'Type' instead - it now contains the SystemType for primitive types.")]
189		public string SystemType {
190			get {
191				return this.Type;
192			}
193		}
194		
195		public int PointerNestingLevel {
196			get {
197				return pointerNestingLevel;
198			}
199			set {
200				Debug.Assert(this.IsNull == false);
201				pointerNestingLevel = value;
202			}
203		}
204		
205		/// <summary>
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 {}.
210		/// </summary>
211		public int[] RankSpecifier {
212			get {
213				return rankSpecifier;
214			}
215			set {
216				Debug.Assert(this.IsNull == false);
217				rankSpecifier = value;
218			}
219		}
220		
221		public List<TypeReference> GenericTypes {
222			get {
223				return genericTypes;
224			}
225		}
226		
227		public bool IsArrayType {
228			get {
229				return rankSpecifier != null && rankSpecifier.Length > 0;
230			}
231		}
232		
233		public static TypeReference CheckNull(TypeReference typeReference)
234		{
235			return typeReference ?? NullTypeReference.Instance;
236		}
237		
238		public static TypeReference Null {
239			get {
240				return NullTypeReference.Instance;
241			}
242		}
243		
244		public virtual bool IsNull {
245			get {
246				return false;
247			}
248		}
249		
250		/// <summary>
251		/// Gets/Sets if the type reference had a "global::" prefix.
252		/// </summary>
253		public bool IsGlobal {
254			get; set;
255		}
256		
257		/// <summary>
258		/// Gets/Sets if the type reference was using a language keyword.
259		/// </summary>
260		public bool IsKeyword {
261			get; set;
262		}
263		
264		public TypeReference(string type)
265		{
266			this.Type = type;
267		}
268		
269		[Obsolete("Type and SystemType are no longer distinguished - use the (string type, bool isKeyword) constructor instead!")]
270		public TypeReference(string type, string systemType)
271		{
272			this.Type = systemType;
273			this.IsKeyword = type != systemType;
274		}
275		
276		public TypeReference(string type, bool isKeyword)
277		{
278			this.Type = type;
279			this.IsKeyword = isKeyword;
280		}
281		
282		public TypeReference(string type, List<TypeReference> genericTypes) : this(type)
283		{
284			if (genericTypes != null) {
285				this.genericTypes = genericTypes;
286			}
287		}
288		
289		public TypeReference(string type, int[] rankSpecifier) : this(type, 0, rankSpecifier)
290		{
291		}
292		
293		public TypeReference(string type, int pointerNestingLevel, int[] rankSpecifier) : this(type, pointerNestingLevel, rankSpecifier, null)
294		{
295		}
296		
297		public TypeReference(string type, int pointerNestingLevel, int[] rankSpecifier, List<TypeReference> genericTypes)
298		{
299			Debug.Assert(type != null);
300			this.type = type;
301			this.pointerNestingLevel = pointerNestingLevel;
302			this.rankSpecifier = rankSpecifier;
303			if (genericTypes != null) {
304				this.genericTypes = genericTypes;
305			}
306		}
307		
308		protected TypeReference()
309		{}
310		
311		public override object AcceptVisitor(IAstVisitor visitor, object data)
312		{
313			return visitor.VisitTypeReference(this, data);
314		}
315		
316		public override string ToString()
317		{
318			StringBuilder b = new StringBuilder(type);
319			if (genericTypes != null && genericTypes.Count > 0) {
320				b.Append('<');
321				for (int i = 0; i < genericTypes.Count; i++) {
322					if (i > 0) b.Append(',');
323					b.Append(genericTypes[i].ToString());
324				}
325				b.Append('>');
326			}
327			if (pointerNestingLevel > 0) {
328				b.Append('*', pointerNestingLevel);
329			}
330			if (IsArrayType) {
331				foreach (int rank in rankSpecifier) {
332					b.Append('[');
333					if (rank < 0)
334						b.Append('`', -rank);
335					else
336						b.Append(',', rank);
337					b.Append(']');
338				}
339			}
340			return b.ToString();
341		}
342		
343		public static bool AreEqualReferences(TypeReference a, TypeReference b)
344		{
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;
354			if (a.IsArrayType) {
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;
358				}
359			}
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]))
363					return false;
364			}
365			return true;
366		}
367	}
368
369	internal sealed class NullTypeReference : TypeReference
370	{
371		public static readonly NullTypeReference Instance = new NullTypeReference();
372		public override bool IsNull {
373			get {
374				return true;
375			}
376		}
377		public override TypeReference Clone()
378		{
379			return this;
380		}
381		public override object AcceptVisitor(IAstVisitor visitor, object data)
382		{
383			return null;
384		}
385		
386		public override string ToString()
387		{
388			return String.Format("[NullTypeReference]");
389		}
390	}
391
392	/// <summary>
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)
397	/// </summary>
398	public class InnerClassTypeReference: TypeReference
399	{
400		TypeReference baseType;
401		
402		public TypeReference BaseType {
403			get { return baseType; }
404			set { baseType = value; }
405		}
406		
407		public override TypeReference Clone()
408		{
409			InnerClassTypeReference c = new InnerClassTypeReference(baseType.Clone(), Type, new List<TypeReference>());
410			CopyFields(this, c);
411			return c;
412		}
413		
414		public InnerClassTypeReference(TypeReference outerClass, string innerType, List<TypeReference> innerGenericTypes)
415			: base(innerType, innerGenericTypes)
416		{
417			this.baseType = outerClass;
418		}
419		
420		public override object AcceptVisitor(IAstVisitor visitor, object data)
421		{
422			return visitor.VisitInnerClassTypeReference(this, data);
423		}
424		
425		/// <summary>
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)
429		/// </summary>
430		public TypeReference CombineToNormalTypeReference()
431		{
432			TypeReference tr = (baseType is InnerClassTypeReference)
433				? ((InnerClassTypeReference)baseType).CombineToNormalTypeReference()
434				: baseType.Clone();
435			CopyFields(this, tr);
436			tr.Type += "." + Type;
437			return tr;
438		}
439		
440		public override string ToString()
441		{
442			return "[InnerClassTypeReference: (" + baseType.ToString() + ")." + base.ToString() + "]";
443		}
444	}
445}