/NRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs

http://github.com/icsharpcode/ILSpy · C# · 200 lines · 148 code · 28 blank · 24 comment · 39 complexity · 3fa0fff4b3ac4cc40e9d9a58e831e64a MD5 · raw file

  1. // Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4. // software and associated documentation files (the "Software"), to deal in the Software
  5. // without restriction, including without limitation the rights to use, copy, modify, merge,
  6. // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7. // to whom the Software is furnished to do so, subject to the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be included in all copies or
  10. // substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  13. // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  14. // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
  15. // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  16. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  17. // DEALINGS IN THE SOFTWARE.
  18. using System;
  19. using System.Collections.Generic;
  20. using ICSharpCode.NRefactory.TypeSystem.Implementation;
  21. namespace ICSharpCode.NRefactory.TypeSystem
  22. {
  23. /// <summary>
  24. /// Represents an array type.
  25. /// </summary>
  26. public sealed class ArrayType : TypeWithElementType, ICompilationProvider
  27. {
  28. readonly int dimensions;
  29. readonly ICompilation compilation;
  30. public ArrayType(ICompilation compilation, IType elementType, int dimensions = 1) : base(elementType)
  31. {
  32. if (compilation == null)
  33. throw new ArgumentNullException("compilation");
  34. if (dimensions <= 0)
  35. throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive");
  36. this.compilation = compilation;
  37. this.dimensions = dimensions;
  38. ICompilationProvider p = elementType as ICompilationProvider;
  39. if (p != null && p.Compilation != compilation)
  40. throw new InvalidOperationException("Cannot create an array type using a different compilation from the element type.");
  41. }
  42. public override TypeKind Kind {
  43. get { return TypeKind.Array; }
  44. }
  45. public ICompilation Compilation {
  46. get { return compilation; }
  47. }
  48. public int Dimensions {
  49. get { return dimensions; }
  50. }
  51. public override string NameSuffix {
  52. get {
  53. return "[" + new string(',', dimensions-1) + "]";
  54. }
  55. }
  56. public override bool? IsReferenceType {
  57. get { return true; }
  58. }
  59. public override int GetHashCode()
  60. {
  61. return unchecked(elementType.GetHashCode() * 71681 + dimensions);
  62. }
  63. public override bool Equals(IType other)
  64. {
  65. ArrayType a = other as ArrayType;
  66. return a != null && elementType.Equals(a.elementType) && a.dimensions == dimensions;
  67. }
  68. public override ITypeReference ToTypeReference()
  69. {
  70. return new ArrayTypeReference(elementType.ToTypeReference(), dimensions);
  71. }
  72. public override IEnumerable<IType> DirectBaseTypes {
  73. get {
  74. List<IType> baseTypes = new List<IType>();
  75. IType t = compilation.FindType(KnownTypeCode.Array);
  76. if (t.Kind != TypeKind.Unknown)
  77. baseTypes.Add(t);
  78. if (dimensions == 1 && elementType.Kind != TypeKind.Pointer) {
  79. // single-dimensional arrays implement IList<T>
  80. ITypeDefinition def = compilation.FindType(KnownTypeCode.IListOfT) as ITypeDefinition;
  81. if (def != null)
  82. baseTypes.Add(new ParameterizedType(def, new[] { elementType }));
  83. // And in .NET 4.5 they also implement IReadOnlyList<T>
  84. def = compilation.FindType(KnownTypeCode.IReadOnlyListOfT) as ITypeDefinition;
  85. if (def != null)
  86. baseTypes.Add(new ParameterizedType(def, new[] { elementType }));
  87. }
  88. return baseTypes;
  89. }
  90. }
  91. public override IEnumerable<IMethod> GetMethods(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
  92. {
  93. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  94. return EmptyList<IMethod>.Instance;
  95. else
  96. return compilation.FindType(KnownTypeCode.Array).GetMethods(filter, options);
  97. }
  98. public override IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
  99. {
  100. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  101. return EmptyList<IMethod>.Instance;
  102. else
  103. return compilation.FindType(KnownTypeCode.Array).GetMethods(typeArguments, filter, options);
  104. }
  105. public override IEnumerable<IMethod> GetAccessors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
  106. {
  107. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  108. return EmptyList<IMethod>.Instance;
  109. else
  110. return compilation.FindType(KnownTypeCode.Array).GetAccessors(filter, options);
  111. }
  112. public override IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
  113. {
  114. if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
  115. return EmptyList<IProperty>.Instance;
  116. else
  117. return compilation.FindType(KnownTypeCode.Array).GetProperties(filter, options);
  118. }
  119. // NestedTypes, Events, Fields: System.Array doesn't have any; so we can use the AbstractType default implementation
  120. // that simply returns an empty list
  121. public override IType AcceptVisitor(TypeVisitor visitor)
  122. {
  123. return visitor.VisitArrayType(this);
  124. }
  125. public override IType VisitChildren(TypeVisitor visitor)
  126. {
  127. IType e = elementType.AcceptVisitor(visitor);
  128. if (e == elementType)
  129. return this;
  130. else
  131. return new ArrayType(compilation, e, dimensions);
  132. }
  133. }
  134. [Serializable]
  135. public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning
  136. {
  137. readonly ITypeReference elementType;
  138. readonly int dimensions;
  139. public ArrayTypeReference(ITypeReference elementType, int dimensions = 1)
  140. {
  141. if (elementType == null)
  142. throw new ArgumentNullException("elementType");
  143. if (dimensions <= 0)
  144. throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive");
  145. this.elementType = elementType;
  146. this.dimensions = dimensions;
  147. }
  148. public ITypeReference ElementType {
  149. get { return elementType; }
  150. }
  151. public int Dimensions {
  152. get { return dimensions; }
  153. }
  154. public IType Resolve(ITypeResolveContext context)
  155. {
  156. return new ArrayType(context.Compilation, elementType.Resolve(context), dimensions);
  157. }
  158. public override string ToString()
  159. {
  160. return elementType.ToString() + "[" + new string(',', dimensions - 1) + "]";
  161. }
  162. int ISupportsInterning.GetHashCodeForInterning()
  163. {
  164. return elementType.GetHashCode() ^ dimensions;
  165. }
  166. bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
  167. {
  168. ArrayTypeReference o = other as ArrayTypeReference;
  169. return o != null && elementType == o.elementType && dimensions == o.dimensions;
  170. }
  171. }
  172. }