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