aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/algo
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/algo')
-rw-r--r--crates/ra_syntax/src/algo/mod.rs54
-rw-r--r--crates/ra_syntax/src/algo/visit.rs63
-rw-r--r--crates/ra_syntax/src/algo/walk.rs6
3 files changed, 71 insertions, 52 deletions
diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs
index e686a5704..b4896c482 100644
--- a/crates/ra_syntax/src/algo/mod.rs
+++ b/crates/ra_syntax/src/algo/mod.rs
@@ -1,16 +1,18 @@
1pub mod walk;
2pub mod visit; 1pub mod visit;
2pub mod walk;
3 3
4use crate::{ 4use crate::{
5 SyntaxNodeRef, TextUnit, TextRange,
6 text_utils::{contains_offset_nonstrict, is_subrange}, 5 text_utils::{contains_offset_nonstrict, is_subrange},
6 SyntaxNodeRef, TextRange, TextUnit,
7}; 7};
8 8
9pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset { 9pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset {
10 let range = node.range(); 10 let range = node.range();
11 assert!( 11 assert!(
12 contains_offset_nonstrict(range, offset), 12 contains_offset_nonstrict(range, offset),
13 "Bad offset: range {:?} offset {:?}", range, offset 13 "Bad offset: range {:?} offset {:?}",
14 range,
15 offset
14 ); 16 );
15 if range.is_empty() { 17 if range.is_empty() {
16 return LeafAtOffset::None; 18 return LeafAtOffset::None;
@@ -20,20 +22,23 @@ pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffse
20 return LeafAtOffset::Single(node); 22 return LeafAtOffset::Single(node);
21 } 23 }
22 24
23 let mut children = node.children() 25 let mut children = node.children().filter(|child| {
24 .filter(|child| { 26 let child_range = child.range();
25 let child_range = child.range(); 27 !child_range.is_empty() && contains_offset_nonstrict(child_range, offset)
26 !child_range.is_empty() && contains_offset_nonstrict(child_range, offset) 28 });
27 });
28 29
29 let left = children.next().unwrap(); 30 let left = children.next().unwrap();
30 let right = children.next(); 31 let right = children.next();
31 assert!(children.next().is_none()); 32 assert!(children.next().is_none());
32 return if let Some(right) = right { 33 return if let Some(right) = right {
33 match (find_leaf_at_offset(left, offset), find_leaf_at_offset(right, offset)) { 34 match (
34 (LeafAtOffset::Single(left), LeafAtOffset::Single(right)) => 35 find_leaf_at_offset(left, offset),
35 LeafAtOffset::Between(left, right), 36 find_leaf_at_offset(right, offset),
36 _ => unreachable!() 37 ) {
38 (LeafAtOffset::Single(left), LeafAtOffset::Single(right)) => {
39 LeafAtOffset::Between(left, right)
40 }
41 _ => unreachable!(),
37 } 42 }
38 } else { 43 } else {
39 find_leaf_at_offset(left, offset) 44 find_leaf_at_offset(left, offset)
@@ -44,7 +49,7 @@ pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffse
44pub enum LeafAtOffset<'a> { 49pub enum LeafAtOffset<'a> {
45 None, 50 None,
46 Single(SyntaxNodeRef<'a>), 51 Single(SyntaxNodeRef<'a>),
47 Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>) 52 Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>),
48} 53}
49 54
50impl<'a> LeafAtOffset<'a> { 55impl<'a> LeafAtOffset<'a> {
@@ -52,7 +57,7 @@ impl<'a> LeafAtOffset<'a> {
52 match self { 57 match self {
53 LeafAtOffset::None => None, 58 LeafAtOffset::None => None,
54 LeafAtOffset::Single(node) => Some(node), 59 LeafAtOffset::Single(node) => Some(node),
55 LeafAtOffset::Between(_, right) => Some(right) 60 LeafAtOffset::Between(_, right) => Some(right),
56 } 61 }
57 } 62 }
58 63
@@ -60,7 +65,7 @@ impl<'a> LeafAtOffset<'a> {
60 match self { 65 match self {
61 LeafAtOffset::None => None, 66 LeafAtOffset::None => None,
62 LeafAtOffset::Single(node) => Some(node), 67 LeafAtOffset::Single(node) => Some(node),
63 LeafAtOffset::Between(left, _) => Some(left) 68 LeafAtOffset::Between(left, _) => Some(left),
64 } 69 }
65 } 70 }
66} 71}
@@ -71,8 +76,14 @@ impl<'f> Iterator for LeafAtOffset<'f> {
71 fn next(&mut self) -> Option<SyntaxNodeRef<'f>> { 76 fn next(&mut self) -> Option<SyntaxNodeRef<'f>> {
72 match *self { 77 match *self {
73 LeafAtOffset::None => None, 78 LeafAtOffset::None => None,
74 LeafAtOffset::Single(node) => { *self = LeafAtOffset::None; Some(node) } 79 LeafAtOffset::Single(node) => {
75 LeafAtOffset::Between(left, right) => { *self = LeafAtOffset::Single(right); Some(left) } 80 *self = LeafAtOffset::None;
81 Some(node)
82 }
83 LeafAtOffset::Between(left, right) => {
84 *self = LeafAtOffset::Single(right);
85 Some(left)
86 }
76 } 87 }
77 } 88 }
78} 89}
@@ -81,14 +92,15 @@ pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRe
81 assert!( 92 assert!(
82 is_subrange(root.range(), range), 93 is_subrange(root.range(), range),
83 "node range: {:?}, target range: {:?}", 94 "node range: {:?}, target range: {:?}",
84 root.range(), range, 95 root.range(),
96 range,
85 ); 97 );
86 let (left, right) = match ( 98 let (left, right) = match (
87 find_leaf_at_offset(root, range.start()).right_biased(), 99 find_leaf_at_offset(root, range.start()).right_biased(),
88 find_leaf_at_offset(root, range.end()).left_biased() 100 find_leaf_at_offset(root, range.end()).left_biased(),
89 ) { 101 ) {
90 (Some(l), Some(r)) => (l, r), 102 (Some(l), Some(r)) => (l, r),
91 _ => return root 103 _ => return root,
92 }; 104 };
93 105
94 common_ancestor(left, right) 106 common_ancestor(left, right)
@@ -103,7 +115,7 @@ fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNo
103 panic!("Can't find common ancestor of {:?} and {:?}", n1, n2) 115 panic!("Can't find common ancestor of {:?} and {:?}", n1, n2)
104} 116}
105 117
106pub fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item=T> { 118pub fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item = T> {
107 ::itertools::unfold(seed, move |slot| { 119 ::itertools::unfold(seed, move |slot| {
108 slot.take().map(|curr| { 120 slot.take().map(|curr| {
109 *slot = step(&curr); 121 *slot = step(&curr);
diff --git a/crates/ra_syntax/src/algo/visit.rs b/crates/ra_syntax/src/algo/visit.rs
index 1ae988a87..c021f464c 100644
--- a/crates/ra_syntax/src/algo/visit.rs
+++ b/crates/ra_syntax/src/algo/visit.rs
@@ -1,23 +1,31 @@
1use std::marker::PhantomData; 1use crate::{AstNode, SyntaxNodeRef};
2use crate::{SyntaxNodeRef, AstNode};
3 2
3use std::marker::PhantomData;
4 4
5pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> { 5pub fn visitor<'a, T>() -> impl Visitor<'a, Output = T> {
6 EmptyVisitor { ph: PhantomData } 6 EmptyVisitor { ph: PhantomData }
7} 7}
8 8
9pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output=T, Ctx=C> { 9pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output = T, Ctx = C> {
10 EmptyVisitorCtx { ph: PhantomData, ctx } 10 EmptyVisitorCtx {
11 ph: PhantomData,
12 ctx,
13 }
11} 14}
12 15
13pub trait Visitor<'a>: Sized { 16pub trait Visitor<'a>: Sized {
14 type Output; 17 type Output;
15 fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output>; 18 fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output>;
16 fn visit<N, F>(self, f: F) -> Vis<Self, N, F> 19 fn visit<N, F>(self, f: F) -> Vis<Self, N, F>
17 where N: AstNode<'a>, 20 where
18 F: FnOnce(N) -> Self::Output, 21 N: AstNode<'a>,
22 F: FnOnce(N) -> Self::Output,
19 { 23 {
20 Vis { inner: self, f, ph: PhantomData } 24 Vis {
25 inner: self,
26 f,
27 ph: PhantomData,
28 }
21 } 29 }
22} 30}
23 31
@@ -26,16 +34,21 @@ pub trait VisitorCtx<'a>: Sized {
26 type Ctx; 34 type Ctx;
27 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx>; 35 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx>;
28 fn visit<N, F>(self, f: F) -> VisCtx<Self, N, F> 36 fn visit<N, F>(self, f: F) -> VisCtx<Self, N, F>
29 where N: AstNode<'a>, 37 where
30 F: FnOnce(N, Self::Ctx) -> Self::Output, 38 N: AstNode<'a>,
39 F: FnOnce(N, Self::Ctx) -> Self::Output,
31 { 40 {
32 VisCtx { inner: self, f, ph: PhantomData } 41 VisCtx {
42 inner: self,
43 f,
44 ph: PhantomData,
45 }
33 } 46 }
34} 47}
35 48
36#[derive(Debug)] 49#[derive(Debug)]
37struct EmptyVisitor<T> { 50struct EmptyVisitor<T> {
38 ph: PhantomData<fn() -> T> 51 ph: PhantomData<fn() -> T>,
39} 52}
40 53
41impl<'a, T> Visitor<'a> for EmptyVisitor<T> { 54impl<'a, T> Visitor<'a> for EmptyVisitor<T> {
@@ -69,10 +82,10 @@ pub struct Vis<V, N, F> {
69} 82}
70 83
71impl<'a, V, N, F> Visitor<'a> for Vis<V, N, F> 84impl<'a, V, N, F> Visitor<'a> for Vis<V, N, F>
72 where 85where
73 V: Visitor<'a>, 86 V: Visitor<'a>,
74 N: AstNode<'a>, 87 N: AstNode<'a>,
75 F: FnOnce(N) -> <V as Visitor<'a>>::Output, 88 F: FnOnce(N) -> <V as Visitor<'a>>::Output,
76{ 89{
77 type Output = <V as Visitor<'a>>::Output; 90 type Output = <V as Visitor<'a>>::Output;
78 91
@@ -90,21 +103,19 @@ pub struct VisCtx<V, N, F> {
90} 103}
91 104
92impl<'a, V, N, F> VisitorCtx<'a> for VisCtx<V, N, F> 105impl<'a, V, N, F> VisitorCtx<'a> for VisCtx<V, N, F>
93 where 106where
94 V: VisitorCtx<'a>, 107 V: VisitorCtx<'a>,
95 N: AstNode<'a>, 108 N: AstNode<'a>,
96 F: FnOnce(N, <V as VisitorCtx<'a>>::Ctx) -> <V as VisitorCtx<'a>>::Output, 109 F: FnOnce(N, <V as VisitorCtx<'a>>::Ctx) -> <V as VisitorCtx<'a>>::Output,
97{ 110{
98 type Output = <V as VisitorCtx<'a>>::Output; 111 type Output = <V as VisitorCtx<'a>>::Output;
99 type Ctx = <V as VisitorCtx<'a>>::Ctx; 112 type Ctx = <V as VisitorCtx<'a>>::Ctx;
100 113
101 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx> { 114 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx> {
102 let VisCtx { inner, f, .. } = self; 115 let VisCtx { inner, f, .. } = self;
103 inner.accept(node).or_else(|ctx| 116 inner.accept(node).or_else(|ctx| match N::cast(node) {
104 match N::cast(node) { 117 None => Err(ctx),
105 None => Err(ctx), 118 Some(node) => Ok(f(node, ctx)),
106 Some(node) => Ok(f(node, ctx)) 119 })
107 }
108 )
109 } 120 }
110} 121}
diff --git a/crates/ra_syntax/src/algo/walk.rs b/crates/ra_syntax/src/algo/walk.rs
index d34415626..9afa86401 100644
--- a/crates/ra_syntax/src/algo/walk.rs
+++ b/crates/ra_syntax/src/algo/walk.rs
@@ -1,8 +1,4 @@
1use crate::{ 1use crate::{algo::generate, SyntaxNodeRef};
2 SyntaxNodeRef,
3 algo::generate,
4};
5
6 2
7#[derive(Debug, Copy, Clone)] 3#[derive(Debug, Copy, Clone)]
8pub enum WalkEvent<'a> { 4pub enum WalkEvent<'a> {