Indent statements in suppressed ranges#6507
Conversation
|
Current dependencies on/for this PR:
This comment was auto-generated by Graphite. |
PR Check ResultsEcosystem✅ ecosystem check detected no changes. BenchmarkLinuxWindows |
ce43cf6 to
09bc0d9
Compare
33e5b05 to
0883745
Compare
0883745 to
e4b26f2
Compare
613d18e to
5622dac
Compare
e4b26f2 to
12f9bbc
Compare
crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/.editorconfig
Show resolved
Hide resolved
| /// This implementation makes use of this fact and assumes a tab size of 1. | ||
| /// * The source document is correctly indented because it is valid Python code (or the formatter would have failed parsing the code). | ||
| #[derive(Copy, Clone)] | ||
| struct Indentation(u32); |
There was a problem hiding this comment.
There's already an Indentation in ruff_python_parser, do we want to give this one a different name?
There was a problem hiding this comment.
Do you have a recommendation? I wasn't able to come up with a good name.
I'm not too concerned about the naming conflict, considering that this is a private type.
| /// Notice how the `not_formatted + b` expression statement gets the same indentation as the `print` statement above, | ||
| /// but the indentation of the expression remains unchanged. It changes the indentation to: | ||
| /// * Prevent syntax errors because of different indentation levels between formatted and suppressed statements. | ||
| /// * Align with the `fmt: skip` where statements are indented as well, but inner expressions are formatted as is. |
There was a problem hiding this comment.
i like the docstring solution of only stripping the shared leading indentation, through docstring we would also already have the utils for that, except for own line comments.
There was a problem hiding this comment.
I would like that too. But we would need to track two different indentations:
- One to strip before statements
- The shared leading indentation, for comments
It may otherwise result in invalid code if a comment has less indentation than the statements. I think we consider introducing this complexity if we get reports that our fmt: off breaks the intended formatting (or e.g. test if the entire suite is disabled, and if so, don't fix up the indent)
| // Is there any remaining content after the last token? If so, return it as the last | ||
| // logical line. | ||
| return if self.last_line_end < self.content_end { | ||
| let content_start = self.last_line_end; | ||
| self.last_line_end = self.content_end; | ||
| Some(Ok(LogicalLine { | ||
| content_range: TextRange::new(content_start, self.content_end), | ||
| contains_newlines, | ||
| has_trailing_newline: false, |
There was a problem hiding this comment.
what would that content be and how do we know whether it contains newlines?
There was a problem hiding this comment.
I extended the comment to mention what content it is and changed contains_newlines to always be No because the lexer would otherwise return a Newline token.
crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/indent.py
Show resolved
Hide resolved
5622dac to
05cbaab
Compare
12f9bbc to
bdab1c2
Compare
bdab1c2 to
df98068
Compare

Summary
This PR implements logic to fix up the indentation of suppressed statement ranges to prevent that formatting the following file results in a syntax error:
fmt: skipandfmt: offbehavior (re-indents the statement, but not its content)It may be a bit surprising that this PR also changes the indentation of comments. This is necessary to avoid that a comment getting associated with a different node after formatting once, if the indentation sequence changed:
For example, if we format the following with an indent of 4 spaces:
The output without re-indenting comments would be:
This results in an instability because the end of body comments of
testnow have a smaller indentation thanpass, resulting in the formatter associating these as trailing comments of the functiontestrather than thepassstatement. Now,fmt: onsuddenly re-enables formatting ofdisabled + formatting;The re-formatting of comments and statements may be controversial inside of a
fmt: off..fmt: onregion but the benefits of being able to format files with suppressed ranges rather than just failing if the indentations end up miss matching outweighs the maybe surprising behavior mainly because it results in no chance if the statements are correctly indented.Test Plan
I added new test cases, including test cases with mixed indentation.