Browse Source

Fix infinite recursion when resolving the base type of "class Test : Test.Base { public class Base {} }"

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
177fb85a00
  1. 10
      ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs
  2. 8
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  3. 2
      ICSharpCode.NRefactory/Utils/BusyManager.cs

10
ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs

@ -91,7 +91,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
for (int i = 0; i < typeArgs.Length; i++) { for (int i = 0; i < typeArgs.Length; i++) {
typeArgs[i] = typeArguments[i].Resolve(context); typeArgs[i] = typeArguments[i].Resolve(context);
} }
ResolveResult rr = r.ResolveMemberType(targetRR, identifier, typeArgs); ResolveResult rr;
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
rr = r.ResolveMemberType(targetRR, identifier, typeArgs);
} else {
// This can happen for "class Test : $Test.Base$ { public class Base {} }":
return ErrorResolveResult.UnknownError; // don't cache this error
}
}
if (cacheManager != null) if (cacheManager != null)
cacheManager.SetShared(this, rr); cacheManager.SetShared(this, rr);
return rr; return rr;

8
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -860,5 +860,13 @@ class B
Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name); Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name);
Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name); Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name);
} }
[Test]
public void InheritingInnerClassShouldNotCauseStackOverflow()
{
string program = @"class Test : $Test.Base$, Test.ITest { public class Base {} interface ITest {} }";
var result = Resolve<TypeResolveResult>(program);
Assert.AreEqual("Test.Base", result.Type.FullName);
}
} }
} }

2
ICSharpCode.NRefactory/Utils/BusyManager.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.NRefactory.Utils
/// However, using a simple 'bool busy' is not thread-safe, so we use a /// However, using a simple 'bool busy' is not thread-safe, so we use a
/// thread-static BusyManager. /// thread-static BusyManager.
/// </summary> /// </summary>
static class BusyManager public static class BusyManager
{ {
public struct BusyLock : IDisposable public struct BusyLock : IDisposable
{ {

Loading…
Cancel
Save