@@ -8,19 +8,23 @@ use std::cmp::Ordering;
8
8
9
9
use crate :: configuration:: * ;
10
10
11
- // a little rough, but good enough for our purposes
11
+ // very rough... this should be improved to not allocate so much
12
+ // and be cleaner
12
13
13
- pub fn get_node_sorter_from_order < ' a > ( order : SortOrder ) -> Option < Box < dyn Fn ( ( usize , Option < Node < ' a > > ) , ( usize , Option < Node < ' a > > ) , Program < ' a > ) -> Ordering > > {
14
+ pub fn get_node_sorter_from_order < ' a > (
15
+ order : SortOrder ,
16
+ named_type_imports_exports_order : NamedTypeImportsExportsOrder ,
17
+ ) -> Option < Box < dyn Fn ( ( usize , Option < Node < ' a > > ) , ( usize , Option < Node < ' a > > ) , Program < ' a > ) -> Ordering > > {
14
18
// todo: how to reduce code duplication here?
15
19
match order {
16
20
SortOrder :: Maintain => None ,
17
- SortOrder :: CaseInsensitive => Some ( Box :: new ( |( a_index, a) , ( b_index, b) , program| {
21
+ SortOrder :: CaseInsensitive => Some ( Box :: new ( move |( a_index, a) , ( b_index, b) , program| {
18
22
let result = if is_import_or_export_declaration ( & a) {
19
- cmp_optional_nodes ( a, b, program, |a, b, module| {
23
+ cmp_optional_nodes ( a, b, program, named_type_imports_exports_order , |a, b, module| {
20
24
cmp_module_specifiers ( a. text_fast ( module) , b. text_fast ( module) , cmp_text_case_insensitive)
21
25
} )
22
26
} else {
23
- cmp_optional_nodes ( a, b, program, |a, b, module| {
27
+ cmp_optional_nodes ( a, b, program, named_type_imports_exports_order , |a, b, module| {
24
28
cmp_text_case_insensitive ( a. text_fast ( module) , b. text_fast ( module) )
25
29
} )
26
30
} ;
@@ -30,13 +34,15 @@ pub fn get_node_sorter_from_order<'a>(order: SortOrder) -> Option<Box<dyn Fn((us
30
34
result
31
35
}
32
36
} ) ) ,
33
- SortOrder :: CaseSensitive => Some ( Box :: new ( |( a_index, a) , ( b_index, b) , program| {
37
+ SortOrder :: CaseSensitive => Some ( Box :: new ( move |( a_index, a) , ( b_index, b) , program| {
34
38
let result = if is_import_or_export_declaration ( & a) {
35
- cmp_optional_nodes ( a, b, program, |a, b, module| {
39
+ cmp_optional_nodes ( a, b, program, named_type_imports_exports_order , |a, b, module| {
36
40
cmp_module_specifiers ( a. text_fast ( module) , b. text_fast ( module) , cmp_text_case_sensitive)
37
41
} )
38
42
} else {
39
- cmp_optional_nodes ( a, b, program, |a, b, module| cmp_text_case_sensitive ( a. text_fast ( module) , b. text_fast ( module) ) )
43
+ cmp_optional_nodes ( a, b, program, named_type_imports_exports_order, |a, b, module| {
44
+ cmp_text_case_sensitive ( a. text_fast ( module) , b. text_fast ( module) )
45
+ } )
40
46
} ;
41
47
if result == Ordering :: Equal {
42
48
a_index. cmp ( & b_index)
@@ -51,11 +57,12 @@ fn cmp_optional_nodes<'a>(
51
57
a : Option < Node < ' a > > ,
52
58
b : Option < Node < ' a > > ,
53
59
program : Program < ' a > ,
60
+ named_type_imports_exports_order : NamedTypeImportsExportsOrder ,
54
61
cmp_func : impl Fn ( & SourceRange , & SourceRange , Program < ' a > ) -> Ordering ,
55
62
) -> Ordering {
56
63
if let Some ( a) = a {
57
64
if let Some ( b) = b {
58
- cmp_nodes ( a, b, program, cmp_func)
65
+ cmp_nodes ( a, b, program, named_type_imports_exports_order , cmp_func)
59
66
} else {
60
67
Ordering :: Greater
61
68
}
@@ -66,15 +73,36 @@ fn cmp_optional_nodes<'a>(
66
73
}
67
74
}
68
75
69
- fn cmp_nodes < ' a > ( a : Node < ' a > , b : Node < ' a > , program : Program < ' a > , cmp_func : impl Fn ( & SourceRange , & SourceRange , Program < ' a > ) -> Ordering ) -> Ordering {
76
+ fn cmp_nodes < ' a > (
77
+ a : Node < ' a > ,
78
+ b : Node < ' a > ,
79
+ program : Program < ' a > ,
80
+ named_type_imports_exports_order : NamedTypeImportsExportsOrder ,
81
+ cmp_func : impl Fn ( & SourceRange , & SourceRange , Program < ' a > ) -> Ordering ,
82
+ ) -> Ordering {
70
83
let a_nodes = get_comparison_nodes ( a) ;
71
84
let b_nodes = get_comparison_nodes ( b) ;
72
85
73
86
for ( i, a) in a_nodes. iter ( ) . enumerate ( ) {
74
87
if let Some ( b) = b_nodes. get ( i) {
75
- let cmp_result = cmp_func ( a, b, program) ;
76
- if cmp_result != Ordering :: Equal {
77
- return cmp_result;
88
+ match ( a, b) {
89
+ ( ComparisonNode :: HasType , ComparisonNode :: NoType ) => match named_type_imports_exports_order {
90
+ NamedTypeImportsExportsOrder :: First => return Ordering :: Less ,
91
+ NamedTypeImportsExportsOrder :: Last => return Ordering :: Greater ,
92
+ NamedTypeImportsExportsOrder :: None => { }
93
+ } ,
94
+ ( ComparisonNode :: NoType , ComparisonNode :: HasType ) => match named_type_imports_exports_order {
95
+ NamedTypeImportsExportsOrder :: First => return Ordering :: Greater ,
96
+ NamedTypeImportsExportsOrder :: Last => return Ordering :: Less ,
97
+ NamedTypeImportsExportsOrder :: None => { }
98
+ } ,
99
+ ( ComparisonNode :: Node ( a) , ComparisonNode :: Node ( b) ) => {
100
+ let cmp_result = cmp_func ( a, b, program) ;
101
+ if cmp_result != Ordering :: Equal {
102
+ return cmp_result;
103
+ }
104
+ }
105
+ _ => { }
78
106
}
79
107
} else {
80
108
return Ordering :: Greater ;
@@ -88,42 +116,58 @@ fn cmp_nodes<'a>(a: Node<'a>, b: Node<'a>, program: Program<'a>, cmp_func: impl
88
116
}
89
117
}
90
118
91
- fn get_comparison_nodes ( node : Node ) -> Vec < SourceRange > {
119
+ enum ComparisonNode {
120
+ HasType ,
121
+ NoType ,
122
+ Node ( SourceRange ) ,
123
+ }
124
+
125
+ fn get_comparison_nodes ( node : Node ) -> Vec < ComparisonNode > {
92
126
match node {
93
127
Node :: ImportNamedSpecifier ( node) => {
128
+ let first_node = if node. is_type_only ( ) {
129
+ ComparisonNode :: HasType
130
+ } else {
131
+ ComparisonNode :: NoType
132
+ } ;
94
133
if let Some ( imported) = & node. imported {
95
- vec ! [ imported. range( ) , node. local. range( ) ]
134
+ vec ! [ first_node , ComparisonNode :: Node ( imported. range( ) ) , ComparisonNode :: Node ( node. local. range( ) ) ]
96
135
} else {
97
- vec ! [ node. local. range( ) ]
136
+ vec ! [ first_node , ComparisonNode :: Node ( node. local. range( ) ) ]
98
137
}
99
138
}
100
139
Node :: ExportNamedSpecifier ( node) => {
140
+ let first_node = if node. is_type_only ( ) {
141
+ ComparisonNode :: HasType
142
+ } else {
143
+ ComparisonNode :: NoType
144
+ } ;
101
145
if let Some ( exported) = & node. exported {
102
- vec ! [ node. orig. range( ) , exported. range( ) ]
146
+ vec ! [ first_node , ComparisonNode :: Node ( node. orig. range( ) ) , ComparisonNode :: Node ( exported. range( ) ) ]
103
147
} else {
104
- vec ! [ node. orig. range( ) ]
148
+ vec ! [ first_node , ComparisonNode :: Node ( node. orig. range( ) ) ]
105
149
}
106
150
}
107
151
Node :: ImportDecl ( node) => {
108
- vec ! [ node. src. range( ) ]
152
+ vec ! [ ComparisonNode :: Node ( node. src. range( ) ) ]
109
153
}
110
154
Node :: NamedExport ( node) => {
111
155
if let Some ( src) = & node. src {
112
- vec ! [ src. range( ) ]
156
+ vec ! [ ComparisonNode :: Node ( src. range( ) ) ]
113
157
} else if cfg ! ( debug_assertions) {
114
158
unimplemented ! ( "Should not call this for named exports with src." ) ;
115
159
} else {
116
- vec ! [ node. range( ) ]
160
+ vec ! [ ComparisonNode :: Node ( node. range( ) ) ]
117
161
}
118
162
}
119
163
Node :: ExportAll ( node) => {
120
- vec ! [ node. src. range( ) ]
164
+ vec ! [ ComparisonNode :: Node ( node. src. range( ) ) ]
121
165
}
122
166
_ => {
123
167
if cfg ! ( debug_assertions) {
124
168
unimplemented ! ( "Not implemented sort node." ) ;
125
169
} else {
126
- vec ! [ node. range( ) ]
170
+ vec ! [ ComparisonNode :: Node ( node. range( ) ) ]
127
171
}
128
172
}
129
173
}
0 commit comments