Skip to content

Commit b3e58fe

Browse files
committed
chore: Fix issues for import/export decl sorting implementation.
* Fix comment block not having a newline when on line before. * Handle exports with a module specifier. Open a question in swc about maybe removing implementing `Spanned` on `Option<S>`.
1 parent fee133d commit b3e58fe

File tree

4 files changed

+69
-12
lines changed

4 files changed

+69
-12
lines changed

src/parsing/parser.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4410,14 +4410,6 @@ fn parse_leading_comments<'a>(node: &dyn SpanDataContainer, context: &mut Contex
44104410
parse_comments_as_leading(node, leading_comments, context)
44114411
}
44124412

4413-
fn parse_leading_comments_on_previous_lines<'a>(node: &dyn SpanDataContainer, last_node: Option<&dyn SpanDataContainer>, context: &mut Context<'a>) -> PrintItems {
4414-
let node_start_line = node.start_line(context);
4415-
let leading_comments_on_previous_lines = node.leading_comments(context)
4416-
.take_while(|c| c.kind == CommentKind::Line || c.start_line(context) < node_start_line)
4417-
.collect::<Vec<&'a Comment>>();
4418-
parse_comment_collection(leading_comments_on_previous_lines.into_iter(), last_node, None, context)
4419-
}
4420-
44214413
fn parse_comments_as_leading<'a>(node: &dyn SpanDataContainer, comments: CommentsIterator<'a>, context: &mut Context<'a>) -> PrintItems {
44224414
let mut items = PrintItems::new();
44234415
if let Some(last_comment) = comments.get_last_comment() {
@@ -4450,6 +4442,13 @@ fn parse_trailing_comments_as_statements<'a>(node: &dyn SpanDataContainer, conte
44504442
parse_comments_as_statements(unhandled_comments.into_iter(), Some(node), context)
44514443
}
44524444

4445+
fn get_leading_comments_on_previous_lines<'a>(node: &dyn SpanDataContainer, context: &mut Context<'a>) -> Vec<&'a Comment> {
4446+
let node_start_line = node.start_line(context);
4447+
node.leading_comments(context)
4448+
.take_while(|c| c.kind == CommentKind::Line || c.start_line(context) < node_start_line)
4449+
.collect::<Vec<_>>()
4450+
}
4451+
44534452
fn get_trailing_comments_as_statements<'a>(node: &dyn SpanDataContainer, context: &mut Context<'a>) -> Vec<&'a Comment> {
44544453
let mut comments = Vec::new();
44554454
let node_end_line = node.end_line(context);
@@ -4791,12 +4790,18 @@ fn parse_statements<'a>(inner_span_data: Span, stmts: Vec<Node<'a>>, context: &m
47914790
for (stmt_group_index, stmt_group) in stmt_groups.into_iter().enumerate() {
47924791
if stmt_group.kind == StmtGroupKind::Imports || stmt_group.kind == StmtGroupKind::Exports {
47934792
// keep the leading comments of the stmt group on the same line
4794-
items.extend(parse_leading_comments_on_previous_lines(&stmt_group.nodes.first().as_ref().unwrap().lo(), if let Some(last_node) = &last_node {
4795-
// todo: why can't I just use .as_ref() here and why does this need to be inlined?
4793+
let comments = get_leading_comments_on_previous_lines(&stmt_group.nodes.first().as_ref().unwrap().lo(), context);
4794+
let last_comment = comments.iter()
4795+
.filter(|c| !context.has_handled_comment(c))
4796+
.last()
4797+
.map(|c| (&c.span).into());
4798+
items.extend(parse_comments_as_statements(comments.into_iter(), if let Some(last_node) = &last_node {
4799+
// todo: why can't I just use .as_ref() here?
47964800
Some(last_node)
47974801
} else {
47984802
None
47994803
}, context));
4804+
last_node = last_comment.or(last_node);
48004805
}
48014806

48024807
let nodes_len = stmt_group.nodes.len();
@@ -4900,7 +4905,11 @@ fn get_stmt_groups<'a>(stmts: Vec<Node<'a>>, context: &mut Context<'a>) -> Vec<S
49004905
let last_end_line = previous_last_end_line.take();
49014906
let stmt_group_kind = match stmt {
49024907
Node::ImportDecl(_) => StmtGroupKind::Imports,
4903-
Node::NamedExport(_) | Node::ExportAll(_) => StmtGroupKind::Exports,
4908+
Node::ExportAll(_) => StmtGroupKind::Exports,
4909+
Node::NamedExport(NamedExport {
4910+
src: Some(_),
4911+
..
4912+
}) => StmtGroupKind::Exports,
49044913
_ => StmtGroupKind::Other,
49054914
};
49064915
previous_last_end_line = match stmt_group_kind {

src/parsing/sorting/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,14 @@ fn get_comparison_nodes<'a>(node: &Node<'a>) -> Vec<Span> {
108108
vec![node.src.span()]
109109
},
110110
Node::NamedExport(node) => {
111-
vec![node.src.span()]
111+
if let Some(src) = &node.src {
112+
vec![src.span()]
113+
} else {
114+
#[cfg(debug_assertions)]
115+
unimplemented!("Should not call this for named exports with src.");
116+
#[cfg(not(debug_assertions))]
117+
vec![node.span_data()]
118+
}
112119
},
113120
Node::ExportAll(node) => {
114121
vec![node.src.span()]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
== should format ==
2+
export { n1 } from "test";
3+
export { n1 };
4+
5+
[expect]
6+
export { n1 } from "test";
7+
export { n1 };

tests/specs/statements/sorting/Statements_SortOrder.txt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,37 @@ import "n";
5757
// group 2
5858
import "a";
5959
import "b";
60+
61+
== should keep leading comment block on separate line ==
62+
/**
63+
* testing
64+
*/
65+
import * as test from "b";
66+
import * as test from "a";
67+
68+
[expect]
69+
/**
70+
* testing
71+
*/
72+
import * as test from "a";
73+
import * as test from "b";
74+
75+
== should handle comments in between on different lines ==
76+
import { a } from "test";
77+
78+
/* barrel:ignore */
79+
import { a } from "test";
80+
81+
// other
82+
83+
import { a } from "test";
84+
85+
[expect]
86+
import { a } from "test";
87+
88+
/* barrel:ignore */
89+
import { a } from "test";
90+
91+
// other
92+
93+
import { a } from "test";

0 commit comments

Comments
 (0)