Skip to content

Commit 0b395d7

Browse files
autofix-ci[bot]leaysgur
authored andcommitted
[autofix.ci] apply automated fixes
1 parent fb4ce3f commit 0b395d7

File tree

4 files changed

+72
-5
lines changed

4 files changed

+72
-5
lines changed

crates/oxc_formatter/src/ir_transform/sort_imports/import_unit.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ impl<'a> SortableImport<'a> {
6767
has_namespace_specifier: *has_namespace_specifier,
6868
has_named_specifier: *has_named_specifier,
6969
path_kind: to_path_kind(source),
70+
source,
7071
};
7172
self.group_idx = matcher.match_group(&options.groups);
7273

@@ -112,17 +113,18 @@ fn has_side_effect_style_group(groups: &[Vec<String>]) -> bool {
112113
/// Contains all characteristics of an import needed to determine which group it belongs to,
113114
/// such as whether it's a type import, side-effect import, style import, and what kind of path it uses.
114115
#[derive(Debug, Clone)]
115-
struct ImportGroupMatcher {
116+
struct ImportGroupMatcher<'a> {
116117
is_side_effect: bool,
117118
is_type_import: bool,
118119
is_style_import: bool,
119120
has_default_specifier: bool,
120121
has_namespace_specifier: bool,
121122
has_named_specifier: bool,
122123
path_kind: ImportPathKind,
124+
source: &'a str,
123125
}
124126

125-
impl ImportGroupMatcher {
127+
impl<'a> ImportGroupMatcher<'a> {
126128
/// Match this import against the configured groups and return the group index.
127129
/// Returns the index of the first matching group, or the index of "unknown" group if present,
128130
/// or the last index + 1 if no match found.
@@ -195,6 +197,7 @@ impl ImportGroupMatcher {
195197
| ImportSelector::Parent
196198
| ImportSelector::Sibling
197199
| ImportSelector::Index
200+
| ImportSelector::Subpath
198201
);
199202

200203
if is_path_type_selector {
@@ -274,15 +277,30 @@ impl ImportGroupMatcher {
274277
}
275278

276279
// Path-based selectors
280+
// Order matches perfectionist: index, sibling, parent, subpath, internal, builtin, external
277281
match self.path_kind {
278282
ImportPathKind::Index => selectors.push(ImportSelector::Index),
279283
ImportPathKind::Sibling => selectors.push(ImportSelector::Sibling),
280284
ImportPathKind::Parent => selectors.push(ImportSelector::Parent),
285+
ImportPathKind::Internal => {}
286+
ImportPathKind::Builtin => {}
287+
ImportPathKind::External => {}
288+
ImportPathKind::Unknown => {}
289+
}
290+
291+
// Subpath selector (independent of path kind, comes after parent)
292+
if is_subpath(self.source) {
293+
selectors.push(ImportSelector::Subpath);
294+
}
295+
296+
// Continue with remaining path-based selectors
297+
match self.path_kind {
281298
ImportPathKind::Internal => selectors.push(ImportSelector::Internal),
282299
ImportPathKind::Builtin => selectors.push(ImportSelector::Builtin),
283300
ImportPathKind::External => selectors.push(ImportSelector::External),
284-
ImportPathKind::Unknown => {}
301+
_ => {}
285302
}
303+
286304
// Catch-all selector
287305
selectors.push(ImportSelector::Import);
288306

@@ -345,6 +363,8 @@ enum ImportSelector {
345363
Sibling,
346364
/// Parent module imports (`../foo`)
347365
Parent,
366+
/// Subpath imports (package.json imports field, e.g., `#foo`)
367+
Subpath,
348368
/// Internal module imports (matching internal patterns like `~/`, `@/`)
349369
Internal,
350370
/// Built-in module imports (`node:fs`, `fs`)
@@ -372,6 +392,7 @@ impl ImportSelector {
372392
Self::Index => "index",
373393
Self::Sibling => "sibling",
374394
Self::Parent => "parent",
395+
Self::Subpath => "subpath",
375396
Self::Internal => "internal",
376397
Self::Builtin => "builtin",
377398
Self::External => "external",
@@ -520,3 +541,9 @@ fn is_index_import(source: &str) -> bool {
520541
| "./index.d.js"
521542
) || source.ends_with('/')
522543
}
544+
545+
/// Check if an import is a Node.js subpath import.
546+
/// Subpath imports start with '#' and are defined in package.json imports field.
547+
fn is_subpath(source: &str) -> bool {
548+
source.starts_with('#')
549+
}

crates/oxc_formatter/src/ir_transform/sort_imports/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,9 @@ fn sort_within_group(
375375
let mut non_side_effect_iter = non_side_effect_indices.into_iter();
376376

377377
for pos in 0..indices.len() {
378-
if let Some(&(se_pos, se_idx)) = side_effect_iter.peek() && se_pos == pos {
378+
if let Some(&(se_pos, se_idx)) = side_effect_iter.peek()
379+
&& se_pos == pos
380+
{
379381
result.push(se_idx);
380382
side_effect_iter.next();
381383
continue;

crates/oxc_formatter/tests/ir_transform/_sort-imports-tests.ref.snap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ describe("misc", () => {
8383
options: [
8484
{
8585
groups: ["builtin", "external", "side-effect"],
86-
newlinesBetween: "never",
8786
},
8887
],
8988
});

crates/oxc_formatter/tests/ir_transform/sort_imports.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,4 +1574,43 @@ import { b } from "b";
15741574
import { a } from "@/a";
15751575
"#,
15761576
);
1577+
// Supports subpath
1578+
assert_format(
1579+
r##"
1580+
import a from "../a";
1581+
import b from "./b";
1582+
import subpath from "#subpath";
1583+
import e from "timers";
1584+
import c from "./index";
1585+
import d from "d";
1586+
1587+
import style from "style.css";
1588+
"##,
1589+
r#"{
1590+
"experimentalSortImports": {
1591+
"groups": [
1592+
"style",
1593+
[
1594+
"index",
1595+
"internal",
1596+
"subpath",
1597+
"external",
1598+
"sibling",
1599+
"builtin",
1600+
"parent"
1601+
]
1602+
]
1603+
}
1604+
}"#,
1605+
r##"
1606+
import style from "style.css";
1607+
1608+
import subpath from "#subpath";
1609+
import a from "../a";
1610+
import b from "./b";
1611+
import c from "./index";
1612+
import d from "d";
1613+
import e from "timers";
1614+
"##,
1615+
);
15771616
}

0 commit comments

Comments
 (0)