mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-01 16:17:53 +00:00
Correctly handle newlines after/before comments (#4895)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary This issue fixes the removal of empty lines between a leading comment and the previous statement: ```python a = 20 # leading comment b = 10 ``` Ruff removed the empty line between `a` and `b` because: * The leading comments formatting does not preserve leading newlines (to avoid adding new lines at the top of a body) * The `JoinNodesBuilder` counted the lines before `b`, which is 1 -> Doesn't insert a new line This is fixed by changing the `JoinNodesBuilder` to count the lines instead *after* the last node. This correctly gives 1, and the `# leading comment` will insert the empty lines between any other leading comment or the node. ## Test Plan I added a new test for empty lines.
This commit is contained in:
parent
222ca98a41
commit
6ab3fc60f4
19 changed files with 332 additions and 124 deletions
|
@ -146,6 +146,33 @@ pub(crate) fn lines_after(offset: TextSize, code: &str) -> u32 {
|
|||
newlines
|
||||
}
|
||||
|
||||
/// Returns the position after skipping any trailing trivia up to, but not including the newline character.
|
||||
pub(crate) fn skip_trailing_trivia(offset: TextSize, code: &str) -> TextSize {
|
||||
let rest = &code[usize::from(offset)..];
|
||||
let mut iter = rest.char_indices();
|
||||
|
||||
while let Some((relative_offset, c)) = iter.next() {
|
||||
match c {
|
||||
'\n' | '\r' => return offset + TextSize::try_from(relative_offset).unwrap(),
|
||||
'#' => {
|
||||
// Skip the comment
|
||||
let newline_offset = iter
|
||||
.as_str()
|
||||
.find(['\n', '\r'])
|
||||
.unwrap_or(iter.as_str().len());
|
||||
|
||||
return offset
|
||||
+ TextSize::try_from(relative_offset + '#'.len_utf8() + newline_offset)
|
||||
.unwrap();
|
||||
}
|
||||
c if is_python_whitespace(c) => continue,
|
||||
_ => return offset + TextSize::try_from(relative_offset).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
offset + rest.text_len()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::trivia::{lines_after, lines_before};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue