Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/generation/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8047,16 +8047,27 @@ fn gen_node_with_separator<'a>(value: Node<'a>, generated_separator: PrintItems,
PrintItems::new()
};

// comments that sit between the node and the comma on a subsequent line —
// the default trailing-comments path only emits same-line comments, so these
// would otherwise be dropped (issue #684).
let between_node_and_comma = if let Some(comma_token) = comma_token {
gen_comments_between_node_and_comma(value, comma_token, context)
} else {
PrintItems::new()
};

// if the current node is ignored and already has a semi-colon, then skip adding a separator
let is_ignored_with_semi_colon =
value.text_fast(context.program).ends_with(';') && get_has_ignore_comment(&value.leading_comments_fast(context.program), value, context);
if is_ignored_with_semi_colon {
items.extend(gen_node(value, context));
} else {
let generated_separator = generated_separator.into_rc_path();
let between_node_and_comma = between_node_and_comma.into_rc_path();
items.extend(gen_node_with_inner_gen(value, context, move |mut items, _| {
// this Rc clone is necessary because we can't move the captured generated_separator out of this closure
items.push_optional_path(generated_separator);
items.push_optional_path(between_node_and_comma);
items
}));
}
Expand All @@ -8073,6 +8084,38 @@ fn gen_node_with_separator<'a>(value: Node<'a>, generated_separator: PrintItems,
}
}

fn gen_comments_between_node_and_comma<'a>(value: Node<'a>, comma_token: &TokenAndSpan, context: &mut Context<'a>) -> PrintItems {
// collect comments between the node end and the comma — these would be classified
// as trailing comments of the node, but the existing path only emits ones on the
// same line, dropping anything that sits on a subsequent line.
let node_end = value.range().end;
let node_end_line = node_end.end_line_fast(context.program);
let mut comments_to_emit = Vec::new();
for comment in comma_token.range().start.leading_comments_fast(context.program) {
if context.has_handled_comment(&comment) {
continue;
}
if comment.start() < node_end {
continue;
}
// skip same-line trailing comments — those flow through the regular trailing path
if comment.start_line_fast(context.program) <= node_end_line {
continue;
}
comments_to_emit.push(comment);
}

if comments_to_emit.is_empty() {
return PrintItems::new();
}

let comma_range = comma_token.range();
let mut items = PrintItems::new();
items.push_signal(Signal::NewLine);
items.extend(gen_comment_collection(comments_to_emit.into_iter(), None, Some(&comma_range), context));
items
}

/// Some nodes don't have a TsTypeAnn, but instead a Box<TsType>
fn gen_type_ann_with_colon_if_exists_for_type<'a>(type_ann: Option<TsType<'a>>, context: &mut Context<'a>) -> PrintItems {
if let Some(type_ann) = type_ann {
Expand Down
71 changes: 71 additions & 0 deletions tests/specs/issues/issue0684.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
== should preserve comment between argument and following comma (issue #684) ==
const x = useMemo(() =>
doSomething()
// eslint-disable-next-line react-hooks/exhaustive-deps
, [dep]);

[expect]
const x = useMemo(
() => doSomething(),
// eslint-disable-next-line react-hooks/exhaustive-deps
[dep],
);

== should preserve multiple comments between argument and comma ==
foo(
a
// c1
/* c2 */
// c3
, b);

[expect]
foo(
a,
// c1
/* c2 */
// c3
b,
);

== should preserve comment before comma in array literal ==
[
1
// c
, 2
];

[expect]
[
1,
// c
2,
];

== should preserve comment before comma in object literal ==
({
a: 1
// c
, b: 2
});

[expect]
({
a: 1,
// c
b: 2,
});

== should preserve comment before comma in function parameters ==
function f(
a
// c
, b
) {}

[expect]
function f(
a,
// c
b,
) {}
Loading