aboutsummaryrefslogtreecommitdiffstats
path: root/askama_derive/src/generator.rs
diff options
context:
space:
mode:
authorLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2018-06-22 16:03:37 +0200
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2018-06-22 16:13:08 +0200
commit21edd48917baf57728adf7fd7693741f84b85402 (patch)
treebccb0c2cc15d246d982f18b05a65452b7d45cc55 /askama_derive/src/generator.rs
parenta451bf29b607f7e47cd1e674a1adf490a2496af2 (diff)
downloadaskama-21edd48917baf57728adf7fd7693741f84b85402.tar.gz
askama-21edd48917baf57728adf7fd7693741f84b85402.tar.bz2
askama-21edd48917baf57728adf7fd7693741f84b85402.zip
Reinstate use of Deref for inherited variable access
Diffstat (limited to 'askama_derive/src/generator.rs')
-rw-r--r--askama_derive/src/generator.rs41
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,
}
}