From f6525c9a591db267063b9bb0a785edf1b6864d95 Mon Sep 17 00:00:00 2001 From: Daniel Hawkins Date: Fri, 12 Dec 2025 03:20:08 +0000 Subject: [PATCH] fix(reflow): use relevant untaken count for indent calculations Refactor indentation calculation logic to properly account for indent troughs when determining relevant untaken indents. Previously, the code used `untaken_indents.len()` directly, which didn't filter out irrelevant indents when a trough was present. Changes: - Add `relevant_untaken_count()` method to `IndentPoint` that mirrors the filtering logic in `IndentLine::desired_indent_units()` - Update `lint_line_untaken_positive_indents()` to use the new method - Update `lint_line_untaken_negative_indents()` to use the new method - Add `.max(0)` guards to prevent negative indent values This fixes incorrect indentation calculations in cases where indent troughs are present, ensuring that only relevant untaken indents are considered when computing desired indentation levels. --- crates/cli-python/tests/dbt/output.stderr | 2 +- crates/lib/src/utils/reflow/reindent.rs | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/cli-python/tests/dbt/output.stderr b/crates/cli-python/tests/dbt/output.stderr index 6e66602ee..ed6d6c80f 100644 --- a/crates/cli-python/tests/dbt/output.stderr +++ b/crates/cli-python/tests/dbt/output.stderr @@ -1,6 +1,6 @@ == [models/customers.sql] FAIL L: 22 | P: 16 | LT02 | Expected indent of 4 spaces. [layout.indent] -L: 42 | P: 27 | LT02 | Expected line break and indent of 4 spaces before "on". +L: 42 | P: 27 | LT02 | Expected line break and indent of 8 spaces before "on". | [layout.indent] L: 42 | P: 31 | LT02 | Expected indent of 12 spaces. [layout.indent] L: 65 | P: 41 | LT01 | Expected only single space before "customers". Found " diff --git a/crates/lib/src/utils/reflow/reindent.rs b/crates/lib/src/utils/reflow/reindent.rs index 8bdf2bf1d..97fc06299 100644 --- a/crates/lib/src/utils/reflow/reindent.rs +++ b/crates/lib/src/utils/reflow/reindent.rs @@ -45,6 +45,21 @@ impl IndentPoint { fn closing_indent_balance(&self) -> isize { self.initial_indent_balance + self.indent_impulse } + + /// Returns the count of relevant untaken indents, filtering when there's a trough. + /// This mirrors the logic in `IndentLine::desired_indent_units`. + fn relevant_untaken_count(&self) -> usize { + if self.indent_trough != 0 { + self.untaken_indents + .iter() + .filter(|&&i| { + i <= self.initial_indent_balance - (self.indent_impulse - self.indent_trough) + }) + .count() + } else { + self.untaken_indents.len() + } + } } #[derive(Debug, Clone)] @@ -675,7 +690,7 @@ fn lint_line_untaken_positive_indents( if imbalanced_indent_locs.contains(&ip.idx) { // Force it at the relevant position. let desired_indent = single_indent - .repeat((ip.closing_indent_balance() - ip.untaken_indents.len() as isize) as usize); + .repeat((ip.closing_indent_balance() - ip.relevant_untaken_count() as isize).max(0) as usize); let target_point = elements[ip.idx].as_point().unwrap(); let (results, new_point) = target_point.indent_to( @@ -689,7 +704,7 @@ fn lint_line_untaken_positive_indents( elements[ip.idx] = ReflowElement::Point(new_point); // Keep track of the indent we forced, by returning it. - return (results, vec![ip.closing_indent_balance() as usize]); + return (results, vec![ip.closing_indent_balance().max(0) as usize]); } } @@ -757,7 +772,7 @@ fn lint_line_untaken_positive_indents( if ip.closing_indent_balance() == closing_trough { target_point_idx = ip.idx; desired_indent = single_indent - .repeat((ip.closing_indent_balance() - ip.untaken_indents.len() as isize) as usize); + .repeat((ip.closing_indent_balance() - ip.relevant_untaken_count() as isize).max(0) as usize); break; } } @@ -829,7 +844,7 @@ fn lint_line_untaken_negative_indents( } let desired_indent = single_indent.repeat( - (ip.closing_indent_balance() - ip.untaken_indents.len() as isize + (ip.closing_indent_balance() - ip.relevant_untaken_count() as isize + forced_indents.len() as isize) .max(0) as usize, );