]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_dev/src/update_lints.rs
556b67e0b3742ec1eee0165cf5937b38d8167d9b
[rust.git] / src / tools / clippy / clippy_dev / src / update_lints.rs
1 use crate::{
2     gather_all, gen_changelog_lint_list, gen_deprecated, gen_lint_group_list, gen_modules_list, gen_register_lint_list,
3     replace_region_in_file, Lint, DOCS_LINK,
4 };
5 use std::path::Path;
6
7 #[derive(Clone, Copy, PartialEq)]
8 pub enum UpdateMode {
9     Check,
10     Change,
11 }
12
13 #[allow(clippy::too_many_lines)]
14 pub fn run(update_mode: UpdateMode) {
15     let lint_list: Vec<Lint> = gather_all().collect();
16
17     let internal_lints = Lint::internal_lints(&lint_list);
18     let deprecated_lints = Lint::deprecated_lints(&lint_list);
19     let usable_lints = Lint::usable_lints(&lint_list);
20     let mut sorted_usable_lints = usable_lints.clone();
21     sorted_usable_lints.sort_by_key(|lint| lint.name.clone());
22
23     let usable_lint_count = round_to_fifty(usable_lints.len());
24
25     let mut file_change = replace_region_in_file(
26         Path::new("src/lintlist/mod.rs"),
27         "begin lint list",
28         "end lint list",
29         false,
30         update_mode == UpdateMode::Change,
31         || {
32             format!("vec!{:#?}", sorted_usable_lints)
33                 .lines()
34                 .map(ToString::to_string)
35                 .collect::<Vec<_>>()
36         },
37     )
38     .changed;
39
40     file_change |= replace_region_in_file(
41         Path::new("README.md"),
42         &format!(
43             r#"\[There are over \d+ lints included in this crate!\]\({}\)"#,
44             DOCS_LINK
45         ),
46         "",
47         true,
48         update_mode == UpdateMode::Change,
49         || {
50             vec![format!(
51                 "[There are over {} lints included in this crate!]({})",
52                 usable_lint_count, DOCS_LINK
53             )]
54         },
55     )
56     .changed;
57
58     file_change |= replace_region_in_file(
59         Path::new("CHANGELOG.md"),
60         "<!-- begin autogenerated links to lint list -->",
61         "<!-- end autogenerated links to lint list -->",
62         false,
63         update_mode == UpdateMode::Change,
64         || gen_changelog_lint_list(usable_lints.iter().chain(deprecated_lints.iter())),
65     )
66     .changed;
67
68     file_change |= replace_region_in_file(
69         Path::new("clippy_lints/src/lib.rs"),
70         "begin deprecated lints",
71         "end deprecated lints",
72         false,
73         update_mode == UpdateMode::Change,
74         || gen_deprecated(deprecated_lints.iter()),
75     )
76     .changed;
77
78     file_change |= replace_region_in_file(
79         Path::new("clippy_lints/src/lib.rs"),
80         "begin register lints",
81         "end register lints",
82         false,
83         update_mode == UpdateMode::Change,
84         || gen_register_lint_list(usable_lints.iter().chain(internal_lints.iter())),
85     )
86     .changed;
87
88     file_change |= replace_region_in_file(
89         Path::new("clippy_lints/src/lib.rs"),
90         "begin lints modules",
91         "end lints modules",
92         false,
93         update_mode == UpdateMode::Change,
94         || gen_modules_list(usable_lints.iter()),
95     )
96     .changed;
97
98     // Generate lists of lints in the clippy::all lint group
99     file_change |= replace_region_in_file(
100         Path::new("clippy_lints/src/lib.rs"),
101         r#"store.register_group\(true, "clippy::all""#,
102         r#"\]\);"#,
103         false,
104         update_mode == UpdateMode::Change,
105         || {
106             // clippy::all should only include the following lint groups:
107             let all_group_lints = usable_lints.iter().filter(|l| {
108                 l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf"
109             });
110
111             gen_lint_group_list(all_group_lints)
112         },
113     )
114     .changed;
115
116     // Generate the list of lints for all other lint groups
117     for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) {
118         file_change |= replace_region_in_file(
119             Path::new("clippy_lints/src/lib.rs"),
120             &format!("store.register_group\\(true, \"clippy::{}\"", lint_group),
121             r#"\]\);"#,
122             false,
123             update_mode == UpdateMode::Change,
124             || gen_lint_group_list(lints.iter()),
125         )
126         .changed;
127     }
128
129     if update_mode == UpdateMode::Check && file_change {
130         println!(
131             "Not all lints defined properly. \
132              Please run `cargo dev update_lints` to make sure all lints are defined properly."
133         );
134         std::process::exit(1);
135     }
136 }
137
138 pub fn print_lints() {
139     let lint_list: Vec<Lint> = gather_all().collect();
140     let usable_lints = Lint::usable_lints(&lint_list);
141     let usable_lint_count = usable_lints.len();
142     let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter());
143
144     for (lint_group, mut lints) in grouped_by_lint_group {
145         if lint_group == "Deprecated" {
146             continue;
147         }
148         println!("\n## {}", lint_group);
149
150         lints.sort_by_key(|l| l.name.clone());
151
152         for lint in lints {
153             println!("* [{}]({}#{}) ({})", lint.name, DOCS_LINK, lint.name, lint.desc);
154         }
155     }
156
157     println!("there are {} lints", usable_lint_count);
158 }
159
160 fn round_to_fifty(count: usize) -> usize {
161     count / 50 * 50
162 }