Browse Source

Prevent creating ConstructedReturnTypes that cause infinite recursion.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1390 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
130f45f439
  1. 21
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs
  2. 17
      src/AddIns/BackendBindings/Boo/BooBinding/Test/ResolverTests.cs

21
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs

@ -43,7 +43,7 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -43,7 +43,7 @@ namespace Grunwald.BooBinding.CodeCompletion
get {
// clear up references to method/expression after the type has been resolved
if (block != null) {
GetReturnTypeVisitor v = new GetReturnTypeVisitor(context);
GetReturnTypeVisitor v = new GetReturnTypeVisitor(this);
Block b = block;
block = null; // reset block before calling Visit to prevent StackOverflow
v.Visit(b);
@ -70,9 +70,11 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -70,9 +70,11 @@ namespace Grunwald.BooBinding.CodeCompletion
class GetReturnTypeVisitor : DepthFirstVisitor
{
IClass context;
public GetReturnTypeVisitor(IClass context)
InferredReturnType parentReturnType;
public GetReturnTypeVisitor(InferredReturnType parentReturnType)
{
this.context = context;
this.context = parentReturnType.context;
this.parentReturnType = parentReturnType;
}
public IReturnType result;
@ -99,7 +101,18 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -99,7 +101,18 @@ namespace Grunwald.BooBinding.CodeCompletion
{
noReturnStatement = false;
IClass enumerable = ProjectContentRegistry.Mscorlib.GetClass("System.Collections.Generic.IEnumerable", 1);
result = new ConstructedReturnType(enumerable.DefaultReturnType, new IReturnType[] { new InferredReturnType(node.Expression, context) });
// Prevent creating an infinite number of InferredReturnTypes in inferring cycles
parentReturnType.expression = new NullLiteralExpression();
IReturnType returnType = new BooResolver().GetTypeOfExpression(node.Expression, context);
returnType.GetUnderlyingClass(); // force to infer type
if (parentReturnType.expression == null) {
// inferrence cycle with parentReturnType
returnType = new GetClassReturnType(context.ProjectContent, "?", 0);
}
parentReturnType.expression = null;
result = new ConstructedReturnType(enumerable.DefaultReturnType, new IReturnType[] { returnType });
}
public override void OnCallableBlockExpression(CallableBlockExpression node)

17
src/AddIns/BackendBindings/Boo/BooBinding/Test/ResolverTests.cs

@ -254,6 +254,23 @@ namespace Grunwald.BooBinding.Tests @@ -254,6 +254,23 @@ namespace Grunwald.BooBinding.Tests
LocalResolveResult rr2 = Resolve<LocalResolveResult>(prog, "mybool", "/*mark*/");
Assert.AreEqual("System.Boolean", rr2.ResolvedType.FullyQualifiedName);
}
[Test]
public void InfiniteRecursionGenerator()
{
string prog =
"class Test:\n" +
"\t_testList = []\n" +
"\tTestProperty:\n" +
"\t\tget:\n" +
"\t\t\tfor testobj as Test in _testList:\n" +
"\t\t\t\tyield testobj.TestProperty /*mark*/\n";
MemberResolveResult rr = Resolve<MemberResolveResult>(prog, "testobj.TestProperty", "/*mark*/");
Assert.AreEqual("Test.TestProperty", rr.ResolvedMember.FullyQualifiedName);
Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.ResolvedType.FullyQualifiedName);
// prevent creating self-referring ConstructedReturnType
Assert.AreEqual("?", rr.ResolvedType.TypeArguments[0].FullyQualifiedName);
}
#endregion
#region Nested Classes

Loading…
Cancel
Save