use alloc::borrow::ToOwned;
use crate::ast::AstGraph;
use crate::syntax::dispatchers::Dispatcher;
use crate::syntax::fields::{OptionalField, RequiredField};
use crate::syntax::readers::common::missing_node;
use crate::syntax::{SyntaxGraph, SyntaxGraphError, SyntaxMetadata};
use crate::{CodeGraph, Language, NodeId};
pub type SyntaxReader =
fn(args: &mut SyntaxGraphArgs<'_>, n_id: NodeId) -> Result<Option<NodeId>, SyntaxGraphError>;
pub struct SyntaxGraphArgs<'a> {
pub language: Language,
pub ast_graph: &'a AstGraph,
pub syntax_graph: &'a mut SyntaxGraph,
pub metadata: &'a mut SyntaxMetadata,
pub dispatcher: Dispatcher,
}
impl<'a> SyntaxGraphArgs<'a> {
#[must_use]
pub fn new(
language: Language,
ast_graph: &'a AstGraph,
syntax_graph: &'a mut SyntaxGraph,
metadata: &'a mut SyntaxMetadata,
dispatcher: Dispatcher,
) -> Self {
Self {
language,
ast_graph,
syntax_graph,
metadata,
dispatcher,
}
}
pub fn generic(&mut self, n_id: NodeId) -> Result<NodeId, SyntaxGraphError> {
let ast_graph = self.ast_graph;
let node_type = ast_graph
.label_type(n_id)
.ok_or(SyntaxGraphError::MissingAstNode)?;
let built = match (self.dispatcher)(node_type) {
Some(reader) => reader(self, n_id)?,
None => None,
};
built.map_or_else(
|| missing_node::reader(self, n_id, node_type.to_owned()),
Ok,
)
}
#[must_use]
pub fn optional_field_alt<F: OptionalField>(&self, n_id: NodeId, key: F) -> Option<NodeId> {
self.ast_graph
.nodes
.get(&n_id)
.and_then(|node| node.fields.get(key.name()).copied())
}
pub fn required_field_alt<F: RequiredField>(
&self,
n_id: NodeId,
key: F,
) -> Result<NodeId, SyntaxGraphError> {
self.ast_graph
.nodes
.get(&n_id)
.ok_or(SyntaxGraphError::MissingAstNode)?
.fields
.get(key.name())
.copied()
.ok_or(SyntaxGraphError::UnexpectedAstShape)
}
}