From ac226021cfd26a9332b5971f3e05118d77822af5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 26 Aug 2018 12:09:28 +0300 Subject: scope based comletion --- crates/libsyntax2/src/algo/visit.rs | 58 +++++++++++++++++++++++++++++++++++++ crates/libsyntax2/src/algo/walk.rs | 10 +++---- 2 files changed, 63 insertions(+), 5 deletions(-) (limited to 'crates/libsyntax2/src/algo') diff --git a/crates/libsyntax2/src/algo/visit.rs b/crates/libsyntax2/src/algo/visit.rs index a36c8f45e..9f1c127c7 100644 --- a/crates/libsyntax2/src/algo/visit.rs +++ b/crates/libsyntax2/src/algo/visit.rs @@ -6,6 +6,10 @@ pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> { EmptyVisitor { ph: PhantomData } } +pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output=T, Ctx=C> { + EmptyVisitorCtx { ph: PhantomData, ctx } +} + pub trait Visitor<'a>: Sized { type Output; fn accept(self, node: SyntaxNodeRef<'a>) -> Option; @@ -17,6 +21,18 @@ pub trait Visitor<'a>: Sized { } } +pub trait VisitorCtx<'a>: Sized { + type Output; + type Ctx; + fn accept(self, node: SyntaxNodeRef<'a>) -> Result; + fn visit(self, f: F) -> VisCtx + where N: AstNode<'a>, + F: FnOnce(N, Self::Ctx) -> Self::Output, + { + VisCtx { inner: self, f, ph: PhantomData } + } +} + #[derive(Debug)] struct EmptyVisitor { ph: PhantomData T> @@ -30,6 +46,21 @@ impl<'a, T> Visitor<'a> for EmptyVisitor { } } +#[derive(Debug)] +struct EmptyVisitorCtx { + ctx: C, + ph: PhantomData T>, +} + +impl<'a, T, C> VisitorCtx<'a> for EmptyVisitorCtx { + type Output = T; + type Ctx = C; + + fn accept(self, _node: SyntaxNodeRef<'a>) -> Result { + Err(self.ctx) + } +} + #[derive(Debug)] pub struct Vis { inner: V, @@ -50,3 +81,30 @@ impl<'a, V, N, F> Visitor<'a> for Vis inner.accept(node).or_else(|| N::cast(node).map(f)) } } + +#[derive(Debug)] +pub struct VisCtx { + inner: V, + f: F, + ph: PhantomData, +} + +impl<'a, V, N, F> VisitorCtx<'a> for VisCtx + where + V: VisitorCtx<'a>, + N: AstNode<'a>, + F: FnOnce(N, >::Ctx) -> >::Output, +{ + type Output = >::Output; + type Ctx = >::Ctx; + + fn accept(self, node: SyntaxNodeRef<'a>) -> Result { + let VisCtx { inner, f, .. } = self; + inner.accept(node).or_else(|ctx| + match N::cast(node) { + None => Err(ctx), + Some(node) => Ok(f(node, ctx)) + } + ) + } +} diff --git a/crates/libsyntax2/src/algo/walk.rs b/crates/libsyntax2/src/algo/walk.rs index d8797c453..536ee705f 100644 --- a/crates/libsyntax2/src/algo/walk.rs +++ b/crates/libsyntax2/src/algo/walk.rs @@ -17,19 +17,19 @@ pub enum WalkEvent<'a> { } pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator> { - generate(Some(WalkEvent::Enter(root)), |pos| { + generate(Some(WalkEvent::Enter(root)), move |pos| { let next = match *pos { WalkEvent::Enter(node) => match node.first_child() { Some(child) => WalkEvent::Enter(child), None => WalkEvent::Exit(node), }, WalkEvent::Exit(node) => { + if node == root { + return None; + } match node.next_sibling() { Some(sibling) => WalkEvent::Enter(sibling), - None => match node.parent() { - Some(node) => WalkEvent::Exit(node), - None => return None, - }, + None => WalkEvent::Exit(node.parent().unwrap()), } } }; -- cgit v1.2.3