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));
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)
//! 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,
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,
};
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,
}
}
}