mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00
Extract LineIndex
independent methods from Locator
(#13938)
This commit is contained in:
parent
f8eb547fb4
commit
9f3a38d408
171 changed files with 1348 additions and 1284 deletions
|
@ -2,23 +2,22 @@
|
|||
// "reStructuredText."
|
||||
#![allow(clippy::doc_markdown)]
|
||||
|
||||
use itertools::Itertools;
|
||||
use std::cmp::Ordering;
|
||||
use std::sync::LazyLock;
|
||||
use std::{borrow::Cow, collections::VecDeque};
|
||||
|
||||
use itertools::Itertools;
|
||||
use regex::Regex;
|
||||
|
||||
use ruff_formatter::printer::SourceMapGeneration;
|
||||
use ruff_python_ast::{str::Quote, AnyStringFlags, StringFlags};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use {
|
||||
ruff_formatter::{write, FormatOptions, IndentStyle, LineWidth, Printed},
|
||||
ruff_python_trivia::{is_python_whitespace, PythonWhitespace},
|
||||
ruff_source_file::Locator,
|
||||
ruff_text_size::{Ranged, TextLen, TextRange, TextSize},
|
||||
};
|
||||
|
||||
use super::NormalizedString;
|
||||
use crate::preview::{
|
||||
is_docstring_code_block_in_docstring_indent_enabled,
|
||||
is_join_implicit_concatenated_string_enabled,
|
||||
|
@ -26,6 +25,8 @@ use crate::preview::{
|
|||
use crate::string::StringQuotes;
|
||||
use crate::{prelude::*, DocstringCodeLineWidth, FormatModuleError};
|
||||
|
||||
use super::NormalizedString;
|
||||
|
||||
/// Format a docstring by trimming whitespace and adjusting the indentation.
|
||||
///
|
||||
/// Summary of changes we make:
|
||||
|
@ -1592,9 +1593,8 @@ fn docstring_format_source(
|
|||
let comment_ranges = CommentRanges::from(parsed.tokens());
|
||||
let source_code = ruff_formatter::SourceCode::new(source);
|
||||
let comments = crate::Comments::from_ast(parsed.syntax(), source_code, &comment_ranges);
|
||||
let locator = Locator::new(source);
|
||||
|
||||
let ctx = PyFormatContext::new(options, locator.contents(), comments, parsed.tokens())
|
||||
let ctx = PyFormatContext::new(options, source, comments, parsed.tokens())
|
||||
.in_docstring(docstring_quote_style);
|
||||
let formatted = crate::format!(ctx, [parsed.syntax().format()])?;
|
||||
formatted
|
||||
|
|
|
@ -6,6 +6,7 @@ use ruff_python_ast::str_prefix::{
|
|||
AnyStringPrefix, ByteStringPrefix, FStringPrefix, StringLiteralPrefix,
|
||||
};
|
||||
use ruff_python_ast::{AnyStringFlags, FStringElement, StringFlags, StringLike, StringLikePart};
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::comments::{leading_comments, trailing_comments};
|
||||
|
@ -72,7 +73,7 @@ impl<'a> FormatImplicitConcatenatedStringExpanded<'a> {
|
|||
impl Format<PyFormatContext<'_>> for FormatImplicitConcatenatedStringExpanded<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||
let comments = f.context().comments().clone();
|
||||
let quoting = self.string.quoting(&f.context().locator());
|
||||
let quoting = self.string.quoting(f.context().source());
|
||||
|
||||
let join_implicit_concatenated_string_enabled =
|
||||
is_join_implicit_concatenated_string_enabled(f.context());
|
||||
|
@ -158,10 +159,9 @@ impl<'a> FormatImplicitConcatenatedStringFlat<'a> {
|
|||
if let StringLikePart::FString(fstring) = part {
|
||||
if fstring.elements.iter().any(|element| match element {
|
||||
// Same as for other literals. Multiline literals can't fit on a single line.
|
||||
FStringElement::Literal(literal) => context
|
||||
.locator()
|
||||
.slice(literal.range())
|
||||
.contains(['\n', '\r']),
|
||||
FStringElement::Literal(literal) => {
|
||||
context.source().contains_line_break(literal.range())
|
||||
}
|
||||
FStringElement::Expression(expression) => {
|
||||
if is_f_string_formatting_enabled(context) {
|
||||
// Expressions containing comments can't be joined.
|
||||
|
@ -169,7 +169,7 @@ impl<'a> FormatImplicitConcatenatedStringFlat<'a> {
|
|||
} else {
|
||||
// Multiline f-string expressions can't be joined if the f-string formatting is disabled because
|
||||
// the string gets inserted in verbatim preserving the newlines.
|
||||
context.locator().slice(expression).contains(['\n', '\r'])
|
||||
context.source().contains_line_break(expression.range())
|
||||
}
|
||||
}
|
||||
}) {
|
||||
|
@ -269,12 +269,7 @@ impl Format<PyFormatContext<'_>> for FormatImplicitConcatenatedStringFlat<'_> {
|
|||
for part in self.string.parts().rev() {
|
||||
assert!(part.is_string_literal());
|
||||
|
||||
if f.context()
|
||||
.locator()
|
||||
.slice(part.content_range())
|
||||
.trim()
|
||||
.is_empty()
|
||||
{
|
||||
if f.context().source()[part.content_range()].trim().is_empty() {
|
||||
// Don't format the part.
|
||||
parts.next_back();
|
||||
} else {
|
||||
|
@ -298,10 +293,7 @@ impl Format<PyFormatContext<'_>> for FormatImplicitConcatenatedStringFlat<'_> {
|
|||
.fmt(f)?;
|
||||
|
||||
if first_non_empty {
|
||||
first_non_empty = f
|
||||
.context()
|
||||
.locator()
|
||||
.slice(part.content_range())
|
||||
first_non_empty = f.context().source()[part.content_range()]
|
||||
.trim_start()
|
||||
.is_empty();
|
||||
}
|
||||
|
@ -328,7 +320,7 @@ impl Format<PyFormatContext<'_>> for FormatImplicitConcatenatedStringFlat<'_> {
|
|||
self.flags,
|
||||
FStringLayout::from_f_string(
|
||||
f_string,
|
||||
&f.context().locator(),
|
||||
f.context().source(),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -365,7 +357,7 @@ struct FormatLiteralContent {
|
|||
|
||||
impl Format<PyFormatContext<'_>> for FormatLiteralContent {
|
||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let content = f.context().locator().slice(self.range);
|
||||
let content = &f.context().source()[self.range];
|
||||
let mut normalized = normalize_string(
|
||||
content,
|
||||
0,
|
||||
|
|
|
@ -7,7 +7,6 @@ use ruff_python_ast::{
|
|||
str_prefix::{AnyStringPrefix, StringLiteralPrefix},
|
||||
AnyStringFlags, StringFlags,
|
||||
};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::expression::expr_f_string::f_string_quoting;
|
||||
|
@ -89,16 +88,16 @@ impl From<Quote> for QuoteStyle {
|
|||
|
||||
// Extension trait that adds formatter specific helper methods to `StringLike`.
|
||||
pub(crate) trait StringLikeExtensions {
|
||||
fn quoting(&self, locator: &Locator<'_>) -> Quoting;
|
||||
fn quoting(&self, source: &str) -> Quoting;
|
||||
|
||||
fn is_multiline(&self, source: &str) -> bool;
|
||||
}
|
||||
|
||||
impl StringLikeExtensions for ast::StringLike<'_> {
|
||||
fn quoting(&self, locator: &Locator<'_>) -> Quoting {
|
||||
fn quoting(&self, source: &str) -> Quoting {
|
||||
match self {
|
||||
Self::String(_) | Self::Bytes(_) => Quoting::CanChange,
|
||||
Self::FString(f_string) => f_string_quoting(f_string, locator),
|
||||
Self::FString(f_string) => f_string_quoting(f_string, source),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use ruff_python_ast::visitor::source_order::SourceOrderVisitor;
|
|||
use ruff_python_ast::{
|
||||
str::Quote, AnyStringFlags, BytesLiteral, FString, StringFlags, StringLikePart, StringLiteral,
|
||||
};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
use ruff_text_size::{Ranged, TextRange, TextSlice};
|
||||
|
||||
use crate::context::FStringState;
|
||||
use crate::prelude::*;
|
||||
|
@ -152,7 +152,7 @@ impl<'a, 'src> StringNormalizer<'a, 'src> {
|
|||
|
||||
/// Computes the strings preferred quotes.
|
||||
pub(crate) fn choose_quotes(&self, string: StringLikePart) -> QuoteSelection {
|
||||
let raw_content = self.context.locator().slice(string.content_range());
|
||||
let raw_content = &self.context.source()[string.content_range()];
|
||||
let first_quote_or_normalized_char_offset = raw_content
|
||||
.bytes()
|
||||
.position(|b| matches!(b, b'\\' | b'"' | b'\'' | b'\r' | b'{'));
|
||||
|
@ -196,7 +196,7 @@ impl<'a, 'src> StringNormalizer<'a, 'src> {
|
|||
|
||||
/// Computes the strings preferred quotes and normalizes its content.
|
||||
pub(crate) fn normalize(&self, string: StringLikePart) -> NormalizedString<'src> {
|
||||
let raw_content = self.context.locator().slice(string.content_range());
|
||||
let raw_content = &self.context.source()[string.content_range()];
|
||||
let quote_selection = self.choose_quotes(string);
|
||||
|
||||
let normalized = if let Some(first_quote_or_escape_offset) =
|
||||
|
@ -256,7 +256,7 @@ impl QuoteMetadata {
|
|||
) -> Self {
|
||||
match part {
|
||||
StringLikePart::String(_) | StringLikePart::Bytes(_) => {
|
||||
let text = context.locator().slice(part.content_range());
|
||||
let text = &context.source()[part.content_range()];
|
||||
|
||||
Self::from_str(text, part.flags(), preferred_quote)
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ impl QuoteMetadata {
|
|||
};
|
||||
|
||||
let mut metadata = QuoteMetadata::from_str(
|
||||
context.locator().slice(first.range()),
|
||||
context.source().slice(first),
|
||||
fstring.flags.into(),
|
||||
preferred_quote,
|
||||
);
|
||||
|
@ -285,7 +285,7 @@ impl QuoteMetadata {
|
|||
for literal in literals {
|
||||
metadata = metadata
|
||||
.merge(&QuoteMetadata::from_str(
|
||||
context.locator().slice(literal.range()),
|
||||
context.source().slice(literal),
|
||||
fstring.flags.into(),
|
||||
preferred_quote,
|
||||
))
|
||||
|
@ -294,7 +294,7 @@ impl QuoteMetadata {
|
|||
|
||||
metadata
|
||||
} else {
|
||||
let text = context.locator().slice(part.content_range());
|
||||
let text = &context.source()[part.content_range()];
|
||||
|
||||
Self::from_str(text, part.flags(), preferred_quote)
|
||||
}
|
||||
|
@ -893,7 +893,7 @@ pub(super) fn is_fstring_with_quoted_debug_expression(
|
|||
) -> bool {
|
||||
if fstring.elements.expressions().any(|expression| {
|
||||
if expression.debug_text.is_some() {
|
||||
let content = context.locator().slice(expression.range());
|
||||
let content = context.source().slice(expression);
|
||||
match fstring.flags.quote_style() {
|
||||
Quote::Single => {
|
||||
if fstring.flags.is_triple_quoted() {
|
||||
|
@ -969,10 +969,7 @@ pub(super) fn is_fstring_with_triple_quoted_literal_expression_containing_quotes
|
|||
}
|
||||
|
||||
fn contains_quote(&self, range: TextRange, flags: AnyStringFlags) -> bool {
|
||||
self.context
|
||||
.locator()
|
||||
.slice(range)
|
||||
.contains(flags.quote_style().as_char())
|
||||
self.context.source()[range].contains(flags.quote_style().as_char())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue