mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Fix API of Attr
This commit is contained in:
parent
71efdaa636
commit
5a4b4f507e
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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"),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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>,
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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: [
|
||||
|
Loading…
x
Reference in New Issue
Block a user