Skip to content

Consider making LF the default line terminator #89

Description

@matt-edmondson

The decision that was deferred

#81 made the line terminator configurable but kept the default as Environment.NewLine, so determinism is opt-in. That was a deliberate deviation from its own first acceptance criterion, which asked for byte-identical output across platforms by default.

The reasoning at the time: flipping the default silently changes the bytes every current Windows consumer gets, and that is a maintainer's call rather than an implementer's. This issue is that call, written down so it does not just get lost.

The case for flipping it

  • It is a code-generation library. Its output is overwhelmingly written to files, committed, diffed, or compared against golden files — all of which want reproducibility more than they want the host's convention.
  • The status quo produces silent bugs. ktsu.Semantics carried a post-processing pass for years purely to undo Environment.NewLine, and — see Retire GeneratedSource once CodeBlocker emits deterministic newlines Semantics#184 — that pass was itself rewriting to the wrong terminator after the repository migrated to LF, with git quietly normalising the difference on every commit. Nobody noticed because nothing surfaced it.
  • The tests here made the same mistake. 46 of 67 failed on any non-Windows host, and only ever passed because CI ran on Windows. That was fixed independently on main in d4a7153.
  • LF is what the ecosystem stores. This repository's own .gitattributes says * text=auto eol=lf.

The case against

  • It is a behavioural break for any consumer relying on the current output, in a way that will not show up as a compile error — only as a diff.
  • Consumers who genuinely want the host convention would have to opt in, whereas today they get it for free.

If it goes ahead

  • One-line change in CodeBlocker.cs: NewLines.HostNewLines.Lf in the three defaulting call sites.
  • Tag the commit [major], since the release pipeline derives the version from it.
  • README.md needs its "Line Endings" section reworded — NewLines.Host becomes the opt-in rather than the default.
  • The existing tests are already terminator-explicit, so they should not need changing. NewLineTests.DefaultNewLineStringIsTheHostTerminator is the one that pins current behaviour and would be rewritten.

Acceptance criteria

  • Decision recorded here either way, so it stops being an open question.
  • If flipped: default is LF, [major], README.md updated, and the change called out in release notes as a behavioural break.

Context

Deferred from #81, delivered in #87.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions