|  | 
|  | 1 | +use rustc_ast::AttrStyle; | 
| 1 | 2 | use rustc_errors::DiagArgValue; | 
| 2 | 3 | use rustc_hir::attrs::MacroUseArgs; | 
| 3 | 4 | 
 | 
| @@ -133,3 +134,65 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser { | 
| 133 | 134 |  ]); | 
| 134 | 135 |  const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); | 
| 135 | 136 | } | 
|  | 137 | + | 
|  | 138 | +pub(crate) struct MacroExportParser; | 
|  | 139 | + | 
|  | 140 | +impl<S: Stage> SingleAttributeParser<S> for MacroExportParser { | 
|  | 141 | + const PATH: &[Symbol] = &[sym::macro_export]; | 
|  | 142 | + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; | 
|  | 143 | + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; | 
|  | 144 | + const TEMPLATE: AttributeTemplate = template!(Word, List: &["local_inner_macros"]); | 
|  | 145 | + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ | 
|  | 146 | + Allow(Target::MacroDef), | 
|  | 147 | + Error(Target::WherePredicate), | 
|  | 148 | + Error(Target::Crate), | 
|  | 149 | + ]); | 
|  | 150 | + | 
|  | 151 | + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { | 
|  | 152 | + let suggestions = || { | 
|  | 153 | + <Self as SingleAttributeParser<S>>::TEMPLATE | 
|  | 154 | + .suggestions(AttrStyle::Inner, "macro_export") | 
|  | 155 | + }; | 
|  | 156 | + let local_inner_macros = match args { | 
|  | 157 | + ArgParser::NoArgs => false, | 
|  | 158 | + ArgParser::List(list) => { | 
|  | 159 | + let Some(l) = list.single() else { | 
|  | 160 | + let span = cx.attr_span; | 
|  | 161 | + cx.emit_lint( | 
|  | 162 | + AttributeLintKind::InvalidMacroExportArguments { | 
|  | 163 | + suggestions: suggestions(), | 
|  | 164 | + }, | 
|  | 165 | + span, | 
|  | 166 | + ); | 
|  | 167 | + return None; | 
|  | 168 | + }; | 
|  | 169 | + match l.meta_item().and_then(|i| i.path().word_sym()) { | 
|  | 170 | + Some(sym::local_inner_macros) => true, | 
|  | 171 | + _ => { | 
|  | 172 | + let span = cx.attr_span; | 
|  | 173 | + cx.emit_lint( | 
|  | 174 | + AttributeLintKind::InvalidMacroExportArguments { | 
|  | 175 | + suggestions: suggestions(), | 
|  | 176 | + }, | 
|  | 177 | + span, | 
|  | 178 | + ); | 
|  | 179 | + return None; | 
|  | 180 | + } | 
|  | 181 | + } | 
|  | 182 | + } | 
|  | 183 | + ArgParser::NameValue(_) => { | 
|  | 184 | + let span = cx.attr_span; | 
|  | 185 | + let suggestions = suggestions(); | 
|  | 186 | + cx.emit_err(IllFormedAttributeInputLint { | 
|  | 187 | + num_suggestions: suggestions.len(), | 
|  | 188 | + suggestions: DiagArgValue::StrListSepByAnd( | 
|  | 189 | + suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), | 
|  | 190 | + ), | 
|  | 191 | + span, | 
|  | 192 | + }); | 
|  | 193 | + return None; | 
|  | 194 | + } | 
|  | 195 | + }; | 
|  | 196 | + Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros }) | 
|  | 197 | + } | 
|  | 198 | +} | 
0 commit comments