@@ -19,6 +19,7 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
19
19
use rustc_span:: { sym, Loc , Span , Symbol } ;
20
20
use serde:: { ser:: SerializeStruct , Serialize , Serializer } ;
21
21
use std:: collections:: BinaryHeap ;
22
+ use std:: fmt;
22
23
use std:: fs:: { self , OpenOptions } ;
23
24
use std:: io:: prelude:: * ;
24
25
use std:: path:: Path ;
@@ -41,6 +42,30 @@ const EXCLUDED_LINT_GROUPS: [&str; 1] = ["clippy::internal"];
41
42
/// Collected deprecated lint will be assigned to this group in the JSON output
42
43
const DEPRECATED_LINT_GROUP_STR : & str = "DEPRECATED" ;
43
44
45
+ /// This template will be used to format the configuration section in the lint documentation.
46
+ /// The `configurations` parameter will be replaced with one or multiple formatted
47
+ /// `ClippyConfiguration` instances. See `CONFIGURATION_VALUE_TEMPLATE` for further customizations
48
+ macro_rules! CONFIGURATION_SECTION_TEMPLATE {
49
+ ( ) => {
50
+ r#"
51
+ **Configuration**
52
+ This lint has the following configuration variables:
53
+
54
+ {configurations}
55
+ "#
56
+ } ;
57
+ }
58
+ /// This template will be used to format an individual `ClippyConfiguration` instance in the
59
+ /// lint documentation.
60
+ ///
61
+ /// The format function will provide strings for the following parameters: `name`, `ty`, `doc` and
62
+ /// `default`
63
+ macro_rules! CONFIGURATION_VALUE_TEMPLATE {
64
+ ( ) => {
65
+ "* {name}: {ty}: {doc} (defaults to `{default}`)\n "
66
+ } ;
67
+ }
68
+
44
69
const LINT_EMISSION_FUNCTIONS : [ & [ & str ] ; 7 ] = [
45
70
& [ "clippy_utils" , "diagnostics" , "span_lint" ] ,
46
71
& [ "clippy_utils" , "diagnostics" , "span_lint_and_help" ] ,
@@ -120,6 +145,14 @@ impl MetadataCollector {
120
145
config : collect_configs ( ) ,
121
146
}
122
147
}
148
+
149
+ fn get_lint_configs ( & self , lint_name : & str ) -> Option < String > {
150
+ self . config
151
+ . iter ( )
152
+ . filter_map ( |x| x. lints . iter ( ) . any ( |x| x == lint_name) . then ( || format ! ( "{}" , x) ) )
153
+ . reduce ( |acc, x| acc + & x)
154
+ . map ( |configurations| format ! ( CONFIGURATION_SECTION_TEMPLATE !( ) , configurations = configurations) )
155
+ }
123
156
}
124
157
125
158
impl Drop for MetadataCollector {
@@ -225,6 +258,9 @@ impl Serialize for ApplicabilityInfo {
225
258
}
226
259
}
227
260
261
+ // ==================================================================
262
+ // Configuration
263
+ // ==================================================================
228
264
#[ derive( Debug ) ]
229
265
pub ( crate ) struct ClippyConfigurationBasicInfo {
230
266
pub name : & ' static str ,
@@ -242,9 +278,6 @@ struct ClippyConfiguration {
242
278
default : String ,
243
279
}
244
280
245
- // ==================================================================
246
- // Configuration
247
- // ==================================================================
248
281
fn collect_configs ( ) -> Vec < ClippyConfiguration > {
249
282
let cons = crate :: utils:: conf:: metadata:: get_configuration_metadata ( ) ;
250
283
cons. iter ( )
@@ -297,6 +330,19 @@ fn to_kebab(config_name: &str) -> String {
297
330
config_name. replace ( '_' , "-" )
298
331
}
299
332
333
+ impl fmt:: Display for ClippyConfiguration {
334
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> fmt:: Result {
335
+ write ! (
336
+ f,
337
+ CONFIGURATION_VALUE_TEMPLATE !( ) ,
338
+ name = self . name,
339
+ ty = self . config_type,
340
+ doc = self . doc,
341
+ default = self . default
342
+ )
343
+ }
344
+ }
345
+
300
346
// ==================================================================
301
347
// Lint pass
302
348
// ==================================================================
@@ -321,8 +367,12 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
321
367
if !BLACK_LISTED_LINTS . contains( & lint_name. as_str( ) ) ;
322
368
// metadata extraction
323
369
if let Some ( group) = get_lint_group_or_lint( cx, & lint_name, item) ;
324
- if let Some ( docs) = extract_attr_docs_or_lint( cx, item) ;
370
+ if let Some ( mut docs) = extract_attr_docs_or_lint( cx, item) ;
325
371
then {
372
+ if let Some ( configuration_section) = self . get_lint_configs( & lint_name) {
373
+ docs. push_str( & configuration_section) ;
374
+ }
375
+
326
376
self . lints. push( LintMetadata :: new(
327
377
lint_name,
328
378
SerializableSpan :: from_item( cx, item) ,
0 commit comments