-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow with
on anonymous types
#53248
Changes from 3 commits
1365a81
302fbcc
ff57fe8
dc0c581
85b60cf
ff73199
13ceeb7
ef7097e
f930d4b
0e97cf9
2bad303
9f3cdac
3a6e4e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7201,6 +7201,25 @@ IOperation handleAnonymousTypeWithExpression(WithOperation operation, int? captu | |
foreach (IOperation initializer in initializers) | ||
{ | ||
var simpleAssignment = (ISimpleAssignmentOperation)initializer; | ||
|
||
int valueCaptureId = GetNextCaptureId(outerCaptureRegion); | ||
VisitAndCapture(simpleAssignment.Value, valueCaptureId); | ||
LeaveRegionsUpTo(innerCaptureRegion); | ||
var valueCaptureRef = new FlowCaptureReferenceOperation(valueCaptureId, operation.Operand.Syntax, | ||
operation.Operand.Type, constantValue: operation.Operand.GetConstantValue()); | ||
|
||
if (simpleAssignment.Target is InvalidOperation) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that it would be better to use the following error recovery strategy. Anything that we cannot reliably translate to an Anonymous Type property assignment we are simply visting, adding as a statement and forgetting without capturing it and adding fake assignments in AnonymousObjectCreationOperation. We should also see what to do with duplicate initializers for the same property, I think those should be "skipped" in a similar manner. #Closed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{ | ||
var badTarget = new InvalidOperation(ImmutableArray<IOperation>.Empty, semanticModel: null, simpleAssignment.Target.Syntax, | ||
type: null, constantValue: null, isImplicit: true); | ||
|
||
var badAssignment = new SimpleAssignmentOperation(isRef: false, badTarget, valueCaptureRef, | ||
semanticModel: null, operation.Syntax, valueCaptureRef.Type, constantValue: null, isImplicit: true); | ||
|
||
initializerBuilder.Add(badAssignment); | ||
continue; | ||
} | ||
|
||
var propertyReference = (IPropertyReferenceOperation)simpleAssignment.Target; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think so. Nested initializers and indexing initializers are parsing errors. Expressions fall into the InvalidOperation check above. |
||
|
||
Debug.Assert(propertyReference != null); | ||
|
@@ -7209,12 +7228,6 @@ IOperation handleAnonymousTypeWithExpression(WithOperation operation, int? captu | |
Debug.Assert(propertyReference.Instance.Kind == OperationKind.InstanceReference); | ||
Debug.Assert(((IInstanceReferenceOperation)propertyReference.Instance).ReferenceKind == InstanceReferenceKind.ImplicitReceiver); | ||
|
||
int valueCaptureId = GetNextCaptureId(outerCaptureRegion); | ||
VisitAndCapture(simpleAssignment.Value, valueCaptureId); | ||
LeaveRegionsUpTo(innerCaptureRegion); | ||
var valueCaptureRef = new FlowCaptureReferenceOperation(valueCaptureId, operation.Operand.Syntax, | ||
operation.Operand.Type, constantValue: operation.Operand.GetConstantValue()); | ||
|
||
var property = propertyReference.Property; | ||
var assignment = makeAssignment(property, valueCaptureRef, operation); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1369,6 +1369,12 @@ public override void VisitAnonymousObjectCreation(IAnonymousObjectCreationOperat | |
foreach (var initializer in operation.Initializers) | ||
{ | ||
var simpleAssignment = (ISimpleAssignmentOperation)initializer; | ||
if (simpleAssignment.Target is InvalidOperation) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{ | ||
// We construct such nodes for `with` expressions on anonymous types | ||
continue; | ||
} | ||
|
||
var propertyReference = (IPropertyReferenceOperation)simpleAssignment.Target; | ||
Assert.Empty(propertyReference.Arguments); | ||
Assert.Equal(OperationKind.InstanceReference, propertyReference.Instance.Kind); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -869,6 +869,12 @@ public override void VisitAnonymousObjectCreation(IAnonymousObjectCreationOperat | |
foreach (var initializer in operation.Initializers) | ||
{ | ||
var simpleAssignment = (ISimpleAssignmentOperation)initializer; | ||
if (simpleAssignment.Target is InvalidOperation) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{ | ||
// We construct such nodes for `with` expressions on anonymous types | ||
continue; | ||
} | ||
|
||
var propertyReference = (IPropertyReferenceOperation)simpleAssignment.Target; | ||
Assert.Empty(propertyReference.Arguments); | ||
Assert.Equal(OperationKind.InstanceReference, propertyReference.Instance.Kind); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,6 +84,7 @@ protected override Task<CompletionDescription> GetDescriptionWorkerAsync(Documen | |
private static bool IsLegalFieldOrProperty(ISymbol symbol) | ||
{ | ||
return symbol.IsWriteableFieldOrProperty() | ||
|| symbol.ContainingType.IsAnonymousType | ||
|| CanSupportObjectInitializer(symbol); | ||
Comment on lines
+87
to
88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if the new check should be moved to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i'm fine with either approach. |
||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment about the cast as in setAllProperties #Closed