diff options
Diffstat (limited to '')
| -rw-r--r-- | askama_derive/src/generator.rs | 41 | 
1 files changed, 22 insertions, 19 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index e2c77f3..6cf518a 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -5,6 +5,8 @@ use shared::{filters, path};  use proc_macro2::Span; +use quote::ToTokens; +  use std::collections::{HashMap, HashSet};  use std::path::{Path, PathBuf};  use std::{cmp, hash, str}; @@ -25,7 +27,6 @@ struct Generator<'a> {      next_ws: Option<&'a str>,      skip_ws: bool,      vars: usize, -    inherited: usize,  }  impl<'a> Generator<'a> { @@ -45,7 +46,6 @@ impl<'a> Generator<'a> {              next_ws: None,              skip_ws: false,              vars: 0, -            inherited: 0,          }      } @@ -59,6 +59,8 @@ impl<'a> Generator<'a> {          let heritage = if !ctx.blocks.is_empty() {              if ctx.extends.is_some() && self.input.parent.is_none() {                  panic!("expected field '_parent' in extending template struct"); +            } else if let Some(parent) = self.input.parent { +                self.deref_to_parent(parent);              }              let heritage = Heritage::new(ctx, self.contexts);              self.trait_blocks(&heritage); @@ -91,7 +93,7 @@ impl<'a> Generator<'a> {          self.writeln("}");          self.write_header(&trait_name, None); -        for (level, ctx, def) in heritage.blocks.values() { +        for (ctx, def) in heritage.blocks.values() {              if let Node::BlockDef(ws1, name, nodes, ws2) = def {                  self.writeln("#[allow(unused_variables)]");                  self.writeln(&format!( @@ -101,7 +103,6 @@ impl<'a> Generator<'a> {                  ));                  self.prepare_ws(*ws1); -                self.inherited = heritage.levels - *level;                  self.locals.push();                  self.handle(ctx, nodes, AstLevel::Block);                  self.locals.pop(); @@ -114,8 +115,6 @@ impl<'a> Generator<'a> {              }          }          self.writeln("}"); - -        self.inherited = 0;      }      // Implement `Template` for the given context struct. @@ -127,9 +126,7 @@ impl<'a> Generator<'a> {          );          if let Some(heritage) = heritage { -            self.inherited = heritage.levels;              self.handle(heritage.root, heritage.root.nodes, AstLevel::Top); -            self.inherited = 0;          } else {              self.handle(ctx, &ctx.nodes, AstLevel::Top);          } @@ -140,6 +137,19 @@ impl<'a> Generator<'a> {          self.writeln("}");      } +    // Implement `Deref<Parent>` for an inheriting context struct. +    fn deref_to_parent(&mut self, parent_type: &syn::Type) { +        self.write_header("::std::ops::Deref", None); +        self.writeln(&format!( +            "type Target = {};", +            parent_type.into_token_stream() +        )); +        self.writeln("fn deref(&self) -> &Self::Target {"); +        self.writeln("&self._parent"); +        self.writeln("}"); +        self.writeln("}"); +    } +      // Implement `Display` for the given context struct.      fn impl_display(&mut self) {          self.write_header("::std::fmt::Display", None); @@ -743,9 +753,6 @@ impl<'a> Generator<'a> {              code.push_str(s);          } else {              code.push_str("self."); -            for _ in 0..self.inherited { -                code.push_str("_parent."); -            }              code.push_str(s);          }          DisplayWrap::Unwrapped @@ -883,8 +890,7 @@ where  struct Heritage<'a> {      root: &'a Context<'a>, -    levels: usize, -    blocks: HashMap<&'a str, (usize, &'a Context<'a>, &'a Node<'a>)>, +    blocks: HashMap<&'a str, (&'a Context<'a>, &'a Node<'a>)>,  }  impl<'a> Heritage<'a> { @@ -892,25 +898,22 @@ impl<'a> Heritage<'a> {          mut ctx: &'n Context<'n>,          contexts: &'n HashMap<&'n PathBuf, Context<'n>>,      ) -> Heritage<'n> { -        let mut levels = 0; -        let mut blocks: HashMap<_, (usize, _, _)> = ctx.blocks +        let mut blocks: HashMap<_, (_, _)> = ctx.blocks              .iter() -            .map(|(name, def)| (*name, (levels, ctx, *def))) +            .map(|(name, def)| (*name, (ctx, *def)))              .collect();          while let Some(ref path) = ctx.extends {              ctx = &contexts[&path]; -            levels += 1;              for (name, def) in &ctx.blocks {                  if !blocks.contains_key(name) { -                    blocks.insert(name, (levels, ctx, def)); +                    blocks.insert(name, (ctx, def));                  }              }          }          Heritage {              root: ctx, -            levels,              blocks,          }      }  | 
