eure_codegen/
parse.rs

1//! ParseDocument implementations for codegen configuration types.
2//!
3//! These types represent the `$codegen` and `$codegen-defaults` extensions
4//! defined in the Eure schema spec (`assets/schemas/eure-schema.schema.eure`).
5//!
6//! # Types
7//!
8//! - [`RootCodegen`] - Root-level `$codegen` extension
9//! - [`CodegenDefaults`] - Root-level `$codegen-defaults` extension
10//! - [`UnionCodegen`] - Codegen settings for union types
11//! - [`RecordCodegen`] - Codegen settings for record types
12//! - [`FieldCodegen`] - Codegen settings for individual record fields
13
14use eure_macros::ParseDocument;
15
16// ============================================================================
17// Root-Level Codegen Types
18// ============================================================================
19
20/// Root-level codegen settings.
21///
22/// Corresponds to `$types.root-codegen` in the schema.
23/// Used at document root via `$codegen` extension.
24///
25/// # Example
26///
27/// ```eure
28/// $codegen {
29///   type = "MyRootType"
30/// }
31/// ```
32#[derive(Debug, Clone, Default, ParseDocument)]
33#[eure(crate = eure_document)]
34pub struct RootCodegen {
35    /// The root type name for the generated code.
36    #[eure(rename = "type", default)]
37    pub type_name: Option<String>,
38}
39
40/// Default codegen settings applied to all types.
41///
42/// Corresponds to `$types.codegen-defaults` in the schema.
43/// Used at document root via `$codegen-defaults` extension.
44///
45/// # Example
46///
47/// ```eure
48/// $codegen-defaults {
49///   derive = ["Debug", "Clone", "PartialEq"]
50///   ext-types-field-prefix = "ext_"
51///   ext-types-type-prefix = "Ext"
52///   document-node-id-field = "doc_node"
53/// }
54/// ```
55#[derive(Debug, Clone, Default, ParseDocument)]
56#[eure(crate = eure_document, rename_all = "kebab-case")]
57pub struct CodegenDefaults {
58    /// Default derive macros for all generated types.
59    #[eure(default)]
60    pub derive: Option<Vec<String>>,
61    /// Prefix for extension type field names (e.g., "ext_" -> ext_types).
62    #[eure(default)]
63    pub ext_types_field_prefix: Option<String>,
64    /// Prefix for extension type names (e.g., "Ext" -> ExtTypes).
65    #[eure(default)]
66    pub ext_types_type_prefix: Option<String>,
67    /// Field name for storing document node ID in generated types.
68    #[eure(default)]
69    pub document_node_id_field: Option<String>,
70}
71
72// ============================================================================
73// Type-Level Codegen Types
74// ============================================================================
75
76/// Codegen settings for union types.
77///
78/// Corresponds to `$types.union-codegen` in the schema.
79/// Used via `$ext-type.codegen` on union type definitions.
80/// Includes flattened fields from `$types.base-codegen`.
81///
82/// # Example
83///
84/// ```eure
85/// @ $types.my-union {
86///   $variant: union
87///   $codegen {
88///     type = "MyUnion"
89///     variant-types = true
90///     variant-types-suffix = "Variant"
91///   }
92///   variants.a = `text`
93///   variants.b = `integer`
94/// }
95/// ```
96#[derive(Debug, Clone, Default, ParseDocument)]
97#[eure(crate = eure_document, rename_all = "kebab-case")]
98pub struct UnionCodegen {
99    /// Override the generated type name (from base-codegen).
100    #[eure(rename = "type", default)]
101    pub type_name: Option<String>,
102    /// Override the list of derive macros (from base-codegen).
103    #[eure(default)]
104    pub derive: Option<Vec<String>>,
105    /// Generate separate types for each variant instead of struct-like variants.
106    #[eure(default)]
107    pub variant_types: Option<bool>,
108    /// Suffix for variant type names (e.g., "Type" -> TextType, IntegerType).
109    #[eure(default)]
110    pub variant_types_suffix: Option<String>,
111}
112
113/// Codegen settings for record types.
114///
115/// Corresponds to `$types.record-codegen` in the schema.
116/// Used via `$ext-type.codegen` on record type definitions.
117/// Includes flattened fields from `$types.base-codegen`.
118///
119/// For field-level codegen settings, use [`FieldCodegen`] via
120/// `value.$ext-type.codegen` on individual fields.
121///
122/// # Example
123///
124/// ```eure
125/// @ $types.user {
126///   $codegen {
127///     type = "User"
128///     derive = ["Debug", "Clone", "Serialize"]
129///   }
130///   name = `text`
131///   age = `integer`
132/// }
133/// ```
134#[derive(Debug, Clone, Default, ParseDocument)]
135#[eure(crate = eure_document)]
136pub struct RecordCodegen {
137    /// Override the generated type name (from base-codegen).
138    #[eure(rename = "type", default)]
139    pub type_name: Option<String>,
140    /// Override the list of derive macros (from base-codegen).
141    #[eure(default)]
142    pub derive: Option<Vec<String>>,
143}
144
145/// Codegen settings for individual record fields.
146///
147/// Corresponds to `$types.field-codegen` in the schema.
148/// Used via `value.$ext-type.codegen` on record field values.
149///
150/// # Example
151///
152/// ```eure
153/// @ $types.user {
154///   user-name = `text`
155///   user-name.$codegen.name = "username"  // Rename to `username` in Rust
156/// }
157/// ```
158#[derive(Debug, Clone, Default, ParseDocument)]
159#[eure(crate = eure_document)]
160pub struct FieldCodegen {
161    /// Override the field name in generated Rust code.
162    #[eure(default)]
163    pub name: Option<String>,
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169    use eure_document::document::node::NodeValue;
170    use eure_document::document::{EureDocument, NodeId};
171
172    fn create_empty_map_node(doc: &mut EureDocument) -> NodeId {
173        let root_id = doc.get_root_id();
174        doc.node_mut(root_id).content = NodeValue::Map(Default::default());
175        root_id
176    }
177
178    #[test]
179    fn test_root_codegen_empty() {
180        let mut doc = EureDocument::new();
181        let node_id = create_empty_map_node(&mut doc);
182
183        let result: RootCodegen = doc.parse(node_id).unwrap();
184        assert!(result.type_name.is_none());
185    }
186
187    #[test]
188    fn test_codegen_defaults_empty() {
189        let mut doc = EureDocument::new();
190        let node_id = create_empty_map_node(&mut doc);
191
192        let result: CodegenDefaults = doc.parse(node_id).unwrap();
193        assert!(result.derive.is_none());
194        assert!(result.ext_types_field_prefix.is_none());
195        assert!(result.ext_types_type_prefix.is_none());
196        assert!(result.document_node_id_field.is_none());
197    }
198
199    #[test]
200    fn test_union_codegen_empty() {
201        let mut doc = EureDocument::new();
202        let node_id = create_empty_map_node(&mut doc);
203
204        let result: UnionCodegen = doc.parse(node_id).unwrap();
205        assert!(result.type_name.is_none());
206        assert!(result.derive.is_none());
207        assert!(result.variant_types.is_none());
208        assert!(result.variant_types_suffix.is_none());
209    }
210
211    #[test]
212    fn test_record_codegen_empty() {
213        let mut doc = EureDocument::new();
214        let node_id = create_empty_map_node(&mut doc);
215
216        let result: RecordCodegen = doc.parse(node_id).unwrap();
217        assert!(result.type_name.is_none());
218        assert!(result.derive.is_none());
219    }
220
221    #[test]
222    fn test_field_codegen_empty() {
223        let mut doc = EureDocument::new();
224        let node_id = create_empty_map_node(&mut doc);
225
226        let result: FieldCodegen = doc.parse(node_id).unwrap();
227        assert!(result.name.is_none());
228    }
229}