Test plan for "null-conditional assignment"
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
Championed issue: https://github.com/dotnet/csharplang/issues/8677
Speclet: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-14.0/null-conditional-assignment.md
Label: https://github.com/dotnet/roslyn/labels/Feature%20-%20Null%20Conditional%20Assignment
Feature branch: https://github.com/dotnet/roslyn/tree/features/null-conditional-assignment
## Compiler
- [x] language version
- [x] parsing / syntax model does *not* depend on language version (`NullConditionalAssignmentParsingTests`)
- [x] member and element assignment (`LangVersion_*`)
- [x] compound assignment: (`LangVersion_03`)
- [x] parsing (`NullConditionalAssignmentParsingTests.VariousAssignmentKinds_LeftMemberAccess`)
- [x] arithmetic operators: `+=`, etc. (`CompoundAssignment_01`)
- [ ] logical operators: `|=`, etc.
- [ ] shift operators: `<<=`, etc.
- [x] increment, decrement (disallowed): `a?.B++`, `--a?.B` (`IncrementDecrement_01`)
- [x] member kinds:
- [x] field
- [x] property
- [x] event
- [x] method
- [x] null coalescing: `a?.B ??= c` (`NullCoalescingAssignment_01`)
- [x] nested:
- [x] `a?.b?.c = d` (`PropertyAccessAssignment_Nested_01`)
- [x] `a?.b = c?.d = e?.f` (`FieldAccessAssignment_Nested_03`)
- [x] `a?.b = c ?? d` (`NullConditionalAssignmentParsingTests.NullCoalescing_LeftMemberAccess`)
- [x] readonly member
- [ ] readonly indexer
- [x] `struct` receiver (`FieldAccessAssignment_StructReceiver_*`)
- [x] readonly member
- [x] `ref` returning member (`AssignRefReturningMethod_01`)
- [ ] cases from [*Readonly setter calls on non-variables*](https://github.com/dotnet/csharplang/blob/main/proposals/readonly-setter-calls-on-non-variables.md)
- [ ] spec explicitly the limitations around structs
- [ ] `a?.B = c` where `B` is `init` property
- [ ] inline array with conditional element assignment
- [ ] Expression trees (disallowed)
- [ ] `dynamic` receiver
- [ ] `*s?.P = e`
- [x] use result: `(a?.B = c)?.ToString()`
- [ ] member with reference type
- [x] member with value type
- [x] member with type parameter type: (`TypeParameter_*`)
- [x] unconstrained (disallowed)
- [x] `struct` constraint
- [x] `class` constraint
- [ ] element assignment
- [ ] evaluation:
- [x] receiver evaluated exactly once (`FieldAccessAssignment_Nested_03`)
- [x] RHS evaluated conditionally (`FieldAccessAssignment_Nested_03`)
- [ ] element index evaluated conditionally
- [ ] member arguments evaluated conditionally
- [x] using result (`FieldAccessAssignment_Nested_04`)
- [x] ref assignment (disallowed): `a?.B = ref c` (`RefAssignment_01`)
- [x] deconstruction assignment (disallowed): `(a?.B, c?.D) = (x, y)` (`DeconstructionLeft`)
- [ ] await: `(await a)?.B = c`
- [ ] definite assignment
- [x] receiver not definitely assigned (`DefiniteAssignment_01`)
- [ ] variable only assigned or used in RHS
- [ ] variable only assigned or used in member arguments
- [ ] nullable analysis
- [x] receiver maybe null after `a?.B = c` (`NullableAnalysis_01`)
- [x] receiver and member not null after checking result (`NullableAnalysis_01`)
- [ ] `a?.B = a.C;` should not warn for `a.C`
- [ ] suppression operator: `a?.B! = c`
- [ ] ~~Semantic model~~ (no changes)
- [ ] ~~`IOperation`~~ (no changes)
- [x] CFG (`ConditionalAccessFlow_06`, `_07`)
- [ ] null-coalescing assignment: `??=` (ensure assignment in correct branch of CFG)
- [ ] conditional receiver: `(c ? a : b)?.D = e`
- [ ] ~~Public API~~ (no changes)
## Productivity
- [x] formatting
- [x] Quick info for member
- [x] Go to Definition for member
- [x] Refactoring from existing code
- [x] Generate member for `a?.b = c` #77526
Contributor guide
Assessment
This issue has not been assessed yet.