Skip to content

Commit 489bded

Browse files
committed
WIP: update_lints.py RIIR
1 parent eb2cfe6 commit 489bded

File tree

2 files changed

+218
-2
lines changed

2 files changed

+218
-2
lines changed

clippy_dev/src/lib.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ impl Lint {
5454
pub fn by_lint_group(lints: &[Self]) -> HashMap<String, Vec<Self>> {
5555
lints.iter().map(|lint| (lint.group.to_string(), lint.clone())).into_group_map()
5656
}
57+
58+
/// Generates `pub mod module_name` for the lints in the given `group`
59+
pub fn gen_pub_mod_for_group(lints: &[Lint]) -> Vec<String> {
60+
lints.into_iter().map(|l| format!("pub mod {};", l.module)).collect::<Vec<String>>()
61+
}
62+
63+
pub fn gen_lint_group(lints: &[Lint]) -> Vec<String> {
64+
lints.into_iter().map(|l| format!(" {}::{},", l.module, l.name.to_uppercase())).collect::<Vec<String>>()
65+
}
5766
}
5867

5968
pub fn gather_all() -> impl Iterator<Item=Lint> {
@@ -86,6 +95,67 @@ fn lint_files() -> impl Iterator<Item=fs::DirEntry> {
8695
.filter(|f| f.path().extension() == Some(OsStr::new("rs")))
8796
}
8897

98+
99+
pub fn clippy_version_from_toml() -> String {
100+
let mut file = fs::File::open("../Cargo.toml").unwrap();
101+
let mut content = String::new();
102+
file.read_to_string(&mut content).unwrap();
103+
let version_line = content.lines().find(|l| l.starts_with("version ="));
104+
if let Some(version_line) = version_line {
105+
let split = version_line.split(" ").collect::<Vec<&str>>();
106+
split[2].trim_matches('"').to_string()
107+
} else {
108+
panic!("Error: version not found in Cargo.toml!");
109+
}
110+
}
111+
112+
pub fn replace_region_in_file<F>(path: &str, start: &str, end: &str, replace_start: bool, replacements: F) where F: Fn() -> Vec<String> {
113+
let mut f = fs::File::open(path).expect(&format!("File not found: {}", path));
114+
let mut contents = String::new();
115+
f.read_to_string(&mut contents).expect("Something went wrong reading the file");
116+
let replaced = replace_region_in_text(&contents, start, end, replace_start, replacements);
117+
118+
let mut f = fs::File::create(path).expect(&format!("File not found: {}", path));
119+
f.write_all(replaced.as_bytes()).expect("Unable to write file");
120+
}
121+
122+
// Replace a region in a file delimited by two lines matching regexes.
123+
//
124+
// A callback is called to write the new region.
125+
// If `replace_start` is true, the start delimiter line is replaced as well.
126+
// The end delimiter line is never replaced.
127+
pub fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> String where F: Fn() -> Vec<String> {
128+
let lines = text.lines();
129+
let mut in_old_region = false;
130+
let mut found = false;
131+
let mut new_lines = vec![];
132+
let start = Regex::new(start).unwrap();
133+
let end = Regex::new(end).unwrap();
134+
135+
for line in lines {
136+
if in_old_region {
137+
if end.is_match(&line) {
138+
in_old_region = false;
139+
new_lines.extend(replacements());
140+
new_lines.push(line.to_string());
141+
}
142+
} else if start.is_match(&line) {
143+
if !replace_start {
144+
new_lines.push(line.to_string());
145+
}
146+
in_old_region = true;
147+
found = true;
148+
} else {
149+
new_lines.push(line.to_string());
150+
}
151+
}
152+
153+
if !found {
154+
println!("regex {:?} not found", start);
155+
}
156+
new_lines.join("\n")
157+
}
158+
89159
#[test]
90160
fn test_parse_contents() {
91161
let result: Vec<Lint> = parse_contents(
@@ -125,6 +195,44 @@ declare_deprecated_lint! {
125195
assert_eq!(expected, result);
126196
}
127197

198+
199+
#[test]
200+
fn test_replace_region() {
201+
let text = r#"
202+
abc
203+
123
204+
789
205+
def
206+
ghi"#;
207+
let expected = r#"
208+
abc
209+
hello world
210+
def
211+
ghi"#;
212+
let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || {
213+
vec!["hello world".to_string()]
214+
});
215+
assert_eq!(expected, result);
216+
}
217+
218+
#[test]
219+
fn test_replace_region_with_start() {
220+
let text = r#"
221+
abc
222+
123
223+
789
224+
def
225+
ghi"#;
226+
let expected = r#"
227+
hello world
228+
def
229+
ghi"#;
230+
let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || {
231+
vec!["hello world".to_string()]
232+
});
233+
assert_eq!(expected, result);
234+
}
235+
128236
#[test]
129237
fn test_active_lints() {
130238
let lints = vec![
@@ -154,3 +262,29 @@ fn test_by_lint_group() {
154262
]);
155263
assert_eq!(expected, Lint::by_lint_group(&lints));
156264
}
265+
266+
#[test]
267+
fn test_gen_pub_mod_for_group() {
268+
let lints = vec![
269+
Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "abc"),
270+
Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"),
271+
];
272+
let expected = vec![
273+
"pub mod abc;".to_string(),
274+
"pub mod module_name;".to_string(),
275+
];
276+
assert_eq!(expected, Lint::gen_pub_mod_for_group(&lints));
277+
}
278+
279+
#[test]
280+
fn test_gen_lint_group() {
281+
let lints = vec![
282+
Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "abc"),
283+
Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"),
284+
];;
285+
let expected = vec![
286+
" abc::SHOULD_ASSERT_EQ,".to_string(),
287+
" module_name::SHOULD_ASSERT_EQ2,".to_string()
288+
];
289+
assert_eq!(expected, Lint::gen_lint_group(&lints));
290+
}

