diff options
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/syntax_text.rs | 65 |
1 files changed, 26 insertions, 39 deletions
diff --git a/crates/ra_syntax/src/syntax_text.rs b/crates/ra_syntax/src/syntax_text.rs index 6bb2ff461..b013164c4 100644 --- a/crates/ra_syntax/src/syntax_text.rs +++ b/crates/ra_syntax/src/syntax_text.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use std::{fmt, ops}; | 1 | use std::{fmt, ops::{self, Bound}}; |
2 | 2 | ||
3 | use crate::{SyntaxNode, TextRange, TextUnit, SyntaxElement}; | 3 | use crate::{SyntaxNode, TextRange, TextUnit, SyntaxElement}; |
4 | 4 | ||
@@ -54,10 +54,31 @@ impl<'a> SyntaxText<'a> { | |||
54 | self.range.len() | 54 | self.range.len() |
55 | } | 55 | } |
56 | 56 | ||
57 | pub fn slice(&self, range: impl SyntaxTextSlice) -> SyntaxText<'a> { | 57 | /// NB, the offsets here are absolute, and this probably doesn't make sense! |
58 | let range = range.restrict(self.range).unwrap_or_else(|| { | 58 | pub fn slice(&self, range: impl ops::RangeBounds<TextUnit>) -> SyntaxText<'a> { |
59 | panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range) | 59 | let start = match range.start_bound() { |
60 | }); | 60 | Bound::Included(b) => *b, |
61 | Bound::Excluded(b) => *b + TextUnit::from(1u32), | ||
62 | Bound::Unbounded => self.range.start(), | ||
63 | }; | ||
64 | let end = match range.end_bound() { | ||
65 | Bound::Included(b) => *b + TextUnit::from(1u32), | ||
66 | Bound::Excluded(b) => *b, | ||
67 | Bound::Unbounded => self.range.end(), | ||
68 | }; | ||
69 | assert!( | ||
70 | start <= end, | ||
71 | "invalid slice, range: {:?}, slice: {:?}", | ||
72 | self.range, | ||
73 | (range.start_bound(), range.end_bound()), | ||
74 | ); | ||
75 | let range = TextRange::from_to(start, end); | ||
76 | assert!( | ||
77 | range.is_subrange(&self.range), | ||
78 | "invalid slice, range: {:?}, slice: {:?}", | ||
79 | self.range, | ||
80 | range, | ||
81 | ); | ||
61 | SyntaxText { node: self.node, range } | 82 | SyntaxText { node: self.node, range } |
62 | } | 83 | } |
63 | 84 | ||
@@ -88,40 +109,6 @@ impl<'a> fmt::Display for SyntaxText<'a> { | |||
88 | } | 109 | } |
89 | } | 110 | } |
90 | 111 | ||
91 | pub trait SyntaxTextSlice: fmt::Debug { | ||
92 | fn restrict(&self, range: TextRange) -> Option<TextRange>; | ||
93 | } | ||
94 | |||
95 | impl SyntaxTextSlice for TextRange { | ||
96 | fn restrict(&self, range: TextRange) -> Option<TextRange> { | ||
97 | self.intersection(&range) | ||
98 | } | ||
99 | } | ||
100 | |||
101 | impl SyntaxTextSlice for ops::RangeTo<TextUnit> { | ||
102 | fn restrict(&self, range: TextRange) -> Option<TextRange> { | ||
103 | if !range.contains_inclusive(self.end) { | ||
104 | return None; | ||
105 | } | ||
106 | Some(TextRange::from_to(range.start(), self.end)) | ||
107 | } | ||
108 | } | ||
109 | |||
110 | impl SyntaxTextSlice for ops::RangeFrom<TextUnit> { | ||
111 | fn restrict(&self, range: TextRange) -> Option<TextRange> { | ||
112 | if !range.contains_inclusive(self.start) { | ||
113 | return None; | ||
114 | } | ||
115 | Some(TextRange::from_to(self.start, range.end())) | ||
116 | } | ||
117 | } | ||
118 | |||
119 | impl SyntaxTextSlice for ops::Range<TextUnit> { | ||
120 | fn restrict(&self, range: TextRange) -> Option<TextRange> { | ||
121 | TextRange::from_to(self.start, self.end).restrict(range) | ||
122 | } | ||
123 | } | ||
124 | |||
125 | impl From<SyntaxText<'_>> for String { | 112 | impl From<SyntaxText<'_>> for String { |
126 | fn from(text: SyntaxText) -> String { | 113 | fn from(text: SyntaxText) -> String { |
127 | text.to_string() | 114 | text.to_string() |