Browse Source

Use BusyManager to avoid infinite recursion when there are inheritance cycles.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
0d26071311
  1. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  2. 7
      ICSharpCode.NRefactory/TypeSystem/ConstructedType.cs
  3. 8
      ICSharpCode.NRefactory/TypeSystem/Implementation/AggregateTypeResolveContext.cs
  4. 5
      ICSharpCode.NRefactory/TypeSystem/Implementation/BitVector16.cs
  5. 55
      ICSharpCode.NRefactory/TypeSystem/Implementation/BusyManager.cs
  6. 5
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs
  7. 5
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs
  8. 106
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs
  9. 4
      ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -162,6 +162,7 @@ @@ -162,6 +162,7 @@
<Compile Include="TypeSystem\Implementation\AbstractMember.cs" />
<Compile Include="TypeSystem\Implementation\AbstractType.cs" />
<Compile Include="TypeSystem\Implementation\BitVector16.cs" />
<Compile Include="TypeSystem\Implementation\BusyManager.cs" />
<Compile Include="TypeSystem\Implementation\DefaultAttribute.cs" />
<Compile Include="TypeSystem\Implementation\DefaultEvent.cs" />
<Compile Include="TypeSystem\Implementation\DefaultExplicitInterfaceImplementation.cs" />

7
ICSharpCode.NRefactory/TypeSystem/ConstructedType.cs

@ -44,6 +44,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -44,6 +44,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
return base.VisitTypeParameter(type);
}
}
public IType Apply(IType type)
{
return type.AcceptVisitor(this);
}
}
readonly ITypeDefinition genericType;
@ -150,7 +155,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -150,7 +155,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public IEnumerable<IType> GetBaseTypes(ITypeResolveContext context)
{
Substitution substitution = new Substitution(typeArguments);
return genericType.GetBaseTypes(context).Select(t => t.AcceptVisitor(substitution));
return genericType.GetBaseTypes(context).Select(substitution.Apply);
}
public IList<IType> GetNestedTypes(ITypeResolveContext context)

8
ICSharpCode.NRefactory/TypeSystem/Implementation/AggregateTypeResolveContext.cs

@ -74,15 +74,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -74,15 +74,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
for (int i = 0; i < sync.Length; i++) {
sync[i] = contexts[i].Synchronize();
}
return new MultiSynchronizedTypeResolveContext(this, sync);
return new AggregateSynchronizedTypeResolveContext(sync);
}
sealed class MultiSynchronizedTypeResolveContext : ProxyTypeResolveContext, ISynchronizedTypeResolveContext
sealed class AggregateSynchronizedTypeResolveContext : AggregateTypeResolveContext, ISynchronizedTypeResolveContext
{
readonly ISynchronizedTypeResolveContext[] sync;
public MultiSynchronizedTypeResolveContext(ITypeResolveContext target, ISynchronizedTypeResolveContext[] sync)
: base(target)
public AggregateSynchronizedTypeResolveContext(ISynchronizedTypeResolveContext[] sync)
: base(sync)
{
this.sync = sync;
}

5
ICSharpCode.NRefactory/TypeSystem/Implementation/BitVector16.cs

@ -56,5 +56,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -56,5 +56,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return left.data != right.data;
}
#endregion
public override string ToString()
{
return data.ToString("x4");
}
}
}

55
ICSharpCode.NRefactory/TypeSystem/Implementation/BusyManager.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// This class is used to prevent stack overflows by representing a 'busy' flag
/// that prevents reentrance when another call is running.
/// However, using a simple 'bool busy' is not thread-safe, so we use a
/// thread-static BusyManager.
/// </summary>
static class BusyManager
{
public struct BusyLock : IDisposable
{
public static readonly BusyLock Failed = new BusyLock(null);
readonly List<object> objectList;
public BusyLock(List<object> objectList)
{
this.objectList = objectList;
}
public bool Success {
get { return objectList != null; }
}
public void Dispose()
{
if (objectList != null) {
objectList.RemoveAt(objectList.Count - 1);
}
}
}
[ThreadStatic] static List<object> _activeObjects;
public static BusyLock Enter(object obj)
{
List<object> activeObjects = _activeObjects;
if (activeObjects == null)
activeObjects = _activeObjects = new List<object>();
for (int i = 0; i < activeObjects.Count; i++) {
if (activeObjects[i] == obj)
return BusyLock.Failed;
}
activeObjects.Add(obj);
return new BusyLock(activeObjects);
}
}
}

