use alloc::vec;
use alloc::vec::Vec;
use crate::path_search::search::{SearchArgs, SearchResult};
use crate::query::adj_ast;
use crate::syntax::SyntaxNode;
use crate::NodeId;
fn method_modifies_symbol(
args: &SearchArgs<'_>,
expression: &str,
object_id: Option<NodeId>,
) -> bool {
let object_match = object_id
.and_then(|o_id| args.graph.nodes.get(&o_id))
.and_then(SyntaxNode::symbol)
== Some(args.symbol);
let dotted = expression
.split_once('.')
.is_some_and(|(head, _)| head == args.symbol);
let arrow = expression
.split_once("->")
.is_some_and(|(head, _)| head.trim_start_matches('$') == args.symbol);
object_match || dotted || arrow
}
fn method_calls_symbol(args: &SearchArgs<'_>, arguments_id: Option<NodeId>) -> bool {
let Some(al_id) = arguments_id else {
return false;
};
adj_ast(args.graph, al_id, Some(1), &["SymbolLookup"])
.into_iter()
.any(|n_id| args.graph.nodes.get(&n_id).and_then(SyntaxNode::symbol) == Some(args.symbol))
}
pub fn search(args: &SearchArgs<'_>) -> Vec<SearchResult> {
let Some(SyntaxNode::MethodInvocation {
expression,
object_id,
arguments_id,
..
}) = args.graph.nodes.get(&args.n_id)
else {
return Vec::new();
};
let modifies = !args.def_only && method_modifies_symbol(args, expression, *object_id);
let calls = args.all_related && method_calls_symbol(args, *arguments_id);
if modifies || calls {
return vec![(false, args.n_id)];
}
Vec::new()
}