Skip to main content

fxrank_lang_python/detect/
expr.rs

1//! Shared callee-rendering helpers used by both `calls` and `risk` detectors.
2
3use libcst_native::{Expression, Name};
4
5/// Render a callee expression into a dotted string: `Name("open")` → `"open"`,
6/// `Attribute(Name("requests"), "get")` → `"requests.get"`. Returns `None` for
7/// shapes we don't model (calls-of-calls, subscript callees, etc.).
8pub fn render_expr(expr: &Expression) -> Option<String> {
9    match expr {
10        Expression::Name(n) => Some(n.value.to_owned()),
11        Expression::Attribute(a) => {
12            let base = render_expr(&a.value)?;
13            Some(format!("{base}.{}", a.attr.value))
14        }
15        _ => None,
16    }
17}
18
19/// The leftmost `Name` of an expression chain — the anchor for line resolution.
20pub fn leftmost_name<'a>(expr: &'a Expression<'a>) -> Option<&'a Name<'a>> {
21    match expr {
22        Expression::Name(n) => Some(n),
23        Expression::Attribute(a) => leftmost_name(&a.value),
24        Expression::Call(c) => leftmost_name(&c.func),
25        Expression::Subscript(s) => leftmost_name(&s.value),
26        Expression::Await(a) => leftmost_name(&a.expression),
27        _ => None,
28    }
29}