@@ -19,6 +19,7 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
1919use rustc_span:: { sym, Loc , Span , Symbol } ;
2020use serde:: { ser:: SerializeStruct , Serialize , Serializer } ;
2121use std:: collections:: BinaryHeap ;
22+ use std:: fmt;
2223use std:: fs:: { self , OpenOptions } ;
2324use std:: io:: prelude:: * ;
2425use std:: path:: Path ;
@@ -41,6 +42,30 @@ const EXCLUDED_LINT_GROUPS: [&str; 1] = ["clippy::internal"];
4142/// Collected deprecated lint will be assigned to this group in the JSON output
4243const DEPRECATED_LINT_GROUP_STR : & str = "DEPRECATED" ;
4344
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+
4469const LINT_EMISSION_FUNCTIONS : [ & [ & str ] ; 7 ] = [
4570 & [ "clippy_utils" , "diagnostics" , "span_lint" ] ,
4671 & [ "clippy_utils" , "diagnostics" , "span_lint_and_help" ] ,
@@ -120,6 +145,14 @@ impl MetadataCollector {
120145 config : collect_configs ( ) ,
121146 }
122147 }
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+ }
123156}
124157
125158impl Drop for MetadataCollector {
@@ -225,6 +258,9 @@ impl Serialize for ApplicabilityInfo {
225258 }
226259}
227260
261+ // ==================================================================
262+ // Configuration
263+ // ==================================================================
228264#[ derive( Debug ) ]
229265pub ( crate ) struct ClippyConfigurationBasicInfo {
230266 pub name : & ' static str ,
@@ -242,9 +278,6 @@ struct ClippyConfiguration {
242278 default : String ,
243279}
244280
245- // ==================================================================
246- // Configuration
247- // ==================================================================
248281fn collect_configs ( ) -> Vec < ClippyConfiguration > {
249282 let cons = crate :: utils:: conf:: metadata:: get_configuration_metadata ( ) ;
250283 cons. iter ( )
@@ -297,6 +330,19 @@ fn to_kebab(config_name: &str) -> String {
297330 config_name. replace ( '_' , "-" )
298331}
299332
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+
300346// ==================================================================
301347// Lint pass
302348// ==================================================================
@@ -321,8 +367,12 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
321367 if !BLACK_LISTED_LINTS . contains( & lint_name. as_str( ) ) ;
322368 // metadata extraction
323369 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) ;
325371 then {
372+ if let Some ( configuration_section) = self . get_lint_configs( & lint_name) {
373+ docs. push_str( & configuration_section) ;
374+ }
375+
326376 self . lints. push( LintMetadata :: new(
327377 lint_name,
328378 SerializableSpan :: from_item( cx, item) ,
0 commit comments