@@ -2,10 +2,14 @@ use rustc_errors::DiagArgValue;
22use rustc_feature:: { AttributeTemplate , template} ;
33use rustc_hir:: Target ;
44use rustc_hir:: attrs:: { AttributeKind , MacroUseArgs } ;
5+ use rustc_hir:: lints:: AttributeLintKind ;
56use rustc_span:: { Span , Symbol , sym} ;
67use thin_vec:: ThinVec ;
78
8- use crate :: attributes:: { AcceptMapping , AttributeParser , NoArgsAttributeParser , OnDuplicate } ;
9+ use crate :: attributes:: {
10+ AcceptMapping , AttributeOrder , AttributeParser , NoArgsAttributeParser , OnDuplicate ,
11+ SingleAttributeParser ,
12+ } ;
913use crate :: context:: MaybeWarn :: { Allow , Error , Warn } ;
1014use crate :: context:: { AcceptContext , AllowedTargets , FinalizeContext , Stage } ;
1115use crate :: parser:: ArgParser ;
@@ -139,3 +143,63 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
139143 ] ) ;
140144 const CREATE : fn ( Span ) -> AttributeKind = |span| AttributeKind :: AllowInternalUnsafe ( span) ;
141145}
146+
147+ pub ( crate ) struct MacroExportParser ;
148+
149+ impl < S : Stage > SingleAttributeParser < S > for crate :: attributes:: macro_attrs:: MacroExportParser {
150+ const PATH : & [ Symbol ] = & [ sym:: macro_export] ;
151+ const ATTRIBUTE_ORDER : AttributeOrder = AttributeOrder :: KeepOutermost ;
152+ const ON_DUPLICATE : OnDuplicate < S > = OnDuplicate :: Warn ;
153+ const TEMPLATE : AttributeTemplate = template ! ( Word , List : & [ "local_inner_macros" ] ) ;
154+ const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowListWarnRest ( & [
155+ Allow ( Target :: MacroDef ) ,
156+ Error ( Target :: WherePredicate ) ,
157+ Error ( Target :: Crate ) ,
158+ ] ) ;
159+
160+ fn convert ( cx : & mut AcceptContext < ' _ , ' _ , S > , args : & ArgParser < ' _ > ) -> Option < AttributeKind > {
161+ let suggestions =
162+ || <Self as SingleAttributeParser < S > >:: TEMPLATE . suggestions ( false , "macro_export" ) ;
163+ let local_inner_macros = match args {
164+ ArgParser :: NoArgs => false ,
165+ ArgParser :: List ( list) => {
166+ let Some ( l) = list. single ( ) else {
167+ let span = cx. attr_span ;
168+ cx. emit_lint (
169+ AttributeLintKind :: InvalidMacroExportArguments {
170+ suggestions : suggestions ( ) ,
171+ } ,
172+ span,
173+ ) ;
174+ return None ;
175+ } ;
176+ match l. meta_item ( ) . and_then ( |i| i. path ( ) . word_sym ( ) ) {
177+ Some ( sym:: local_inner_macros) => true ,
178+ _ => {
179+ let span = cx. attr_span ;
180+ cx. emit_lint (
181+ AttributeLintKind :: InvalidMacroExportArguments {
182+ suggestions : suggestions ( ) ,
183+ } ,
184+ span,
185+ ) ;
186+ return None ;
187+ }
188+ }
189+ }
190+ ArgParser :: NameValue ( _) => {
191+ let span = cx. attr_span ;
192+ let suggestions = suggestions ( ) ;
193+ cx. emit_err ( session_diagnostics:: IllFormedAttributeInputLint {
194+ num_suggestions : suggestions. len ( ) ,
195+ suggestions : DiagArgValue :: StrListSepByAnd (
196+ suggestions. into_iter ( ) . map ( |s| format ! ( "`{s}`" ) . into ( ) ) . collect ( ) ,
197+ ) ,
198+ span,
199+ } ) ;
200+ return None ;
201+ }
202+ } ;
203+ Some ( AttributeKind :: MacroExport { span : cx. attr_span , local_inner_macros } )
204+ }
205+ }
0 commit comments