rustpython_ruff_python_ast/token/
parentheses.rs1use ruff_text_size::{Ranged, TextLen, TextRange};
2
3use super::{TokenKind, Tokens};
4use crate::{AnyNodeRef, ExprRef};
5
6pub fn parentheses_iterator<'a>(
14 expr: ExprRef<'a>,
15 parent: Option<AnyNodeRef>,
16 tokens: &'a Tokens,
17) -> impl Iterator<Item = TextRange> + 'a {
18 let after_tokens = if let Some(parent) = parent {
19 let exclusive_parent_end = if parent.is_arguments() {
23 parent.end() - ")".text_len()
24 } else {
25 parent.end()
26 };
27
28 tokens.in_range(TextRange::new(expr.end(), exclusive_parent_end))
29 } else {
30 tokens.after(expr.end())
31 };
32
33 let right_parens = after_tokens
34 .iter()
35 .filter(|token| !token.kind().is_trivia())
36 .take_while(move |token| token.kind() == TokenKind::Rpar);
37
38 let left_parens = tokens
39 .before(expr.start())
40 .iter()
41 .rev()
42 .filter(|token| !token.kind().is_trivia())
43 .take_while(|token| token.kind() == TokenKind::Lpar);
44
45 right_parens
46 .zip(left_parens)
47 .map(|(right, left)| TextRange::new(left.start(), right.end()))
48}
49
50pub fn parenthesized_range(
53 expr: ExprRef,
54 parent: AnyNodeRef,
55 tokens: &Tokens,
56) -> Option<TextRange> {
57 parentheses_iterator(expr, Some(parent), tokens).last()
58}