Skip to content

Commit 0318fdd

Browse files
committed
RIIR update_lints: Replace lint count in README.md
This allows the usage of `util/dev update_lints` which will write the new lint_count to the `README.md`.
1 parent af441b5 commit 0318fdd

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

clippy_dev/src/lib.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,88 @@ fn lint_files() -> impl Iterator<Item=walkdir::DirEntry> {
101101
.filter(|f| f.path().extension() == Some(OsStr::new("rs")))
102102
}
103103

104+
/// Replace a region in a file delimited by two lines matching regexes.
105+
///
106+
/// `path` is the relative path to the file on which you want to perform the replacement.
107+
///
108+
/// See `replace_region_in_text` documentation of the other options.
109+
pub fn replace_region_in_file<F>(path: &str, start: &str, end: &str, replace_start: bool, replacements: F) where F: Fn() -> Vec<String> {
110+
let mut f = fs::File::open(path).expect(&format!("File not found: {}", path));
111+
let mut contents = String::new();
112+
f.read_to_string(&mut contents).expect("Something went wrong reading the file");
113+
let replaced = replace_region_in_text(&contents, start, end, replace_start, replacements);
114+
115+
let mut f = fs::File::create(path).expect(&format!("File not found: {}", path));
116+
f.write_all(replaced.as_bytes()).expect("Unable to write file");
117+
// Ensure we write the changes with a trailing newline so that
118+
// the file has the proper line endings.
119+
f.write(b"\n").expect("Unable to write file");
120+
}
121+
122+
/// Replace a region in a text delimited by two lines matching regexes.
123+
///
124+
/// * `text` is the input text on which you want to perform the replacement
125+
/// * `start` is a `&str` that describes the delimiter line before the region you want to replace.
126+
/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too.
127+
/// * `end` is a `&str` that describes the delimiter line until where the replacement should
128+
/// happen. As the `&str` will be converted to a `Regex`, this can contain regex syntax, too.
129+
/// * If `replace_start` is true, the `start` delimiter line is replaced as well.
130+
/// The `end` delimiter line is never replaced.
131+
/// * `replacements` is a closure that has to return a `Vec<String>` which contains the new text.
132+
///
133+
/// If you want to perform the replacement on files instead of already parsed text,
134+
/// use `replace_region_in_file`.
135+
///
136+
/// # Example
137+
///
138+
/// ```
139+
/// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end";
140+
/// let result = clippy_dev::replace_region_in_text(
141+
/// the_text,
142+
/// r#"replace_start"#,
143+
/// r#"replace_end"#,
144+
/// false,
145+
/// || {
146+
/// vec!["a different".to_string(), "text".to_string()]
147+
/// }
148+
/// );
149+
/// assert_eq!("replace_start\na different\ntext\nreplace_end", result);
150+
/// ```
151+
pub fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> String where F: Fn() -> Vec<String> {
152+
let lines = text.lines();
153+
let mut in_old_region = false;
154+
let mut found = false;
155+
let mut new_lines = vec![];
156+
let start = Regex::new(start).unwrap();
157+
let end = Regex::new(end).unwrap();
158+
159+
for line in lines {
160+
if in_old_region {
161+
if end.is_match(&line) {
162+
in_old_region = false;
163+
new_lines.extend(replacements());
164+
new_lines.push(line.to_string());
165+
}
166+
} else if start.is_match(&line) {
167+
if !replace_start {
168+
new_lines.push(line.to_string());
169+
}
170+
in_old_region = true;
171+
found = true;
172+
} else {
173+
new_lines.push(line.to_string());
174+
}
175+
}
176+
177+
if !found {
178+
// This happens if the provided regex in `clippy_dev/src/main.rs` is not found in the
179+
// given text or file. Most likely this is an error on the programmer's side and the Regex
180+
// is incorrect.
181+
println!("regex {:?} not found. You may have to update it.", start);
182+
}
183+
new_lines.join("\n")
184+
}
185+
104186
#[test]
105187
fn test_parse_contents() {
106188
let result: Vec<Lint> = parse_contents(
@@ -140,6 +222,43 @@ declare_deprecated_lint! {
140222
assert_eq!(expected, result);
141223
}
142224

225+
#[test]
226+
fn test_replace_region() {
227+
let text = r#"
228+
abc
229+
123
230+
789
231+
def
232+
ghi"#;
233+
let expected = r#"
234+
abc
235+
hello world
236+
def
237+
ghi"#;
238+
let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || {
239+
vec!["hello world".to_string()]
240+
});
241+
assert_eq!(expected, result);
242+
}
243+
244+
#[test]
245+
fn test_replace_region_with_start() {
246+
let text = r#"
247+
abc
248+
123
249+
789
250+
def
251+
ghi"#;
252+
let expected = r#"
253+
hello world
254+
def
255+
ghi"#;
256+
let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || {
257+
vec!["hello world".to_string()]
258+
});
259+
assert_eq!(expected, result);
260+
}
261+
143262
#[test]
144263
fn test_usable_lints() {
145264
let lints = vec![

clippy_dev/src/main.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ fn main() {
3232
if let Some(matches) = matches.subcommand_matches("update_lints") {
3333
if matches.is_present("print-only") {
3434
print_lints();
35+
} else {
36+
update_lints();
3537
}
3638
}
3739
}
@@ -55,3 +57,21 @@ fn print_lints() {
5557

5658
println!("there are {} lints", lint_count);
5759
}
60+
61+
fn update_lints() {
62+
let lint_list = gather_all();
63+
let usable_lints: Vec<Lint> = Lint::usable_lints(lint_list).collect();
64+
let lint_count = usable_lints.len();
65+
66+
replace_region_in_file(
67+
"../README.md",
68+
r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang-nursery.github.io/rust-clippy/master/index.html\)"#,
69+
"",
70+
true,
71+
|| {
72+
vec![
73+
format!("[There are {} lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)", lint_count)
74+
]
75+
}
76+
);
77+
}

0 commit comments

Comments
 (0)