diff options
Diffstat (limited to 'crates/ra_syntax/src/ast/extensions.rs')
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index cb0aee422..44de4af89 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -1,6 +1,8 @@ | |||
1 | //! Various extension methods to ast Nodes, which are hard to code-generate. | 1 | //! Various extension methods to ast Nodes, which are hard to code-generate. |
2 | //! Extensions for various expressions live in a sibling `expr_extensions` module. | 2 | //! Extensions for various expressions live in a sibling `expr_extensions` module. |
3 | 3 | ||
4 | use itertools::Itertools; | ||
5 | |||
4 | use crate::{ | 6 | use crate::{ |
5 | ast::{self, child_opt, children, AstNode, AttrInput, SyntaxNode}, | 7 | ast::{self, child_opt, children, AstNode, AttrInput, SyntaxNode}, |
6 | SmolStr, SyntaxElement, | 8 | SmolStr, SyntaxElement, |
@@ -35,6 +37,12 @@ fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { | |||
35 | node.green().children().next().and_then(|it| it.into_token()).unwrap().text() | 37 | node.green().children().next().and_then(|it| it.into_token()).unwrap().text() |
36 | } | 38 | } |
37 | 39 | ||
40 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
41 | pub enum AttrKind { | ||
42 | Inner, | ||
43 | Outer, | ||
44 | } | ||
45 | |||
38 | impl ast::Attr { | 46 | impl ast::Attr { |
39 | pub fn as_simple_atom(&self) -> Option<SmolStr> { | 47 | pub fn as_simple_atom(&self) -> Option<SmolStr> { |
40 | match self.input() { | 48 | match self.input() { |
@@ -69,6 +77,18 @@ impl ast::Attr { | |||
69 | _ => None, | 77 | _ => None, |
70 | } | 78 | } |
71 | } | 79 | } |
80 | |||
81 | pub fn kind(&self) -> AttrKind { | ||
82 | let first_token = self.syntax().first_token(); | ||
83 | let first_token_kind = first_token.as_ref().map(SyntaxToken::kind); | ||
84 | let second_token_kind = | ||
85 | first_token.and_then(|token| token.next_token()).as_ref().map(SyntaxToken::kind); | ||
86 | |||
87 | match (first_token_kind, second_token_kind) { | ||
88 | (Some(SyntaxKind::POUND), Some(SyntaxKind::EXCL)) => AttrKind::Inner, | ||
89 | _ => AttrKind::Outer, | ||
90 | } | ||
91 | } | ||
72 | } | 92 | } |
73 | 93 | ||
74 | #[derive(Debug, Clone, PartialEq, Eq)] | 94 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -293,6 +313,40 @@ impl ast::BindPat { | |||
293 | } | 313 | } |
294 | } | 314 | } |
295 | 315 | ||
316 | pub struct SlicePatComponents { | ||
317 | pub prefix: Vec<ast::Pat>, | ||
318 | pub slice: Option<ast::Pat>, | ||
319 | pub suffix: Vec<ast::Pat>, | ||
320 | } | ||
321 | |||
322 | impl ast::SlicePat { | ||
323 | pub fn components(&self) -> SlicePatComponents { | ||
324 | let mut args = self.args().peekable(); | ||
325 | let prefix = args | ||
326 | .peeking_take_while(|p| match p { | ||
327 | ast::Pat::DotDotPat(_) => false, | ||
328 | ast::Pat::BindPat(bp) => match bp.pat() { | ||
329 | Some(ast::Pat::DotDotPat(_)) => false, | ||
330 | _ => true, | ||
331 | }, | ||
332 | ast::Pat::RefPat(rp) => match rp.pat() { | ||
333 | Some(ast::Pat::DotDotPat(_)) => false, | ||
334 | Some(ast::Pat::BindPat(bp)) => match bp.pat() { | ||
335 | Some(ast::Pat::DotDotPat(_)) => false, | ||
336 | _ => true, | ||
337 | }, | ||
338 | _ => true, | ||
339 | }, | ||
340 | _ => true, | ||
341 | }) | ||
342 | .collect(); | ||
343 | let slice = args.next(); | ||
344 | let suffix = args.collect(); | ||
345 | |||
346 | SlicePatComponents { prefix, slice, suffix } | ||
347 | } | ||
348 | } | ||
349 | |||
296 | impl ast::PointerType { | 350 | impl ast::PointerType { |
297 | pub fn is_mut(&self) -> bool { | 351 | pub fn is_mut(&self) -> bool { |
298 | self.syntax().children_with_tokens().any(|n| n.kind() == T![mut]) | 352 | self.syntax().children_with_tokens().any(|n| n.kind() == T![mut]) |