diff --git a/src/autofix/fixer.rs b/src/autofix/fixer.rs index fd827914c9..827b50814d 100644 --- a/src/autofix/fixer.rs +++ b/src/autofix/fixer.rs @@ -1,7 +1,3 @@ -use std::fs; -use std::path::Path; - -use anyhow::Result; use itertools::Itertools; use rustpython_parser::ast::Location; @@ -24,17 +20,15 @@ impl From for Mode { } /// Auto-fix errors in a file, and write the fixed source code to disk. -pub fn fix_file(checks: &mut [Check], contents: &str, path: &Path) -> Result<()> { +pub fn fix_file(checks: &mut [Check], contents: &str) -> Option { if checks.iter().all(|check| check.fix.is_none()) { - return Ok(()); + return None; } - let output = apply_fixes( + Some(apply_fixes( checks.iter_mut().filter_map(|check| check.fix.as_mut()), contents, - ); - - fs::write(path, output).map_err(|e| e.into()) + )) } /// Apply a series of fixes. diff --git a/src/linter.rs b/src/linter.rs index 63743b31ba..b16a8c2ae2 100644 --- a/src/linter.rs +++ b/src/linter.rs @@ -1,4 +1,6 @@ use std::fs::write; +use std::io; +use std::io::Write; use std::path::Path; use anyhow::Result; @@ -83,7 +85,12 @@ pub(crate) fn check_path( Ok(checks) } -pub fn lint_stdin(path: &Path, stdin: &str, settings: &Settings) -> Result> { +pub fn lint_stdin( + path: &Path, + stdin: &str, + settings: &Settings, + autofix: &fixer::Mode, +) -> Result> { // Tokenize once. let tokens: Vec = tokenize(stdin); @@ -91,14 +98,16 @@ pub fn lint_stdin(path: &Path, stdin: &str, settings: &Settings) -> Result stdin.to_string(), + Some(content) => content, + }; + io::stdout().write_all(output.as_bytes())?; + } // Convert to messages. Ok(checks @@ -141,7 +150,9 @@ pub fn lint_path( // Apply autofix. if matches!(autofix, fixer::Mode::Apply) { - fix_file(&mut checks, &contents, path)?; + if let Some(fixed_contents) = fix_file(&mut checks, &contents) { + write(path, fixed_contents)?; + } }; // Convert to messages. diff --git a/src/main.rs b/src/main.rs index adf420caa7..4d95437165 100644 --- a/src/main.rs +++ b/src/main.rs @@ -81,9 +81,9 @@ fn read_from_stdin() -> Result { Ok(buffer) } -fn run_once_stdin(settings: &Settings, filename: &Path) -> Result> { +fn run_once_stdin(settings: &Settings, filename: &Path, autofix: bool) -> Result> { let stdin = read_from_stdin()?; - let mut messages = lint_stdin(filename, &stdin, settings)?; + let mut messages = lint_stdin(filename, &stdin, settings, &autofix.into())?; messages.sort_unstable(); Ok(messages) } @@ -365,18 +365,20 @@ fn inner_main() -> Result { println!("Formatted {modifications} files."); } } else { - let messages = if cli.files == vec![PathBuf::from("-")] { - if cli.fix { - eprintln!("Warning: --fix is not enabled when reading from stdin."); - } - + let (messages, print_messages) = if cli.files == vec![PathBuf::from("-")] { let filename = cli.stdin_filename.unwrap_or_else(|| "-".to_string()); let path = Path::new(&filename); - run_once_stdin(&settings, path)? + ( + run_once_stdin(&settings, path, cli.fix)?, + !cli.quiet && !cli.fix, + ) } else { - run_once(&cli.files, &settings, !cli.no_cache, cli.fix)? + ( + run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?, + !cli.quiet, + ) }; - if !cli.quiet { + if print_messages { printer.write_once(&messages)?; } diff --git a/tests/integration_test.rs b/tests/integration_test.rs index a6749972c4..c2abaa09a9 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -39,9 +39,42 @@ fn test_stdin_autofix() -> Result<()> { let mut cmd = Command::cargo_bin(crate_name!())?; let output = cmd .args(&["-", "--fix"]) - .write_stdin("import os\n") + .write_stdin("import os\nimport sys\n\nprint(sys.version)\n") .assert() - .failure(); - assert!(str::from_utf8(&output.get_output().stdout)?.contains("-:1:1: F401")); + .success(); + assert_eq!( + str::from_utf8(&output.get_output().stdout)?, + "import sys\n\nprint(sys.version)\n" + ); + Ok(()) +} + +#[test] +fn test_stdin_autofix_when_not_fixable_should_still_print_contents() -> Result<()> { + let mut cmd = Command::cargo_bin(crate_name!())?; + let output = cmd + .args(&["-", "--fix"]) + .write_stdin("import os\nimport sys\n\nif (1, 2):\n print(sys.version)\n") + .assert() + .failure(); + assert_eq!( + str::from_utf8(&output.get_output().stdout)?, + "import sys\n\nif (1, 2):\n print(sys.version)\n" + ); + Ok(()) +} + +#[test] +fn test_stdin_autofix_when_no_issues_should_still_print_contents() -> Result<()> { + let mut cmd = Command::cargo_bin(crate_name!())?; + let output = cmd + .args(&["-", "--fix"]) + .write_stdin("import sys\n\nprint(sys.version)\n") + .assert() + .success(); + assert_eq!( + str::from_utf8(&output.get_output().stdout)?, + "import sys\n\nprint(sys.version)\n" + ); Ok(()) }