Skip to content

print(File): preserve blank-line separation between statements - #74

Closed
NullVoxPopuli-ai-agent wants to merge 1 commit into
NullVoxPopuli:mainfrom
NullVoxPopuli-ai-agent:print-preserve-blank-lines
Closed

print(File): preserve blank-line separation between statements#74
NullVoxPopuli-ai-agent wants to merge 1 commit into
NullVoxPopuli:mainfrom
NullVoxPopuli-ai-agent:print-preserve-blank-lines

Conversation

@NullVoxPopuli-ai-agent

Copy link
Copy Markdown

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.js tripped simple-import-sort (group separation), import/newline-after-import, and padding-line-between-statements.

What this does

  • toTree attaches the original source text to the File node (file.source, optional in the d.ts).
  • The statement-list join sites (Program, block/static-block/class bodies, switch cases + case bodies, TS type-literal/interface/module bodies, enum members) go through a printStatements helper: 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 single source.slice(prev.end, node.start) between neighbors — offsets only, no line table.
  • Works with comment weaving: a blank line before a comment+statement pair survives (the gap is measured between the statements, so the comment rides along).

Performance

  • Standalone print(node): without a File in flight the helper falls straight through to the old map/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

  • 6 new inline-snapshot tests: top-level blank lines, import groups, function/class bodies, blank-before-comment, run-collapsing, and standalone printing staying dense.
  • pnpm test: 235 passing; pnpm lint clean.

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

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>
@NullVoxPopuli-ai-agent

Copy link
Copy Markdown
Author

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 (simple-import-sort group separation, import/newline-after-import, padding-line-between-statements on ember.nvp's reprinted tests/test-helper.js) are all auto-fixable — running the generated app's own eslint --fix inserts exactly the three blank lines, and the file then passes both eslint and the app's prettier config. The user's configured lint pass restores everything blank-line-related; the printer doesn't need to.

(Comment preservation from #73 remains necessary — --fix can't resurrect deleted comments — but blank lines are pure formatting, which is lint's job.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant