Insert newline between docstring and following own line comment (#8216)

**Summary** Previously, own line comment following after a docstring
followed by newline(s) before the first content statement were treated
as trailing on the docstring and we didn't insert a newline after the
docstring as black would.

Before:
```python
class ModuleBrowser:
    """Browse module classes and functions in IDLE."""
    # This class is also the base class for pathbrowser.PathBrowser.

    def __init__(self, master, path, *, _htest=False, _utest=False):
        pass
```
After:
```python
class ModuleBrowser:
    """Browse module classes and functions in IDLE."""

    # This class is also the base class for pathbrowser.PathBrowser.

    def __init__(self, master, path, *, _htest=False, _utest=False):
        pass
```

I'm not entirely happy about hijacking
`handle_own_line_comment_between_statements`, but i don't know a better
spot to put it.

Fixes #7948

**Test Plan** Fixtures
This commit is contained in:
konsti 2023-10-30 14:18:54 +01:00 committed by GitHub
parent cf74debf42
commit b6c4074836
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 275 additions and 7 deletions

View file

@ -1,8 +1,9 @@
use std::cmp::Ordering;
use ruff_python_ast::whitespace::indentation;
use ruff_python_ast::AnyNodeRef;
use ruff_python_ast::{self as ast, Comprehension, Expr, MatchCase, ModModule, Parameters};
use ruff_python_ast::{
self as ast, AnyNodeRef, Comprehension, Expr, MatchCase, ModModule, Parameters,
};
use ruff_python_trivia::{
find_only_token_in_range, indentation_at_offset, BackwardsTokenizer, CommentRanges,
SimpleToken, SimpleTokenKind, SimpleTokenizer,
@ -544,6 +545,10 @@ fn handle_own_line_comment_between_statements<'a>(
return CommentPlacement::Default(comment);
}
if comment.line_position().is_end_of_line() {
return CommentPlacement::Default(comment);
}
// If the comment is directly attached to the following statement; make it a leading
// comment:
// ```python

View file

@ -584,9 +584,30 @@ impl Format<PyFormatContext<'_>> for DocstringStmt<'_> {
string_literal
.format()
.with_options(StringLayout::DocString),
trailing_comments(node_comments.trailing),
]
)
)?;
// Comments after docstrings need a newline between the docstring and the comment.
// (https://github.com/astral-sh/ruff/issues/7948)
// ```python
// class ModuleBrowser:
// """Browse module classes and functions in IDLE."""
// # ^ Insert a newline above here
//
// def __init__(self, master, path, *, _htest=False, _utest=False):
// pass
// ```
if let Some(own_line) = node_comments
.trailing
.iter()
.find(|comment| comment.line_position().is_own_line())
{
if lines_before(own_line.start(), f.context().source()) < 2 {
empty_line().fmt(f)?;
}
}
trailing_comments(node_comments.trailing).fmt(f)
}
}
}