Skip to content

Commit

Permalink
Merge pull request #19278 from mavasani/ObjectCreationExpression
Browse files Browse the repository at this point in the history
IObjectCreationExpression API Change
  • Loading branch information
mavasani authored May 9, 2017
2 parents bc9be6c + 1d9b64a commit c16e998
Show file tree
Hide file tree
Showing 16 changed files with 603 additions and 317 deletions.
38 changes: 1 addition & 37 deletions src/Compilers/CSharp/Portable/BoundTree/Expression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -515,43 +515,7 @@ internal partial class BoundObjectCreationExpression : IObjectCreationExpression

ImmutableArray<IArgument> IHasArgumentsExpression.ArgumentsInEvaluationOrder => BoundCall.DeriveArguments(this.Arguments, this.ArgumentNamesOpt, this.ArgsToParamsOpt, this.ArgumentRefKindsOpt, this.Constructor.Parameters, this.Syntax);

ImmutableArray<ISymbolInitializer> IObjectCreationExpression.MemberInitializers
{
get
{
return (ImmutableArray<ISymbolInitializer>)s_memberInitializersMappings.GetValue(this,
objectCreationExpression =>
{
var objectInitializerExpression = this.InitializerExpressionOpt as BoundObjectInitializerExpression;
if (objectInitializerExpression != null)
{
var builder = ArrayBuilder<ISymbolInitializer>.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<ISymbolInitializer>.Empty;
});
}
}
ImmutableArray<IOperation> IObjectCreationExpression.Initializers => GetChildInitializers(this.InitializerExpressionOpt).As<IOperation>();

internal static ImmutableArray<BoundExpression> GetChildInitializers(BoundExpression objectOrCollectionInitializer)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<Compile Include="IOperation\IOperationTests_IArgument.cs" />
<Compile Include="IOperation\IOperationTests_IIfStatement.cs" />
<Compile Include="IOperation\IOperationTests_IFieldReferenceExpression.cs" />
<Compile Include="IOperation\IOperationTests_IObjectCreationExpression.cs" />
<Compile Include="IOperation\IOperationTests_IParameterReferenceExpression.cs" />
<Compile Include="IOperation\IOperationTests_ISymbolInitializer.cs" />
<Compile Include="IOperation\IOperationTests_InvalidExpression.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@ public void M3()
);
}

[Fact]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/19300")]
public void MemberInitializerCSharp()
{
const string source = @"
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -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<System.Int32> 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<System.Int32, System.Int32> 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<System.Int32>) (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<System.Int32, System.Int32>) (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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,113 +332,5 @@ class C

VerifyOperationTreeAndDiagnosticsForTest<EqualsValueClauseSyntax>(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()
/*<bind>*/{
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() { """""""" };
}/*</bind>*/
}
";
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<BlockSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1522,11 +1522,11 @@ public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, T
/// </remarks>
internal sealed partial class ObjectCreationExpression : Operation, IHasArgumentsExpression, IObjectCreationExpression
{
public ObjectCreationExpression(IMethodSymbol constructor, ImmutableArray<ISymbolInitializer> memberInitializers, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
public ObjectCreationExpression(IMethodSymbol constructor, ImmutableArray<IOperation> initializers, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(OperationKind.ObjectCreationExpression, isInvalid, syntax, type, constantValue)
{
Constructor = constructor;
MemberInitializers = memberInitializers;
Initializers = initializers;
}
/// <summary>
/// Constructor to be invoked on the created instance.
Expand All @@ -1535,7 +1535,7 @@ public ObjectCreationExpression(IMethodSymbol constructor, ImmutableArray<ISymbo
/// <summary>
/// Explicitly-specified member initializers.
/// </summary>
public ImmutableArray<ISymbolInitializer> MemberInitializers { get; }
public ImmutableArray<IOperation> Initializers { get; }
public override void Accept(OperationVisitor visitor)
{
visitor.VisitObjectCreationExpression(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ public interface IObjectCreationExpression : IHasArgumentsExpression
/// </summary>
IMethodSymbol Constructor { get; }
/// <summary>
/// Explicitly-specified member initializers.
/// List of member or collection initializer expressions in the object initializer, if any.
/// </summary>
ImmutableArray<ISymbolInitializer> MemberInitializers { get; }
ImmutableArray<IOperation> Initializers { get; }
}
}

2 changes: 1 addition & 1 deletion src/Compilers/Core/Portable/Operations/OperationWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit c16e998

Please sign in to comment.