diff --git a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs index 605ada05830fab7385f4a4a7f1a2afac7abd51ed..4329f117fca05d925820ee51a7584d000f9eeeca 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs @@ -515,43 +515,7 @@ internal partial class BoundObjectCreationExpression : IObjectCreationExpression ImmutableArray IHasArgumentsExpression.ArgumentsInEvaluationOrder => BoundCall.DeriveArguments(this.Arguments, this.ArgumentNamesOpt, this.ArgsToParamsOpt, this.ArgumentRefKindsOpt, this.Constructor.Parameters, this.Syntax); - ImmutableArray IObjectCreationExpression.MemberInitializers - { - get - { - return (ImmutableArray)s_memberInitializersMappings.GetValue(this, - objectCreationExpression => - { - var objectInitializerExpression = this.InitializerExpressionOpt as BoundObjectInitializerExpression; - if (objectInitializerExpression != null) - { - var builder = ArrayBuilder.GetInstance(objectInitializerExpression.Initializers.Length); - foreach (var memberAssignment in objectInitializerExpression.Initializers) - { - var assignment = memberAssignment as BoundAssignmentOperator; - var leftSymbol = (assignment?.Left as BoundObjectInitializerMember)?.MemberSymbol; - - if ((object)leftSymbol == null) - { - continue; - } - - switch (leftSymbol.Kind) - { - case SymbolKind.Field: - builder.Add(new FieldInitializer(assignment.Syntax, (IFieldSymbol)leftSymbol, assignment.Right)); - break; - case SymbolKind.Property: - builder.Add(new PropertyInitializer(assignment.Syntax, (IPropertySymbol)leftSymbol, assignment.Right)); - break; - } - } - return builder.ToImmutableAndFree(); - } - return ImmutableArray.Empty; - }); - } - } + ImmutableArray IObjectCreationExpression.Initializers => GetChildInitializers(this.InitializerExpressionOpt).As(); internal static ImmutableArray GetChildInitializers(BoundExpression objectOrCollectionInitializer) { diff --git a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj index 9858091851294c4949a7439ea4b91d85d1c0ca0d..4c1aefc95328824aae6c219f47467fd9feae0ab0 100644 --- a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj +++ b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj @@ -63,6 +63,7 @@ + diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IObjectCreationExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IObjectCreationExpression.cs new file mode 100644 index 0000000000000000000000000000000000000000..2a5b571057c7dc151e31e104e296ec9662412b7f --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IObjectCreationExpression.cs @@ -0,0 +1,254 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [Fact, WorkItem(17588, "https://github.com/dotnet/roslyn/issues/17588")] + public void ObjectCreationWithMemberInitializers() + { + string source = @" +struct B +{ + public bool Field; +} + +class F +{ + public int Field; + public string Property1 { set; get; } + public B Property2 { set; get; } +} + +class C +{ + public void M1() + /**/{ + var x1 = new F(); + var x2 = new F() { Field = 2 }; + var x3 = new F() { Property1 = """" }; + var x4 = new F() { Property1 = """", Field = 2 }; + var x5 = new F() { Property2 = new B { Field = true } }; + + var e1 = new F() { Property2 = 1 }; + var e2 = new F() { """" }; + }/**/ +} +"; + string expectedOperationTree = @" +IBlockStatement (7 statements, 7 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: '{ ... }') + Locals: Local_1: F x1 + Local_2: F x2 + Local_3: F x3 + Local_4: F x4 + Local_5: F x5 + Local_6: F e1 + Local_7: F e2 + IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'var x1 = new F();') + IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'var x1 = new F();') + Variables: Local_1: F x1 + Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F) (Syntax: 'new F()') + IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'var x2 = ne ... ield = 2 };') + IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'var x2 = ne ... ield = 2 };') + Variables: Local_1: F x2 + Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F) (Syntax: 'new F() { Field = 2 }') + Initializers(1): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) (Syntax: 'Field = 2') + Left: IOperation: (OperationKind.None) (Syntax: 'Field') + Right: ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') + IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'var x3 = ne ... ty1 = """" };') + IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'var x3 = ne ... ty1 = """" };') + Variables: Local_1: F x3 + Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F) (Syntax: 'new F() { P ... rty1 = """" }') + Initializers(1): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.String) (Syntax: 'Property1 = """"') + Left: IOperation: (OperationKind.None) (Syntax: 'Property1') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: """") (Syntax: '""""') + IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'var x4 = ne ... ield = 2 };') + IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'var x4 = ne ... ield = 2 };') + Variables: Local_1: F x4 + Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F) (Syntax: 'new F() { P ... Field = 2 }') + Initializers(2): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.String) (Syntax: 'Property1 = """"') + Left: IOperation: (OperationKind.None) (Syntax: 'Property1') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: """") (Syntax: '""""') + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) (Syntax: 'Field = 2') + Left: IOperation: (OperationKind.None) (Syntax: 'Field') + Right: ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') + IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'var x5 = ne ... = true } };') + IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'var x5 = ne ... = true } };') + Variables: Local_1: F x5 + Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F) (Syntax: 'new F() { P ... = true } }') + Initializers(1): IAssignmentExpression (OperationKind.AssignmentExpression, Type: B) (Syntax: 'Property2 = ... ld = true }') + Left: IOperation: (OperationKind.None) (Syntax: 'Property2') + Right: IObjectCreationExpression (Constructor: B..ctor()) (OperationKind.ObjectCreationExpression, Type: B) (Syntax: 'new B { Field = true }') + Initializers(1): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Boolean) (Syntax: 'Field = true') + Left: IOperation: (OperationKind.None) (Syntax: 'Field') + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) (Syntax: 'true') + IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'var e1 = ne ... rty2 = 1 };') + IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'var e1 = ne ... rty2 = 1 };') + Variables: Local_1: F e1 + Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F, IsInvalid) (Syntax: 'new F() { P ... erty2 = 1 }') + Initializers(1): IAssignmentExpression (OperationKind.AssignmentExpression, Type: B, IsInvalid) (Syntax: 'Property2 = 1') + Left: IOperation: (OperationKind.None) (Syntax: 'Property2') + Right: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: B, IsInvalid) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'var e2 = new F() { """" };') + IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'var e2 = new F() { """" };') + Variables: Local_1: F e2 + Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F, IsInvalid) (Syntax: 'new F() { """" }') + Initializers(1): IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '""""') + Children(1): ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: """") (Syntax: '""""') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0029: Cannot implicitly convert type 'int' to 'B' + // var e1 = new F() { Property2 = 1 }; + Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "B").WithLocation(24, 40), + // CS1922: Cannot initialize type 'F' with a collection initializer because it does not implement 'System.Collections.IEnumerable' + // var e2 = new F() { "" }; + Diagnostic(ErrorCode.ERR_CollectionInitRequiresIEnumerable, @"{ """" }").WithArguments("F").WithLocation(25, 26) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(17588, "https://github.com/dotnet/roslyn/issues/17588")] + public void ObjectCreationWithCollectionInitializer() + { + string source = @" +using System.Collections.Generic; + +class C +{ + private readonly int field; + public void M1(int x) + { + int y = 0; + var x1 = /**/new List { x, y, field }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationExpression (Constructor: System.Collections.Generic.List..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Collections.Generic.List) (Syntax: 'new List(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(17588, "https://github.com/dotnet/roslyn/issues/17588")] + public void ObjectCreationWithNestedCollectionInitializer() + { + string source = @" +using System.Collections.Generic; +using System.Linq; + +class C +{ + private readonly int field = 0; + public void M1(int x) + { + int y = 0; + var x1 = /**/new List> { + new[] { x, y }.ToList(), + new List { field } + }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationExpression (Constructor: System.Collections.Generic.List>..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Collections.Generic.List>) (Syntax: 'new List
  • System.Linq.Enumerable.ToList(this System.Collections.Generic.IEnumerable source)) (OperationKind.InvocationExpression, Type: System.Collections.Generic.List) (Syntax: 'new[] { x, y }.ToList()') + Arguments(1): IArgument (ArgumentKind.Explicit, Matching Parameter: source) (OperationKind.Argument) (Syntax: 'new[] { x, y }') + IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Collections.Generic.IEnumerable) (Syntax: 'new[] { x, y }') + IArrayCreationExpression (Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[]) (Syntax: 'new[] { x, y }') + Dimension Sizes(1): ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: 'new[] { x, y }') + Initializer: IArrayInitializer (2 elements) (OperationKind.ArrayInitializer) (Syntax: '{ x, y }') + Element Values(2): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'y') + IOperation: (OperationKind.None) (Syntax: 'new List { field }') + Children(1): IObjectCreationExpression (Constructor: System.Collections.Generic.List..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Collections.Generic.List) (Syntax: 'new List { field }') + Initializers(1): IOperation: (OperationKind.None) (Syntax: 'field') + Children(1): IFieldReferenceExpression: System.Int32 C.field (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'field') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: 'field') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(17588, "https://github.com/dotnet/roslyn/issues/17588")] + public void ObjectCreationWithMemberAndCollectionInitializers() + { + string source = @" +using System.Collections.Generic; + +internal class Class +{ + public int X { get; set; } + public List Y { get; set; } + public Dictionary Z { get; set; } + public Class C { get; set; } + + private readonly int field = 0; + + public void M(int x) + { + int y = 0; + var c = /**/new Class() { + X = x, + Y = { x, y, 3 }, + Z = { { x, y } }, + C = { X = field } + }/**/; + } +} +"; + string expectedOperationTree = @" +IObjectCreationExpression (Constructor: Class..ctor()) (OperationKind.ObjectCreationExpression, Type: Class) (Syntax: 'new Class() ... }') + Initializers(4): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) (Syntax: 'X = x') + Left: IOperation: (OperationKind.None) (Syntax: 'X') + Right: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Collections.Generic.List) (Syntax: 'Y = { x, y, 3 }') + Left: IOperation: (OperationKind.None) (Syntax: 'Y') + Right: IOperation: (OperationKind.None) (Syntax: '{ x, y, 3 }') + Children(3): IOperation: (OperationKind.None) (Syntax: 'x') + Children(1): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + IOperation: (OperationKind.None) (Syntax: 'y') + Children(1): ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'y') + IOperation: (OperationKind.None) (Syntax: '3') + Children(1): ILiteralExpression (Text: 3) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Collections.Generic.Dictionary) (Syntax: 'Z = { { x, y } }') + Left: IOperation: (OperationKind.None) (Syntax: 'Z') + Right: IOperation: (OperationKind.None) (Syntax: '{ { x, y } }') + Children(1): IOperation: (OperationKind.None) (Syntax: '{ x, y }') + Children(2): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'y') + IAssignmentExpression (OperationKind.AssignmentExpression, Type: Class) (Syntax: 'C = { X = field }') + Left: IOperation: (OperationKind.None) (Syntax: 'C') + Right: IOperation: (OperationKind.None) (Syntax: '{ X = field }') + Children(1): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) (Syntax: 'X = field') + Left: IOperation: (OperationKind.None) (Syntax: 'X') + Right: IFieldReferenceExpression: System.Int32 Class.field (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'field') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Class) (Syntax: 'field') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + } +} \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs index 509772a22f1994d6e697d8f835885f6797cd10ab..9f62943ac058a54145a905c1fe8387039f29847b 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs @@ -165,26 +165,30 @@ public void M(int x, int y, int z) "; string expectedOperationTree = @" IObjectCreationExpression (Constructor: Class..ctor()) (OperationKind.ObjectCreationExpression, Type: Class) (Syntax: 'new Class() ... { X = z } }') - Member Initializers(4): IPropertyInitializer (Property: System.Int32 Class.X { get; set; }) (OperationKind.PropertyInitializerInCreation) (Syntax: 'X = x') - IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') - IPropertyInitializer (Property: System.Collections.Generic.List Class.Y { get; set; }) (OperationKind.PropertyInitializerInCreation) (Syntax: 'Y = { x, y, 3 }') - IOperation: (OperationKind.None) (Syntax: '{ x, y, 3 }') - Children(3): IOperation: (OperationKind.None) (Syntax: 'x') - Children(1): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') - IOperation: (OperationKind.None) (Syntax: 'y') - Children(1): IParameterReferenceExpression: y (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'y') - IOperation: (OperationKind.None) (Syntax: '3') - Children(1): ILiteralExpression (Text: 3) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') - IPropertyInitializer (Property: System.Collections.Generic.Dictionary Class.Z { get; set; }) (OperationKind.PropertyInitializerInCreation) (Syntax: 'Z = { { x, y } }') - IOperation: (OperationKind.None) (Syntax: '{ { x, y } }') - Children(1): IOperation: (OperationKind.None) (Syntax: '{ x, y }') - Children(2): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') - IParameterReferenceExpression: y (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'y') - IPropertyInitializer (Property: Class Class.C { get; set; }) (OperationKind.PropertyInitializerInCreation) (Syntax: 'C = { X = z }') - IOperation: (OperationKind.None) (Syntax: '{ X = z }') - Children(1): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) (Syntax: 'X = z') - Left: IOperation: (OperationKind.None) (Syntax: 'X') - Right: IParameterReferenceExpression: z (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'z') + Initializers(4): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) (Syntax: 'X = x') + Left: IOperation: (OperationKind.None) (Syntax: 'X') + Right: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Collections.Generic.List) (Syntax: 'Y = { x, y, 3 }') + Left: IOperation: (OperationKind.None) (Syntax: 'Y') + Right: IOperation: (OperationKind.None) (Syntax: '{ x, y, 3 }') + Children(3): IOperation: (OperationKind.None) (Syntax: 'x') + Children(1): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + IOperation: (OperationKind.None) (Syntax: 'y') + Children(1): IParameterReferenceExpression: y (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'y') + IOperation: (OperationKind.None) (Syntax: '3') + Children(1): ILiteralExpression (Text: 3) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Collections.Generic.Dictionary) (Syntax: 'Z = { { x, y } }') + Left: IOperation: (OperationKind.None) (Syntax: 'Z') + Right: IOperation: (OperationKind.None) (Syntax: '{ { x, y } }') + Children(1): IOperation: (OperationKind.None) (Syntax: '{ x, y }') + Children(2): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + IParameterReferenceExpression: y (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'y') + IAssignmentExpression (OperationKind.AssignmentExpression, Type: Class) (Syntax: 'C = { X = z }') + Left: IOperation: (OperationKind.None) (Syntax: 'C') + Right: IOperation: (OperationKind.None) (Syntax: '{ X = z }') + Children(1): IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) (Syntax: 'X = z') + Left: IOperation: (OperationKind.None) (Syntax: 'X') + Right: IParameterReferenceExpression: z (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'z') "; var expectedDiagnostics = DiagnosticDescription.None; diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.cs index dbc5ed2c4157d25303e8e3fb5c57cb209a0f20d7..7dc638e30f762ba91d4cd88fe32c87f3ea095992 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.cs @@ -332,113 +332,5 @@ class C VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } - - [Fact, WorkItem(17595, "https://github.com/dotnet/roslyn/issues/17595")] - public void MemberInitializerCSharp() - { - string source = @" -struct B -{ - public bool Field; -} - -class F -{ - public int Field; - public string Property1 { set; get; } - public B Property2 { set; get; } -} - -class C -{ - public void M1() - /**/{ - var x1 = new F(); - var x2 = new F() { Field = 2 }; - var x3 = new F() { Property1 = """""""" }; - var x4 = new F() { Property1 = """""""", Field = 2 }; - var x5 = new F() { Property2 = new B { Field = true } }; - - var e1 = new F() { Property2 = 1 }; - var e2 = new F() { """""""" }; - }/**/ -} -"; - string expectedOperationTree = @" -IBlockStatement (7 statements, 7 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: '{ ... }') - Locals: Local_1: F x1 - Local_2: F x2 - Local_3: F x3 - Local_4: F x4 - Local_5: F x5 - Local_6: F e1 - Local_7: F e2 - IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'var x1 = new F();') - IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'var x1 = new F();') - Variables: Local_1: F x1 - Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F) (Syntax: 'new F()') - IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'var x2 = ne ... ield = 2 };') - IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'var x2 = ne ... ield = 2 };') - Variables: Local_1: F x2 - Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F) (Syntax: 'new F() { Field = 2 }') - Member Initializers(1): IFieldInitializer (Field: System.Int32 F.Field) (OperationKind.FieldInitializerInCreation) (Syntax: 'Field = 2') - ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') - IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'var x3 = ne ... 1 = """""""" };') - IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'var x3 = ne ... 1 = """""""" };') - Variables: Local_1: F x3 - Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F, IsInvalid) (Syntax: 'new F() { P ... y1 = """""""" }') - Member Initializers(1): IPropertyInitializer (Property: System.String F.Property1 { get; set; }) (OperationKind.PropertyInitializerInCreation) (Syntax: 'Property1 = """"') - ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: """") (Syntax: '""""') - IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'var x4 = ne ... ield = 2 };') - IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'var x4 = ne ... ield = 2 };') - Variables: Local_1: F x4 - Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F, IsInvalid) (Syntax: 'new F() { P ... Field = 2 }') - Member Initializers(2): IPropertyInitializer (Property: System.String F.Property1 { get; set; }) (OperationKind.PropertyInitializerInCreation) (Syntax: 'Property1 = """"') - ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: """") (Syntax: '""""') - IFieldInitializer (Field: System.Int32 F.Field) (OperationKind.FieldInitializerInCreation) (Syntax: 'Field = 2') - ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') - IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'var x5 = ne ... = true } };') - IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'var x5 = ne ... = true } };') - Variables: Local_1: F x5 - Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F) (Syntax: 'new F() { P ... = true } }') - Member Initializers(1): IPropertyInitializer (Property: B F.Property2 { get; set; }) (OperationKind.PropertyInitializerInCreation) (Syntax: 'Property2 = ... ld = true }') - IObjectCreationExpression (Constructor: B..ctor()) (OperationKind.ObjectCreationExpression, Type: B) (Syntax: 'new B { Field = true }') - Member Initializers(1): IFieldInitializer (Field: System.Boolean B.Field) (OperationKind.FieldInitializerInCreation) (Syntax: 'Field = true') - ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) (Syntax: 'true') - IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'var e1 = ne ... rty2 = 1 };') - IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'var e1 = ne ... rty2 = 1 };') - Variables: Local_1: F e1 - Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F, IsInvalid) (Syntax: 'new F() { P ... erty2 = 1 }') - Member Initializers(1): IPropertyInitializer (Property: B F.Property2 { get; set; }) (OperationKind.PropertyInitializerInCreation, IsInvalid) (Syntax: 'Property2 = 1') - IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: B, IsInvalid) (Syntax: '1') - ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') - IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'var e2 = ne ... ) { """""""" };') - IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'var e2 = ne ... ) { """""""" };') - Variables: Local_1: F e2 - Initializer: IObjectCreationExpression (Constructor: F..ctor()) (OperationKind.ObjectCreationExpression, Type: F, IsInvalid) (Syntax: 'new F() { """""""" }') -"; - var expectedDiagnostics = new DiagnosticDescription[] { - // CS1003: Syntax error, ',' expected - // var x3 = new F() { Property1 = """" }; - Diagnostic(ErrorCode.ERR_SyntaxError, @"""""").WithArguments(",", "").WithLocation(20, 42), - // CS1003: Syntax error, ',' expected - // var x4 = new F() { Property1 = """", Field = 2 }; - Diagnostic(ErrorCode.ERR_SyntaxError, @"""""").WithArguments(",", "").WithLocation(21, 42), - // CS1003: Syntax error, ',' expected - // var e2 = new F() { """" }; - Diagnostic(ErrorCode.ERR_SyntaxError, @"""""").WithArguments(",", "").WithLocation(25, 30), - // CS0747: Invalid initializer member declarator - // var x3 = new F() { Property1 = """" }; - Diagnostic(ErrorCode.ERR_InvalidInitializerElementInitializer, @"""""").WithLocation(20, 42), - // CS0747: Invalid initializer member declarator - // var x4 = new F() { Property1 = """", Field = 2 }; - Diagnostic(ErrorCode.ERR_InvalidInitializerElementInitializer, @"""""").WithLocation(21, 42), - // CS0029: Cannot implicitly convert type 'int' to 'B' - // var e1 = new F() { Property2 = 1 }; - Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "B").WithLocation(24, 40) - }; - - VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); - } } } \ No newline at end of file diff --git a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs index 93bd76bd272834025a3c7d40fe1e5f3dc3fb968f..1188abb551c47b29741e0e42fc861085d904a95b 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs @@ -1522,11 +1522,11 @@ public override void Accept(OperationVisitor visitor) /// internal sealed partial class ObjectCreationExpression : Operation, IHasArgumentsExpression, IObjectCreationExpression { - public ObjectCreationExpression(IMethodSymbol constructor, ImmutableArray memberInitializers, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + public ObjectCreationExpression(IMethodSymbol constructor, ImmutableArray initializers, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : base(OperationKind.ObjectCreationExpression, isInvalid, syntax, type, constantValue) { Constructor = constructor; - MemberInitializers = memberInitializers; + Initializers = initializers; } /// /// Constructor to be invoked on the created instance. @@ -1535,7 +1535,7 @@ internal sealed partial class ObjectCreationExpression : Operation, IHasArgument /// /// Explicitly-specified member initializers. /// - public ImmutableArray MemberInitializers { get; } + public ImmutableArray Initializers { get; } public override void Accept(OperationVisitor visitor) { visitor.VisitObjectCreationExpression(this); diff --git a/src/Compilers/Core/Portable/Operations/IObjectCreationExpression.cs b/src/Compilers/Core/Portable/Operations/IObjectCreationExpression.cs index 9a06dedb54c60b963bba837d35f8113b39e88ee8..dfe2997af5ae3e20ea75388e24575d5e1d5941fc 100644 --- a/src/Compilers/Core/Portable/Operations/IObjectCreationExpression.cs +++ b/src/Compilers/Core/Portable/Operations/IObjectCreationExpression.cs @@ -18,9 +18,9 @@ public interface IObjectCreationExpression : IHasArgumentsExpression /// IMethodSymbol Constructor { get; } /// - /// Explicitly-specified member initializers. + /// List of member or collection initializer expressions in the object initializer, if any. /// - ImmutableArray MemberInitializers { get; } + ImmutableArray Initializers { get; } } } diff --git a/src/Compilers/Core/Portable/Operations/OperationWalker.cs b/src/Compilers/Core/Portable/Operations/OperationWalker.cs index aeed5ce40c37d1f8991e26ca699431c174449f33..f9798628922b0056412acc5370fb96a81967db9a 100644 --- a/src/Compilers/Core/Portable/Operations/OperationWalker.cs +++ b/src/Compilers/Core/Portable/Operations/OperationWalker.cs @@ -345,7 +345,7 @@ public override void VisitAddressOfExpression(IAddressOfExpression operation) public override void VisitObjectCreationExpression(IObjectCreationExpression operation) { VisitArray(operation.ArgumentsInEvaluationOrder); - VisitArray(operation.MemberInitializers); + VisitArray(operation.Initializers); } public override void VisitFieldInitializer(IFieldInitializer operation) diff --git a/src/Compilers/VisualBasic/Portable/BoundTree/Expression.vb b/src/Compilers/VisualBasic/Portable/BoundTree/Expression.vb index 029f3a6f4c82079991e22e9e7aab95d35256941f..73c08fcfe98c0ab57fc056fc175326d18f54a236 100644 --- a/src/Compilers/VisualBasic/Portable/BoundTree/Expression.vb +++ b/src/Compilers/VisualBasic/Portable/BoundTree/Expression.vb @@ -1155,8 +1155,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Friend Partial Class BoundObjectCreationExpression Implements IObjectCreationExpression - Private Shared ReadOnly s_memberInitializersMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundObjectCreationExpression, Object) - Private ReadOnly Property IObjectCreationExpression_Constructor As IMethodSymbol Implements IObjectCreationExpression.Constructor Get Return Me.ConstructorOpt @@ -1170,31 +1168,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property - Private ReadOnly Property IObjectCreationExpression_MemberInitializers As ImmutableArray(Of ISymbolInitializer) Implements IObjectCreationExpression.MemberInitializers - Get - Dim initializer = s_memberInitializersMappings.GetValue(Me, Function(objectCreationStatement) - Dim objectInitializerExpression As BoundObjectInitializerExpressionBase = Me.InitializerOpt - If objectInitializerExpression IsNot Nothing Then - Dim builder = ArrayBuilder(Of ISymbolInitializer).GetInstance(objectInitializerExpression.Initializers.Length) - For Each memberAssignment In objectInitializerExpression.Initializers - Dim assignment = TryCast(memberAssignment, BoundAssignmentOperator) - Dim left = assignment?.Left - If left IsNot Nothing Then - Select Case left.Kind - Case BoundKind.FieldAccess - builder.Add(New FieldInitializer(assignment.Syntax, DirectCast(left, BoundFieldAccess).FieldSymbol, assignment.Right)) - Case BoundKind.PropertyAccess - builder.Add(New PropertyInitializer(assignment.Syntax, DirectCast(left, BoundPropertyAccess).PropertySymbol, assignment.Right)) - End Select - End If - Next - Return builder.ToImmutableAndFree() - End If - - Return ImmutableArray(Of ISymbolInitializer).Empty - End Function) - - Return DirectCast(initializer, ImmutableArray(Of ISymbolInitializer)) + Private ReadOnly Property IObjectCreationExpression_Initializers As ImmutableArray(Of IOperation) Implements IObjectCreationExpression.Initializers + Get + Return If(Me.InitializerOpt IsNot Nothing, Me.InitializerOpt.Initializers.As(Of IOperation), ImmutableArray(Of IOperation).Empty) End Get End Property diff --git a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj index c12ac6254f277c2a8fd532dcdfdfc215798f0b67..019f9ff3a953095d1dd210ddf3f27701665d1737 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj +++ b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj @@ -108,6 +108,7 @@ + diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IObjectCreationExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IObjectCreationExpression.vb new file mode 100644 index 0000000000000000000000000000000000000000..232e15217842b781761bbf4f67110f2410f6f015 --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IObjectCreationExpression.vb @@ -0,0 +1,265 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax +Imports Roslyn.Test.Utilities + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics + + Partial Public Class IOperationTests + Inherits SemanticModelTestBase + + + Public Sub ObjectCreationWithMemberInitializers() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = .Value + + VerifyOperationTreeAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + Public Sub ObjectCreationWithCollectionInitializer() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of ObjectCreationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + Public Sub ObjectCreationWithNestedCollectionInitializer() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of ObjectCreationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + Public Sub ObjectCreationWithMemberAndCollectionInitializers() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of ObjectCreationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + End Class +End Namespace diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb index 65581f7e4b42962f237fd416fb5e05bc5ede6617..e3af89888feb6a01ad204387b64baf36c198e9d4 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb @@ -226,7 +226,7 @@ IOperation: (OperationKind.None) (Syntax: 'From y In x ... nto Count()') VerifyOperationTreeAndDiagnosticsForTest(Of QueryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics) End Sub - + Public Sub ParameterReference_ObjectAndCollectionInitializer() Dim source = .Value +End Class]]>.Value Dim expectedOperationTree = .Value Dim expectedDiagnostics = String.Empty diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.vb index 974d686a259cc302de6cb781d2d4a26de03eae5c..42dcdd99240a6223fecad3b1968701802c93eb52 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.vb @@ -269,99 +269,5 @@ IFieldInitializer (Field: C.i2 As System.Int32) (OperationKind.FieldInitializerA VerifyOperationTreeAndDiagnosticsForTest(Of EqualsValueSyntax)(source, expectedOperationTree, expectedDiagnostics) End Sub - - - Public Sub MemberInitializer() - Dim source = .Value - - Dim expectedOperationTree = .Value - - Dim expectedDiagnostics = .Value - - VerifyOperationTreeAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) - End Sub End Class End Namespace diff --git a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs index 95209b461d02a58df59201acfa1778bb3b56a961..4a0e6df980f3c1013dc206a15346d605f96bc4aa 100644 --- a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs +++ b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs @@ -879,7 +879,7 @@ public override void VisitObjectCreationExpression(IObjectCreationExpression ope LogCommonPropertiesAndNewLine(operation); VisitArguments(operation); - VisitArray(operation.MemberInitializers, "Member Initializers", logElementCount: true); + VisitArray(operation.Initializers, "Initializers", logElementCount: true); } public override void VisitFieldInitializer(IFieldInitializer operation)