use crate::syntax::fields::php::{namespace_use_clause, namespace_use_declaration};
use crate::{
query::{adj_ast, label_text, match_ast_d, match_ast_group_d},
syntax::{
builders::import_statement::{build_import_statement_node, ImportElement},
SyntaxGraphArgs, SyntaxGraphError,
},
utilities::text_nodes::node_to_str,
NodeId,
};
use alloc::{format, string::String, vec::Vec};
pub fn reader(
args: &mut SyntaxGraphArgs<'_>,
n_id: NodeId,
) -> Result<Option<NodeId>, SyntaxGraphError> {
let graph = args.ast_graph;
let prefix = match_ast_d(graph, n_id, "namespace_name", None)
.map(|prefix_n_id| node_to_str(graph, prefix_n_id));
let clauses_parent = args
.optional_field_alt(n_id, namespace_use_declaration::BODY)
.unwrap_or(n_id);
let typed_statement = args
.optional_field_alt(n_id, namespace_use_declaration::TYPE)
.is_some();
let elements: Vec<ImportElement> =
match_ast_group_d(graph, clauses_parent, "namespace_use_clause", None)
.into_iter()
.filter_map(|clause_n_id| {
clause_element(args, clause_n_id, prefix.as_deref(), typed_statement)
})
.collect();
build_import_statement_node(args, n_id, &elements, false, &[]).map(Some)
}
fn clause_element(
args: &SyntaxGraphArgs<'_>,
clause_n_id: NodeId,
prefix: Option<&str>,
typed_statement: bool,
) -> Option<ImportElement> {
let graph = args.ast_graph;
let alias_n_id = args.optional_field_alt(clause_n_id, namespace_use_clause::ALIAS);
let name_n_id = adj_ast(graph, clause_n_id, None, &["name", "qualified_name"])
.into_iter()
.find(|child_n_id| Some(*child_n_id) != alias_n_id)?;
let name = node_to_str(graph, name_n_id);
let qualified = prefix.map_or_else(|| name.clone(), |prefix| format!("{prefix}\\{name}"));
let expression = qualified
.strip_prefix('\\')
.map_or_else(|| qualified.clone(), String::from);
let alias = alias_n_id
.and_then(|alias_n_id| label_text(graph, alias_n_id))
.map(String::from);
let typed_clause = typed_statement
|| args
.optional_field_alt(clause_n_id, namespace_use_clause::TYPE)
.is_some();
let bound_name = if typed_clause {
String::new()
} else {
alias
.clone()
.unwrap_or_else(|| String::from(expression.rsplit('\\').next().unwrap_or(&expression)))
};
Some(ImportElement {
expression: Some(expression),
alias,
corrected_n_id: Some(clause_n_id),
bound_name: Some(bound_name),
..ImportElement::default()
})
}