spatialos_codegen/
resolver.rs

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}