use crate::ast::AstGraph;
use crate::query::match_ast_group_d;
use crate::syntax::builders::array_node::build_array_node;
use crate::syntax::builders::object::build_object_node;
use crate::syntax::builders::object_creation::build_object_creation_node;
use crate::syntax::fields::go::composite_literal;
use crate::syntax::readers::go::common::{literal_elements, ARRAY_TYPES};
use crate::syntax::{SyntaxGraphArgs, SyntaxGraphError};
use crate::utilities::text_nodes::node_to_str;
use crate::{CodeGraph, NodeId};
const NAMED_TYPES: &[&str] = &["qualified_type", "type_identifier"];
fn element_type_id(graph: &AstGraph, type_id: NodeId) -> Option<NodeId> {
if !ARRAY_TYPES.contains(&graph.label_type(type_id).unwrap_or_default()) {
return None;
}
graph.nodes.get(&type_id)?.fields.get("element_id").copied()
}
pub fn build_composite(
args: &mut SyntaxGraphArgs<'_>,
n_id: NodeId,
type_id: NodeId,
body_id: NodeId,
) -> Result<NodeId, SyntaxGraphError> {
let element_id = element_type_id(args.ast_graph, type_id);
args.metadata.element_type_stack.push(element_id);
let built = build_shape(args, n_id, type_id, body_id);
args.metadata.element_type_stack.pop();
built
}
fn build_shape(
args: &mut SyntaxGraphArgs<'_>,
n_id: NodeId,
type_id: NodeId,
body_id: NodeId,
) -> Result<NodeId, SyntaxGraphError> {
let graph = args.ast_graph;
let type_kind = graph.label_type(type_id).unwrap_or_default();
let type_name = node_to_str(graph, type_id);
if ARRAY_TYPES.contains(&type_kind) {
let elements = literal_elements(graph, body_id);
let element_type = element_type_id(graph, type_id)
.filter(|id| NAMED_TYPES.contains(&graph.label_type(*id).unwrap_or_default()))
.map(|id| node_to_str(graph, id));
return build_array_node(args, n_id, &elements, element_type);
}
if !match_ast_group_d(graph, body_id, "keyed_element", None).is_empty() {
let initializer_id = (type_kind != "map_type").then_some(type_id);
return build_object_creation_node(
args,
n_id,
type_name,
Some(body_id),
initializer_id,
None,
);
}
let name = NAMED_TYPES.contains(&type_kind).then_some(type_name);
let c_ids: &[NodeId] = if type_kind == "qualified_type" {
&[type_id, body_id]
} else {
&[body_id]
};
build_object_node(args, n_id, c_ids, name, None)
}
pub fn reader(
args: &mut SyntaxGraphArgs<'_>,
n_id: NodeId,
) -> Result<Option<NodeId>, SyntaxGraphError> {
let type_id = args.required_field_alt(n_id, composite_literal::TYPE)?;
let body_id = args.required_field_alt(n_id, composite_literal::BODY)?;
build_composite(args, n_id, type_id, body_id).map(Some)
}