diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs index fb5760f4c5..a3a3ff2a2a 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs @@ -1127,7 +1127,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.nonLiftedOperator = nonLiftedMethod; // Comparison operators keep the 'bool' return type even when lifted. if (IsComparisonOperator(nonLiftedMethod)) - this.returnType = nonLiftedMethod.ReturnType; + this.ReturnType = nonLiftedMethod.ReturnType; } public IList NonLiftedParameters { diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index 58411c567e..04e16ab79b 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -948,7 +948,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // 7.6.10.6 Anonymous object creation expressions List properties = new List(); foreach (var expr in anonymousTypeCreateExpression.Initializers) { - Scan(expr); Expression resolveExpr; var name = GetAnonymousTypePropertyName(expr, out resolveExpr); if (!string.IsNullOrEmpty(name)) { @@ -966,7 +965,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver properties.Add(property); } } - return new ResolveResult(new AnonymousType(resolver.Compilation, properties)); + IType anonymousType = new AnonymousType(resolver.Compilation, properties); + resolver = resolver.PushInitializerType(anonymousType); + ScanChildren(anonymousTypeCreateExpression); + resolver = resolver.PopInitializerType(); + return new ResolveResult(anonymousType); } sealed class VarTypeReference : ITypeReference diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AnonymousTypeTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AnonymousTypeTests.cs new file mode 100644 index 0000000000..4990c0c88e --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AnonymousTypeTests.cs @@ -0,0 +1,64 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Linq; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class AnonymousTypeTests : ResolverTestBase + { + const string programStart = @"using System; +using System.Collections.Generic; +using System.Linq; +class Test { + void M(IEnumerable list1, IEnumerable list2) { + "; + const string programEnd = " } }"; + + [Test] + public void Zip() + { + string program = programStart + "$var$ q = list1.Zip(list2, (a,b) => new { a, b });" + programEnd; + var rr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.Type.FullName); + var type = (AnonymousType)((ParameterizedType)rr.Type).TypeArguments.Single(); + Assert.AreEqual(TypeKind.Anonymous, type.Kind); + Assert.AreEqual(2, type.Properties.Count); + Assert.AreEqual("a", type.Properties[0].Name); + Assert.AreEqual("b", type.Properties[1].Name); + Assert.AreEqual("System.String", type.Properties[0].ReturnType.ReflectionName); + Assert.AreEqual("System.Int32", type.Properties[1].ReturnType.ReflectionName); + } + + [Test] + public void ZipItem1() + { + string program = programStart + "var q = list1.Zip(list2, (a,b) => new { $Item1 = a$, Item2 = b });" + programEnd; + var rr = Resolve(program); + Assert.AreEqual(TypeKind.Anonymous, rr.Member.DeclaringType.Kind); + Assert.AreEqual("Item1", rr.Member.Name); + Assert.AreEqual(EntityType.Property, rr.Member.EntityType); + Assert.AreEqual("System.String", rr.Member.ReturnType.FullName); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index 4fa3d983ce..dbc2da4f08 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -1,4 +1,4 @@ - + {63D3B27A-D966-4902-90B3-30290E1692F1} @@ -146,6 +146,7 @@ + diff --git a/ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs b/ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs index 1109eea0f9..23fb367a52 100644 --- a/ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs @@ -42,7 +42,22 @@ namespace ICSharpCode.NRefactory.TypeSystem this.compilation = compilation; this.unresolvedProperties = properties.ToArray(); var context = new SimpleTypeResolveContext(compilation.MainAssembly); - this.resolvedProperties = new ProjectedList(context, unresolvedProperties, (c, p) => (IProperty)p.CreateResolved(c)); + this.resolvedProperties = new ProjectedList(context, unresolvedProperties, (c, p) => new AnonymousTypeProperty(p, c, this)); + } + + sealed class AnonymousTypeProperty : DefaultResolvedProperty, IEntity + { + readonly AnonymousType declaringType; + + public AnonymousTypeProperty(IUnresolvedProperty unresolved, ITypeResolveContext parentContext, AnonymousType declaringType) + : base(unresolved, parentContext) + { + this.declaringType = declaringType; + } + + IType IEntity.DeclaringType { + get { return declaringType; } + } } public override ITypeReference ToTypeReference() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs index bf79177471..94af4875a5 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { readonly IType declaringType; readonly IMember memberDefinition; - protected IType returnType; + IType returnType; protected SpecializedMember(IType declaringType, IMember memberDefinition) { @@ -92,6 +92,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public IType ReturnType { get { return returnType; } + protected set { returnType = value; } } public bool IsVirtual {