5
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs

@ -71,5 +71,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -71,5 +71,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return namedArguments;
}
}
public override string ToString()
{
return "[" + attributeType + "]";
}
}
}

5
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs

@ -22,5 +22,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -22,5 +22,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.InterfaceType = interfaceType;
this.MemberName = memberName;
}
public override string ToString()
{
return InterfaceType + "." + MemberName;
}
}
}

106
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs

@ -357,82 +357,104 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -357,82 +357,104 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IList<IType> GetNestedTypes(ITypeResolveContext context)
{
IList<IType> nestedTypes = null;
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && baseTypeDef.ClassType != ClassType.Interface) {
// get nested types from baseType (not baseTypeDef) so that generics work correctly
nestedTypes = baseType.GetNestedTypes(context);
break; // there is at most 1 non-interface base
}
}
if (nestedTypes == null)
nestedTypes = new List<IType>();
foreach (ITypeDefinition innerClass in this.InnerClasses) {
if (innerClass.TypeParameterCount > 0) {
// Parameterize inner classes with their own type parameters, as per <remarks> on IType.GetNestedTypes.
nestedTypes.Add(new ConstructedType(innerClass, innerClass.TypeParameters));
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
IList<IType> nestedTypes = null;
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && baseTypeDef.ClassType != ClassType.Interface) {
// get nested types from baseType (not baseTypeDef) so that generics work correctly
nestedTypes = baseType.GetNestedTypes(context);
break; // there is at most 1 non-interface base
}
}
if (nestedTypes == null)
nestedTypes = new List<IType>();
foreach (ITypeDefinition innerClass in this.InnerClasses) {
if (innerClass.TypeParameterCount > 0) {
// Parameterize inner classes with their own type parameters, as per <remarks> on IType.GetNestedTypes.
nestedTypes.Add(new ConstructedType(innerClass, innerClass.TypeParameters));
} else {
nestedTypes.Add(innerClass);
}
}
return nestedTypes;
} else {
nestedTypes.Add(innerClass);
return new List<IType>();
}
}
return nestedTypes;
}
public IList<IMethod> GetMethods(ITypeResolveContext context)
{
List<IMethod> methods = new List<IMethod>();
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) {
methods.AddRange(baseType.GetMethods(context));
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) {
methods.AddRange(baseType.GetMethods(context));
}
}
methods.AddRange(this.Methods);
}
}
methods.AddRange(this.Methods);
return methods;
}
public IList<IProperty> GetProperties(ITypeResolveContext context)
{
List<IProperty> properties = new List<IProperty>();
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) {
properties.AddRange(baseType.GetProperties(context));
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) {
properties.AddRange(baseType.GetProperties(context));
}
}
properties.AddRange(this.Properties);
}
}
properties.AddRange(this.Properties);
return properties;
}
public IList<IField> GetFields(ITypeResolveContext context)
{
List<IField> fields = new List<IField>();
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) {
fields.AddRange(baseType.GetFields(context));
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) {
fields.AddRange(baseType.GetFields(context));
}
}
fields.AddRange(this.Fields);
}
}
fields.AddRange(this.Fields);
return fields;
}
public IList<IEvent> GetEvents(ITypeResolveContext context)
{
List<IEvent> events = new List<IEvent>();
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) {
events.AddRange(baseType.GetEvents(context));
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
foreach (var baseTypeRef in this.BaseTypes) {
IType baseType = baseTypeRef.Resolve(context);
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) {
events.AddRange(baseType.GetEvents(context));
}
}
events.AddRange(this.Events);
}
}
events.AddRange(this.Events);
return events;
}

4
ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs

@ -18,8 +18,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -18,8 +18,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// Creates a new NestedTypeReference.
/// </summary>
/// <param name="baseTypeRef">Reference to the base type.</param>
/// <param name="name"></param>
/// <param name="additionalTypeParameterCount"></param>
/// <param name="name">Name of the nested class</param>
/// <param name="additionalTypeParameterCount">Number of type parameters on the inner class (without type parameters on baseTypeRef)</param>
public NestedTypeReference(ITypeReference baseTypeRef, string name, int additionalTypeParameterCount)
{
if (baseTypeRef == null)

Loading…
Cancel
Save