1use std::any::Any;
2use std::borrow::Cow;
3
4use rustc_data_structures::sync::DynSend;
5use rustc_errors::{Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, Level};
6use rustc_hir::lints::{AttributeLintKind, FormatWarning};
7use rustc_middle::ty::TyCtxt;
8use rustc_session::Session;
9
10use crate::lints;
11
12mod check_cfg;
13
14pub struct DiagAndSess<'sess> {
15 pub callback: Box<
16 dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level, &dyn Any) -> Diag<'b, ()> + DynSend + 'static,
17 >,
18 pub sess: &'sess Session,
19}
20
21impl<'a> Diagnostic<'a, ()> for DiagAndSess<'_> {
22 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
23 (self.callback)(dcx, level, self.sess)
24 }
25}
26
27pub struct DecorateAttrLint<'a, 'sess, 'tcx> {
30 pub sess: &'sess Session,
31 pub tcx: Option<TyCtxt<'tcx>>,
32 pub diagnostic: &'a AttributeLintKind,
33}
34
35impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> {
36 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
37 match self.diagnostic {
38 AttributeLintKind::IllFormedAttributeInput { suggestions, docs, help } => {
39 lints::IllFormedAttributeInput {
40 num_suggestions: suggestions.len(),
41 suggestions: DiagArgValue::StrListSepByAnd(
42 suggestions.into_iter().map(|s| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", s))
})format!("`{s}`").into()).collect(),
43 ),
44 has_docs: docs.is_some(),
45 docs: docs.unwrap_or(""),
46 help: help.clone().map(|h| lints::IllFormedAttributeInputHelp { lint: h }),
47 }
48 .into_diag(dcx, level)
49 }
50 AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => {
51 lints::EmptyAttributeList {
52 attr_span: *first_span,
53 attr_path: attr_path.clone(),
54 valid_without_list: *valid_without_list,
55 }
56 .into_diag(dcx, level)
57 }
58 AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => {
59 lints::InvalidTargetLint {
60 name: name.clone(),
61 target,
62 applied: DiagArgValue::StrListSepByAnd(
63 applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
64 ),
65 only,
66 attr_span: *attr_span,
67 }
68 .into_diag(dcx, level)
69 }
70 &AttributeLintKind::InvalidStyle {
71 ref name,
72 is_used_as_inner,
73 target,
74 target_span,
75 } => lints::InvalidAttrStyle {
76 name: name.clone(),
77 is_used_as_inner,
78 target_span: (!is_used_as_inner).then_some(target_span),
79 target,
80 }
81 .into_diag(dcx, level),
82 &AttributeLintKind::UnexpectedCfgName(name, value) => {
83 check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
84 .into_diag(dcx, level)
85 }
86 &AttributeLintKind::UnexpectedCfgValue(name, value) => {
87 check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value)
88 .into_diag(dcx, level)
89 }
90 &AttributeLintKind::DuplicateDocAlias { first_definition } => {
91 lints::DocAliasDuplicated { first_defn: first_definition }.into_diag(dcx, level)
92 }
93
94 &AttributeLintKind::DocAutoCfgExpectsHideOrShow => {
95 lints::DocAutoCfgExpectsHideOrShow.into_diag(dcx, level)
96 }
97
98 &AttributeLintKind::AmbiguousDeriveHelpers => {
99 lints::AmbiguousDeriveHelpers.into_diag(dcx, level)
100 }
101
102 &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => {
103 lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.into_diag(dcx, level)
104 }
105
106 &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => {
107 lints::DocAutoCfgHideShowExpectsList { attr_name }.into_diag(dcx, level)
108 }
109
110 &AttributeLintKind::DocInvalid => lints::DocInvalid.into_diag(dcx, level),
111
112 &AttributeLintKind::DocUnknownInclude { span, inner, value } => {
113 lints::DocUnknownInclude {
114 inner,
115 value,
116 sugg: (span, Applicability::MaybeIncorrect),
117 }
118 .into_diag(dcx, level)
119 }
120
121 &AttributeLintKind::DocUnknownSpotlight { span } => {
122 lints::DocUnknownSpotlight { sugg_span: span }.into_diag(dcx, level)
123 }
124
125 &AttributeLintKind::DocUnknownPasses { name, span } => {
126 lints::DocUnknownPasses { name, note_span: span }.into_diag(dcx, level)
127 }
128
129 &AttributeLintKind::DocUnknownPlugins { span } => {
130 lints::DocUnknownPlugins { label_span: span }.into_diag(dcx, level)
131 }
132
133 &AttributeLintKind::DocUnknownAny { name } => {
134 lints::DocUnknownAny { name }.into_diag(dcx, level)
135 }
136
137 &AttributeLintKind::DocAutoCfgWrongLiteral => {
138 lints::DocAutoCfgWrongLiteral.into_diag(dcx, level)
139 }
140
141 &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.into_diag(dcx, level),
142
143 &AttributeLintKind::DocTestUnknown { name } => {
144 lints::DocTestUnknown { name }.into_diag(dcx, level)
145 }
146
147 &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.into_diag(dcx, level),
148
149 &AttributeLintKind::AttrCrateLevelOnly => {
150 lints::AttrCrateLevelOnly.into_diag(dcx, level)
151 }
152
153 &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => {
154 lints::DoNotRecommendDoesNotExpectArgs.into_diag(dcx, level)
155 }
156
157 &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes {
158 sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }),
159 }
160 .into_diag(dcx, level),
161
162 &AttributeLintKind::MalformedDoc => lints::MalformedDoc.into_diag(dcx, level),
163
164 &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.into_diag(dcx, level),
165
166 &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.into_diag(dcx, level),
167 &AttributeLintKind::MalFormedDiagnosticAttribute { attribute, options, span } => {
168 lints::MalFormedDiagnosticAttributeLint { attribute, options, span }
169 .into_diag(dcx, level)
170 }
171
172 AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning {
173 FormatWarning::PositionalArgument { .. } => {
174 lints::DisallowedPositionalArgument.into_diag(dcx, level)
175 }
176 FormatWarning::InvalidSpecifier { .. } => {
177 lints::InvalidFormatSpecifier.into_diag(dcx, level)
178 }
179 FormatWarning::DisallowedPlaceholder { .. } => {
180 lints::DisallowedPlaceholder.into_diag(dcx, level)
181 }
182 },
183 AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => {
184 lints::WrappedParserError { description, label, span: *span }.into_diag(dcx, level)
185 }
186 &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => {
187 lints::IgnoredDiagnosticOption { option_name, first_span, later_span }
188 .into_diag(dcx, level)
189 }
190 &AttributeLintKind::MissingOptionsForDiagnosticAttribute { attribute, options } => {
191 lints::MissingOptionsForDiagnosticAttribute { attribute, options }
192 .into_diag(dcx, level)
193 }
194 &AttributeLintKind::NonMetaItemDiagnosticAttribute => {
195 lints::NonMetaItemDiagnosticAttribute.into_diag(dcx, level)
196 }
197 }
198 }
199}