Skip to content

Commit 34946b7

Browse files
guyoron1kylehgc
authored andcommitted
fix(prettier): read check results from stderr, never report a failing check as success
Prettier >= 1.19 writes its --check results ([warn] <file>) to stderr, but the filter ran with RunOptions::stdout_only() and also explicitly skipped any line containing [warn]. On a failing check the file list was silently discarded and the filter produced 'Prettier: All files formatted correctly' alongside exit code 1. - filter the combined stdout+stderr stream - recognize '[warn] <file>' lines as files needing formatting - exit-aware guard: a check that exited non-zero with no parsable file list passes the real output through instead of claiming success
1 parent 9c77b36 commit 34946b7

1 file changed

Lines changed: 66 additions & 4 deletions

File tree

‎src/cmds/js/prettier_cmd.rs‎

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,24 @@ pub fn run(args: &[String], verbose: u8) -> Result<i32> {
1616
eprintln!("Running: prettier {}", args.join(" "));
1717
}
1818

19-
runner::run_filtered(
19+
// Prettier >= 1.19 logs its `--check` results ("[warn] <file>") to stderr,
20+
// not stdout — the filter must see the combined output, and the exit code,
21+
// to avoid reporting a failing check as success.
22+
runner::run_filtered_with_exit(
2023
cmd,
2124
"prettier",
2225
&args.join(" "),
23-
filter_prettier_output,
24-
RunOptions::stdout_only(),
26+
filter_prettier_output_with_exit,
27+
RunOptions::default(),
2528
)
2629
}
2730

2831
/// Filter Prettier output - show only files that need formatting
2932
pub fn filter_prettier_output(output: &str) -> String {
33+
filter_prettier_output_with_exit(output, 0)
34+
}
35+
36+
fn filter_prettier_output_with_exit(output: &str, exit_code: i32) -> String {
3037
// #221: empty or whitespace-only output means prettier didn't run
3138
if output.trim().is_empty() {
3239
return "Error: prettier produced no output".to_string();
@@ -39,6 +46,13 @@ pub fn filter_prettier_output(output: &str) -> String {
3946
for line in output.lines() {
4047
let trimmed = line.trim();
4148

49+
// Prettier >= 1.19 prefixes each check result with "[warn] " (on
50+
// stderr). Strip the prefix so those file lines are recognized.
51+
let trimmed = trimmed
52+
.strip_prefix("[warn]")
53+
.map(str::trim_start)
54+
.unwrap_or(trimmed);
55+
4256
// Detect check mode vs write mode
4357
if trimmed.contains("Checking formatting") {
4458
is_check_mode = true;
@@ -49,7 +63,6 @@ pub fn filter_prettier_output(output: &str) -> String {
4963
&& !trimmed.starts_with("Checking")
5064
&& !trimmed.starts_with("All matched")
5165
&& !trimmed.starts_with("Code style")
52-
&& !trimmed.contains("[warn]")
5366
&& !trimmed.contains("[error]")
5467
&& (trimmed.ends_with(".ts")
5568
|| trimmed.ends_with(".tsx")
@@ -88,6 +101,12 @@ pub fn filter_prettier_output(output: &str) -> String {
88101
if is_check_mode {
89102
// Check mode: show files that need formatting
90103
if files_to_format.is_empty() {
104+
if exit_code != 0 {
105+
// Prettier failed but no file list could be parsed (unknown
106+
// extension, unexpected output shape). Never claim success on
107+
// a failing check — pass the real output through.
108+
return output.trim().to_string();
109+
}
91110
result.push_str("Prettier: All files formatted correctly\n");
92111
} else {
93112
result.push_str(&format!(
@@ -181,4 +200,47 @@ Code style issues found in the above file(s). Forgot to run Prettier?
181200
assert!(result.contains("Error"));
182201
assert!(!result.contains("All files formatted"));
183202
}
203+
204+
// --- failing `--check` writes "[warn] <file>" to stderr (prettier >= 1.19) ---
205+
206+
#[test]
207+
fn test_filter_check_failure_warn_prefixed_files() {
208+
// Real prettier 3.x --check output (combined stdout + stderr)
209+
let output = "Checking formatting...\n\
210+
[warn] src/app.ts\n\
211+
[warn] src/util.js\n\
212+
[warn] Code style issues found in the above files. Run Prettier with --write to fix.";
213+
let result = filter_prettier_output_with_exit(output, 1);
214+
assert!(
215+
result.contains("2 files need formatting"),
216+
"got: {}",
217+
result
218+
);
219+
assert!(result.contains("src/app.ts"));
220+
assert!(result.contains("src/util.js"));
221+
assert!(!result.contains("All files formatted correctly"));
222+
}
223+
224+
#[test]
225+
fn test_filter_check_failure_never_reports_success() {
226+
// Unrecognized extension: no file list parsed, but prettier exited 1 —
227+
// must not claim success.
228+
let output = "Checking formatting...\n\
229+
[warn] src/component.vue\n\
230+
[warn] Code style issues found in the above file. Run Prettier with --write to fix.";
231+
let result = filter_prettier_output_with_exit(output, 1);
232+
assert!(
233+
!result.contains("All files formatted correctly"),
234+
"failing check reported as success: {}",
235+
result
236+
);
237+
assert!(result.contains("src/component.vue"));
238+
}
239+
240+
#[test]
241+
fn test_filter_check_success_exit_zero_unchanged() {
242+
let output = "Checking formatting...\nAll matched files use Prettier code style!";
243+
let result = filter_prettier_output_with_exit(output, 0);
244+
assert!(result.contains("All files formatted correctly"));
245+
}
184246
}

0 commit comments

Comments
 (0)