use crate::syntax::fields::ruby::call;
use crate::{
query::{get_nodes_by_path, match_ast_group_d},
syntax::{
builders::{
import_statement::{build_import_statement_node, ImportElement},
method_invocation::{build_method_invocation_node, DirectChildren},
},
SyntaxGraphArgs, SyntaxGraphError,
},
utilities::text_nodes::node_to_str,
NodeId,
};
use alloc::borrow::ToOwned;
use alloc::{collections::BTreeSet, string::String};
use alloc::{format, vec};
fn process_ruby_imports(
args: &mut SyntaxGraphArgs<'_>,
n_id: NodeId,
argument_id: NodeId,
method_name: &str,
) -> Result<Option<NodeId>, SyntaxGraphError> {
let graph = args.ast_graph;
let mut module_nodes = BTreeSet::<NodeId>::new();
let first_path = get_nodes_by_path(graph, argument_id, &["string", "string_content"]);
let second_path = get_nodes_by_path(
graph,
argument_id,
&["string", "interpolation", "identifier"],
);
let arg = match_ast_group_d(graph, argument_id, "identifier", Some(1));
module_nodes.extend(first_path);
module_nodes.extend(second_path);
module_nodes.extend(arg);
let mut import_attrs: vec::Vec<ImportElement> = vec::Vec::new();
for module_id in module_nodes {
let module_expression = node_to_str(graph, module_id);
import_attrs.push(ImportElement {
expression: Some(module_expression),
method_name: Some(method_name.to_owned()),
corrected_n_id: Some(module_id),
..Default::default()
});
}
build_import_statement_node(args, n_id, &import_attrs, false, &[]).map(Some)
}
pub fn reader(
args: &mut SyntaxGraphArgs<'_>,
n_id: NodeId,
) -> Result<Option<NodeId>, SyntaxGraphError> {
let graph = args.ast_graph;
let argument_id = args.optional_field_alt(n_id, call::ARGUMENTS);
let method_id = args.optional_field_alt(n_id, call::METHOD);
let operator_id = args.optional_field_alt(n_id, call::OPERATOR);
let object_id = args.optional_field_alt(n_id, call::RECEIVER);
let block_id = args.optional_field_alt(n_id, call::BLOCK);
let mut method_name = method_id.map_or_else(String::new, |id| node_to_str(graph, id));
if operator_id.is_some_and(|op_id| node_to_str(graph, op_id) == "::") {
method_name = format!("::{method_name}");
}
let ruby_imports = &["require", "require_relative", "load", "autoload"];
if ruby_imports.contains(&method_name.as_str()) && object_id.is_none() {
if let Some(arguments_id) = argument_id {
return process_ruby_imports(args, n_id, arguments_id, &method_name);
}
}
let children = DirectChildren {
expression_id: method_id,
arguments_id: argument_id,
object_id,
block_id,
};
build_method_invocation_node(args, n_id, method_name, children, None).map(Some)
}