Adjust IAnonymousPropertyOperation to be resilient to nullability changes.

上级 48df9006
......@@ -395,9 +395,9 @@ internal static ImmutableArray<BoundNode> CreateInvalidChildrenFromArgumentsExpr
isImplicit: true);
// Find matching declaration for the current argument.
IPropertySymbol property = AnonymousTypeManager.GetAnonymousTypeProperty((NamedTypeSymbol)type, i);
if (currentDeclarationIndex >= declarations.Length ||
(object)property != declarations[currentDeclarationIndex].Property)
PropertySymbol property = AnonymousTypeManager.GetAnonymousTypeProperty((NamedTypeSymbol)type, i);
BoundAnonymousPropertyDeclaration anonymousProperty = getDeclaration(declarations, property, ref currentDeclarationIndex);
if (anonymousProperty is null)
{
// No matching declaration, synthesize a property reference to be assigned.
target = new PropertyReferenceOperation(
......@@ -413,7 +413,6 @@ internal static ImmutableArray<BoundNode> CreateInvalidChildrenFromArgumentsExpr
}
else
{
BoundAnonymousPropertyDeclaration anonymousProperty = declarations[currentDeclarationIndex++];
target = new PropertyReferenceOperation(anonymousProperty.Property,
instance,
ImmutableArray<IArgumentOperation>.Empty,
......@@ -435,6 +434,28 @@ internal static ImmutableArray<BoundNode> CreateInvalidChildrenFromArgumentsExpr
Debug.Assert(currentDeclarationIndex == declarations.Length);
return builder.ToImmutableAndFree();
static BoundAnonymousPropertyDeclaration getDeclaration(ImmutableArray<BoundAnonymousPropertyDeclaration> declarations, PropertySymbol currentProperty, ref int currentDeclarationIndex)
{
if (currentDeclarationIndex >= declarations.Length)
{
return null;
}
var currentDeclaration = declarations[currentDeclarationIndex];
// https://github.com/dotnet/roslyn/issues/35044: This works for simple success cases, but does not work for failures. Likely will have to do something more complicated here involving rebinding the
// declarators based on the newly constructed anonymous type symbol above and matching them to the existing symbol
if ((object)currentProperty == currentDeclaration.Property ||
(currentDeclaration.Property.Name == currentProperty.Name &&
currentDeclaration.Property.Type.Equals(currentProperty.Type, TypeCompareKind.ConsiderEverything | TypeCompareKind.AllNullableIgnoreOptions)))
{
currentDeclarationIndex++;
return currentDeclaration;
}
return null;
}
}
internal class Helper
......
......@@ -1639,5 +1639,46 @@ void M(object p, int? i1, int i2, int? j1, int j2)
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
}
[Fact]
public void AnonymousObjectCreation_NullableEnabled_PropertyMatches()
{
var source = @"
#nullable enable
class C
{
void M(int i1, object o1)
{
var obj = /*<bind>*/new { a = i1, o1, b = ""Hello world!"" }/*</bind>*/;
}
}";
var expectedOperationTree = @"
IAnonymousObjectCreationOperation (OperationKind.AnonymousObjectCreation, Type: <anonymous type: System.Int32 a, System.Object o1, System.String b>) (Syntax: 'new { a = i ... o world!"" }')
Initializers(3):
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'a = i1')
Left:
IPropertyReferenceOperation: System.Int32 <anonymous type: System.Int32 a, System.Object o1, System.String b>.a { get; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'a')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: <anonymous type: System.Int32 a, System.Object o1, System.String b>, IsImplicit) (Syntax: 'new { a = i ... o world!"" }')
Right:
IParameterReferenceOperation: i1 (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'i1')
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Object, IsImplicit) (Syntax: 'o1')
Left:
IPropertyReferenceOperation: System.Object <anonymous type: System.Int32 a, System.Object o1, System.String b>.o1 { get; } (OperationKind.PropertyReference, Type: System.Object, IsImplicit) (Syntax: 'o1')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: <anonymous type: System.Int32 a, System.Object o1, System.String b>, IsImplicit) (Syntax: 'new { a = i ... o world!"" }')
Right:
IParameterReferenceOperation: o1 (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o1')
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.String, Constant: ""Hello world!"") (Syntax: 'b = ""Hello world!""')
Left:
IPropertyReferenceOperation: System.String <anonymous type: System.Int32 a, System.Object o1, System.String b>.b { get; } (OperationKind.PropertyReference, Type: System.String) (Syntax: 'b')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: <anonymous type: System.Int32 a, System.Object o1, System.String b>, IsImplicit) (Syntax: 'new { a = i ... o world!"" }')
Right:
ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: ""Hello world!"") (Syntax: '""Hello world!""')";
VerifyOperationTreeAndDiagnosticsForTest<AnonymousObjectCreationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics: DiagnosticDescription.None);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册