From 1d2d015bc57fb3cbe23398785789ae51e92ca219 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 28 Jun 2023 10:52:23 -0400 Subject: [PATCH] Make standard input detection robust to invalid arguments (#5393) ## Summary This PR fixes a silent failure that manifested itself in https://github.com/astral-sh/ruff-vscode/issues/238. In short, if the user provided invalid arguments to Ruff in the VS Code extension (like `"ruff.args": ["a"]`), then we generated something like the following command: ```console /path/to/ruff --force-exclude --no-cache --no-fix --format json - --fix a --stdin-filename /path/to/file.py ``` Since this contains both `-` and `a` as the "input files", Ruff would treat this as if we're linting the files names `-` and `a`, rather than linting standard input. This PR modifies out standard input detection to force standard input when `--stdin-filename` is present, or at least one file is `-`. (We then warn and ignore the others.) --- crates/ruff_cli/src/lib.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/crates/ruff_cli/src/lib.rs b/crates/ruff_cli/src/lib.rs index b7abecc4a1..90d705b286 100644 --- a/crates/ruff_cli/src/lib.rs +++ b/crates/ruff_cli/src/lib.rs @@ -77,6 +77,27 @@ fn change_detected(paths: &[PathBuf]) -> Option { None } +/// Returns true if the linter should read from standard input. +fn is_stdin(files: &[PathBuf], stdin_filename: Option<&Path>) -> bool { + // If the user provided a `--stdin-filename`, always read from standard input. + if stdin_filename.is_some() { + if let Some(file) = files.iter().find(|file| file.as_path() != Path::new("-")) { + warn_user_once!( + "Ignoring file {} in favor of standard input.", + file.display() + ); + } + return true; + } + + // If the user provided exactly `-`, read from standard input. + if files.len() == 1 && files[0] == Path::new("-") { + return true; + } + + false +} + pub fn run( Args { command, @@ -329,7 +350,7 @@ pub fn check(args: CheckArgs, log_level: LogLevel) -> Result { } } } else { - let is_stdin = cli.files == vec![PathBuf::from("-")]; + let is_stdin = is_stdin(&cli.files, cli.stdin_filename.as_deref()); // Generate lint violations. let diagnostics = if is_stdin {