use crate::syntax::{SyntaxGraph, SyntaxNode};
#[must_use]
fn node_variable_type(node: &SyntaxNode) -> Option<&str> {
match node {
SyntaxNode::Parameter { variable_type, .. }
| SyntaxNode::VariableDeclaration { variable_type, .. } => variable_type.as_deref(),
_ => None,
}
}
#[must_use]
pub fn fqn_from_graph_imports<'a>(sg: &'a SyntaxGraph, name: &str) -> Option<&'a str> {
sg.nodes.values().find_map(|node| {
if !matches!(node.label_type(), "Import" | "ModuleImport") {
return None;
}
let expr = node.expression()?;
if expr.is_empty() || expr.ends_with(".*") {
return None;
}
(expr.rsplit('.').next() == Some(name)).then_some(expr)
})
}
#[must_use]
pub fn fqn_from_graph_variable_type<'a>(sg: &'a SyntaxGraph, symbol: &str) -> Option<&'a str> {
sg.symbol_index
.get(symbol)
.into_iter()
.flat_map(|scopes| scopes.values())
.flatten()
.find_map(|nid| {
let var_type = node_variable_type(sg.nodes.get(nid)?)?;
if var_type.is_empty() {
return None;
}
if var_type.contains('.') {
return Some(var_type);
}
fqn_from_graph_imports(sg, var_type)
})
}
#[must_use]
pub fn receiver_fqn_from_graph_symbol<'a>(sg: &'a SyntaxGraph, symbol: &str) -> Option<&'a str> {
fqn_from_graph_imports(sg, symbol).or_else(|| fqn_from_graph_variable_type(sg, symbol))
}