diff options
author | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-08-08 12:35:15 +0200 |
---|---|---|
committer | Dirkjan Ochtman <dirkjan@ochtman.nl> | 2017-08-08 12:36:29 +0200 |
commit | e3d08c72bc2a7c34243208e68158b6f919701082 (patch) | |
tree | 72bac8ca70162e50240a82b660669048edbb89e4 /askama_derive/src/generator.rs | |
parent | 20efa67bc1120f34a3f5be2015090e8ee818ddd5 (diff) | |
download | askama-e3d08c72bc2a7c34243208e68158b6f919701082.tar.gz askama-e3d08c72bc2a7c34243208e68158b6f919701082.tar.bz2 askama-e3d08c72bc2a7c34243208e68158b6f919701082.zip |
Implement Deref<Parent> for inheriting templates (fixes #28)
Diffstat (limited to '')
-rw-r--r-- | askama_derive/src/generator.rs | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index a3363b4..fd2fb5b 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -379,6 +379,18 @@ impl<'a> Generator<'a> { self.writeln("}"); } + // Implement `Deref<Parent>` for an inheriting context struct. + fn deref_to_parent(&mut self, ast: &syn::DeriveInput, parent_type: &syn::Ty) { + self.write_header(ast, "::std::ops::Deref"); + let mut tokens = Tokens::new(); + parent_type.to_tokens(&mut tokens); + self.writeln(&format!("type Target = {};", tokens.as_str())); + self.writeln("fn deref(&self) -> &Self::Target {"); + self.writeln("&self._parent"); + self.writeln("}"); + self.writeln("}"); + } + // Implement `TraitFromPathName` for the given context struct. fn impl_trait(&mut self, ast: &syn::DeriveInput, trait_name: &str, blocks: &'a [Node], nodes: Option<&'a [Node]>) { @@ -461,6 +473,23 @@ fn trait_name_for_path(base: &Option<Expr>, path: &str) -> String { res } +fn get_parent_type(ast: &syn::DeriveInput) -> Option<&syn::Ty> { + match ast.body { + syn::Body::Struct(ref data) => { + data.fields().iter().filter_map(|f| { + f.ident.as_ref().and_then(|name| { + if name.as_ref() == "_parent" { + Some(&f.ty) + } else { + None + } + }) + }) + }, + _ => panic!("derive(Template) only works for struct items"), + }.next() +} + pub fn generate(ast: &syn::DeriveInput, path: &str, mut nodes: Vec<Node>) -> String { let mut base: Option<Expr> = None; let mut blocks = Vec::new(); @@ -489,6 +518,8 @@ pub fn generate(ast: &syn::DeriveInput, path: &str, mut nodes: Vec<Node>) -> Str let trait_name = trait_name_for_path(&base, path); if base.is_none() { gen.define_trait(&trait_name, &block_names); + } else { + gen.deref_to_parent(ast, &get_parent_type(ast).unwrap()); } let trait_nodes = if base.is_none() { Some(&content[..]) } else { None }; |