mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:24:57 +00:00
Implement a common trait for the string flags (#11564)
This commit is contained in:
parent
6be00d5775
commit
246a3388ee
20 changed files with 184 additions and 153 deletions
|
@ -4,6 +4,7 @@ use std::iter::Peekable;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
use ruff_python_ast::StringFlags;
|
||||||
use ruff_python_parser::lexer::LexResult;
|
use ruff_python_parser::lexer::LexResult;
|
||||||
use ruff_python_parser::Tok;
|
use ruff_python_parser::Tok;
|
||||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use ruff_python_ast::AnyStringFlags;
|
use ruff_python_ast::{AnyStringFlags, StringFlags};
|
||||||
use ruff_text_size::TextLen;
|
use ruff_text_size::TextLen;
|
||||||
|
|
||||||
/// Returns the raw contents of the string given the string's contents and flags.
|
/// Returns the raw contents of the string given the string's contents and flags.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::visitor::{walk_f_string, Visitor};
|
use ruff_python_ast::visitor::{walk_f_string, Visitor};
|
||||||
use ruff_python_ast::{self as ast, AnyStringFlags, StringLike};
|
use ruff_python_ast::{self as ast, AnyStringFlags, StringFlags, StringLike};
|
||||||
use ruff_source_file::Locator;
|
use ruff_source_file::Locator;
|
||||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::{self as ast, AnyStringFlags, StringLike};
|
use ruff_python_ast::{self as ast, AnyStringFlags, StringFlags, StringLike};
|
||||||
use ruff_source_file::Locator;
|
use ruff_source_file::Locator;
|
||||||
use ruff_text_size::{Ranged, TextRange};
|
use ruff_text_size::{Ranged, TextRange};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::{AnyStringFlags, Expr, ExprStringLiteral};
|
use ruff_python_ast::{Expr, ExprStringLiteral, StringFlags, StringLiteral};
|
||||||
use ruff_python_literal::{
|
use ruff_python_literal::{
|
||||||
cformat::{CFormatErrorType, CFormatString},
|
cformat::{CFormatErrorType, CFormatString},
|
||||||
format::FormatPart,
|
format::FormatPart,
|
||||||
|
@ -90,9 +90,13 @@ pub(crate) fn call(checker: &mut Checker, string: &str, range: TextRange) {
|
||||||
/// PLE1300
|
/// PLE1300
|
||||||
/// Ex) `"%z" % "1"`
|
/// Ex) `"%z" % "1"`
|
||||||
pub(crate) fn percent(checker: &mut Checker, expr: &Expr, format_string: &ExprStringLiteral) {
|
pub(crate) fn percent(checker: &mut Checker, expr: &Expr, format_string: &ExprStringLiteral) {
|
||||||
for string_literal in &format_string.value {
|
for StringLiteral {
|
||||||
let string = checker.locator().slice(string_literal);
|
value: _,
|
||||||
let flags = AnyStringFlags::from(string_literal.flags);
|
range,
|
||||||
|
flags,
|
||||||
|
} in &format_string.value
|
||||||
|
{
|
||||||
|
let string = checker.locator().slice(range);
|
||||||
let string = &string
|
let string = &string
|
||||||
[usize::from(flags.opener_len())..(string.len() - usize::from(flags.closer_len()))];
|
[usize::from(flags.opener_len())..(string.len() - usize::from(flags.closer_len()))];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use ruff_python_ast::{self as ast, AnyStringFlags, Expr};
|
use ruff_python_ast::{self as ast, Expr, StringFlags, StringLiteral};
|
||||||
use ruff_python_literal::cformat::{CFormatPart, CFormatSpec, CFormatStrOrBytes, CFormatString};
|
use ruff_python_literal::cformat::{CFormatPart, CFormatSpec, CFormatStrOrBytes, CFormatString};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
@ -217,12 +217,15 @@ pub(crate) fn bad_string_format_type(
|
||||||
) {
|
) {
|
||||||
// Parse each string segment.
|
// Parse each string segment.
|
||||||
let mut format_strings = vec![];
|
let mut format_strings = vec![];
|
||||||
for string_literal in &format_string.value {
|
for StringLiteral {
|
||||||
let string = checker.locator().slice(string_literal);
|
value: _,
|
||||||
let flags = AnyStringFlags::from(string_literal.flags);
|
range,
|
||||||
let quote_len = usize::from(flags.quote_len());
|
flags,
|
||||||
let string =
|
} in &format_string.value
|
||||||
&string[(usize::from(flags.prefix_len()) + quote_len)..(string.len() - quote_len)];
|
{
|
||||||
|
let string = checker.locator().slice(range);
|
||||||
|
let string = &string
|
||||||
|
[usize::from(flags.opener_len())..(string.len() - usize::from(flags.closer_len()))];
|
||||||
|
|
||||||
// Parse the format string (e.g. `"%s"`) into a list of `PercentFormat`.
|
// Parse the format string (e.g. `"%s"`) into a list of `PercentFormat`.
|
||||||
if let Ok(format_string) = CFormatString::from_str(string) {
|
if let Ok(format_string) = CFormatString::from_str(string) {
|
||||||
|
|
|
@ -3,8 +3,7 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::whitespace::indentation;
|
use ruff_python_ast::{self as ast, whitespace::indentation, AnyStringFlags, Expr, StringFlags};
|
||||||
use ruff_python_ast::{self as ast, AnyStringFlags, Expr};
|
|
||||||
use ruff_python_codegen::Stylist;
|
use ruff_python_codegen::Stylist;
|
||||||
use ruff_python_literal::cformat::{
|
use ruff_python_literal::cformat::{
|
||||||
CConversionFlags, CFormatPart, CFormatPrecision, CFormatQuantity, CFormatString,
|
CConversionFlags, CFormatPart, CFormatPrecision, CFormatQuantity, CFormatString,
|
||||||
|
|
|
@ -1351,6 +1351,64 @@ impl Ranged for FStringPart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait StringFlags: Copy {
|
||||||
|
/// Does the string use single or double quotes in its opener and closer?
|
||||||
|
fn quote_style(self) -> Quote;
|
||||||
|
|
||||||
|
/// Is the string triple-quoted, i.e.,
|
||||||
|
/// does it begin and end with three consecutive quote characters?
|
||||||
|
fn is_triple_quoted(self) -> bool;
|
||||||
|
|
||||||
|
fn prefix(self) -> AnyStringPrefix;
|
||||||
|
|
||||||
|
/// A `str` representation of the quotes used to start and close.
|
||||||
|
/// This does not include any prefixes the string has in its opener.
|
||||||
|
fn quote_str(self) -> &'static str {
|
||||||
|
if self.is_triple_quoted() {
|
||||||
|
match self.quote_style() {
|
||||||
|
Quote::Single => "'''",
|
||||||
|
Quote::Double => r#"""""#,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match self.quote_style() {
|
||||||
|
Quote::Single => "'",
|
||||||
|
Quote::Double => "\"",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The length of the quotes used to start and close the string.
|
||||||
|
/// This does not include the length of any prefixes the string has
|
||||||
|
/// in its opener.
|
||||||
|
fn quote_len(self) -> TextSize {
|
||||||
|
if self.is_triple_quoted() {
|
||||||
|
TextSize::new(3)
|
||||||
|
} else {
|
||||||
|
TextSize::new(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The total length of the string's opener,
|
||||||
|
/// i.e., the length of the prefixes plus the length
|
||||||
|
/// of the quotes used to open the string.
|
||||||
|
fn opener_len(self) -> TextSize {
|
||||||
|
self.prefix().as_str().text_len() + self.quote_len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The total length of the string's closer.
|
||||||
|
/// This is always equal to `self.quote_len()`,
|
||||||
|
/// but is provided here for symmetry with the `opener_len()` method.
|
||||||
|
fn closer_len(self) -> TextSize {
|
||||||
|
self.quote_len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_string_contents(self, contents: &str) -> String {
|
||||||
|
let prefix = self.prefix();
|
||||||
|
let quote_str = self.quote_str();
|
||||||
|
format!("{prefix}{quote_str}{contents}{quote_str}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
struct FStringFlagsInner: u8 {
|
struct FStringFlagsInner: u8 {
|
||||||
|
@ -1420,11 +1478,13 @@ impl FStringFlags {
|
||||||
FStringPrefix::Regular
|
FStringPrefix::Regular
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StringFlags for FStringFlags {
|
||||||
/// Return `true` if the f-string is triple-quoted, i.e.,
|
/// Return `true` if the f-string is triple-quoted, i.e.,
|
||||||
/// it begins and ends with three consecutive quote characters.
|
/// it begins and ends with three consecutive quote characters.
|
||||||
/// For example: `f"""{bar}"""`
|
/// For example: `f"""{bar}"""`
|
||||||
pub const fn is_triple_quoted(self) -> bool {
|
fn is_triple_quoted(self) -> bool {
|
||||||
self.0.contains(FStringFlagsInner::TRIPLE_QUOTED)
|
self.0.contains(FStringFlagsInner::TRIPLE_QUOTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1432,13 +1492,17 @@ impl FStringFlags {
|
||||||
/// used by the f-string's opener and closer:
|
/// used by the f-string's opener and closer:
|
||||||
/// - `f"{"a"}"` -> `QuoteStyle::Double`
|
/// - `f"{"a"}"` -> `QuoteStyle::Double`
|
||||||
/// - `f'{"a"}'` -> `QuoteStyle::Single`
|
/// - `f'{"a"}'` -> `QuoteStyle::Single`
|
||||||
pub const fn quote_style(self) -> Quote {
|
fn quote_style(self) -> Quote {
|
||||||
if self.0.contains(FStringFlagsInner::DOUBLE) {
|
if self.0.contains(FStringFlagsInner::DOUBLE) {
|
||||||
Quote::Double
|
Quote::Double
|
||||||
} else {
|
} else {
|
||||||
Quote::Single
|
Quote::Single
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prefix(self) -> AnyStringPrefix {
|
||||||
|
AnyStringPrefix::Format(self.prefix())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for FStringFlags {
|
impl fmt::Debug for FStringFlags {
|
||||||
|
@ -1830,12 +1894,14 @@ impl StringLiteralFlags {
|
||||||
StringLiteralPrefix::Empty
|
StringLiteralPrefix::Empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StringFlags for StringLiteralFlags {
|
||||||
/// Return the quoting style (single or double quotes)
|
/// Return the quoting style (single or double quotes)
|
||||||
/// used by the string's opener and closer:
|
/// used by the string's opener and closer:
|
||||||
/// - `"a"` -> `QuoteStyle::Double`
|
/// - `"a"` -> `QuoteStyle::Double`
|
||||||
/// - `'a'` -> `QuoteStyle::Single`
|
/// - `'a'` -> `QuoteStyle::Single`
|
||||||
pub const fn quote_style(self) -> Quote {
|
fn quote_style(self) -> Quote {
|
||||||
if self.0.contains(StringLiteralFlagsInner::DOUBLE) {
|
if self.0.contains(StringLiteralFlagsInner::DOUBLE) {
|
||||||
Quote::Double
|
Quote::Double
|
||||||
} else {
|
} else {
|
||||||
|
@ -1846,9 +1912,13 @@ impl StringLiteralFlags {
|
||||||
/// Return `true` if the string is triple-quoted, i.e.,
|
/// Return `true` if the string is triple-quoted, i.e.,
|
||||||
/// it begins and ends with three consecutive quote characters.
|
/// it begins and ends with three consecutive quote characters.
|
||||||
/// For example: `"""bar"""`
|
/// For example: `"""bar"""`
|
||||||
pub const fn is_triple_quoted(self) -> bool {
|
fn is_triple_quoted(self) -> bool {
|
||||||
self.0.contains(StringLiteralFlagsInner::TRIPLE_QUOTED)
|
self.0.contains(StringLiteralFlagsInner::TRIPLE_QUOTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prefix(self) -> AnyStringPrefix {
|
||||||
|
AnyStringPrefix::Regular(self.prefix())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for StringLiteralFlags {
|
impl fmt::Debug for StringLiteralFlags {
|
||||||
|
@ -2171,11 +2241,13 @@ impl BytesLiteralFlags {
|
||||||
ByteStringPrefix::Regular
|
ByteStringPrefix::Regular
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StringFlags for BytesLiteralFlags {
|
||||||
/// Return `true` if the bytestring is triple-quoted, i.e.,
|
/// Return `true` if the bytestring is triple-quoted, i.e.,
|
||||||
/// it begins and ends with three consecutive quote characters.
|
/// it begins and ends with three consecutive quote characters.
|
||||||
/// For example: `b"""{bar}"""`
|
/// For example: `b"""{bar}"""`
|
||||||
pub const fn is_triple_quoted(self) -> bool {
|
fn is_triple_quoted(self) -> bool {
|
||||||
self.0.contains(BytesLiteralFlagsInner::TRIPLE_QUOTED)
|
self.0.contains(BytesLiteralFlagsInner::TRIPLE_QUOTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2183,13 +2255,17 @@ impl BytesLiteralFlags {
|
||||||
/// used by the bytestring's opener and closer:
|
/// used by the bytestring's opener and closer:
|
||||||
/// - `b"a"` -> `QuoteStyle::Double`
|
/// - `b"a"` -> `QuoteStyle::Double`
|
||||||
/// - `b'a'` -> `QuoteStyle::Single`
|
/// - `b'a'` -> `QuoteStyle::Single`
|
||||||
pub const fn quote_style(self) -> Quote {
|
fn quote_style(self) -> Quote {
|
||||||
if self.0.contains(BytesLiteralFlagsInner::DOUBLE) {
|
if self.0.contains(BytesLiteralFlagsInner::DOUBLE) {
|
||||||
Quote::Double
|
Quote::Double
|
||||||
} else {
|
} else {
|
||||||
Quote::Single
|
Quote::Single
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prefix(self) -> AnyStringPrefix {
|
||||||
|
AnyStringPrefix::Bytes(self.prefix())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for BytesLiteralFlags {
|
impl fmt::Debug for BytesLiteralFlags {
|
||||||
|
@ -2340,7 +2416,70 @@ impl AnyStringFlags {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn prefix(self) -> AnyStringPrefix {
|
pub fn new(prefix: AnyStringPrefix, quotes: Quote, triple_quoted: bool) -> Self {
|
||||||
|
let new = Self::default().with_prefix(prefix).with_quote_style(quotes);
|
||||||
|
if triple_quoted {
|
||||||
|
new.with_triple_quotes()
|
||||||
|
} else {
|
||||||
|
new
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does the string have a `u` or `U` prefix?
|
||||||
|
pub const fn is_u_string(self) -> bool {
|
||||||
|
self.0.contains(AnyStringFlagsInner::U_PREFIX)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does the string have an `r` or `R` prefix?
|
||||||
|
pub const fn is_raw_string(self) -> bool {
|
||||||
|
self.0.intersects(
|
||||||
|
AnyStringFlagsInner::R_PREFIX_LOWER.union(AnyStringFlagsInner::R_PREFIX_UPPER),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does the string have an `f` or `F` prefix?
|
||||||
|
pub const fn is_f_string(self) -> bool {
|
||||||
|
self.0.contains(AnyStringFlagsInner::F_PREFIX)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does the string have a `b` or `B` prefix?
|
||||||
|
pub const fn is_byte_string(self) -> bool {
|
||||||
|
self.0.contains(AnyStringFlagsInner::B_PREFIX)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_quote_style(mut self, quotes: Quote) -> Self {
|
||||||
|
match quotes {
|
||||||
|
Quote::Double => self.0 |= AnyStringFlagsInner::DOUBLE,
|
||||||
|
Quote::Single => self.0 -= AnyStringFlagsInner::DOUBLE,
|
||||||
|
};
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_triple_quotes(mut self) -> Self {
|
||||||
|
self.0 |= AnyStringFlagsInner::TRIPLE_QUOTED;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StringFlags for AnyStringFlags {
|
||||||
|
/// Does the string use single or double quotes in its opener and closer?
|
||||||
|
fn quote_style(self) -> Quote {
|
||||||
|
if self.0.contains(AnyStringFlagsInner::DOUBLE) {
|
||||||
|
Quote::Double
|
||||||
|
} else {
|
||||||
|
Quote::Single
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is the string triple-quoted, i.e.,
|
||||||
|
/// does it begin and end with three consecutive quote characters?
|
||||||
|
fn is_triple_quoted(self) -> bool {
|
||||||
|
self.0.contains(AnyStringFlagsInner::TRIPLE_QUOTED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prefix(self) -> AnyStringPrefix {
|
||||||
let AnyStringFlags(flags) = self;
|
let AnyStringFlags(flags) = self;
|
||||||
|
|
||||||
// f-strings
|
// f-strings
|
||||||
|
@ -2377,123 +2516,6 @@ impl AnyStringFlags {
|
||||||
}
|
}
|
||||||
AnyStringPrefix::Regular(StringLiteralPrefix::Empty)
|
AnyStringPrefix::Regular(StringLiteralPrefix::Empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(prefix: AnyStringPrefix, quotes: Quote, triple_quoted: bool) -> Self {
|
|
||||||
let new = Self::default().with_prefix(prefix).with_quote_style(quotes);
|
|
||||||
if triple_quoted {
|
|
||||||
new.with_triple_quotes()
|
|
||||||
} else {
|
|
||||||
new
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does the string have a `u` or `U` prefix?
|
|
||||||
pub const fn is_u_string(self) -> bool {
|
|
||||||
self.0.contains(AnyStringFlagsInner::U_PREFIX)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does the string have an `r` or `R` prefix?
|
|
||||||
pub const fn is_raw_string(self) -> bool {
|
|
||||||
self.0.intersects(
|
|
||||||
AnyStringFlagsInner::R_PREFIX_LOWER.union(AnyStringFlagsInner::R_PREFIX_UPPER),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does the string have an `f` or `F` prefix?
|
|
||||||
pub const fn is_f_string(self) -> bool {
|
|
||||||
self.0.contains(AnyStringFlagsInner::F_PREFIX)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does the string have a `b` or `B` prefix?
|
|
||||||
pub const fn is_byte_string(self) -> bool {
|
|
||||||
self.0.contains(AnyStringFlagsInner::B_PREFIX)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does the string use single or double quotes in its opener and closer?
|
|
||||||
pub const fn quote_style(self) -> Quote {
|
|
||||||
if self.0.contains(AnyStringFlagsInner::DOUBLE) {
|
|
||||||
Quote::Double
|
|
||||||
} else {
|
|
||||||
Quote::Single
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Is the string triple-quoted, i.e.,
|
|
||||||
/// does it begin and end with three consecutive quote characters?
|
|
||||||
pub const fn is_triple_quoted(self) -> bool {
|
|
||||||
self.0.contains(AnyStringFlagsInner::TRIPLE_QUOTED)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A `str` representation of the quotes used to start and close.
|
|
||||||
/// This does not include any prefixes the string has in its opener.
|
|
||||||
pub const fn quote_str(self) -> &'static str {
|
|
||||||
if self.is_triple_quoted() {
|
|
||||||
match self.quote_style() {
|
|
||||||
Quote::Single => "'''",
|
|
||||||
Quote::Double => r#"""""#,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match self.quote_style() {
|
|
||||||
Quote::Single => "'",
|
|
||||||
Quote::Double => "\"",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The length of the prefixes used (if any) in the string's opener.
|
|
||||||
pub fn prefix_len(self) -> TextSize {
|
|
||||||
self.prefix().as_str().text_len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The length of the quotes used to start and close the string.
|
|
||||||
/// This does not include the length of any prefixes the string has
|
|
||||||
/// in its opener.
|
|
||||||
pub const fn quote_len(self) -> TextSize {
|
|
||||||
if self.is_triple_quoted() {
|
|
||||||
TextSize::new(3)
|
|
||||||
} else {
|
|
||||||
TextSize::new(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The total length of the string's opener,
|
|
||||||
/// i.e., the length of the prefixes plus the length
|
|
||||||
/// of the quotes used to open the string.
|
|
||||||
pub fn opener_len(self) -> TextSize {
|
|
||||||
self.prefix_len() + self.quote_len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The total length of the string's closer.
|
|
||||||
/// This is always equal to `self.quote_len()`,
|
|
||||||
/// but is provided here for symmetry with the `opener_len()` method.
|
|
||||||
pub const fn closer_len(self) -> TextSize {
|
|
||||||
self.quote_len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn format_string_contents(self, contents: &str) -> String {
|
|
||||||
format!(
|
|
||||||
"{}{}{}{}",
|
|
||||||
self.prefix(),
|
|
||||||
self.quote_str(),
|
|
||||||
contents,
|
|
||||||
self.quote_str()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_quote_style(mut self, quotes: Quote) -> Self {
|
|
||||||
match quotes {
|
|
||||||
Quote::Double => self.0 |= AnyStringFlagsInner::DOUBLE,
|
|
||||||
Quote::Single => self.0 -= AnyStringFlagsInner::DOUBLE,
|
|
||||||
};
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_triple_quotes(mut self) -> Self {
|
|
||||||
self.0 |= AnyStringFlagsInner::TRIPLE_QUOTED;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for AnyStringFlags {
|
impl fmt::Debug for AnyStringFlags {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::ops::Deref;
|
||||||
|
|
||||||
use once_cell::unsync::OnceCell;
|
use once_cell::unsync::OnceCell;
|
||||||
|
|
||||||
use ruff_python_ast::str::Quote;
|
use ruff_python_ast::{str::Quote, StringFlags};
|
||||||
use ruff_python_parser::lexer::LexResult;
|
use ruff_python_parser::lexer::LexResult;
|
||||||
use ruff_python_parser::Tok;
|
use ruff_python_parser::Tok;
|
||||||
use ruff_source_file::{find_newline, LineEnding, Locator};
|
use ruff_source_file::{find_newline, LineEnding, Locator};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_formatter::write;
|
use ruff_formatter::write;
|
||||||
use ruff_python_ast::{AnyStringFlags, FString};
|
use ruff_python_ast::{AnyStringFlags, FString, StringFlags};
|
||||||
use ruff_source_file::Locator;
|
use ruff_source_file::Locator;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::borrow::Cow;
|
||||||
use ruff_formatter::{format_args, write, Buffer, RemoveSoftLinesBuffer};
|
use ruff_formatter::{format_args, write, Buffer, RemoveSoftLinesBuffer};
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
ConversionFlag, Expr, FStringElement, FStringExpressionElement, FStringLiteralElement,
|
ConversionFlag, Expr, FStringElement, FStringExpressionElement, FStringLiteralElement,
|
||||||
|
StringFlags,
|
||||||
};
|
};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use memchr::memchr2;
|
||||||
|
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
self as ast, AnyNodeRef, AnyStringFlags, Expr, ExprBytesLiteral, ExprFString,
|
self as ast, AnyNodeRef, AnyStringFlags, Expr, ExprBytesLiteral, ExprFString,
|
||||||
ExprStringLiteral, ExpressionRef, StringLiteral,
|
ExprStringLiteral, ExpressionRef, StringFlags, StringLiteral,
|
||||||
};
|
};
|
||||||
use ruff_source_file::Locator;
|
use ruff_source_file::Locator;
|
||||||
use ruff_text_size::{Ranged, TextRange};
|
use ruff_text_size::{Ranged, TextRange};
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::{borrow::Cow, collections::VecDeque};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use ruff_formatter::printer::SourceMapGeneration;
|
use ruff_formatter::printer::SourceMapGeneration;
|
||||||
use ruff_python_ast::str::Quote;
|
use ruff_python_ast::{str::Quote, StringFlags};
|
||||||
use ruff_python_parser::ParseError;
|
use ruff_python_parser::ParseError;
|
||||||
use {once_cell::sync::Lazy, regex::Regex};
|
use {once_cell::sync::Lazy, regex::Regex};
|
||||||
use {
|
use {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use ruff_python_ast::str::Quote;
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
self as ast,
|
self as ast,
|
||||||
str_prefix::{AnyStringPrefix, StringLiteralPrefix},
|
str_prefix::{AnyStringPrefix, StringLiteralPrefix},
|
||||||
AnyStringFlags,
|
AnyStringFlags, StringFlags,
|
||||||
};
|
};
|
||||||
use ruff_text_size::{Ranged, TextRange};
|
use ruff_text_size::{Ranged, TextRange};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
||||||
use std::iter::FusedIterator;
|
use std::iter::FusedIterator;
|
||||||
|
|
||||||
use ruff_formatter::FormatContext;
|
use ruff_formatter::FormatContext;
|
||||||
use ruff_python_ast::{str::Quote, AnyStringFlags};
|
use ruff_python_ast::{str::Quote, AnyStringFlags, StringFlags};
|
||||||
use ruff_source_file::Locator;
|
use ruff_source_file::Locator;
|
||||||
use ruff_text_size::{Ranged, TextRange};
|
use ruff_text_size::{Ranged, TextRange};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use ruff_python_ast::StringFlags;
|
||||||
use ruff_python_parser::Tok;
|
use ruff_python_parser::Tok;
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ use unicode_normalization::UnicodeNormalization;
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
str::Quote,
|
str::Quote,
|
||||||
str_prefix::{AnyStringPrefix, FStringPrefix},
|
str_prefix::{AnyStringPrefix, FStringPrefix},
|
||||||
AnyStringFlags, Int, IpyEscapeKind,
|
AnyStringFlags, Int, IpyEscapeKind, StringFlags,
|
||||||
};
|
};
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use ruff_python_ast::AnyStringFlags;
|
use ruff_python_ast::{AnyStringFlags, StringFlags};
|
||||||
|
|
||||||
/// The context representing the current f-string that the lexer is in.
|
/// The context representing the current f-string that the lexer is in.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -36,13 +36,13 @@ impl FStringContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the quote character for the current f-string.
|
/// Returns the quote character for the current f-string.
|
||||||
pub(crate) const fn quote_char(&self) -> char {
|
pub(crate) fn quote_char(&self) -> char {
|
||||||
self.flags.quote_style().as_char()
|
self.flags.quote_style().as_char()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the triple quotes for the current f-string if it is a triple-quoted
|
/// Returns the triple quotes for the current f-string if it is a triple-quoted
|
||||||
/// f-string, `None` otherwise.
|
/// f-string, `None` otherwise.
|
||||||
pub(crate) const fn triple_quotes(&self) -> Option<&'static str> {
|
pub(crate) fn triple_quotes(&self) -> Option<&'static str> {
|
||||||
if self.is_triple_quoted() {
|
if self.is_triple_quoted() {
|
||||||
Some(self.flags.quote_str())
|
Some(self.flags.quote_str())
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,7 +56,7 @@ impl FStringContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the current f-string is a triple-quoted f-string.
|
/// Returns `true` if the current f-string is a triple-quoted f-string.
|
||||||
pub(crate) const fn is_triple_quoted(&self) -> bool {
|
pub(crate) fn is_triple_quoted(&self) -> bool {
|
||||||
self.flags.is_triple_quoted()
|
self.flags.is_triple_quoted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use bstr::ByteSlice;
|
use bstr::ByteSlice;
|
||||||
|
|
||||||
use ruff_python_ast::{self as ast, AnyStringFlags, Expr};
|
use ruff_python_ast::{self as ast, AnyStringFlags, Expr, StringFlags};
|
||||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||||
|
|
||||||
use crate::lexer::{LexicalError, LexicalErrorType};
|
use crate::lexer::{LexicalError, LexicalErrorType};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use ruff_python_ast::{AnyStringFlags, BoolOp, Int, IpyEscapeKind, Operator, UnaryOp};
|
use ruff_python_ast::{AnyStringFlags, BoolOp, Int, IpyEscapeKind, Operator, StringFlags, UnaryOp};
|
||||||
|
|
||||||
/// The set of tokens the Python source code can be tokenized in.
|
/// The set of tokens the Python source code can be tokenized in.
|
||||||
#[derive(Clone, Debug, PartialEq, is_macro::Is)]
|
#[derive(Clone, Debug, PartialEq, is_macro::Is)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue