use alloc::borrow::ToOwned;
use alloc::string::String;
use alloc::vec::Vec;
use crate::ast::AstGraph;
use crate::query::{get_node_by_path, label_text, match_ast_d, match_ast_group, match_ast_group_d};
use crate::syntax::builders::import_global::build_import_global_node;
use crate::syntax::fields::javascript::import_statement;
use crate::syntax::readers::javascript::common::strip_quotes;
use crate::syntax::{SyntaxGraphArgs, SyntaxGraphError};
use crate::utilities::text_nodes::node_to_str;
use crate::NodeId;
pub fn reader(
args: &mut SyntaxGraphArgs<'_>,
n_id: NodeId,
) -> Result<Option<NodeId>, SyntaxGraphError> {
let graph = args.ast_graph;
let mut expression = args
.required_field_alt(n_id, import_statement::SOURCE)
.ok()
.map(|source_id| strip_quotes(&node_to_str(graph, source_id)))
.unwrap_or_default();
let import_clauses = match_ast_group(
graph,
n_id,
&["import_clause", "import_require_clause"],
None,
);
let clause0 = import_clauses
.get("import_clause")
.filter(|v| !v.is_empty())
.or_else(|| {
import_clauses
.get("import_require_clause")
.filter(|v| !v.is_empty())
})
.and_then(|v| v.first().copied());
let (alias, module_nodes) =
clause0.map_or((None, Vec::new()), |clause| resolve_imports(graph, clause));
if let Some(req0) = import_clauses
.get("import_require_clause")
.and_then(|v| v.first().copied())
{
if let Some(exp_id) = get_node_by_path(graph, req0, &["string", "string_fragment"]) {
expression = label_text(graph, exp_id)
.map(ToOwned::to_owned)
.unwrap_or_default();
}
}
build_import_global_node(args, n_id, expression, &module_nodes, alias).map(Some)
}
fn resolve_imports(graph: &AstGraph, clause: NodeId) -> (Option<String>, Vec<NodeId>) {
let imports = match_ast_group(
graph,
clause,
&["namespace_import", "named_imports", "identifier"],
None,
);
let ns_identifier = imports
.get("namespace_import")
.and_then(|v| v.first())
.and_then(|ns| match_ast_d(graph, *ns, "identifier", None));
let first_identifier = imports.get("identifier").and_then(|v| v.first().copied());
let mut alias = None;
let mut module_nodes = Vec::new();
if let Some(id) = ns_identifier.or(first_identifier) {
alias = label_text(graph, id).map(ToOwned::to_owned);
} else if let Some(named0) = imports
.get("named_imports")
.and_then(|v| v.first().copied())
{
module_nodes.extend(match_ast_group_d(graph, named0, "import_specifier", None));
}
if imports.get("identifier").is_some_and(|v| !v.is_empty()) {
if let Some(named0) = imports
.get("named_imports")
.and_then(|v| v.first().copied())
{
module_nodes.extend(match_ast_group_d(graph, named0, "import_specifier", None));
}
}
(alias, module_nodes)
}