aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/syntax_text.rs65
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 @@
1use std::{fmt, ops}; 1use std::{fmt, ops::{self, Bound}};
2 2
3use crate::{SyntaxNode, TextRange, TextUnit, SyntaxElement}; 3use 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
91pub trait SyntaxTextSlice: fmt::Debug {
92 fn restrict(&self, range: TextRange) -> Option<TextRange>;
93}
94
95impl SyntaxTextSlice for TextRange {
96 fn restrict(&self, range: TextRange) -> Option<TextRange> {
97 self.intersection(&range)
98 }
99}
100
101impl 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
110impl 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
119impl 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
125impl From<SyntaxText<'_>> for String { 112impl From<SyntaxText<'_>> for String {
126 fn from(text: SyntaxText) -> String { 113 fn from(text: SyntaxText) -> String {
127 text.to_string() 114 text.to_string()