Skip to content

Commit 31a78e3

Browse files
committed
fix: #119 - Import and exports should be sorted taking folders into account.
1 parent a117b19 commit 31a78e3

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

src/parsing/sorting/module_specifiers.rs

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ pub fn cmp_module_specifiers(a: &str, b: &str, cmp_text: impl Fn(&str, &str) ->
44
let a_info = get_module_specifier_info(a);
55
let b_info = get_module_specifier_info(b);
66

7-
match a_info.kind {
7+
return match a_info.kind {
88
ModuleSpecifierKind::Absolute => {
99
match b_info.kind {
10-
ModuleSpecifierKind::Absolute => cmp_text(a_info.comparison_text, b_info.comparison_text),
10+
ModuleSpecifierKind::Absolute => compare_folder_items(&a_info, &b_info, cmp_text),
1111
ModuleSpecifierKind::Relative(_) => Ordering::Less,
1212
}
1313
},
@@ -20,17 +20,42 @@ pub fn cmp_module_specifiers(a: &str, b: &str, cmp_text: impl Fn(&str, &str) ->
2020
} else if a_relative_count < b_relative_count {
2121
Ordering::Greater
2222
} else {
23-
cmp_text(a_info.comparison_text, b_info.comparison_text)
23+
compare_folder_items(&a_info, &b_info, cmp_text)
2424
}
2525
},
2626
}
2727
}
28+
};
29+
30+
fn compare_folder_items(a_info: &ModuleSpecifierInfo, b_info: &ModuleSpecifierInfo, cmp_text: impl Fn(&str, &str) -> Ordering) -> Ordering {
31+
let max_len = std::cmp::min(a_info.folder_items.len(), b_info.folder_items.len());
32+
// compare the common items except for the potential file name at the end
33+
for i in 0..max_len - 1 {
34+
let a_text = a_info.folder_items[i];
35+
let b_text = b_info.folder_items[i];
36+
let ordering = cmp_text(a_text, b_text);
37+
if ordering != Ordering::Equal {
38+
return ordering;
39+
}
40+
}
41+
42+
if a_info.folder_items.len() != b_info.folder_items.len() {
43+
// the import that has a folder name should appear before the one with a file name
44+
if a_info.folder_items.len() > b_info.folder_items.len() {
45+
Ordering::Less
46+
} else {
47+
Ordering::Greater
48+
}
49+
} else {
50+
// compare the file names
51+
cmp_text(a_info.folder_items.last().unwrap(), b_info.folder_items.last().unwrap())
52+
}
2853
}
2954
}
3055

3156
struct ModuleSpecifierInfo<'a> {
32-
comparison_text: &'a str,
3357
kind: ModuleSpecifierKind,
58+
folder_items: Vec<&'a str>,
3459
}
3560

3661
#[derive(Debug, PartialEq)]
@@ -59,12 +84,12 @@ fn get_module_specifier_info<'a>(text: &'a str) -> ModuleSpecifierInfo<'a> {
5984
}
6085

6186
ModuleSpecifierInfo {
62-
comparison_text: &no_quotes_text[start_index..],
87+
folder_items: no_quotes_text[start_index..].split('/').collect(),
6388
kind: ModuleSpecifierKind::Relative(relative_count),
6489
}
6590
} else {
6691
ModuleSpecifierInfo {
67-
comparison_text: no_quotes_text,
92+
folder_items: no_quotes_text.split('/').collect(),
6893
kind: ModuleSpecifierKind::Absolute,
6994
}
7095
}
@@ -93,39 +118,39 @@ mod test {
93118
#[test]
94119
fn it_should_get_module_specifier_info_when_empty() {
95120
let result = get_module_specifier_info("''");
96-
assert_eq!(result.comparison_text, "");
121+
assert_eq!(result.folder_items, vec![""]);
97122
assert_eq!(result.kind, ModuleSpecifierKind::Absolute);
98123
}
99124

100125
#[test]
101126
fn it_should_get_module_specifier_info_for_absolute() {
102127
// double quotes
103128
let result = get_module_specifier_info(r#""testing/asdf""#);
104-
assert_eq!(result.comparison_text, "testing/asdf");
129+
assert_eq!(result.folder_items, vec!["testing", "asdf"]);
105130
assert_eq!(result.kind, ModuleSpecifierKind::Absolute);
106131

107132
// single quotes
108133
let result = get_module_specifier_info("'testing'");
109-
assert_eq!(result.comparison_text, "testing");
134+
assert_eq!(result.folder_items, vec!["testing"]);
110135
assert_eq!(result.kind, ModuleSpecifierKind::Absolute);
111136
}
112137

113138
#[test]
114139
fn it_should_get_module_specifier_info_for_relative() {
115140
let result = get_module_specifier_info("'./a'");
116-
assert_eq!(result.comparison_text, "a");
141+
assert_eq!(result.folder_items, vec!["a"]);
117142
assert_eq!(result.kind, ModuleSpecifierKind::Relative(0));
118143

119144
let result = get_module_specifier_info("'./../testing-test/t'");
120-
assert_eq!(result.comparison_text, "testing-test/t");
145+
assert_eq!(result.folder_items, vec!["testing-test", "t"]);
121146
assert_eq!(result.kind, ModuleSpecifierKind::Relative(1));
122147

123148
let result = get_module_specifier_info("'../asdf'");
124-
assert_eq!(result.comparison_text, "asdf");
149+
assert_eq!(result.folder_items, vec!["asdf"]);
125150
assert_eq!(result.kind, ModuleSpecifierKind::Relative(1));
126151

127152
let result = get_module_specifier_info("'../../../test'");
128-
assert_eq!(result.comparison_text, "test");
153+
assert_eq!(result.folder_items, vec!["test"]);
129154
assert_eq!(result.kind, ModuleSpecifierKind::Relative(3));
130155
}
131156
}

tests/specs/file/sorting/Statements_SortOrder.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import "../../b";
66
import "b";
77
import "a";
88
import "../../a";
9+
import "../../a/b";
910
export * from "c";
1011
export * from "a";
1112
test;
@@ -19,6 +20,7 @@ import "a";
1920
// testing
2021
import "a";
2122
import "b";
23+
import "../../a/b";
2224
import "../../a";
2325
import "../../b";
2426
import "../a";
@@ -91,3 +93,13 @@ import { a } from "test";
9193
// other
9294

9395
import { a } from "test";
96+
97+
== should put folders above files ==
98+
import * as t from "https://deno.land/x/a.ts";
99+
import * as u from "https://deno.land/x/sub-dir/a.ts";
100+
import * as u from "https://deno.land/x/sub-dir/other/a.ts";
101+
102+
[expect]
103+
import * as u from "https://deno.land/x/sub-dir/other/a.ts";
104+
import * as u from "https://deno.land/x/sub-dir/a.ts";
105+
import * as t from "https://deno.land/x/a.ts";

0 commit comments

Comments
 (0)