~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

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