mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 05:15:12 +00:00
parent
a95deec00f
commit
424b720c19
62 changed files with 1799 additions and 3890 deletions
|
@ -7,7 +7,6 @@ use crate::comments::{leading_comments, trailing_comments};
|
|||
use crate::expression::expr_tuple::TupleParentheses;
|
||||
use crate::expression::parentheses::is_expression_parenthesized;
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_comprehension_leading_expression_comments_same_line_enabled;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FormatComprehension;
|
||||
|
@ -36,14 +35,12 @@ impl FormatNodeRule<Comprehension> for FormatComprehension {
|
|||
// )
|
||||
// ]
|
||||
// ```
|
||||
let will_be_parenthesized =
|
||||
is_comprehension_leading_expression_comments_same_line_enabled(f.context())
|
||||
&& self.preserve_parentheses
|
||||
&& is_expression_parenthesized(
|
||||
self.expression.into(),
|
||||
f.context().comments().ranges(),
|
||||
f.context().source(),
|
||||
);
|
||||
let will_be_parenthesized = self.preserve_parentheses
|
||||
&& is_expression_parenthesized(
|
||||
self.expression.into(),
|
||||
f.context().comments().ranges(),
|
||||
f.context().source(),
|
||||
);
|
||||
|
||||
if has_leading_comments && !will_be_parenthesized {
|
||||
soft_line_break_or_space().fmt(f)
|
||||
|
|
|
@ -4,8 +4,7 @@ use ruff_source_file::LineRanges;
|
|||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_f_string_formatting_enabled;
|
||||
use crate::string::{Quoting, StringNormalizer, StringQuotes};
|
||||
use crate::string::{StringNormalizer, StringQuotes};
|
||||
|
||||
use super::f_string_element::FormatFStringElement;
|
||||
|
||||
|
@ -13,66 +12,25 @@ use super::f_string_element::FormatFStringElement;
|
|||
///
|
||||
/// For example, this would be used to format the f-string part in `"foo" f"bar {x}"`
|
||||
/// or the standalone f-string in `f"foo {x} bar"`.
|
||||
pub(crate) struct FormatFString<'a> {
|
||||
value: &'a FString,
|
||||
/// The quoting of an f-string. This is determined by the parent node
|
||||
/// (f-string expression) and is required to format an f-string correctly.
|
||||
quoting: Quoting,
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct FormatFString;
|
||||
|
||||
impl<'a> FormatFString<'a> {
|
||||
pub(crate) fn new(value: &'a FString, quoting: Quoting) -> Self {
|
||||
Self { value, quoting }
|
||||
}
|
||||
}
|
||||
impl FormatNodeRule<FString> for FormatFString {
|
||||
fn fmt_fields(&self, item: &FString, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let normalizer = StringNormalizer::from_context(f.context());
|
||||
|
||||
impl Format<PyFormatContext<'_>> for FormatFString<'_> {
|
||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
// If the preview style is enabled, make the decision on what quotes to use locally for each
|
||||
// f-string instead of globally for the entire f-string expression.
|
||||
let quoting = if is_f_string_formatting_enabled(f.context()) {
|
||||
Quoting::CanChange
|
||||
} else {
|
||||
self.quoting
|
||||
};
|
||||
|
||||
let normalizer = StringNormalizer::from_context(f.context()).with_quoting(quoting);
|
||||
|
||||
// If f-string formatting is disabled (not in preview), then we will
|
||||
// fall back to the previous behavior of normalizing the f-string.
|
||||
if !is_f_string_formatting_enabled(f.context()) {
|
||||
let result = normalizer.normalize(self.value.into()).fmt(f);
|
||||
let comments = f.context().comments();
|
||||
self.value.elements.iter().for_each(|value| {
|
||||
comments.mark_verbatim_node_comments_formatted(value.into());
|
||||
// Above method doesn't mark the trailing comments of the f-string elements
|
||||
// as formatted, so we need to do it manually. For example,
|
||||
//
|
||||
// ```python
|
||||
// f"""foo {
|
||||
// x:.3f
|
||||
// # comment
|
||||
// }"""
|
||||
// ```
|
||||
for trailing_comment in comments.trailing(value) {
|
||||
trailing_comment.mark_formatted();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
let string_kind = normalizer.choose_quotes(self.value.into()).flags();
|
||||
let string_kind = normalizer.choose_quotes(item.into()).flags();
|
||||
|
||||
let context = FStringContext::new(
|
||||
string_kind,
|
||||
FStringLayout::from_f_string(self.value, f.context().source()),
|
||||
FStringLayout::from_f_string(item, f.context().source()),
|
||||
);
|
||||
|
||||
// Starting prefix and quote
|
||||
let quotes = StringQuotes::from(string_kind);
|
||||
write!(f, [string_kind.prefix(), quotes])?;
|
||||
|
||||
for element in &self.value.elements {
|
||||
for element in &item.elements {
|
||||
FormatFStringElement::new(element, context).fmt(f)?;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,7 @@ impl<'a> FormatFStringLiteralElement<'a> {
|
|||
impl Format<PyFormatContext<'_>> for FormatFStringLiteralElement<'_> {
|
||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let literal_content = f.context().source().slice(self.element);
|
||||
let normalized =
|
||||
normalize_string(literal_content, 0, self.fstring_flags, false, false, true);
|
||||
let normalized = normalize_string(literal_content, 0, self.fstring_flags, false);
|
||||
match &normalized {
|
||||
Cow::Borrowed(_) => source_text_slice(self.element.range()).fmt(f),
|
||||
Cow::Owned(normalized) => text(normalized).fmt(f),
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
use ruff_formatter::{write, FormatRuleWithOptions};
|
||||
use ruff_python_ast::AstNode;
|
||||
use ruff_formatter::{format_args, write, FormatRuleWithOptions};
|
||||
use ruff_python_ast::MatchCase;
|
||||
|
||||
use crate::builders::parenthesize_if_expands;
|
||||
use crate::expression::maybe_parenthesize_expression;
|
||||
use crate::expression::parentheses::{
|
||||
NeedsParentheses, OptionalParentheses, Parentheses, Parenthesize,
|
||||
};
|
||||
use crate::expression::parentheses::Parenthesize;
|
||||
use crate::pattern::maybe_parenthesize_pattern;
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_match_case_parentheses_enabled;
|
||||
use crate::statement::clause::{clause_body, clause_header, ClauseHeader};
|
||||
use crate::statement::suite::SuiteKind;
|
||||
|
||||
|
@ -39,42 +34,12 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
|
|||
let comments = f.context().comments().clone();
|
||||
let dangling_item_comments = comments.dangling(item);
|
||||
|
||||
let format_pattern = format_with(|f| {
|
||||
if is_match_case_parentheses_enabled(f.context()) {
|
||||
maybe_parenthesize_pattern(pattern, item).fmt(f)
|
||||
} else {
|
||||
let has_comments =
|
||||
comments.has_leading(pattern) || comments.has_trailing_own_line(pattern);
|
||||
|
||||
if has_comments {
|
||||
pattern.format().with_options(Parentheses::Always).fmt(f)
|
||||
} else {
|
||||
match pattern.needs_parentheses(item.as_any_node_ref(), f.context()) {
|
||||
OptionalParentheses::Multiline => parenthesize_if_expands(
|
||||
&pattern.format().with_options(Parentheses::Never),
|
||||
)
|
||||
.fmt(f),
|
||||
OptionalParentheses::Always => {
|
||||
pattern.format().with_options(Parentheses::Always).fmt(f)
|
||||
}
|
||||
OptionalParentheses::Never | OptionalParentheses::BestFit => {
|
||||
pattern.format().with_options(Parentheses::Never).fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let format_guard = guard.as_deref().map(|guard| {
|
||||
format_with(|f| {
|
||||
write!(f, [space(), token("if"), space()])?;
|
||||
|
||||
if is_match_case_parentheses_enabled(f.context()) {
|
||||
maybe_parenthesize_expression(guard, item, Parenthesize::IfBreaksParenthesized)
|
||||
.fmt(f)
|
||||
} else {
|
||||
guard.format().fmt(f)
|
||||
}
|
||||
maybe_parenthesize_expression(guard, item, Parenthesize::IfBreaksParenthesized)
|
||||
.fmt(f)
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -84,9 +49,12 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
|
|||
clause_header(
|
||||
ClauseHeader::MatchCase(item),
|
||||
dangling_item_comments,
|
||||
&format_with(|f| {
|
||||
write!(f, [token("case"), space(), format_pattern, format_guard])
|
||||
}),
|
||||
&format_args![
|
||||
token("case"),
|
||||
space(),
|
||||
maybe_parenthesize_pattern(pattern, item),
|
||||
format_guard
|
||||
],
|
||||
),
|
||||
clause_body(
|
||||
body,
|
||||
|
|
|
@ -2,8 +2,7 @@ use ruff_formatter::FormatRuleWithOptions;
|
|||
use ruff_python_ast::StringLiteral;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_f_string_implicit_concatenated_string_literal_quotes_enabled;
|
||||
use crate::string::{docstring, Quoting, StringNormalizer};
|
||||
use crate::string::{docstring, StringNormalizer};
|
||||
use crate::QuoteStyle;
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -28,12 +27,6 @@ pub enum StringLiteralKind {
|
|||
String,
|
||||
/// A string literal used as a docstring.
|
||||
Docstring,
|
||||
/// A string literal that is implicitly concatenated with an f-string. This
|
||||
/// makes the overall expression an f-string whose quoting detection comes
|
||||
/// from the parent node (f-string expression).
|
||||
#[deprecated]
|
||||
#[allow(private_interfaces)]
|
||||
InImplicitlyConcatenatedFString(Quoting),
|
||||
}
|
||||
|
||||
impl StringLiteralKind {
|
||||
|
@ -41,26 +34,6 @@ impl StringLiteralKind {
|
|||
pub(crate) const fn is_docstring(self) -> bool {
|
||||
matches!(self, StringLiteralKind::Docstring)
|
||||
}
|
||||
|
||||
/// Returns the quoting to be used for this string literal.
|
||||
fn quoting(self, context: &PyFormatContext) -> Quoting {
|
||||
match self {
|
||||
StringLiteralKind::String | StringLiteralKind::Docstring => Quoting::CanChange,
|
||||
#[allow(deprecated)]
|
||||
StringLiteralKind::InImplicitlyConcatenatedFString(quoting) => {
|
||||
// Allow string literals to pick the "optimal" quote character
|
||||
// even if any other fstring in the implicit concatenation uses an expression
|
||||
// containing a quote character.
|
||||
// TODO: Remove StringLiteralKind::InImplicitlyConcatenatedFString when promoting
|
||||
// this style to stable and remove the layout from `AnyStringPart::String`.
|
||||
if is_f_string_implicit_concatenated_string_literal_quotes_enabled(context) {
|
||||
Quoting::CanChange
|
||||
} else {
|
||||
quoting
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FormatNodeRule<StringLiteral> for FormatStringLiteral {
|
||||
|
@ -75,7 +48,6 @@ impl FormatNodeRule<StringLiteral> for FormatStringLiteral {
|
|||
};
|
||||
|
||||
let normalized = StringNormalizer::from_context(f.context())
|
||||
.with_quoting(self.layout.quoting(f.context()))
|
||||
.with_preferred_quote_style(quote_style)
|
||||
.normalize(item.into());
|
||||
|
||||
|
|
|
@ -6,9 +6,7 @@ use crate::expression::parentheses::{
|
|||
is_expression_parenthesized, parenthesized, Parentheses, Parenthesize,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::preview::{
|
||||
is_with_single_item_pre_39_enabled, is_with_single_target_parentheses_enabled,
|
||||
};
|
||||
use crate::preview::is_with_single_target_parentheses_enabled;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum WithItemLayout {
|
||||
|
@ -154,9 +152,7 @@ impl FormatNodeRule<WithItem> for FormatWithItem {
|
|||
}
|
||||
|
||||
WithItemLayout::Python38OrOlder { single } => {
|
||||
let parenthesize = if (single && is_with_single_item_pre_39_enabled(f.context()))
|
||||
|| is_parenthesized
|
||||
{
|
||||
let parenthesize = if single || is_parenthesized {
|
||||
Parenthesize::IfBreaks
|
||||
} else {
|
||||
Parenthesize::IfRequired
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue