apply patch

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
Brent Westbrook 2025-12-09 08:51:59 -05:00
parent e8540d9b08
commit c7b1089631
No known key found for this signature in database
1 changed files with 79 additions and 58 deletions

View File

@ -1,10 +1,13 @@
use ruff_formatter::{FormatRuleWithOptions, RemoveSoftLinesBuffer, format_args, write}; use ruff_formatter::{FormatRuleWithOptions, RemoveSoftLinesBuffer, format_args, write};
use ruff_python_ast::{AnyNodeRef, Expr, ExprLambda}; use ruff_python_ast::{AnyNodeRef, Expr, ExprLambda};
use ruff_text_size::Ranged; use ruff_python_trivia::SimpleTokenizer;
use ruff_text_size::{Ranged, TextRange};
use crate::builders::parenthesize_if_expands; use crate::builders::parenthesize_if_expands;
use crate::comments::{dangling_comments, leading_comments, trailing_comments}; use crate::comments::{dangling_comments, leading_comments, trailing_comments};
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses}; use crate::expression::parentheses::{
NeedsParentheses, OptionalParentheses, Parentheses, is_expression_parenthesized,
};
use crate::expression::{CallChainLayout, has_own_parentheses}; use crate::expression::{CallChainLayout, has_own_parentheses};
use crate::other::parameters::ParametersParentheses; use crate::other::parameters::ParametersParentheses;
use crate::prelude::*; use crate::prelude::*;
@ -24,6 +27,9 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
body, body,
} = item; } = item;
let body = &**body;
let parameters = parameters.as_deref();
let comments = f.context().comments().clone(); let comments = f.context().comments().clone();
let dangling = comments.dangling(item); let dangling = comments.dangling(item);
let preview = is_parenthesize_lambda_bodies_enabled(f.context()); let preview = is_parenthesize_lambda_bodies_enabled(f.context());
@ -31,11 +37,24 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
write!(f, [token("lambda")])?; write!(f, [token("lambda")])?;
if let Some(parameters) = parameters { if let Some(parameters) = parameters {
let parameters_have_comments = comments.contains_comments(parameters.as_ref().into()); let parameters_have_comments = comments.contains_comments(parameters.into());
// In this context, a dangling comment can either be a comment between the `lambda` and the // In this context, a dangling comment can either be a comment between the `lambda` and the
// parameters, or a comment between the parameters and the body. // parameters, or a comment between the parameters and the body.
let (dangling_before_parameters, dangling_after_parameters) = let (dangling_before_parameters, dangling_after_parameters) = dangling
.split_at(dangling.partition_point(|comment| comment.end() < parameters.start()));
let (end_of_line_lambda_keyword_comments, leading_parameter_comments) = if preview {
dangling_before_parameters.split_at(
dangling_before_parameters
.iter()
.position(|comment| comment.line_position().is_own_line())
.unwrap_or(dangling_before_parameters.len()),
)
} else {
([].as_slice(), dangling_before_parameters)
};
// To prevent an instability in cases like: // To prevent an instability in cases like:
// //
// ```py // ```py
@ -71,18 +90,19 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
// x // x
// ) // )
// ``` // ```
if preview && !parameters_have_comments {
([].as_slice(), dangling)
} else {
dangling.split_at(
dangling.partition_point(|comment| comment.end() < parameters.start()),
)
};
if dangling_before_parameters.is_empty() { trailing_comments(end_of_line_lambda_keyword_comments).fmt(f)?;
if leading_parameter_comments.is_empty() && !comments.has_leading(parameters) {
write!(f, [space()])?; write!(f, [space()])?;
} else { } else {
write!(f, [dangling_comments(dangling_before_parameters)])?; write!(
f,
[
hard_line_break(),
leading_comments(leading_parameter_comments)
]
)?;
} }
// Try to keep the parameters on a single line, unless there are intervening comments. // Try to keep the parameters on a single line, unless there are intervening comments.
@ -124,7 +144,8 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
// ``` // ```
// //
// and alternate between own line and end of line. // and alternate between own line and end of line.
let (dangling_end_of_line, dangling_own_line) = dangling_after_parameters.split_at( let (after_parameters_end_of_line, leading_body_comments) =
dangling_after_parameters.split_at(
dangling_after_parameters dangling_after_parameters
.iter() .iter()
.position(|comment| comment.line_position().is_own_line()) .position(|comment| comment.line_position().is_own_line())
@ -137,9 +158,9 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
[ [
space(), space(),
token("("), token("("),
trailing_comments(dangling_end_of_line), trailing_comments(after_parameters_end_of_line),
block_indent(&format_args!( block_indent(&format_args!(
leading_comments(dangling_own_line), leading_comments(leading_body_comments),
body.format().with_options(Parentheses::Never) body.format().with_options(Parentheses::Never)
)), )),
token(")") token(")")
@ -196,7 +217,7 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
} }
if preview { if preview {
let body_comments = comments.leading_dangling_trailing(&**body); let body_comments = comments.leading_dangling_trailing(body);
let fmt_body = format_with(|f: &mut PyFormatter| { let fmt_body = format_with(|f: &mut PyFormatter| {
// If the body has comments, we always want to preserve the parentheses. This also // If the body has comments, we always want to preserve the parentheses. This also
// ensures that we correctly handle parenthesized comments, and don't need to worry // ensures that we correctly handle parenthesized comments, and don't need to worry
@ -232,7 +253,7 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
// ), // ),
// ) // )
// ``` // ```
else if matches!(&**body, Expr::Call(_) | Expr::Subscript(_)) { else if matches!(body, Expr::Call(_) | Expr::Subscript(_)) {
let unparenthesized = body.format().with_options(Parentheses::Never); let unparenthesized = body.format().with_options(Parentheses::Never);
if CallChainLayout::from_expression( if CallChainLayout::from_expression(
body.into(), body.into(),