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}