diff options
author | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-02-12 20:38:14 +0100 |
---|---|---|
committer | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-02-12 20:38:14 +0100 |
commit | c74e9e8971c06ed77eeee79cbac2c4c325b3ffa4 (patch) | |
tree | 3bf410232558d989379681f4593a717118e6bebd | |
parent | 7b831bd79fd1a1b3f6149420b34df1a19644554c (diff) | |
download | askama-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.rs | 45 | ||||
-rw-r--r-- | testing/tests/inheritance.rs | 6 |
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"); } |