From 71efdaa6364142b359c59659ec10f35a1e53b5d2 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Mon, 30 Sep 2019 04:44:33 +0800 Subject: Parse correct AttrInput --- crates/ra_syntax/src/ast/generated.rs | 44 +++++++++++++++++++++++++++++++++++ crates/ra_syntax/src/grammar.ron | 3 ++- 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'crates/ra_syntax/src') diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index dc1f8c82c..408449fd6 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -166,11 +166,55 @@ impl AstNode for Attr { } } impl Attr { + pub fn path(&self) -> Option { + AstChildren::new(&self.syntax).next() + } + pub fn input(&self) -> Option { + AstChildren::new(&self.syntax).next() + } pub fn value(&self) -> Option { AstChildren::new(&self.syntax).next() } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum AttrInput { + Literal(Literal), + TokenTree(TokenTree), +} +impl From for AttrInput { + fn from(node: Literal) -> AttrInput { + AttrInput::Literal(node) + } +} +impl From for AttrInput { + fn from(node: TokenTree) -> AttrInput { + AttrInput::TokenTree(node) + } +} +impl AstNode for AttrInput { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + LITERAL | TOKEN_TREE => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + LITERAL => AttrInput::Literal(Literal { syntax }), + TOKEN_TREE => AttrInput::TokenTree(TokenTree { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + AttrInput::Literal(it) => &it.syntax, + AttrInput::TokenTree(it) => &it.syntax, + } + } +} +impl AttrInput {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AwaitExpr { pub(crate) syntax: SyntaxNode, } diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 5f395501a..8cb45f394 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -576,7 +576,8 @@ Grammar( traits: [ "NameOwner", "AttrsOwner","DocCommentsOwner" ], options: [ "TokenTree", "Path" ], ), - "Attr": ( options: [ ["value", "TokenTree"] ] ), + "AttrInput": ( enum: [ "Literal", "TokenTree" ] ), + "Attr": ( options: [ "Path", [ "input", "AttrInput" ], [ "value", "TokenTree" ] ] ), "TokenTree": (), "TypeParamList": ( collections: [ -- cgit v1.2.3 From 5a4b4f507e9b90bfe41b451763868cba0a70c392 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Mon, 30 Sep 2019 05:15:03 +0800 Subject: Fix API of Attr --- crates/ra_syntax/src/ast/extensions.rs | 66 +++++++++++++--------------------- crates/ra_syntax/src/ast/generated.rs | 3 -- crates/ra_syntax/src/ast/traits.rs | 2 +- crates/ra_syntax/src/grammar.ron | 2 +- 4 files changed, 26 insertions(+), 47 deletions(-) (limited to 'crates/ra_syntax/src') diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index 8c5ece65d..a7b886457 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -1,10 +1,8 @@ //! Various extension methods to ast Nodes, which are hard to code-generate. //! Extensions for various expressions live in a sibling `expr_extensions` module. -use itertools::Itertools; - use crate::{ - ast::{self, child_opt, children, AstChildren, AstNode, SyntaxNode}, + ast::{self, child_opt, children, AstChildren, AstNode, AttrInput, SyntaxNode}, SmolStr, SyntaxElement, SyntaxKind::*, SyntaxToken, T, @@ -39,12 +37,7 @@ fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { impl ast::Attr { pub fn is_inner(&self) -> bool { - let tt = match self.value() { - None => return false, - Some(tt) => tt, - }; - - let prev = match tt.syntax().prev_sibling() { + let prev = match self.syntax().prev_sibling() { None => return false, Some(prev) => prev, }; @@ -52,48 +45,37 @@ impl ast::Attr { prev.kind() == T![!] } - pub fn as_atom(&self) -> Option { - let tt = self.value()?; - let (_bra, attr, _ket) = tt.syntax().children_with_tokens().collect_tuple()?; - if attr.kind() == IDENT { - Some(attr.as_token()?.text().clone()) - } else { - None + pub fn as_simple_atom(&self) -> Option { + match self.input() { + None => self.simple_name(), + Some(_) => None, } } - pub fn as_call(&self) -> Option<(SmolStr, ast::TokenTree)> { - let tt = self.value()?; - let (_bra, attr, args, _ket) = tt.syntax().children_with_tokens().collect_tuple()?; - let args = ast::TokenTree::cast(args.as_node()?.clone())?; - if attr.kind() == IDENT { - Some((attr.as_token()?.text().clone(), args)) - } else { - None + pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> { + match self.input() { + Some(AttrInput::TokenTree(tt)) => Some((self.simple_name()?, tt)), + _ => None, } } - pub fn as_named(&self) -> Option { - let tt = self.value()?; - let attr = tt.syntax().children_with_tokens().nth(1)?; - if attr.kind() == IDENT { - Some(attr.as_token()?.text().clone()) - } else { - None + pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> { + match self.input() { + Some(AttrInput::Literal(lit)) => { + let key = self.simple_name()?; + // FIXME: escape? raw string? + let value = lit.syntax().first_token()?.text().trim_matches('"').into(); + Some((key, value)) + } + _ => None, } } - pub fn as_key_value(&self) -> Option<(SmolStr, SmolStr)> { - let tt = self.value()?; - let tt_node = tt.syntax(); - let attr = tt_node.children_with_tokens().nth(1)?; - if attr.kind() == IDENT { - let key = attr.as_token()?.text().clone(); - let val_node = tt_node.children_with_tokens().find(|t| t.kind() == STRING)?; - let val = val_node.as_token()?.text().trim_start_matches('"').trim_end_matches('"'); - Some((key, SmolStr::new(val))) - } else { - None + pub fn simple_name(&self) -> Option { + let path = self.path()?; + match (path.segment(), path.qualifier()) { + (Some(segment), None) => Some(segment.syntax().first_token()?.text().clone()), + _ => None, } } } diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 408449fd6..aaf03ce3f 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -172,9 +172,6 @@ impl Attr { pub fn input(&self) -> Option { AstChildren::new(&self.syntax).next() } - pub fn value(&self) -> Option { - AstChildren::new(&self.syntax).next() - } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AttrInput { diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index c3e676d4c..f275a4955 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs @@ -99,7 +99,7 @@ pub trait AttrsOwner: AstNode { children(self) } fn has_atom_attr(&self, atom: &str) -> bool { - self.attrs().filter_map(|x| x.as_atom()).any(|x| x == atom) + self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom) } } diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 8cb45f394..30328f59f 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -577,7 +577,7 @@ Grammar( options: [ "TokenTree", "Path" ], ), "AttrInput": ( enum: [ "Literal", "TokenTree" ] ), - "Attr": ( options: [ "Path", [ "input", "AttrInput" ], [ "value", "TokenTree" ] ] ), + "Attr": ( options: [ "Path", [ "input", "AttrInput" ] ] ), "TokenTree": (), "TypeParamList": ( collections: [ -- cgit v1.2.3 From f7e12559cb26b59a9a2ecee4deecaf6fe9100d16 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Mon, 30 Sep 2019 16:09:02 +0800 Subject: Fixes --- crates/ra_syntax/src/ast/extensions.rs | 9 --------- 1 file changed, 9 deletions(-) (limited to 'crates/ra_syntax/src') diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index a7b886457..cefc00402 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -36,15 +36,6 @@ fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { } impl ast::Attr { - pub fn is_inner(&self) -> bool { - let prev = match self.syntax().prev_sibling() { - None => return false, - Some(prev) => prev, - }; - - prev.kind() == T![!] - } - pub fn as_simple_atom(&self) -> Option { match self.input() { None => self.simple_name(), -- cgit v1.2.3