cairo_lang_semantic/
plugin.rs

1use std::any::{self, Any};
2use std::sync::Arc;
3
4use cairo_lang_defs::ids::{InlineMacroExprPluginId, MacroPluginId, ModuleId};
5use cairo_lang_defs::plugin::{InlineMacroExprPlugin, MacroPlugin, NamedPlugin, PluginDiagnostic};
6use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
7use salsa::Database;
8
9use crate::ids::AnalyzerPluginId;
10
11/// A trait for an analyzer plugin: external plugin that generates additional diagnostics for
12/// modules.
13pub trait AnalyzerPlugin: std::fmt::Debug + Sync + Send + Any {
14    /// Runs the plugin on a module.
15    fn diagnostics<'db>(
16        &self,
17        db: &'db dyn Database,
18        module_id: ModuleId<'db>,
19    ) -> Vec<PluginDiagnostic<'db>>;
20    /// Allows this plugin supplies.
21    /// Any allow the plugin supplies without declaring here are likely to cause a
22    /// compilation error for unknown allow.
23    /// If the plugin checks for patterns that you want to allow in some places, for example
24    /// `#[allow(some_pattern)]` you will need to declare it here.
25    fn declared_allows(&self) -> Vec<String> {
26        Vec::new()
27    }
28
29    /// A `TypeId` of the plugin, used to compare the concrete types
30    /// of plugins given as trait objects.
31    fn plugin_type_id(&self) -> any::TypeId {
32        self.type_id()
33    }
34}
35
36/// A suite of plugins.
37#[derive(Clone, Debug, Default)]
38pub struct PluginSuite {
39    /// The macro plugins, running on all items.
40    pub plugins: Vec<Arc<dyn MacroPlugin>>,
41    /// The inline macro plugins, running on matching inline macro expressions.
42    pub inline_macro_plugins: OrderedHashMap<String, Arc<dyn InlineMacroExprPlugin>>,
43    /// The analyzer plugins, running on all modules.
44    pub analyzer_plugins: Vec<Arc<dyn AnalyzerPlugin>>,
45}
46impl PluginSuite {
47    /// Adds a macro plugin.
48    pub fn add_plugin_ex(&mut self, plugin: Arc<dyn MacroPlugin>) -> &mut Self {
49        self.plugins.push(plugin);
50        self
51    }
52    /// Adds a macro plugin.
53    pub fn add_plugin<T: MacroPlugin + Default + 'static>(&mut self) -> &mut Self {
54        self.add_plugin_ex(Arc::new(T::default()))
55    }
56    /// Adds an inline macro plugin.
57    pub fn add_inline_macro_plugin_ex(
58        &mut self,
59        name: &str,
60        plugin: Arc<dyn InlineMacroExprPlugin>,
61    ) -> &mut Self {
62        self.inline_macro_plugins.insert(name.into(), plugin);
63        self
64    }
65    /// Adds an inline macro plugin.
66    pub fn add_inline_macro_plugin<T: NamedPlugin + InlineMacroExprPlugin>(&mut self) -> &mut Self {
67        self.add_inline_macro_plugin_ex(T::NAME, Arc::new(T::default()));
68        self
69    }
70    /// Adds an analyzer plugin.
71    pub fn add_analyzer_plugin_ex(&mut self, plugin: Arc<dyn AnalyzerPlugin>) -> &mut Self {
72        self.analyzer_plugins.push(plugin);
73        self
74    }
75    /// Adds an analyzer plugin.
76    pub fn add_analyzer_plugin<T: AnalyzerPlugin + Default + 'static>(&mut self) -> &mut Self {
77        self.add_analyzer_plugin_ex(Arc::new(T::default()))
78    }
79    /// Adds another plugin suite into this suite.
80    pub fn add(&mut self, suite: PluginSuite) -> &mut Self {
81        self.plugins.extend(suite.plugins);
82        self.inline_macro_plugins.extend(suite.inline_macro_plugins);
83        self.analyzer_plugins.extend(suite.analyzer_plugins);
84        self
85    }
86}
87
88/// A helper representation for the plugin IDs obtained from
89/// [`crate::db::PluginSuiteInput::intern_plugin_suite`].
90#[derive(Clone, Debug)]
91pub struct InternedPluginSuite<'db> {
92    pub macro_plugins: Arc<[MacroPluginId<'db>]>,
93    pub inline_macro_plugins: Arc<OrderedHashMap<String, InlineMacroExprPluginId<'db>>>,
94    pub analyzer_plugins: Arc<[AnalyzerPluginId<'db>]>,
95}