ruff/crates/ruff_python_ast/src/stmt_if.rs
Charlie Marsh fc89976c24
Move Ranged into ruff_text_size (#6919)
## Summary

The motivation here is that this enables us to implement `Ranged` in
crates that don't depend on `ruff_python_ast`.

Largely a mechanical refactor with a lot of regex, Clippy help, and
manual fixups.

## Test Plan

`cargo test`
2023-08-27 14:12:51 -04:00

48 lines
1.4 KiB
Rust

use crate::{ElifElseClause, Expr, Stmt, StmtIf};
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
use ruff_text_size::{Ranged, TextRange};
use std::iter;
/// Return the `Range` of the first `Elif` or `Else` token in an `If` statement.
pub fn elif_else_range(clause: &ElifElseClause, contents: &str) -> Option<TextRange> {
let token = SimpleTokenizer::new(contents, clause.range)
.skip_trivia()
.next()?;
matches!(token.kind, SimpleTokenKind::Elif | SimpleTokenKind::Else).then_some(token.range())
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum BranchKind {
If,
Elif,
}
pub struct IfElifBranch<'a> {
pub kind: BranchKind,
pub test: &'a Expr,
pub body: &'a [Stmt],
pub range: TextRange,
}
impl Ranged for IfElifBranch<'_> {
fn range(&self) -> TextRange {
self.range
}
}
pub fn if_elif_branches(stmt_if: &StmtIf) -> impl Iterator<Item = IfElifBranch> {
iter::once(IfElifBranch {
kind: BranchKind::If,
test: stmt_if.test.as_ref(),
body: stmt_if.body.as_slice(),
range: TextRange::new(stmt_if.start(), stmt_if.body.last().unwrap().end()),
})
.chain(stmt_if.elif_else_clauses.iter().filter_map(|clause| {
Some(IfElifBranch {
kind: BranchKind::Elif,
test: clause.test.as_ref()?,
body: clause.body.as_slice(),
range: clause.range,
})
}))
}