Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory-5.5.0/TypeSystem/ParameterizedType.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 14.8 KB
Line 
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 System.Collections.ObjectModel;
22using System.Diagnostics;
23using System.Linq;
24using System.Text;
25
26using ICSharpCode.NRefactory.TypeSystem.Implementation;
27
28namespace ICSharpCode.NRefactory.TypeSystem
29{
30  /// <summary>
31  /// ParameterizedType represents an instance of a generic type.
32  /// Example: List&lt;string&gt;
33  /// </summary>
34  /// <remarks>
35  /// When getting the members, this type modifies the lists so that
36  /// type parameters in the signatures of the members are replaced with
37  /// the type arguments.
38  /// </remarks>
39  [Serializable]
40  public sealed class ParameterizedType : IType, ICompilationProvider
41  {
42    readonly ITypeDefinition genericType;
43    readonly IType[] typeArguments;
44   
45    public ParameterizedType(ITypeDefinition genericType, IEnumerable<IType> typeArguments)
46    {
47      if (genericType == null)
48        throw new ArgumentNullException("genericType");
49      if (typeArguments == null)
50        throw new ArgumentNullException("typeArguments");
51      this.genericType = genericType;
52      this.typeArguments = typeArguments.ToArray(); // copy input array to ensure it isn't modified
53      if (this.typeArguments.Length == 0)
54        throw new ArgumentException("Cannot use ParameterizedType with 0 type arguments.");
55      if (genericType.TypeParameterCount != this.typeArguments.Length)
56        throw new ArgumentException("Number of type arguments must match the type definition's number of type parameters");
57      for (int i = 0; i < this.typeArguments.Length; i++) {
58        if (this.typeArguments[i] == null)
59          throw new ArgumentNullException("typeArguments[" + i + "]");
60        ICompilationProvider p = this.typeArguments[i] as ICompilationProvider;
61        if (p != null && p.Compilation != genericType.Compilation)
62          throw new InvalidOperationException("Cannot parameterize a type with type arguments from a different compilation.");
63      }
64    }
65   
66    /// <summary>
67    /// Fast internal version of the constructor. (no safety checks)
68    /// Keeps the array that was passed and assumes it won't be modified.
69    /// </summary>
70    internal ParameterizedType(ITypeDefinition genericType, IType[] typeArguments)
71    {
72      Debug.Assert(genericType.TypeParameterCount == typeArguments.Length);
73      this.genericType = genericType;
74      this.typeArguments = typeArguments;
75    }
76   
77    public TypeKind Kind {
78      get { return genericType.Kind; }
79    }
80   
81    public ICompilation Compilation {
82      get { return genericType.Compilation; }
83    }
84   
85    public bool? IsReferenceType {
86      get { return genericType.IsReferenceType; }
87    }
88   
89    public IType DeclaringType {
90      get {
91        ITypeDefinition declaringTypeDef = genericType.DeclaringTypeDefinition;
92        if (declaringTypeDef != null && declaringTypeDef.TypeParameterCount > 0
93            && declaringTypeDef.TypeParameterCount <= genericType.TypeParameterCount)
94        {
95          IType[] newTypeArgs = new IType[declaringTypeDef.TypeParameterCount];
96          Array.Copy(this.typeArguments, 0, newTypeArgs, 0, newTypeArgs.Length);
97          return new ParameterizedType(declaringTypeDef, newTypeArgs);
98        }
99        return declaringTypeDef;
100      }
101    }
102   
103    public int TypeParameterCount {
104      get { return typeArguments.Length; }
105    }
106   
107    public string FullName {
108      get { return genericType.FullName; }
109    }
110   
111    public string Name {
112      get { return genericType.Name; }
113    }
114   
115    public string Namespace {
116      get { return genericType.Namespace; }
117    }
118   
119    public string ReflectionName {
120      get {
121        StringBuilder b = new StringBuilder(genericType.ReflectionName);
122        b.Append('[');
123        for (int i = 0; i < typeArguments.Length; i++) {
124          if (i > 0)
125            b.Append(',');
126          b.Append('[');
127          b.Append(typeArguments[i].ReflectionName);
128          b.Append(']');
129        }
130        b.Append(']');
131        return b.ToString();
132      }
133    }
134   
135    public override string ToString()
136    {
137      return ReflectionName;
138    }
139   
140    public IList<IType> TypeArguments {
141      get {
142        return typeArguments;
143      }
144    }
145
146    public bool IsParameterized {
147      get {
148        return true;
149      }
150    }
151
152    /// <summary>
153    /// Same as 'parameterizedType.TypeArguments[index]', but is a bit more efficient (doesn't require the read-only wrapper).
154    /// </summary>
155    public IType GetTypeArgument(int index)
156    {
157      return typeArguments[index];
158    }
159   
160    /// <summary>
161    /// Gets the definition of the generic type.
162    /// For <c>ParameterizedType</c>, this method never returns null.
163    /// </summary>
164    public ITypeDefinition GetDefinition()
165    {
166      return genericType;
167    }
168   
169    public ITypeReference ToTypeReference()
170    {
171      return new ParameterizedTypeReference(genericType.ToTypeReference(), typeArguments.Select(t => t.ToTypeReference()));
172    }
173   
174    /// <summary>
175    /// Gets a type visitor that performs the substitution of class type parameters with the type arguments
176    /// of this parameterized type.
177    /// </summary>
178    public TypeParameterSubstitution GetSubstitution()
179    {
180      return new TypeParameterSubstitution(typeArguments, null);
181    }
182   
183    /// <summary>
184    /// Gets a type visitor that performs the substitution of class type parameters with the type arguments
185    /// of this parameterized type,
186    /// and also substitutes method type parameters with the specified method type arguments.
187    /// </summary>
188    public TypeParameterSubstitution GetSubstitution(IList<IType> methodTypeArguments)
189    {
190      return new TypeParameterSubstitution(typeArguments, methodTypeArguments);
191    }
192   
193    public IEnumerable<IType> DirectBaseTypes {
194      get {
195        var substitution = GetSubstitution();
196        return genericType.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution));
197      }
198    }
199   
200    public IEnumerable<IType> GetNestedTypes(Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None)
201    {
202      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
203        return genericType.GetNestedTypes(filter, options);
204      else
205        return GetMembersHelper.GetNestedTypes(this, filter, options);
206    }
207   
208    public IEnumerable<IType> GetNestedTypes(IList<IType> typeArguments, Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None)
209    {
210      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
211        return genericType.GetNestedTypes(typeArguments, filter, options);
212      else
213        return GetMembersHelper.GetNestedTypes(this, typeArguments, filter, options);
214    }
215   
216    public IEnumerable<IMethod> GetConstructors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
217    {
218      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
219        return genericType.GetConstructors(filter, options);
220      else
221        return GetMembersHelper.GetConstructors(this, filter, options);
222    }
223   
224    public IEnumerable<IMethod> GetMethods(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
225    {
226      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
227        return genericType.GetMethods(filter, options);
228      else
229        return GetMembersHelper.GetMethods(this, filter, options);
230    }
231   
232    public IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
233    {
234      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
235        return genericType.GetMethods(typeArguments, filter, options);
236      else
237        return GetMembersHelper.GetMethods(this, typeArguments, filter, options);
238    }
239   
240    public IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
241    {
242      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
243        return genericType.GetProperties(filter, options);
244      else
245        return GetMembersHelper.GetProperties(this, filter, options);
246    }
247   
248    public IEnumerable<IField> GetFields(Predicate<IUnresolvedField> filter = null, GetMemberOptions options = GetMemberOptions.None)
249    {
250      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
251        return genericType.GetFields(filter, options);
252      else
253        return GetMembersHelper.GetFields(this, filter, options);
254    }
255   
256    public IEnumerable<IEvent> GetEvents(Predicate<IUnresolvedEvent> filter = null, GetMemberOptions options = GetMemberOptions.None)
257    {
258      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
259        return genericType.GetEvents(filter, options);
260      else
261        return GetMembersHelper.GetEvents(this, filter, options);
262    }
263   
264    public IEnumerable<IMember> GetMembers(Predicate<IUnresolvedMember> filter = null, GetMemberOptions options = GetMemberOptions.None)
265    {
266      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
267        return genericType.GetMembers(filter, options);
268      else
269        return GetMembersHelper.GetMembers(this, filter, options);
270    }
271   
272    public IEnumerable<IMethod> GetAccessors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
273    {
274      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions)
275        return genericType.GetAccessors(filter, options);
276      else
277        return GetMembersHelper.GetAccessors(this, filter, options);
278    }
279   
280    public override bool Equals(object obj)
281    {
282      return Equals(obj as IType);
283    }
284   
285    public bool Equals(IType other)
286    {
287      ParameterizedType c = other as ParameterizedType;
288      if (c == null || !genericType.Equals(c.genericType) || typeArguments.Length != c.typeArguments.Length)
289        return false;
290      for (int i = 0; i < typeArguments.Length; i++) {
291        if (!typeArguments[i].Equals(c.typeArguments[i]))
292          return false;
293      }
294      return true;
295    }
296   
297    public override int GetHashCode()
298    {
299      int hashCode = genericType.GetHashCode();
300      unchecked {
301        foreach (var ta in typeArguments) {
302          hashCode *= 1000000007;
303          hashCode += 1000000009 * ta.GetHashCode();
304        }
305      }
306      return hashCode;
307    }
308   
309    public IType AcceptVisitor(TypeVisitor visitor)
310    {
311      return visitor.VisitParameterizedType(this);
312    }
313   
314    public IType VisitChildren(TypeVisitor visitor)
315    {
316      IType g = genericType.AcceptVisitor(visitor);
317      ITypeDefinition def = g as ITypeDefinition;
318      if (def == null)
319        return g;
320      // Keep ta == null as long as no elements changed, allocate the array only if necessary.
321      IType[] ta = (g != genericType) ? new IType[typeArguments.Length] : null;
322      for (int i = 0; i < typeArguments.Length; i++) {
323        IType r = typeArguments[i].AcceptVisitor(visitor);
324        if (r == null)
325          throw new NullReferenceException("TypeVisitor.Visit-method returned null");
326        if (ta == null && r != typeArguments[i]) {
327          // we found a difference, so we need to allocate the array
328          ta = new IType[typeArguments.Length];
329          for (int j = 0; j < i; j++) {
330            ta[j] = typeArguments[j];
331          }
332        }
333        if (ta != null)
334          ta[i] = r;
335      }
336      if (def == genericType && ta == null)
337        return this;
338      else
339        return new ParameterizedType(def, ta ?? typeArguments);
340    }
341  }
342 
343  /// <summary>
344  /// ParameterizedTypeReference is a reference to generic class that specifies the type parameters.
345  /// Example: List&lt;string&gt;
346  /// </summary>
347  [Serializable]
348  public sealed class ParameterizedTypeReference : ITypeReference, ISupportsInterning
349  {
350    readonly ITypeReference genericType;
351    readonly ITypeReference[] typeArguments;
352   
353    public ParameterizedTypeReference(ITypeReference genericType, IEnumerable<ITypeReference> typeArguments)
354    {
355      if (genericType == null)
356        throw new ArgumentNullException("genericType");
357      if (typeArguments == null)
358        throw new ArgumentNullException("typeArguments");
359      this.genericType = genericType;
360      this.typeArguments = typeArguments.ToArray();
361      for (int i = 0; i < this.typeArguments.Length; i++) {
362        if (this.typeArguments[i] == null)
363          throw new ArgumentNullException("typeArguments[" + i + "]");
364      }
365    }
366   
367    public ITypeReference GenericType {
368      get { return genericType; }
369    }
370   
371    public ReadOnlyCollection<ITypeReference> TypeArguments {
372      get {
373        return Array.AsReadOnly(typeArguments);
374      }
375    }
376   
377    public IType Resolve(ITypeResolveContext context)
378    {
379      IType baseType = genericType.Resolve(context);
380      ITypeDefinition baseTypeDef = baseType.GetDefinition();
381      if (baseTypeDef == null)
382        return baseType;
383      int tpc = baseTypeDef.TypeParameterCount;
384      if (tpc == 0)
385        return baseTypeDef;
386      IType[] resolvedTypes = new IType[tpc];
387      for (int i = 0; i < resolvedTypes.Length; i++) {
388        if (i < typeArguments.Length)
389          resolvedTypes[i] = typeArguments[i].Resolve(context);
390        else
391          resolvedTypes[i] = SpecialType.UnknownType;
392      }
393      return new ParameterizedType(baseTypeDef, resolvedTypes);
394    }
395   
396    public override string ToString()
397    {
398      StringBuilder b = new StringBuilder(genericType.ToString());
399      b.Append('[');
400      for (int i = 0; i < typeArguments.Length; i++) {
401        if (i > 0)
402          b.Append(',');
403        b.Append('[');
404        b.Append(typeArguments[i].ToString());
405        b.Append(']');
406      }
407      b.Append(']');
408      return b.ToString();
409    }
410   
411    int ISupportsInterning.GetHashCodeForInterning()
412    {
413      int hashCode = genericType.GetHashCode();
414      unchecked {
415        foreach (ITypeReference t in typeArguments) {
416          hashCode *= 27;
417          hashCode += t.GetHashCode();
418        }
419      }
420      return hashCode;
421    }
422   
423    bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
424    {
425      ParameterizedTypeReference o = other as ParameterizedTypeReference;
426      if (o != null && genericType == o.genericType && typeArguments.Length == o.typeArguments.Length) {
427        for (int i = 0; i < typeArguments.Length; i++) {
428          if (typeArguments[i] != o.typeArguments[i])
429            return false;
430        }
431        return true;
432      }
433      return false;
434    }
435  }
436}
Note: See TracBrowser for help on using the repository browser.