aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast/extensions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/ast/extensions.rs')
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs54
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
4use itertools::Itertools;
5
4use crate::{ 6use 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)]
41pub enum AttrKind {
42 Inner,
43 Outer,
44}
45
38impl ast::Attr { 46impl 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
316pub struct SlicePatComponents {
317 pub prefix: Vec<ast::Pat>,
318 pub slice: Option<ast::Pat>,
319 pub suffix: Vec<ast::Pat>,
320}
321
322impl 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
296impl ast::PointerType { 350impl 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])