xsd_parser/optimizer/
resolve_typedefs.rs1use std::collections::HashMap;
2
3use crate::types::{Base, TypeVariant};
4
5use super::{get_typedefs, Optimizer};
6
7impl Optimizer {
8 #[doc = include_str!("../../tests/optimizer/complex_flatten.xsd")]
16 #[doc = include_str!("../../tests/optimizer/expected0/resolve_typedefs.rs")]
21 #[doc = include_str!("../../tests/optimizer/expected1/resolve_typedefs.rs")]
26 pub fn resolve_typedefs(mut self) -> Self {
28 tracing::debug!("resolve_typedefs");
29
30 let typedefs = get_typedefs!(self);
31
32 macro_rules! resolve_base {
33 ($base:expr) => {
34 match &mut $base {
35 Base::None => (),
36 Base::Extension(x) => *x = typedefs.resolve(x).clone(),
37 Base::Restriction(x) => *x = typedefs.resolve(x).clone(),
38 }
39 };
40 }
41
42 let mut replaced_references = HashMap::new();
43
44 for type_ in self.types.values_mut() {
45 match &mut type_.variant {
46 TypeVariant::Reference(x) if x.is_single() => {
47 let new_type = typedefs.resolve(&x.type_).clone();
48 replaced_references
49 .entry(x.type_.clone())
50 .or_insert_with(|| new_type.clone());
51 x.type_ = new_type;
52 }
53 TypeVariant::Union(x) => {
54 resolve_base!(&mut x.base);
55
56 for x in &mut *x.types {
57 x.type_ = typedefs.resolve(&x.type_).clone();
58 }
59 }
60 TypeVariant::Dynamic(x) => {
61 x.type_ = x.type_.as_ref().map(|x| typedefs.resolve(x)).cloned();
62
63 for x in &mut x.derived_types {
64 *x = typedefs.resolve(x).clone();
65 }
66 }
67 TypeVariant::Enumeration(x) => {
68 resolve_base!(&mut x.base);
69
70 for x in &mut *x.variants {
71 if let Some(x) = &mut x.type_ {
72 *x = typedefs.resolve(x).clone();
73 }
74 }
75 }
76 TypeVariant::ComplexType(x) => {
77 resolve_base!(&mut x.base);
78
79 if let Some(ident) = &mut x.content {
80 *ident = typedefs.resolve(ident).clone();
81 }
82
83 for attrib in &mut *x.attributes {
84 attrib.type_ = typedefs.resolve(&attrib.type_).clone();
85 }
86 }
87 TypeVariant::All(x) | TypeVariant::Choice(x) | TypeVariant::Sequence(x) => {
88 for element in &mut *x.elements {
89 element.type_ = typedefs.resolve(&element.type_).clone();
90 }
91 }
92 _ => (),
93 }
94 }
95
96 for type_ in self.types.values_mut() {
97 let TypeVariant::Dynamic(di) = &mut type_.variant else {
98 continue;
99 };
100
101 for derived in &mut di.derived_types {
102 if let Some(new_type) = replaced_references.get(derived) {
103 *derived = new_type.clone();
104 }
105 }
106 }
107
108 self
109 }
110}