1use crate::IRModule;
7use std::error::Error as StdError;
8use thiserror::Error;
9
10#[derive(Error, Debug)]
12pub enum PluginError {
13 #[error("Plugin '{plugin}' initialization failed: {message}")]
15 Initialization {
16 plugin: String,
18 message: String,
20 },
21
22 #[error("Plugin '{plugin}' execution failed: {message}")]
24 Execution {
25 plugin: String,
27 message: String,
29 #[source]
31 source: Option<Box<dyn StdError + Send + Sync>>,
32 },
33
34 #[error("Plugin '{0}' not found in registry")]
36 NotFound(String),
37
38 #[error("Plugin '{0}' is already registered")]
40 AlreadyRegistered(String),
41}
42
43impl PluginError {
44 pub fn initialization(plugin: impl Into<String>, message: impl Into<String>) -> Self {
46 Self::Initialization {
47 plugin: plugin.into(),
48 message: message.into(),
49 }
50 }
51
52 pub fn execution(plugin: impl Into<String>, message: impl Into<String>) -> Self {
54 Self::Execution {
55 plugin: plugin.into(),
56 message: message.into(),
57 source: None,
58 }
59 }
60
61 pub fn with_source(mut self, error: Box<dyn StdError + Send + Sync>) -> Self {
63 if let Self::Execution { source, .. } = &mut self {
64 *source = Some(error);
65 }
66 self
67 }
68}
69
70pub trait Plugin: Send + Sync {
108 fn name(&self) -> &str;
110
111 fn version(&self) -> &str;
113
114 fn description(&self) -> Option<&str> {
116 None
117 }
118
119 fn initialize(&mut self) -> Result<(), PluginError>;
123
124 fn before_parse(&mut self, input: &str) -> Result<String, PluginError> {
129 Ok(input.to_string())
130 }
131
132 fn after_parse(&mut self, module: IRModule) -> Result<IRModule, PluginError> {
137 Ok(module)
138 }
139
140 fn after_generate(&mut self, code: String) -> Result<String, PluginError> {
145 Ok(code)
146 }
147
148 fn shutdown(&mut self) -> Result<(), PluginError> {
152 Ok(())
153 }
154}
155
156pub struct PluginRegistry {
174 plugins: Vec<Box<dyn Plugin>>,
175}
176
177impl PluginRegistry {
178 pub fn new() -> Self {
180 Self {
181 plugins: Vec::new(),
182 }
183 }
184
185 pub fn register(&mut self, mut plugin: Box<dyn Plugin>) -> Result<(), PluginError> {
200 let name = plugin.name().to_string();
201
202 if self.plugins.iter().any(|p| p.name() == name) {
204 return Err(PluginError::AlreadyRegistered(name));
205 }
206
207 plugin
209 .initialize()
210 .map_err(|e| PluginError::initialization(&name, format!("{}", e)))?;
211
212 self.plugins.push(plugin);
213 Ok(())
214 }
215
216 pub fn get(&self, name: &str) -> Option<&dyn Plugin> {
228 self.plugins
229 .iter()
230 .map(|p| p.as_ref())
231 .find(|p| p.name() == name)
232 }
233
234 pub fn get_mut(&mut self, name: &str) -> Option<&mut dyn Plugin> {
236 for plugin in &mut self.plugins {
237 if plugin.name() == name {
238 return Some(plugin.as_mut());
239 }
240 }
241 None
242 }
243
244 pub fn plugin_names(&self) -> Vec<&str> {
256 self.plugins.iter().map(|p| p.name()).collect()
257 }
258
259 pub fn count(&self) -> usize {
261 self.plugins.len()
262 }
263
264 pub fn has_plugin(&self, name: &str) -> bool {
266 self.plugins.iter().any(|p| p.name() == name)
267 }
268
269 pub fn remove(&mut self, name: &str) -> Option<Box<dyn Plugin>> {
281 let pos = self.plugins.iter().position(|p| p.name() == name)?;
282 Some(self.plugins.remove(pos))
283 }
284
285 pub fn before_parse(&mut self, mut input: String) -> Result<String, PluginError> {
289 for plugin in &mut self.plugins {
290 input = plugin.before_parse(&input)?;
291 }
292 Ok(input)
293 }
294
295 pub fn after_parse(&mut self, mut module: IRModule) -> Result<IRModule, PluginError> {
299 for plugin in &mut self.plugins {
300 module = plugin.after_parse(module)?;
301 }
302 Ok(module)
303 }
304
305 pub fn after_generate(&mut self, mut code: String) -> Result<String, PluginError> {
309 for plugin in &mut self.plugins {
310 code = plugin.after_generate(code)?;
311 }
312 Ok(code)
313 }
314
315 pub fn shutdown(&mut self) -> Result<(), PluginError> {
317 for plugin in &mut self.plugins {
318 plugin.shutdown()?;
319 }
320 Ok(())
321 }
322}
323
324impl Default for PluginRegistry {
325 fn default() -> Self {
326 Self::new()
327 }
328}
329
330impl Drop for PluginRegistry {
331 fn drop(&mut self) {
332 let _ = self.shutdown();
333 }
334}
335
336pub struct HeaderPlugin {
348 header: String,
349}
350
351impl HeaderPlugin {
352 pub fn new(header: impl Into<String>) -> Self {
354 Self {
355 header: header.into(),
356 }
357 }
358}
359
360impl Plugin for HeaderPlugin {
361 fn name(&self) -> &str {
362 "HeaderPlugin"
363 }
364
365 fn version(&self) -> &str {
366 "1.0.0"
367 }
368
369 fn description(&self) -> Option<&str> {
370 Some("Adds a header comment to generated code")
371 }
372
373 fn initialize(&mut self) -> Result<(), PluginError> {
374 Ok(())
375 }
376
377 fn after_generate(&mut self, code: String) -> Result<String, PluginError> {
378 Ok(format!("// {}\n\n{}", self.header, code))
379 }
380}
381
382pub struct LoggingPlugin {
386 verbose: bool,
387}
388
389impl LoggingPlugin {
390 pub fn new(verbose: bool) -> Self {
392 Self { verbose }
393 }
394
395 fn log(&self, stage: &str, message: &str) {
396 if self.verbose {
397 println!("[LoggingPlugin] {}: {}", stage, message);
398 }
399 }
400}
401
402impl Plugin for LoggingPlugin {
403 fn name(&self) -> &str {
404 "LoggingPlugin"
405 }
406
407 fn version(&self) -> &str {
408 "1.0.0"
409 }
410
411 fn description(&self) -> Option<&str> {
412 Some("Logs processing stages for debugging")
413 }
414
415 fn initialize(&mut self) -> Result<(), PluginError> {
416 self.log("init", "Plugin initialized");
417 Ok(())
418 }
419
420 fn before_parse(&mut self, input: &str) -> Result<String, PluginError> {
421 self.log("before_parse", &format!("Input length: {}", input.len()));
422 Ok(input.to_string())
423 }
424
425 fn after_parse(&mut self, module: IRModule) -> Result<IRModule, PluginError> {
426 self.log(
427 "after_parse",
428 &format!("Generated {} types", module.types.len()),
429 );
430 Ok(module)
431 }
432
433 fn after_generate(&mut self, code: String) -> Result<String, PluginError> {
434 self.log(
435 "after_generate",
436 &format!("Generated code: {} bytes", code.len()),
437 );
438 Ok(code)
439 }
440
441 fn shutdown(&mut self) -> Result<(), PluginError> {
442 self.log("shutdown", "Plugin shutting down");
443 Ok(())
444 }
445}
446
447#[cfg(test)]
448mod tests {
449 use super::*;
450
451 struct TestPlugin {
452 name: String,
453 initialized: bool,
454 }
455
456 impl TestPlugin {
457 fn new(name: impl Into<String>) -> Self {
458 Self {
459 name: name.into(),
460 initialized: false,
461 }
462 }
463 }
464
465 impl Plugin for TestPlugin {
466 fn name(&self) -> &str {
467 &self.name
468 }
469
470 fn version(&self) -> &str {
471 "1.0.0"
472 }
473
474 fn initialize(&mut self) -> Result<(), PluginError> {
475 self.initialized = true;
476 Ok(())
477 }
478
479 fn after_generate(&mut self, code: String) -> Result<String, PluginError> {
480 Ok(format!("// Modified by {}\n{}", self.name, code))
481 }
482 }
483
484 #[test]
485 fn test_plugin_registration() {
486 let mut registry = PluginRegistry::new();
487 let plugin = Box::new(TestPlugin::new("test1"));
488
489 registry.register(plugin).unwrap();
490 assert_eq!(registry.count(), 1);
491 assert!(registry.has_plugin("test1"));
492 }
493
494 #[test]
495 fn test_duplicate_registration() {
496 let mut registry = PluginRegistry::new();
497 registry
498 .register(Box::new(TestPlugin::new("test1")))
499 .unwrap();
500
501 let result = registry.register(Box::new(TestPlugin::new("test1")));
502 assert!(result.is_err());
503 }
504
505 #[test]
506 fn test_plugin_retrieval() {
507 let mut registry = PluginRegistry::new();
508 registry
509 .register(Box::new(TestPlugin::new("test1")))
510 .unwrap();
511
512 let plugin = registry.get("test1");
513 assert!(plugin.is_some());
514 assert_eq!(plugin.unwrap().name(), "test1");
515
516 let missing = registry.get("missing");
517 assert!(missing.is_none());
518 }
519
520 #[test]
521 fn test_plugin_removal() {
522 let mut registry = PluginRegistry::new();
523 registry
524 .register(Box::new(TestPlugin::new("test1")))
525 .unwrap();
526
527 assert_eq!(registry.count(), 1);
528
529 let removed = registry.remove("test1");
530 assert!(removed.is_some());
531 assert_eq!(registry.count(), 0);
532 }
533
534 #[test]
535 fn test_after_generate() {
536 let mut registry = PluginRegistry::new();
537 registry
538 .register(Box::new(TestPlugin::new("test1")))
539 .unwrap();
540
541 let code = "original code".to_string();
542 let result = registry.after_generate(code).unwrap();
543
544 assert!(result.contains("Modified by test1"));
545 assert!(result.contains("original code"));
546 }
547
548 #[test]
549 fn test_header_plugin() {
550 let mut plugin = HeaderPlugin::new("Generated by Test");
551 plugin.initialize().unwrap();
552
553 let code = "fn main() {}".to_string();
554 let result = plugin.after_generate(code).unwrap();
555
556 assert!(result.starts_with("// Generated by Test"));
557 }
558
559 #[test]
560 fn test_logging_plugin() {
561 let mut plugin = LoggingPlugin::new(false);
562 plugin.initialize().unwrap();
563
564 let input = "test input";
565 let result = plugin.before_parse(input).unwrap();
566 assert_eq!(result, input);
567 }
568}