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.rs73
1 files changed, 23 insertions, 50 deletions
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 8c5ece65d..cefc00402 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -1,10 +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
6use crate::{ 4use crate::{
7 ast::{self, child_opt, children, AstChildren, AstNode, SyntaxNode}, 5 ast::{self, child_opt, children, AstChildren, AstNode, AttrInput, SyntaxNode},
8 SmolStr, SyntaxElement, 6 SmolStr, SyntaxElement,
9 SyntaxKind::*, 7 SyntaxKind::*,
10 SyntaxToken, T, 8 SyntaxToken, T,
@@ -38,62 +36,37 @@ fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {
38} 36}
39 37
40impl ast::Attr { 38impl ast::Attr {
41 pub fn is_inner(&self) -> bool { 39 pub fn as_simple_atom(&self) -> Option<SmolStr> {
42 let tt = match self.value() { 40 match self.input() {
43 None => return false, 41 None => self.simple_name(),
44 Some(tt) => tt, 42 Some(_) => None,
45 };
46
47 let prev = match tt.syntax().prev_sibling() {
48 None => return false,
49 Some(prev) => prev,
50 };
51
52 prev.kind() == T![!]
53 }
54
55 pub fn as_atom(&self) -> Option<SmolStr> {
56 let tt = self.value()?;
57 let (_bra, attr, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
58 if attr.kind() == IDENT {
59 Some(attr.as_token()?.text().clone())
60 } else {
61 None
62 } 43 }
63 } 44 }
64 45
65 pub fn as_call(&self) -> Option<(SmolStr, ast::TokenTree)> { 46 pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
66 let tt = self.value()?; 47 match self.input() {
67 let (_bra, attr, args, _ket) = tt.syntax().children_with_tokens().collect_tuple()?; 48 Some(AttrInput::TokenTree(tt)) => Some((self.simple_name()?, tt)),
68 let args = ast::TokenTree::cast(args.as_node()?.clone())?; 49 _ => None,
69 if attr.kind() == IDENT {
70 Some((attr.as_token()?.text().clone(), args))
71 } else {
72 None
73 } 50 }
74 } 51 }
75 52
76 pub fn as_named(&self) -> Option<SmolStr> { 53 pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> {
77 let tt = self.value()?; 54 match self.input() {
78 let attr = tt.syntax().children_with_tokens().nth(1)?; 55 Some(AttrInput::Literal(lit)) => {
79 if attr.kind() == IDENT { 56 let key = self.simple_name()?;
80 Some(attr.as_token()?.text().clone()) 57 // FIXME: escape? raw string?
81 } else { 58 let value = lit.syntax().first_token()?.text().trim_matches('"').into();
82 None 59 Some((key, value))
60 }
61 _ => None,
83 } 62 }
84 } 63 }
85 64
86 pub fn as_key_value(&self) -> Option<(SmolStr, SmolStr)> { 65 pub fn simple_name(&self) -> Option<SmolStr> {
87 let tt = self.value()?; 66 let path = self.path()?;
88 let tt_node = tt.syntax(); 67 match (path.segment(), path.qualifier()) {
89 let attr = tt_node.children_with_tokens().nth(1)?; 68 (Some(segment), None) => Some(segment.syntax().first_token()?.text().clone()),
90 if attr.kind() == IDENT { 69 _ => None,
91 let key = attr.as_token()?.text().clone();
92 let val_node = tt_node.children_with_tokens().find(|t| t.kind() == STRING)?;
93 let val = val_node.as_token()?.text().trim_start_matches('"').trim_end_matches('"');
94 Some((key, SmolStr::new(val)))
95 } else {
96 None
97 } 70 }
98 } 71 }
99} 72}