fix: tidy fix defaults match tidy check issues (#1424) · patchloom/patchloom@1f2d2a9 · GitHub
Skip to content

Commit 1f2d2a9

Browse files
authored
fix: tidy fix defaults match tidy check issues (#1424)
## Summary fixrealloop multi-file round found that bare `tidy fix --apply` reported success with zero files changed while `tidy check` still flagged missing final newline and trailing whitespace on the same tree. - Default `tidy fix` (no write-policy flags, no `--respect-editorconfig`) now enables final-newline and trailing-whitespace fixes. - Explicit flags or EditorConfig keep opt-in behavior unchanged. - Docs/help examples updated. ## Test plan - [x] Unit tests for check-parity defaults and explicit trim-only - [x] Existing EditorConfig per-extension integration test - [x] `make check-fast` - [x] Release binary: messy file cleaned, subsequent check clean Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
1 parent 7cc3e08 commit 1f2d2a9

4 files changed

Lines changed: 139 additions & 10 deletions

File tree

docs/reference/README.md

Lines changed: 2 additions & 2 deletions

src/cmd/tidy/fix.rs

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,49 @@ fn emit_tidy_fix_output(
114114
Ok(())
115115
}
116116

117+
/// Write-policy fields for `tidy fix` after applying check-parity defaults.
118+
struct TidyFixPolicy {
119+
ensure_final_newline: bool,
120+
trim_trailing_whitespace: bool,
121+
normalize_eol: Option<crate::cli::global::EolMode>,
122+
collapse_blanks: bool,
123+
}
124+
125+
/// When the user did not pass any write-policy flag and is not only
126+
/// indenting/dedenting, enable the same normalizations that `tidy check`
127+
/// always reports (final newline + trailing whitespace). Otherwise
128+
/// `tidy fix --apply` is a silent no-op while `tidy check` still fails
129+
/// (fixrealloop feature gap).
130+
fn effective_tidy_fix_policy(
131+
global: &GlobalFlags,
132+
dedent: Option<&str>,
133+
indent: Option<&str>,
134+
) -> TidyFixPolicy {
135+
// EditorConfig opt-in is also "explicit policy": do not force check-parity
136+
// defaults on top of per-file EditorConfig rules.
137+
let any_explicit_policy = global.ensure_final_newline
138+
|| global.trim_trailing_whitespace
139+
|| global.normalize_eol.is_some()
140+
|| global.collapse_blanks
141+
|| global.respect_editorconfig
142+
|| dedent.is_some()
143+
|| indent.is_some();
144+
if any_explicit_policy {
145+
return TidyFixPolicy {
146+
ensure_final_newline: global.ensure_final_newline,
147+
trim_trailing_whitespace: global.trim_trailing_whitespace,
148+
normalize_eol: global.normalize_eol,
149+
collapse_blanks: global.collapse_blanks,
150+
};
151+
}
152+
TidyFixPolicy {
153+
ensure_final_newline: true,
154+
trim_trailing_whitespace: true,
155+
normalize_eol: None,
156+
collapse_blanks: false,
157+
}
158+
}
159+
117160
/// Run `tidy fix` for the given paths and optional dedent/indent/lines.
118161
pub(super) fn run_fix(
119162
paths: Vec<String>,
@@ -127,6 +170,8 @@ pub(super) fn run_fix(
127170
anyhow::bail!("--dedent and --indent cannot both be set");
128171
}
129172

173+
let policy_flags = effective_tidy_fix_policy(global, dedent.as_deref(), indent.as_deref());
174+
130175
let cwd = global.resolve_cwd()?;
131176
global.check_paths_contained(&cwd, &paths)?;
132177
let glob_matcher = crate::build_glob_matcher_from_global(global)?;
@@ -141,6 +186,18 @@ pub(super) fn run_fix(
141186
let quiet = global.quiet;
142187
let dedent_ref = dedent.as_deref();
143188
let indent_ref = indent.as_deref();
189+
// policy_from_flags reads ensure/trim/eol from GlobalFlags. Overlay the
190+
// effective tidy defaults (and keep editorconfig opt-in from the caller).
191+
let policy_global = GlobalFlags {
192+
ensure_final_newline: policy_flags.ensure_final_newline,
193+
trim_trailing_whitespace: policy_flags.trim_trailing_whitespace,
194+
normalize_eol: policy_flags.normalize_eol,
195+
collapse_blanks: policy_flags.collapse_blanks,
196+
respect_editorconfig: global.respect_editorconfig,
197+
quiet: global.quiet,
198+
..GlobalFlags::default()
199+
};
200+
144201
let dirty_rel_paths: Vec<String> = crate::par_process_files(
145202
&fix_file_paths,
146203
glob_matcher.as_ref(),
@@ -150,7 +207,7 @@ pub(super) fn run_fix(
150207
Some(text) => text,
151208
None => return None,
152209
};
153-
let policy = policy_from_flags(global, Some(file_path));
210+
let policy = policy_from_flags(&policy_global, Some(file_path));
154211
let mut fixed = apply_policy(&original, &policy).into_owned();
155212
if let Some(spec) = dedent_ref {
156213
fixed = crate::write::dedent_content(&fixed, spec, line_range);
@@ -176,8 +233,8 @@ pub(super) fn run_fix(
176233
return Ok(exit::SUCCESS);
177234
}
178235

179-
let eol_str = global.normalize_eol.map(eol_mode_to_str);
180-
let collapse = if global.collapse_blanks {
236+
let eol_str = policy_flags.normalize_eol.map(eol_mode_to_str);
237+
let collapse = if policy_flags.collapse_blanks {
181238
Some(true)
182239
} else {
183240
None
@@ -186,8 +243,8 @@ pub(super) fn run_fix(
186243
.iter()
187244
.map(|rel_path| Operation::TidyFix {
188245
path: rel_path.clone(),
189-
ensure_final_newline: Some(global.ensure_final_newline),
190-
trim_trailing_whitespace: Some(global.trim_trailing_whitespace),
246+
ensure_final_newline: Some(policy_flags.ensure_final_newline),
247+
trim_trailing_whitespace: Some(policy_flags.trim_trailing_whitespace),
191248
normalize_eol: eol_str.map(String::from),
192249
collapse_blanks: collapse,
193250
dedent: dedent.clone(),
@@ -196,6 +253,8 @@ pub(super) fn run_fix(
196253
})
197254
.collect();
198255

256+
// Mode/apply still come from the caller's global flags; only the
257+
// write-policy fields use the effective check-parity defaults above.
199258
let (cwd, result) = crate::cmd::output::stage_for_write(WriteSource::Operations(ops), global)?;
200259

201260
tidy_fix_output(global, result, &dirty_rel_paths, &cwd)

src/cmd/tidy/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ use clap::Args;
1414
#[derive(Debug, Args)]
1515
#[command(after_help = "\
1616
EXAMPLES:
17-
patchloom tidy src/ --ensure-final-newline
18-
patchloom tidy . --trim-trailing-whitespace --apply
19-
patchloom tidy . --normalize-eol lf --check")]
17+
patchloom tidy fix . --apply
18+
patchloom tidy fix src/ --ensure-final-newline --apply
19+
patchloom tidy fix . --trim-trailing-whitespace --apply
20+
patchloom tidy check . --normalize-eol lf
21+
22+
With no write-policy flags, `tidy fix` enables final-newline and trailing-
23+
whitespace fixes (the same issues `tidy check` always reports). Pass explicit
24+
flags to narrow the fix set.")]
2025
pub struct TidyArgs {
2126
#[command(subcommand)]
2227
pub action: TidyAction,

src/cmd/tidy/tests.rs

Lines changed: 65 additions & 0 deletions

0 commit comments

Comments
 (0)