spatialos_codegen/ast/
root.rs1use crate::ast::SchemaFile;
2use crate::{ast::ASTNode, resolver::resolve_types};
3use std::convert::TryFrom;
4use std::ffi::OsStr;
5use std::path::Path;
6use std::path::PathBuf;
7use walkdir::WalkDir;
8
9#[derive(Debug, Eq, PartialEq, Default)]
10pub struct ASTBuilder {
11 directories: Vec<PathBuf>,
12}
13
14#[allow(dead_code)]
15impl ASTBuilder {
16 pub fn build(self) -> AST {
17 self.directories
18 .into_iter()
19 .map(|d| {
20 WalkDir::new(&d)
21 .follow_links(true)
22 .into_iter()
23 .filter_map(|e| e.ok())
24 .map(|e| {
25 e.path()
26 .to_str()
27 .map(|s| s.to_string())
28 .ok_or("Can't tranform into &str")
29 })
30 .filter_map(Result::ok)
31 .map(PathBuf::from)
32 .filter(|p| p.extension() == Some(OsStr::new("schema")))
33 .map(|p| (SchemaFile::try_from(p.clone()), p))
34 .map(|(schemas, buf)| match schemas {
35 Ok(data) => Ok(data),
36 Err(e) => {
37 eprintln!("{}: {:?}", e, buf);
38 Err(())
39 }
40 })
41 .filter_map(Result::ok)
42 .collect::<Vec<_>>()
43 })
44 .flatten()
45 .fold(AST::default(), |acc, val| {
46 acc.merge_schema(&val, &val.package_name)
47 })
48 }
49
50 pub fn with_directory<P: AsRef<Path>>(mut self, path: P) -> Self {
51 let path = path.as_ref().to_path_buf();
52 self.directories.push(path);
53 self
54 }
55}
56
57#[derive(Debug, Eq, PartialEq, Default)]
58pub struct AST {
59 pub inner: Vec<ASTNode>,
60}
61
62impl AST {
63 pub fn generate<P: AsRef<Path> + Clone, S: AsRef<str>>(self, path: P, module: S) -> Result<(), std::io::Error> {
64 let new_ast = resolve_types(self, module);
65 let path_clone = path.clone();
66 if path_clone.as_ref().exists() {
67 std::fs::remove_dir_all(path)?;
68 }
69 for node in &new_ast.inner {
70 node.generate_node(path_clone.clone())?;
71 }
72 ASTNode::generate_mod_rs(&new_ast.inner, path_clone)
73 }
74
75 fn merge_schema<T: AsRef<str>>(self, schema: &SchemaFile, path: &[T]) -> Self {
76 if !path.is_empty() {
77 let is_path_present = self
78 .inner
79 .iter()
80 .map(|n| match n {
81 ASTNode::SchemaNode(_) => panic!("SchemaFile shouldn't be at the root of AST"),
82 ASTNode::PackageNode(pn) => pn.name == *path[0].as_ref(),
83 })
84 .fold(false, |acc, val| acc | val);
85 if is_path_present {
86 AST {
87 inner: self
88 .inner
89 .into_iter()
90 .map(|n| n.merge_schema(schema, path))
91 .collect::<Vec<ASTNode>>(),
92 }
93 } else {
94 let mut inner = self.inner;
95 inner.push(ASTNode::package_schema(schema, path));
96 AST { inner }
97 }
98 } else {
99 panic!("SchemaFile does not have a package name");
100 }
101 }
102}