From 3c9a369908860b0c9c8d62442eaf4ea495334f08 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 30 May 2020 11:50:55 -0400 Subject: [PATCH 1/2] Skipping over pseudo contexts has fixed most of the tests. --- src/renderer/context_element.rs | 10 ++++++++ src/renderer/iteration_context.rs | 4 +++ src/renderer/parameters_context.rs | 4 +++ src/renderer/walking.rs | 39 +++++++++++++++++++++--------- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/renderer/context_element.rs b/src/renderer/context_element.rs index 992fa6b..ec2e5a0 100644 --- a/src/renderer/context_element.rs +++ b/src/renderer/context_element.rs @@ -21,6 +21,16 @@ pub trait Truthiness { pub trait Walkable { fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError>; + + /// If an element contains meta information and should not be + /// returned as the final result of a walk, this function should + /// return true. + /// + /// For example, the iteration context contains $idx and $len but + /// it should not be the result of a dot-reference like `{.}`. + fn is_pseudo_element(&self) -> bool { + false + } } pub trait Renderable { diff --git a/src/renderer/iteration_context.rs b/src/renderer/iteration_context.rs index acdd9a1..f6a3998 100644 --- a/src/renderer/iteration_context.rs +++ b/src/renderer/iteration_context.rs @@ -68,6 +68,10 @@ impl Walkable for IterationContext { _ => Err(WalkError::CantWalk), } } + + fn is_pseudo_element(&self) -> bool { + true + } } impl CompareContextElement for IterationContext { diff --git a/src/renderer/parameters_context.rs b/src/renderer/parameters_context.rs index 7a3e6b1..1d4dd8b 100644 --- a/src/renderer/parameters_context.rs +++ b/src/renderer/parameters_context.rs @@ -103,6 +103,10 @@ impl Walkable for ParametersContext { OwnedRValue::RVLiteral(literal) => Ok(literal), } } + + fn is_pseudo_element(&self) -> bool { + true + } } impl Clone for ParametersContext { diff --git a/src/renderer/walking.rs b/src/renderer/walking.rs index 49dff7f..58cd0b4 100644 --- a/src/renderer/walking.rs +++ b/src/renderer/walking.rs @@ -1,4 +1,5 @@ use crate::renderer::context_element::ContextElement; +use crate::renderer::context_element::Walkable; use crate::renderer::WalkError; use std::borrow::Borrow; @@ -34,6 +35,17 @@ where WalkResult::FullyWalked(output) } +pub fn get_first_non_pseudo_element<'a, B>(breadcrumbs: &'a Vec) -> Option<&B> +where + B: Borrow, +{ + breadcrumbs + .iter() + .rev() + .filter(|b| !(*b).borrow().is_pseudo_element()) + .next() +} + pub fn walk_path<'a, B, P>( breadcrumbs: &'a Vec, path: &Vec

, @@ -60,17 +72,22 @@ where .borrow() == "." { - return match walk_path_from_single_level( - breadcrumbs - .last() - .expect("Breadcrumbs should never be empty"), - &path[1..], - ) { - // If no walking was done at all or we partially walked - // then stop trying to find anything because '.' restricts - // us to the current scope - WalkResult::NoWalk | WalkResult::PartialWalk => Err(WalkError::CantWalk), - WalkResult::FullyWalked(new_context) => Ok(new_context), + let first_non_pseudo_element = get_first_non_pseudo_element(breadcrumbs); + // println!( + // "First non-pseudo element: {:?}", + // first_non_pseudo_element.map(|b| b.borrow()) + // ); + return match first_non_pseudo_element { + None => Err(WalkError::CantWalk), + Some(current_context) => { + match walk_path_from_single_level(current_context, &path[1..]) { + // If no walking was done at all or we partially walked + // then stop trying to find anything because '.' restricts + // us to the current scope + WalkResult::NoWalk | WalkResult::PartialWalk => Err(WalkError::CantWalk), + WalkResult::FullyWalked(new_context) => Ok(new_context), + } + } }; } for context in breadcrumbs.iter().rev() { From a0e2ba2b82470b0dacfb406ba87992be12e4c66d Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 30 May 2020 12:24:50 -0400 Subject: [PATCH 2/2] Had to update the 1-behind insertion for partial parameters to account for pseudo elements. --- src/renderer/renderer.rs | 15 ++++++++++++++- src/renderer/walking.rs | 4 ---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/renderer/renderer.rs b/src/renderer/renderer.rs index 0de9263..88617db 100644 --- a/src/renderer/renderer.rs +++ b/src/renderer/renderer.rs @@ -17,6 +17,7 @@ use crate::renderer::inline_partial_tree::InlinePartialTreeElement; use crate::renderer::iteration_context::IterationContext; use crate::renderer::parameters_context::ParametersContext; use crate::renderer::walking::walk_path; +use std::borrow::Borrow; use std::collections::HashMap; #[derive(Clone, Debug)] @@ -813,6 +814,15 @@ impl<'a> DustRenderer<'a> { Some(new_stack) } + fn get_index_of_first_non_pseudo_element<'b, B>(breadcrumbs: &'b Vec) -> Option + where + B: Borrow, + { + breadcrumbs + .iter() + .rposition(|b| !(*b).borrow().is_pseudo_element()) + } + fn new_breadcrumbs_partial<'b>( breadcrumbs: &'b Vec<&'b dyn ContextElement>, explicit_context_breadcrumbs: &'b Vec<&'b dyn ContextElement>, @@ -837,7 +847,10 @@ impl<'a> DustRenderer<'a> { // added after the current context but before the explicit // context. match explicit_context { - None => new_stack.insert(std::cmp::max(new_stack.len() - 1, 0), ctx), + None => new_stack.insert( + Self::get_index_of_first_non_pseudo_element(&new_stack).unwrap_or(0), + ctx, + ), _ => new_stack.push(ctx), } }); diff --git a/src/renderer/walking.rs b/src/renderer/walking.rs index 58cd0b4..c0c2365 100644 --- a/src/renderer/walking.rs +++ b/src/renderer/walking.rs @@ -73,10 +73,6 @@ where == "." { let first_non_pseudo_element = get_first_non_pseudo_element(breadcrumbs); - // println!( - // "First non-pseudo element: {:?}", - // first_non_pseudo_element.map(|b| b.borrow()) - // ); return match first_non_pseudo_element { None => Err(WalkError::CantWalk), Some(current_context) => {