print(File): preserve blank-line separation between statements - #74
Conversation
Reprinting a whole file previously joined every statement with a single newline, losing the blank lines that separate import groups, logical sections, and class members. Downstream that breaks lint rules in the consuming project (simple-import-sort group separation, import/newline-after-import, padding-line-between-statements) since prettier preserves blank lines but never invents them. toTree now attaches the original source text to the File node, and the statement-list join sites (Program, block/static/class bodies, switch cases, TS type/interface/module bodies, enum members) go through a printStatements helper: while a File with a known source is being printed, a gap of two-or-more newlines between consecutive nodes in the original source is preserved as one blank line (runs collapse to one). Standalone print(node) is unchanged -- without a File in flight the helper falls straight through to the old map/join (measured at parity with main: +0.5% / +0.7% / +3.7% across three interleaved runs of the 4k-line micro-benchmark, within the harness's noise). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Closing this one — per your note on the ember.nvp side: "we don't actually care [about re-creating what prettier does]. we expect prettier and lint to run on new projects right away so that formatting can be correct for how the user has configured." That philosophy makes this PR unnecessary, and I verified it concretely: the three diagnostics that motivated it ( (Comment preservation from #73 remains necessary — |
Follow-up to #73, found while wiring the print()+prettier pipeline into ember.nvp (NullVoxPopuli/ember.nvp#58): reprinting a whole file joined every statement with a single newline, so blank lines separating import groups, logical sections, and class members were lost. Prettier preserves blank lines but never invents them, so in the consuming project the reprinted
tests/test-helper.jstrippedsimple-import-sort(group separation),import/newline-after-import, andpadding-line-between-statements.What this does
toTreeattaches the original source text to theFilenode (file.source, optional in the d.ts).printStatementshelper: while a File with a known source is in flight, a gap of two-or-more newlines between consecutive nodes in the original source is preserved as exactly one blank line (runs collapse). Detection is a singlesource.slice(prev.end, node.start)between neighbors — offsets only, no line table.Performance
print(node): without a File in flight the helper falls straight through to the oldmap/join— one null check per statement list (not per node). Measured at parity with main on the 4k-line micro-benchmark: +0.5% / +0.7% / +3.7% across three interleaved runs (within that harness's noise band).print(File): unchanged ballpark (0.67ms vs 0.68ms before on the same fixture); the per-pair gap check is one substring between adjacent statements.Testing
pnpm test: 235 passing;pnpm lintclean.Once released, ember.nvp bumps the dep and its reprinted test-helper becomes fully lint-clean (the last open item from ember.nvp#58).
🤖 Generated with Claude Code