rustc_attr_parsing/attributes/diagnostic/
on_unknown.rs1use rustc_hir::attrs::diagnostic::Directive;
2use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
3
4use crate::attributes::diagnostic::*;
5use crate::attributes::prelude::*;
6
7#[derive(#[automatically_derived]
impl ::core::default::Default for OnUnknownParser {
#[inline]
fn default() -> OnUnknownParser {
OnUnknownParser {
span: ::core::default::Default::default(),
directive: ::core::default::Default::default(),
}
}
}Default)]
8pub(crate) struct OnUnknownParser {
9 span: Option<Span>,
10 directive: Option<(Span, Directive)>,
11}
12
13impl OnUnknownParser {
14 fn parse<'sess, S: Stage>(
15 &mut self,
16 cx: &mut AcceptContext<'_, 'sess, S>,
17 args: &ArgParser,
18 mode: Mode,
19 ) {
20 if !cx.features().diagnostic_on_unknown() {
21 return;
22 }
23 let span = cx.attr_span;
24 self.span = Some(span);
25
26 let items = match args {
27 ArgParser::List(items) if !items.is_empty() => items,
28 ArgParser::NoArgs | ArgParser::List(_) => {
29 cx.emit_lint(
30 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
31 AttributeLintKind::MissingOptionsForOnUnknown,
32 span,
33 );
34 return;
35 }
36 ArgParser::NameValue(_) => {
37 cx.emit_lint(
38 MALFORMED_DIAGNOSTIC_ATTRIBUTES,
39 AttributeLintKind::MalformedOnUnknownAttr { span },
40 span,
41 );
42 return;
43 }
44 };
45
46 if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
47 merge_directives(cx, &mut self.directive, (span, directive));
48 };
49 }
50}
51
52impl<S: Stage> AttributeParser<S> for OnUnknownParser {
53 const ATTRIBUTES: AcceptMapping<Self, S> = &[(
54 &[sym::diagnostic, sym::on_unknown],
55 ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
56 |this, cx, args| {
57 this.parse(cx, args, Mode::DiagnosticOnUnknown);
58 },
59 )];
60 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
62
63 fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
64 if let Some(span) = self.span {
65 Some(AttributeKind::OnUnknown {
66 span,
67 directive: self.directive.map(|d| Box::new(d.1)),
68 })
69 } else {
70 None
71 }
72 }
73}