未验证 提交 7bae11e1 编写于 作者: F Fred Silberberg 提交者: GitHub

Merge pull request #27308 from 333fred/dynamic-collection-initializers

Support Dynamic Collection Initializers
......@@ -615,7 +615,7 @@ private IObjectOrCollectionInitializerOperation CreateBoundCollectionInitializer
return new LazyObjectOrCollectionInitializerExpression(initializers, _semanticModel, syntax, type, constantValue, isImplicit);
}
private IOperation CreateBoundObjectInitializerMemberOperation(BoundObjectInitializerMember boundObjectInitializerMember)
private IOperation CreateBoundObjectInitializerMemberOperation(BoundObjectInitializerMember boundObjectInitializerMember, bool isObjectOrCollectionInitializer = false)
{
Symbol memberSymbol = boundObjectInitializerMember.MemberSymbol;
......@@ -664,7 +664,9 @@ private IOperation CreateBoundObjectInitializerMemberOperation(BoundObjectInitia
}
else
{
var accessor = property.GetOwnOrInheritedSetMethod();
// In nested member initializers, the property is not actually set. Instead, it is retrieved for a series of Add method calls or nested property setter calls,
// so we need to use the getter for this property
MethodSymbol accessor = isObjectOrCollectionInitializer ? property.GetOwnOrInheritedGetMethod() : property.GetOwnOrInheritedSetMethod();
if (accessor == null || boundObjectInitializerMember.ResultKind == LookupResultKind.OverloadResolutionFailure || accessor.OriginalDefinition is ErrorMethodSymbol)
{
Lazy<ImmutableArray<IOperation>> children = new Lazy<ImmutableArray<IOperation>>(() =>
......@@ -765,7 +767,10 @@ private IDynamicInvocationOperation CreateBoundDynamicCollectionElementInitializ
ITypeSymbol type = boundCollectionElementInitializer.Type;
Optional<object> constantValue = ConvertToOptional(boundCollectionElementInitializer.ConstantValue);
bool isImplicit = boundCollectionElementInitializer.WasCompilerGenerated;
return new LazyDynamicInvocationExpression(operation, arguments, argumentNames: ImmutableArray<string>.Empty, argumentRefKinds: ImmutableArray<RefKind>.Empty, _semanticModel, syntax, type, constantValue, isImplicit);
BoundImplicitReceiver implicitReceiver = boundCollectionElementInitializer.ImplicitReceiver;
Lazy<IOperation> addReference = new Lazy<IOperation>(() =>
CreateBoundDynamicMemberAccessOperation(implicitReceiver, typeArgumentsOpt: ImmutableArray<TypeSymbol>.Empty, memberName: "Add", implicitReceiver.Syntax, type: null, value: default, isImplicit: true));
return new LazyDynamicInvocationExpression(addReference, arguments, argumentNames: ImmutableArray<string>.Empty, argumentRefKinds: ImmutableArray<RefKind>.Empty, _semanticModel, syntax, type, constantValue, isImplicit);
}
private IOperation CreateUnboundLambdaOperation(UnboundLambda unboundLambda)
......@@ -1067,7 +1072,17 @@ private IMemberInitializerOperation CreateBoundMemberInitializerOperation(BoundA
{
Debug.Assert(IsMemberInitializer(boundAssignmentOperator));
Lazy<IOperation> target = new Lazy<IOperation>(() => Create(boundAssignmentOperator.Left));
Lazy<IOperation> target = new Lazy<IOperation>(() => {
// We can have bad expressions on the left, fall back to standard creation if that's this case
if (boundAssignmentOperator.Left.Kind == BoundKind.ObjectInitializerMember)
{
return _cache.GetOrAdd(boundAssignmentOperator.Left, key => CreateBoundObjectInitializerMemberOperation((BoundObjectInitializerMember)key, isObjectOrCollectionInitializer: true));
}
else
{
return Create(boundAssignmentOperator.Left);
}
});
Lazy<IObjectOrCollectionInitializerOperation> value = new Lazy<IObjectOrCollectionInitializerOperation>(() => (IObjectOrCollectionInitializerOperation)Create(boundAssignmentOperator.Right));
SyntaxNode syntax = boundAssignmentOperator.Syntax;
ITypeSymbol type = boundAssignmentOperator.Type;
......
......@@ -425,6 +425,9 @@ public void M(int x, int y)
Initializers(1):
IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: System.Void) (Syntax: '{ x, y }')
Expression:
IDynamicMemberReferenceOperation (Member Name: ""Add"", Containing Type: null) (OperationKind.DynamicMemberReference, Type: null, IsImplicit) (Syntax: 'X')
Type Arguments(0)
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: dynamic, IsImplicit) (Syntax: 'X')
Arguments(2):
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x')
......
......@@ -423,6 +423,9 @@ public static void DisplayCollection<T>(IEnumerable<T> collection)
Initializers(1):
IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: System.Void, IsImplicit) (Syntax: '1')
Expression:
IDynamicMemberReferenceOperation (Member Name: ""Add"", Containing Type: null) (OperationKind.DynamicMemberReference, Type: null, IsImplicit) (Syntax: 'list')
Type Arguments(0)
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: dynamic, IsImplicit) (Syntax: 'list')
Arguments(1):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
......
......@@ -70,10 +70,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim result = New BoundLateMemberAccess(node, name, containerType, receiver, boundTypeArguments, LateBoundAccessKind.Unknown, objType)
If receiver IsNot Nothing AndAlso Not receiver.WasCompilerGenerated AndAlso result.Syntax Is receiver.Syntax Then
result.SetWasCompilerGenerated()
End If
Return result
End Function
......
......@@ -2641,6 +2641,335 @@ Block[B8] - Exit
VerifyFlowGraphAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedFlowGraph, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)>
<Fact()>
Public Sub ObjectCreationFlow_15()
Dim source = <![CDATA[
Imports System
Imports System.Collections
Imports System.Collections.Generic
Class C1
Implements IEnumerable(Of Integer)
Sub M(c As C1, o1 as Object, o2 As Object)'BIND:"Sub M(c As C1, o1 as Object, o2 As Object)"
c = New C1() From {o1, o2}
End Sub
Public Function GetEnumerator() As IEnumerator(Of Integer) Implements IEnumerable(Of Integer).GetEnumerator
Throw New NotImplementedException()
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Throw New NotImplementedException()
End Function
Public Sub Add(i As Integer)
End Sub
Public Sub Add(l As Long)
End Sub
End Class]]>.Value
Dim expectedDiagnostics = String.Empty
Dim expectedFlowGraph = <![CDATA[
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Block[B1] - Block
Predecessors: [B0]
Statements (5)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: C1) (Syntax: 'c')
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'New C1() From {o1, o2}')
Value:
IObjectCreationOperation (Constructor: Sub C1..ctor()) (OperationKind.ObjectCreation, Type: C1) (Syntax: 'New C1() From {o1, o2}')
Arguments(0)
Initializer:
null
IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: System.Object, IsImplicit) (Syntax: 'o1')
Expression:
IDynamicMemberReferenceOperation (Member Name: "Add", Containing Type: null) (OperationKind.DynamicMemberReference, Type: System.Object, IsImplicit) (Syntax: 'o1')
Type Arguments(0)
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() From {o1, o2}')
Arguments(1):
IParameterReferenceOperation: o1 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o1')
ArgumentNames(0)
ArgumentRefKinds: null
IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: System.Object, IsImplicit) (Syntax: 'o2')
Expression:
IDynamicMemberReferenceOperation (Member Name: "Add", Containing Type: null) (OperationKind.DynamicMemberReference, Type: System.Object, IsImplicit) (Syntax: 'o2')
Type Arguments(0)
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() From {o1, o2}')
Arguments(1):
IParameterReferenceOperation: o2 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o2')
ArgumentNames(0)
ArgumentRefKinds: null
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'c = New C1( ... om {o1, o2}')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C1, IsImplicit) (Syntax: 'c = New C1( ... om {o1, o2}')
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'c')
Right:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() From {o1, o2}')
Next (Regular) Block[B2]
Block[B2] - Exit
Predecessors: [B1]
Statements (0)
]]>.Value
VerifyFlowGraphAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedFlowGraph, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)>
<Fact()>
Public Sub ObjectCreationFlow_16()
Dim source = <![CDATA[
Imports System
Imports System.Collections
Imports System.Collections.Generic
Class C1
Implements IEnumerable(Of Integer)
Sub M(c As C1, o1 as Object, o2 As Object, o3 As Object)'BIND:"Sub M(c As C1, o1 as Object, o2 As Object, o3 As Object)"
c = New C1() From {o1, If(o2, o3)}
End Sub
Public Function GetEnumerator() As IEnumerator(Of Integer) Implements IEnumerable(Of Integer).GetEnumerator
Throw New NotImplementedException()
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Throw New NotImplementedException()
End Function
Public Sub Add(i As Integer)
End Sub
Public Sub Add(l As Long)
End Sub
End Class]]>.Value
Dim expectedDiagnostics = String.Empty
Dim expectedFlowGraph = <![CDATA[
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Block[B1] - Block
Predecessors: [B0]
Statements (4)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: C1) (Syntax: 'c')
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'New C1() Fr ... If(o2, o3)}')
Value:
IObjectCreationOperation (Constructor: Sub C1..ctor()) (OperationKind.ObjectCreation, Type: C1) (Syntax: 'New C1() Fr ... If(o2, o3)}')
Arguments(0)
Initializer:
null
IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: System.Object, IsImplicit) (Syntax: 'o1')
Expression:
IDynamicMemberReferenceOperation (Member Name: "Add", Containing Type: null) (OperationKind.DynamicMemberReference, Type: System.Object, IsImplicit) (Syntax: 'o1')
Type Arguments(0)
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() Fr ... If(o2, o3)}')
Arguments(1):
IParameterReferenceOperation: o1 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o1')
ArgumentNames(0)
ArgumentRefKinds: null
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'o2')
Value:
IParameterReferenceOperation: o2 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o2')
Jump if True (Regular) to Block[B3]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'o2')
Operand:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'o2')
Next (Regular) Block[B2]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'o2')
Value:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'o2')
Next (Regular) Block[B4]
Block[B3] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'o3')
Value:
IParameterReferenceOperation: o3 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o3')
Next (Regular) Block[B4]
Block[B4] - Block
Predecessors: [B2] [B3]
Statements (2)
IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: System.Object, IsImplicit) (Syntax: 'If(o2, o3)')
Expression:
IDynamicMemberReferenceOperation (Member Name: "Add", Containing Type: null) (OperationKind.DynamicMemberReference, Type: System.Object, IsImplicit) (Syntax: 'If(o2, o3)')
Type Arguments(0)
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() Fr ... If(o2, o3)}')
Arguments(1):
IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'If(o2, o3)')
ArgumentNames(0)
ArgumentRefKinds: null
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'c = New C1( ... If(o2, o3)}')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C1, IsImplicit) (Syntax: 'c = New C1( ... If(o2, o3)}')
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'c')
Right:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() Fr ... If(o2, o3)}')
Next (Regular) Block[B5]
Block[B5] - Exit
Predecessors: [B4]
Statements (0)
]]>.Value
VerifyFlowGraphAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedFlowGraph, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)>
<Fact()>
Public Sub ObjectCreationFlow_17()
Dim source = <![CDATA[
Imports System
Imports System.Collections
Imports System.Collections.Generic
Class C1
Implements IEnumerable(Of Integer)
Sub M(c As C1, o1 as Object, o2 As Object, o3 As Object)'BIND:"Sub M(c As C1, o1 as Object, o2 As Object, o3 As Object)"
c = New C1() From {{1, 2}, {o1, If(o2, o3)}}
End Sub
Public Function GetEnumerator() As IEnumerator(Of Integer) Implements IEnumerable(Of Integer).GetEnumerator
Throw New NotImplementedException()
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Throw New NotImplementedException()
End Function
Public Sub Add(i1 As Integer, i2 As Integer)
End Sub
Public Sub Add(l1 As Long, l2 As Long)
End Sub
End Class]]>.Value
Dim expectedDiagnostics = String.Empty
Dim expectedFlowGraph = <![CDATA[
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Block[B1] - Block
Predecessors: [B0]
Statements (5)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'c')
Value:
IParameterReferenceOperation: c (OperationKind.ParameterReference, Type: C1) (Syntax: 'c')
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'New C1() Fr ... f(o2, o3)}}')
Value:
IObjectCreationOperation (Constructor: Sub C1..ctor()) (OperationKind.ObjectCreation, Type: C1) (Syntax: 'New C1() Fr ... f(o2, o3)}}')
Arguments(0)
Initializer:
null
IInvocationOperation ( Sub C1.Add(i1 As System.Int32, i2 As System.Int32)) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: '{1, 2}')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() Fr ... f(o2, o3)}}')
Arguments(2):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i1) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i2) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: '2')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'o1')
Value:
IParameterReferenceOperation: o1 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o1')
IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'o2')
Value:
IParameterReferenceOperation: o2 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o2')
Jump if True (Regular) to Block[B3]
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'o2')
Operand:
IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'o2')
Next (Regular) Block[B2]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 4 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'o2')
Value:
IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'o2')
Next (Regular) Block[B4]
Block[B3] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 4 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'o3')
Value:
IParameterReferenceOperation: o3 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o3')
Next (Regular) Block[B4]
Block[B4] - Block
Predecessors: [B2] [B3]
Statements (2)
IDynamicInvocationOperation (OperationKind.DynamicInvocation, Type: System.Object, IsImplicit) (Syntax: '{o1, If(o2, o3)}')
Expression:
IDynamicMemberReferenceOperation (Member Name: "Add", Containing Type: null) (OperationKind.DynamicMemberReference, Type: System.Object, IsImplicit) (Syntax: '{o1, If(o2, o3)}')
Type Arguments(0)
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() Fr ... f(o2, o3)}}')
Arguments(2):
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'o1')
IFlowCaptureReferenceOperation: 4 (OperationKind.FlowCaptureReference, Type: System.Object, IsImplicit) (Syntax: 'If(o2, o3)')
ArgumentNames(0)
ArgumentRefKinds: null
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'c = New C1( ... f(o2, o3)}}')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C1, IsImplicit) (Syntax: 'c = New C1( ... f(o2, o3)}}')
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'c')
Right:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C1, IsImplicit) (Syntax: 'New C1() Fr ... f(o2, o3)}}')
Next (Regular) Block[B5]
Block[B5] - Exit
Predecessors: [B4]
Statements (0)
]]>.Value
VerifyFlowGraphAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedFlowGraph, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)>
<Fact()>
Public Sub ObjectCreationFlow_18()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册