aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/algo/visit.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-16 10:54:24 +0100
committerAleksey Kladov <[email protected]>2018-09-16 11:07:39 +0100
commitb5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch)
tree9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_syntax/src/algo/visit.rs
parentba0bfeee12e19da40b5eabc8d0408639af10e96f (diff)
rename all things
Diffstat (limited to 'crates/ra_syntax/src/algo/visit.rs')
-rw-r--r--crates/ra_syntax/src/algo/visit.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/algo/visit.rs b/crates/ra_syntax/src/algo/visit.rs
new file mode 100644
index 000000000..9f1c127c7
--- /dev/null
+++ b/crates/ra_syntax/src/algo/visit.rs
@@ -0,0 +1,110 @@
1use std::marker::PhantomData;
2use {SyntaxNodeRef, AstNode};
3
4
5pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> {
6 EmptyVisitor { ph: PhantomData }
7}
8
9pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output=T, Ctx=C> {
10 EmptyVisitorCtx { ph: PhantomData, ctx }
11}
12
13pub trait Visitor<'a>: Sized {
14 type Output;
15 fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output>;
16 fn visit<N, F>(self, f: F) -> Vis<Self, N, F>
17 where N: AstNode<'a>,
18 F: FnOnce(N) -> Self::Output,
19 {
20 Vis { inner: self, f, ph: PhantomData }
21 }
22}
23
24pub trait VisitorCtx<'a>: Sized {
25 type Output;
26 type Ctx;
27 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx>;
28 fn visit<N, F>(self, f: F) -> VisCtx<Self, N, F>
29 where N: AstNode<'a>,
30 F: FnOnce(N, Self::Ctx) -> Self::Output,
31 {
32 VisCtx { inner: self, f, ph: PhantomData }
33 }
34}
35
36#[derive(Debug)]
37struct EmptyVisitor<T> {
38 ph: PhantomData<fn() -> T>
39}
40
41impl<'a, T> Visitor<'a> for EmptyVisitor<T> {
42 type Output = T;
43
44 fn accept(self, _node: SyntaxNodeRef<'a>) -> Option<T> {
45 None
46 }
47}
48
49#[derive(Debug)]
50struct EmptyVisitorCtx<T, C> {
51 ctx: C,
52 ph: PhantomData<fn() -> T>,
53}
54
55impl<'a, T, C> VisitorCtx<'a> for EmptyVisitorCtx<T, C> {
56 type Output = T;
57 type Ctx = C;
58
59 fn accept(self, _node: SyntaxNodeRef<'a>) -> Result<T, C> {
60 Err(self.ctx)
61 }
62}
63
64#[derive(Debug)]
65pub struct Vis<V, N, F> {
66 inner: V,
67 f: F,
68 ph: PhantomData<fn(N)>,
69}
70
71impl<'a, V, N, F> Visitor<'a> for Vis<V, N, F>
72 where
73 V: Visitor<'a>,
74 N: AstNode<'a>,
75 F: FnOnce(N) -> <V as Visitor<'a>>::Output,
76{
77 type Output = <V as Visitor<'a>>::Output;
78
79 fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output> {
80 let Vis { inner, f, .. } = self;
81 inner.accept(node).or_else(|| N::cast(node).map(f))
82 }
83}
84
85#[derive(Debug)]
86pub struct VisCtx<V, N, F> {
87 inner: V,
88 f: F,
89 ph: PhantomData<fn(N)>,
90}
91
92impl<'a, V, N, F> VisitorCtx<'a> for VisCtx<V, N, F>
93 where
94 V: VisitorCtx<'a>,
95 N: AstNode<'a>,
96 F: FnOnce(N, <V as VisitorCtx<'a>>::Ctx) -> <V as VisitorCtx<'a>>::Output,
97{
98 type Output = <V as VisitorCtx<'a>>::Output;
99 type Ctx = <V as VisitorCtx<'a>>::Ctx;
100
101 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx> {
102 let VisCtx { inner, f, .. } = self;
103 inner.accept(node).or_else(|ctx|
104 match N::cast(node) {
105 None => Err(ctx),
106 Some(node) => Ok(f(node, ctx))
107 }
108 )
109 }
110}