xsd_parser/generator/
mod.rs

1//! The `generator` module contains the code [`Generator`] and all related types.
2
3pub mod renderer;
4
5mod context;
6mod data;
7mod error;
8mod helper;
9mod misc;
10
11use std::collections::{BTreeMap, HashSet, VecDeque};
12use std::fmt::Display;
13use std::str::FromStr;
14
15use proc_macro2::{Ident as Ident2, TokenStream};
16use quote::{format_ident, ToTokens};
17use renderer::{Renderer, TypesRenderer};
18use smallvec::{smallvec, SmallVec};
19use tracing::instrument;
20
21use crate::code::{format_module_ident, format_type_ident, IdentPath, Module};
22use crate::schema::{MaxOccurs, NamespaceId};
23use crate::types::{Ident, IdentType, Name, Type, TypeVariant, Types};
24
25pub use self::context::Context;
26pub use self::data::{
27    BuildInType, ComplexType, ComplexTypeAttribute, ComplexTypeBase, ComplexTypeContent,
28    ComplexTypeElement, ComplexTypeEnum, ComplexTypeStruct, DerivedType, DynamicType,
29    EnumerationType, EnumerationTypeVariant, ReferenceType, StructMode, TypeData, UnionType,
30    UnionTypeVariant,
31};
32pub use self::error::Error;
33pub use self::misc::{BoxFlags, GeneratorFlags, SerdeSupport, TypedefMode};
34
35use self::helper::Walk;
36use self::misc::{DynTypeTraits, PendingType, TraitInfos, TypeRef};
37
38/// Type that is used to generate rust code from a [`Types`] object.
39#[must_use]
40#[derive(Debug)]
41pub struct Generator<'types> {
42    config: Config<'types>,
43    state: State<'types>,
44    renderers: Vec<Box<dyn Renderer>>,
45}
46
47/// Type that is used to generate rust code from a [`Types`] object.
48///
49/// In contrast to [`Generator`] this type does not allow changes to the
50/// configuration of the generator, because at least one type was already
51/// generated.
52#[must_use]
53#[derive(Debug)]
54pub struct GeneratorFixed<'types> {
55    config: Config<'types>,
56    state: State<'types>,
57    module: Module,
58    renderers: Vec<Box<dyn Renderer>>,
59}
60
61/// Contains the configuration of the generator.
62#[derive(Debug)]
63pub struct Config<'types> {
64    /// Reference to the types the code should be generated for.
65    pub types: &'types Types,
66
67    /// Flags that controls the behavior of the generator.
68    pub flags: GeneratorFlags,
69
70    /// Traits the generator should derive the generated types from.
71    pub derive: Vec<Ident2>,
72
73    /// List of postfixed to add to the name of the generated types.
74    ///
75    /// This corresponds to the variants of [`IdentType`].
76    pub postfixes: [String; 8],
77
78    /// Tells the generator how to deal with boxed elements.
79    pub box_flags: BoxFlags,
80
81    /// Tells the generator how to deal with type definitions.
82    pub typedef_mode: TypedefMode,
83
84    /// Tells the generator if and how to generate code to support [`serde`].
85    pub serde_support: SerdeSupport,
86
87    /// List of traits that should be implemented by dynamic types.
88    pub dyn_type_traits: DynTypeTraits,
89
90    /// Name of the `xsd_parser` crate.
91    pub xsd_parser_crate: Ident2,
92}
93
94#[derive(Debug)]
95struct State<'types> {
96    cache: BTreeMap<Ident, TypeRef>,
97    trait_infos: Option<TraitInfos>,
98    pending: VecDeque<PendingType<'types>>,
99}
100
101/* Generator */
102
103impl<'types> Generator<'types> {
104    /// Create a new code generator from the passed `types`.
105    pub fn new(types: &'types Types) -> Self {
106        let config = Config {
107            types,
108            flags: GeneratorFlags::empty(),
109            derive: vec![format_ident!("Debug")],
110            postfixes: [
111                String::from("Type"),        // Type = 0
112                String::new(),               // Group = 1
113                String::from("ElementType"), // Element = 2
114                String::new(),               // ElementType = 3
115                String::new(),               // Attribute = 4
116                String::new(),               // AttributeGroup = 5
117                String::new(),               // BuildIn = 6
118                String::new(),               // Enumeration = 7
119            ],
120            box_flags: BoxFlags::AUTO,
121            typedef_mode: TypedefMode::Auto,
122            serde_support: SerdeSupport::None,
123            dyn_type_traits: DynTypeTraits::Auto,
124            xsd_parser_crate: format_ident!("xsd_parser"),
125        };
126        let state = State {
127            cache: BTreeMap::new(),
128            trait_infos: None,
129            pending: VecDeque::new(),
130        };
131        let renderers = Vec::new();
132
133        Self {
134            config,
135            state,
136            renderers,
137        }
138    }
139
140    /// Set the name of the `xsd-parser` create that the generator should use for
141    /// generating the code.
142    pub fn xsd_parser_crate<S: Display>(mut self, value: S) -> Self {
143        self.config.xsd_parser_crate = format_ident!("{value}");
144
145        self
146    }
147
148    /// Set the traits the generated types should derive from.
149    ///
150    /// Default is `Debug` and `Clone`.
151    ///
152    /// # Examples
153    ///
154    /// ```ignore
155    /// let generator = Generator::new(types)
156    ///     .derive(["Debug", "Clone", "Eq", "PartialEq", "Ord", "PartialOrd"]);
157    /// ```
158    pub fn derive<I>(mut self, value: I) -> Self
159    where
160        I: IntoIterator,
161        I::Item: Display,
162    {
163        self.config.derive = value.into_iter().map(|x| format_ident!("{x}")).collect();
164
165        self
166    }
167
168    /// Set the traits that should be implemented by dynamic types.
169    ///
170    /// The passed values must be valid type paths.
171    ///
172    /// # Errors
173    ///
174    /// Will raise a [`InvalidIdentifier`](Error::InvalidIdentifier) error
175    /// if the passed strings does not represent a valid identifier.
176    ///
177    /// # Examples
178    ///
179    /// ```ignore
180    /// let generator = Generator::new(types)
181    ///     .dyn_type_traits(["core::fmt::Debug", "core::any::Any"]);
182    /// ```
183    pub fn dyn_type_traits<I>(mut self, value: I) -> Result<Self, Error>
184    where
185        I: IntoIterator,
186        I::Item: AsRef<str>,
187    {
188        let traits = value
189            .into_iter()
190            .map(|x| {
191                let s = x.as_ref();
192                IdentPath::from_str(s).map_err(|()| Error::InvalidIdentifier(s.into()))
193            })
194            .collect::<Result<Vec<_>, _>>()?;
195
196        self.config.dyn_type_traits = DynTypeTraits::Custom(traits);
197
198        Ok(self)
199    }
200
201    /// Set the [`BoxFlags`] flags the generator should use for generating the code.
202    pub fn box_flags(mut self, value: BoxFlags) -> Self {
203        self.config.box_flags = value;
204
205        self
206    }
207
208    /// Set the [`TypedefMode`] value the generator should use for generating the code.
209    pub fn typedef_mode(mut self, value: TypedefMode) -> Self {
210        self.config.typedef_mode = value;
211
212        self
213    }
214
215    /// Set the [`SerdeSupport`] value the generator should use for generating the code.
216    pub fn serde_support(mut self, value: SerdeSupport) -> Self {
217        self.config.serde_support = value;
218
219        self
220    }
221
222    /// Set the [`GeneratorFlags`] flags the generator should use for generating the code.
223    pub fn flags(mut self, value: GeneratorFlags) -> Self {
224        self.config.flags = value;
225
226        self
227    }
228
229    /// Add the passed [`GeneratorFlags`] flags the generator should use for generating the code.
230    pub fn with_flags(mut self, value: GeneratorFlags) -> Self {
231        self.config.flags |= value;
232
233        self
234    }
235
236    /// Set the postfixes the generator should use for the different types.
237    ///
238    /// Default is `"Type"` for the [`IdentType::Type`] type and `""` for the other types.
239    pub fn with_type_postfix<S: Into<String>>(mut self, type_: IdentType, postfix: S) -> Self {
240        self.config.postfixes[type_ as usize] = postfix.into();
241
242        self
243    }
244
245    /// Add a custom implemented type to the generator.
246    ///
247    /// This will add a custom implemented type to the generator. These types are
248    /// usually implemented and provided by the user of the generated code. The
249    /// generator will just reference to the type definition and will not generate
250    /// any code related to this type.
251    ///
252    /// # Errors
253    ///
254    /// Returns an error if the namespace of the passed identifier is unknown.
255    ///
256    /// # Examples
257    ///
258    /// ```ignore
259    /// let generator = Generator::new(types)
260    ///     .with_type(Ident::type_("UserDefinedType"));
261    /// ```
262    pub fn with_type(mut self, ident: Ident) -> Result<Self, Error> {
263        let module_ident = format_module(self.config.types, ident.ns)?;
264        let type_ident = format_ident!("{}", ident.name.to_string());
265
266        let type_ref = TypeRef {
267            ident: ident.clone(),
268            module_ident,
269            type_ident,
270            boxed_elements: HashSet::new(),
271        };
272        self.state.cache.insert(ident, type_ref);
273
274        Ok(self)
275    }
276
277    /// Add a [`Renderer`] to the generator.
278    pub fn with_renderer<X>(mut self, renderer: X) -> Self
279    where
280        X: Renderer + 'static,
281    {
282        self.renderers.push(Box::new(renderer));
283
284        self
285    }
286
287    /// Add the default renderers to the generator.
288    pub fn with_default_renderers(self) -> Self {
289        self.with_renderer(TypesRenderer)
290    }
291
292    /// Remove all [`Renderer`]s from the generator.
293    pub fn clear_renderers(mut self) -> Self {
294        self.renderers.clear();
295
296        self
297    }
298
299    /// Will fix the generator by call [`into_fixed`](Self::into_fixed) and then
300    /// [`generate_type`](GeneratorFixed::generate_type).
301    #[instrument(err, level = "trace", skip(self))]
302    pub fn generate_type(self, ident: Ident) -> Result<GeneratorFixed<'types>, Error> {
303        self.into_fixed().generate_type(ident)
304    }
305
306    /// Will fix the generator by call [`into_fixed`](Self::into_fixed) and then
307    /// [`generate_all_types`](GeneratorFixed::generate_all_types).
308    ///
309    /// # Errors
310    ///
311    /// Will just forward the errors from [`generate_all_types`](GeneratorFixed::generate_all_types).
312    pub fn generate_all_types(self) -> Result<GeneratorFixed<'types>, Error> {
313        self.into_fixed().generate_all_types()
314    }
315
316    /// Will convert the generator into a [`GeneratorFixed`].
317    pub fn into_fixed(self) -> GeneratorFixed<'types> {
318        let Self {
319            mut config,
320            state,
321            mut renderers,
322        } = self;
323        let module = Module::default();
324
325        config.dyn_type_traits = match config.dyn_type_traits {
326            DynTypeTraits::Auto => {
327                let traits = config.derive.iter().map(|x| match x.to_string().as_ref() {
328                    "Debug" => IdentPath::from_str("core::fmt::Debug").unwrap(),
329                    "Hash" => IdentPath::from_str("core::hash::Hash").unwrap(),
330                    _ => IdentPath::from_ident(x.clone()),
331                });
332
333                let serde: SmallVec<[IdentPath; 2]> = if config.serde_support == SerdeSupport::None
334                {
335                    smallvec![]
336                } else {
337                    smallvec![
338                        IdentPath::from_str("serde::Serialize").unwrap(),
339                        IdentPath::from_str("serde::de::DeserializeOwned").unwrap()
340                    ]
341                };
342
343                let as_any = IdentPath::from_parts(
344                    Some(config.xsd_parser_crate.clone()),
345                    format_ident!("AsAny"),
346                );
347
348                DynTypeTraits::Custom(traits.chain(serde).chain(Some(as_any)).collect())
349            }
350            x => x,
351        };
352
353        for renderer in &mut renderers {
354            renderer.initialize(&mut config);
355        }
356
357        GeneratorFixed {
358            config,
359            state,
360            module,
361            renderers,
362        }
363    }
364}
365
366impl<'types> GeneratorFixed<'types> {
367    /// Generate the code for the given type.
368    ///
369    /// This will generate the code for the passed type identifier and all
370    /// dependencies of this type.
371    ///
372    /// # Examples
373    ///
374    /// ```ignore
375    /// let generator = Generator::new(types)
376    ///     .generate_type(Ident::type_("Root"));
377    /// ```
378    #[instrument(err, level = "trace", skip(self))]
379    pub fn generate_type(mut self, ident: Ident) -> Result<GeneratorFixed<'types>, Error> {
380        self.state.get_or_create_type_ref(&self.config, ident)?;
381        self.generate_pending()?;
382
383        Ok(self)
384    }
385
386    /// Generate the code for all types.
387    ///
388    /// This will generate the code for all types that are specified in
389    /// the [`Types`] object passed to the generator.
390    ///
391    /// # Examples
392    ///
393    /// ```ignore
394    /// let generator = Generator::new(types)
395    ///     .generate_all_types();
396    /// ```
397    #[instrument(err, level = "trace", skip(self))]
398    pub fn generate_all_types(mut self) -> Result<Self, Error> {
399        for ident in self.config.types.keys() {
400            self.state
401                .get_or_create_type_ref(&self.config, ident.clone())?;
402        }
403        self.generate_pending()?;
404
405        Ok(self)
406    }
407
408    /// Generate the code for all named types.
409    ///
410    /// This will generate the code for all types with an explicit name and all
411    /// dependencies of these types that are specified in the [`Types`] object
412    /// passed to the generator.
413    ///
414    /// # Examples
415    ///
416    /// ```ignore
417    /// let generator = Generator::new(types)
418    ///     .generate_named_types();
419    /// ```
420    #[instrument(err, level = "trace", skip(self))]
421    pub fn generate_named_types(mut self) -> Result<Self, Error> {
422        for ident in self.config.types.keys() {
423            if ident.name.is_named() {
424                self.state
425                    .get_or_create_type_ref(&self.config, ident.clone())?;
426            }
427        }
428        self.generate_pending()?;
429
430        Ok(self)
431    }
432
433    /// Finish the code generation.
434    ///
435    /// This will return the generated code as [`TokenStream`].
436    #[instrument(level = "trace", skip(self))]
437    pub fn finish(self) -> TokenStream {
438        self.into_module().to_token_stream()
439    }
440
441    /// Finish the code generation and return the generated [`Module`] structure.
442    #[instrument(level = "trace", skip(self))]
443    pub fn into_module(self) -> Module {
444        let Self {
445            config,
446            mut module,
447            state: _,
448            mut renderers,
449        } = self;
450
451        for renderer in &mut renderers {
452            renderer.finish(&config, &mut module);
453        }
454
455        module
456    }
457
458    #[instrument(err, level = "trace", skip(self))]
459    fn generate_pending(&mut self) -> Result<(), Error> {
460        while let Some(args) = self.state.pending.pop_front() {
461            self.generate_type_intern(args)?;
462        }
463
464        Ok(())
465    }
466
467    #[instrument(err, level = "trace", skip(self))]
468    fn generate_type_intern(&mut self, data: PendingType<'types>) -> Result<(), Error> {
469        let PendingType { ty, ident } = data;
470        let Self {
471            config,
472            state,
473            module,
474            renderers,
475        } = self;
476        let ty = TypeData::new(ty, &ident, config, state)?;
477        let mut ctx = Context::new(&ident, config, module);
478
479        tracing::debug!("Render type: {ident}");
480
481        for renderer in renderers {
482            renderer.render_type(&mut ctx, &ty);
483        }
484
485        Ok(())
486    }
487}
488
489impl Config<'_> {
490    fn check_flags(&self, flags: GeneratorFlags) -> bool {
491        self.flags.intersects(flags)
492    }
493}
494
495impl<'types> State<'types> {
496    #[instrument(level = "trace", skip(self, config))]
497    fn get_or_create_type_ref(
498        &mut self,
499        config: &Config<'types>,
500        ident: Ident,
501    ) -> Result<&TypeRef, Error> {
502        if !self.cache.contains_key(&ident) {
503            let ty = config
504                .types
505                .get(&ident)
506                .ok_or_else(|| Error::UnknownType(ident.clone()))?;
507            let name = make_type_name(&config.postfixes, ty, &ident);
508            let (module_ident, type_ident) = if let TypeVariant::BuildIn(x) = &ty.variant {
509                (None, format_ident!("{x}"))
510            } else {
511                let use_modules = config.flags.intersects(GeneratorFlags::USE_MODULES);
512                let module_ident =
513                    format_module(config.types, use_modules.then_some(ident.ns).flatten())?;
514                let type_ident = format_type_ident(&name, ty.display_name.as_deref());
515
516                (module_ident, type_ident)
517            };
518
519            tracing::debug!("Queue new type generation: {ident}");
520
521            let boxed_elements = get_boxed_elements(&ident, ty, config.types, &self.cache);
522            self.pending.push_back(PendingType {
523                ty,
524                ident: ident.clone(),
525            });
526
527            let type_ref = TypeRef {
528                ident: ident.clone(),
529                type_ident,
530                module_ident,
531                boxed_elements,
532            };
533
534            assert!(self.cache.insert(ident.clone(), type_ref).is_none());
535        }
536
537        Ok(self.cache.get_mut(&ident).unwrap())
538    }
539}
540
541/* Helper */
542
543fn get_boxed_elements<'a>(
544    ident: &Ident,
545    mut ty: &'a Type,
546    types: &'a Types,
547    cache: &BTreeMap<Ident, TypeRef>,
548) -> HashSet<Ident> {
549    if let TypeVariant::ComplexType(ci) = &ty.variant {
550        if let Some(type_) = ci.content.as_ref().and_then(|ident| types.get(ident)) {
551            ty = type_;
552        }
553    }
554
555    match &ty.variant {
556        TypeVariant::All(si) | TypeVariant::Choice(si) | TypeVariant::Sequence(si) => si
557            .elements
558            .iter()
559            .filter_map(|f| {
560                if Walk::new(types, cache).is_loop(ident, &f.type_) {
561                    Some(f.ident.clone())
562                } else {
563                    None
564                }
565            })
566            .collect(),
567        _ => HashSet::new(),
568    }
569}
570
571fn make_type_name(postfixes: &[String], ty: &Type, ident: &Ident) -> Name {
572    if let TypeVariant::Reference(ti) = &ty.variant {
573        if ident.name.is_generated() && ti.type_.name.is_named() {
574            let s = ti.type_.name.to_type_name();
575
576            if ti.max_occurs > MaxOccurs::Bounded(1) {
577                return Name::new_generated(format!("{s}List"));
578            } else if ti.min_occurs == 0 {
579                return Name::new_generated(format!("{s}Opt"));
580            }
581        }
582    }
583
584    let postfix = postfixes
585        .get(ident.type_ as usize)
586        .map_or("", |s| s.as_str());
587
588    let s = ident.name.to_type_name();
589
590    if s.ends_with(postfix) {
591        ident.name.clone()
592    } else {
593        Name::new_generated(format!("{s}{postfix}"))
594    }
595}
596
597fn format_module(types: &Types, ns: Option<NamespaceId>) -> Result<Option<Ident2>, Error> {
598    let Some(ns) = ns else {
599        return Ok(None);
600    };
601
602    let module = types.modules.get(&ns).ok_or(Error::UnknownNamespace(ns))?;
603    let Some(name) = &module.name else {
604        return Ok(None);
605    };
606
607    Ok(Some(format_module_ident(name)))
608}