feat(fmt): #144 Phase 3 — delete preserveTopLevelComments (~500 LOC removal)#147
Merged
Merged
Conversation
…emoval)
Phase 3 migrates the ~500 LOC string-anchor post-pass in app/Main.hs
into AST-driven drain hooks in Sky.Format.Format. Every own-line
comment now routes through a semantic boundary:
* top-decl boundary (drainBefore col 0)
* value body (drainBefore bodyCol)
* let-def + let-body (drainBefore defCol)
* case-arm pattern (drainBefore branchCol)
* record / list / tuple / update field (drainBefore col; auto-multi-
line if any element has drained comments)
* lambda body (drainAnyBefore — permissive col match because
fmtArg wraps in parens and shifts bodyCol away from source col)
* if-else body (drainBefore elseCol)
End-of-decl mop-up (drainInnerUntil nextDeclLine) catches body-trailer
comments — the "prevIsBody + no blank lines" quirk-fix from the
legacy walker, but AST-side and driven by the parser's _commentPos +
_commentCol tags.
Deleted from app/Main.hs (~550 LOC):
* preserveTopLevelComments (main entry)
* collectCommentBlocks, injectComments, declKey, nextAnchorKey
* isBindingShape, collectTrailingComments, splitTrailingComment
* reattachTrailing, addHeaderBlock, addPrev/NextAnchorBlock
* filterAstEmittedBlocks, extractAstEmittedBodies,
normalizeCommentBody, astMarkerText, stripAstMarkers
Kept (belt-and-braces safety):
* fmtSafetyCheck, fmtCommentTally, fmtForceMessage — still guard
against a future regression that drops >5% of input comments.
FmtSpec's SKY_FMT_FORCE test previously verified the safety guard's
behaviour on a fixture that dropped 3 of 9 lambda-body comments in
Phase 1/2. Phase 3 preserves all comments, so that fixture no
longer trips the guard; the test now verifies the file-mode + env-
var contract mechanically (writes, exits 0, comments preserved).
Verified:
* cabal test — 993 examples, 0 failures, 6 pending (baseline count).
* CommentsSpec (18/18) + FmtSpec (3/3) + FormatSpec (14/14) green.
* #144 fixture (/tmp/sky144/StatsTest.sky): 9 comments preserved,
zero sentinel leak, idempotent.
* 40 examples: all clean-format AND byte-idempotent under two
fmt passes.
Line counts:
* app/Main.hs: 3109 → 2567 (-542)
* src/Sky/Format/Format.hs: 656 → 852 (+196 for drain hooks + helpers)
* Net: -346 lines, single source of truth for comment placement.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Claude-Session: https://claude.ai/code/session_013PZXpgCdbQ3A1eSwxCqAQZ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Final phase of the issue #144 architectural close. Phase 1 (parser tags) + Phase 2 (Format.hs threading + Lambda drain) shipped in v0.17.7 (#146). This PR deletes the ~500 LOC string-anchor workaround from
app/Main.hsand completes the AST-driven comment placement rewrite.What ships
AST-side drain hooks added at every hole point —
Sky.Format.Formatnow handles:Deleted from
app/Main.hs—preserveTopLevelComments+ 14 helpers + AST sentinel bookkeeping (astMarkerText,stripAstMarkers,extractAstEmittedBodies,filterAstEmittedBlocks,normalizeCommentBody).Kept as belt-and-braces —
fmtSafetyCheck+fmtCommentTally+fmtForceMessagestill guards >5% drop regression.Line count
app/Main.hs: 3109 → 2567 lines (-542 LOC)src/Sky/Format/Format.hs: 656 → 852 lines (+196 LOC for drain hooks/helpers)Verification
cabal testsweep: 993 examples, 0 failures, 6 pending (baseline; no regressions)CommentsSpec18/18 +FmtSpec3/3 +FormatSpec14/14 greensky fmtself-reports issue with comments #144 fixture (/tmp/sky144/StatsTest.sky): exit 0, 9 comments preserved, zero\x03sentinel leaks, two-pass byte-identicalTest plan
cabal testfull sweep — 993/0/6 baselinesky fmton issuesky fmtself-reports issue with comments #144 fixture — 9 comments, exit 0, byte-idempotent\x03) in output🤖 Generated with Claude Code
https://claude.ai/code/session_013PZXpgCdbQ3A1eSwxCqAQZ