Maybe parenthesize long constants and names (#6816)

This commit is contained in:
Micha Reiser 2023-08-24 11:47:57 +02:00 committed by GitHub
parent e4c13846e3
commit 04a9a8dd03
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 357 additions and 368 deletions

View file

@ -1,5 +1,5 @@
use ruff_formatter::prelude::tag::Condition;
use ruff_formatter::{format_args, write, Argument, Arguments};
use ruff_formatter::{format_args, write, Argument, Arguments, FormatContext, FormatOptions};
use ruff_python_ast::node::AnyNodeRef;
use ruff_python_ast::{ExpressionRef, Ranged};
use ruff_python_trivia::{first_non_trivia_token, SimpleToken, SimpleTokenKind, SimpleTokenizer};
@ -15,14 +15,37 @@ pub(crate) enum OptionalParentheses {
/// Add parentheses if the expression expands over multiple lines
Multiline,
/// Always set parentheses regardless if the expression breaks or if they were
/// Always set parentheses regardless if the expression breaks or if they are
/// present in the source.
Always,
/// Never add parentheses
/// Add parentheses if it helps to make this expression fit. Otherwise never add parentheses.
/// This mode should only be used for expressions that don't have their own split points, e.g. identifiers,
/// or constants.
BestFit,
/// Never add parentheses. Use it for expressions that have their own parentheses or if the expression body always spans multiple lines (multiline strings).
Never,
}
pub(super) fn should_use_best_fit<T>(value: T, context: &PyFormatContext) -> bool
where
T: Ranged,
{
let text_len = context.source()[value.range()].len();
// Only use best fits if:
// * The text is longer than 5 characters:
// This is to align the behavior with `True` and `False`, that don't use best fits and are 5 characters long.
// It allows to avoid [`OptionalParentheses::BestFit`] for most numbers and common identifiers like `self`.
// The downside is that it can result in short values not being parenthesized if they exceed the line width.
// This is considered an edge case not worth the performance penalty and IMO, breaking an identifier
// of 5 characters to avoid it exceeding the line width by 1 reduces the readability.
// * The text is know to never fit: The text can never fit even when parenthesizing if it is longer
// than the configured line width (minus indent).
text_len > 5 && text_len < context.options().line_width().value() as usize
}
pub(crate) trait NeedsParentheses {
/// Determines if this object needs optional parentheses or if it is safe to omit the parentheses.
fn needs_parentheses(