Skip to main content

nargo_transformer/
plugin.rs

1use nargo_ir::IRModule;
2use nargo_types::{NargoValue, Result, Span};
3use serde::{Deserialize, Serialize};
4use std::{collections::HashMap, ffi::OsStr, fs, path::Path};
5
6/// 插件生命周期阶段
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
8pub enum PluginLifecycle {
9    /// 初始化阶段,插件首次加载时执行
10    Init,
11    /// 变换前阶段,在所有变换开始前执行
12    PreTransform,
13    /// 变换阶段,与内置变换一起执行
14    Transform,
15    /// 变换后阶段,在所有变换完成后执行
16    PostTransform,
17    /// 清理阶段,在整个变换过程结束后执行
18    Cleanup,
19}
20
21/// 插件配置项
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct PluginConfig {
24    /// 插件名称
25    pub name: String,
26    /// 插件版本
27    pub version: String,
28    /// 插件描述
29    pub description: String,
30    /// 插件优先级(数值越小,优先级越高)
31    pub priority: i32,
32    /// 插件配置参数
33    pub config: HashMap<String, NargoValue>,
34    /// 插件启用状态
35    pub enabled: bool,
36}
37
38/// 插件接口
39pub trait Plugin: Send + Sync {
40    /// 获取插件名称
41    fn name(&self) -> String;
42
43    /// 获取插件描述
44    fn description(&self) -> String;
45
46    /// 初始化插件
47    fn init(&mut self, config: &PluginConfig) -> Result<()>;
48
49    /// 执行插件逻辑
50    fn run(&mut self, ir: &mut IRModule, lifecycle: PluginLifecycle) -> Result<()>;
51
52    /// 清理插件资源
53    fn cleanup(&mut self) -> Result<()>;
54}
55
56/// 插件管理器
57pub struct PluginManager {
58    plugins: Vec<Box<dyn Plugin>>,
59    configs: HashMap<String, PluginConfig>,
60}
61
62impl Default for PluginManager {
63    fn default() -> Self {
64        Self::new()
65    }
66}
67
68impl PluginManager {
69    /// 创建新的插件管理器
70    pub fn new() -> Self {
71        Self { plugins: Vec::new(), configs: HashMap::new() }
72    }
73
74    /// 加载插件
75    pub fn load_plugin<P: Plugin + 'static>(&mut self, plugin: P, config: PluginConfig) -> Result<()> {
76        let plugin_name = plugin.name();
77
78        // 初始化插件
79        let mut plugin_box = Box::new(plugin);
80        plugin_box.init(&config)?;
81
82        // 存储插件和配置
83        self.plugins.push(plugin_box);
84        self.configs.insert(plugin_name, config);
85
86        // 按优先级排序插件
87        self.plugins.sort_by(|a, b| {
88            let a_name = a.name();
89            let b_name = b.name();
90            let a_priority = self.configs.get(&a_name).map(|c| c.priority).unwrap_or(0);
91            let b_priority = self.configs.get(&b_name).map(|c| c.priority).unwrap_or(0);
92            a_priority.cmp(&b_priority)
93        });
94
95        Ok(())
96    }
97
98    /// 从目录加载插件
99    pub fn load_plugins_from_directory(&mut self, directory: &Path) -> Result<()> {
100        if !directory.exists() || !directory.is_dir() {
101            return Ok(()); // 目录不存在,直接返回
102        }
103
104        for entry in fs::read_dir(directory)? {
105            let entry = entry?;
106            let path = entry.path();
107
108            // 只处理 .rs 文件
109            if path.is_file() && path.extension() == Some(OsStr::new("rs")) {
110                // 这里简化处理,实际实现可能需要动态加载或编译插件
111                // 目前我们假设插件已经通过 crate 依赖的方式集成
112                // 后续可以扩展为支持动态加载
113            }
114        }
115
116        Ok(())
117    }
118
119    /// 执行指定生命周期阶段的所有插件
120    pub fn run_plugins(&mut self, ir: &mut IRModule, lifecycle: PluginLifecycle) -> Result<()> {
121        for plugin in &mut self.plugins {
122            let plugin_name = plugin.name();
123            let config = self.configs.get(&plugin_name).unwrap();
124
125            if config.enabled {
126                plugin.run(ir, lifecycle.clone())?;
127            }
128        }
129
130        Ok(())
131    }
132
133    /// 清理所有插件
134    pub fn cleanup_plugins(&mut self) -> Result<()> {
135        for plugin in &mut self.plugins {
136            plugin.cleanup()?;
137        }
138
139        Ok(())
140    }
141
142    /// 获取所有插件信息
143    pub fn get_plugins_info(&self) -> Vec<(String, PluginConfig)> {
144        self.configs.iter().map(|(name, config)| (name.clone(), config.clone())).collect()
145    }
146
147    /// 启用或禁用插件
148    pub fn set_plugin_enabled(&mut self, plugin_name: &str, enabled: bool) -> Result<()> {
149        if let Some(config) = self.configs.get_mut(plugin_name) {
150            config.enabled = enabled;
151            Ok(())
152        }
153        else {
154            Err(nargo_types::Error::external_error("PluginManager".to_string(), format!("Plugin {} not found", plugin_name), Span::unknown()))
155        }
156    }
157}