mirror of https://github.com/astral-sh/ruff
74 lines
2.5 KiB
Rust
74 lines
2.5 KiB
Rust
use ruff_python_ast::{AnyStringFlags, InterpolatedStringElements};
|
|
use ruff_source_file::LineRanges;
|
|
use ruff_text_size::Ranged;
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub(crate) struct InterpolatedStringContext {
|
|
/// The string flags of the enclosing f/t-string part.
|
|
enclosing_flags: AnyStringFlags,
|
|
layout: InterpolatedStringLayout,
|
|
}
|
|
|
|
impl InterpolatedStringContext {
|
|
pub(crate) const fn new(flags: AnyStringFlags, layout: InterpolatedStringLayout) -> Self {
|
|
Self {
|
|
enclosing_flags: flags,
|
|
layout,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn flags(self) -> AnyStringFlags {
|
|
self.enclosing_flags
|
|
}
|
|
|
|
pub(crate) const fn is_multiline(self) -> bool {
|
|
matches!(self.layout, InterpolatedStringLayout::Multiline)
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub(crate) enum InterpolatedStringLayout {
|
|
/// Original f/t-string is flat.
|
|
/// Don't break expressions to keep the string flat.
|
|
Flat,
|
|
/// Original f/t-string has multiline expressions in the replacement fields.
|
|
/// Allow breaking expressions across multiple lines.
|
|
Multiline,
|
|
}
|
|
|
|
impl InterpolatedStringLayout {
|
|
// Heuristic: Allow breaking the f/t-string expressions across multiple lines
|
|
// only if there already is at least one multiline expression. This puts the
|
|
// control in the hands of the user to decide if they want to break the
|
|
// f/t-string expressions across multiple lines or not. This is similar to
|
|
// how Prettier does it for template literals in JavaScript.
|
|
//
|
|
// If it's single quoted f-string and it contains a multiline expression, then we
|
|
// assume that the target version of Python supports it (3.12+). If there are comments
|
|
// used in any of the expression of the f-string, then it's always going to be multiline
|
|
// and we assume that the target version of Python supports it (3.12+).
|
|
//
|
|
// Reference: https://prettier.io/docs/en/next/rationale.html#template-literals
|
|
pub(crate) fn from_interpolated_string_elements(
|
|
elements: &InterpolatedStringElements,
|
|
source: &str,
|
|
) -> Self {
|
|
if elements
|
|
.interpolations()
|
|
.any(|expr| source.contains_line_break(expr.range()))
|
|
{
|
|
Self::Multiline
|
|
} else {
|
|
Self::Flat
|
|
}
|
|
}
|
|
|
|
pub(crate) const fn is_flat(self) -> bool {
|
|
matches!(self, InterpolatedStringLayout::Flat)
|
|
}
|
|
|
|
pub(crate) const fn is_multiline(self) -> bool {
|
|
matches!(self, InterpolatedStringLayout::Multiline)
|
|
}
|
|
}
|