aboutsummaryrefslogtreecommitdiffstats
path: root/askama_derive/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--askama_derive/src/lib.rs154
-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