use std::any::Any;
use std::ops::Deref;
use std::sync::Arc;
use cairo_lang_filesystem::ids::DiagnosticMapping;
use cairo_lang_syntax::node::ast;
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use smol_str::SmolStr;
pub trait GeneratedFileAuxData: std::fmt::Debug + Sync + Send {
fn as_any(&self) -> &dyn Any;
fn eq(&self, other: &dyn GeneratedFileAuxData) -> bool;
}
#[derive(Clone, Debug)]
pub struct DynGeneratedFileAuxData(pub Arc<dyn GeneratedFileAuxData>);
impl DynGeneratedFileAuxData {
pub fn new<T: GeneratedFileAuxData + 'static>(aux_data: T) -> Self {
DynGeneratedFileAuxData(Arc::new(aux_data))
}
}
impl Deref for DynGeneratedFileAuxData {
type Target = Arc<dyn GeneratedFileAuxData>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl PartialEq for DynGeneratedFileAuxData {
fn eq(&self, that: &DynGeneratedFileAuxData) -> bool {
GeneratedFileAuxData::eq(&*self.0, &*that.0)
}
}
impl Eq for DynGeneratedFileAuxData {}
pub struct PluginGeneratedFile {
pub name: SmolStr,
pub content: String,
pub diagnostics_mappings: Vec<DiagnosticMapping>,
pub aux_data: Option<DynGeneratedFileAuxData>,
}
#[derive(Default)]
pub struct PluginResult {
pub code: Option<PluginGeneratedFile>,
pub diagnostics: Vec<PluginDiagnostic>,
pub remove_original_item: bool,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct PluginDiagnostic {
pub stable_ptr: SyntaxStablePtrId,
pub message: String,
}
pub trait MacroPlugin: std::fmt::Debug + Sync + Send {
fn generate_code(&self, db: &dyn SyntaxGroup, item_ast: ast::Item) -> PluginResult;
fn declared_attributes(&self) -> Vec<String>;
}
#[derive(Default)]
pub struct InlinePluginResult {
pub code: Option<PluginGeneratedFile>,
pub diagnostics: Vec<PluginDiagnostic>,
}
pub trait InlineMacroExprPlugin: std::fmt::Debug + Sync + Send {
fn generate_code(
&self,
db: &dyn SyntaxGroup,
item_ast: &ast::ExprInlineMacro,
) -> InlinePluginResult;
}
pub trait NamedPlugin: Default + 'static {
const NAME: &'static str;
}
#[derive(Clone, Debug, Default)]
pub struct PluginSuite {
pub plugins: Vec<Arc<dyn MacroPlugin>>,
pub inline_macro_plugins: OrderedHashMap<String, Arc<dyn InlineMacroExprPlugin>>,
}
impl PluginSuite {
pub fn add_plugin_ex(&mut self, plugin: Arc<dyn MacroPlugin>) -> &mut Self {
self.plugins.push(plugin);
self
}
pub fn add_plugin<T: MacroPlugin + Default + 'static>(&mut self) -> &mut Self {
self.add_plugin_ex(Arc::new(T::default()))
}
pub fn add_inline_macro_plugin_ex(
&mut self,
name: &str,
plugin: Arc<dyn InlineMacroExprPlugin>,
) -> &mut Self {
self.inline_macro_plugins.insert(name.into(), plugin);
self
}
pub fn add_inline_macro_plugin<T: NamedPlugin + InlineMacroExprPlugin>(&mut self) -> &mut Self {
self.add_inline_macro_plugin_ex(T::NAME, Arc::new(T::default()));
self
}
pub fn add(&mut self, suite: PluginSuite) -> &mut Self {
self.plugins.extend(suite.plugins);
self.inline_macro_plugins.extend(suite.inline_macro_plugins);
self
}
}