wearte_derive/
lib.rs

1//!
2//! `wearte_derive` is the core of the crate, and where the procedural macro `derive(Tempalte)` is
3//! implemented. `wearte_derive` will have as input a template file and the definition of the struct
4//! that goes together. With this, wearte will parse the file and the struct to create an **ast**,
5//! and will provide the user's struct the functionality of `fmt` for the template.
6//! Derivation is implements `fmt::Display`, superTrait of `Template`, and if activated,
7//! `actix_web::Responder` will be implemented on the user's struct.
8//! `Template` is defined in the main wearte crate and implements `fmt` in functions like
9//! `call`, `call_into_fmt`, `call_into_io`, `mime `, and `size_hint `.
10//!
11extern crate proc_macro;
12
13#[macro_use]
14extern crate nom;
15#[macro_use]
16extern crate quote;
17
18mod generator;
19mod logger;
20mod parser;
21
22use proc_macro::TokenStream;
23use syn;
24
25use std::collections::BTreeMap;
26
27use wearte_config::{read_config_file, Config};
28
29use crate::generator::{visit_derive, Print};
30use crate::logger::log;
31use crate::parser::{parse, parse_partials, Node};
32use wearte_config::PrintConfig;
33
34#[proc_macro_derive(Template, attributes(template))]
35pub fn derive(input: TokenStream) -> TokenStream {
36    build(&syn::parse(input).unwrap())
37}
38
39#[inline]
40fn build(i: &syn::DeriveInput) -> TokenStream {
41    let config_toml: &str = &read_config_file();
42    let config = &Config::new(config_toml);
43
44    let s = visit_derive(i, &config);
45
46    let mut sources = BTreeMap::new();
47
48    let mut check = vec![(s.path.clone(), s.src.clone())];
49    while let Some((path, src)) = check.pop() {
50        for n in &parse_partials(&src) {
51            match n {
52                Node::Partial(_, partial, _) => {
53                    check.push(config.get_partial(&path, partial));
54                }
55                _ => unreachable!(),
56            }
57        }
58        sources.insert(path, src);
59    }
60
61    let mut parsed = BTreeMap::new();
62    for (p, src) in &sources {
63        parsed.insert(p, parse(src));
64    }
65
66    if config.print_override == PrintConfig::Ast
67        || config.print_override == PrintConfig::All
68        || s.print == Print::Ast
69        || s.print == Print::All
70    {
71        eprintln!("{:?}\n", parsed);
72    }
73
74    let code = generator::generate(&config, &s, &parsed);
75    if config.print_override == PrintConfig::Code
76        || config.print_override == PrintConfig::All
77        || s.print == Print::Code
78        || s.print == Print::All
79    {
80        log(&code, s.path.to_str().unwrap().to_owned(), &config.debug);
81    }
82
83    code.parse().unwrap()
84}