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

@ -13,7 +13,7 @@ pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| {
let derive_attr = nominal
.attrs()
.filter_map(|x| x.as_call())
.filter_map(|x| x.as_simple_call())
.filter(|(name, _arg)| name == "derive")
.map(|(_name, arg)| arg)
.next();

View File

@ -151,7 +151,7 @@ impl LangItems {
fn lang_item_name<T: AttrsOwner>(node: &T) -> Option<SmolStr> {
node.attrs()
.filter_map(|a| a.as_key_value())
.filter_map(|a| a.as_simple_key_value())
.filter(|(key, _)| key == "lang")
.map(|(_, val)| val)
.nth(0)

View File

@ -353,8 +353,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
let name = m.name().map(|it| it.as_name());
let ast_id = self.source_ast_id_map.ast_id(&m);
let export = m.has_atom_attr("macro_export")
|| m.attrs().filter_map(|x| x.as_call()).any(|(name, _)| name == "macro_export");
let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
self.push_item(current_module, RawItem::Macro(m));
@ -385,7 +384,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
fn extract_mod_path_attribute(module: &ast::Module) -> Option<SmolStr> {
module.attrs().into_iter().find_map(|attr| {
attr.as_key_value().and_then(|(name, value)| {
attr.as_simple_key_value().and_then(|(name, value)| {
let is_path = name == "path";
if is_path {
Some(value)

View File

@ -77,7 +77,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
node_range: node.syntax().text_range(),
kind: node.syntax().kind(),
detail,
deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"),
deprecated: node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated"),
})
}

View File

@ -19,7 +19,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.keyword\.unsafe { color: #DFAF8F; }
.keyword\.control { color: #F0DFAF; font-weight: bold; }
</style>
<pre><code><span class="attribute">#</span><span class="attribute">[</span><span class="attribute">derive</span><span class="attribute">(</span><span class="attribute">Clone</span><span class="attribute">,</span><span class="attribute"> </span><span class="attribute">Debug</span><span class="attribute">)</span><span class="attribute">]</span>
<pre><code><span class="attribute">#</span><span class="attribute">[</span><span class="attribute text">derive</span><span class="attribute">(</span><span class="attribute">Clone</span><span class="attribute">,</span><span class="attribute"> </span><span class="attribute">Debug</span><span class="attribute">)</span><span class="attribute">]</span>
<span class="keyword">struct</span> <span class="type">Foo</span> {
<span class="keyword">pub</span> <span class="field">x</span>: <span class="type">i32</span>,
<span class="keyword">pub</span> <span class="field">y</span>: <span class="type">i32</span>,

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

View File

@ -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: [