rustc_attr_parsing/
lints.rs

1use std::borrow::Cow;
2
3use rustc_errors::{DiagArgValue, LintEmitter};
4use rustc_hir::Target;
5use rustc_hir::lints::{AttributeLint, AttributeLintKind};
6use rustc_span::sym;
7
8use crate::session_diagnostics;
9
10pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emitter: L) {
11    let AttributeLint { id, span, kind } = lint;
12
13    match kind {
14        &AttributeLintKind::UnusedDuplicate { this, other, warning } => lint_emitter
15            .emit_node_span_lint(
16                rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
17                *id,
18                *span,
19                session_diagnostics::UnusedDuplicate { this, other, warning },
20            ),
21        AttributeLintKind::IllFormedAttributeInput { suggestions } => {
22            lint_emitter.emit_node_span_lint(
23                rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT,
24                *id,
25                *span,
26                session_diagnostics::IllFormedAttributeInput {
27                    num_suggestions: suggestions.len(),
28                    suggestions: DiagArgValue::StrListSepByAnd(
29                        suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
30                    ),
31                },
32            );
33        }
34        AttributeLintKind::InvalidMacroExportArguments { suggestions } => lint_emitter
35            .emit_node_span_lint(
36                rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS,
37                *id,
38                *span,
39                session_diagnostics::IllFormedAttributeInput {
40                    num_suggestions: suggestions.len(),
41                    suggestions: DiagArgValue::StrListSepByAnd(
42                        suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
43                    ),
44                },
45            ),
46        AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => {
47            lint_emitter.emit_node_span_lint(
48                rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
49                *id,
50                *first_span,
51                session_diagnostics::EmptyAttributeList {
52                    attr_span: *first_span,
53                    attr_path: attr_path.clone(),
54                    valid_without_list: *valid_without_list,
55                },
56            )
57        }
58        AttributeLintKind::InvalidTarget { name, target, applied, only } => lint_emitter
59            .emit_node_span_lint(
60                // This check is here because `deprecated` had its own lint group and removing this would be a breaking change
61                if name.segments[0].name == sym::deprecated
62                    && ![
63                        Target::Closure,
64                        Target::Expression,
65                        Target::Statement,
66                        Target::Arm,
67                        Target::MacroCall,
68                    ]
69                    .contains(target)
70                {
71                    rustc_session::lint::builtin::USELESS_DEPRECATED
72                } else {
73                    rustc_session::lint::builtin::UNUSED_ATTRIBUTES
74                },
75                *id,
76                *span,
77                session_diagnostics::InvalidTargetLint {
78                    name: name.clone(),
79                    target: target.plural_name(),
80                    applied: DiagArgValue::StrListSepByAnd(
81                        applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
82                    ),
83                    only,
84                    attr_span: *span,
85                },
86            ),
87
88        &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => {
89            lint_emitter.emit_node_span_lint(
90                rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
91                *id,
92                *span,
93                session_diagnostics::InvalidAttrStyle {
94                    name: name.clone(),
95                    is_used_as_inner,
96                    target_span: (!is_used_as_inner).then_some(target_span),
97                    target,
98                },
99            )
100        }
101    }
102}