You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Multi-line expression bodies (ExpressionBodyFactory / AccessorKind.Expression) lose indentation on every line after the first #112
PropertyTemplate (CodeBlocker/Templates/PropertyTemplate.cs:56, ExpressionBodyFactory) and AccessorTemplate (CodeBlocker/Templates/AccessorTemplate.cs:95, AccessorKind.Expression) render the expression fragment and pass it to codeBlocker.Write(...) as one string.
IndentedTextWriter only indents at the start of a Write/WriteLine call, not after newlines embedded in the string. So every continuation line of the fragment lands at the fragment's own indent, not the enclosing one.
TemplateRendering.SpliceFragment was introduced to fix exactly this ("a nested body used to come out flush against the left margin"). It is applied to WriteBody and to block accessors, but not to these two expression paths.
Reproduction (ran)
A ClassTemplateC containing PropertyTemplatepublic int X, whose ExpressionBodyFactory writes a switch expression:
k switch
{
_ => 0,
}
Actual: \tpublic int X => k switch\n{\n\t_ => 0,\n}; (the brace and the arm are one level too shallow).
Expected: \tpublic int X => k switch\n\t{\n\t\t_ => 0,\n\t};
If the factory ends with WriteLine, the trailing ; also ends up alone on its own line.
Why it matters
Switch expressions, collection expressions and object initializers are the typical multi-line expression bodies, and they all come out mis-indented. That breaks golden-file tests and any consumer that formats or diffs the generated code.
Suggested fix / acceptance criteria
Split the fragment with TemplateRendering.SplitLines.
Write the first line inline after =>.
Emit the remaining lines through the same path SpliceFragment uses so they pick up the current indent.
Append ; to the last line, not to a trailing empty line.
Add tests for a nested multi-line expression-bodied property and accessor.
Priority: Medium. The generated code still compiles, but it is mis-indented. That breaks golden-file tests and diffs for switch expressions, collection expressions and initializers.
Area / suggested assignee: The expression-body paths in PropertyTemplate (ExpressionBodyFactory) and AccessorTemplate (AccessorKind.Expression), reusing TemplateRendering.SpliceFragment / SplitLines. Maintainer: @matt-edmondson.
Next steps: Write the first line inline after =>, splice the remaining lines at the current indent, and put ; on the last non-empty line. Add nested tests for a multi-line property and a multi-line accessor.
Activity
matt-edmondson commentedon Sep 26, 2026
Triage
PropertyTemplate(ExpressionBodyFactory) andAccessorTemplate(AccessorKind.Expression), reusingTemplateRendering.SpliceFragment/SplitLines. Maintainer: @matt-edmondson."or\in DefaultValue generates C# that doesn't compile #111 change template rendering, so they can go in one PR.=>, splice the remaining lines at the current indent, and put;on the last non-empty line. Add nested tests for a multi-line property and a multi-line accessor.Generated by Claude Code