Skipping over pseudo contexts has fixed most of the tests.

This commit is contained in:
Tom Alexander 2020-05-30 11:50:55 -04:00
parent f04e84dc31
commit 3c9a369908
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 46 additions and 11 deletions

View File

@ -21,6 +21,16 @@ pub trait Truthiness {
pub trait Walkable { pub trait Walkable {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError>; 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 { pub trait Renderable {

View File

@ -68,6 +68,10 @@ impl Walkable for IterationContext {
_ => Err(WalkError::CantWalk), _ => Err(WalkError::CantWalk),
} }
} }
fn is_pseudo_element(&self) -> bool {
true
}
} }
impl CompareContextElement for IterationContext { impl CompareContextElement for IterationContext {

View File

@ -103,6 +103,10 @@ impl Walkable for ParametersContext {
OwnedRValue::RVLiteral(literal) => Ok(literal), OwnedRValue::RVLiteral(literal) => Ok(literal),
} }
} }
fn is_pseudo_element(&self) -> bool {
true
}
} }
impl Clone for ParametersContext { impl Clone for ParametersContext {

View File

@ -1,4 +1,5 @@
use crate::renderer::context_element::ContextElement; use crate::renderer::context_element::ContextElement;
use crate::renderer::context_element::Walkable;
use crate::renderer::WalkError; use crate::renderer::WalkError;
use std::borrow::Borrow; use std::borrow::Borrow;
@ -34,6 +35,17 @@ where
WalkResult::FullyWalked(output) WalkResult::FullyWalked(output)
} }
pub fn get_first_non_pseudo_element<'a, B>(breadcrumbs: &'a Vec<B>) -> Option<&B>
where
B: Borrow<dyn ContextElement + 'a>,
{
breadcrumbs
.iter()
.rev()
.filter(|b| !(*b).borrow().is_pseudo_element())
.next()
}
pub fn walk_path<'a, B, P>( pub fn walk_path<'a, B, P>(
breadcrumbs: &'a Vec<B>, breadcrumbs: &'a Vec<B>,
path: &Vec<P>, path: &Vec<P>,
@ -60,17 +72,22 @@ where
.borrow() .borrow()
== "." == "."
{ {
return match walk_path_from_single_level( let first_non_pseudo_element = get_first_non_pseudo_element(breadcrumbs);
breadcrumbs // println!(
.last() // "First non-pseudo element: {:?}",
.expect("Breadcrumbs should never be empty"), // first_non_pseudo_element.map(|b| b.borrow())
&path[1..], // );
) { return match first_non_pseudo_element {
// If no walking was done at all or we partially walked None => Err(WalkError::CantWalk),
// then stop trying to find anything because '.' restricts Some(current_context) => {
// us to the current scope match walk_path_from_single_level(current_context, &path[1..]) {
WalkResult::NoWalk | WalkResult::PartialWalk => Err(WalkError::CantWalk), // If no walking was done at all or we partially walked
WalkResult::FullyWalked(new_context) => Ok(new_context), // 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() { for context in breadcrumbs.iter().rev() {