Skip to content

Commit 888515b

Browse files
authored
refactor(useExportType): dedup code (#10681)
1 parent b6e1146 commit 888515b

8 files changed

Lines changed: 152 additions & 226 deletions

File tree

.changeset/thick-bugs-push.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Fixed [`useExportType`](https://biomejs.dev/linter/rules/use-export-type/) that reported useless details in some diagnostics.

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_analyze/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ biome_string_case = { workspace = true }
2525
biome_suppression = { workspace = true }
2626
biome_text_edit = { workspace = true }
2727
camino = { workspace = true }
28+
either = { workspace = true }
2829
enumflags2 = { workspace = true }
2930
indexmap = { workspace = true }
3031
rustc-hash = { workspace = true }

crates/biome_analyze/src/utils.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,14 @@ pub fn is_separated_list_sorted_by<'a, L: Language + 'a, N: AstNode<Language = L
5050
/// Chunks are sorted separately.
5151
///
5252
/// This sort is stable (i.e., does not reorder equal elements).
53-
pub fn sorted_separated_list_by<'a, L: Language + 'a, List, Node, Key>(
53+
pub fn sorted_separated_list_by<'a, L, List, Node, Key>(
5454
list: &List,
5555
get_key: impl Fn(&Node) -> Option<Key>,
5656
make_separator: fn() -> SyntaxToken<L>,
5757
comparator: impl Fn(&Key, &Key) -> Ordering,
5858
) -> Result<List, SyntaxError>
5959
where
60+
L: Language + 'a,
6061
List: AstSeparatedList<Language = L, Node = Node> + AstNode<Language = L> + 'a,
6162
Node: AstNode<Language = L> + 'a,
6263
{
@@ -117,7 +118,7 @@ where
117118
/// It allows you to add missing separators and remove an extra separator.
118119
/// Usually, you collect every pair of nodes and separators in a vector and then pass a mutable iterator to `fix_separators`.
119120
///
120-
/// See [sorted_separated_list_by] as a usage example.
121+
/// See [`sorted_separated_list_by`] as a usage example.
121122
pub fn fix_separators<'a, L: Language + 'a, N: AstNode<Language = L> + 'a>(
122123
// Mutable iterator of a list of nodes and their optional separators
123124
iter: impl std::iter::ExactSizeIterator<Item = (&'a mut N, &'a mut Option<SyntaxToken<L>>)>,
@@ -159,6 +160,78 @@ pub fn fix_separators<'a, L: Language + 'a, N: AstNode<Language = L> + 'a>(
159160
}
160161
}
161162

163+
/// Splits the list into two new lists according to a partitioning function.
164+
///
165+
/// Every item of `list` is passed to `partition` that decides if the item is
166+
/// part of the left or the right returned list.
167+
/// The `partition` function can change the passed item before returning it.
168+
/// This allows supporting cases where the passed AST node must be modified.
169+
///
170+
/// This function returns `None` if it encounters a buggy item or
171+
/// if `partition` returns `None` for at least one item.
172+
///
173+
/// The trailing separators are moved with their node.
174+
pub fn split_separated_list<'a, L, List, Node>(
175+
list: &List,
176+
partition: impl Fn(Node) -> Option<either::Either<Node, Node>>,
177+
) -> Option<(List, List)>
178+
where
179+
L: Language + 'a,
180+
List: AstSeparatedList<Language = L, Node = Node> + AstNode<Language = L> + 'a,
181+
Node: AstNode<Language = L> + 'a,
182+
{
183+
let mut left_items = Vec::with_capacity(list.len());
184+
let mut left_separators = Vec::with_capacity(list.len());
185+
let mut right_items = Vec::with_capacity(list.len());
186+
let mut right_separators = Vec::with_capacity(list.len());
187+
188+
for AstSeparatedElement {
189+
node,
190+
trailing_separator,
191+
} in list.elements()
192+
{
193+
// Abort the split if a node is buggy or if `partition` returns `None`.
194+
let node = node.ok()?;
195+
let trailing_separator = trailing_separator.ok()?;
196+
let (items, separators, node) = match partition(node)? {
197+
either::Either::Left(node) => (&mut left_items, &mut left_separators, node),
198+
either::Either::Right(node) => (&mut right_items, &mut right_separators, node),
199+
};
200+
items.push(node);
201+
if let Some(trailing_separator) = trailing_separator {
202+
separators.push(trailing_separator);
203+
}
204+
}
205+
206+
let mut left_items = left_items.into_iter();
207+
let mut left_separators = left_separators.into_iter();
208+
let left_list = List::unwrap_cast(SyntaxNode::new_detached(
209+
list.syntax().kind(),
210+
(0..left_items.len() + left_separators.len()).map(|index| {
211+
if index % 2 == 0 {
212+
Some(left_items.next()?.into_syntax().into())
213+
} else {
214+
Some(left_separators.next()?.into())
215+
}
216+
}),
217+
));
218+
219+
let mut right_items = right_items.into_iter();
220+
let mut right_separators = right_separators.into_iter();
221+
let right_list = List::unwrap_cast(SyntaxNode::new_detached(
222+
list.syntax().kind(),
223+
(0..right_items.len() + right_separators.len()).map(|index| {
224+
if index % 2 == 0 {
225+
Some(right_items.next()?.into_syntax().into())
226+
} else {
227+
Some(right_separators.next()?.into())
228+
}
229+
}),
230+
));
231+
232+
Some((left_list, right_list))
233+
}
234+
162235
/// Counts lines in a syntax tree, used by `noExcessiveLinesPerFile`.
163236
///
164237
/// When `skip_blank_lines` is true, counts tokens with leading newlines (excluding blank lines).

crates/biome_js_analyze/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ biome_tailwind_syntax = { workspace = true }
5151
biome_unicode_table = { workspace = true }
5252
bitvec = "1.0.1"
5353
camino = { workspace = true }
54+
either = { workspace = true }
5455
enumflags2 = { workspace = true }
5556
globset = { workspace = true }
5657
phf = { workspace = true }

0 commit comments

Comments
 (0)