Skip to content

Commit 7a0e7b5

Browse files
committed
Fix formatter blank-line growth between doc comments and items
Two formatter idempotency bugs: 1. Doc comment → attribute/item: `emit_blank_lines_to` preserved blank lines from the source between a doc comment and its item's attribute, causing blank lines to grow on each format pass. Fixed by skipping blank-line insertion when the last leading comment was a doc comment. 2. World declaration body: `last_source_line` was not updated after emitting `{\n`, causing the first import block to get an extra blank line on each pass. Fixed by setting `last_source_line` after the `{`. https://claude.ai/code/session_0181NuipeuMorkJgDi4dh3Dp
1 parent baafe5b commit 7a0e7b5

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

wado-compiler/lib/core/prelude/types.wado

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// This module defines fundamental sum types that are used throughout Wado programs.
44

55
/// Tuple type family declaration — establishes `core:prelude` as the owner of all tuple types.
6-
76
#[comp_feature("tuple")]
87
pub type [..T];
98

wado-compiler/src/unparse.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,16 @@ impl<'a> Unparser<'a> {
111111
let span = get_item_span(item);
112112

113113
// Emit leading comments (handles blank lines before comments)
114-
self.emit_leading_comments(&span);
114+
let last_comment_was_doc = self.emit_leading_comments_and_check_doc(&span);
115115

116116
// Emit blank lines before the item itself.
117117
// Use the first attribute line (if any) to avoid growing blank lines
118118
// between doc comments and attrs on repeated formatting passes.
119-
self.emit_blank_lines_to(get_item_first_line(item));
119+
// Skip blank-line insertion when the last leading comment was a doc comment,
120+
// because doc comments belong to the item and shouldn't be separated by blank lines.
121+
if !last_comment_was_doc {
122+
self.emit_blank_lines_to(get_item_first_line(item));
123+
}
120124

121125
match item {
122126
Item::Use(u) => self.unparse_use(u),
@@ -1047,6 +1051,7 @@ impl<'a> Unparser<'a> {
10471051
self.output.push_str("world ");
10481052
self.output.push_str(&w.name);
10491053
self.output.push_str(" {\n");
1054+
self.last_source_line = w.span.line;
10501055

10511056
self.indent_level += 1;
10521057

@@ -2538,6 +2543,22 @@ impl<'a> Unparser<'a> {
25382543
}
25392544
}
25402545

2546+
/// Like `emit_leading_comments` but returns whether the last emitted comment was a doc comment.
2547+
fn emit_leading_comments_and_check_doc(&mut self, span: &Span) -> bool {
2548+
let mut last_was_doc = false;
2549+
for comment in self.comments.leading_comments(span) {
2550+
if self.emitted_comments.insert(comment.span.start) {
2551+
self.emit_blank_lines_to(comment.span.line);
2552+
self.write_indent();
2553+
self.emit_comment(comment);
2554+
self.output.push('\n');
2555+
self.last_source_line = comment.span.line;
2556+
last_was_doc = comment.kind == crate::comment::CommentKind::DocLine;
2557+
}
2558+
}
2559+
last_was_doc
2560+
}
2561+
25412562
fn emit_trailing_comments(&mut self, span: &Span) {
25422563
for comment in self.comments.trailing_comments(span) {
25432564
if self.emitted_comments.insert(comment.span.start) {

0 commit comments

Comments
 (0)