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}