1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
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:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
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.
20
using System.Collections.Generic;
21
using System.Globalization;
23
using ICSharpCode.NRefactory.Utils;
25
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
27
public abstract class AbstractTypeParameter : ITypeParameter, ICompilationProvider
29
readonly ICompilation compilation;
30
readonly EntityType ownerType;
31
readonly IEntity owner;
34
readonly IList<IAttribute> attributes;
35
readonly DomRegion region;
36
readonly VarianceModifier variance;
38
protected AbstractTypeParameter(IEntity owner, int index, string name, VarianceModifier variance, IList<IAttribute> attributes, DomRegion region)
41
throw new ArgumentNullException("owner");
43
this.compilation = owner.Compilation;
44
this.ownerType = owner.EntityType;
46
this.name = name ?? ((this.OwnerType == EntityType.Method ? "!!" : "!") + index.ToString(CultureInfo.InvariantCulture));
47
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
49
this.variance = variance;
52
protected AbstractTypeParameter(ICompilation compilation, EntityType ownerType, int index, string name, VarianceModifier variance, IList<IAttribute> attributes, DomRegion region)
54
if (compilation == null)
55
throw new ArgumentNullException("compilation");
56
this.compilation = compilation;
57
this.ownerType = ownerType;
59
this.name = name ?? ((this.OwnerType == EntityType.Method ? "!!" : "!") + index.ToString(CultureInfo.InvariantCulture));
60
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
62
this.variance = variance;
65
public EntityType OwnerType {
66
get { return ownerType; }
69
public IEntity Owner {
77
public IList<IAttribute> Attributes {
78
get { return attributes; }
81
public VarianceModifier Variance {
82
get { return variance; }
85
public DomRegion Region {
86
get { return region; }
89
public ICompilation Compilation {
90
get { return compilation; }
93
volatile IType effectiveBaseClass;
95
public IType EffectiveBaseClass {
97
if (effectiveBaseClass == null) {
98
// protect against cyclic type parameters
99
using (var busyLock = BusyManager.Enter(this)) {
100
if (!busyLock.Success)
101
return SpecialType.UnknownType; // don't cache this error
102
effectiveBaseClass = CalculateEffectiveBaseClass();
105
return effectiveBaseClass;
109
IType CalculateEffectiveBaseClass()
111
if (HasValueTypeConstraint)
112
return this.Compilation.FindType(KnownTypeCode.ValueType);
114
List<IType> classTypeConstraints = new List<IType>();
115
foreach (IType constraint in this.DirectBaseTypes) {
116
if (constraint.Kind == TypeKind.Class) {
117
classTypeConstraints.Add(constraint);
118
} else if (constraint.Kind == TypeKind.TypeParameter) {
119
IType baseClass = ((ITypeParameter)constraint).EffectiveBaseClass;
120
if (baseClass.Kind == TypeKind.Class)
121
classTypeConstraints.Add(baseClass);
124
if (classTypeConstraints.Count == 0)
125
return this.Compilation.FindType(KnownTypeCode.Object);
126
// Find the derived-most type in the resulting set:
127
IType result = classTypeConstraints[0];
128
for (int i = 1; i < classTypeConstraints.Count; i++) {
129
if (classTypeConstraints[i].GetDefinition().IsDerivedFrom(result.GetDefinition()))
130
result = classTypeConstraints[i];
135
ICollection<IType> effectiveInterfaceSet;
137
public ICollection<IType> EffectiveInterfaceSet {
139
var result = LazyInit.VolatileRead(ref effectiveInterfaceSet);
140
if (result != null) {
143
// protect against cyclic type parameters
144
using (var busyLock = BusyManager.Enter(this)) {
145
if (!busyLock.Success)
146
return EmptyList<IType>.Instance; // don't cache this error
147
return LazyInit.GetOrSet(ref effectiveInterfaceSet, CalculateEffectiveInterfaceSet());
153
ICollection<IType> CalculateEffectiveInterfaceSet()
155
HashSet<IType> result = new HashSet<IType>();
156
foreach (IType constraint in this.DirectBaseTypes) {
157
if (constraint.Kind == TypeKind.Interface) {
158
result.Add(constraint);
159
} else if (constraint.Kind == TypeKind.TypeParameter) {
160
result.UnionWith(((ITypeParameter)constraint).EffectiveInterfaceSet);
166
public abstract bool HasDefaultConstructorConstraint { get; }
167
public abstract bool HasReferenceTypeConstraint { get; }
168
public abstract bool HasValueTypeConstraint { get; }
170
public TypeKind Kind {
171
get { return TypeKind.TypeParameter; }
174
public bool? IsReferenceType {
176
if (this.HasValueTypeConstraint)
178
if (this.HasReferenceTypeConstraint)
181
// A type parameter is known to be a reference type if it has the reference type constraint
182
// or its effective base class is not object or System.ValueType.
183
IType effectiveBaseClass = this.EffectiveBaseClass;
184
if (effectiveBaseClass.Kind == TypeKind.Class || effectiveBaseClass.Kind == TypeKind.Delegate) {
185
ITypeDefinition effectiveBaseClassDef = effectiveBaseClass.GetDefinition();
186
if (effectiveBaseClassDef != null) {
187
switch (effectiveBaseClassDef.KnownTypeCode) {
188
case KnownTypeCode.Object:
189
case KnownTypeCode.ValueType:
190
case KnownTypeCode.Enum:
195
} else if (effectiveBaseClass.Kind == TypeKind.Struct || effectiveBaseClass.Kind == TypeKind.Enum) {
202
IType IType.DeclaringType {
206
int IType.TypeParameterCount {
210
bool IType.IsParameterized {
211
get { return false; }
214
readonly static IList<IType> emptyTypeArguments = new IType[0];
215
IList<IType> IType.TypeArguments {
216
get { return emptyTypeArguments; }
219
public abstract IEnumerable<IType> DirectBaseTypes { get; }
225
string INamedElement.Namespace {
226
get { return string.Empty; }
229
string INamedElement.FullName {
233
public string ReflectionName {
235
return (this.OwnerType == EntityType.Method ? "``" : "`") + index.ToString(CultureInfo.InvariantCulture);
239
ITypeDefinition IType.GetDefinition()
244
public IType AcceptVisitor(TypeVisitor visitor)
246
return visitor.VisitTypeParameter(this);
249
public IType VisitChildren(TypeVisitor visitor)
254
public ITypeReference ToTypeReference()
256
return TypeParameterReference.Create(this.OwnerType, this.Index);
259
IEnumerable<IType> IType.GetNestedTypes(Predicate<ITypeDefinition> filter, GetMemberOptions options)
261
return EmptyList<IType>.Instance;
264
IEnumerable<IType> IType.GetNestedTypes(IList<IType> typeArguments, Predicate<ITypeDefinition> filter, GetMemberOptions options)
266
return EmptyList<IType>.Instance;
269
public IEnumerable<IMethod> GetConstructors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
271
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
272
if (this.HasDefaultConstructorConstraint || this.HasValueTypeConstraint) {
273
if (filter == null || filter(DefaultUnresolvedMethod.DummyConstructor)) {
274
return new [] { DefaultResolvedMethod.GetDummyConstructor(compilation, this) };
277
return EmptyList<IMethod>.Instance;
279
return GetMembersHelper.GetConstructors(this, filter, options);
283
public IEnumerable<IMethod> GetMethods(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
285
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
286
return EmptyList<IMethod>.Instance;
288
return GetMembersHelper.GetMethods(this, FilterNonStatic(filter), options);
291
public IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
293
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
294
return EmptyList<IMethod>.Instance;
296
return GetMembersHelper.GetMethods(this, typeArguments, FilterNonStatic(filter), options);
299
public IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
301
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
302
return EmptyList<IProperty>.Instance;
304
return GetMembersHelper.GetProperties(this, FilterNonStatic(filter), options);
307
public IEnumerable<IField> GetFields(Predicate<IUnresolvedField> filter = null, GetMemberOptions options = GetMemberOptions.None)
309
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
310
return EmptyList<IField>.Instance;
312
return GetMembersHelper.GetFields(this, FilterNonStatic(filter), options);
315
public IEnumerable<IEvent> GetEvents(Predicate<IUnresolvedEvent> filter = null, GetMemberOptions options = GetMemberOptions.None)
317
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
318
return EmptyList<IEvent>.Instance;
320
return GetMembersHelper.GetEvents(this, FilterNonStatic(filter), options);
323
public IEnumerable<IMember> GetMembers(Predicate<IUnresolvedMember> filter = null, GetMemberOptions options = GetMemberOptions.None)
325
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
326
return EmptyList<IMember>.Instance;
328
return GetMembersHelper.GetMembers(this, FilterNonStatic(filter), options);
331
public IEnumerable<IMethod> GetAccessors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
333
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
334
return EmptyList<IMethod>.Instance;
336
return GetMembersHelper.GetAccessors(this, FilterNonStatic(filter), options);
339
public TypeParameterSubstitution GetSubstitution()
341
return TypeParameterSubstitution.Identity;
344
public TypeParameterSubstitution GetSubstitution(IList<IType> methodTypeArguments)
346
return TypeParameterSubstitution.Identity;
349
static Predicate<T> FilterNonStatic<T>(Predicate<T> filter) where T : class, IUnresolvedMember
352
return member => !member.IsStatic;
354
return member => !member.IsStatic && filter(member);
357
public sealed override bool Equals(object obj)
359
return Equals(obj as IType);
362
public override int GetHashCode()
364
return base.GetHashCode();
367
public virtual bool Equals(IType other)
369
return this == other; // use reference equality for type parameters
372
public override string ToString()
374
return this.ReflectionName + " (owner=" + owner + ")";