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/ast/expr_extensions.rs77
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs60
-rw-r--r--crates/ra_syntax/src/lib.rs9
-rw-r--r--crates/ra_syntax/src/parsing/lexer.rs25
-rw-r--r--crates/ra_syntax/src/parsing/reparsing.rs11
-rw-r--r--crates/ra_syntax/src/syntax_text.rs65
-rw-r--r--crates/ra_syntax/src/validation.rs7
7 files changed, 128 insertions, 126 deletions
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 9484c3b9b..17763809d 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -3,7 +3,8 @@
3use crate::{ 3use crate::{
4 SyntaxToken, SyntaxElement, SmolStr, 4 SyntaxToken, SyntaxElement, SmolStr,
5 ast::{self, AstNode, AstChildren, children, child_opt}, 5 ast::{self, AstNode, AstChildren, children, child_opt},
6 SyntaxKind::* 6 SyntaxKind::*,
7 T
7}; 8};
8 9
9#[derive(Debug, Clone, PartialEq, Eq)] 10#[derive(Debug, Clone, PartialEq, Eq)]
@@ -34,7 +35,7 @@ impl ast::IfExpr {
34 35
35impl ast::RefExpr { 36impl ast::RefExpr {
36 pub fn is_mut(&self) -> bool { 37 pub fn is_mut(&self) -> bool {
37 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW) 38 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
38 } 39 }
39} 40}
40 41
@@ -51,9 +52,9 @@ pub enum PrefixOp {
51impl ast::PrefixExpr { 52impl ast::PrefixExpr {
52 pub fn op_kind(&self) -> Option<PrefixOp> { 53 pub fn op_kind(&self) -> Option<PrefixOp> {
53 match self.op_token()?.kind() { 54 match self.op_token()?.kind() {
54 STAR => Some(PrefixOp::Deref), 55 T![*] => Some(PrefixOp::Deref),
55 EXCL => Some(PrefixOp::Not), 56 T![!] => Some(PrefixOp::Not),
56 MINUS => Some(PrefixOp::Neg), 57 T![-] => Some(PrefixOp::Neg),
57 _ => None, 58 _ => None,
58 } 59 }
59 } 60 }
@@ -133,37 +134,37 @@ impl ast::BinExpr {
133 fn op_details(&self) -> Option<(SyntaxToken, BinOp)> { 134 fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
134 self.syntax().children_with_tokens().filter_map(|it| it.as_token()).find_map(|c| { 135 self.syntax().children_with_tokens().filter_map(|it| it.as_token()).find_map(|c| {
135 match c.kind() { 136 match c.kind() {
136 PIPEPIPE => Some((c, BinOp::BooleanOr)), 137 T![||] => Some((c, BinOp::BooleanOr)),
137 AMPAMP => Some((c, BinOp::BooleanAnd)), 138 T![&&] => Some((c, BinOp::BooleanAnd)),
138 EQEQ => Some((c, BinOp::EqualityTest)), 139 T![==] => Some((c, BinOp::EqualityTest)),
139 NEQ => Some((c, BinOp::NegatedEqualityTest)), 140 T![!=] => Some((c, BinOp::NegatedEqualityTest)),
140 LTEQ => Some((c, BinOp::LesserEqualTest)), 141 T![<=] => Some((c, BinOp::LesserEqualTest)),
141 GTEQ => Some((c, BinOp::GreaterEqualTest)), 142 T![>=] => Some((c, BinOp::GreaterEqualTest)),
142 L_ANGLE => Some((c, BinOp::LesserTest)), 143 T![<] => Some((c, BinOp::LesserTest)),
143 R_ANGLE => Some((c, BinOp::GreaterTest)), 144 T![>] => Some((c, BinOp::GreaterTest)),
144 PLUS => Some((c, BinOp::Addition)), 145 T![+] => Some((c, BinOp::Addition)),
145 STAR => Some((c, BinOp::Multiplication)), 146 T![*] => Some((c, BinOp::Multiplication)),
146 MINUS => Some((c, BinOp::Subtraction)), 147 T![-] => Some((c, BinOp::Subtraction)),
147 SLASH => Some((c, BinOp::Division)), 148 T![/] => Some((c, BinOp::Division)),
148 PERCENT => Some((c, BinOp::Remainder)), 149 T![%] => Some((c, BinOp::Remainder)),
149 SHL => Some((c, BinOp::LeftShift)), 150 T![<<] => Some((c, BinOp::LeftShift)),
150 SHR => Some((c, BinOp::RightShift)), 151 T![>>] => Some((c, BinOp::RightShift)),
151 CARET => Some((c, BinOp::BitwiseXor)), 152 T![^] => Some((c, BinOp::BitwiseXor)),
152 PIPE => Some((c, BinOp::BitwiseOr)), 153 T![|] => Some((c, BinOp::BitwiseOr)),
153 AMP => Some((c, BinOp::BitwiseAnd)), 154 T![&] => Some((c, BinOp::BitwiseAnd)),
154 DOTDOT => Some((c, BinOp::RangeRightOpen)), 155 T![..] => Some((c, BinOp::RangeRightOpen)),
155 DOTDOTEQ => Some((c, BinOp::RangeRightClosed)), 156 T![..=] => Some((c, BinOp::RangeRightClosed)),
156 EQ => Some((c, BinOp::Assignment)), 157 T![=] => Some((c, BinOp::Assignment)),
157 PLUSEQ => Some((c, BinOp::AddAssign)), 158 T![+=] => Some((c, BinOp::AddAssign)),
158 SLASHEQ => Some((c, BinOp::DivAssign)), 159 T![/=] => Some((c, BinOp::DivAssign)),
159 STAREQ => Some((c, BinOp::MulAssign)), 160 T![*=] => Some((c, BinOp::MulAssign)),
160 PERCENTEQ => Some((c, BinOp::RemAssign)), 161 T![%=] => Some((c, BinOp::RemAssign)),
161 SHREQ => Some((c, BinOp::ShrAssign)), 162 T![>>=] => Some((c, BinOp::ShrAssign)),
162 SHLEQ => Some((c, BinOp::ShlAssign)), 163 T![<<=] => Some((c, BinOp::ShlAssign)),
163 MINUSEQ => Some((c, BinOp::SubAssign)), 164 T![-=] => Some((c, BinOp::SubAssign)),
164 PIPEEQ => Some((c, BinOp::BitOrAssign)), 165 T![|=] => Some((c, BinOp::BitOrAssign)),
165 AMPEQ => Some((c, BinOp::BitAndAssign)), 166 T![&=] => Some((c, BinOp::BitAndAssign)),
166 CARETEQ => Some((c, BinOp::BitXorAssign)), 167 T![^=] => Some((c, BinOp::BitXorAssign)),
167 _ => None, 168 _ => None,
168 } 169 }
169 }) 170 })
@@ -211,7 +212,7 @@ impl ast::ArrayExpr {
211 } 212 }
212 213
213 fn is_repeat(&self) -> bool { 214 fn is_repeat(&self) -> bool {
214 self.syntax().children_with_tokens().any(|it| it.kind() == SEMI) 215 self.syntax().children_with_tokens().any(|it| it.kind() == T![;])
215 } 216 }
216} 217}
217 218
@@ -258,7 +259,7 @@ impl ast::Literal {
258 LiteralKind::FloatNumber { suffix: suffix } 259 LiteralKind::FloatNumber { suffix: suffix }
259 } 260 }
260 STRING | RAW_STRING => LiteralKind::String, 261 STRING | RAW_STRING => LiteralKind::String,
261 TRUE_KW | FALSE_KW => LiteralKind::Bool, 262 T![true] | T![false] => LiteralKind::Bool,
262 BYTE_STRING | RAW_BYTE_STRING => LiteralKind::ByteString, 263 BYTE_STRING | RAW_BYTE_STRING => LiteralKind::ByteString,
263 CHAR => LiteralKind::Char, 264 CHAR => LiteralKind::Char,
264 BYTE => LiteralKind::Byte, 265 BYTE => LiteralKind::Byte,
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index f3466c585..e4c99784c 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -3,7 +3,12 @@
3 3
4use itertools::Itertools; 4use itertools::Itertools;
5 5
6use crate::{SmolStr, SyntaxToken, ast::{self, AstNode, children, child_opt}, SyntaxKind::*, SyntaxElement}; 6use crate::{
7 SmolStr, SyntaxToken,
8 ast::{self, AstNode, children, child_opt},
9 SyntaxKind::*,
10 SyntaxElement, T,
11};
7use ra_parser::SyntaxKind; 12use ra_parser::SyntaxKind;
8 13
9impl ast::Name { 14impl ast::Name {
@@ -32,7 +37,7 @@ impl ast::Attr {
32 Some(prev) => prev, 37 Some(prev) => prev,
33 }; 38 };
34 39
35 prev.kind() == EXCL 40 prev.kind() == T![!]
36 } 41 }
37 42
38 pub fn as_atom(&self) -> Option<SmolStr> { 43 pub fn as_atom(&self) -> Option<SmolStr> {
@@ -102,9 +107,9 @@ impl ast::PathSegment {
102 PathSegmentKind::Name(name_ref) 107 PathSegmentKind::Name(name_ref)
103 } else { 108 } else {
104 match self.syntax().first_child_or_token()?.kind() { 109 match self.syntax().first_child_or_token()?.kind() {
105 SELF_KW => PathSegmentKind::SelfKw, 110 T![self] => PathSegmentKind::SelfKw,
106 SUPER_KW => PathSegmentKind::SuperKw, 111 T![super] => PathSegmentKind::SuperKw,
107 CRATE_KW => PathSegmentKind::CrateKw, 112 T![crate] => PathSegmentKind::CrateKw,
108 _ => return None, 113 _ => return None,
109 } 114 }
110 }; 115 };
@@ -113,7 +118,7 @@ impl ast::PathSegment {
113 118
114 pub fn has_colon_colon(&self) -> bool { 119 pub fn has_colon_colon(&self) -> bool {
115 match self.syntax.first_child_or_token().map(|s| s.kind()) { 120 match self.syntax.first_child_or_token().map(|s| s.kind()) {
116 Some(COLONCOLON) => true, 121 Some(T![::]) => true,
117 _ => false, 122 _ => false,
118 } 123 }
119 } 124 }
@@ -129,14 +134,14 @@ impl ast::Module {
129 pub fn has_semi(&self) -> bool { 134 pub fn has_semi(&self) -> bool {
130 match self.syntax().last_child_or_token() { 135 match self.syntax().last_child_or_token() {
131 None => false, 136 None => false,
132 Some(node) => node.kind() == SEMI, 137 Some(node) => node.kind() == T![;],
133 } 138 }
134 } 139 }
135} 140}
136 141
137impl ast::UseTree { 142impl ast::UseTree {
138 pub fn has_star(&self) -> bool { 143 pub fn has_star(&self) -> bool {
139 self.syntax().children_with_tokens().any(|it| it.kind() == STAR) 144 self.syntax().children_with_tokens().any(|it| it.kind() == T![*])
140 } 145 }
141} 146}
142 147
@@ -172,7 +177,7 @@ impl ast::ImplBlock {
172 } 177 }
173 178
174 pub fn is_negative(&self) -> bool { 179 pub fn is_negative(&self) -> bool {
175 self.syntax().children_with_tokens().any(|t| t.kind() == EXCL) 180 self.syntax().children_with_tokens().any(|t| t.kind() == T![!])
176 } 181 }
177} 182}
178 183
@@ -196,6 +201,17 @@ impl StructKind<'_> {
196} 201}
197 202
198impl ast::StructDef { 203impl ast::StructDef {
204 pub fn is_union(&self) -> bool {
205 for child in self.syntax().children_with_tokens() {
206 match child.kind() {
207 T![struct] => return false,
208 T![union] => return true,
209 _ => (),
210 }
211 }
212 false
213 }
214
199 pub fn kind(&self) -> StructKind { 215 pub fn kind(&self) -> StructKind {
200 StructKind::from_node(self) 216 StructKind::from_node(self)
201 } 217 }
@@ -219,7 +235,7 @@ impl ast::FnDef {
219 self.syntax() 235 self.syntax()
220 .last_child_or_token() 236 .last_child_or_token()
221 .and_then(|it| it.as_token()) 237 .and_then(|it| it.as_token())
222 .filter(|it| it.kind() == SEMI) 238 .filter(|it| it.kind() == T![;])
223 } 239 }
224} 240}
225 241
@@ -227,7 +243,7 @@ impl ast::LetStmt {
227 pub fn has_semi(&self) -> bool { 243 pub fn has_semi(&self) -> bool {
228 match self.syntax().last_child_or_token() { 244 match self.syntax().last_child_or_token() {
229 None => false, 245 None => false,
230 Some(node) => node.kind() == SEMI, 246 Some(node) => node.kind() == T![;],
231 } 247 }
232 } 248 }
233} 249}
@@ -236,7 +252,7 @@ impl ast::ExprStmt {
236 pub fn has_semi(&self) -> bool { 252 pub fn has_semi(&self) -> bool {
237 match self.syntax().last_child_or_token() { 253 match self.syntax().last_child_or_token() {
238 None => false, 254 None => false,
239 Some(node) => node.kind() == SEMI, 255 Some(node) => node.kind() == T![;],
240 } 256 }
241 } 257 }
242} 258}
@@ -270,29 +286,29 @@ impl ast::FieldExpr {
270 286
271impl ast::RefPat { 287impl ast::RefPat {
272 pub fn is_mut(&self) -> bool { 288 pub fn is_mut(&self) -> bool {
273 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW) 289 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
274 } 290 }
275} 291}
276 292
277impl ast::BindPat { 293impl ast::BindPat {
278 pub fn is_mutable(&self) -> bool { 294 pub fn is_mutable(&self) -> bool {
279 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW) 295 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
280 } 296 }
281 297
282 pub fn is_ref(&self) -> bool { 298 pub fn is_ref(&self) -> bool {
283 self.syntax().children_with_tokens().any(|n| n.kind() == REF_KW) 299 self.syntax().children_with_tokens().any(|n| n.kind() == T![ref])
284 } 300 }
285} 301}
286 302
287impl ast::PointerType { 303impl ast::PointerType {
288 pub fn is_mut(&self) -> bool { 304 pub fn is_mut(&self) -> bool {
289 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW) 305 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
290 } 306 }
291} 307}
292 308
293impl ast::ReferenceType { 309impl ast::ReferenceType {
294 pub fn is_mut(&self) -> bool { 310 pub fn is_mut(&self) -> bool {
295 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW) 311 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
296 } 312 }
297} 313}
298 314
@@ -311,19 +327,19 @@ impl ast::SelfParam {
311 self.syntax() 327 self.syntax()
312 .children_with_tokens() 328 .children_with_tokens()
313 .filter_map(|it| it.as_token()) 329 .filter_map(|it| it.as_token())
314 .find(|it| it.kind() == SELF_KW) 330 .find(|it| it.kind() == T![self])
315 .expect("invalid tree: self param must have self") 331 .expect("invalid tree: self param must have self")
316 } 332 }
317 333
318 pub fn kind(&self) -> SelfParamKind { 334 pub fn kind(&self) -> SelfParamKind {
319 let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == AMP); 335 let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == T![&]);
320 if borrowed { 336 if borrowed {
321 // check for a `mut` coming after the & -- `mut &self` != `&mut self` 337 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
322 if self 338 if self
323 .syntax() 339 .syntax()
324 .children_with_tokens() 340 .children_with_tokens()
325 .skip_while(|n| n.kind() != AMP) 341 .skip_while(|n| n.kind() != T![&])
326 .any(|n| n.kind() == MUT_KW) 342 .any(|n| n.kind() == T![mut])
327 { 343 {
328 SelfParamKind::MutRef 344 SelfParamKind::MutRef
329 } else { 345 } else {
@@ -355,6 +371,6 @@ impl ast::WherePred {
355 371
356impl ast::TraitDef { 372impl ast::TraitDef {
357 pub fn is_auto(&self) -> bool { 373 pub fn is_auto(&self) -> bool {
358 self.syntax().children_with_tokens().any(|t| t.kind() == AUTO_KW) 374 self.syntax().children_with_tokens().any(|t| t.kind() == T![auto])
359 } 375 }
360} 376}
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 65c65d6aa..0ceabc203 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -179,10 +179,7 @@ fn api_walkthrough() {
179 179
180 // There's a bunch of traversal methods on `SyntaxNode`: 180 // There's a bunch of traversal methods on `SyntaxNode`:
181 assert_eq!(expr_syntax.parent(), Some(block.syntax())); 181 assert_eq!(expr_syntax.parent(), Some(block.syntax()));
182 assert_eq!( 182 assert_eq!(block.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{']));
183 block.syntax().first_child_or_token().map(|it| it.kind()),
184 Some(SyntaxKind::L_CURLY)
185 );
186 assert_eq!( 183 assert_eq!(
187 expr_syntax.next_sibling_or_token().map(|it| it.kind()), 184 expr_syntax.next_sibling_or_token().map(|it| it.kind()),
188 Some(SyntaxKind::WHITESPACE) 185 Some(SyntaxKind::WHITESPACE)
@@ -191,9 +188,7 @@ fn api_walkthrough() {
191 // As well as some iterator helpers: 188 // As well as some iterator helpers:
192 let f = expr_syntax.ancestors().find_map(ast::FnDef::cast); 189 let f = expr_syntax.ancestors().find_map(ast::FnDef::cast);
193 assert_eq!(f, Some(&*func)); 190 assert_eq!(f, Some(&*func));
194 assert!(expr_syntax 191 assert!(expr_syntax.siblings_with_tokens(Direction::Next).any(|it| it.kind() == T!['}']));
195 .siblings_with_tokens(Direction::Next)
196 .any(|it| it.kind() == SyntaxKind::R_CURLY));
197 assert_eq!( 192 assert_eq!(
198 expr_syntax.descendants_with_tokens().count(), 193 expr_syntax.descendants_with_tokens().count(),
199 8, // 5 tokens `1`, ` `, `+`, ` `, `!` 194 8, // 5 tokens `1`, ` `, `+`, ` `, `!`
diff --git a/crates/ra_syntax/src/parsing/lexer.rs b/crates/ra_syntax/src/parsing/lexer.rs
index a3791b503..6eb96f03d 100644
--- a/crates/ra_syntax/src/parsing/lexer.rs
+++ b/crates/ra_syntax/src/parsing/lexer.rs
@@ -7,6 +7,7 @@ mod strings;
7use crate::{ 7use crate::{
8 SyntaxKind::{self, *}, 8 SyntaxKind::{self, *},
9 TextUnit, 9 TextUnit,
10 T,
10}; 11};
11 12
12use self::{ 13use self::{
@@ -90,16 +91,16 @@ fn next_token_inner(c: char, ptr: &mut Ptr) -> SyntaxKind {
90 match c { 91 match c {
91 // Possiblily multi-byte tokens, 92 // Possiblily multi-byte tokens,
92 // but we only produce single byte token now 93 // but we only produce single byte token now
93 // DOTDOTDOT, DOTDOT, DOTDOTEQ, DOT 94 // T![...], T![..], T![..=], T![.]
94 '.' => return DOT, 95 '.' => return T![.],
95 // COLONCOLON COLON 96 // T![::] T![:]
96 ':' => return COLON, 97 ':' => return T![:],
97 // EQEQ FATARROW EQ 98 // T![==] FATARROW T![=]
98 '=' => return EQ, 99 '=' => return T![=],
99 // NEQ EXCL 100 // T![!=] T![!]
100 '!' => return EXCL, 101 '!' => return T![!],
101 // THIN_ARROW MINUS 102 // T![->] T![-]
102 '-' => return MINUS, 103 '-' => return T![-],
103 104
104 // If the character is an ident start not followed by another single 105 // If the character is an ident start not followed by another single
105 // quote, then this is a lifetime name: 106 // quote, then this is a lifetime name:
@@ -148,8 +149,8 @@ fn scan_ident(c: char, ptr: &mut Ptr) -> SyntaxKind {
148 ptr.bump(); 149 ptr.bump();
149 true 150 true
150 } 151 }
151 ('_', None) => return UNDERSCORE, 152 ('_', None) => return T![_],
152 ('_', Some(c)) if !is_ident_continue(c) => return UNDERSCORE, 153 ('_', Some(c)) if !is_ident_continue(c) => return T![_],
153 _ => false, 154 _ => false,
154 }; 155 };
155 ptr.bump_while(is_ident_continue); 156 ptr.bump_while(is_ident_continue);
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs
index 434f850d1..6de02a15a 100644
--- a/crates/ra_syntax/src/parsing/reparsing.rs
+++ b/crates/ra_syntax/src/parsing/reparsing.rs
@@ -17,7 +17,8 @@ use crate::{
17 text_token_source::TextTokenSource, 17 text_token_source::TextTokenSource,
18 text_tree_sink::TextTreeSink, 18 text_tree_sink::TextTreeSink,
19 lexer::{tokenize, Token}, 19 lexer::{tokenize, Token},
20 } 20 },
21 T,
21}; 22};
22 23
23pub(crate) fn incremental_reparse( 24pub(crate) fn incremental_reparse(
@@ -122,16 +123,16 @@ fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(&SyntaxN
122 123
123fn is_balanced(tokens: &[Token]) -> bool { 124fn is_balanced(tokens: &[Token]) -> bool {
124 if tokens.is_empty() 125 if tokens.is_empty()
125 || tokens.first().unwrap().kind != L_CURLY 126 || tokens.first().unwrap().kind != T!['{']
126 || tokens.last().unwrap().kind != R_CURLY 127 || tokens.last().unwrap().kind != T!['}']
127 { 128 {
128 return false; 129 return false;
129 } 130 }
130 let mut balance = 0usize; 131 let mut balance = 0usize;
131 for t in &tokens[1..tokens.len() - 1] { 132 for t in &tokens[1..tokens.len() - 1] {
132 match t.kind { 133 match t.kind {
133 L_CURLY => balance += 1, 134 T!['{'] => balance += 1,
134 R_CURLY => { 135 T!['}'] => {
135 balance = match balance.checked_sub(1) { 136 balance = match balance.checked_sub(1) {
136 Some(b) => b, 137 Some(b) => b,
137 None => return false, 138 None => return false,
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()
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index 11a1fb4a7..b53900a4b 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -5,9 +5,10 @@ mod field_expr;
5 5
6use crate::{ 6use crate::{
7 SourceFile, SyntaxError, AstNode, SyntaxNode, TextUnit, 7 SourceFile, SyntaxError, AstNode, SyntaxNode, TextUnit,
8 SyntaxKind::{L_CURLY, R_CURLY, BYTE, BYTE_STRING, STRING, CHAR}, 8 SyntaxKind::{BYTE, BYTE_STRING, STRING, CHAR},
9 ast, 9 ast,
10 algo::visit::{visitor_ctx, VisitorCtx}, 10 algo::visit::{visitor_ctx, VisitorCtx},
11 T,
11}; 12};
12 13
13pub(crate) use unescape::EscapeError; 14pub(crate) use unescape::EscapeError;
@@ -83,8 +84,8 @@ pub(crate) fn validate_block_structure(root: &SyntaxNode) {
83 let mut stack = Vec::new(); 84 let mut stack = Vec::new();
84 for node in root.descendants() { 85 for node in root.descendants() {
85 match node.kind() { 86 match node.kind() {
86 L_CURLY => stack.push(node), 87 T!['{'] => stack.push(node),
87 R_CURLY => { 88 T!['}'] => {
88 if let Some(pair) = stack.pop() { 89 if let Some(pair) = stack.pop() {
89 assert_eq!( 90 assert_eq!(
90 node.parent(), 91 node.parent(),