mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-18 11:41:21 +00:00
Merge 4c7765877d into 665f68036c
This commit is contained in:
commit
f50d3e8bbd
3 changed files with 100 additions and 22 deletions
|
|
@ -193,3 +193,20 @@ def foo():
|
||||||
not (aaaaaaaaaaaaaaaaaaaaa[bbbbbbbb, ccccccc]) and dddddddddd < eeeeeeeeeeeeeee
|
not (aaaaaaaaaaaaaaaaaaaaa[bbbbbbbb, ccccccc]) and dddddddddd < eeeeeeeeeeeeeee
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Regression tests for https://github.com/astral-sh/ruff/issues/19226
|
||||||
|
if '' and (not #
|
||||||
|
0):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if '' and (
|
||||||
|
# unary comment
|
||||||
|
not
|
||||||
|
# operand comment
|
||||||
|
(
|
||||||
|
# comment
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
)
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
|
||||||
|
|
@ -515,6 +515,44 @@ const fn is_simple_power_operand(expr: &Expr) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Safely checks if there's an `LParen` token between a comment and expression start,
|
||||||
|
/// with special handling for unary operations to avoid `TextRange` panics.
|
||||||
|
fn has_lparen_between_comment_and_expression(
|
||||||
|
comment: &SourceComment,
|
||||||
|
expression: &Expr,
|
||||||
|
source: &str,
|
||||||
|
) -> bool {
|
||||||
|
// For unary operations, we need to use the operand's start position instead of the
|
||||||
|
// expression's start position. This prevents panics when comments appear between
|
||||||
|
// the unary operator and its operand.
|
||||||
|
//
|
||||||
|
// Example that would panic without this fix:
|
||||||
|
// if '' and (
|
||||||
|
// not
|
||||||
|
// # comment
|
||||||
|
// 0):
|
||||||
|
// pass
|
||||||
|
//
|
||||||
|
// In this case:
|
||||||
|
// - expression.start() points to 'not'
|
||||||
|
// - comment.end() points after '#'
|
||||||
|
// - expression.start() < comment.end(), so TextRange::new would panic
|
||||||
|
// - comment.end() <= operand.start(), so using operand works correctly
|
||||||
|
let operand_start = match expression {
|
||||||
|
Expr::UnaryOp(unary_op) => unary_op.operand.start(),
|
||||||
|
_ => expression.start(),
|
||||||
|
};
|
||||||
|
let tokenizer = SimpleTokenizer::new(source, TextRange::new(comment.end(), operand_start));
|
||||||
|
|
||||||
|
matches!(
|
||||||
|
tokenizer.skip_trivia().next(),
|
||||||
|
Some(SimpleToken {
|
||||||
|
kind: SimpleTokenKind::LParen,
|
||||||
|
..
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Owned [`FlatBinaryExpressionSlice`]. Read the [`FlatBinaryExpressionSlice`] documentation for more details about the data structure.
|
/// Owned [`FlatBinaryExpressionSlice`]. Read the [`FlatBinaryExpressionSlice`] documentation for more details about the data structure.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct FlatBinaryExpression<'a>(SmallVec<[OperandOrOperator<'a>; 8]>);
|
struct FlatBinaryExpression<'a>(SmallVec<[OperandOrOperator<'a>; 8]>);
|
||||||
|
|
@ -837,17 +875,8 @@ impl<'a> Operand<'a> {
|
||||||
if is_expression_parenthesized((*expression).into(), comments.ranges(), source) {
|
if is_expression_parenthesized((*expression).into(), comments.ranges(), source) {
|
||||||
leading.iter().any(|comment| {
|
leading.iter().any(|comment| {
|
||||||
!comment.is_formatted()
|
!comment.is_formatted()
|
||||||
&& matches!(
|
&& has_lparen_between_comment_and_expression(
|
||||||
SimpleTokenizer::new(
|
comment, expression, source,
|
||||||
source,
|
|
||||||
TextRange::new(comment.end(), expression.start()),
|
|
||||||
)
|
|
||||||
.skip_trivia()
|
|
||||||
.next(),
|
|
||||||
Some(SimpleToken {
|
|
||||||
kind: SimpleTokenKind::LParen,
|
|
||||||
..
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -923,17 +952,10 @@ impl Format<PyFormatContext<'_>> for Operand<'_> {
|
||||||
.iter()
|
.iter()
|
||||||
.rposition(|comment| {
|
.rposition(|comment| {
|
||||||
comment.is_unformatted()
|
comment.is_unformatted()
|
||||||
&& matches!(
|
&& has_lparen_between_comment_and_expression(
|
||||||
SimpleTokenizer::new(
|
comment,
|
||||||
|
expression,
|
||||||
f.context().source(),
|
f.context().source(),
|
||||||
TextRange::new(comment.end(), expression.start()),
|
|
||||||
)
|
|
||||||
.skip_trivia()
|
|
||||||
.next(),
|
|
||||||
Some(SimpleToken {
|
|
||||||
kind: SimpleTokenKind::LParen,
|
|
||||||
..
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map_or(0, |position| position + 1);
|
.map_or(0, |position| position + 1);
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,23 @@ def foo():
|
||||||
not (aaaaaaaaaaaaaaaaaaaaa[bbbbbbbb, ccccccc]) and dddddddddd < eeeeeeeeeeeeeee
|
not (aaaaaaaaaaaaaaaaaaaaa[bbbbbbbb, ccccccc]) and dddddddddd < eeeeeeeeeeeeeee
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Regression tests for https://github.com/astral-sh/ruff/issues/19226
|
||||||
|
if '' and (not #
|
||||||
|
0):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if '' and (
|
||||||
|
# unary comment
|
||||||
|
not
|
||||||
|
# operand comment
|
||||||
|
(
|
||||||
|
# comment
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
)
|
||||||
|
):
|
||||||
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
@ -415,4 +432,26 @@ def foo():
|
||||||
not (aaaaaaaaaaaaaaaaaaaaa[bbbbbbbb, ccccccc]) and dddddddddd < eeeeeeeeeeeeeee
|
not (aaaaaaaaaaaaaaaaaaaaa[bbbbbbbb, ccccccc]) and dddddddddd < eeeeeeeeeeeeeee
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Regression tests for https://github.com/astral-sh/ruff/issues/19226
|
||||||
|
if "" and ( #
|
||||||
|
not 0
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if (
|
||||||
|
""
|
||||||
|
and
|
||||||
|
# unary comment
|
||||||
|
# operand comment
|
||||||
|
(
|
||||||
|
not (
|
||||||
|
# comment
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
pass
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue