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 DefaultValue, comments and attributes lose their indent after the first line: a nested field's [\n\t1,\n] initialiser drops to column 1 #132
TemplateBase.WriteDefaultValueTo (CodeBlocker/Templates/TemplateBase.cs:96), AddComments (:157), and AddAttributes (:184) all pass the caller's string straight to CodeBlocker.Write / WriteLine. IndentedTextWriter adds the indent only after its own WriteLine. It does not add it after a line break embedded in the text. The first line of a multi-line value is indented, and every later line starts at the indent the caller happened to type, usually none.
Repro (class C nested in Outer, so members sit at two tabs):
newFieldTemplate{Type="int[]",Name="xs",DefaultValue="[\n\t1,\n\t2,\n]"}newFieldTemplate{Type="int",Name="y",Comments={"// line a\n// line b"}}
Observed (→ = tab):
→→int[] xs = [
→1,
→2,
];
→→// line a
// line b
→→int y;
If DefaultValue contains CRLF and the writer uses LF, or the other way round, the output also mixes line endings. That breaks the byte-identical output #81 established, along the same lines as #123 does for bodies.
Why it matters
The templates exist so callers do not have to manage indentation. The most common multi-line DefaultValue is a collection or object initialiser, and it comes out misaligned whenever the member is nested or sits under a namespace scope. A generator that commits its output then shows formatting churn, or a formatter has to clean up after it. The output still compiles, so this is a layout defect, not a correctness one.
#112 fixed this same problem for expression bodies only (WriteExpressionBody). The three paths above were left out.
Suggested fix
Route DefaultValue, each comment, and each attribute through the same splice used for expression bodies (TemplateRendering.SpliceFragment). The first line stays on the declaration line, and each following line is written with WriteLine so it picks up the current indent.
Normalise line endings first, the way DocComment.SplitLines does.
Leave DefaultValueIsQuoted values alone. QuoteStringLiteral already escapes \n, so they are safe.
A nested field with DefaultValue = "[\n\t1,\n\t2,\n]" renders each continuation line at the field's indent plus the value's own relative indent.
A multi-line comment string and a multi-line attribute render every line at the member's indent.
CRLF inside any of the three values produces only the writer's NewLine in the output.
Tests cover all three paths, both nested and at top level.
Related, but none of them covers these paths: #112 (closed, expression bodies), #123 (body line endings), #121 (verbatim strings in bodies), #126 (blank line after Write("")).
Category: Bug (layout and formatting defect; labelled enhancement, but the output is wrong rather than a missing feature)
Priority: Low. The generated code still compiles. The effect is misaligned indentation and possibly mixed line endings, which cause formatting churn in committed generator output.
Next step: splice all three paths, normalise line endings first, leave DefaultValueIsQuoted values alone, and add tests for both nested and top-level members.
Activity
matt-edmondson commentedon Oct 7, 2026
Triage
enhancement, but the output is wrong rather than a missing feature)TemplateBase.WriteDefaultValueTo/AddComments/AddAttributes(Templates/TemplateBase.cs:96, 157, 184). ReuseTemplateRendering.SpliceFragmentfrom Multi-line expression bodies (ExpressionBodyFactory / AccessorKind.Expression) lose indentation on every line after the first #112.DefaultValuecould change a string's value.DefaultValueIsQuotedvalues alone, and add tests for both nested and top-level members.Generated by Claude Code