PageRenderTime 55ms CodeModel.GetById 27ms 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. using System;
  8. using System.Collections.Generic;
  9. using System.Diagnostics;
  10. using System.Globalization;
  11. using System.Runtime.InteropServices;
  12. using System.Text;
  13. namespace ICSharpCode.OldNRefactory.Ast
  14. {
  15. public class TypeReference : AbstractNode, INullable, ICloneable
  16. {
  17. public static readonly TypeReference StructConstraint = new TypeReference("constraint: struct");
  18. public static readonly TypeReference ClassConstraint = new TypeReference("constraint: class");
  19. public static readonly TypeReference NewConstraint = new TypeReference("constraint: new");
  20. string type = "";
  21. int pointerNestingLevel;
  22. int[] rankSpecifier;
  23. List<TypeReference> genericTypes = new List<TypeReference>();
  24. #region Static primitive type list
  25. static Dictionary<string, string> types = new Dictionary<string, string>();
  26. static Dictionary<string, string> vbtypes = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
  27. static Dictionary<string, string> typesReverse = new Dictionary<string, string>();
  28. static Dictionary<string, string> vbtypesReverse = new Dictionary<string, string>();
  29. static TypeReference()
  30. {
  31. // C# types
  32. types.Add("bool", "System.Boolean");
  33. types.Add("byte", "System.Byte");
  34. types.Add("char", "System.Char");
  35. types.Add("decimal", "System.Decimal");
  36. types.Add("double", "System.Double");
  37. types.Add("float", "System.Single");
  38. types.Add("int", "System.Int32");
  39. types.Add("long", "System.Int64");
  40. types.Add("object", "System.Object");
  41. types.Add("sbyte", "System.SByte");
  42. types.Add("short", "System.Int16");
  43. types.Add("string", "System.String");
  44. types.Add("uint", "System.UInt32");
  45. types.Add("ulong", "System.UInt64");
  46. types.Add("ushort", "System.UInt16");
  47. types.Add("void", "System.Void");
  48. // VB.NET types
  49. vbtypes.Add("Boolean", "System.Boolean");
  50. vbtypes.Add("Byte", "System.Byte");
  51. vbtypes.Add("SByte", "System.SByte");
  52. vbtypes.Add("Date", "System.DateTime");
  53. vbtypes.Add("Char", "System.Char");
  54. vbtypes.Add("Decimal", "System.Decimal");
  55. vbtypes.Add("Double", "System.Double");
  56. vbtypes.Add("Single", "System.Single");
  57. vbtypes.Add("Integer", "System.Int32");
  58. vbtypes.Add("Long", "System.Int64");
  59. vbtypes.Add("UInteger","System.UInt32");
  60. vbtypes.Add("ULong", "System.UInt64");
  61. vbtypes.Add("Object", "System.Object");
  62. vbtypes.Add("Short", "System.Int16");
  63. vbtypes.Add("UShort", "System.UInt16");
  64. vbtypes.Add("String", "System.String");
  65. foreach (KeyValuePair<string, string> pair in types) {
  66. typesReverse.Add(pair.Value, pair.Key);
  67. }
  68. foreach (KeyValuePair<string, string> pair in vbtypes) {
  69. vbtypesReverse.Add(pair.Value, pair.Key);
  70. }
  71. }
  72. /// <summary>
  73. /// Gets a shortname=>full name dictionary of C# types.
  74. /// </summary>
  75. public static IDictionary<string, string> PrimitiveTypesCSharp {
  76. get { return types; }
  77. }
  78. /// <summary>
  79. /// Gets a shortname=>full name dictionary of VB types.
  80. /// </summary>
  81. public static IDictionary<string, string> PrimitiveTypesVB {
  82. get { return vbtypes; }
  83. }
  84. /// <summary>
  85. /// Gets a full name=>shortname dictionary of C# types.
  86. /// </summary>
  87. public static IDictionary<string, string> PrimitiveTypesCSharpReverse {
  88. get { return typesReverse; }
  89. }
  90. /// <summary>
  91. /// Gets a full name=>shortname dictionary of VB types.
  92. /// </summary>
  93. public static IDictionary<string, string> PrimitiveTypesVBReverse {
  94. get { return vbtypesReverse; }
  95. }
  96. static string GetSystemType(string type)
  97. {
  98. if (types == null) return type;
  99. string systemType;
  100. if (types.TryGetValue(type, out systemType)) {
  101. return systemType;
  102. }
  103. if (vbtypes.TryGetValue(type, out systemType)) {
  104. return systemType;
  105. }
  106. return type;
  107. }
  108. #endregion
  109. object ICloneable.Clone()
  110. {
  111. return this.Clone();
  112. }
  113. public virtual TypeReference Clone()
  114. {
  115. TypeReference c = new TypeReference(type);
  116. CopyFields(this, c);
  117. return c;
  118. }
  119. /// <summary>
  120. /// Copies the pointerNestingLevel, RankSpecifier, GenericTypes and IsGlobal flag
  121. /// from <paramref name="from"/> to <paramref name="to"/>.
  122. /// </summary>
  123. /// <remarks>
  124. /// If <paramref name="to"/> already contains generics, the new generics are appended to the list.
  125. /// </remarks>
  126. protected static void CopyFields(TypeReference from, TypeReference to)
  127. {
  128. to.pointerNestingLevel = from.pointerNestingLevel;
  129. if (from.rankSpecifier != null) {
  130. to.rankSpecifier = (int[])from.rankSpecifier.Clone();
  131. }
  132. foreach (TypeReference r in from.genericTypes) {
  133. to.genericTypes.Add(r.Clone());
  134. }
  135. to.IsGlobal = from.IsGlobal;
  136. to.IsKeyword = from.IsKeyword;
  137. }
  138. public string Type {
  139. get {
  140. return type;
  141. }
  142. set {
  143. Debug.Assert(value != null);
  144. type = value ?? "?";
  145. }
  146. }
  147. /// <summary>
  148. /// Removes the last identifier from the type.
  149. /// e.g. "System.String.Length" becomes "System.String" or
  150. /// "System.Collections.IEnumerable(of string).Current" becomes "System.Collections.IEnumerable(of string)"
  151. /// This is used for explicit interface implementation in VB.
  152. /// </summary>
  153. public static string StripLastIdentifierFromType(ref TypeReference tr)
  154. {
  155. if (tr is InnerClassTypeReference && ((InnerClassTypeReference)tr).Type.IndexOf('.') < 0) {
  156. string ident = ((InnerClassTypeReference)tr).Type;
  157. tr = ((InnerClassTypeReference)tr).BaseType;
  158. return ident;
  159. } else {
  160. int pos = tr.Type.LastIndexOf('.');
  161. if (pos < 0)
  162. return tr.Type;
  163. string ident = tr.Type.Substring(pos + 1);
  164. tr.Type = tr.Type.Substring(0, pos);
  165. return ident;
  166. }
  167. }
  168. [Obsolete("Use 'Type' instead - it now contains the SystemType for primitive types.")]
  169. public string SystemType {
  170. get {
  171. return this.Type;
  172. }
  173. }
  174. public int PointerNestingLevel {
  175. get {
  176. return pointerNestingLevel;
  177. }
  178. set {
  179. Debug.Assert(this.IsNull == false);
  180. pointerNestingLevel = value;
  181. }
  182. }
  183. /// <summary>
  184. /// The rank of the array type.
  185. /// For "object[]", this is { 0 }; for "object[,]", it is {1}.
  186. /// For "object[,][,,][]", it is {1, 2, 0}.
  187. /// For non-array types, this property is null or {}.
  188. /// </summary>
  189. public int[] RankSpecifier {
  190. get {
  191. return rankSpecifier;
  192. }
  193. set {
  194. Debug.Assert(this.IsNull == false);
  195. rankSpecifier = value;
  196. }
  197. }
  198. public List<TypeReference> GenericTypes {
  199. get {
  200. return genericTypes;
  201. }
  202. }
  203. public bool IsArrayType {
  204. get {
  205. return rankSpecifier != null && rankSpecifier.Length > 0;
  206. }
  207. }
  208. public static TypeReference CheckNull(TypeReference typeReference)
  209. {
  210. return typeReference ?? NullTypeReference.Instance;
  211. }
  212. public static TypeReference Null {
  213. get {
  214. return NullTypeReference.Instance;
  215. }
  216. }
  217. public virtual bool IsNull {
  218. get {
  219. return false;
  220. }
  221. }
  222. /// <summary>
  223. /// Gets/Sets if the type reference had a "global::" prefix.
  224. /// </summary>
  225. public bool IsGlobal {
  226. get; set;
  227. }
  228. /// <summary>
  229. /// Gets/Sets if the type reference was using a language keyword.
  230. /// </summary>
  231. public bool IsKeyword {
  232. get; set;
  233. }
  234. public TypeReference(string type)
  235. {
  236. this.Type = type;
  237. }
  238. [Obsolete("Type and SystemType are no longer distinguished - use the (string type, bool isKeyword) constructor instead!")]
  239. public TypeReference(string type, string systemType)
  240. {
  241. this.Type = systemType;
  242. this.IsKeyword = type != systemType;
  243. }
  244. public TypeReference(string type, bool isKeyword)
  245. {
  246. this.Type = type;
  247. this.IsKeyword = isKeyword;
  248. }
  249. public TypeReference(string type, List<TypeReference> genericTypes) : this(type)
  250. {
  251. if (genericTypes != null) {
  252. this.genericTypes = genericTypes;
  253. }
  254. }
  255. public TypeReference(string type, int[] rankSpecifier) : this(type, 0, rankSpecifier)
  256. {
  257. }
  258. public TypeReference(string type, int pointerNestingLevel, int[] rankSpecifier) : this(type, pointerNestingLevel, rankSpecifier, null)
  259. {
  260. }
  261. public TypeReference(string type, int pointerNestingLevel, int[] rankSpecifier, List<TypeReference> genericTypes)
  262. {
  263. Debug.Assert(type != null);
  264. this.type = type;
  265. this.pointerNestingLevel = pointerNestingLevel;
  266. this.rankSpecifier = rankSpecifier;
  267. if (genericTypes != null) {
  268. this.genericTypes = genericTypes;
  269. }
  270. }
  271. protected TypeReference()
  272. {}
  273. public override object AcceptVisitor(IAstVisitor visitor, object data)
  274. {
  275. return visitor.VisitTypeReference(this, data);
  276. }
  277. public override string ToString()
  278. {
  279. StringBuilder b = new StringBuilder(type);
  280. if (genericTypes != null && genericTypes.Count > 0) {
  281. b.Append('<');
  282. for (int i = 0; i < genericTypes.Count; i++) {
  283. if (i > 0) b.Append(',');
  284. b.Append(genericTypes[i].ToString());
  285. }
  286. b.Append('>');
  287. }
  288. if (pointerNestingLevel > 0) {
  289. b.Append('*', pointerNestingLevel);
  290. }
  291. if (IsArrayType) {
  292. foreach (int rank in rankSpecifier) {
  293. b.Append('[');
  294. if (rank < 0)
  295. b.Append('`', -rank);
  296. else
  297. b.Append(',', rank);
  298. b.Append(']');
  299. }
  300. }
  301. return b.ToString();
  302. }
  303. public static bool AreEqualReferences(TypeReference a, TypeReference b)
  304. {
  305. if (a == b) return true;
  306. if (a == null || b == null) return false;
  307. if (a is InnerClassTypeReference) a = ((InnerClassTypeReference)a).CombineToNormalTypeReference();
  308. if (b is InnerClassTypeReference) b = ((InnerClassTypeReference)b).CombineToNormalTypeReference();
  309. if (a.type != b.type) return false;
  310. if (a.IsKeyword != b.IsKeyword) return false;
  311. if (a.IsGlobal != b.IsGlobal) return false;
  312. if (a.pointerNestingLevel != b.pointerNestingLevel) return false;
  313. if (a.IsArrayType != b.IsArrayType) return false;
  314. if (a.IsArrayType) {
  315. if (a.rankSpecifier.Length != b.rankSpecifier.Length) return false;
  316. for (int i = 0; i < a.rankSpecifier.Length; i++) {
  317. if (a.rankSpecifier[i] != b.rankSpecifier[i]) return false;
  318. }
  319. }
  320. if (a.genericTypes.Count != b.genericTypes.Count) return false;
  321. for (int i = 0; i < a.genericTypes.Count; i++) {
  322. if (!AreEqualReferences(a.genericTypes[i], b.genericTypes[i]))
  323. return false;
  324. }
  325. return true;
  326. }
  327. }
  328. internal sealed class NullTypeReference : TypeReference
  329. {
  330. public static readonly NullTypeReference Instance = new NullTypeReference();
  331. public override bool IsNull {
  332. get {
  333. return true;
  334. }
  335. }
  336. public override TypeReference Clone()
  337. {
  338. return this;
  339. }
  340. public override object AcceptVisitor(IAstVisitor visitor, object data)
  341. {
  342. return null;
  343. }
  344. public override string ToString()
  345. {
  346. return String.Format("[NullTypeReference]");
  347. }
  348. }
  349. /// <summary>
  350. /// We need this special type reference for cases like
  351. /// OuterClass(Of T1).InnerClass(Of T2) (in expression or type context)
  352. /// or Dictionary(Of String, NamespaceStruct).KeyCollection (in type context, otherwise it's a
  353. /// MemberReferenceExpression)
  354. /// </summary>
  355. public class InnerClassTypeReference: TypeReference
  356. {
  357. TypeReference baseType;
  358. public TypeReference BaseType {
  359. get { return baseType; }
  360. set { baseType = value; }
  361. }
  362. public override TypeReference Clone()
  363. {
  364. InnerClassTypeReference c = new InnerClassTypeReference(baseType.Clone(), Type, new List<TypeReference>());
  365. CopyFields(this, c);
  366. return c;
  367. }
  368. public InnerClassTypeReference(TypeReference outerClass, string innerType, List<TypeReference> innerGenericTypes)
  369. : base(innerType, innerGenericTypes)
  370. {
  371. this.baseType = outerClass;
  372. }
  373. public override object AcceptVisitor(IAstVisitor visitor, object data)
  374. {
  375. return visitor.VisitInnerClassTypeReference(this, data);
  376. }
  377. /// <summary>
  378. /// Creates a type reference where all type parameters are specified for the innermost class.
  379. /// Namespace.OuterClass(of string).InnerClass(of integer).InnerInnerClass
  380. /// becomes Namespace.OuterClass.InnerClass.InnerInnerClass(of string, integer)
  381. /// </summary>
  382. public TypeReference CombineToNormalTypeReference()
  383. {
  384. TypeReference tr = (baseType is InnerClassTypeReference)
  385. ? ((InnerClassTypeReference)baseType).CombineToNormalTypeReference()
  386. : baseType.Clone();
  387. CopyFields(this, tr);
  388. tr.Type += "." + Type;
  389. return tr;
  390. }
  391. public override string ToString()
  392. {
  393. return "[InnerClassTypeReference: (" + baseType.ToString() + ")." + base.ToString() + "]";
  394. }
  395. }
  396. }