clippy_dev/src/main.rs

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,20 @@ fn main() {
1414
Arg::with_name("print-only")
1515
.long("print-only")
1616
.short("p")
17-
.help("Print a table of lints to STDOUT. Does not modify any files."),
18-
)
17+
.help("Print a table of lints to STDOUT. Does not modify any files."))
18+
.arg(
19+
Arg::with_name("changes")
20+
.short("c")
21+
.help("Print a warning and set exit status to 1 if files would be changed"),
22+
),
1923
)
2024
.get_matches();
2125

2226
if let Some(matches) = matches.subcommand_matches("update_lints") {
2327
if matches.is_present("print-only") {
2428
print_lints();
29+
} else {
30+
update_lints();
2531
}
2632
}
2733
}
@@ -43,3 +49,79 @@ fn print_lints() {
4349

4450
println!("there are {} lints", Lint::active_lints(&lint_list).count());
4551
}
52+
53+
54+
fn update_lints() {
55+
let lint_list = gather_all().collect::<Vec<Lint>>();
56+
let active_lints = Lint::active_lints(&lint_list);
57+
let lint_count = active_lints.count();
58+
let clippy_version = clippy_version_from_toml();
59+
60+
replace_region_in_file(
61+
"../README.md",
62+
r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)"#,
63+
"",
64+
true,
65+
|| {
66+
vec![
67+
format!("[There are {} lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)", lint_count)
68+
]
69+
}
70+
);
71+
replace_region_in_file(
72+
"../CHANGELOG.md",
73+
"<!-- begin autogenerated links to lint list -->",
74+
"<!-- end autogenerated links to lint list -->",
75+
false,
76+
|| {
77+
vec![
78+
// TODO
79+
//
80+
// lambda: ["[`{0}`]: {1}#{0}\n".format(l[1], docs_link) for l in
81+
// sorted(all_lints + deprecated_lints,
82+
// key=lambda l: l[1])],
83+
]
84+
}
85+
);
86+
replace_region_in_file(
87+
"../Cargo.toml",
88+
"# begin automatic update",
89+
"# end automatic update",
90+
false,
91+
|| {
92+
vec![
93+
format!("clippy_lints = {{ version = \"{}\", path = \"clippy_lints\" }}\n", clippy_version)
94+
]
95+
}
96+
);
97+
replace_region_in_file(
98+
"../clippy_lints/Cargo.toml",
99+
"# begin automatic update",
100+
"# end automatic update",
101+
false,
102+
|| {
103+
vec![format!("version = {}", clippy_version)]
104+
}
105+
);
106+
replace_region_in_file(
107+
"../clippy_lints/src/lib.rs",
108+
"begin lints modules",
109+
"end lints modules",
110+
false,
111+
|| {
112+
Lint::gen_pub_mod_for_group(&active_lints)
113+
}
114+
);
115+
replace_region_in_file(
116+
"../clippy_lints/src/lib.rs",
117+
r#"reg.register_lint_group\("clippy""#,
118+
r#"\]\);"#,
119+
false,
120+
|| {
121+
vec![
122+
// TODO: gen_group
123+
]
124+
}
125+
);
126+
// TODO: Add the register_lint_group inside the loop, too
127+
}

0 commit comments

Comments
 (0)