|
1 |
| -use std::{fmt, ops}; |
| 1 | +use std::{fmt, ops::{self, Bound}}; |
2 | 2 |
|
3 | 3 | use crate::{SyntaxNode, TextRange, TextUnit, SyntaxElement};
|
4 | 4 |
|
@@ -54,10 +54,31 @@ impl<'a> SyntaxText<'a> {
|
54 | 54 | self.range.len()
|
55 | 55 | }
|
56 | 56 |
|
57 |
| - pub fn slice(&self, range: impl SyntaxTextSlice) -> SyntaxText<'a> { |
58 |
| - let range = range.restrict(self.range).unwrap_or_else(|| { |
59 |
| - panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range) |
60 |
| - }); |
| 57 | + /// NB, the offsets here are absolute, and this probably doesn't make sense! |
| 58 | + pub fn slice(&self, range: impl ops::RangeBounds<TextUnit>) -> SyntaxText<'a> { |
| 59 | + let start = match range.start_bound() { |
| 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 | 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 | 112 | impl From<SyntaxText<'_>> for String {
|
126 | 113 | fn from(text: SyntaxText) -> String {
|
127 | 114 | text.to_string()
|
|
0 commit comments