From 211c6a1b05ef652dabd68a24c73541dcbd1d8d6c Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 5 Oct 2012 01:37:43 +0200 Subject: [PATCH] Implemented ITypeParameter.EffectiveInterfaceSet --- .../TypeSystem/ITypeParameter.cs | 2 +- .../AbstractResolvedTypeParameter.cs | 85 ++++++++++++------- .../Implementation/DummyTypeParameter.cs | 2 +- 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs index 9d4b360635..7e0a89d8f8 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs @@ -107,7 +107,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the effective interface set of this type parameter. /// - IList EffectiveInterfaceSet { get; } + ICollection EffectiveInterfaceSet { get; } /// /// Gets if the type parameter has the 'new()' constraint. diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs index 8b12e0e920..cede6c7a8b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs @@ -94,48 +94,73 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public IType EffectiveBaseClass { get { - if (effectiveBaseClass == null) - effectiveBaseClass = CalculateEffectiveBaseClass(); + if (effectiveBaseClass == null) { + // protect against cyclic type parameters + using (var busyLock = BusyManager.Enter(this)) { + if (!busyLock.Success) + return SpecialType.UnknownType; // don't cache this error + effectiveBaseClass = CalculateEffectiveBaseClass(); + } + } return effectiveBaseClass; } } IType CalculateEffectiveBaseClass() { - // protect against cyclic type parameters - using (var busyLock = BusyManager.Enter(this)) { - if (!busyLock.Success) - return SpecialType.UnknownType; - - if (HasValueTypeConstraint) - return this.Compilation.FindType(KnownTypeCode.ValueType); - - List classTypeConstraints = new List(); - foreach (IType constraint in this.DirectBaseTypes) { - if (constraint.Kind == TypeKind.Class) { - classTypeConstraints.Add(constraint); - } else if (constraint.Kind == TypeKind.TypeParameter) { - IType baseClass = ((ITypeParameter)constraint).EffectiveBaseClass; - if (baseClass.Kind == TypeKind.Class) - classTypeConstraints.Add(baseClass); - } - } - if (classTypeConstraints.Count == 0) - return this.Compilation.FindType(KnownTypeCode.Object); - // Find the derived-most type in the resulting set: - IType result = classTypeConstraints[0]; - for (int i = 1; i < classTypeConstraints.Count; i++) { - if (classTypeConstraints[i].GetDefinition().IsDerivedFrom(result.GetDefinition())) - result = classTypeConstraints[i]; + if (HasValueTypeConstraint) + return this.Compilation.FindType(KnownTypeCode.ValueType); + + List classTypeConstraints = new List(); + foreach (IType constraint in this.DirectBaseTypes) { + if (constraint.Kind == TypeKind.Class) { + classTypeConstraints.Add(constraint); + } else if (constraint.Kind == TypeKind.TypeParameter) { + IType baseClass = ((ITypeParameter)constraint).EffectiveBaseClass; + if (baseClass.Kind == TypeKind.Class) + classTypeConstraints.Add(baseClass); } - return result; } + if (classTypeConstraints.Count == 0) + return this.Compilation.FindType(KnownTypeCode.Object); + // Find the derived-most type in the resulting set: + IType result = classTypeConstraints[0]; + for (int i = 1; i < classTypeConstraints.Count; i++) { + if (classTypeConstraints[i].GetDefinition().IsDerivedFrom(result.GetDefinition())) + result = classTypeConstraints[i]; + } + return result; } - public IList EffectiveInterfaceSet { + ICollection effectiveInterfaceSet; + + public ICollection EffectiveInterfaceSet { get { - throw new NotImplementedException(); + var result = LazyInit.VolatileRead(ref effectiveInterfaceSet); + if (result != null) { + return result; + } else { + // protect against cyclic type parameters + using (var busyLock = BusyManager.Enter(this)) { + if (!busyLock.Success) + return EmptyList.Instance; // don't cache this error + return LazyInit.GetOrSet(ref effectiveInterfaceSet, CalculateEffectiveInterfaceSet()); + } + } + } + } + + ICollection CalculateEffectiveInterfaceSet() + { + HashSet result = new HashSet(); + foreach (IType constraint in this.DirectBaseTypes) { + if (constraint.Kind == TypeKind.Interface) { + result.Add(constraint); + } else if (constraint.Kind == TypeKind.TypeParameter) { + result.UnionWith(((ITypeParameter)constraint).EffectiveInterfaceSet); + } } + return result; } public abstract bool HasDefaultConstructorConstraint { get; } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs index 22e7fc4fc8..f0ec26d0e1 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs @@ -189,7 +189,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return SpecialType.UnknownType; } } - IList ITypeParameter.EffectiveInterfaceSet { + ICollection ITypeParameter.EffectiveInterfaceSet { get { return EmptyList.Instance; } }