mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-16 16:40:19 +00:00
Hug multiline-strings preview style (#9243)
This commit is contained in:
parent
6be73322da
commit
ac02d3aedd
16 changed files with 590 additions and 215 deletions
|
@ -17,11 +17,14 @@ use crate::context::{NodeLevel, WithNodeLevel};
|
|||
use crate::expression::expr_generator_exp::is_generator_parenthesized;
|
||||
use crate::expression::expr_tuple::is_tuple_parenthesized;
|
||||
use crate::expression::parentheses::{
|
||||
is_expression_parenthesized, optional_parentheses, parenthesized, NeedsParentheses,
|
||||
OptionalParentheses, Parentheses, Parenthesize,
|
||||
is_expression_parenthesized, optional_parentheses, parenthesized, HuggingStyle,
|
||||
NeedsParentheses, OptionalParentheses, Parentheses, Parenthesize,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_hug_parens_with_braces_and_square_brackets_enabled;
|
||||
use crate::preview::{
|
||||
is_hug_parens_with_braces_and_square_brackets_enabled, is_multiline_string_handling_enabled,
|
||||
};
|
||||
use crate::string::AnyString;
|
||||
|
||||
mod binary_like;
|
||||
pub(crate) mod expr_attribute;
|
||||
|
@ -126,7 +129,7 @@ impl FormatRule<Expr, PyFormatContext<'_>> for FormatExpr {
|
|||
let node_comments = comments.leading_dangling_trailing(expression);
|
||||
if !node_comments.has_leading() && !node_comments.has_trailing() {
|
||||
parenthesized("(", &format_expr, ")")
|
||||
.with_indent(!is_expression_huggable(expression, f.context()))
|
||||
.with_hugging(is_expression_huggable(expression, f.context()))
|
||||
.fmt(f)
|
||||
} else {
|
||||
format_with_parentheses_comments(expression, &node_comments, f)
|
||||
|
@ -444,7 +447,7 @@ impl Format<PyFormatContext<'_>> for MaybeParenthesizeExpression<'_> {
|
|||
OptionalParentheses::Never => match parenthesize {
|
||||
Parenthesize::IfBreaksOrIfRequired => {
|
||||
parenthesize_if_expands(&expression.format().with_options(Parentheses::Never))
|
||||
.with_indent(!is_expression_huggable(expression, f.context()))
|
||||
.with_indent(is_expression_huggable(expression, f.context()).is_none())
|
||||
.fmt(f)
|
||||
}
|
||||
|
||||
|
@ -1084,7 +1087,7 @@ pub(crate) fn has_own_parentheses(
|
|||
}
|
||||
|
||||
/// Returns `true` if the expression can hug directly to enclosing parentheses, as in Black's
|
||||
/// `hug_parens_with_braces_and_square_brackets` preview style behavior.
|
||||
/// `hug_parens_with_braces_and_square_brackets` or `multiline_string_handling` preview styles behavior.
|
||||
///
|
||||
/// For example, in preview style, given:
|
||||
/// ```python
|
||||
|
@ -1110,11 +1113,10 @@ pub(crate) fn has_own_parentheses(
|
|||
/// ]
|
||||
/// )
|
||||
/// ```
|
||||
pub(crate) fn is_expression_huggable(expr: &Expr, context: &PyFormatContext) -> bool {
|
||||
if !is_hug_parens_with_braces_and_square_brackets_enabled(context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub(crate) fn is_expression_huggable(
|
||||
expr: &Expr,
|
||||
context: &PyFormatContext,
|
||||
) -> Option<HuggingStyle> {
|
||||
match expr {
|
||||
Expr::Tuple(_)
|
||||
| Expr::List(_)
|
||||
|
@ -1122,18 +1124,14 @@ pub(crate) fn is_expression_huggable(expr: &Expr, context: &PyFormatContext) ->
|
|||
| Expr::Dict(_)
|
||||
| Expr::ListComp(_)
|
||||
| Expr::SetComp(_)
|
||||
| Expr::DictComp(_) => true,
|
||||
| Expr::DictComp(_) => is_hug_parens_with_braces_and_square_brackets_enabled(context)
|
||||
.then_some(HuggingStyle::Always),
|
||||
|
||||
Expr::Starred(ast::ExprStarred { value, .. }) => matches!(
|
||||
value.as_ref(),
|
||||
Expr::Tuple(_)
|
||||
| Expr::List(_)
|
||||
| Expr::Set(_)
|
||||
| Expr::Dict(_)
|
||||
| Expr::ListComp(_)
|
||||
| Expr::SetComp(_)
|
||||
| Expr::DictComp(_)
|
||||
),
|
||||
Expr::Starred(ast::ExprStarred { value, .. }) => is_expression_huggable(value, context),
|
||||
|
||||
Expr::StringLiteral(string) => is_huggable_string(AnyString::String(string), context),
|
||||
Expr::BytesLiteral(bytes) => is_huggable_string(AnyString::Bytes(bytes), context),
|
||||
Expr::FString(fstring) => is_huggable_string(AnyString::FString(fstring), context),
|
||||
|
||||
Expr::BoolOp(_)
|
||||
| Expr::NamedExpr(_)
|
||||
|
@ -1147,18 +1145,28 @@ pub(crate) fn is_expression_huggable(expr: &Expr, context: &PyFormatContext) ->
|
|||
| Expr::YieldFrom(_)
|
||||
| Expr::Compare(_)
|
||||
| Expr::Call(_)
|
||||
| Expr::FString(_)
|
||||
| Expr::Attribute(_)
|
||||
| Expr::Subscript(_)
|
||||
| Expr::Name(_)
|
||||
| Expr::Slice(_)
|
||||
| Expr::IpyEscapeCommand(_)
|
||||
| Expr::StringLiteral(_)
|
||||
| Expr::BytesLiteral(_)
|
||||
| Expr::NumberLiteral(_)
|
||||
| Expr::BooleanLiteral(_)
|
||||
| Expr::NoneLiteral(_)
|
||||
| Expr::EllipsisLiteral(_) => false,
|
||||
| Expr::EllipsisLiteral(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if `string` is a multiline string that is not implicitly concatenated.
|
||||
fn is_huggable_string(string: AnyString, context: &PyFormatContext) -> Option<HuggingStyle> {
|
||||
if !is_multiline_string_handling_enabled(context) {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !string.is_implicit_concatenated() && string.is_multiline(context.source()) {
|
||||
Some(HuggingStyle::IfFirstLineFits)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue