1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate nom;
extern crate quote;
extern crate syn;
#[cfg(feature = "serde-json")]
extern crate serde;
#[cfg(feature = "serde-json")]
extern crate serde_json;
pub use escaping::MarkupDisplay;
pub use errors::{Error, Result};
pub mod filters;
pub mod path;
mod escaping;
mod generator;
mod input;
mod parser;
use input::Print;
use parser::{Node, Macro};
use std::borrow::Cow;
use std::collections::HashMap;
use std::path::Path;
/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
pub fn build_template(ast: &syn::DeriveInput) -> String {
let data = input::TemplateInput::new(ast);
let nodes = parser::parse(data.source.as_ref());
let imports = Imports::new(&nodes, &data.path);
if data.meta.print == Print::Ast || data.meta.print == Print::All {
println!("{:?}", nodes);
}
let code = generator::generate(&data, &nodes, &imports.macro_map());
if data.meta.print == Print::Code || data.meta.print == Print::All {
println!("{}", code);
}
code
}
pub struct Imports<'a> {
pub sources: Vec<Cow<'a, str>>
}
impl <'a> Imports<'a> {
pub fn new(parent_nodes: &'a [Node], parent_path: &'a Path) -> Imports<'a> {
let sources = parent_nodes.iter().filter_map(|n| {
match *n {
Node::Import(_, ref import_path) => {
let path = path::find_template_from_path(import_path, Some(parent_path));
let src = path::get_template_source(&path);
Some(Cow::Owned(src))
},
_ => None,
}
}).collect();
Imports { sources }
}
pub fn parse(&'a self) -> HashMap<&'a str, Macro<'a>> {
self.sources.iter()
.flat_map(|s| parser::parse(s.as_ref()))
.filter_map(|n| {
match n {
Node::Macro(name, m) => Some((name, m)),
_ => None,
}})
.collect()
}
}
mod errors {
error_chain! {
foreign_links {
Fmt(::std::fmt::Error);
Json(::serde_json::Error) #[cfg(feature = "serde-json")];
}
}
}
|