baobao_codegen/language/traits.rs
1//! Language-agnostic code generation traits.
2
3use std::path::Path;
4
5use baobao_core::{ArgType, ContextFieldType};
6use eyre::Result;
7
8/// Trait for language-specific code generators.
9///
10/// Implement this trait to add support for generating CLI code in a new language.
11pub trait LanguageCodegen {
12 /// Language identifier (e.g., "rust", "typescript", "go")
13 fn language(&self) -> &'static str;
14
15 /// File extension for generated source files (e.g., "rs", "ts", "go")
16 fn file_extension(&self) -> &'static str;
17
18 /// Preview generated files without writing to disk
19 fn preview(&self) -> Vec<PreviewFile>;
20
21 /// Generate all files into the specified output directory
22 fn generate(&self, output_dir: &Path) -> Result<GenerateResult>;
23
24 /// Clean orphaned generated files.
25 ///
26 /// Removes:
27 /// - Generated command files that are no longer in the manifest
28 /// - Unmodified handler stubs that are no longer in the manifest
29 ///
30 /// Handler files that have been modified by the user are not deleted.
31 ///
32 /// Default implementation returns an empty result (no cleaning).
33 fn clean(&self, _output_dir: &Path) -> Result<CleanResult> {
34 Ok(CleanResult::default())
35 }
36
37 /// Preview what would be cleaned without actually deleting files.
38 ///
39 /// Default implementation returns an empty result.
40 fn preview_clean(&self, _output_dir: &Path) -> Result<CleanResult> {
41 Ok(CleanResult::default())
42 }
43}
44
45/// Result of code generation
46#[derive(Debug, Default)]
47pub struct GenerateResult {
48 /// Handler files that were created (stubs for new commands)
49 pub created_handlers: Vec<String>,
50 /// Handler files that exist but are no longer used
51 pub orphan_handlers: Vec<String>,
52}
53
54/// Result of cleaning orphaned files
55#[derive(Debug, Default)]
56pub struct CleanResult {
57 /// Generated command files that were deleted
58 pub deleted_commands: Vec<String>,
59 /// Handler files that were deleted (unmodified stubs)
60 pub deleted_handlers: Vec<String>,
61 /// Handler files that were skipped (modified by user)
62 pub skipped_handlers: Vec<String>,
63}
64
65/// A generated file for preview
66#[derive(Debug)]
67pub struct PreviewFile {
68 /// Relative path from output directory
69 pub path: String,
70 /// File content
71 pub content: String,
72}
73
74/// Trait for mapping schema types to language-specific type strings.
75///
76/// Implement this trait for each target language to provide type mappings.
77pub trait TypeMapper {
78 /// The target language name
79 fn language(&self) -> &'static str;
80
81 /// Map an argument type to a language-specific type string
82 fn map_arg_type(&self, arg_type: ArgType) -> &'static str;
83
84 /// Map an optional argument type (e.g., `Option<String>` in Rust, `string | undefined` in TS)
85 fn map_optional_arg_type(&self, arg_type: ArgType) -> String {
86 // Default implementation - languages can override
87 format!("Option<{}>", self.map_arg_type(arg_type))
88 }
89
90 /// Map a context field type to a language-specific type string
91 fn map_context_type(&self, field_type: &ContextFieldType) -> &'static str;
92}