use crate::{
ast::{Body, EnumVariant, ExprKind, ItemField, ItemKind, StmtKind},
common::{BodyId, ExprId, FieldId, ItemId, Level, StmtId, VariantId},
ffi,
lint::Lint,
prelude::{HasNodeId, NodeId},
};
#[repr(C)]
#[cfg_attr(feature = "driver-api", derive(typed_builder::TypedBuilder))]
pub struct AstMap<'ast> {
callbacks: AstMapCallbacks<'ast>,
}
impl<'ast> AstMap<'ast> {
pub fn lint_level_at(&self, lint: &'static Lint, node: impl HasNodeId) -> Level {
(self.callbacks.lint_level_at)(self.callbacks.data, lint, node.node_id())
}
pub fn item(&self, id: ItemId) -> Option<ItemKind<'ast>> {
(self.callbacks.item)(self.callbacks.data, id).copy()
}
pub fn unwrap_item(&self, id: ItemId) -> ItemKind<'ast> {
self.item(id)
.unwrap_or_else(|| panic!("The requested item is unavailable (id = {id:?})"))
}
pub fn variant(&self, id: VariantId) -> Option<&EnumVariant<'ast>> {
(self.callbacks.variant)(self.callbacks.data, id).copy()
}
pub fn unwrap_variant(&self, id: VariantId) -> &EnumVariant<'ast> {
self.variant(id)
.unwrap_or_else(|| panic!("The requested enum variant is unavailable (id = {id:?})"))
}
pub fn field(&self, id: FieldId) -> Option<&ItemField<'ast>> {
(self.callbacks.field)(self.callbacks.data, id).copy()
}
pub fn unwrap_field(&self, id: FieldId) -> &ItemField<'ast> {
self.field(id)
.unwrap_or_else(|| panic!("The requested field is unavailable (id = {id:?})"))
}
pub fn body(&self, id: BodyId) -> &Body<'ast> {
(self.callbacks.body)(self.callbacks.data, id)
}
pub fn stmt(&self, id: StmtId) -> StmtKind<'ast> {
(self.callbacks.stmt)(self.callbacks.data, id)
}
pub fn expr(&self, id: ExprId) -> ExprKind<'ast> {
(self.callbacks.expr)(self.callbacks.data, id)
}
}
#[repr(C)]
#[cfg_attr(feature = "driver-api", visibility::make(pub))]
#[cfg_attr(feature = "driver-api", derive(typed_builder::TypedBuilder))]
struct AstMapCallbacks<'ast> {
pub data: &'ast AstMapData,
pub item: extern "C" fn(data: &'ast AstMapData, id: ItemId) -> ffi::FfiOption<ItemKind<'ast>>,
pub variant: extern "C" fn(data: &'ast AstMapData, id: VariantId) -> ffi::FfiOption<&'ast EnumVariant<'ast>>,
pub field: extern "C" fn(data: &'ast AstMapData, id: FieldId) -> ffi::FfiOption<&'ast ItemField<'ast>>,
pub body: extern "C" fn(data: &'ast AstMapData, id: BodyId) -> &'ast Body<'ast>,
pub stmt: extern "C" fn(data: &'ast AstMapData, id: StmtId) -> StmtKind<'ast>,
pub expr: extern "C" fn(data: &'ast AstMapData, id: ExprId) -> ExprKind<'ast>,
pub lint_level_at: extern "C" fn(data: &'ast AstMapData, lint: &'static Lint, node: NodeId) -> Level,
}
#[repr(C)]
#[cfg_attr(feature = "driver-api", visibility::make(pub))]
struct AstMapData {
_data: usize,
}