roslyn
roslyn copied to clipboard
Primary constructor (properties) have sequence points but breakpoints can't be placed
Currently the emitted metadata/pdb for primary constructors are incompatible with the implementation of several IDE features (breakpoint placement, EnC, code coverage):
- The synthesized constructor assigns parameters to backing fields directly. A sequence point is emitted for the entire constructor and additional sequence point is emitted for each backing field assignment.
Stepping into new C(1,2)
makes 3 steps in the constructor:
Step 1:
Step 2:
Step 3:
If the record declaration has a body the entire declaration is active, which is odd:
-
The accessors generated for properties specified in primary constructors have sequence points and are not marked by
[CompilerGenerated]
attribute. When debugging the debugger allows to step into to property accessor and the active statement (yellow span) is displayed over the parameter syntax (note: the user may have stepping into properties disabled:). This causes code coverage tools to report uncovered code (see https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1567458).
-
The IDE does not allow placing breakpoints on the syntax of the parameters.
I think we should consider:
- Instead of assigning to the backing field the constructor emits call to the property setter. This would also fix https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1567458.
- Make the constructor non-user code (remove all sequence points emitted to the constructor) and mark it
[CompilerGenerated]
. - Allow placing breakpoint on any primary constructor parameter in the IDE. Two breakpoints would be placed: onto the getter and onto the setter.
- Fix EnC to account for these breakpoints. Edits inserting whitespace into the primary constructor declaration, or code around the entire declaration are currently broken. E.g.
Related: https://github.com/dotnet/csharplang/discussions/5999
@davidwengier FYI
What's the effect of placing CompilerGenerated on the constructor? It prevents the debugger from stepping in?
What's the effect of placing CompilerGenerated on the constructor? It prevents the debugger from stepping in?
CompilerGenerated has no effect on debugging.
Fixed by https://github.com/dotnet/roslyn/pull/68765