Reinstate use of Deref for inherited variable access

This commit is contained in:
Dirkjan Ochtman 2018-06-22 16:03:37 +02:00
parent a451bf29b6
commit 21edd48917

View File

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