]>
Commit | Line | Data |
---|---|---|
1 | //! Implementation of the `#[cfg_accessible(path)]` attribute macro. | |
2 | ||
3 | use rustc_ast as ast; | |
4 | use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; | |
5 | use rustc_feature::AttributeTemplate; | |
6 | use rustc_parse::validate_attr; | |
7 | use rustc_span::symbol::sym; | |
8 | use rustc_span::Span; | |
9 | ||
10 | pub(crate) struct Expander; | |
11 | ||
12 | fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> { | |
13 | match mi.meta_item_list() { | |
14 | None => {} | |
15 | Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"), | |
16 | Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"), | |
17 | Some([nmi]) => match nmi.meta_item() { | |
18 | None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"), | |
19 | Some(mi) => { | |
20 | if !mi.is_word() { | |
21 | ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments"); | |
22 | } | |
23 | return Some(&mi.path); | |
24 | } | |
25 | }, | |
26 | } | |
27 | None | |
28 | } | |
29 | ||
30 | impl MultiItemModifier for Expander { | |
31 | fn expand( | |
32 | &self, | |
33 | ecx: &mut ExtCtxt<'_>, | |
34 | span: Span, | |
35 | meta_item: &ast::MetaItem, | |
36 | item: Annotatable, | |
37 | _is_derive_const: bool, | |
38 | ) -> ExpandResult<Vec<Annotatable>, Annotatable> { | |
39 | let template = AttributeTemplate { list: Some("path"), ..Default::default() }; | |
40 | validate_attr::check_builtin_meta_item( | |
41 | &ecx.sess.parse_sess, | |
42 | &meta_item, | |
43 | ast::AttrStyle::Outer, | |
44 | sym::cfg_accessible, | |
45 | template, | |
46 | ); | |
47 | ||
48 | let Some(path) = validate_input(ecx, meta_item) else { | |
49 | return ExpandResult::Ready(Vec::new()); | |
50 | }; | |
51 | ||
52 | match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) { | |
53 | Ok(true) => ExpandResult::Ready(vec![item]), | |
54 | Ok(false) => ExpandResult::Ready(Vec::new()), | |
55 | Err(Indeterminate) if ecx.force_mode => { | |
56 | ecx.span_err(span, "cannot determine whether the path is accessible or not"); | |
57 | ExpandResult::Ready(vec![item]) | |
58 | } | |
59 | Err(Indeterminate) => ExpandResult::Retry(item), | |
60 | } | |
61 | } | |
62 | } |