rfmt 1.2.3 → 1.2.5
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 +12 -0
- data/Cargo.lock +1 -1
- data/ext/rfmt/Cargo.toml +1 -1
- data/ext/rfmt/src/emitter/mod.rs +242 -19
- data/lib/rfmt/rfmt.so +0 -0
- data/lib/rfmt/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 67e0ceb39e5630237f92ac2d78fcf2438313dcd883c72ec44066ede9e9868735
|
|
4
|
+
data.tar.gz: 69b818c97c55f1ffc4f09518393c2249b71e0e084207249ba8fa631679d66167
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2e7cc3e550d2506c0f6691f6b4823f76a2c88e94519d46ca080c2d3b57a7330d5e3df4bca1ab4e18ae1551ea6821c92210638d657997cb6a72631512e47d2bc5
|
|
7
|
+
data.tar.gz: '0491cb8029834d053692a9cc251da952c5bbbf6e38045bcfe3a90dfb2a9ebf31cb3dfb09bfa640b0c22b427d1ab47f0e801ecd44a88c79626f05ab4898d19c64'
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.2.5] - 2026-01-04
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Fix trailing comments on `end` keyword (e.g., `end # rubocop:disable`)
|
|
7
|
+
- Fix block internal comments being moved outside the block
|
|
8
|
+
- Fix blank line preservation between code and comments inside blocks
|
|
9
|
+
|
|
10
|
+
## [1.2.4] - 2026-01-04
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Fix comment indent space handling
|
|
14
|
+
|
|
3
15
|
## [1.2.3] - 2026-01-04
|
|
4
16
|
|
|
5
17
|
### Fixed
|
data/Cargo.lock
CHANGED
data/ext/rfmt/Cargo.toml
CHANGED
data/ext/rfmt/src/emitter/mod.rs
CHANGED
|
@@ -50,8 +50,11 @@ impl Emitter {
|
|
|
50
50
|
|
|
51
51
|
self.emit_node(ast, 0)?;
|
|
52
52
|
|
|
53
|
+
// Find the last emitted code line for proper blank line handling
|
|
54
|
+
let last_code_line = Self::find_last_code_line(ast);
|
|
55
|
+
|
|
53
56
|
// Emit any remaining comments that weren't emitted
|
|
54
|
-
self.emit_remaining_comments()?;
|
|
57
|
+
self.emit_remaining_comments(last_code_line)?;
|
|
55
58
|
|
|
56
59
|
// Ensure file ends with a newline
|
|
57
60
|
if !self.buffer.ends_with('\n') {
|
|
@@ -61,14 +64,30 @@ impl Emitter {
|
|
|
61
64
|
Ok(self.buffer.clone())
|
|
62
65
|
}
|
|
63
66
|
|
|
67
|
+
/// Find the last line of code in the AST (excluding comments)
|
|
68
|
+
fn find_last_code_line(ast: &Node) -> usize {
|
|
69
|
+
let mut max_line = ast.location.end_line;
|
|
70
|
+
for child in &ast.children {
|
|
71
|
+
let child_end = Self::find_last_code_line(child);
|
|
72
|
+
if child_end > max_line {
|
|
73
|
+
max_line = child_end;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
max_line
|
|
77
|
+
}
|
|
78
|
+
|
|
64
79
|
/// Emit all comments that haven't been emitted yet
|
|
65
|
-
fn emit_remaining_comments(&mut self) -> Result<()> {
|
|
66
|
-
let mut last_end_line: Option<usize> =
|
|
80
|
+
fn emit_remaining_comments(&mut self, last_code_line: usize) -> Result<()> {
|
|
81
|
+
let mut last_end_line: Option<usize> = Some(last_code_line);
|
|
67
82
|
for (idx, comment) in self.all_comments.iter().enumerate() {
|
|
68
83
|
if self.emitted_comment_indices.contains(&idx) {
|
|
69
84
|
continue;
|
|
70
85
|
}
|
|
71
|
-
//
|
|
86
|
+
// Ensure we start on a new line for remaining comments
|
|
87
|
+
if !self.buffer.ends_with('\n') {
|
|
88
|
+
self.buffer.push('\n');
|
|
89
|
+
}
|
|
90
|
+
// Preserve blank lines between code/comments
|
|
72
91
|
if let Some(prev_line) = last_end_line {
|
|
73
92
|
let gap = comment.location.start_line.saturating_sub(prev_line);
|
|
74
93
|
for _ in 1..gap {
|
|
@@ -104,16 +123,37 @@ impl Emitter {
|
|
|
104
123
|
}
|
|
105
124
|
|
|
106
125
|
if comment.location.end_line < line {
|
|
107
|
-
comments_to_emit.push((
|
|
126
|
+
comments_to_emit.push((
|
|
127
|
+
idx,
|
|
128
|
+
comment.text.clone(),
|
|
129
|
+
comment.location.start_line,
|
|
130
|
+
comment.location.end_line,
|
|
131
|
+
));
|
|
108
132
|
}
|
|
109
133
|
}
|
|
110
134
|
|
|
135
|
+
// Sort by start_line to emit in order
|
|
136
|
+
comments_to_emit.sort_by_key(|(_, _, start, _)| *start);
|
|
137
|
+
|
|
111
138
|
let comments_count = comments_to_emit.len();
|
|
112
|
-
|
|
139
|
+
let mut last_comment_end_line: Option<usize> = None;
|
|
140
|
+
|
|
141
|
+
for (i, (idx, text, comment_start_line, comment_end_line)) in
|
|
142
|
+
comments_to_emit.into_iter().enumerate()
|
|
143
|
+
{
|
|
144
|
+
// Preserve blank lines between comments
|
|
145
|
+
if let Some(prev_end) = last_comment_end_line {
|
|
146
|
+
let gap = comment_start_line.saturating_sub(prev_end);
|
|
147
|
+
for _ in 1..gap {
|
|
148
|
+
self.buffer.push('\n');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
113
152
|
writeln!(self.buffer, "{}{}", indent_str, text)?;
|
|
114
153
|
self.emitted_comment_indices.push(idx);
|
|
154
|
+
last_comment_end_line = Some(comment_end_line);
|
|
115
155
|
|
|
116
|
-
//
|
|
156
|
+
// Add blank line after the LAST comment if there was a gap to the code
|
|
117
157
|
if i == comments_count - 1 && line > comment_end_line + 1 {
|
|
118
158
|
self.buffer.push('\n');
|
|
119
159
|
}
|
|
@@ -122,6 +162,114 @@ impl Emitter {
|
|
|
122
162
|
Ok(())
|
|
123
163
|
}
|
|
124
164
|
|
|
165
|
+
/// Check if there are any unemitted comments in the given line range
|
|
166
|
+
fn has_comments_in_range(&self, start_line: usize, end_line: usize) -> bool {
|
|
167
|
+
self.all_comments.iter().enumerate().any(|(idx, comment)| {
|
|
168
|
+
!self.emitted_comment_indices.contains(&idx)
|
|
169
|
+
&& comment.location.start_line >= start_line
|
|
170
|
+
&& comment.location.end_line < end_line
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/// Emit comments that are within a given line range (exclusive of end_line)
|
|
175
|
+
fn emit_comments_in_range(
|
|
176
|
+
&mut self,
|
|
177
|
+
start_line: usize,
|
|
178
|
+
end_line: usize,
|
|
179
|
+
indent_level: usize,
|
|
180
|
+
) -> Result<()> {
|
|
181
|
+
let indent_str = match self.config.formatting.indent_style {
|
|
182
|
+
IndentStyle::Spaces => " ".repeat(self.config.formatting.indent_width * indent_level),
|
|
183
|
+
IndentStyle::Tabs => "\t".repeat(indent_level),
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
let mut comments_to_emit = Vec::new();
|
|
187
|
+
for (idx, comment) in self.all_comments.iter().enumerate() {
|
|
188
|
+
if self.emitted_comment_indices.contains(&idx) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if comment.location.start_line >= start_line && comment.location.end_line < end_line {
|
|
193
|
+
comments_to_emit.push((
|
|
194
|
+
idx,
|
|
195
|
+
comment.text.clone(),
|
|
196
|
+
comment.location.start_line,
|
|
197
|
+
comment.location.end_line,
|
|
198
|
+
));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Sort by start_line to emit in order
|
|
203
|
+
comments_to_emit.sort_by_key(|(_, _, start, _)| *start);
|
|
204
|
+
|
|
205
|
+
let mut last_comment_end_line: Option<usize> = None;
|
|
206
|
+
|
|
207
|
+
for (idx, text, comment_start_line, comment_end_line) in comments_to_emit {
|
|
208
|
+
// Preserve blank lines between comments
|
|
209
|
+
if let Some(prev_end) = last_comment_end_line {
|
|
210
|
+
let gap = comment_start_line.saturating_sub(prev_end);
|
|
211
|
+
for _ in 1..gap {
|
|
212
|
+
self.buffer.push('\n');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
writeln!(self.buffer, "{}{}", indent_str, text)?;
|
|
217
|
+
self.emitted_comment_indices.push(idx);
|
|
218
|
+
last_comment_end_line = Some(comment_end_line);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
Ok(())
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/// Emit comments that are within a given line range, preserving blank lines from prev_line
|
|
225
|
+
fn emit_comments_in_range_with_prev_line(
|
|
226
|
+
&mut self,
|
|
227
|
+
start_line: usize,
|
|
228
|
+
end_line: usize,
|
|
229
|
+
indent_level: usize,
|
|
230
|
+
prev_line: usize,
|
|
231
|
+
) -> Result<()> {
|
|
232
|
+
let indent_str = match self.config.formatting.indent_style {
|
|
233
|
+
IndentStyle::Spaces => " ".repeat(self.config.formatting.indent_width * indent_level),
|
|
234
|
+
IndentStyle::Tabs => "\t".repeat(indent_level),
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
let mut comments_to_emit = Vec::new();
|
|
238
|
+
for (idx, comment) in self.all_comments.iter().enumerate() {
|
|
239
|
+
if self.emitted_comment_indices.contains(&idx) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if comment.location.start_line >= start_line && comment.location.end_line < end_line {
|
|
244
|
+
comments_to_emit.push((
|
|
245
|
+
idx,
|
|
246
|
+
comment.text.clone(),
|
|
247
|
+
comment.location.start_line,
|
|
248
|
+
comment.location.end_line,
|
|
249
|
+
));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Sort by start_line to emit in order
|
|
254
|
+
comments_to_emit.sort_by_key(|(_, _, start, _)| *start);
|
|
255
|
+
|
|
256
|
+
let mut last_end_line: usize = prev_line;
|
|
257
|
+
|
|
258
|
+
for (idx, text, comment_start_line, comment_end_line) in comments_to_emit {
|
|
259
|
+
// Preserve blank lines between previous content and this comment
|
|
260
|
+
let gap = comment_start_line.saturating_sub(last_end_line);
|
|
261
|
+
for _ in 1..gap {
|
|
262
|
+
self.buffer.push('\n');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
writeln!(self.buffer, "{}{}", indent_str, text)?;
|
|
266
|
+
self.emitted_comment_indices.push(idx);
|
|
267
|
+
last_end_line = comment_end_line;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
Ok(())
|
|
271
|
+
}
|
|
272
|
+
|
|
125
273
|
/// Emit comments that appear on the same line (trailing comments)
|
|
126
274
|
fn emit_trailing_comments(&mut self, line: usize) -> Result<()> {
|
|
127
275
|
let mut indices_to_emit = Vec::new();
|
|
@@ -249,6 +397,9 @@ impl Emitter {
|
|
|
249
397
|
// Emit body (children), but skip structural nodes (class name, superclass)
|
|
250
398
|
// Use start_line check to properly handle CallNode superclasses like ActiveRecord::Migration[8.0]
|
|
251
399
|
let class_start_line = node.location.start_line;
|
|
400
|
+
let class_end_line = node.location.end_line;
|
|
401
|
+
let mut has_body_content = false;
|
|
402
|
+
|
|
252
403
|
for child in &node.children {
|
|
253
404
|
// Skip nodes on the same line as class definition (name, superclass)
|
|
254
405
|
if child.location.start_line == class_start_line {
|
|
@@ -257,18 +408,25 @@ impl Emitter {
|
|
|
257
408
|
if self.is_structural_node(&child.node_type) {
|
|
258
409
|
continue;
|
|
259
410
|
}
|
|
411
|
+
has_body_content = true;
|
|
260
412
|
self.emit_node(child, indent_level + 1)?;
|
|
261
413
|
}
|
|
262
414
|
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
415
|
+
// Emit comments that are inside the class body but not attached to any node
|
|
416
|
+
// These are comments between class_start_line and class_end_line
|
|
417
|
+
self.emit_comments_in_range(class_start_line + 1, class_end_line, indent_level + 1)?;
|
|
418
|
+
|
|
419
|
+
// Add newline before end if there was body content or internal comments
|
|
420
|
+
if (has_body_content || self.has_comments_in_range(class_start_line + 1, class_end_line))
|
|
421
|
+
&& !self.buffer.ends_with('\n')
|
|
422
|
+
{
|
|
267
423
|
self.buffer.push('\n');
|
|
268
424
|
}
|
|
269
425
|
|
|
270
426
|
self.emit_indent(indent_level)?;
|
|
271
427
|
write!(self.buffer, "end")?;
|
|
428
|
+
// Emit trailing comments on end line (e.g., `end # rubocop:disable`)
|
|
429
|
+
self.emit_trailing_comments(node.location.end_line)?;
|
|
272
430
|
|
|
273
431
|
Ok(())
|
|
274
432
|
}
|
|
@@ -289,25 +447,33 @@ impl Emitter {
|
|
|
289
447
|
self.emit_trailing_comments(node.location.start_line)?;
|
|
290
448
|
self.buffer.push('\n');
|
|
291
449
|
|
|
450
|
+
let module_start_line = node.location.start_line;
|
|
451
|
+
let module_end_line = node.location.end_line;
|
|
452
|
+
let mut has_body_content = false;
|
|
453
|
+
|
|
292
454
|
// Emit body (children), but skip structural nodes
|
|
293
455
|
for child in &node.children {
|
|
294
456
|
if self.is_structural_node(&child.node_type) {
|
|
295
457
|
continue;
|
|
296
458
|
}
|
|
459
|
+
has_body_content = true;
|
|
297
460
|
self.emit_node(child, indent_level + 1)?;
|
|
298
461
|
}
|
|
299
462
|
|
|
300
|
-
//
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
463
|
+
// Emit comments that are inside the module body but not attached to any node
|
|
464
|
+
self.emit_comments_in_range(module_start_line + 1, module_end_line, indent_level + 1)?;
|
|
465
|
+
|
|
466
|
+
// Add newline before end if there was body content or internal comments
|
|
467
|
+
if (has_body_content || self.has_comments_in_range(module_start_line + 1, module_end_line))
|
|
468
|
+
&& !self.buffer.ends_with('\n')
|
|
305
469
|
{
|
|
306
470
|
self.buffer.push('\n');
|
|
307
471
|
}
|
|
308
472
|
|
|
309
473
|
self.emit_indent(indent_level)?;
|
|
310
474
|
write!(self.buffer, "end")?;
|
|
475
|
+
// Emit trailing comments on end line (e.g., `end # rubocop:disable`)
|
|
476
|
+
self.emit_trailing_comments(node.location.end_line)?;
|
|
311
477
|
|
|
312
478
|
Ok(())
|
|
313
479
|
}
|
|
@@ -380,6 +546,8 @@ impl Emitter {
|
|
|
380
546
|
|
|
381
547
|
self.emit_indent(indent_level)?;
|
|
382
548
|
write!(self.buffer, "end")?;
|
|
549
|
+
// Emit trailing comments on end line (e.g., `end # rubocop:disable`)
|
|
550
|
+
self.emit_trailing_comments(node.location.end_line)?;
|
|
383
551
|
|
|
384
552
|
Ok(())
|
|
385
553
|
}
|
|
@@ -411,6 +579,8 @@ impl Emitter {
|
|
|
411
579
|
|
|
412
580
|
self.emit_indent(indent_level)?;
|
|
413
581
|
write!(self.buffer, "end")?;
|
|
582
|
+
// Emit trailing comments on end line
|
|
583
|
+
self.emit_trailing_comments(node.location.end_line)?;
|
|
414
584
|
} else {
|
|
415
585
|
// Implicit begin - emit children directly
|
|
416
586
|
for (i, child) in node.children.iter().enumerate() {
|
|
@@ -463,7 +633,8 @@ impl Emitter {
|
|
|
463
633
|
}
|
|
464
634
|
} else if expect_continuation {
|
|
465
635
|
// Continuation line after trailing comma or backslash
|
|
466
|
-
|
|
636
|
+
// Add space after comma or if no trailing space
|
|
637
|
+
if !rescue_decl.ends_with(' ') {
|
|
467
638
|
rescue_decl.push(' ');
|
|
468
639
|
}
|
|
469
640
|
let content = trimmed.trim_end_matches('\\').trim();
|
|
@@ -600,6 +771,8 @@ impl Emitter {
|
|
|
600
771
|
// Emit "end" keyword
|
|
601
772
|
self.emit_indent(indent_level)?;
|
|
602
773
|
write!(self.buffer, "end")?;
|
|
774
|
+
// Emit trailing comments on end line
|
|
775
|
+
self.emit_trailing_comments(node.location.end_line)?;
|
|
603
776
|
|
|
604
777
|
Ok(())
|
|
605
778
|
}
|
|
@@ -817,6 +990,8 @@ impl Emitter {
|
|
|
817
990
|
if !is_elsif {
|
|
818
991
|
self.emit_indent(indent_level)?;
|
|
819
992
|
write!(self.buffer, "end")?;
|
|
993
|
+
// Emit trailing comments on end line
|
|
994
|
+
self.emit_trailing_comments(node.location.end_line)?;
|
|
820
995
|
}
|
|
821
996
|
|
|
822
997
|
Ok(())
|
|
@@ -907,17 +1082,46 @@ impl Emitter {
|
|
|
907
1082
|
self.buffer.push('\n');
|
|
908
1083
|
|
|
909
1084
|
// Find and emit the body (StatementsNode among children)
|
|
1085
|
+
let block_start_line = block_node.location.start_line;
|
|
1086
|
+
let block_end_line = block_node.location.end_line;
|
|
1087
|
+
let mut last_stmt_end_line = block_start_line;
|
|
1088
|
+
|
|
910
1089
|
for child in &block_node.children {
|
|
911
1090
|
if matches!(child.node_type, NodeType::StatementsNode) {
|
|
912
1091
|
self.emit_statements(child, indent_level + 1)?;
|
|
1092
|
+
// Track the last statement's end line for blank line preservation
|
|
1093
|
+
if let Some(last_child) = child.children.last() {
|
|
1094
|
+
last_stmt_end_line = last_child.location.end_line;
|
|
1095
|
+
}
|
|
913
1096
|
self.buffer.push('\n');
|
|
914
1097
|
break;
|
|
915
1098
|
}
|
|
916
1099
|
}
|
|
917
1100
|
|
|
1101
|
+
// Emit comments that are inside the block but not attached to any node
|
|
1102
|
+
// (comments between last statement and 'end')
|
|
1103
|
+
let had_internal_comments =
|
|
1104
|
+
self.has_comments_in_range(block_start_line + 1, block_end_line);
|
|
1105
|
+
if had_internal_comments {
|
|
1106
|
+
// Preserve blank line between last statement and first comment
|
|
1107
|
+
self.emit_comments_in_range_with_prev_line(
|
|
1108
|
+
block_start_line + 1,
|
|
1109
|
+
block_end_line,
|
|
1110
|
+
indent_level + 1,
|
|
1111
|
+
last_stmt_end_line,
|
|
1112
|
+
)?;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// Add newline if there were internal comments
|
|
1116
|
+
if had_internal_comments && !self.buffer.ends_with('\n') {
|
|
1117
|
+
self.buffer.push('\n');
|
|
1118
|
+
}
|
|
1119
|
+
|
|
918
1120
|
// Emit 'end'
|
|
919
1121
|
self.emit_indent(indent_level)?;
|
|
920
1122
|
write!(self.buffer, "end")?;
|
|
1123
|
+
// Emit trailing comments on end line
|
|
1124
|
+
self.emit_trailing_comments(block_end_line)?;
|
|
921
1125
|
|
|
922
1126
|
Ok(())
|
|
923
1127
|
}
|
|
@@ -995,6 +1199,20 @@ impl Emitter {
|
|
|
995
1199
|
if let Some(text) = text_owned {
|
|
996
1200
|
self.emit_indent(indent_level)?;
|
|
997
1201
|
write!(self.buffer, "{}", text)?;
|
|
1202
|
+
|
|
1203
|
+
// Mark comments that are strictly inside this node's line range as emitted
|
|
1204
|
+
// (they are included in the source extraction)
|
|
1205
|
+
// Don't mark trailing comments on the last line (they come after the node ends)
|
|
1206
|
+
for (idx, comment) in self.all_comments.iter().enumerate() {
|
|
1207
|
+
if !self.emitted_comment_indices.contains(&idx)
|
|
1208
|
+
&& comment.location.start_line >= node.location.start_line
|
|
1209
|
+
&& comment.location.end_line < node.location.end_line
|
|
1210
|
+
{
|
|
1211
|
+
self.emitted_comment_indices.push(idx);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// Emit trailing comments on the same line (after the node ends)
|
|
998
1216
|
self.emit_trailing_comments(node.location.end_line)?;
|
|
999
1217
|
}
|
|
1000
1218
|
}
|
|
@@ -1015,12 +1233,13 @@ impl Emitter {
|
|
|
1015
1233
|
self.emit_indent(indent_level)?;
|
|
1016
1234
|
write!(self.buffer, "{}", text)?;
|
|
1017
1235
|
|
|
1018
|
-
// Mark comments
|
|
1236
|
+
// Mark comments that are strictly inside this node's line range as emitted
|
|
1019
1237
|
// (they are included in the source extraction)
|
|
1238
|
+
// Don't mark trailing comments on the last line (they come after the node ends)
|
|
1020
1239
|
for (idx, comment) in self.all_comments.iter().enumerate() {
|
|
1021
1240
|
if !self.emitted_comment_indices.contains(&idx)
|
|
1022
1241
|
&& comment.location.start_line >= node.location.start_line
|
|
1023
|
-
&& comment.location.end_line
|
|
1242
|
+
&& comment.location.end_line < node.location.end_line
|
|
1024
1243
|
{
|
|
1025
1244
|
self.emitted_comment_indices.push(idx);
|
|
1026
1245
|
}
|
|
@@ -1091,6 +1310,8 @@ impl Emitter {
|
|
|
1091
1310
|
|
|
1092
1311
|
self.emit_indent(indent_level)?;
|
|
1093
1312
|
write!(self.buffer, "end")?;
|
|
1313
|
+
// Emit trailing comments on end line
|
|
1314
|
+
self.emit_trailing_comments(node.location.end_line)?;
|
|
1094
1315
|
|
|
1095
1316
|
Ok(())
|
|
1096
1317
|
}
|
|
@@ -1142,6 +1363,8 @@ impl Emitter {
|
|
|
1142
1363
|
|
|
1143
1364
|
self.emit_indent(indent_level)?;
|
|
1144
1365
|
write!(self.buffer, "end")?;
|
|
1366
|
+
// Emit trailing comments on end line
|
|
1367
|
+
self.emit_trailing_comments(node.location.end_line)?;
|
|
1145
1368
|
|
|
1146
1369
|
Ok(())
|
|
1147
1370
|
}
|
data/lib/rfmt/rfmt.so
CHANGED
|
Binary file
|
data/lib/rfmt/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rfmt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- fujitani sora
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rb_sys
|