use alloc::format;
use alloc::string::String;
use crate::query::match_ast;
use crate::syntax::builders::method_invocation::{build_method_invocation_node, DirectChildren};
use crate::syntax::fields::c_sharp::invocation_expression;
use crate::syntax::readers::common::receiver_fqn::{
fqn_from_graph_imports, receiver_fqn_from_graph_symbol,
};
use crate::syntax::{SyntaxGraph, SyntaxGraphArgs, SyntaxGraphError, SyntaxNode};
use crate::utilities::text_nodes::node_to_str;
use crate::NodeId;
fn receiver_fqn_from_node(sg: &SyntaxGraph, n_id: Option<NodeId>) -> Option<String> {
match sg.nodes.get(&n_id?)? {
SyntaxNode::MemberAccess {
member,
expression_id,
..
} => {
let member = member.trim_start_matches(':');
let inner = receiver_fqn_from_node(sg, Some(*expression_id))?;
(!inner.is_empty() && !member.is_empty()).then(|| format!("{inner}.{member}"))
}
SyntaxNode::SymbolLookup { symbol, value, .. } => {
let raw = if symbol.is_empty() {
value.as_deref().unwrap_or_default()
} else {
symbol.as_str()
};
let trimmed = raw.trim_start_matches(':');
if trimmed.is_empty() {
None
} else {
receiver_fqn_from_graph_symbol(sg, trimmed).map(String::from)
}
}
SyntaxNode::ObjectCreation { name, .. } => {
let name = name.trim_start_matches(':');
if name.is_empty() {
None
} else if name.contains('.') {
Some(String::from(name))
} else {
fqn_from_graph_imports(sg, name).map(String::from)
}
}
SyntaxNode::MethodInvocation {
receiver_type_fqn, ..
} => receiver_type_fqn.clone(),
_ => None,
}
}
fn member_access_receiver(sg: &SyntaxGraph, invocation_id: NodeId) -> Option<NodeId> {
let SyntaxNode::MethodInvocation {
expression_id: Some(expr_id),
..
} = sg.nodes.get(&invocation_id)?
else {
return None;
};
match sg.nodes.get(expr_id)? {
SyntaxNode::MemberAccess { expression_id, .. } => Some(*expression_id),
_ => None,
}
}
pub fn reader(
args: &mut SyntaxGraphArgs<'_>,
n_id: NodeId,
) -> Result<Option<NodeId>, SyntaxGraphError> {
let graph = args.ast_graph;
let arguments_id = args.required_field_alt(n_id, invocation_expression::ARGUMENTS)?;
let expr_id = args.required_field_alt(n_id, invocation_expression::FUNCTION)?;
let expr = node_to_str(graph, expr_id);
let include_args = match_ast(graph, arguments_id, &["(", ")"], None).contains_key("__0__");
let children = DirectChildren {
expression_id: Some(expr_id),
arguments_id: include_args.then_some(arguments_id),
..DirectChildren::default()
};
let invocation_id = build_method_invocation_node(args, n_id, expr, children, None)?;
if let Some(fqn) = member_access_receiver(args.syntax_graph, invocation_id)
.and_then(|inner| receiver_fqn_from_node(args.syntax_graph, Some(inner)))
{
if let Some(SyntaxNode::MethodInvocation {
receiver_type_fqn, ..
}) = args.syntax_graph.nodes.get_mut(&invocation_id)
{
*receiver_type_fqn = Some(fqn);
}
}
Ok(Some(invocation_id))
}