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