1use std::collections::HashMap;
2
3use crate::ast::{
4 ASTNode, Component, DataType, Member, PackageNode, ResolvedTypeKind, SchemaFile, Type,
5 UserDefinedType, AST,
6};
7
8type Context = HashMap<String, (String, ResolvedTypeKind)>;
9
10fn register_type<S: AsRef<str>>(path: S, ty: &Type) -> Vec<(String, (String, ResolvedTypeKind))> {
11 let mut types = vec![(
12 ty.name.clone(),
13 (
14 path.as_ref().to_owned() + "::" + &ty.name,
15 ResolvedTypeKind::Type,
16 ),
17 )];
18 types.extend(
19 ty.types
20 .iter()
21 .map(|ty| register_type(path.as_ref(), ty))
22 .flatten(),
23 );
24 types.extend(ty.enums.iter().map(|en| {
25 (
26 en.name.to_owned(),
27 (
28 path.as_ref().to_string() + "::" + &en.name,
29 ResolvedTypeKind::Enum,
30 ),
31 )
32 }));
33 types
34}
35
36fn register_component<S: AsRef<str>>(
37 path: S,
38 comp: &Component,
39) -> Vec<(String, (String, ResolvedTypeKind))> {
40 let mut types = vec![(
41 comp.name.clone(),
42 (
43 path.as_ref().to_owned() + "::" + &comp.name,
44 ResolvedTypeKind::Component,
45 ),
46 )];
47 types.extend(
48 comp.types
49 .iter()
50 .map(|ty| register_type(path.as_ref(), ty))
51 .flatten(),
52 );
53 types.extend(comp.enums.iter().map(|en| {
54 (
55 en.name.to_owned(),
56 (
57 path.as_ref().to_string() + "::" + &en.name,
58 ResolvedTypeKind::Enum,
59 ),
60 )
61 }));
62 types
63}
64
65fn register_schemas<S: AsRef<str>>(
66 path: S,
67 schema: &SchemaFile,
68) -> Vec<(String, (String, ResolvedTypeKind))> {
69 let mut types = schema
70 .components
71 .iter()
72 .map(|comp| register_component(path.as_ref(), comp))
73 .flatten()
74 .collect::<Vec<_>>();
75 types.extend(
76 schema
77 .types
78 .iter()
79 .map(|ty| register_type(path.as_ref(), ty))
80 .flatten(),
81 );
82 types.extend(schema.enums.iter().map(|en| {
83 (
84 en.name.to_owned(),
85 (
86 path.as_ref().to_string() + "::" + &en.name,
87 ResolvedTypeKind::Enum,
88 ),
89 )
90 }));
91 types
92}
93
94fn register_node<S: AsRef<str>>(
95 path: S,
96 node: &ASTNode,
97) -> Vec<(String, (String, ResolvedTypeKind))> {
98 match node {
99 ASTNode::PackageNode(package) => package
100 .inner
101 .iter()
102 .map(|node| register_node(path.as_ref().to_owned() + "::" + &package.name, node))
103 .flatten()
104 .collect(),
105 ASTNode::SchemaNode(schema) => register_schemas(path.as_ref().to_string() + "::" + &schema.name, schema),
106 }
107}
108
109fn resolve_date_type(ctx: &Context, data_type: DataType) -> DataType {
110 match data_type {
111 DataType::UserDefined(UserDefinedType::Unresolved(unresolved)) => {
112 DataType::UserDefined(UserDefinedType::from(
113 ctx.get(&unresolved)
114 .unwrap_or_else(|| panic!("Unable to resolve: {}", unresolved)),
115 ))
116 }
117 DataType::Map(ty1, ty2) => DataType::Map(
118 Box::new(resolve_date_type(ctx, *ty1)),
119 Box::new(resolve_date_type(ctx, *ty2)),
120 ),
121 DataType::List(ty) => DataType::List(Box::new(resolve_date_type(ctx, *ty))),
122 DataType::Option(ty) => DataType::Option(Box::new(resolve_date_type(ctx, *ty))),
123 _ => data_type,
124 }
125}
126
127fn resolve_member(ctx: &Context, mut member: Member) -> Member {
128 member.m_type = resolve_date_type(ctx, member.m_type);
129 member
130}
131
132fn resolve_component(ctx: &Context, mut comp: Component) -> Component {
133 comp.members = comp
134 .members
135 .into_iter()
136 .map(|member| resolve_member(ctx, member))
137 .collect();
138 comp.types = comp
139 .types
140 .into_iter()
141 .map(|ty| resolve_type(ctx, ty))
142 .collect();
143 comp
144}
145
146fn resolve_type(ctx: &Context, mut ty: Type) -> Type {
147 ty.members = ty
148 .members
149 .into_iter()
150 .map(|member| resolve_member(ctx, member))
151 .collect();
152 ty.types = ty
153 .types
154 .into_iter()
155 .map(|ty| resolve_type(ctx, ty))
156 .collect();
157 ty
158}
159
160fn resolve_schema(ctx: &Context, mut schema: SchemaFile) -> SchemaFile {
161 schema.components = schema
162 .components
163 .into_iter()
164 .map(|component| resolve_component(ctx, component))
165 .collect();
166 schema.types = schema
167 .types
168 .into_iter()
169 .map(|t| resolve_type(ctx, t))
170 .collect();
171 schema
172}
173
174fn resolve_package(ctx: &Context, mut package: PackageNode) -> PackageNode {
175 package.inner = package
176 .inner
177 .into_iter()
178 .map(|n| resolve_node(ctx, n))
179 .collect();
180 package
181}
182
183fn resolve_node(ctx: &Context, node: ASTNode) -> ASTNode {
184 match node {
185 ASTNode::PackageNode(package) => ASTNode::PackageNode(resolve_package(ctx, package)),
186 ASTNode::SchemaNode(schema) => ASTNode::SchemaNode(resolve_schema(ctx, schema)),
187 }
188}
189
190pub fn resolve_types<S: AsRef<str>>(mut ast: AST, module: S) -> AST {
191 let ctx = ast
192 .inner
193 .iter()
194 .map(|node| register_node("crate::".to_string() + module.as_ref() , node))
195 .flatten()
196 .collect::<HashMap<_, _>>();
197
198 ast.inner = ast
199 .inner
200 .into_iter()
201 .map(|node| resolve_node(&ctx, node))
202 .collect();
203 ast
204}