rfmt 1.6.1 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Cargo.lock +1 -1
- data/ext/rfmt/Cargo.toml +1 -1
- data/ext/rfmt/src/format/rule.rs +53 -3
- data/ext/rfmt/src/format/rules/call.rs +20 -3
- data/lib/rfmt/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f1d0fa5ba56d10568e9dd3625974abc815350c4c6c2ff03d5114d8c38aae9a1
|
|
4
|
+
data.tar.gz: 4b6256a168e7be4a70c162a26bea0983fd6397397224cd1953abbe9cc1cbd01b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a90b0b5f699c21e3e5aebd5f33ce71c152694a3cc51c812d2ffda946d2250a7714ae572ab9e7538531386e09b91210aa50f5e4de49e1d11234afd6803525ede4
|
|
7
|
+
data.tar.gz: ab5588dfe3b5035e444219ad218756b475d964f18b47fdb78311593ba964c7c4436856abca58a13fc2e799eaa7d85815e6e70be39e6d0e083d9c7951c3867553
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.6.2] - 2026-04-24
|
|
4
|
+
|
|
5
|
+
Minor stability refinements on top of the 1.6.x architecture release. See the 1.6.1 notes below for the feature set this series delivers.
|
|
6
|
+
|
|
3
7
|
## [1.6.1] - 2026-04-24
|
|
4
8
|
|
|
5
9
|
Follow-up release consolidating the 1.6.0 architecture work.
|
data/Cargo.lock
CHANGED
data/ext/rfmt/Cargo.toml
CHANGED
data/ext/rfmt/src/format/rule.rs
CHANGED
|
@@ -217,6 +217,23 @@ pub fn format_comments_before_end(
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
let mut docs: Vec<Doc> = vec![hardline()];
|
|
220
|
+
// Preserve the blank line that separated the body's last content from
|
|
221
|
+
// the first trailing comment. Without this, a construct like
|
|
222
|
+
//
|
|
223
|
+
// def foo
|
|
224
|
+
// body
|
|
225
|
+
// <- blank line
|
|
226
|
+
// # trailing annotation
|
|
227
|
+
// end
|
|
228
|
+
//
|
|
229
|
+
// collapses to `body\n# trailing annotation\nend`. Detect the case
|
|
230
|
+
// heuristically: if the source line immediately above the first
|
|
231
|
+
// standalone comment is blank, emit an extra hardline.
|
|
232
|
+
if let Some(first) = standalone_refs.first() {
|
|
233
|
+
if first.start_line > 1 && is_line_blank(ctx.source(), first.start_line - 1) {
|
|
234
|
+
docs.push(hardline());
|
|
235
|
+
}
|
|
236
|
+
}
|
|
220
237
|
let mut last_end_line: Option<usize> = None;
|
|
221
238
|
let mut indices_to_mark: Vec<usize> = Vec::with_capacity(standalone_refs.len());
|
|
222
239
|
|
|
@@ -297,11 +314,23 @@ pub fn format_remaining_comments(ctx: &mut FormatContext, last_code_line: usize)
|
|
|
297
314
|
let mut indices_to_mark: Vec<usize> = Vec::with_capacity(comment_refs.len());
|
|
298
315
|
|
|
299
316
|
for cref in &comment_refs {
|
|
300
|
-
// Preserve blank lines
|
|
317
|
+
// Preserve blank lines. On the first iteration we must emit *at
|
|
318
|
+
// least one* hardline to separate the first remaining comment from
|
|
319
|
+
// the main document's last token (otherwise an orphan comment whose
|
|
320
|
+
// `start_line <= last_code_line` would concatenate onto whatever
|
|
321
|
+
// ended the output — producing e.g. `end# comment…` when a block's
|
|
322
|
+
// internal comments fall through to this tail handler). Round-tripping
|
|
323
|
+
// the already-formatted output must still be idempotent, so we
|
|
324
|
+
// cap the emission at the number of line breaks visible in the
|
|
325
|
+
// source: 1 for an adjacent comment, N for N-1 blank lines above it.
|
|
301
326
|
let gap = cref.start_line.saturating_sub(last_end_line);
|
|
302
327
|
|
|
303
|
-
|
|
304
|
-
|
|
328
|
+
if is_first {
|
|
329
|
+
let hardlines_to_emit = gap.max(1);
|
|
330
|
+
for _ in 0..hardlines_to_emit {
|
|
331
|
+
docs.push(hardline());
|
|
332
|
+
}
|
|
333
|
+
} else if gap > 0 {
|
|
305
334
|
for _ in 0..gap.max(1) {
|
|
306
335
|
docs.push(hardline());
|
|
307
336
|
}
|
|
@@ -499,6 +528,27 @@ pub fn reformat_chain_lines(
|
|
|
499
528
|
Cow::Owned(result)
|
|
500
529
|
}
|
|
501
530
|
|
|
531
|
+
/// Returns true when the given 1-based `line` in `source` contains only
|
|
532
|
+
/// whitespace (or is empty). Returns false for any line that has code or
|
|
533
|
+
/// a comment.
|
|
534
|
+
fn is_line_blank(source: &str, line: usize) -> bool {
|
|
535
|
+
let mut current = 1usize;
|
|
536
|
+
let mut line_start = 0usize;
|
|
537
|
+
for (i, b) in source.bytes().enumerate() {
|
|
538
|
+
if current == line {
|
|
539
|
+
let end = source[i..].find('\n').map_or(source.len(), |n| i + n);
|
|
540
|
+
return source[line_start..end]
|
|
541
|
+
.bytes()
|
|
542
|
+
.all(|b| b == b' ' || b == b'\t' || b == b'\r');
|
|
543
|
+
}
|
|
544
|
+
if b == b'\n' {
|
|
545
|
+
current += 1;
|
|
546
|
+
line_start = i + 1;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
false
|
|
550
|
+
}
|
|
551
|
+
|
|
502
552
|
/// Removes at most one trailing `\n` (optionally preceded by a single `\r`)
|
|
503
553
|
/// from `s`. Spaces, tabs, and any additional preceding newlines are
|
|
504
554
|
/// preserved.
|
|
@@ -13,9 +13,9 @@ use crate::error::Result;
|
|
|
13
13
|
use crate::format::context::FormatContext;
|
|
14
14
|
use crate::format::registry::RuleRegistry;
|
|
15
15
|
use crate::format::rule::{
|
|
16
|
-
format_child, format_leading_comments, format_statements,
|
|
17
|
-
line_leading_indent, mark_comments_in_range_emitted,
|
|
18
|
-
strip_one_trailing_newline, FormatRule,
|
|
16
|
+
format_child, format_comments_before_end, format_leading_comments, format_statements,
|
|
17
|
+
format_trailing_comment, line_leading_indent, mark_comments_in_range_emitted,
|
|
18
|
+
reformat_chain_lines, strip_one_trailing_newline, FormatRule,
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/// Rule for formatting method calls.
|
|
@@ -251,6 +251,23 @@ fn format_do_end_block(
|
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
// Emit any standalone comments between the last body statement and `end`.
|
|
255
|
+
//
|
|
256
|
+
// Without this the orphan comments inside a `do…end` block (e.g. the
|
|
257
|
+
// commented-out config stanzas in a generated `spec_helper.rb`) never
|
|
258
|
+
// get claimed by any `format_leading_comments` call, fall through to
|
|
259
|
+
// `format_remaining_comments` at the end of the file, and get emitted
|
|
260
|
+
// *after* the block's own `end` — producing `end# comment…` with no
|
|
261
|
+
// separator and dropping the body indent.
|
|
262
|
+
let comments_before_end = format_comments_before_end(
|
|
263
|
+
ctx,
|
|
264
|
+
block_node.location.start_line,
|
|
265
|
+
block_node.location.end_line,
|
|
266
|
+
);
|
|
267
|
+
if !comments_before_end.is_empty() {
|
|
268
|
+
docs.push(indent(comments_before_end));
|
|
269
|
+
}
|
|
270
|
+
|
|
254
271
|
// Emit 'end'
|
|
255
272
|
docs.push(hardline());
|
|
256
273
|
docs.push(text("end"));
|
data/lib/rfmt/version.rb
CHANGED