mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 22:54:42 +00:00
Use correct start location for class/function clause header (#7802)
## Summary This PR fixes the bug where the formatter would panic if a class/function with decorators had a suppression comment. The fix is to use to correct start location to find the `async`/`def`/`class` keyword when decorators are present which is the end of the last decorator. ## Test Plan Add test cases for the fix and update the snapshots.
This commit is contained in:
parent
7b4fb4fb5d
commit
a1509dfc7c
3 changed files with 50 additions and 2 deletions
|
@ -17,3 +17,16 @@ class Test:
|
||||||
def test():
|
def test():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Regression test for https://github.com/astral-sh/ruff/issues/7735
|
||||||
|
@decorator1
|
||||||
|
@decorator2
|
||||||
|
class Foo: # fmt: skip
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Regression test for https://github.com/astral-sh/ruff/issues/7735
|
||||||
|
@decorator1
|
||||||
|
@decorator2
|
||||||
|
def foo(): # fmt: skip
|
||||||
|
pass
|
||||||
|
|
|
@ -203,15 +203,23 @@ impl<'a> ClauseHeader<'a> {
|
||||||
fn first_keyword_range(self, source: &str) -> FormatResult<TextRange> {
|
fn first_keyword_range(self, source: &str) -> FormatResult<TextRange> {
|
||||||
match self {
|
match self {
|
||||||
ClauseHeader::Class(header) => {
|
ClauseHeader::Class(header) => {
|
||||||
find_keyword(header.start(), SimpleTokenKind::Class, source)
|
let start_position = header
|
||||||
|
.decorator_list
|
||||||
|
.last()
|
||||||
|
.map_or_else(|| header.start(), Ranged::end);
|
||||||
|
find_keyword(start_position, SimpleTokenKind::Class, source)
|
||||||
}
|
}
|
||||||
ClauseHeader::Function(header) => {
|
ClauseHeader::Function(header) => {
|
||||||
|
let start_position = header
|
||||||
|
.decorator_list
|
||||||
|
.last()
|
||||||
|
.map_or_else(|| header.start(), Ranged::end);
|
||||||
let keyword = if header.is_async {
|
let keyword = if header.is_async {
|
||||||
SimpleTokenKind::Async
|
SimpleTokenKind::Async
|
||||||
} else {
|
} else {
|
||||||
SimpleTokenKind::Def
|
SimpleTokenKind::Def
|
||||||
};
|
};
|
||||||
find_keyword(header.start(), keyword, source)
|
find_keyword(start_position, keyword, source)
|
||||||
}
|
}
|
||||||
ClauseHeader::If(header) => find_keyword(header.start(), SimpleTokenKind::If, source),
|
ClauseHeader::If(header) => find_keyword(header.start(), SimpleTokenKind::If, source),
|
||||||
ClauseHeader::ElifElse(ElifElseClause {
|
ClauseHeader::ElifElse(ElifElseClause {
|
||||||
|
|
|
@ -23,6 +23,19 @@ class Test:
|
||||||
def test():
|
def test():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Regression test for https://github.com/astral-sh/ruff/issues/7735
|
||||||
|
@decorator1
|
||||||
|
@decorator2
|
||||||
|
class Foo: # fmt: skip
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Regression test for https://github.com/astral-sh/ruff/issues/7735
|
||||||
|
@decorator1
|
||||||
|
@decorator2
|
||||||
|
def foo(): # fmt: skip
|
||||||
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
@ -43,6 +56,20 @@ class Test:
|
||||||
# leading class comment
|
# leading class comment
|
||||||
def test():
|
def test():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Regression test for https://github.com/astral-sh/ruff/issues/7735
|
||||||
|
@decorator1
|
||||||
|
@decorator2
|
||||||
|
class Foo: # fmt: skip
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Regression test for https://github.com/astral-sh/ruff/issues/7735
|
||||||
|
@decorator1
|
||||||
|
@decorator2
|
||||||
|
def foo(): # fmt: skip
|
||||||
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue