Skip to content
This repository was archived by the owner on Nov 24, 2023. It is now read-only.

Commit 3ee72ab

Browse files
committed
Add filtering by machine applicability
1 parent 8ed4006 commit 3ee72ab

File tree

8 files changed

+74
-18
lines changed

8 files changed

+74
-18
lines changed

cargo-fix/src/main.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ fn rustfix_crate(rustc: &Path, filename: &str) -> Result<FixedCrate, Error> {
165165
return Ok(Default::default())
166166
}
167167

168+
let fix_mode = env::var_os("__CARGO_FIX_YOLO")
169+
.map(|_| rustfix::Filter::Everything)
170+
.unwrap_or(rustfix::Filter::MachineApplicableOnly);
171+
168172
// Sift through the output of the compiler to look for JSON messages
169173
// indicating fixes that we can apply.
170174
let stderr = str::from_utf8(&output.stderr).context("failed to parse rustc stderr as utf-8")?;
@@ -176,7 +180,7 @@ fn rustfix_crate(rustc: &Path, filename: &str) -> Result<FixedCrate, Error> {
176180
.filter_map(|line| serde_json::from_str::<Diagnostic>(line).ok())
177181

178182
// From each diagnostic try to extract suggestions from rustc
179-
.filter_map(|diag| rustfix::collect_suggestions(&diag, &only));
183+
.filter_map(|diag| rustfix::collect_suggestions(&diag, &only, fix_mode));
180184

181185
// Collect suggestions by file so we can apply them one at a time later.
182186
let mut file_map = HashMap::new();

cargo-fix/tests/all/broken_build.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ fn fix_broken_if_requested() {
3636
)
3737
.build();
3838

39-
p.expect_cmd("cargo-fix fix --broken-code").status(0).run();
39+
p.expect_cmd("cargo-fix fix --broken-code")
40+
.env("__CARGO_FIX_YOLO", "true")
41+
.status(0)
42+
.run();
4043
}
4144

4245
#[test]
@@ -111,6 +114,7 @@ fn broken_fixes_backed_out() {
111114

112115
// Attempt to fix code, but our shim will always fail the second compile
113116
p.expect_cmd("cargo-fix fix")
117+
.env("__CARGO_FIX_YOLO", "true")
114118
.cwd("bar")
115119
.env("RUSTC", p.root.join("foo/target/debug/foo"))
116120
.stderr_contains("not rust code")

cargo-fix/tests/all/dependencies.rs

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ fn fix_path_deps() {
5454
[FINISHED] dev [unoptimized + debuginfo]
5555
";
5656
p.expect_cmd("cargo-fix fix")
57+
.env("__CARGO_FIX_YOLO", "true")
5758
.stdout("")
5859
.stderr(stderr)
5960
.run();

cargo-fix/tests/all/smoke.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ fn fixes_extra_mut() {
3434
[FINISHED] dev [unoptimized + debuginfo]
3535
";
3636
p.expect_cmd("cargo-fix fix")
37+
.env("__CARGO_FIX_YOLO", "true")
3738
.stdout("")
3839
.stderr(stderr)
3940
.run();
@@ -60,6 +61,7 @@ fn fixes_two_missing_ampersands() {
6061
[FINISHED] dev [unoptimized + debuginfo]
6162
";
6263
p.expect_cmd("cargo-fix fix")
64+
.env("__CARGO_FIX_YOLO", "true")
6365
.stdout("")
6466
.stderr(stderr)
6567
.run();
@@ -85,6 +87,7 @@ fn tricky() {
8587
[FINISHED] dev [unoptimized + debuginfo]
8688
";
8789
p.expect_cmd("cargo-fix fix")
90+
.env("__CARGO_FIX_YOLO", "true")
8891
.stdout("")
8992
.stderr(stderr)
9093
.run();
@@ -102,7 +105,9 @@ fn preserve_line_endings() {
102105
)
103106
.build();
104107

105-
p.expect_cmd("cargo-fix fix").run();
108+
p.expect_cmd("cargo-fix fix")
109+
.env("__CARGO_FIX_YOLO", "true")
110+
.run();
106111
assert!(p.read("src/lib.rs").contains("\r\n"));
107112
}
108113

@@ -118,7 +123,9 @@ fn fix_deny_warnings() {
118123
)
119124
.build();
120125

121-
p.expect_cmd("cargo-fix fix").run();
126+
p.expect_cmd("cargo-fix fix")
127+
.env("__CARGO_FIX_YOLO", "true")
128+
.run();
122129
}
123130

124131
#[test]
@@ -139,7 +146,9 @@ fn fix_deny_warnings_but_not_others() {
139146
)
140147
.build();
141148

142-
p.expect_cmd("cargo-fix fix").run();
149+
p.expect_cmd("cargo-fix fix")
150+
.env("__CARGO_FIX_YOLO", "true")
151+
.run();
143152
assert!(!p.read("src/lib.rs").contains("let mut x = 3;"));
144153
assert!(p.read("src/lib.rs").contains("fn bar() {}"));
145154
}
@@ -170,6 +179,7 @@ fn fix_two_files() {
170179
.build();
171180

172181
p.expect_cmd("cargo-fix fix")
182+
.env("__CARGO_FIX_YOLO", "true")
173183
.stderr_contains("[FIXING] src/bar.rs (1 fix)")
174184
.stderr_contains("[FIXING] src/lib.rs (1 fix)")
175185
.run();

cargo-fix/tests/all/subtargets.rs

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ fn fixes_missing_ampersand() {
4040
.build();
4141

4242
p.expect_cmd("cargo fix -- --all-targets")
43+
.env("__CARGO_FIX_YOLO", "true")
4344
.stdout("")
4445
.stderr_contains("[COMPILING] foo v0.1.0 (CWD)")
4546
.stderr_contains("[FIXING] build.rs (1 fix)")

src/diagnostics.rs

+9
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,19 @@ pub struct DiagnosticSpan {
4141
/// load the fully rendered version from the parent `Diagnostic`,
4242
/// however.
4343
pub suggested_replacement: Option<String>,
44+
pub suggestion_applicability: Option<Applicability>,
4445
/// Macro invocations that created the code at this span, if any.
4546
expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
4647
}
4748

49+
#[derive(Copy, Clone, Debug, PartialEq, Deserialize)]
50+
pub enum Applicability {
51+
MachineApplicable,
52+
HasPlaceholders,
53+
MaybeIncorrect,
54+
Unspecified,
55+
}
56+
4857
#[derive(Deserialize, Debug)]
4958
pub struct DiagnosticSpanLine {
5059
pub text: String,

src/lib.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,21 @@ pub mod diagnostics;
1818
use diagnostics::{Diagnostic, DiagnosticSpan};
1919
mod replace;
2020

21+
#[derive(Debug, Clone, Copy)]
22+
pub enum Filter {
23+
MachineApplicableOnly,
24+
Everything,
25+
}
26+
2127
pub fn get_suggestions_from_json<S: ::std::hash::BuildHasher>(
2228
input: &str,
2329
only: &HashSet<String, S>,
30+
filter: Filter,
2431
) -> serde_json::error::Result<Vec<Suggestion>> {
2532
let mut result = Vec::new();
2633
for cargo_msg in serde_json::Deserializer::from_str(input).into_iter::<Diagnostic>() {
2734
// One diagnostic line might have multiple suggestions
28-
result.extend(collect_suggestions(&cargo_msg?, only));
35+
result.extend(collect_suggestions(&cargo_msg?, only, filter));
2936
}
3037
Ok(result)
3138
}
@@ -142,6 +149,7 @@ fn collect_span(span: &DiagnosticSpan) -> Option<Replacement> {
142149
pub fn collect_suggestions<S: ::std::hash::BuildHasher>(
143150
diagnostic: &Diagnostic,
144151
only: &HashSet<String, S>,
152+
filter: Filter,
145153
) -> Option<Suggestion> {
146154
if !only.is_empty() {
147155
if let Some(ref code) = diagnostic.code {
@@ -165,7 +173,19 @@ pub fn collect_suggestions<S: ::std::hash::BuildHasher>(
165173
.children
166174
.iter()
167175
.filter_map(|child| {
168-
let replacements: Vec<_> = child.spans.iter().filter_map(collect_span).collect();
176+
let replacements: Vec<_> = child.spans.iter()
177+
.filter(|span| {
178+
use diagnostics::Applicability::*;
179+
use Filter::*;
180+
181+
match (filter, &span.suggestion_applicability) {
182+
(MachineApplicableOnly, Some(MachineApplicable)) => true,
183+
(MachineApplicableOnly, _) => false,
184+
(_, _) => true,
185+
}
186+
})
187+
.filter_map(collect_span)
188+
.collect();
169189
if replacements.is_empty() {
170190
None
171191
} else {

tests/parse_and_replace.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ extern crate failure;
1212
extern crate difference;
1313

1414
use std::ffi::OsString;
15-
use std::{env, fs};
15+
use std::fs;
1616
use std::path::{Path, PathBuf};
1717
use std::collections::HashSet;
1818
use std::process::Output;
@@ -32,9 +32,6 @@ mod settings {
3232
pub const CHECK_JSON: &str = "RUSTFIX_TEST_CHECK_JSON";
3333
pub const RECORD_JSON: &str = "RUSTFIX_TEST_RECORD_JSON";
3434
pub const RECORD_FIXED_RUST: &str = "RUSTFIX_TEST_RECORD_FIXED_RUST";
35-
36-
// set automatically
37-
pub const MODE: &str = "RUSTFIX_MODE";
3835
}
3936

4037
fn compile(file: &Path, mode: &str) -> Result<Output, Error> {
@@ -118,15 +115,15 @@ fn diff(expected: &str, actual: &str) -> String {
118115
Difference::Rem(rem) => ("-", rem),
119116
};
120117
if !different {
121-
write!(&mut res, "differences found (+ == actual, - == expected):\n");
118+
write!(&mut res, "differences found (+ == actual, - == expected):\n").unwrap();
122119
different = true;
123120
}
124121
for diff in diff.lines() {
125-
writeln!(&mut res, "{} {}", prefix, diff);
122+
writeln!(&mut res, "{} {}", prefix, diff).unwrap();
126123
}
127124
}
128125
if different {
129-
write!(&mut res, "");
126+
write!(&mut res, "").unwrap();
130127
}
131128

132129
res
@@ -137,13 +134,21 @@ fn test_rustfix_with_file<P: AsRef<Path>>(file: P, mode: &str) -> Result<(), Err
137134
let json_file = file.with_extension("json");
138135
let fixed_file = file.with_extension("fixed.rs");
139136

137+
let filter_suggestions = if mode == fixmode::EVERYTHING {
138+
rustfix::Filter::Everything
139+
} else {
140+
rustfix::Filter::MachineApplicableOnly
141+
};
142+
140143
debug!("next up: {:?}", file);
141144
let code = read_file(file)
142145
.context(format!("could not read {}", file.display()))?;
143146
let errors = compile_and_get_json_errors(file, mode)
144147
.context(format!("could compile {}", file.display()))?;
145-
let suggestions = rustfix::get_suggestions_from_json(&errors, &HashSet::new())
146-
.context("could not load suggestions")?;
148+
let suggestions =
149+
rustfix::get_suggestions_from_json(
150+
&errors, &HashSet::new(), filter_suggestions,
151+
).context("could not load suggestions")?;
147152

148153
if std::env::var(settings::RECORD_JSON).is_ok() {
149154
use std::io::Write;
@@ -155,8 +160,10 @@ fn test_rustfix_with_file<P: AsRef<Path>>(file: P, mode: &str) -> Result<(), Err
155160
if std::env::var(settings::CHECK_JSON).is_ok() {
156161
let expected_json = read_file(&json_file)
157162
.context(format!("could not load json fixtures for {}", file.display()))?;;
158-
let expected_suggestions = rustfix::get_suggestions_from_json(&expected_json, &HashSet::new())
159-
.context("could not load expected suggesitons")?;
163+
let expected_suggestions =
164+
rustfix::get_suggestions_from_json(
165+
&expected_json, &HashSet::new(), filter_suggestions,
166+
).context("could not load expected suggesitons")?;
160167

161168
ensure!(
162169
expected_suggestions == suggestions,

0 commit comments

Comments
 (0)