From 9d0e6ae0f8d81c5823cb6adec588e4dc8ece5bc2 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 21 Aug 2011 23:49:30 +0200 Subject: [PATCH] Resolver: added support for collection initializers and nested object initializers. --- .../CSharp/Resolver/LambdaTests.cs | 7 +-- .../CSharp/Resolver/ObjectCreationTests.cs | 40 +++++++++++++ .../CSharp/Resolver/CSharpResolver.cs | 5 +- .../CSharp/Resolver/ResolveVisitor.cs | 57 ++++++++++++++----- 4 files changed, 89 insertions(+), 20 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs index 5abde3da4c..e3472e8b43 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -159,7 +159,7 @@ class TestClass { #endregion #region Lambda In Collection Initializer - [Test, Ignore("Parser doesn't support collection initializers yet")] + [Test] public void LambdaInCollectionInitializer1() { string program = @"using System; using System.Collections.Generic; @@ -174,7 +174,7 @@ class TestClass { Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } - [Test, Ignore("Parser doesn't support collection initializers yet")] + [Test] public void LambdaInCollectionInitializer2() { string program = @"using System; using System.Collections.Generic; @@ -189,8 +189,7 @@ class TestClass { Assert.AreEqual("System.Char", lrr.Type.ReflectionName); } - - [Test, Ignore("Parser doesn't support collection initializers yet")] + [Test] public void LambdaInCollectionInitializer3() { string program = @"using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs index bf889c6544..9b69e10c8f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs @@ -156,5 +156,45 @@ class B { MemberResolveResult result = Resolve(program); Assert.AreEqual("A.Property", result.Member.FullName); } + + [Test] + public void FieldReferenceInNestedObjectInitializer() + { + string program = @"class Point { public float X, Y; } +class Rect { public Point TopLeft, BottomRight; } +class B { + void Method() { + var x = new Rect() { TopLeft = { $X = 1$ } }; + } +}"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("Point.X", result.Member.FullName); + } + + [Test, Ignore("Parser returns incorrect positions")] + public void CollectionInitializerTest() + { + string program = @"using System.Collections.Generic; +class B { + void Method() { + var x = new List() { ${ 0 }$ }; + } +}"; + InvocationResolveResult result = Resolve(program); + Assert.AreEqual("System.Collections.Generic.List.Add", result.Member.FullName); + } + + [Test, Ignore("Parser returns incorrect positions")] + public void DictionaryInitializerTest() + { + string program = @"using System.Collections.Generic; +class B { + void Method() { + var x = new Dictionary() { ${ 'a', 0 }$ }; + } +}"; + InvocationResolveResult result = Resolve(program); + Assert.AreEqual("System.Collections.Generic.Dictionary.Add", result.Member.FullName); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs index 3a63e9b9d9..7e6e362455 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs @@ -2109,7 +2109,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return ErrorResult; } - MemberLookup CreateMemberLookup() + /// + /// Creates a MemberLookup instance using this resolver's settings. + /// + public MemberLookup CreateMemberLookup() { return new MemberLookup(context, this.CurrentTypeDefinition, this.UsingScope != null ? this.UsingScope.ProjectContent : null); } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs index 91389da3c3..d69b6b1c28 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs @@ -999,7 +999,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { Expression rhs = namedExpression.Expression; if (rhs is ArrayInitializerExpression) { - throw new NotImplementedException(); + ResolveResult result = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Identifier); + HandleObjectInitializer(result.Type, (ArrayInitializerExpression)rhs); + return result; } else { if (resolverEnabled) { ResolveResult result = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Identifier); @@ -1028,20 +1030,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver var initializer = objectCreateExpression.Initializer; if (!initializer.IsNull) { - resolver.PushInitializerType(type); - foreach (Expression element in initializer.Elements) { - if (element is NamedExpression) { - // assignment in object initializer - Scan(element); - } else if (element is ArrayInitializerExpression) { - // constructor argument list in collection initializer - throw new NotImplementedException(); - } else { - // element in collection initializer - throw new NotImplementedException(); - } - } - resolver.PopInitializerType(); + HandleObjectInitializer(type, initializer); } if (resolverEnabled) { @@ -1061,6 +1050,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } + void HandleObjectInitializer(IType type, ArrayInitializerExpression initializer) + { + resolver.PushInitializerType(type); + foreach (Expression element in initializer.Elements) { + ArrayInitializerExpression aie = element as ArrayInitializerExpression; + if (aie != null) { + if (resolveResultCache.ContainsKey(aie)) { + // Don't resolve the add call again if we already did so + continue; + } + StoreState(aie, resolver.Clone()); + // constructor argument list in collection initializer + ResolveResult[] addArguments = new ResolveResult[aie.Elements.Count]; + int i = 0; + foreach (var addArgument in aie.Elements) { + addArguments[i++] = Resolve(addArgument); + } + MemberLookup memberLookup = resolver.CreateMemberLookup(); + ResolveResult targetResult = new ResolveResult(type); + var addRR = memberLookup.Lookup(targetResult, "Add", EmptyList.Instance, true); + var mgrr = addRR as MethodGroupResolveResult; + if (mgrr != null) { + OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Context, addArguments, null, false, false); + var invocationRR = new InvocationResolveResult(targetResult, or, resolver.Context); + StoreResult(aie, invocationRR); + ProcessConversionsInResult(invocationRR); + } else { + StoreResult(aie, addRR); + } + } else { + // assignment in object initializer (NamedExpression), + // or some unknown kind of expression + Scan(element); + } + } + resolver.PopInitializerType(); + } + public override ResolveResult VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) { if (resolverEnabled) {