aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2017-02-12 20:38:14 +0100
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2017-02-12 20:38:14 +0100
commitc74e9e8971c06ed77eeee79cbac2c4c325b3ffa4 (patch)
tree3bf410232558d989379681f4593a717118e6bebd
parent7b831bd79fd1a1b3f6149420b34df1a19644554c (diff)
downloadaskama-c74e9e8971c06ed77eeee79cbac2c4c325b3ffa4.tar.gz
askama-c74e9e8971c06ed77eeee79cbac2c4c325b3ffa4.tar.bz2
askama-c74e9e8971c06ed77eeee79cbac2c4c325b3ffa4.zip
Explicitly pass trait implementation to top-level base template method
This requires a base template struct to be a member of the derived template's context, but allows the base template to access base template fields.
-rw-r--r--askama/src/generator.rs45
-rw-r--r--testing/tests/inheritance.rs6
2 files changed, 33 insertions, 18 deletions
diff --git a/askama/src/generator.rs b/askama/src/generator.rs
index c8d9ce4..66a266c 100644
--- a/askama/src/generator.rs
+++ b/askama/src/generator.rs
@@ -219,7 +219,7 @@ impl<'a> Generator<'a> {
fn write_block(&mut self, ws1: &WS, name: &str, ws2: &WS) {
self.flush_ws(ws1);
- self.writeln(&format!("self.render_block_{}_to(writer);", name));
+ self.writeln(&format!("timpl.render_block_{}_to(writer);", name));
self.prepare_ws(ws2);
}
@@ -271,12 +271,27 @@ impl<'a> Generator<'a> {
self.writeln(&s);
}
- fn struct_impl(&mut self, ast: &syn::DeriveInput, blocks: &'a [Node]) {
+ fn struct_impl(&mut self, ast: &syn::DeriveInput, path: &str,
+ blocks: &'a [Node], nodes: Option<&'a [Node]>) {
let anno = annotations(&ast.generics);
self.writeln(&format!("impl{} {}{} {{", anno, ast.ident.as_ref(),
anno));
self.indent();
+
self.handle(blocks);
+
+ if let Some(nodes) = nodes {
+ let trait_name = format!("TraitFrom{}", path_as_identifier(path));
+ self.writeln(&format!("fn render_trait_to(&self, timpl: &{},",
+ trait_name));
+ self.writeln(" writer: &mut std::fmt::Write) {");
+ self.indent();
+ self.handle(nodes);
+ self.flush_ws(&WS(false, false));
+ self.dedent();
+ self.writeln("}");
+ }
+
self.dedent();
self.writeln("}");
}
@@ -321,7 +336,7 @@ impl<'a> Generator<'a> {
self.writeln("}");
}
- fn impl_template_for_trait(&mut self, ast: &syn::DeriveInput) {
+ fn impl_template_for_trait(&mut self, ast: &syn::DeriveInput, derived: bool) {
let anno = annotations(&ast.generics);
self.writeln(&format!("impl{} askama::Template for {}{} {{",
anno, ast.ident.as_ref(), anno));
@@ -329,7 +344,11 @@ impl<'a> Generator<'a> {
self.writeln("fn render_to(&self, writer: &mut std::fmt::Write) {");
self.indent();
- self.writeln("self.render_trait_to(writer);");
+ if derived {
+ self.writeln("self._parent.render_trait_to(self, writer);");
+ } else {
+ self.writeln("self.render_trait_to(self, writer);");
+ }
self.dedent();
self.writeln("}");
@@ -337,8 +356,7 @@ impl<'a> Generator<'a> {
self.writeln("}");
}
- fn define_trait(&mut self, path: &str, block_names: &[&str],
- nodes: &'a [Node]) {
+ fn define_trait(&mut self, path: &str, block_names: &[&str]) {
self.writeln(&format!("trait TraitFrom{} {{",
path_as_identifier(path)));
self.indent();
@@ -349,13 +367,6 @@ impl<'a> Generator<'a> {
bname));
}
- self.writeln("fn render_trait_to(&self, writer: &mut std::fmt::Write) {");
- self.indent();
- self.handle(nodes);
- self.flush_ws(&WS(false, false));
- self.dedent();
- self.writeln("}");
-
self.dedent();
self.writeln("}");
}
@@ -391,16 +402,18 @@ pub fn generate(ast: &syn::DeriveInput, path: &str, mut nodes: Vec<Node>) -> Str
let mut gen = Generator::new();
gen.path_based_name(ast, path);
if !blocks.is_empty() {
- gen.struct_impl(ast, &blocks);
if base.is_none() {
- gen.define_trait(path, &block_names, &content);
+ gen.struct_impl(ast, path, &blocks, Some(&content));
+ gen.define_trait(path, &block_names);
+ } else {
+ gen.struct_impl(ast, path, &blocks, None);
}
let tmpl_path = match base {
Some(Expr::StrLit(base_path)) => { base_path },
_ => { path },
};
gen.impl_trait(ast, tmpl_path, &block_names);
- gen.impl_template_for_trait(ast);
+ gen.impl_template_for_trait(ast, base.is_some());
} else {
gen.impl_template(ast, &content);
}
diff --git a/testing/tests/inheritance.rs b/testing/tests/inheritance.rs
index 5d5c23c..156358e 100644
--- a/testing/tests/inheritance.rs
+++ b/testing/tests/inheritance.rs
@@ -10,7 +10,9 @@ struct BaseTemplate { }
#[derive(Template)]
#[template(path = "child.html")]
-struct ChildTemplate { }
+struct ChildTemplate {
+ _parent: BaseTemplate,
+}
#[test]
fn test_use_base_directly() {
@@ -20,6 +22,6 @@ fn test_use_base_directly() {
#[test]
fn test_simple_extends() {
- let t = ChildTemplate { };
+ let t = ChildTemplate { _parent: BaseTemplate {} };
assert_eq!(t.render(), "Content goes here\nCopyright 2017\n");
}