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