PageRenderTime 25ms CodeModel.GetById 11ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 19using System;
 20using System.Collections.Generic;
 21using ICSharpCode.NRefactory.TypeSystem.Implementation;
 22
 23namespace ICSharpCode.NRefactory.TypeSystem
 24{
 25	/// <summary>
 26	/// Represents an array type.
 27	/// </summary>
 28	public sealed class ArrayType : TypeWithElementType, ICompilationProvider
 29	{
 30		readonly int dimensions;
 31		readonly ICompilation compilation;
 32		
 33		public ArrayType(ICompilation compilation, IType elementType, int dimensions = 1) : base(elementType)
 34		{
 35			if (compilation == null)
 36				throw new ArgumentNullException("compilation");
 37			if (dimensions <= 0)
 38				throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive");
 39			this.compilation = compilation;
 40			this.dimensions = dimensions;
 41			
 42			ICompilationProvider p = elementType as ICompilationProvider;
 43			if (p != null && p.Compilation != compilation)
 44				throw new InvalidOperationException("Cannot create an array type using a different compilation from the element type.");
 45		}
 46		
 47		public override TypeKind Kind {
 48			get { return TypeKind.Array; }
 49		}
 50		
 51		public ICompilation Compilation {
 52			get { return compilation; }
 53		}
 54		
 55		public int Dimensions {
 56			get { return dimensions; }
 57		}
 58		
 59		public override string NameSuffix {
 60			get {
 61				return "[" + new string(',', dimensions-1) + "]";
 62			}
 63		}
 64		
 65		public override bool? IsReferenceType {
 66			get { return true; }
 67		}
 68		
 69		public override int GetHashCode()
 70		{
 71			return unchecked(elementType.GetHashCode() * 71681 + dimensions);
 72		}
 73		
 74		public override bool Equals(IType other)
 75		{
 76			ArrayType a = other as ArrayType;
 77			return a != null && elementType.Equals(a.elementType) && a.dimensions == dimensions;
 78		}
 79		
 80		public override ITypeReference ToTypeReference()
 81		{
 82			return new ArrayTypeReference(elementType.ToTypeReference(), dimensions);
 83		}
 84		
 85		public override IEnumerable<IType> DirectBaseTypes {
 86			get {
 87				List<IType> baseTypes = new List<IType>();
 88				IType t = compilation.FindType(KnownTypeCode.Array);
 89				if (t.Kind != TypeKind.Unknown)
 90					baseTypes.Add(t);
 91				if (dimensions == 1 && elementType.Kind != TypeKind.Pointer) {
 92					// single-dimensional arrays implement IList<T>
 93					ITypeDefinition def = compilation.FindType(KnownTypeCode.IListOfT) as ITypeDefinition;
 94					if (def != null)
 95						baseTypes.Add(new ParameterizedType(def, new[] { elementType }));
 96					// And in .NET 4.5 they also implement IReadOnlyList<T>
 97					def = compilation.FindType(KnownTypeCode.IReadOnlyListOfT) as ITypeDefinition;
 98					if (def != null)
 99						baseTypes.Add(new ParameterizedType(def, new[] { elementType }));
100				}
101				return baseTypes;
102			}
103		}
104		
105		public override IEnumerable<IMethod> GetMethods(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).GetMethods(filter, options);
111		}
112		
113		public override IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
114		{
115			if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
116				return EmptyList<IMethod>.Instance;
117			else
118				return compilation.FindType(KnownTypeCode.Array).GetMethods(typeArguments, filter, options);
119		}
120		
121		public override IEnumerable<IMethod> GetAccessors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
122		{
123			if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
124				return EmptyList<IMethod>.Instance;
125			else
126				return compilation.FindType(KnownTypeCode.Array).GetAccessors(filter, options);
127		}
128		
129		public override IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
130		{
131			if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
132				return EmptyList<IProperty>.Instance;
133			else
134				return compilation.FindType(KnownTypeCode.Array).GetProperties(filter, options);
135		}
136		
137		// NestedTypes, Events, Fields: System.Array doesn't have any; so we can use the AbstractType default implementation
138		// that simply returns an empty list
139		
140		public override IType AcceptVisitor(TypeVisitor visitor)
141		{
142			return visitor.VisitArrayType(this);
143		}
144		
145		public override IType VisitChildren(TypeVisitor visitor)
146		{
147			IType e = elementType.AcceptVisitor(visitor);
148			if (e == elementType)
149				return this;
150			else
151				return new ArrayType(compilation, e, dimensions);
152		}
153	}
154	
155	[Serializable]
156	public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning
157	{
158		readonly ITypeReference elementType;
159		readonly int dimensions;
160		
161		public ArrayTypeReference(ITypeReference elementType, int dimensions = 1)
162		{
163			if (elementType == null)
164				throw new ArgumentNullException("elementType");
165			if (dimensions <= 0)
166				throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive");
167			this.elementType = elementType;
168			this.dimensions = dimensions;
169		}
170		
171		public ITypeReference ElementType {
172			get { return elementType; }
173		}
174		
175		public int Dimensions {
176			get { return dimensions; }
177		}
178		
179		public IType Resolve(ITypeResolveContext context)
180		{
181			return new ArrayType(context.Compilation, elementType.Resolve(context), dimensions);
182		}
183		
184		public override string ToString()
185		{
186			return elementType.ToString() + "[" + new string(',', dimensions - 1) + "]";
187		}
188		
189		int ISupportsInterning.GetHashCodeForInterning()
190		{
191			return elementType.GetHashCode() ^ dimensions;
192		}
193		
194		bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
195		{
196			ArrayTypeReference o = other as ArrayTypeReference;
197			return o != null && elementType == o.elementType && dimensions == o.dimensions;
198		}
199	}
200}