From 573103b073e4fc4b570719a700bba29e9a8bc15e Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Tue, 23 Jan 2024 23:26:43 +0100 Subject: [PATCH] Support macros (invocations + macro_rules!) So far limited to mod, impl, trait blocks. --- src/parse.rs | 15 +- src/parse_fn.rs | 58 ++++++- src/parse_impl.rs | 18 ++- src/parse_utils.rs | 11 ++ .../venial__tests__parse_impl_inherent.snap | 87 ++++++++++ .../venial__tests__parse_impl_trait.snap | 87 ++++++++++ src/snapshots/venial__tests__parse_mod.snap | 152 ++++++++++++++++++ .../venial__tests__parse_trait_simple.snap | 74 +++++++++ src/tests.rs | 61 +++++++ src/types.rs | 82 +++++++++- src/types_edition.rs | 5 + 11 files changed, 634 insertions(+), 16 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index 6daae94..5f59f7a 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,4 +1,5 @@ use crate::error::Error; +use crate::parse_fn::consume_macro; use crate::parse_impl::{ consume_either_fn_type_const_static_impl, parse_const_or_static, parse_impl, parse_trait, }; @@ -218,13 +219,17 @@ pub fn consume_declaration(tokens: &mut Peekable) -> Result { - panic!( - "cannot parse declaration: expected keyword struct/enum/union/type/trait/impl/mod/default/const/async/unsafe/extern/fn/static, found token {:?}", - token - ); + if let Some(macro_) = consume_macro(tokens, attributes) { + Declaration::Macro(macro_) + } else { + panic!( + "cannot parse declaration: expected keyword struct/enum/union/type/trait/impl/mod/default/const/async/unsafe/extern/fn/static or macro, found token {:?}", + token + ); + } } None => { - panic!("cannot parse type: expected keyword struct/enum/union/type/trait/impl/mod/default/const/async/unsafe/extern/fn/static, found end-of-stream"); + panic!("cannot parse type: expected keyword struct/enum/union/type/trait/impl/mod/default/const/async/unsafe/extern/fn/static or macro, found end-of-stream"); } }; Ok(declaration) diff --git a/src/parse_fn.rs b/src/parse_fn.rs index d9ef8b0..fe39c44 100644 --- a/src/parse_fn.rs +++ b/src/parse_fn.rs @@ -2,14 +2,14 @@ use crate::parse_type::{ consume_declaration_name, consume_field_type, consume_generic_params, consume_where_clause, }; use crate::parse_utils::{ - consume_comma, consume_ident, consume_outer_attributes, consume_punct, consume_stuff_until, - parse_any_ident, parse_punct, + consume_any_ident, consume_comma, consume_ident, consume_outer_attributes, consume_punct, + consume_stuff_until, parse_any_ident, parse_punct, }; use crate::punctuated::Punctuated; use crate::types::{ FnParam, FnQualifiers, FnReceiverParam, FnTypedParam, Function, GroupSpan, TyExpr, }; -use crate::{Attribute, VisMarker}; +use crate::{Attribute, Macro, VisMarker}; use proc_macro2::{Delimiter, Ident, Punct, TokenStream, TokenTree}; use std::iter::Peekable; @@ -118,7 +118,7 @@ fn consume_fn_return(tokens: &mut TokenIter) -> Option<([Punct; 2], TyExpr)> { Some(( [dash, tip], TyExpr { - tokens: (consume_stuff_until( + tokens: consume_stuff_until( tokens, |token| match token { TokenTree::Group(group) if group.delimiter() == Delimiter::Brace => true, @@ -127,7 +127,7 @@ fn consume_fn_return(tokens: &mut TokenIter) -> Option<([Punct; 2], TyExpr)> { _ => false, }, true, - )), + ), }, )) } @@ -187,7 +187,7 @@ pub(crate) fn consume_fn( TokenTree::Group(group) if group.delimiter() == Delimiter::Parenthesis => { (parse_fn_params(group.stream()), GroupSpan::new(&group)) } - _ => panic!("cannot parse function"), + _ => panic!("cannot parse function; missing parameter list"), }; let (tk_return_arrow, return_ty) = if let Some((arrow, ty)) = consume_fn_return(tokens) { @@ -203,7 +203,7 @@ pub(crate) fn consume_fn( (Some(group.clone()), None) } TokenTree::Punct(punct) if punct.as_char() == ';' => (None, Some(punct.clone())), - _ => panic!("cannot parse function"), + _ => panic!("cannot parse function; missing body or `;`"), }; Ok(Function { @@ -222,3 +222,47 @@ pub(crate) fn consume_fn( body: function_body, }) } + +pub(crate) fn consume_macro(tokens: &mut TokenIter, attributes: Vec) -> Option { + // TODO consider multiple-lookahead instead of potentially cloning many tokens + let before_start = tokens.clone(); + + match consume_macro_inner(tokens, attributes) { + Some(macro_) => Some(macro_), + None => { + // rollback iterator, could be start of const declaration + *tokens = before_start; + None + } + } +} + +fn consume_macro_inner(tokens: &mut TokenIter, attributes: Vec) -> Option { + let name = consume_any_ident(tokens)?; + let tk_bang = consume_punct(tokens, '!')?; + let tk_declared_name = consume_any_ident(tokens); + + let (is_paren, macro_body) = match tokens.next().expect("unexpected end of macro") { + TokenTree::Group(group) if group.delimiter() == Delimiter::Parenthesis => (true, group), + TokenTree::Group(group) if group.delimiter() == Delimiter::Brace => (false, group), + _ => panic!("cannot parse macro; missing `{{}}` or `()` group"), + }; + + let inner_tokens = macro_body.stream().into_iter().collect(); + + let tk_semicolon = if is_paren { + Some(parse_punct(tokens, ';', "macro invocation semicolon")) + } else { + None + }; + + Some(Macro { + attributes, + name, + tk_bang, + tk_declared_name, + tk_braces_or_parens: GroupSpan::new(¯o_body), + inner_tokens, + tk_semicolon, + }) +} diff --git a/src/parse_impl.rs b/src/parse_impl.rs index b8932f8..25fc8b2 100644 --- a/src/parse_impl.rs +++ b/src/parse_impl.rs @@ -1,4 +1,4 @@ -use crate::parse_fn::{consume_fn, NotFunction}; +use crate::parse_fn::{consume_fn, consume_macro, NotFunction}; use crate::parse_mod::parse_mod; use crate::parse_type::{consume_bound, consume_generic_params, consume_where_clause}; use crate::parse_utils::{ @@ -9,6 +9,7 @@ use crate::types::{Constant, ImplMember, TyDefinition, ValueExpr}; use crate::types_edition::GroupSpan; use crate::{Attribute, Declaration, Impl, Trait, TraitMember, TyExpr, VisMarker}; use proc_macro2::{Delimiter, Group, TokenTree}; +use quote::ToTokens; use std::iter::Peekable; type TokenIter = Peekable; @@ -149,7 +150,18 @@ pub(crate) fn consume_either_fn_type_const_static_impl( } } } - _ => panic!("unsupported {} item `{}`", context, ident), + ident => { + if let Some(vis_marker) = vis_marker { + panic!( + "unsupported visibility marker `{}`", + vis_marker.to_token_stream().to_string() + ); + } + match consume_macro(tokens, attributes.clone()) { + Some(macro_) => Declaration::Macro(macro_), + None => panic!("unsupported {} item `{}`", context, ident), + } + } } } else { panic!("unsupported {} element: {:?}", context, tokens.peek()) @@ -177,6 +189,7 @@ pub(crate) fn parse_impl_body(token_group: Group) -> (GroupSpan, Vec, Declaration::Function(function) => ImplMember::Method(function), Declaration::Constant(constant) => ImplMember::Constant(constant), Declaration::TyDefinition(ty_def) => ImplMember::AssocTy(ty_def), + Declaration::Macro(macro_) => ImplMember::Macro(macro_), _ => panic!("unsupported impl item `{:?}`", tokens.peek()), }; @@ -279,6 +292,7 @@ pub(crate) fn parse_trait( ImplMember::Method(function) => TraitMember::Method(function), ImplMember::Constant(constant) => TraitMember::Constant(constant), ImplMember::AssocTy(assoc_ty) => TraitMember::AssocTy(assoc_ty), + ImplMember::Macro(macro_) => TraitMember::Macro(macro_), }) .collect(); diff --git a/src/parse_utils.rs b/src/parse_utils.rs index 4e2372f..b8e11dc 100644 --- a/src/parse_utils.rs +++ b/src/parse_utils.rs @@ -33,6 +33,17 @@ pub(crate) fn parse_ident(tokens: &mut TokenIter, expected: &str, panic_context: } } +pub(crate) fn consume_any_ident(tokens: &mut TokenIter) -> Option { + match tokens.peek() { + Some(TokenTree::Ident(ident)) => { + let ident = ident.clone(); + tokens.next(); + Some(ident) + } + _ => None, + } +} + pub(crate) fn consume_ident(tokens: &mut TokenIter, expected: &str) -> Option { match tokens.peek() { Some(TokenTree::Ident(ident)) if ident == expected => { diff --git a/src/snapshots/venial__tests__parse_impl_inherent.snap b/src/snapshots/venial__tests__parse_impl_inherent.snap index 8868ee2..d194930 100644 --- a/src/snapshots/venial__tests__parse_impl_inherent.snap +++ b/src/snapshots/venial__tests__parse_impl_inherent.snap @@ -260,6 +260,93 @@ Impl( }, }, ), + Macro( + Macro { + attributes: [ + Attribute { + tk_hash: Punct { + char: '#', + spacing: Alone, + }, + tk_brackets: [], + path: [ + clippy, + ":", + ":", + allow, + ], + value: Group( + [ + venial, + ], + (), + ), + }, + ], + name: Ident( + fn_macro, + ), + tk_bang: Punct { + char: '!', + spacing: Alone, + }, + tk_declared_name: None, + tk_braces_or_parens: (), + inner_tokens: [ + Ident { + sym: MyTrait, + }, + ], + tk_semicolon: Some( + Punct { + char: ';', + spacing: Alone, + }, + ), + }, + ), + Macro( + Macro { + attributes: [], + name: Ident( + block_macro, + ), + tk_bang: Punct { + char: '!', + spacing: Alone, + }, + tk_declared_name: None, + tk_braces_or_parens: {}, + inner_tokens: [ + Ident { + sym: fn, + }, + Ident { + sym: inner_fn, + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + }, + Punct { + char: '-', + spacing: Joint, + }, + Punct { + char: '>', + spacing: Alone, + }, + Ident { + sym: bool, + }, + Punct { + char: ';', + spacing: Alone, + }, + ], + tk_semicolon: None, + }, + ), ], }, ) diff --git a/src/snapshots/venial__tests__parse_impl_trait.snap b/src/snapshots/venial__tests__parse_impl_trait.snap index 46c1606..7ad5a86 100644 --- a/src/snapshots/venial__tests__parse_impl_trait.snap +++ b/src/snapshots/venial__tests__parse_impl_trait.snap @@ -340,6 +340,93 @@ Impl( }, }, ), + Macro( + Macro { + attributes: [ + Attribute { + tk_hash: Punct { + char: '#', + spacing: Alone, + }, + tk_brackets: [], + path: [ + clippy, + ":", + ":", + allow, + ], + value: Group( + [ + venial, + ], + (), + ), + }, + ], + name: Ident( + fn_macro, + ), + tk_bang: Punct { + char: '!', + spacing: Alone, + }, + tk_declared_name: None, + tk_braces_or_parens: (), + inner_tokens: [ + Ident { + sym: MyTrait, + }, + ], + tk_semicolon: Some( + Punct { + char: ';', + spacing: Alone, + }, + ), + }, + ), + Macro( + Macro { + attributes: [], + name: Ident( + block_macro, + ), + tk_bang: Punct { + char: '!', + spacing: Alone, + }, + tk_declared_name: None, + tk_braces_or_parens: {}, + inner_tokens: [ + Ident { + sym: fn, + }, + Ident { + sym: inner_fn, + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + }, + Punct { + char: '-', + spacing: Joint, + }, + Punct { + char: '>', + spacing: Alone, + }, + Ident { + sym: bool, + }, + Punct { + char: ';', + spacing: Alone, + }, + ], + tk_semicolon: None, + }, + ), ], }, ) diff --git a/src/snapshots/venial__tests__parse_mod.snap b/src/snapshots/venial__tests__parse_mod.snap index 1503c45..1faa483 100644 --- a/src/snapshots/venial__tests__parse_mod.snap +++ b/src/snapshots/venial__tests__parse_mod.snap @@ -621,6 +621,158 @@ Module( members: [], }, ), + Macro( + Macro { + attributes: [], + name: Ident( + decl_macro, + ), + tk_bang: Punct { + char: '!', + spacing: Alone, + }, + tk_declared_name: None, + tk_braces_or_parens: (), + inner_tokens: [ + Ident { + sym: args, + }, + Punct { + char: ',', + spacing: Alone, + }, + Literal { + lit: 32, + }, + Punct { + char: ';', + spacing: Alone, + }, + Punct { + char: '+', + spacing: Alone, + }, + Punct { + char: '*', + spacing: Alone, + }, + ], + tk_semicolon: Some( + Punct { + char: ';', + spacing: Alone, + }, + ), + }, + ), + Macro( + Macro { + attributes: [ + Attribute { + tk_hash: Punct { + char: '#', + spacing: Alone, + }, + tk_brackets: [], + path: [ + macro_export, + ], + value: Empty, + }, + ], + name: Ident( + macro_rules, + ), + tk_bang: Punct { + char: '!', + spacing: Alone, + }, + tk_declared_name: Some( + Ident( + stringificate, + ), + ), + tk_braces_or_parens: {}, + inner_tokens: [ + Group { + delimiter: Parenthesis, + stream: TokenStream [], + }, + Punct { + char: '=', + spacing: Joint, + }, + Punct { + char: '>', + spacing: Alone, + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + lit: "", + }, + ], + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + char: '$', + spacing: Alone, + }, + Ident { + sym: item, + }, + Punct { + char: ':', + spacing: Alone, + }, + Ident { + sym: item, + }, + ], + }, + Punct { + char: '=', + spacing: Joint, + }, + Punct { + char: '>', + spacing: Alone, + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + sym: stringify, + }, + Punct { + char: '!', + spacing: Alone, + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + char: '$', + spacing: Alone, + }, + Ident { + sym: item, + }, + ], + }, + ], + }, + Punct { + char: ';', + spacing: Alone, + }, + ], + tk_semicolon: None, + }, + ), ], }, ) diff --git a/src/snapshots/venial__tests__parse_trait_simple.snap b/src/snapshots/venial__tests__parse_trait_simple.snap index 4c3f23a..157fd38 100644 --- a/src/snapshots/venial__tests__parse_trait_simple.snap +++ b/src/snapshots/venial__tests__parse_trait_simple.snap @@ -275,6 +275,80 @@ Trait( }, }, ), + Macro( + Macro { + attributes: [], + name: Ident( + decl_macro, + ), + tk_bang: Punct { + char: '!', + spacing: Alone, + }, + tk_declared_name: None, + tk_braces_or_parens: (), + inner_tokens: [], + tk_semicolon: Some( + Punct { + char: ';', + spacing: Alone, + }, + ), + }, + ), + Macro( + Macro { + attributes: [], + name: Ident( + python, + ), + tk_bang: Punct { + char: '!', + spacing: Alone, + }, + tk_declared_name: None, + tk_braces_or_parens: {}, + inner_tokens: [ + Ident { + sym: def, + }, + Ident { + sym: hello, + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: b, + }, + ], + }, + Punct { + char: ':', + spacing: Alone, + }, + Ident { + sym: return, + }, + Literal { + lit: "hello world", + }, + Ident { + sym: if, + }, + Ident { + sym: b, + }, + Ident { + sym: else, + }, + Literal { + lit: "bye world", + }, + ], + tk_semicolon: None, + }, + ), ], }, ) diff --git a/src/tests.rs b/src/tests.rs index 45856a6..6feed03 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -595,6 +595,20 @@ fn parse_complex_enum_variant() { assert_debug_snapshot!(enum_type_3); } +#[test] +#[should_panic] // FIXME +fn parse_enum_with_macro() { + let enum_decl = parse_declaration(quote!( + enum Hello { + A = 1, + macroified! { B = 2 }, + macroified!(B; 2), + } + )); + + assert_debug_snapshot!(enum_decl); +} + // ================= // TYPE CORNER CASES // ================= @@ -929,6 +943,22 @@ fn parse_struct_declaration(tokens: TokenStream) -> Struct { } } +#[test] +#[should_panic] // FIXME +fn parse_struct_with_macro() { + let struct_decl = parse_struct_declaration(quote!( + struct Hello { + a: A, + b: B, + transmogrify! { + c: C, + } + } + )); + + assert_quote_snapshot!(struct_decl); +} + #[test] fn add_lifetime() { let basic_type = parse_struct_declaration(quote!( @@ -1089,6 +1119,13 @@ fn parse_impl_inherent() { pub(crate) fn set_value(&mut self, s: String) {} pub const CONSTANT: i8 = 24 + 7; + + #[clippy::allow(venial)] + fn_macro!(MyTrait); + + block_macro! { + fn inner_fn() -> bool; + } } ); @@ -1126,6 +1163,13 @@ fn parse_impl_trait() { const fn set_value(&mut self, s: String) {} const CONSTANT: i8 = 24 + 7; + + #[clippy::allow(venial)] + fn_macro!(MyTrait); + + block_macro! { + fn inner_fn() -> bool; + } } ); @@ -1294,6 +1338,16 @@ fn parse_mod() { #[contain_it] unsafe mod hazard_mod {} + + decl_macro!(args, 32; + *); + + #[macro_export] + macro_rules! stringificate { + () => { "" } + ($item:item) => { + stringify!($item) + }; + } } }; @@ -1319,6 +1373,13 @@ fn parse_trait_simple() { type AssocType: Bound; type TypeWithDefault = Rc>; + + decl_macro!(); + + python! { + def hello(b): + return "hello world" if b else "bye world" + } } }; diff --git a/src/types.rs b/src/types.rs index 1e287fd..c347ddf 100644 --- a/src/types.rs +++ b/src/types.rs @@ -27,16 +27,38 @@ use crate::Punctuated; #[non_exhaustive] #[derive(Clone, Debug)] pub enum Declaration { + /// `struct` declaration. Struct(Struct), + + /// `enum` declaration. Enum(Enum), + + /// `union` declaration. Union(Union), + + /// `mod` declaration (with a `{}` block, or to refer to separate files as in `mod file;`). Module(Module), + + /// `trait` declaration. Trait(Trait), + + /// `impl` block (inherent or trait implementation). Impl(Impl), + + /// `type` declaration. TyDefinition(TyDefinition), + + /// `fn` declaration. Function(Function), + + /// `const` or `static` declaration. Constant(Constant), + + /// `use` statement. Use(UseDeclaration), + + /// Macro invocation. + Macro(Macro), } /// Declaration of a struct. @@ -204,7 +226,7 @@ pub enum TraitMember { Method(Function), Constant(Constant), AssocTy(TyDefinition), - // other items like macro!{...} or macro!(...); invocations + Macro(Macro), } /// Declaration of an `impl` block. @@ -246,7 +268,7 @@ pub enum ImplMember { Method(Function), Constant(Constant), AssocTy(TyDefinition), - // other items like macro!{...} or macro!(...); invocations + Macro(Macro), } /// Constant or static declaration. @@ -665,6 +687,44 @@ pub struct EnumVariantValue { pub value: TokenTree, } +/// A macro invocation or `macro_rules!` declaration. +/// +/// **Example input:** +/// +/// ```no_run +/// # macro_rules! lazy_static { ($($tt:tt)*) => { } }; +/// lazy_static! { +/// /// Some doc comment. +/// static ref EXAMPLE: u8 = 42; +/// } +/// ``` +/// +/// Declarations of declarative macros are also supported; their only syntactical difference is an identifier (here `my_macro`): +/// ```no_run +/// macro_rules! my_macro { +/// ($($tt:tt)*) => { $($tt)* }; +/// } +/// ``` +#[derive(Clone, Debug)] +pub struct Macro { + /// Any attributes, such as `#[macro_export]`. + pub attributes: Vec, + /// Name of the invoked macro. In case of a macro declaration, this is `macro_rules`. + pub name: Ident, + /// The `!` token. + pub tk_bang: Punct, + /// Only set for `macro_rules!` declarations. + /// + /// In `macro_rules! my_macro { ... }`, this is `my_macro`. + pub tk_declared_name: Option, + /// The `{}` or `()` group around the macro invocation. + pub tk_braces_or_parens: GroupSpan, + /// Unparsed tokens in the macro invocation. + pub inner_tokens: Vec, + /// The `;` token, in case `()` is used. + pub tk_semicolon: Option, +} + /// Information about a [`Group`]. This can be used to recreate the group /// from its inner token sequence, or to create a new group with a /// modified token sequence but the original group's span information. @@ -910,6 +970,7 @@ impl ToTokens for Declaration { Declaration::Function(function_decl) => function_decl.to_tokens(tokens), Declaration::Constant(const_decl) => const_decl.to_tokens(tokens), Declaration::Use(use_decl) => use_decl.to_tokens(tokens), + Declaration::Macro(macro_decl) => macro_decl.to_tokens(tokens), } } } @@ -1114,6 +1175,7 @@ impl ToTokens for ImplMember { ImplMember::Method(function) => function.to_tokens(tokens), ImplMember::Constant(constant) => constant.to_tokens(tokens), ImplMember::AssocTy(assoc_ty) => assoc_ty.to_tokens(tokens), + ImplMember::Macro(macro_) => macro_.to_tokens(tokens), } } } @@ -1124,6 +1186,7 @@ impl ToTokens for TraitMember { TraitMember::Method(function) => function.to_tokens(tokens), TraitMember::Constant(constant) => constant.to_tokens(tokens), TraitMember::AssocTy(assoc_ty) => assoc_ty.to_tokens(tokens), + TraitMember::Macro(macro_) => macro_.to_tokens(tokens), } } } @@ -1415,6 +1478,21 @@ impl ToTokens for EnumVariantValue { } } +impl ToTokens for Macro { + fn to_tokens(&self, tokens: &mut TokenStream) { + for attribute in &self.attributes { + attribute.to_tokens(tokens); + } + self.name.to_tokens(tokens); + self.tk_bang.to_tokens(tokens); + self.tk_declared_name.to_tokens(tokens); + self.tk_braces_or_parens.quote_with(tokens, |tokens| { + tokens.extend(self.inner_tokens.iter().cloned()); + }); + self.tk_semicolon.to_tokens(tokens); + } +} + // --- Default impls --- impl Default for GenericParamList { diff --git a/src/types_edition.rs b/src/types_edition.rs index 9328577..606609a 100644 --- a/src/types_edition.rs +++ b/src/types_edition.rs @@ -22,6 +22,7 @@ impl Declaration { Declaration::Function(function_decl) => &function_decl.attributes, Declaration::Constant(const_decl) => &const_decl.attributes, Declaration::Use(use_decl) => &use_decl.attributes, + Declaration::Macro(macro_decl) => ¯o_decl.attributes, } } @@ -38,6 +39,7 @@ impl Declaration { Declaration::Function(function_decl) => &mut function_decl.attributes, Declaration::Constant(const_decl) => &mut const_decl.attributes, Declaration::Use(use_decl) => &mut use_decl.attributes, + Declaration::Macro(macro_decl) => &mut macro_decl.attributes, } } @@ -59,6 +61,7 @@ impl Declaration { Declaration::Function(function_decl) => function_decl.generic_params.as_ref(), Declaration::Constant(_) => None, Declaration::Use(_) => None, + Declaration::Macro(_) => None, } } @@ -80,6 +83,7 @@ impl Declaration { Declaration::Function(function_decl) => function_decl.generic_params.as_mut(), Declaration::Constant(_) => None, Declaration::Use(_) => None, + Declaration::Macro(_) => None, } } @@ -108,6 +112,7 @@ impl Declaration { Declaration::Function(function_decl) => Some(function_decl.name.clone()), Declaration::Constant(const_decl) => Some(const_decl.name.clone()), Declaration::Use(_) => None, + Declaration::Macro(macro_) => Some(macro_.name.clone()), } }