mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 05:25:17 +00:00
Remove source position from FormatElement::DynamicText
(#4619)
This commit is contained in:
parent
85f094f592
commit
6943beee66
20 changed files with 165 additions and 145 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1900,6 +1900,7 @@ dependencies = [
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
|
"static_assertions",
|
||||||
"tracing",
|
"tracing",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
|
@ -14,6 +14,7 @@ schemars = { workspace = true, optional = true }
|
||||||
serde = { workspace = true, optional = true }
|
serde = { workspace = true, optional = true }
|
||||||
tracing = { version = "0.1.37", default-features = false, features = ["std"] }
|
tracing = { version = "0.1.37", default-features = false, features = ["std"] }
|
||||||
unicode-width = { version = "0.1.10" }
|
unicode-width = { version = "0.1.10" }
|
||||||
|
static_assertions = "1.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = { workspace = true }
|
insta = { workspace = true }
|
||||||
|
|
|
@ -276,8 +276,62 @@ impl std::fmt::Debug for StaticText {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a text from a dynamic string and a range of the input source
|
/// Creates a source map entry from the passed source `position` to the position in the formatted output.
|
||||||
pub fn dynamic_text(text: &str, position: TextSize) -> DynamicText {
|
///
|
||||||
|
/// ## Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// /// ```
|
||||||
|
/// use ruff_formatter::format;
|
||||||
|
/// use ruff_formatter::prelude::*;
|
||||||
|
///
|
||||||
|
/// # fn main() -> FormatResult<()> {
|
||||||
|
/// // the tab must be encoded as \\t to not literally print a tab character ("Hello{tab}World" vs "Hello\tWorld")
|
||||||
|
/// use ruff_text_size::TextSize;
|
||||||
|
/// use ruff_formatter::SourceMarker;
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// let elements = format!(SimpleFormatContext::default(), [
|
||||||
|
/// source_position(TextSize::new(0)),
|
||||||
|
/// text("\"Hello "),
|
||||||
|
/// source_position(TextSize::new(8)),
|
||||||
|
/// text("'Ruff'"),
|
||||||
|
/// source_position(TextSize::new(14)),
|
||||||
|
/// text("\""),
|
||||||
|
/// source_position(TextSize::new(20))
|
||||||
|
/// ])?;
|
||||||
|
///
|
||||||
|
/// let printed = elements.print()?;
|
||||||
|
///
|
||||||
|
/// assert_eq!(printed.as_code(), r#""Hello 'Ruff'""#);
|
||||||
|
/// assert_eq!(printed.sourcemap(), [
|
||||||
|
/// SourceMarker { source: TextSize::new(0), dest: TextSize::new(0) },
|
||||||
|
/// SourceMarker { source: TextSize::new(0), dest: TextSize::new(7) },
|
||||||
|
/// SourceMarker { source: TextSize::new(8), dest: TextSize::new(7) },
|
||||||
|
/// SourceMarker { source: TextSize::new(8), dest: TextSize::new(13) },
|
||||||
|
/// SourceMarker { source: TextSize::new(14), dest: TextSize::new(13) },
|
||||||
|
/// SourceMarker { source: TextSize::new(14), dest: TextSize::new(14) },
|
||||||
|
/// SourceMarker { source: TextSize::new(20), dest: TextSize::new(14) },
|
||||||
|
/// ]);
|
||||||
|
///
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub const fn source_position(position: TextSize) -> SourcePosition {
|
||||||
|
SourcePosition(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
|
pub struct SourcePosition(TextSize);
|
||||||
|
|
||||||
|
impl<Context> Format<Context> for SourcePosition {
|
||||||
|
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||||
|
f.write_element(FormatElement::SourcePosition(self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a text from a dynamic string with its optional start-position in the source document
|
||||||
|
pub fn dynamic_text(text: &str, position: Option<TextSize>) -> DynamicText {
|
||||||
debug_assert_no_newlines(text);
|
debug_assert_no_newlines(text);
|
||||||
|
|
||||||
DynamicText { text, position }
|
DynamicText { text, position }
|
||||||
|
@ -286,14 +340,17 @@ pub fn dynamic_text(text: &str, position: TextSize) -> DynamicText {
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Eq, PartialEq)]
|
||||||
pub struct DynamicText<'a> {
|
pub struct DynamicText<'a> {
|
||||||
text: &'a str,
|
text: &'a str,
|
||||||
position: TextSize,
|
position: Option<TextSize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context> Format<Context> for DynamicText<'_> {
|
impl<Context> Format<Context> for DynamicText<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||||
|
if let Some(source_position) = self.position {
|
||||||
|
f.write_element(FormatElement::SourcePosition(source_position))?;
|
||||||
|
}
|
||||||
|
|
||||||
f.write_element(FormatElement::DynamicText {
|
f.write_element(FormatElement::DynamicText {
|
||||||
text: self.text.to_string().into_boxed_str(),
|
text: self.text.to_string().into_boxed_str(),
|
||||||
source_position: self.position,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1781,7 +1838,7 @@ impl<Context, T> std::fmt::Debug for FormatWith<Context, T> {
|
||||||
/// let mut join = f.join_with(&separator);
|
/// let mut join = f.join_with(&separator);
|
||||||
///
|
///
|
||||||
/// for item in &self.items {
|
/// for item in &self.items {
|
||||||
/// join.entry(&format_with(|f| write!(f, [dynamic_text(item, TextSize::default())])));
|
/// join.entry(&format_with(|f| write!(f, [dynamic_text(item, None)])));
|
||||||
/// }
|
/// }
|
||||||
/// join.finish()
|
/// join.finish()
|
||||||
/// })),
|
/// })),
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
pub mod document;
|
pub mod document;
|
||||||
pub mod tag;
|
pub mod tag;
|
||||||
|
|
||||||
use crate::format_element::tag::{LabelId, Tag};
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
use crate::static_assert;
|
|
||||||
use crate::{TagKind, TextSize};
|
|
||||||
use ruff_text_size::TextRange;
|
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::format_element::tag::{LabelId, Tag};
|
||||||
|
use crate::TagKind;
|
||||||
|
use ruff_text_size::{TextRange, TextSize};
|
||||||
|
|
||||||
/// Language agnostic IR for formatting source code.
|
/// Language agnostic IR for formatting source code.
|
||||||
///
|
///
|
||||||
/// Use the helper functions like [crate::builders::space], [crate::builders::soft_line_break] etc. defined in this file to create elements.
|
/// Use the helper functions like [crate::builders::space], [crate::builders::soft_line_break] etc. defined in this file to create elements.
|
||||||
|
@ -26,16 +24,19 @@ pub enum FormatElement {
|
||||||
/// Forces the parent group to print in expanded mode.
|
/// Forces the parent group to print in expanded mode.
|
||||||
ExpandParent,
|
ExpandParent,
|
||||||
|
|
||||||
|
/// Indicates the position of the elements coming after this element in the source document.
|
||||||
|
/// The printer will create a source map entry from this position in the source document to the
|
||||||
|
/// formatted position.
|
||||||
|
SourcePosition(TextSize),
|
||||||
|
|
||||||
/// Token constructed by the formatter from a static string
|
/// Token constructed by the formatter from a static string
|
||||||
StaticText { text: &'static str },
|
StaticText { text: &'static str },
|
||||||
|
|
||||||
/// Token constructed from the input source as a dynamic
|
/// Token constructed from the input source as a dynamic
|
||||||
/// string with its start position in the input document.
|
/// string.
|
||||||
DynamicText {
|
DynamicText {
|
||||||
/// There's no need for the text to be mutable, using `Box<str>` safes 8 bytes over `String`.
|
/// There's no need for the text to be mutable, using `Box<str>` safes 8 bytes over `String`.
|
||||||
text: Box<str>,
|
text: Box<str>,
|
||||||
/// The start position of the dynamic token in the unformatted source code
|
|
||||||
source_position: TextSize,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Token constructed by slicing a defined range from a static string.
|
/// Token constructed by slicing a defined range from a static string.
|
||||||
|
@ -80,6 +81,9 @@ impl std::fmt::Debug for FormatElement {
|
||||||
fmt.debug_list().entries(interned.deref()).finish()
|
fmt.debug_list().entries(interned.deref()).finish()
|
||||||
}
|
}
|
||||||
FormatElement::Tag(tag) => fmt.debug_tuple("Tag").field(tag).finish(),
|
FormatElement::Tag(tag) => fmt.debug_tuple("Tag").field(tag).finish(),
|
||||||
|
FormatElement::SourcePosition(position) => {
|
||||||
|
fmt.debug_tuple("SourcePosition").field(position).finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,9 +245,10 @@ impl FormatElements for FormatElement {
|
||||||
// Traverse into the most flat version because the content is guaranteed to expand when even
|
// Traverse into the most flat version because the content is guaranteed to expand when even
|
||||||
// the most flat version contains some content that forces a break.
|
// the most flat version contains some content that forces a break.
|
||||||
FormatElement::BestFitting(best_fitting) => best_fitting.most_flat().will_break(),
|
FormatElement::BestFitting(best_fitting) => best_fitting.most_flat().will_break(),
|
||||||
FormatElement::LineSuffixBoundary | FormatElement::Space | FormatElement::Tag(_) => {
|
FormatElement::LineSuffixBoundary
|
||||||
false
|
| FormatElement::Space
|
||||||
}
|
| FormatElement::Tag(_)
|
||||||
|
| FormatElement::SourcePosition(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,20 +374,26 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
static_assert!(std::mem::size_of::<ruff_text_size::TextRange>() == 8usize);
|
mod sizes {
|
||||||
|
// Increasing the size of FormatElement has serious consequences on runtime performance and memory footprint.
|
||||||
|
// Is there a more efficient way to encode the data to avoid increasing its size? Can the information
|
||||||
|
// be recomputed at a later point in time?
|
||||||
|
// You reduced the size of a format element? Excellent work!
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
use crate::format_element::BestFitting;
|
||||||
static_assert!(std::mem::size_of::<crate::format_element::tag::VerbatimKind>() == 8usize);
|
use crate::prelude::tag::VerbatimKind;
|
||||||
|
use crate::prelude::Interned;
|
||||||
|
use ruff_text_size::TextRange;
|
||||||
|
use static_assertions::assert_eq_size;
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
assert_eq_size!(TextRange, [u8; 8]);
|
||||||
#[cfg(target_pointer_width = "64")]
|
assert_eq_size!(VerbatimKind, [u8; 8]);
|
||||||
static_assert!(std::mem::size_of::<crate::format_element::Tag>() == 16usize);
|
assert_eq_size!(Interned, [u8; 16]);
|
||||||
|
assert_eq_size!(BestFitting, [u8; 16]);
|
||||||
|
|
||||||
// Increasing the size of FormatElement has serious consequences on runtime performance and memory footprint.
|
#[cfg(not(debug_assertions))]
|
||||||
// Is there a more efficient way to encode the data to avoid increasing its size? Can the information
|
assert_eq_size!(crate::format_element::Tag, [u8; 16]);
|
||||||
// be recomputed at a later point in time?
|
|
||||||
// You reduced the size of a format element? Excellent work!
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
#[cfg(target_pointer_width = "64")]
|
assert_eq_size!(crate::FormatElement, [u8; 32]);
|
||||||
static_assert!(std::mem::size_of::<crate::FormatElement>() == 32usize);
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ use crate::{
|
||||||
BufferExtensions, Format, FormatContext, FormatElement, FormatOptions, FormatResult, Formatter,
|
BufferExtensions, Format, FormatContext, FormatElement, FormatOptions, FormatResult, Formatter,
|
||||||
IndentStyle, LineWidth, PrinterOptions,
|
IndentStyle, LineWidth, PrinterOptions,
|
||||||
};
|
};
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
@ -231,6 +230,16 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
write!(f, [text("expand_parent")])?;
|
write!(f, [text("expand_parent")])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FormatElement::SourcePosition(position) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
[dynamic_text(
|
||||||
|
&std::format!("source_position({:?})", position),
|
||||||
|
None
|
||||||
|
)]
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
FormatElement::LineSuffixBoundary => {
|
FormatElement::LineSuffixBoundary => {
|
||||||
write!(f, [text("line_suffix_boundary")])?;
|
write!(f, [text("line_suffix_boundary")])?;
|
||||||
}
|
}
|
||||||
|
@ -265,10 +274,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
dynamic_text(
|
dynamic_text(&std::format!("<interned {index}>"), None),
|
||||||
&std::format!("<interned {index}>"),
|
|
||||||
TextSize::default()
|
|
||||||
),
|
|
||||||
space(),
|
space(),
|
||||||
&interned.deref(),
|
&interned.deref(),
|
||||||
]
|
]
|
||||||
|
@ -279,7 +285,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
f,
|
f,
|
||||||
[dynamic_text(
|
[dynamic_text(
|
||||||
&std::format!("<ref interned *{reference}>"),
|
&std::format!("<ref interned *{reference}>"),
|
||||||
TextSize::default()
|
None
|
||||||
)]
|
)]
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -300,10 +306,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
text("<END_TAG_WITHOUT_START<"),
|
text("<END_TAG_WITHOUT_START<"),
|
||||||
dynamic_text(
|
dynamic_text(&std::format!("{:?}", tag.kind()), None),
|
||||||
&std::format!("{:?}", tag.kind()),
|
|
||||||
TextSize::default()
|
|
||||||
),
|
|
||||||
text(">>"),
|
text(">>"),
|
||||||
]
|
]
|
||||||
)?;
|
)?;
|
||||||
|
@ -318,15 +321,9 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
text(")"),
|
text(")"),
|
||||||
soft_line_break_or_space(),
|
soft_line_break_or_space(),
|
||||||
text("ERROR<START_END_TAG_MISMATCH<start: "),
|
text("ERROR<START_END_TAG_MISMATCH<start: "),
|
||||||
dynamic_text(
|
dynamic_text(&std::format!("{start_kind:?}"), None),
|
||||||
&std::format!("{start_kind:?}"),
|
|
||||||
TextSize::default()
|
|
||||||
),
|
|
||||||
text(", end: "),
|
text(", end: "),
|
||||||
dynamic_text(
|
dynamic_text(&std::format!("{:?}", tag.kind()), None),
|
||||||
&std::format!("{:?}", tag.kind()),
|
|
||||||
TextSize::default()
|
|
||||||
),
|
|
||||||
text(">>")
|
text(">>")
|
||||||
]
|
]
|
||||||
)?;
|
)?;
|
||||||
|
@ -358,7 +355,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
text("align("),
|
text("align("),
|
||||||
dynamic_text(&count.to_string(), TextSize::default()),
|
dynamic_text(&count.to_string(), None),
|
||||||
text(","),
|
text(","),
|
||||||
space(),
|
space(),
|
||||||
]
|
]
|
||||||
|
@ -380,10 +377,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
dynamic_text(
|
dynamic_text(&std::format!("\"{group_id:?}\""), None),
|
||||||
&std::format!("\"{group_id:?}\""),
|
|
||||||
TextSize::default()
|
|
||||||
),
|
|
||||||
text(","),
|
text(","),
|
||||||
space(),
|
space(),
|
||||||
]
|
]
|
||||||
|
@ -406,7 +400,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
text("indent_if_group_breaks("),
|
text("indent_if_group_breaks("),
|
||||||
dynamic_text(&std::format!("\"{id:?}\""), TextSize::default()),
|
dynamic_text(&std::format!("\"{id:?}\""), None),
|
||||||
text(","),
|
text(","),
|
||||||
space(),
|
space(),
|
||||||
]
|
]
|
||||||
|
@ -427,10 +421,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
dynamic_text(
|
dynamic_text(&std::format!("\"{group_id:?}\""), None),
|
||||||
&std::format!("\"{group_id:?}\""),
|
|
||||||
TextSize::default()
|
|
||||||
),
|
|
||||||
text(","),
|
text(","),
|
||||||
space(),
|
space(),
|
||||||
]
|
]
|
||||||
|
@ -443,10 +434,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
text("label("),
|
text("label("),
|
||||||
dynamic_text(
|
dynamic_text(&std::format!("\"{label_id:?}\""), None),
|
||||||
&std::format!("\"{label_id:?}\""),
|
|
||||||
TextSize::default()
|
|
||||||
),
|
|
||||||
text(","),
|
text(","),
|
||||||
space(),
|
space(),
|
||||||
]
|
]
|
||||||
|
@ -490,10 +478,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
|
||||||
ContentArrayEnd,
|
ContentArrayEnd,
|
||||||
text(")"),
|
text(")"),
|
||||||
soft_line_break_or_space(),
|
soft_line_break_or_space(),
|
||||||
dynamic_text(
|
dynamic_text(&std::format!("<START_WITHOUT_END<{top:?}>>"), None),
|
||||||
&std::format!("<START_WITHOUT_END<{top:?}>>"),
|
|
||||||
TextSize::default()
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub trait MemoizeFormat<Context> {
|
||||||
/// let value = self.value.get();
|
/// let value = self.value.get();
|
||||||
/// self.value.set(value + 1);
|
/// self.value.set(value + 1);
|
||||||
///
|
///
|
||||||
/// write!(f, [dynamic_text(&std::format!("Formatted {value} times."), TextSize::from(0))])
|
/// write!(f, [dynamic_text(&std::format!("Formatted {value} times."), None)])
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -114,7 +114,7 @@ where
|
||||||
/// write!(f, [
|
/// write!(f, [
|
||||||
/// text("Count:"),
|
/// text("Count:"),
|
||||||
/// space(),
|
/// space(),
|
||||||
/// dynamic_text(&std::format!("{current}"), TextSize::default()),
|
/// dynamic_text(&std::format!("{current}"), None),
|
||||||
/// hard_line_break()
|
/// hard_line_break()
|
||||||
/// ])?;
|
/// ])?;
|
||||||
///
|
///
|
||||||
|
|
|
@ -33,7 +33,6 @@ pub mod group_id;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod printer;
|
pub mod printer;
|
||||||
mod utility_types;
|
|
||||||
|
|
||||||
use crate::formatter::Formatter;
|
use crate::formatter::Formatter;
|
||||||
use crate::group_id::UniqueGroupIdBuilder;
|
use crate::group_id::UniqueGroupIdBuilder;
|
||||||
|
@ -428,7 +427,7 @@ pub type FormatResult<F> = Result<F, FormatError>;
|
||||||
/// fn fmt(&self, f: &mut Formatter<SimpleFormatContext>) -> FormatResult<()> {
|
/// fn fmt(&self, f: &mut Formatter<SimpleFormatContext>) -> FormatResult<()> {
|
||||||
/// write!(f, [
|
/// write!(f, [
|
||||||
/// hard_line_break(),
|
/// hard_line_break(),
|
||||||
/// dynamic_text(&self.0, TextSize::from(0)),
|
/// dynamic_text(&self.0, None),
|
||||||
/// hard_line_break(),
|
/// hard_line_break(),
|
||||||
/// ])
|
/// ])
|
||||||
/// }
|
/// }
|
||||||
|
|
|
@ -95,10 +95,7 @@ impl<'a> Printer<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatElement::StaticText { text } => self.print_text(text, None),
|
FormatElement::StaticText { text } => self.print_text(text, None),
|
||||||
FormatElement::DynamicText {
|
FormatElement::DynamicText { text } => self.print_text(text, None),
|
||||||
text,
|
|
||||||
source_position,
|
|
||||||
} => self.print_text(text, Some(*source_position)),
|
|
||||||
FormatElement::StaticTextSlice { text, range } => self.print_text(&text[*range], None),
|
FormatElement::StaticTextSlice { text, range } => self.print_text(&text[*range], None),
|
||||||
FormatElement::Line(line_mode) => {
|
FormatElement::Line(line_mode) => {
|
||||||
if args.mode().is_flat()
|
if args.mode().is_flat()
|
||||||
|
@ -129,6 +126,11 @@ impl<'a> Printer<'a> {
|
||||||
// Handled in `Document::propagate_expands()
|
// Handled in `Document::propagate_expands()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FormatElement::SourcePosition(position) => {
|
||||||
|
self.state.source_position = *position;
|
||||||
|
self.push_marker();
|
||||||
|
}
|
||||||
|
|
||||||
FormatElement::LineSuffixBoundary => {
|
FormatElement::LineSuffixBoundary => {
|
||||||
const HARD_BREAK: &FormatElement = &FormatElement::Line(LineMode::Hard);
|
const HARD_BREAK: &FormatElement = &FormatElement::Line(LineMode::Hard);
|
||||||
self.flush_line_suffixes(queue, stack, Some(HARD_BREAK));
|
self.flush_line_suffixes(queue, stack, Some(HARD_BREAK));
|
||||||
|
@ -273,7 +275,7 @@ impl<'a> Printer<'a> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_text(&mut self, text: &str, source_position: Option<TextSize>) {
|
fn print_text(&mut self, text: &str, source_range: Option<TextRange>) {
|
||||||
if !self.state.pending_indent.is_empty() {
|
if !self.state.pending_indent.is_empty() {
|
||||||
let (indent_char, repeat_count) = match self.options.indent_style() {
|
let (indent_char, repeat_count) = match self.options.indent_style() {
|
||||||
IndentStyle::Tab => ('\t', 1),
|
IndentStyle::Tab => ('\t', 1),
|
||||||
|
@ -311,28 +313,27 @@ impl<'a> Printer<'a> {
|
||||||
// If the token has no source position (was created by the formatter)
|
// If the token has no source position (was created by the formatter)
|
||||||
// both the start and end marker will use the last known position
|
// both the start and end marker will use the last known position
|
||||||
// in the input source (from state.source_position)
|
// in the input source (from state.source_position)
|
||||||
if let Some(source) = source_position {
|
if let Some(range) = source_range {
|
||||||
self.state.source_position = source;
|
self.state.source_position = range.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push_marker(SourceMarker {
|
self.push_marker();
|
||||||
source: self.state.source_position,
|
|
||||||
dest: self.state.buffer.text_len(),
|
|
||||||
});
|
|
||||||
|
|
||||||
self.print_str(text);
|
self.print_str(text);
|
||||||
|
|
||||||
if source_position.is_some() {
|
if let Some(range) = source_range {
|
||||||
self.state.source_position += text.text_len();
|
self.state.source_position = range.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push_marker(SourceMarker {
|
self.push_marker();
|
||||||
source: self.state.source_position,
|
|
||||||
dest: self.state.buffer.text_len(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_marker(&mut self, marker: SourceMarker) {
|
fn push_marker(&mut self) {
|
||||||
|
let marker = SourceMarker {
|
||||||
|
source: self.state.source_position,
|
||||||
|
dest: self.state.buffer.text_len(),
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(last) = self.state.source_markers.last() {
|
if let Some(last) = self.state.source_markers.last() {
|
||||||
if last != &marker {
|
if last != &marker {
|
||||||
self.state.source_markers.push(marker)
|
self.state.source_markers.push(marker)
|
||||||
|
@ -1008,6 +1009,8 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FormatElement::SourcePosition(_) => {}
|
||||||
|
|
||||||
FormatElement::BestFitting(best_fitting) => {
|
FormatElement::BestFitting(best_fitting) => {
|
||||||
let slice = match args.mode() {
|
let slice = match args.mode() {
|
||||||
PrintMode::Flat => best_fitting.most_flat(),
|
PrintMode::Flat => best_fitting.most_flat(),
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! static_assert {
|
|
||||||
($expr:expr) => {
|
|
||||||
const _: i32 = 0 / $expr as i32;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::write;
|
use ruff_formatter::write;
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::Alias;
|
use crate::cst::Alias;
|
||||||
|
@ -23,10 +22,10 @@ impl Format<ASTFormatContext> for FormatAlias<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
|
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
|
||||||
let alias = self.item;
|
let alias = self.item;
|
||||||
|
|
||||||
write!(f, [dynamic_text(&alias.name, TextSize::default())])?;
|
write!(f, [dynamic_text(&alias.name, None)])?;
|
||||||
if let Some(asname) = &alias.asname {
|
if let Some(asname) = &alias.asname {
|
||||||
write!(f, [text(" as ")])?;
|
write!(f, [text(" as ")])?;
|
||||||
write!(f, [dynamic_text(asname, TextSize::default())])?;
|
write!(f, [dynamic_text(asname, None)])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, [end_of_line_comments(alias)])?;
|
write!(f, [end_of_line_comments(alias)])?;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::write;
|
use ruff_formatter::write;
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::Arg;
|
use crate::cst::Arg;
|
||||||
|
@ -23,7 +22,7 @@ impl Format<ASTFormatContext> for FormatArg<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
|
fn fmt(&self, f: &mut Formatter<ASTFormatContext>) -> FormatResult<()> {
|
||||||
let arg = self.item;
|
let arg = self.item;
|
||||||
|
|
||||||
write!(f, [dynamic_text(&arg.arg, TextSize::default())])?;
|
write!(f, [dynamic_text(&arg.arg, None)])?;
|
||||||
if let Some(annotation) = &arg.annotation {
|
if let Some(annotation) = &arg.annotation {
|
||||||
write!(f, [text(": ")])?;
|
write!(f, [text(": ")])?;
|
||||||
write!(f, [annotation.format()])?;
|
write!(f, [annotation.format()])?;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::{write, Format};
|
use ruff_formatter::{write, Format};
|
||||||
use ruff_text_size::{TextRange, TextSize};
|
use ruff_text_size::TextRange;
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::{Body, Stmt};
|
use crate::cst::{Body, Stmt};
|
||||||
|
@ -98,7 +98,7 @@ impl<Context> Format<Context> for JoinNames<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||||
let mut join = f.join_with(text(", "));
|
let mut join = f.join_with(text(", "));
|
||||||
for name in self.names {
|
for name in self.names {
|
||||||
join.entry(&dynamic_text(name, TextSize::default()));
|
join.entry(&dynamic_text(name, None));
|
||||||
}
|
}
|
||||||
join.finish()
|
join.finish()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::write;
|
use ruff_formatter::write;
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::{Excepthandler, ExcepthandlerKind};
|
use crate::cst::{Excepthandler, ExcepthandlerKind};
|
||||||
|
@ -29,15 +28,7 @@ impl Format<ASTFormatContext> for FormatExcepthandler<'_> {
|
||||||
if let Some(type_) = &type_ {
|
if let Some(type_) = &type_ {
|
||||||
write!(f, [space(), type_.format()])?;
|
write!(f, [space(), type_.format()])?;
|
||||||
if let Some(name) = &name {
|
if let Some(name) = &name {
|
||||||
write!(
|
write!(f, [space(), text("as"), space(), dynamic_text(name, None)])?;
|
||||||
f,
|
|
||||||
[
|
|
||||||
space(),
|
|
||||||
text("as"),
|
|
||||||
space(),
|
|
||||||
dynamic_text(name, TextSize::default()),
|
|
||||||
]
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(f, [text(":")])?;
|
write!(f, [text(":")])?;
|
||||||
|
|
|
@ -4,7 +4,6 @@ use rustpython_parser::ast::{Constant, ConversionFlag};
|
||||||
|
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::{format_args, write};
|
use ruff_formatter::{format_args, write};
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::{
|
use crate::cst::{
|
||||||
|
@ -676,7 +675,7 @@ fn format_attribute(
|
||||||
) -> FormatResult<()> {
|
) -> FormatResult<()> {
|
||||||
write!(f, [value.format()])?;
|
write!(f, [value.format()])?;
|
||||||
write!(f, [text(".")])?;
|
write!(f, [text(".")])?;
|
||||||
write!(f, [dynamic_text(attr, TextSize::default())])?;
|
write!(f, [dynamic_text(attr, None)])?;
|
||||||
write!(f, [end_of_line_comments(expr)])?;
|
write!(f, [end_of_line_comments(expr)])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::write;
|
use ruff_formatter::write;
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::Keyword;
|
use crate::cst::Keyword;
|
||||||
|
@ -25,7 +24,7 @@ impl Format<ASTFormatContext> for FormatKeyword<'_> {
|
||||||
|
|
||||||
write!(f, [leading_comments(keyword)])?;
|
write!(f, [leading_comments(keyword)])?;
|
||||||
if let Some(arg) = &keyword.arg {
|
if let Some(arg) = &keyword.arg {
|
||||||
write!(f, [dynamic_text(arg, TextSize::default())])?;
|
write!(f, [dynamic_text(arg, None)])?;
|
||||||
write!(f, [text("=")])?;
|
write!(f, [text("=")])?;
|
||||||
write!(f, [keyword.value.format()])?;
|
write!(f, [keyword.value.format()])?;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -136,8 +136,8 @@ impl Format<ASTFormatContext> for IntLiteral {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
dynamic_text(&prefix.to_lowercase(), TextSize::default()),
|
dynamic_text(&prefix.to_lowercase(), None),
|
||||||
dynamic_text(&suffix.to_uppercase(), TextSize::default())
|
dynamic_text(&suffix.to_uppercase(), None)
|
||||||
]
|
]
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,6 @@ use rustpython_parser::ast::Constant;
|
||||||
|
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::write;
|
use ruff_formatter::write;
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::{Pattern, PatternKind};
|
use crate::cst::{Pattern, PatternKind};
|
||||||
|
@ -79,7 +78,7 @@ impl Format<ASTFormatContext> for FormatPattern<'_> {
|
||||||
space(),
|
space(),
|
||||||
text("**"),
|
text("**"),
|
||||||
space(),
|
space(),
|
||||||
dynamic_text(rest, TextSize::default())
|
dynamic_text(rest, None)
|
||||||
]
|
]
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -105,13 +104,10 @@ impl Format<ASTFormatContext> for FormatPattern<'_> {
|
||||||
if !kwd_attrs.is_empty() {
|
if !kwd_attrs.is_empty() {
|
||||||
write!(f, [text("(")])?;
|
write!(f, [text("(")])?;
|
||||||
if let Some(attr) = kwd_attrs.first() {
|
if let Some(attr) = kwd_attrs.first() {
|
||||||
write!(f, [dynamic_text(attr, TextSize::default())])?;
|
write!(f, [dynamic_text(attr, None)])?;
|
||||||
}
|
}
|
||||||
for attr in kwd_attrs.iter().skip(1) {
|
for attr in kwd_attrs.iter().skip(1) {
|
||||||
write!(
|
write!(f, [text(","), space(), dynamic_text(attr, None)])?;
|
||||||
f,
|
|
||||||
[text(","), space(), dynamic_text(attr, TextSize::default())]
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
write!(f, [text(")")])?;
|
write!(f, [text(")")])?;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +124,7 @@ impl Format<ASTFormatContext> for FormatPattern<'_> {
|
||||||
}
|
}
|
||||||
PatternKind::MatchStar { name } => {
|
PatternKind::MatchStar { name } => {
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
write!(f, [text("*"), dynamic_text(name, TextSize::default())])?;
|
write!(f, [text("*"), dynamic_text(name, None)])?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, [text("*_")])?;
|
write!(f, [text("*_")])?;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +137,7 @@ impl Format<ASTFormatContext> for FormatPattern<'_> {
|
||||||
write!(f, [space()])?;
|
write!(f, [space()])?;
|
||||||
}
|
}
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
write!(f, [dynamic_text(name, TextSize::default())])?;
|
write!(f, [dynamic_text(name, None)])?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, [text("_")])?;
|
write!(f, [text("_")])?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::{format_args, write};
|
use ruff_formatter::{format_args, write};
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::{
|
use crate::cst::{
|
||||||
|
@ -110,14 +109,7 @@ fn format_class_def(
|
||||||
|
|
||||||
write!(f, [leading_comments(body)])?;
|
write!(f, [leading_comments(body)])?;
|
||||||
|
|
||||||
write!(
|
write!(f, [text("class"), space(), dynamic_text(name, None)])?;
|
||||||
f,
|
|
||||||
[
|
|
||||||
text("class"),
|
|
||||||
space(),
|
|
||||||
dynamic_text(name, TextSize::default())
|
|
||||||
]
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if !bases.is_empty() || !keywords.is_empty() {
|
if !bases.is_empty() || !keywords.is_empty() {
|
||||||
let format_bases = format_with(|f| {
|
let format_bases = format_with(|f| {
|
||||||
|
@ -180,7 +172,7 @@ fn format_func_def(
|
||||||
[
|
[
|
||||||
text("def"),
|
text("def"),
|
||||||
space(),
|
space(),
|
||||||
dynamic_text(name, TextSize::default()),
|
dynamic_text(name, None),
|
||||||
text("("),
|
text("("),
|
||||||
group(&soft_block_indent(&format_with(|f| {
|
group(&soft_block_indent(&format_with(|f| {
|
||||||
if stmt.trivia.iter().any(|c| c.kind.is_magic_trailing_comma()) {
|
if stmt.trivia.iter().any(|c| c.kind.is_magic_trailing_comma()) {
|
||||||
|
@ -653,7 +645,7 @@ fn format_import_from(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(module) = module {
|
if let Some(module) = module {
|
||||||
write!(f, [dynamic_text(module, TextSize::default())])?;
|
write!(f, [dynamic_text(module, None)])?;
|
||||||
}
|
}
|
||||||
write!(f, [space()])?;
|
write!(f, [space()])?;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use rustpython_parser::{Mode, Tok};
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::{write, Format};
|
use ruff_formatter::{write, Format};
|
||||||
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
||||||
use ruff_text_size::{TextRange, TextSize};
|
use ruff_text_size::TextRange;
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::cst::Expr;
|
use crate::cst::Expr;
|
||||||
|
@ -64,7 +64,6 @@ impl Format<ASTFormatContext> for StringLiteralPart {
|
||||||
} else {
|
} else {
|
||||||
double_escape(body).into()
|
double_escape(body).into()
|
||||||
},
|
},
|
||||||
source_position: TextSize::default(),
|
|
||||||
})?;
|
})?;
|
||||||
f.write_element(FormatElement::StaticText { text: "\"" })?;
|
f.write_element(FormatElement::StaticText { text: "\"" })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -76,7 +75,6 @@ impl Format<ASTFormatContext> for StringLiteralPart {
|
||||||
} else {
|
} else {
|
||||||
single_escape(body).into()
|
single_escape(body).into()
|
||||||
},
|
},
|
||||||
source_position: TextSize::default(),
|
|
||||||
})?;
|
})?;
|
||||||
f.write_element(FormatElement::StaticText { text: "'" })?;
|
f.write_element(FormatElement::StaticText { text: "'" })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -90,7 +88,6 @@ impl Format<ASTFormatContext> for StringLiteralPart {
|
||||||
f.write_element(FormatElement::StaticText { text: "'''" })?;
|
f.write_element(FormatElement::StaticText { text: "'''" })?;
|
||||||
f.write_element(FormatElement::DynamicText {
|
f.write_element(FormatElement::DynamicText {
|
||||||
text: body.to_string().into_boxed_str(),
|
text: body.to_string().into_boxed_str(),
|
||||||
source_position: TextSize::default(),
|
|
||||||
})?;
|
})?;
|
||||||
f.write_element(FormatElement::StaticText { text: "'''" })?;
|
f.write_element(FormatElement::StaticText { text: "'''" })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -98,7 +95,6 @@ impl Format<ASTFormatContext> for StringLiteralPart {
|
||||||
f.write_element(FormatElement::StaticText { text: "\"\"\"" })?;
|
f.write_element(FormatElement::StaticText { text: "\"\"\"" })?;
|
||||||
f.write_element(FormatElement::DynamicText {
|
f.write_element(FormatElement::DynamicText {
|
||||||
text: body.to_string().into_boxed_str(),
|
text: body.to_string().into_boxed_str(),
|
||||||
source_position: TextSize::default(),
|
|
||||||
})?;
|
})?;
|
||||||
f.write_element(FormatElement::StaticText { text: "\"\"\"" })?;
|
f.write_element(FormatElement::StaticText { text: "\"\"\"" })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -67,7 +67,6 @@ mod tests {
|
||||||
use insta::assert_snapshot;
|
use insta::assert_snapshot;
|
||||||
|
|
||||||
use ruff_testing_macros::fixture;
|
use ruff_testing_macros::fixture;
|
||||||
use ruff_text_size::TextSize;
|
|
||||||
use similar::TextDiff;
|
use similar::TextDiff;
|
||||||
|
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
|
@ -208,7 +207,7 @@ mod tests {
|
||||||
while let Some(word) = words.next() {
|
while let Some(word) = words.next() {
|
||||||
let is_last = words.peek().is_none();
|
let is_last = words.peek().is_none();
|
||||||
let format_word = format_with(|f| {
|
let format_word = format_with(|f| {
|
||||||
write!(f, [dynamic_text(word, TextSize::default())])?;
|
write!(f, [dynamic_text(word, None)])?;
|
||||||
|
|
||||||
if is_last {
|
if is_last {
|
||||||
write!(f, [text("\"")])?;
|
write!(f, [text("\"")])?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue