Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory-5.5.0/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs @ 11937

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

#2077: created branch and added first version

File size: 31.0 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.Linq;
22using ICSharpCode.NRefactory.Documentation;
23using ICSharpCode.NRefactory.Utils;
24
25namespace ICSharpCode.NRefactory.TypeSystem.Implementation
26{
27  /// <summary>
28  /// Default implementation of <see cref="ITypeDefinition"/>.
29  /// </summary>
30  public class DefaultResolvedTypeDefinition : ITypeDefinition
31  {
32    readonly ITypeResolveContext parentContext;
33    readonly IUnresolvedTypeDefinition[] parts;
34    Accessibility accessibility = Accessibility.Internal;
35    bool isAbstract, isSealed, isShadowing;
36    bool isSynthetic = true; // true if all parts are synthetic
37   
38    public DefaultResolvedTypeDefinition(ITypeResolveContext parentContext, params IUnresolvedTypeDefinition[] parts)
39    {
40      if (parentContext == null || parentContext.CurrentAssembly == null)
41        throw new ArgumentException("Parent context does not specify any assembly", "parentContext");
42      if (parts == null || parts.Length == 0)
43        throw new ArgumentException("No parts were specified", "parts");
44      this.parentContext = parentContext;
45      this.parts = parts;
46     
47      foreach (IUnresolvedTypeDefinition part in parts) {
48        isAbstract  |= part.IsAbstract;
49        isSealed    |= part.IsSealed;
50        isShadowing |= part.IsShadowing;
51        isSynthetic &= part.IsSynthetic; // true if all parts are synthetic
52       
53        // internal is the default, so use another part's accessibility until we find a non-internal accessibility
54        if (accessibility == Accessibility.Internal)
55          accessibility = part.Accessibility;
56      }
57    }
58   
59    IList<ITypeParameter> typeParameters;
60   
61    public IList<ITypeParameter> TypeParameters {
62      get {
63        var result = LazyInit.VolatileRead(ref this.typeParameters);
64        if (result != null) {
65          return result;
66        }
67        ITypeResolveContext contextForTypeParameters = parts[0].CreateResolveContext(parentContext);
68        contextForTypeParameters = contextForTypeParameters.WithCurrentTypeDefinition(this);
69        if (parentContext.CurrentTypeDefinition == null || parentContext.CurrentTypeDefinition.TypeParameterCount == 0) {
70          result = parts[0].TypeParameters.CreateResolvedTypeParameters(contextForTypeParameters);
71        } else {
72          // This is a nested class inside a generic class; copy type parameters from outer class if we can:
73          var outerClass = parentContext.CurrentTypeDefinition;
74          ITypeParameter[] typeParameters = new ITypeParameter[parts[0].TypeParameters.Count];
75          for (int i = 0; i < typeParameters.Length; i++) {
76            var unresolvedTP = parts[0].TypeParameters[i];
77            if (i < outerClass.TypeParameterCount && outerClass.TypeParameters[i].Name == unresolvedTP.Name)
78              typeParameters[i] = outerClass.TypeParameters[i];
79            else
80              typeParameters[i] = unresolvedTP.CreateResolvedTypeParameter(contextForTypeParameters);
81          }
82          result = Array.AsReadOnly(typeParameters);
83        }
84        return LazyInit.GetOrSet(ref this.typeParameters, result);
85      }
86    }
87   
88    IList<IAttribute> attributes;
89   
90    public IList<IAttribute> Attributes {
91      get {
92        var result = LazyInit.VolatileRead(ref this.attributes);
93        if (result != null) {
94          return result;
95        }
96        result = new List<IAttribute>();
97        var context = parentContext.WithCurrentTypeDefinition(this);
98        foreach (IUnresolvedTypeDefinition part in parts) {
99          ITypeResolveContext parentContextForPart = part.CreateResolveContext(context);
100          foreach (var attr in part.Attributes) {
101            result.Add(attr.CreateResolvedAttribute(parentContextForPart));
102          }
103        }
104        if (result.Count == 0)
105          result = EmptyList<IAttribute>.Instance;
106        return LazyInit.GetOrSet(ref this.attributes, result);
107      }
108    }
109   
110    public IList<IUnresolvedTypeDefinition> Parts {
111      get { return parts; }
112    }
113   
114    public SymbolKind SymbolKind {
115      get { return parts[0].SymbolKind; }
116    }
117   
118    [Obsolete("Use the SymbolKind property instead.")]
119    public EntityType EntityType {
120      get { return (EntityType)parts[0].SymbolKind; }
121    }
122   
123    public virtual TypeKind Kind {
124      get { return parts[0].Kind; }
125    }
126   
127    #region NestedTypes
128    IList<ITypeDefinition> nestedTypes;
129   
130    public IList<ITypeDefinition> NestedTypes {
131      get {
132        IList<ITypeDefinition> result = LazyInit.VolatileRead(ref this.nestedTypes);
133        if (result != null) {
134          return result;
135        } else {
136          result = (
137            from part in parts
138            from nestedTypeRef in part.NestedTypes
139            group nestedTypeRef by new { nestedTypeRef.Name, nestedTypeRef.TypeParameters.Count } into g
140            select new DefaultResolvedTypeDefinition(new SimpleTypeResolveContext(this), g.ToArray())
141          ).ToList<ITypeDefinition>().AsReadOnly();
142          return LazyInit.GetOrSet(ref this.nestedTypes, result);
143        }
144      }
145    }
146    #endregion
147   
148    #region Members
149    sealed class MemberList : IList<IMember>
150    {
151      internal readonly ITypeResolveContext[] contextPerMember;
152      internal readonly IUnresolvedMember[] unresolvedMembers;
153      internal readonly IMember[] resolvedMembers;
154      internal readonly int NonPartialMemberCount;
155     
156      public MemberList(List<ITypeResolveContext> contextPerMember, List<IUnresolvedMember> unresolvedNonPartialMembers, List<PartialMethodInfo> partialMethodInfos)
157      {
158        this.NonPartialMemberCount = unresolvedNonPartialMembers.Count;
159        this.contextPerMember = contextPerMember.ToArray();
160        this.unresolvedMembers = unresolvedNonPartialMembers.ToArray();
161        if (partialMethodInfos == null) {
162          this.resolvedMembers = new IMember[unresolvedNonPartialMembers.Count];
163        } else {
164          this.resolvedMembers = new IMember[unresolvedNonPartialMembers.Count + partialMethodInfos.Count];
165          for (int i = 0; i < partialMethodInfos.Count; i++) {
166            var info = partialMethodInfos[i];
167            int memberIndex = NonPartialMemberCount + i;
168            resolvedMembers[memberIndex] = DefaultResolvedMethod.CreateFromMultipleParts(
169              info.Parts.ToArray(), info.Contexts.ToArray (), false);
170          }
171        }
172      }
173     
174      public IMember this[int index] {
175        get {
176          IMember output = LazyInit.VolatileRead(ref resolvedMembers[index]);
177          if (output != null) {
178            return output;
179          }
180          return LazyInit.GetOrSet(ref resolvedMembers[index], unresolvedMembers[index].CreateResolved(contextPerMember[index]));
181        }
182        set { throw new NotSupportedException(); }
183      }
184     
185      public int Count {
186        get { return resolvedMembers.Length; }
187      }
188     
189      bool ICollection<IMember>.IsReadOnly {
190        get { return true; }
191      }
192     
193      public int IndexOf(IMember item)
194      {
195        for (int i = 0; i < this.Count; i++) {
196          if (this[i].Equals(item))
197            return i;
198        }
199        return -1;
200      }
201     
202      void IList<IMember>.Insert(int index, IMember item)
203      {
204        throw new NotSupportedException();
205      }
206     
207      void IList<IMember>.RemoveAt(int index)
208      {
209        throw new NotSupportedException();
210      }
211     
212      void ICollection<IMember>.Add(IMember item)
213      {
214        throw new NotSupportedException();
215      }
216     
217      void ICollection<IMember>.Clear()
218      {
219        throw new NotSupportedException();
220      }
221     
222      bool ICollection<IMember>.Contains(IMember item)
223      {
224        return IndexOf(item) >= 0;
225      }
226     
227      void ICollection<IMember>.CopyTo(IMember[] array, int arrayIndex)
228      {
229        for (int i = 0; i < this.Count; i++) {
230          array[arrayIndex + i] = this[i];
231        }
232      }
233     
234      bool ICollection<IMember>.Remove(IMember item)
235      {
236        throw new NotSupportedException();
237      }
238     
239      public IEnumerator<IMember> GetEnumerator()
240      {
241        for (int i = 0; i < this.Count; i++) {
242          yield return this[i];
243        }
244      }
245     
246      System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
247      {
248        return GetEnumerator();
249      }
250    }
251   
252    sealed class PartialMethodInfo
253    {
254      public readonly string Name;
255      public readonly int TypeParameterCount;
256      public readonly IList<IParameter> Parameters;
257      public readonly List<IUnresolvedMethod> Parts = new List<IUnresolvedMethod>();
258      public readonly List<ITypeResolveContext> Contexts = new List<ITypeResolveContext>();
259
260      public PartialMethodInfo(IUnresolvedMethod method, ITypeResolveContext context)
261      {
262        this.Name = method.Name;
263        this.TypeParameterCount = method.TypeParameters.Count;
264        this.Parameters = method.Parameters.CreateResolvedParameters(context);
265        this.Parts.Add(method);
266        this.Contexts.Add (context);
267      }
268     
269      public void AddPart(IUnresolvedMethod method, ITypeResolveContext context)
270      {
271        if (method.HasBody) {
272          // make the implementation the primary part
273          this.Parts.Insert(0, method);
274          this.Contexts.Insert (0, context);
275        } else {
276          this.Parts.Add(method);
277          this.Contexts.Add (context);
278        }
279      }
280     
281      public bool IsSameSignature(PartialMethodInfo other, StringComparer nameComparer)
282      {
283        return nameComparer.Equals(this.Name, other.Name)
284          && this.TypeParameterCount == other.TypeParameterCount
285          && ParameterListComparer.Instance.Equals(this.Parameters, other.Parameters);
286      }
287    }
288   
289    MemberList memberList;
290   
291    MemberList GetMemberList()
292    {
293      var result = LazyInit.VolatileRead(ref this.memberList);
294      if (result != null) {
295        return result;
296      }
297      List<IUnresolvedMember> unresolvedMembers = new List<IUnresolvedMember>();
298      List<ITypeResolveContext> contextPerMember = new List<ITypeResolveContext>();
299      List<PartialMethodInfo> partialMethodInfos = null;
300      bool addDefaultConstructorIfRequired = false;
301      foreach (IUnresolvedTypeDefinition part in parts) {
302        ITypeResolveContext parentContextForPart = part.CreateResolveContext(parentContext);
303        ITypeResolveContext contextForPart = parentContextForPart.WithCurrentTypeDefinition(this);
304        foreach (var member in part.Members) {
305          IUnresolvedMethod method = member as IUnresolvedMethod;
306          if (method != null && method.IsPartial) {
307            // Merge partial method declaration and implementation
308            if (partialMethodInfos == null)
309              partialMethodInfos = new List<PartialMethodInfo>();
310            PartialMethodInfo newInfo = new PartialMethodInfo(method, contextForPart);
311            PartialMethodInfo existingInfo = null;
312            foreach (var info in partialMethodInfos) {
313              if (newInfo.IsSameSignature(info, Compilation.NameComparer)) {
314                existingInfo = info;
315                break;
316              }
317            }
318            if (existingInfo != null) {
319              // Add the unresolved method to the PartialMethodInfo:
320              existingInfo.AddPart(method, contextForPart);
321            } else {
322              partialMethodInfos.Add(newInfo);
323            }
324          } else {
325            unresolvedMembers.Add(member);
326            contextPerMember.Add(contextForPart);
327          }
328        }
329       
330        addDefaultConstructorIfRequired |= part.AddDefaultConstructorIfRequired;
331      }
332      if (addDefaultConstructorIfRequired) {
333        TypeKind kind = this.Kind;
334        if (kind == TypeKind.Class && !this.IsStatic && !unresolvedMembers.Any(m => m.SymbolKind == SymbolKind.Constructor && !m.IsStatic)
335            || kind == TypeKind.Enum || kind == TypeKind.Struct)
336        {
337          contextPerMember.Add(parts[0].CreateResolveContext(parentContext).WithCurrentTypeDefinition(this));
338          unresolvedMembers.Add(DefaultUnresolvedMethod.CreateDefaultConstructor(parts[0]));
339        }
340      }
341      result = new MemberList(contextPerMember, unresolvedMembers, partialMethodInfos);
342      return LazyInit.GetOrSet(ref this.memberList, result);
343    }
344   
345    public IList<IMember> Members {
346      get { return GetMemberList(); }
347    }
348   
349    public IEnumerable<IField> Fields {
350      get {
351        var members = GetMemberList();
352        for (int i = 0; i < members.unresolvedMembers.Length; i++) {
353          if (members.unresolvedMembers[i].SymbolKind == SymbolKind.Field)
354            yield return (IField)members[i];
355        }
356      }
357    }
358   
359    public IEnumerable<IMethod> Methods {
360      get {
361        var members = GetMemberList();
362        for (int i = 0; i < members.unresolvedMembers.Length; i++) {
363          if (members.unresolvedMembers[i] is IUnresolvedMethod)
364            yield return (IMethod)members[i];
365        }
366        for (int i = members.unresolvedMembers.Length; i < members.Count; i++) {
367          yield return (IMethod)members[i];
368        }
369      }
370    }
371   
372    public IEnumerable<IProperty> Properties {
373      get {
374        var members = GetMemberList();
375        for (int i = 0; i < members.unresolvedMembers.Length; i++) {
376          switch (members.unresolvedMembers[i].SymbolKind) {
377            case SymbolKind.Property:
378            case SymbolKind.Indexer:
379              yield return (IProperty)members[i];
380              break;
381          }
382        }
383      }
384    }
385   
386    public IEnumerable<IEvent> Events {
387      get {
388        var members = GetMemberList();
389        for (int i = 0; i < members.unresolvedMembers.Length; i++) {
390          if (members.unresolvedMembers[i].SymbolKind == SymbolKind.Event)
391            yield return (IEvent)members[i];
392        }
393      }
394    }
395    #endregion
396   
397    volatile KnownTypeCode knownTypeCode = (KnownTypeCode)(-1);
398   
399    public KnownTypeCode KnownTypeCode {
400      get {
401        KnownTypeCode result = this.knownTypeCode;
402        if (result == (KnownTypeCode)(-1)) {
403          result = KnownTypeCode.None;
404          ICompilation compilation = this.Compilation;
405          for (int i = 0; i < KnownTypeReference.KnownTypeCodeCount; i++) {
406            if (compilation.FindType((KnownTypeCode)i) == this) {
407              result = (KnownTypeCode)i;
408              break;
409            }
410          }
411          this.knownTypeCode = result;
412        }
413        return result;
414      }
415    }
416   
417    volatile IType enumUnderlyingType;
418   
419    public IType EnumUnderlyingType {
420      get {
421        IType result = this.enumUnderlyingType;
422        if (result == null) {
423          if (this.Kind == TypeKind.Enum) {
424            result = CalculateEnumUnderlyingType();
425          } else {
426            result = SpecialType.UnknownType;
427          }
428          this.enumUnderlyingType = result;
429        }
430        return result;
431      }
432    }
433   
434    IType CalculateEnumUnderlyingType()
435    {
436      foreach (var part in parts) {
437        var context = part.CreateResolveContext(parentContext).WithCurrentTypeDefinition(this);
438        foreach (var baseTypeRef in part.BaseTypes) {
439          IType type = baseTypeRef.Resolve(context);
440          if (type.Kind != TypeKind.Unknown)
441            return type;
442        }
443      }
444      return this.Compilation.FindType(KnownTypeCode.Int32);
445    }
446   
447    volatile byte hasExtensionMethods; // 0 = unknown, 1 = true, 2 = false
448   
449    public bool HasExtensionMethods {
450      get {
451        byte val = this.hasExtensionMethods;
452        if (val == 0) {
453          if (CalculateHasExtensionMethods())
454            val = 1;
455          else
456            val = 2;
457          this.hasExtensionMethods = val;
458        }
459        return val == 1;
460      }
461    }
462   
463    bool CalculateHasExtensionMethods()
464    {
465      bool noExtensionMethods = true;
466      foreach (var part in parts) {
467        // Return true if any part has extension methods
468        if (part.HasExtensionMethods == true)
469          return true;
470        if (part.HasExtensionMethods == null)
471          noExtensionMethods = false;
472      }
473      // Return false if all parts are known to have no extension methods
474      if (noExtensionMethods)
475        return false;
476      // If unsure, look at the resolved methods.
477      return Methods.Any(m => m.IsExtensionMethod);
478    }
479   
480    public bool IsPartial {
481      get { return parts.Length > 1 || parts[0].IsPartial; }
482    }
483   
484    public bool? IsReferenceType {
485      get {
486        switch (this.Kind) {
487          case TypeKind.Class:
488          case TypeKind.Interface:
489          case TypeKind.Module:
490          case TypeKind.Delegate:
491            return true;
492          case TypeKind.Struct:
493          case TypeKind.Enum:
494          case TypeKind.Void:
495            return false;
496          default:
497            throw new InvalidOperationException("Invalid value for TypeKind");
498        }
499      }
500    }
501   
502    public int TypeParameterCount {
503      get { return parts[0].TypeParameters.Count; }
504    }
505
506    public IList<IType> TypeArguments {
507      get {
508        // ToList() call is necessary because IList<> isn't covariant
509        return TypeParameters.ToList<IType>();
510      }
511    }
512
513    public bool IsParameterized {
514      get { return false; }
515    }
516
517    #region DirectBaseTypes
518    IList<IType> directBaseTypes;
519   
520    public IEnumerable<IType> DirectBaseTypes {
521      get {
522        IList<IType> result = LazyInit.VolatileRead(ref this.directBaseTypes);
523        if (result != null) {
524          return result;
525        }
526        using (var busyLock = BusyManager.Enter(this)) {
527          if (busyLock.Success) {
528            result = CalculateDirectBaseTypes();
529            return LazyInit.GetOrSet(ref this.directBaseTypes, result);
530          } else {
531            // This can happen for "class Test : $Test.Base$ { public class Base {} }"
532            // and also for the valid code
533            // "class Test : Base<Test.Inner> { public class Inner {} }"
534           
535            // Don't cache the error!
536            return EmptyList<IType>.Instance;
537          }
538        }
539      }
540    }
541   
542    IList<IType> CalculateDirectBaseTypes()
543    {
544      List<IType> result = new List<IType>();
545      bool hasNonInterface = false;
546      if (this.Kind != TypeKind.Enum) {
547        foreach (var part in parts) {
548          var context = part.CreateResolveContext(parentContext).WithCurrentTypeDefinition(this);
549          foreach (var baseTypeRef in part.BaseTypes) {
550            IType baseType = baseTypeRef.Resolve(context);
551            if (!(baseType.Kind == TypeKind.Unknown || result.Contains(baseType))) {
552              result.Add(baseType);
553              if (baseType.Kind != TypeKind.Interface)
554                hasNonInterface = true;
555            }
556          }
557        }
558      }
559      if (!hasNonInterface && !(this.Name == "Object" && this.Namespace == "System" && this.TypeParameterCount == 0)) {
560        KnownTypeCode primitiveBaseType;
561        switch (this.Kind) {
562          case TypeKind.Enum:
563            primitiveBaseType = KnownTypeCode.Enum;
564            break;
565          case TypeKind.Struct:
566          case TypeKind.Void:
567            primitiveBaseType = KnownTypeCode.ValueType;
568            break;
569          case TypeKind.Delegate:
570            primitiveBaseType = KnownTypeCode.Delegate;
571            break;
572          default:
573            primitiveBaseType = KnownTypeCode.Object;
574            break;
575        }
576        IType t = parentContext.Compilation.FindType(primitiveBaseType);
577        if (t.Kind != TypeKind.Unknown)
578          result.Add(t);
579      }
580      return result;
581    }
582    #endregion
583   
584    public string FullName {
585      get { return parts[0].FullName; }
586    }
587   
588    public string Name {
589      get { return parts[0].Name; }
590    }
591   
592    public string ReflectionName {
593      get { return parts[0].ReflectionName; }
594    }
595   
596    public string Namespace {
597      get { return parts[0].Namespace; }
598    }
599   
600    public FullTypeName FullTypeName {
601      get { return parts[0].FullTypeName; }
602    }
603   
604    public DomRegion Region {
605      get { return parts[0].Region; }
606    }
607   
608    public DomRegion BodyRegion {
609      get { return parts[0].BodyRegion; }
610    }
611   
612    public ITypeDefinition DeclaringTypeDefinition {
613      get { return parentContext.CurrentTypeDefinition; }
614    }
615   
616    public IType DeclaringType {
617      get { return parentContext.CurrentTypeDefinition; }
618    }
619   
620    public IAssembly ParentAssembly {
621      get { return parentContext.CurrentAssembly; }
622    }
623   
624    public virtual DocumentationComment Documentation {
625      get {
626        foreach (var part in parts) {
627          var unresolvedProvider = part.UnresolvedFile as IUnresolvedDocumentationProvider;
628          if (unresolvedProvider != null) {
629            var doc = unresolvedProvider.GetDocumentation(part, this);
630            if (doc != null)
631              return doc;
632          }
633        }
634        IDocumentationProvider provider = AbstractResolvedEntity.FindDocumentation(parentContext);
635        if (provider != null)
636          return provider.GetDocumentation(this);
637        else
638          return null;
639      }
640    }
641   
642    public ICompilation Compilation {
643      get { return parentContext.Compilation; }
644    }
645   
646    #region Modifiers
647    public bool IsStatic    { get { return isAbstract && isSealed; } }
648    public bool IsAbstract  { get { return isAbstract; } }
649    public bool IsSealed    { get { return isSealed; } }
650    public bool IsShadowing { get { return isShadowing; } }
651    public bool IsSynthetic { get { return isSynthetic; } }
652   
653    public Accessibility Accessibility {
654      get { return accessibility; }
655    }
656   
657    bool IHasAccessibility.IsPrivate {
658      get { return accessibility == Accessibility.Private; }
659    }
660   
661    bool IHasAccessibility.IsPublic {
662      get { return accessibility == Accessibility.Public; }
663    }
664   
665    bool IHasAccessibility.IsProtected {
666      get { return accessibility == Accessibility.Protected; }
667    }
668   
669    bool IHasAccessibility.IsInternal {
670      get { return accessibility == Accessibility.Internal; }
671    }
672   
673    bool IHasAccessibility.IsProtectedOrInternal {
674      get { return accessibility == Accessibility.ProtectedOrInternal; }
675    }
676   
677    bool IHasAccessibility.IsProtectedAndInternal {
678      get { return accessibility == Accessibility.ProtectedAndInternal; }
679    }
680    #endregion
681   
682    ITypeDefinition IType.GetDefinition()
683    {
684      return this;
685    }
686   
687    IType IType.AcceptVisitor(TypeVisitor visitor)
688    {
689      return visitor.VisitTypeDefinition(this);
690    }
691   
692    IType IType.VisitChildren(TypeVisitor visitor)
693    {
694      return this;
695    }
696   
697    public ITypeReference ToTypeReference()
698    {
699      ITypeDefinition declTypeDef = this.DeclaringTypeDefinition;
700      if (declTypeDef != null) {
701        return new NestedTypeReference(declTypeDef.ToTypeReference(), this.Name, this.TypeParameterCount - declTypeDef.TypeParameterCount);
702      } else {
703        IAssembly asm = this.ParentAssembly;
704        IAssemblyReference asmRef;
705        if (asm != null)
706          asmRef = new DefaultAssemblyReference(asm.AssemblyName);
707        else
708          asmRef = null;
709        return new GetClassTypeReference(asmRef, this.Namespace, this.Name, this.TypeParameterCount);
710      }
711    }
712   
713    ISymbolReference ISymbol.ToReference()
714    {
715      return (ISymbolReference)ToTypeReference();
716    }
717   
718    public IEnumerable<IType> GetNestedTypes(Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None)
719    {
720      const GetMemberOptions opt = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;
721      if ((options & opt) == opt) {
722        if (filter == null)
723          return this.NestedTypes;
724        else
725          return GetNestedTypesImpl(filter);
726      } else {
727        return GetMembersHelper.GetNestedTypes(this, filter, options);
728      }
729    }
730   
731    IEnumerable<IType> GetNestedTypesImpl(Predicate<ITypeDefinition> filter)
732    {
733      foreach (var nestedType in this.NestedTypes) {
734        if (filter(nestedType))
735          yield return nestedType;
736      }
737    }
738   
739    public IEnumerable<IType> GetNestedTypes(IList<IType> typeArguments, Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None)
740    {
741      return GetMembersHelper.GetNestedTypes(this, typeArguments, filter, options);
742    }
743   
744    #region GetMembers()
745    IEnumerable<IMember> GetFilteredMembers(Predicate<IUnresolvedMember> filter)
746    {
747      var members = GetMemberList();
748      for (int i = 0; i < members.unresolvedMembers.Length; i++) {
749        if (filter == null || filter(members.unresolvedMembers[i])) {
750          yield return members[i];
751        }
752      }
753      for (int i = members.unresolvedMembers.Length; i < members.Count; i++) {
754        var method = (IMethod)members[i];
755        bool ok = false;
756        foreach (var part in method.Parts) {
757          if (filter == null || filter(part)) {
758            ok = true;
759            break;
760          }
761        }
762        if (ok)
763          yield return method;
764      }
765    }
766   
767    IEnumerable<IMethod> GetFilteredMethods(Predicate<IUnresolvedMethod> filter)
768    {
769      var members = GetMemberList();
770      for (int i = 0; i < members.unresolvedMembers.Length; i++) {
771        IUnresolvedMethod unresolved = members.unresolvedMembers[i] as IUnresolvedMethod;
772        if (unresolved != null && (filter == null || filter(unresolved))) {
773          yield return (IMethod)members[i];
774        }
775      }
776      for (int i = members.unresolvedMembers.Length; i < members.Count; i++) {
777        var method = (IMethod)members[i];
778        bool ok = false;
779        foreach (var part in method.Parts) {
780          if (filter == null || filter(part)) {
781            ok = true;
782            break;
783          }
784        }
785        if (ok)
786          yield return method;
787      }
788    }
789   
790    IEnumerable<TResolved> GetFilteredNonMethods<TUnresolved, TResolved>(Predicate<TUnresolved> filter) where TUnresolved : class, IUnresolvedMember where TResolved : class, IMember
791    {
792      var members = GetMemberList();
793      for (int i = 0; i < members.unresolvedMembers.Length; i++) {
794        TUnresolved unresolved = members.unresolvedMembers[i] as TUnresolved;
795        if (unresolved != null && (filter == null || filter(unresolved))) {
796          yield return (TResolved)members[i];
797        }
798      }
799    }
800   
801    public virtual IEnumerable<IMethod> GetMethods(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
802    {
803      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
804        return GetFilteredMethods(Utils.ExtensionMethods.And(m => !m.IsConstructor, filter));
805      } else {
806        return GetMembersHelper.GetMethods(this, filter, options);
807      }
808    }
809   
810    public virtual IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
811    {
812      return GetMembersHelper.GetMethods(this, typeArguments, filter, options);
813    }
814   
815    public virtual IEnumerable<IMethod> GetConstructors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
816    {
817      if (ComHelper.IsComImport(this)) {
818        IType coClass = ComHelper.GetCoClass(this);
819        using (var busyLock = BusyManager.Enter(this)) {
820          if (busyLock.Success) {
821            return coClass.GetConstructors(filter, options)
822              .Select(m => new SpecializedMethod(m, m.Substitution) { DeclaringType = this });
823          }
824        }
825        return EmptyList<IMethod>.Instance;
826      }
827      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
828        return GetFilteredMethods(Utils.ExtensionMethods.And(m => m.IsConstructor && !m.IsStatic, filter));
829      } else {
830        return GetMembersHelper.GetConstructors(this, filter, options);
831      }
832    }
833   
834    public virtual IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
835    {
836      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
837        return GetFilteredNonMethods<IUnresolvedProperty, IProperty>(filter);
838      } else {
839        return GetMembersHelper.GetProperties(this, filter, options);
840      }
841    }
842   
843    public virtual IEnumerable<IField> GetFields(Predicate<IUnresolvedField> filter = null, GetMemberOptions options = GetMemberOptions.None)
844    {
845      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
846        return GetFilteredNonMethods<IUnresolvedField, IField>(filter);
847      } else {
848        return GetMembersHelper.GetFields(this, filter, options);
849      }
850    }
851   
852    public virtual IEnumerable<IEvent> GetEvents(Predicate<IUnresolvedEvent> filter = null, GetMemberOptions options = GetMemberOptions.None)
853    {
854      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
855        return GetFilteredNonMethods<IUnresolvedEvent, IEvent>(filter);
856      } else {
857        return GetMembersHelper.GetEvents(this, filter, options);
858      }
859    }
860   
861    public virtual IEnumerable<IMember> GetMembers(Predicate<IUnresolvedMember> filter = null, GetMemberOptions options = GetMemberOptions.None)
862    {
863      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
864        return GetFilteredMembers(filter);
865      } else {
866        return GetMembersHelper.GetMembers(this, filter, options);
867      }
868    }
869   
870    public virtual IEnumerable<IMethod> GetAccessors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
871    {
872      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
873        return GetFilteredAccessors(filter);
874      } else {
875        return GetMembersHelper.GetAccessors(this, filter, options);
876      }
877    }
878   
879    IEnumerable<IMethod> GetFilteredAccessors(Predicate<IUnresolvedMethod> filter)
880    {
881      var members = GetMemberList();
882      for (int i = 0; i < members.unresolvedMembers.Length; i++) {
883        IUnresolvedMember unresolved = members.unresolvedMembers[i];
884        var unresolvedProperty = unresolved as IUnresolvedProperty;
885        var unresolvedEvent = unresolved as IUnresolvedEvent;
886        if (unresolvedProperty != null) {
887          if (unresolvedProperty.CanGet && (filter == null || filter(unresolvedProperty.Getter)))
888            yield return ((IProperty)members[i]).Getter;
889          if (unresolvedProperty.CanSet && (filter == null || filter(unresolvedProperty.Setter)))
890            yield return ((IProperty)members[i]).Setter;
891        } else if (unresolvedEvent != null) {
892          if (unresolvedEvent.CanAdd && (filter == null || filter(unresolvedEvent.AddAccessor)))
893            yield return ((IEvent)members[i]).AddAccessor;
894          if (unresolvedEvent.CanRemove && (filter == null || filter(unresolvedEvent.RemoveAccessor)))
895            yield return ((IEvent)members[i]).RemoveAccessor;
896          if (unresolvedEvent.CanInvoke && (filter == null || filter(unresolvedEvent.InvokeAccessor)))
897            yield return ((IEvent)members[i]).InvokeAccessor;
898        }
899      }
900    }
901    #endregion
902   
903    #region GetInterfaceImplementation
904    public IMember GetInterfaceImplementation(IMember interfaceMember)
905    {
906      return GetInterfaceImplementation(new[] { interfaceMember })[0];
907    }
908   
909    public IList<IMember> GetInterfaceImplementation(IList<IMember> interfaceMembers)
910    {
911      // TODO: review the subtle rules for interface reimplementation,
912      // write tests and fix this method.
913      // Also virtual/override is going to be tricky -
914      // I think we'll need to consider the 'virtual' method first for
915      // reimplemenatation purposes, but then actually return the 'override'
916      // (as that's the method that ends up getting called)
917     
918      interfaceMembers = interfaceMembers.ToList(); // avoid evaluating more than once
919     
920      var result = new IMember[interfaceMembers.Count];
921      var signatureToIndexDict = new MultiDictionary<IMember, int>(SignatureComparer.Ordinal);
922      for (int i = 0; i < interfaceMembers.Count; i++) {
923        signatureToIndexDict.Add(interfaceMembers[i], i);
924      }
925      foreach (var member in GetMembers(m => !m.IsExplicitInterfaceImplementation)) {
926        foreach (int interfaceMemberIndex in signatureToIndexDict[member]) {
927          result[interfaceMemberIndex] = member;
928        }
929      }
930      foreach (var explicitImpl in GetMembers(m => m.IsExplicitInterfaceImplementation)) {
931        foreach (var interfaceMember in explicitImpl.ImplementedInterfaceMembers) {
932          foreach (int potentialMatchingIndex in signatureToIndexDict[interfaceMember]) {
933            if (interfaceMember.Equals(interfaceMembers[potentialMatchingIndex])) {
934              result[potentialMatchingIndex] = explicitImpl;
935            }
936          }
937        }
938      }
939      return result;
940    }
941    #endregion
942   
943    public TypeParameterSubstitution GetSubstitution()
944    {
945      return TypeParameterSubstitution.Identity;
946    }
947   
948    public TypeParameterSubstitution GetSubstitution(IList<IType> methodTypeArguments)
949    {
950      return TypeParameterSubstitution.Identity;
951    }
952
953    public bool Equals(IType other)
954    {
955      return this == other;
956    }
957   
958    public override string ToString()
959    {
960      return this.ReflectionName;
961    }
962  }
963}
Note: See TracBrowser for help on using the repository browser.