Skip to content

Commit 7fdb556

Browse files
authored
Strip form feeds from indent passed to dedent_to (#24381)
When adjusting "simple" indentation in the formation of edits, we attempt to dedent manually rather than deferring to LibCST. To do so we must provide a desired indentation, in the form of a string. We often grab this from source code by slicing the text in a range beginning at the start of a line. In Python, the start of a line may contain form feeds but these do not contribute to the indentation. In this PR, we strip the provided indentation of its leading form feeds in order to get the correct indentation amount for use in `dedent_to`. This avoids the introduction of a syntax error in the edit [`adjust_indentation`](https://github.com/astral-sh/ruff/blob/1f430e68af6e627569776dfbcd03b98ac7c29eb6/crates/ruff_linter/src/fix/edits.rs#L429). Note: We could try to stay closer to the user's intent by prepending the form feed prefix of the provided indentation _everywhere_ in the resulting edit, but that seems a little unwieldy and this is a bit of an edge case anyway. Closes #24373
1 parent 1f430e6 commit 7fdb556

3 files changed

Lines changed: 50 additions & 1 deletion

File tree

crates/ruff_linter/resources/test/fixtures/ruff/RUF072.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,12 @@
176176
1
177177
2
178178
finally:
179-
pass
179+
pass
180+
181+
182+
# Regression test for https://github.com/astral-sh/ruff/issues/24373
183+
# (`try` is preceded by a form feed below)
184+
try:
185+
1
186+
finally:
187+
pass

crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__preview__RUF072_RUF072.py.snap

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,3 +349,25 @@ help: Remove the `finally` clause
349349
- pass
350350
175 + 1
351351
176 + 2
352+
177 |
353+
178 |
354+
179 | # Regression test for https://github.com/astral-sh/ruff/issues/24373
355+
356+
RUF072 [*] Empty `finally` clause
357+
--> RUF072.py:186:1
358+
|
359+
184 | try:
360+
185 | 1
361+
186 | / finally:
362+
187 | | pass
363+
| |________^
364+
|
365+
help: Remove the `finally` clause
366+
181 |
367+
182 | # Regression test for https://github.com/astral-sh/ruff/issues/24373
368+
183 | # (`try` is preceded by a form feed below)
369+
- try:
370+
- 1
371+
- finally:
372+
- pass
373+
184 + 1

crates/ruff_python_trivia/src/textwrap.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ pub fn dedent(text: &str) -> Cow<'_, str> {
203203
/// # Panics
204204
/// If the first line is indented by less than the provided indent.
205205
pub fn dedent_to(text: &str, indent: &str) -> Option<String> {
206+
// The caller may provide an `indent` from source code by taking
207+
// a range of text beginning with the start of a line. In Python,
208+
// while a line may begin with form feeds, these do not contribute
209+
// to the indentation. So we strip those here.
210+
let indent = indent.trim_start_matches('\x0C');
206211
// Look at the indentation of the first non-empty line, to determine the "baseline" indentation.
207212
let mut first_comment_indent = None;
208213
let existing_indent_len = text
@@ -753,4 +758,18 @@ mod tests {
753758
].join("");
754759
assert_eq!(dedent_to(&x, ""), Some(y));
755760
}
761+
762+
#[test]
763+
#[rustfmt::skip]
764+
fn dedent_to_ignores_leading_form_feeds_in_provided_indentation() {
765+
let x = [
766+
" 1",
767+
" 2",
768+
].join("\n");
769+
let y = [
770+
"1",
771+
"2",
772+
].join("\n");
773+
assert_eq!(dedent_to(&x, "\x0C\x0C"), Some(y));
774+
}
756775
}

0 commit comments

Comments
 (0)