diff options
Diffstat (limited to '')
| -rw-r--r-- | askama_derive/src/lib.rs | 154 | ||||
| -rw-r--r-- | askama_shared/src/generator.rs (renamed from askama_derive/src/generator.rs) | 39 | 
2 files changed, 38 insertions, 155 deletions
| diff --git a/askama_derive/src/lib.rs b/askama_derive/src/lib.rs index 0b64057..fcd857d 100644 --- a/askama_derive/src/lib.rs +++ b/askama_derive/src/lib.rs @@ -1,17 +1,13 @@  extern crate proc_macro; -#[macro_use] -extern crate quote; - -mod generator; +use askama_shared::heritage::{Context, Heritage};  use askama_shared::input::{Print, Source, TemplateInput}; -use askama_shared::parser::{parse, Expr, Macro, Node}; -use askama_shared::{read_config_file, Config}; +use askama_shared::parser::{parse, Expr, Node}; +use askama_shared::{generator, get_template_source, read_config_file, Config, Integrations};  use proc_macro::TokenStream;  use std::collections::HashMap; -use std::fs; -use std::path::{Path, PathBuf}; +use std::path::PathBuf;  #[proc_macro_derive(Template, attributes(template))]  pub fn derive_template(input: TokenStream) -> TokenStream { @@ -59,7 +55,7 @@ fn build_template(ast: &syn::DeriveInput) -> String {          eprintln!("{:?}", parsed[&input.path]);      } -    let code = generator::generate(&input, &contexts, &heritage); +    let code = generator::generate(&input, &contexts, &heritage, INTEGRATIONS);      if input.print == Print::Code || input.print == Print::All {          eprintln!("{}", code);      } @@ -88,136 +84,10 @@ fn find_used_templates(input: &TemplateInput, map: &mut HashMap<PathBuf, String>      }  } -pub(crate) struct Heritage<'a> { -    root: &'a Context<'a>, -    blocks: BlockAncestry<'a>, -} - -impl<'a> Heritage<'a> { -    fn new<'n>( -        mut ctx: &'n Context<'n>, -        contexts: &'n HashMap<&'n PathBuf, Context<'n>>, -    ) -> Heritage<'n> { -        let mut blocks: BlockAncestry<'n> = ctx -            .blocks -            .iter() -            .map(|(name, def)| (*name, vec![(ctx, *def)])) -            .collect(); - -        while let Some(ref path) = ctx.extends { -            ctx = &contexts[&path]; -            for (name, def) in &ctx.blocks { -                blocks -                    .entry(name) -                    .or_insert_with(|| vec![]) -                    .push((ctx, def)); -            } -        } - -        Heritage { root: ctx, blocks } -    } -} - -type BlockAncestry<'a> = HashMap<&'a str, Vec<(&'a Context<'a>, &'a Node<'a>)>>; - -pub(crate) struct Context<'a> { -    nodes: &'a [Node<'a>], -    extends: Option<PathBuf>, -    blocks: HashMap<&'a str, &'a Node<'a>>, -    macros: HashMap<&'a str, &'a Macro<'a>>, -    imports: HashMap<&'a str, PathBuf>, -} - -impl<'a> Context<'a> { -    fn new<'n>(config: &Config, path: &Path, nodes: &'n [Node<'n>]) -> Context<'n> { -        let mut extends = None; -        let mut blocks = Vec::new(); -        let mut macros = HashMap::new(); -        let mut imports = HashMap::new(); - -        for n in nodes { -            match n { -                Node::Extends(Expr::StrLit(extends_path)) => match extends { -                    Some(_) => panic!("multiple extend blocks found"), -                    None => { -                        extends = Some(config.find_template(extends_path, Some(path))); -                    } -                }, -                def @ Node::BlockDef(_, _, _, _) => { -                    blocks.push(def); -                } -                Node::Macro(name, m) => { -                    macros.insert(*name, m); -                } -                Node::Import(_, import_path, scope) => { -                    let path = config.find_template(import_path, Some(path)); -                    imports.insert(*scope, path); -                } -                _ => {} -            } -        } - -        let mut check_nested = 0; -        let mut nested_blocks = Vec::new(); -        while check_nested < blocks.len() { -            if let Node::BlockDef(_, _, ref nodes, _) = blocks[check_nested] { -                for n in nodes { -                    if let def @ Node::BlockDef(_, _, _, _) = n { -                        nested_blocks.push(def); -                    } -                } -            } else { -                panic!("non block found in list of blocks"); -            } -            blocks.append(&mut nested_blocks); -            check_nested += 1; -        } - -        let blocks: HashMap<_, _> = blocks -            .iter() -            .map(|def| { -                if let Node::BlockDef(_, name, _, _) = def { -                    (*name, *def) -                } else { -                    unreachable!() -                } -            }) -            .collect(); - -        Context { -            nodes, -            extends, -            blocks, -            macros, -            imports, -        } -    } -} - -#[allow(clippy::match_wild_err_arm)] -fn get_template_source(tpl_path: &Path) -> String { -    match fs::read_to_string(tpl_path) { -        Err(_) => panic!( -            "unable to open template file '{}'", -            tpl_path.to_str().unwrap() -        ), -        Ok(mut source) => { -            if source.ends_with('\n') { -                let _ = source.pop(); -            } -            source -        } -    } -} - -#[cfg(test)] -mod tests { -    use super::get_template_source; -    use crate::Config; - -    #[test] -    fn get_source() { -        let path = Config::new("").find_template("b.html", None); -        assert_eq!(get_template_source(&path), "bar"); -    } -} +const INTEGRATIONS: Integrations = Integrations { +    actix: cfg!(feature = "actix-web"), +    gotham: cfg!(feature = "gotham"), +    iron: cfg!(feature = "iron"), +    rocket: cfg!(feature = "rocket"), +    warp: cfg!(feature = "warp"), +}; diff --git a/askama_derive/src/generator.rs b/askama_shared/src/generator.rs index a12b1f0..3171c38 100644 --- a/askama_derive/src/generator.rs +++ b/askama_shared/src/generator.rs @@ -1,13 +1,14 @@ -use super::{get_template_source, Context, Heritage}; -use askama_shared::filters; -use askama_shared::input::{Source, TemplateInput}; -use askama_shared::parser::{ +use super::{get_template_source, Integrations}; +use crate::filters; +use crate::heritage::{Context, Heritage}; +use crate::input::{Source, TemplateInput}; +use crate::parser::{      parse, Cond, Expr, MatchParameter, MatchParameters, MatchVariant, Node, Target, When, WS,  };  use proc_macro2::Span; -use quote::ToTokens; +use quote::{quote, ToTokens};  use std::collections::{HashMap, HashSet};  use std::path::PathBuf; @@ -15,12 +16,14 @@ use std::{cmp, hash, mem, str};  use syn; -pub(crate) fn generate( +pub fn generate(      input: &TemplateInput,      contexts: &HashMap<&PathBuf, Context>,      heritage: &Option<Heritage>, +    integrations: Integrations,  ) -> String { -    Generator::new(input, contexts, heritage, SetChain::new()).build(&contexts[&input.path]) +    Generator::new(input, contexts, heritage, integrations, SetChain::new()) +        .build(&contexts[&input.path])  }  struct Generator<'a> { @@ -30,6 +33,8 @@ struct Generator<'a> {      contexts: &'a HashMap<&'a PathBuf, Context<'a>>,      // The heritage contains references to blocks and their ancestry      heritage: &'a Option<Heritage<'a>>, +    // What integrations need to be generated +    integrations: Integrations,      // Variables accessible directly from the current scope (not redirected to context)      locals: SetChain<'a, &'a str>,      // Suffix whitespace from the previous literal. Will be flushed to the @@ -52,12 +57,14 @@ impl<'a> Generator<'a> {          input: &'n TemplateInput,          contexts: &'n HashMap<&'n PathBuf, Context<'n>>,          heritage: &'n Option<Heritage>, +        integrations: Integrations,          locals: SetChain<'n, &'n str>,      ) -> Generator<'n> {          Generator {              input,              contexts,              heritage, +            integrations,              locals,              next_ws: None,              skip_ws: false, @@ -69,7 +76,13 @@ impl<'a> Generator<'a> {      fn child(&mut self) -> Generator {          let locals = SetChain::with_parent(&self.locals); -        Self::new(self.input, self.contexts, self.heritage, locals) +        Self::new( +            self.input, +            self.contexts, +            self.heritage, +            self.integrations, +            locals, +        )      }      // Takes a Context and generates the relevant implementations. @@ -83,19 +96,19 @@ impl<'a> Generator<'a> {          self.impl_template(ctx, &mut buf);          self.impl_display(&mut buf); -        if cfg!(feature = "iron") { +        if self.integrations.iron {              self.impl_modifier_response(&mut buf);          } -        if cfg!(feature = "rocket") { +        if self.integrations.rocket {              self.impl_rocket_responder(&mut buf);          } -        if cfg!(feature = "actix-web") { +        if self.integrations.actix {              self.impl_actix_web_responder(&mut buf);          } -        if cfg!(feature = "gotham") { +        if self.integrations.gotham {              self.impl_gotham_into_response(&mut buf);          } -        if cfg!(feature = "warp") { +        if self.integrations.warp {              self.impl_warp_reply(&mut buf);          }          buf.buf | 
