Fix API of Attr

This commit is contained in:
uHOOCCOOHu 2019-09-30 05:15:03 +08:00
parent 71efdaa636
commit 5a4b4f507e
No known key found for this signature in database
GPG key ID: CED392DE0C483D00
9 changed files with 32 additions and 54 deletions

View file

@ -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<SmolStr> {
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<SmolStr> {
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<SmolStr> {
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<SmolStr> {
let path = self.path()?;
match (path.segment(), path.qualifier()) {
(Some(segment), None) => Some(segment.syntax().first_token()?.text().clone()),
_ => None,
}
}
}

View file

@ -172,9 +172,6 @@ impl Attr {
pub fn input(&self) -> Option<AttrInput> {
AstChildren::new(&self.syntax).next()
}
pub fn value(&self) -> Option<TokenTree> {
AstChildren::new(&self.syntax).next()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum AttrInput {

View file

@ -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)
}
}