From 3c9a369908860b0c9c8d62442eaf4ea495334f08 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 30 May 2020 11:50:55 -0400 Subject: [PATCH] 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() {