rustc_attr_parsing/attributes/
test_attrs.rs

1use rustc_feature::{AttributeTemplate, template};
2use rustc_hir::attrs::AttributeKind;
3use rustc_hir::lints::AttributeLintKind;
4use rustc_span::{Symbol, sym};
5
6use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
7use crate::context::{AcceptContext, Stage};
8use crate::parser::ArgParser;
9
10pub(crate) struct IgnoreParser;
11
12impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
13    const PATH: &[Symbol] = &[sym::ignore];
14    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
15    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
16    const TEMPLATE: AttributeTemplate = template!(
17        Word, NameValueStr: "reason",
18        "https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute"
19    );
20
21    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
22        Some(AttributeKind::Ignore {
23            span: cx.attr_span,
24            reason: match args {
25                ArgParser::NoArgs => None,
26                ArgParser::NameValue(name_value) => {
27                    let Some(str_value) = name_value.value_as_str() else {
28                        let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
29                            .suggestions(false, "ignore");
30                        let span = cx.attr_span;
31                        cx.emit_lint(
32                            AttributeLintKind::IllFormedAttributeInput { suggestions },
33                            span,
34                        );
35                        return None;
36                    };
37                    Some(str_value)
38                }
39                ArgParser::List(_) => {
40                    let suggestions =
41                        <Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "ignore");
42                    let span = cx.attr_span;
43                    cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
44                    return None;
45                }
46            },
47        })
48    }
49}
50
51pub(crate) struct ShouldPanicParser;
52
53impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser {
54    const PATH: &[Symbol] = &[sym::should_panic];
55    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
56    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
57    const TEMPLATE: AttributeTemplate = template!(
58        Word, List: &[r#"expected = "reason""#], NameValueStr: "reason",
59        "https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute"
60    );
61
62    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
63        Some(AttributeKind::ShouldPanic {
64            span: cx.attr_span,
65            reason: match args {
66                ArgParser::NoArgs => None,
67                ArgParser::NameValue(name_value) => {
68                    let Some(str_value) = name_value.value_as_str() else {
69                        cx.expected_string_literal(
70                            name_value.value_span,
71                            Some(name_value.value_as_lit()),
72                        );
73                        return None;
74                    };
75                    Some(str_value)
76                }
77                ArgParser::List(list) => {
78                    let Some(single) = list.single() else {
79                        cx.expected_single_argument(list.span);
80                        return None;
81                    };
82                    let Some(single) = single.meta_item() else {
83                        cx.expected_name_value(single.span(), Some(sym::expected));
84                        return None;
85                    };
86                    if !single.path().word_is(sym::expected) {
87                        cx.expected_specific_argument_strings(list.span, vec!["expected"]);
88                        return None;
89                    }
90                    let Some(nv) = single.args().name_value() else {
91                        cx.expected_name_value(single.span(), Some(sym::expected));
92                        return None;
93                    };
94                    let Some(expected) = nv.value_as_str() else {
95                        cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
96                        return None;
97                    };
98                    Some(expected)
99                }
100            },
101        })
102    }
103}