mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-02 09:52:18 +00:00
Remove allow(pedantic)
from formatter (#6549)
This commit is contained in:
parent
c39bcbadff
commit
9584f613b9
25 changed files with 348 additions and 316 deletions
|
@ -16,7 +16,7 @@ pub(crate) fn bindings(checker: &mut Checker) {
|
|||
return;
|
||||
}
|
||||
|
||||
for binding in checker.semantic.bindings.iter() {
|
||||
for binding in &*checker.semantic.bindings {
|
||||
if checker.enabled(Rule::UnusedVariable) {
|
||||
if binding.kind.is_bound_exception()
|
||||
&& !binding.is_used()
|
||||
|
|
|
@ -59,7 +59,7 @@ impl Eq for LineWidth {}
|
|||
|
||||
impl PartialOrd for LineWidth {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
self.width.partial_cmp(&other.width)
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ impl TryFrom<Options> for Settings {
|
|||
.ignore_names
|
||||
.unwrap_or_else(default_ignore_names)
|
||||
.into_iter()
|
||||
.chain(options.extend_ignore_names.unwrap_or_default().into_iter())
|
||||
.chain(options.extend_ignore_names.unwrap_or_default())
|
||||
.map(|name| IdentifierPattern::new(&name).map_err(SettingsError::InvalidIgnoreName))
|
||||
.collect::<Result<Vec<_>, Self::Error>>()?,
|
||||
classmethod_decorators: options.classmethod_decorators.unwrap_or_default(),
|
||||
|
|
|
@ -132,7 +132,7 @@ static FORMAT_SPECIFIER: Lazy<Regex> =
|
|||
Lazy::new(|| Regex::new(r"\{(?P<int>\d+)(?P<fmt>.*?)}").unwrap());
|
||||
|
||||
/// Remove the explicit positional indices from a format string.
|
||||
fn remove_specifiers<'a>(value: &mut Expression<'a>, arena: &'a mut typed_arena::Arena<String>) {
|
||||
fn remove_specifiers<'a>(value: &mut Expression<'a>, arena: &'a typed_arena::Arena<String>) {
|
||||
match value {
|
||||
Expression::SimpleString(expr) => {
|
||||
expr.value = arena.alloc(
|
||||
|
@ -217,8 +217,8 @@ fn generate_call(
|
|||
|
||||
// Fix the string itself.
|
||||
let item = match_attribute(&mut call.func)?;
|
||||
let mut arena = typed_arena::Arena::new();
|
||||
remove_specifiers(&mut item.value, &mut arena);
|
||||
let arena = typed_arena::Arena::new();
|
||||
remove_specifiers(&mut item.value, &arena);
|
||||
|
||||
// Remove the parentheses (first and last characters).
|
||||
let mut output = expression.codegen_stylist(stylist);
|
||||
|
|
|
@ -3,8 +3,8 @@ use crate::FormatResult;
|
|||
use std::ffi::c_void;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Mono-morphed type to format an object. Used by the [crate::format!], [crate::format_args!], and
|
||||
/// [crate::write!] macros.
|
||||
/// Mono-morphed type to format an object. Used by the [`crate::format`!], [`crate::format_args`!], and
|
||||
/// [`crate::write`!] macros.
|
||||
///
|
||||
/// This struct is similar to a dynamic dispatch (using `dyn Format`) because it stores a pointer to the value.
|
||||
/// However, it doesn't store the pointer to `dyn Format`'s vtable, instead it statically resolves the function
|
||||
|
@ -33,23 +33,26 @@ impl<'fmt, Context> Argument<'fmt, Context> {
|
|||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn new<F: Format<Context>>(value: &'fmt F) -> Self {
|
||||
#[allow(clippy::inline_always)]
|
||||
#[inline(always)]
|
||||
fn formatter<F: Format<Context>, Context>(
|
||||
ptr: *const c_void,
|
||||
fmt: &mut Formatter<Context>,
|
||||
) -> FormatResult<()> {
|
||||
// SAFETY: Safe because the 'fmt lifetime is captured by the 'lifetime' field.
|
||||
F::fmt(unsafe { &*(ptr as *const F) }, fmt)
|
||||
#[allow(unsafe_code)]
|
||||
F::fmt(unsafe { &*ptr.cast::<F>() }, fmt)
|
||||
}
|
||||
|
||||
Self {
|
||||
value: value as *const F as *const c_void,
|
||||
value: (value as *const F).cast::<std::ffi::c_void>(),
|
||||
lifetime: PhantomData,
|
||||
formatter: formatter::<F, Context>,
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats the value stored by this argument using the given formatter.
|
||||
#[allow(clippy::inline_always)]
|
||||
#[inline(always)]
|
||||
pub(super) fn format(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||
(self.formatter)(self.value, f)
|
||||
|
@ -79,6 +82,7 @@ impl<'fmt, Context> Argument<'fmt, Context> {
|
|||
pub struct Arguments<'fmt, Context>(pub &'fmt [Argument<'fmt, Context>]);
|
||||
|
||||
impl<'fmt, Context> Arguments<'fmt, Context> {
|
||||
#[allow(clippy::inline_always)]
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
pub fn new(arguments: &'fmt [Argument<'fmt, Context>]) -> Self {
|
||||
|
@ -87,6 +91,7 @@ impl<'fmt, Context> Arguments<'fmt, Context> {
|
|||
|
||||
/// Returns the arguments
|
||||
#[inline]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)] // Bug in Clippy? Sizeof Arguments is 16
|
||||
pub(super) fn items(&self) -> &'fmt [Argument<'fmt, Context>] {
|
||||
self.0
|
||||
}
|
||||
|
@ -101,6 +106,7 @@ impl<Context> Clone for Arguments<'_, Context> {
|
|||
}
|
||||
|
||||
impl<Context> Format<Context> for Arguments<'_, Context> {
|
||||
#[allow(clippy::inline_always)]
|
||||
#[inline(always)]
|
||||
fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
|
||||
formatter.write_fmt(*self)
|
||||
|
|
|
@ -7,15 +7,15 @@ use std::any::{Any, TypeId};
|
|||
use std::fmt::Debug;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// A trait for writing or formatting into [FormatElement]-accepting buffers or streams.
|
||||
/// A trait for writing or formatting into [`FormatElement`]-accepting buffers or streams.
|
||||
pub trait Buffer {
|
||||
/// The context used during formatting
|
||||
type Context;
|
||||
|
||||
/// Writes a [crate::FormatElement] into this buffer, returning whether the write succeeded.
|
||||
/// Writes a [`crate::FormatElement`] into this buffer, returning whether the write succeeded.
|
||||
///
|
||||
/// # Errors
|
||||
/// This function will return an instance of [crate::FormatError] on error.
|
||||
/// This function will return an instance of [`crate::FormatError`] on error.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -122,7 +122,7 @@ impl BufferSnapshot {
|
|||
Err(err) => {
|
||||
panic!(
|
||||
"Tried to unwrap snapshot of type {:?} as {:?}",
|
||||
err.type_id(),
|
||||
(*err).type_id(),
|
||||
TypeId::of::<T>()
|
||||
)
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ impl<W: Buffer<Context = Context> + ?Sized, Context> Buffer for &mut W {
|
|||
}
|
||||
|
||||
fn restore_snapshot(&mut self, snapshot: BufferSnapshot) {
|
||||
(**self).restore_snapshot(snapshot)
|
||||
(**self).restore_snapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,7 +426,7 @@ where
|
|||
}
|
||||
|
||||
fn restore_snapshot(&mut self, snapshot: BufferSnapshot) {
|
||||
self.inner.restore_snapshot(snapshot)
|
||||
self.inner.restore_snapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,9 +508,9 @@ fn clean_interned(
|
|||
interned: &Interned,
|
||||
interned_cache: &mut FxHashMap<Interned, Interned>,
|
||||
) -> Interned {
|
||||
match interned_cache.get(interned) {
|
||||
Some(cleaned) => cleaned.clone(),
|
||||
None => {
|
||||
if let Some(cleaned) = interned_cache.get(interned) {
|
||||
cleaned.clone()
|
||||
} else {
|
||||
// Find the first soft line break element or interned element that must be changed
|
||||
let result = interned
|
||||
.iter()
|
||||
|
@ -524,13 +524,13 @@ fn clean_interned(
|
|||
FormatElement::Interned(inner) => {
|
||||
let cleaned_inner = clean_interned(inner, interned_cache);
|
||||
|
||||
if &cleaned_inner != inner {
|
||||
if &cleaned_inner == inner {
|
||||
None
|
||||
} else {
|
||||
let mut cleaned = Vec::with_capacity(interned.len());
|
||||
cleaned.extend_from_slice(&interned[..index]);
|
||||
cleaned.push(FormatElement::Interned(cleaned_inner));
|
||||
Some((cleaned, &interned[index + 1..]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,7 +549,7 @@ fn clean_interned(
|
|||
}
|
||||
element => element.clone(),
|
||||
};
|
||||
cleaned.push(element)
|
||||
cleaned.push(element);
|
||||
}
|
||||
|
||||
Interned::new(cleaned)
|
||||
|
@ -561,7 +561,6 @@ fn clean_interned(
|
|||
interned_cache.insert(interned.clone(), result.clone());
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context> Buffer for RemoveSoftLinesBuffer<'_, Context> {
|
||||
|
@ -597,7 +596,7 @@ impl<Context> Buffer for RemoveSoftLinesBuffer<'_, Context> {
|
|||
}
|
||||
|
||||
fn restore_snapshot(&mut self, snapshot: BufferSnapshot) {
|
||||
self.inner.restore_snapshot(snapshot)
|
||||
self.inner.restore_snapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -658,7 +657,7 @@ pub trait BufferExtensions: Buffer + Sized {
|
|||
where
|
||||
I: IntoIterator<Item = FormatElement>,
|
||||
{
|
||||
for element in elements.into_iter() {
|
||||
for element in elements {
|
||||
self.write_element(element)?;
|
||||
}
|
||||
|
||||
|
@ -685,12 +684,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn write_fmt(&mut self, arguments: Arguments<B::Context>) -> FormatResult<()> {
|
||||
self.buffer.write_fmt(arguments)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn write_element(&mut self, element: FormatElement) -> FormatResult<()> {
|
||||
self.buffer.write_element(element)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use ruff_text_size::TextRange;
|
|||
use std::cell::Cell;
|
||||
use std::marker::PhantomData;
|
||||
use std::num::NonZeroU8;
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
use Tag::*;
|
||||
|
||||
/// A line break that only gets printed if the enclosing `Group` doesn't fit on a single line.
|
||||
|
@ -34,7 +35,7 @@ use Tag::*;
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
/// See [soft_line_break_or_space] if you want to insert a space between the elements if the enclosing
|
||||
/// See [`soft_line_break_or_space`] if you want to insert a space between the elements if the enclosing
|
||||
/// `Group` fits on a single line.
|
||||
///
|
||||
/// Soft line breaks are emitted if the enclosing `Group` doesn't fit on a single line
|
||||
|
@ -217,7 +218,7 @@ impl std::fmt::Debug for Line {
|
|||
///
|
||||
/// # Line feeds
|
||||
/// Tokens may contain line breaks but they must use the line feeds (`\n`).
|
||||
/// The [crate::Printer] converts the line feed characters to the character specified in the [crate::PrinterOptions].
|
||||
/// The [`crate::Printer`] converts the line feed characters to the character specified in the [`crate::PrinterOptions`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -520,7 +521,7 @@ impl<Context> Format<Context> for LineSuffixBoundary {
|
|||
///
|
||||
/// This does not directly influence how this content will be printed, but some
|
||||
/// parts of the formatter may inspect the [labelled element](Tag::StartLabelled)
|
||||
/// using [FormatElements::has_label].
|
||||
/// using [`FormatElements::has_label`].
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
|
@ -648,7 +649,7 @@ impl<Context> Format<Context> for Space {
|
|||
/// the line breaks have to be manually added.
|
||||
///
|
||||
/// This helper should be used only in rare cases, instead you should rely more on
|
||||
/// [block_indent] and [soft_block_indent]
|
||||
/// [`block_indent`] and [`soft_block_indent`]
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -970,7 +971,7 @@ impl<Context> std::fmt::Debug for Align<'_, Context> {
|
|||
/// Block indents indent a block of code, such as in a function body, and therefore insert a line
|
||||
/// break before and after the content.
|
||||
///
|
||||
/// Doesn't create an indention if the passed in content is [FormatElement.is_empty].
|
||||
/// Doesn't create an indention if the passed in content is [`FormatElement.is_empty`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1176,7 +1177,7 @@ impl<Context> Format<Context> for BlockIndent<'_, Context> {
|
|||
IndentMode::Soft => write!(f, [soft_line_break()])?,
|
||||
IndentMode::Block => write!(f, [hard_line_break()])?,
|
||||
IndentMode::SoftLineOrSpace | IndentMode::SoftSpace => {
|
||||
write!(f, [soft_line_break_or_space()])?
|
||||
write!(f, [soft_line_break_or_space()])?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1374,17 +1375,19 @@ pub struct Group<'a, Context> {
|
|||
}
|
||||
|
||||
impl<Context> Group<'_, Context> {
|
||||
#[must_use]
|
||||
pub fn with_group_id(mut self, group_id: Option<GroupId>) -> Self {
|
||||
self.group_id = group_id;
|
||||
self
|
||||
}
|
||||
|
||||
/// Changes the [PrintMode] of the group from [`Flat`](PrintMode::Flat) to [`Expanded`](PrintMode::Expanded).
|
||||
/// Changes the [`PrintMode`] of the group from [`Flat`](PrintMode::Flat) to [`Expanded`](PrintMode::Expanded).
|
||||
/// The result is that any soft-line break gets printed as a regular line break.
|
||||
///
|
||||
/// This is useful for content rendered inside of a [FormatElement::BestFitting] that prints each variant
|
||||
/// in [PrintMode::Flat] to change some content to be printed in [`Expanded`](PrintMode::Expanded) regardless.
|
||||
/// This is useful for content rendered inside of a [`FormatElement::BestFitting`] that prints each variant
|
||||
/// in [`PrintMode::Flat`] to change some content to be printed in [`Expanded`](PrintMode::Expanded) regardless.
|
||||
/// See the documentation of the [`best_fitting`] macro for an example.
|
||||
#[must_use]
|
||||
pub fn should_expand(mut self, should_expand: bool) -> Self {
|
||||
self.should_expand = should_expand;
|
||||
self
|
||||
|
@ -1393,9 +1396,10 @@ impl<Context> Group<'_, Context> {
|
|||
|
||||
impl<Context> Format<Context> for Group<'_, Context> {
|
||||
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||
let mode = match self.should_expand {
|
||||
true => GroupMode::Expand,
|
||||
false => GroupMode::Flat,
|
||||
let mode = if self.should_expand {
|
||||
GroupMode::Expand
|
||||
} else {
|
||||
GroupMode::Flat
|
||||
};
|
||||
|
||||
f.write_element(FormatElement::Tag(StartGroup(
|
||||
|
@ -1602,7 +1606,7 @@ impl<Context> Format<Context> for ExpandParent {
|
|||
///
|
||||
/// The element has no special meaning if used outside of a `Group`. In that case, the content is always emitted.
|
||||
///
|
||||
/// If you're looking for a way to only print something if the `Group` fits on a single line see [self::if_group_fits_on_line].
|
||||
/// If you're looking for a way to only print something if the `Group` fits on a single line see [`self::if_group_fits_on_line`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1684,7 +1688,7 @@ where
|
|||
/// Adds a conditional content specific for `Group`s that fit on a single line. The content isn't
|
||||
/// emitted for `Group`s spanning multiple lines.
|
||||
///
|
||||
/// See [if_group_breaks] if you're looking for a way to print content only for groups spanning multiple lines.
|
||||
/// See [`if_group_breaks`] if you're looking for a way to print content only for groups spanning multiple lines.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1823,6 +1827,7 @@ impl<Context> IfGroupBreaks<'_, Context> {
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn with_group_id(mut self, group_id: Option<GroupId>) -> Self {
|
||||
self.group_id = group_id;
|
||||
self
|
||||
|
@ -1855,7 +1860,7 @@ impl<Context> std::fmt::Debug for IfGroupBreaks<'_, Context> {
|
|||
|
||||
/// Increases the indent level by one if the group with the specified id breaks.
|
||||
///
|
||||
/// This IR has the same semantics as using [if_group_breaks] and [if_group_fits_on_line] together.
|
||||
/// This IR has the same semantics as using [`if_group_breaks`] and [`if_group_fits_on_line`] together.
|
||||
///
|
||||
/// ```
|
||||
/// # use ruff_formatter::prelude::*;
|
||||
|
@ -1874,7 +1879,7 @@ impl<Context> std::fmt::Debug for IfGroupBreaks<'_, Context> {
|
|||
///
|
||||
/// If you want to indent some content if the enclosing group breaks, use [`indent`].
|
||||
///
|
||||
/// Use [if_group_breaks] or [if_group_fits_on_line] if the fitting and breaking content differs more than just the
|
||||
/// Use [`if_group_breaks`] or [`if_group_fits_on_line`] if the fitting and breaking content differs more than just the
|
||||
/// indention level.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -1972,7 +1977,7 @@ impl<Context> std::fmt::Debug for IndentIfGroupBreaks<'_, Context> {
|
|||
|
||||
/// Changes the definition of *fits* for `content`. Instead of measuring it in *flat*, measure it with
|
||||
/// all line breaks expanded and test if no line exceeds the line width. The [`FitsExpanded`] acts
|
||||
/// as a expands boundary similar to best fitting, meaning that a [hard_line_break] will not cause the parent group to expand.
|
||||
/// as a expands boundary similar to best fitting, meaning that a [`hard_line_break`] will not cause the parent group to expand.
|
||||
///
|
||||
/// Useful in conjunction with a group with a condition.
|
||||
///
|
||||
|
@ -2034,6 +2039,7 @@ pub struct FitsExpanded<'a, Context> {
|
|||
impl<Context> FitsExpanded<'_, Context> {
|
||||
/// Sets a `condition` to when the content should fit in expanded mode. The content uses the regular fits
|
||||
/// definition if the `condition` is not met.
|
||||
#[must_use]
|
||||
pub fn with_condition(mut self, condition: Option<Condition>) -> Self {
|
||||
self.condition = condition;
|
||||
self
|
||||
|
@ -2061,7 +2067,7 @@ impl<Context, T> Format<Context> for FormatWith<Context, T>
|
|||
where
|
||||
T: Fn(&mut Formatter<Context>) -> FormatResult<()>,
|
||||
{
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||
(self.formatter)(f)
|
||||
}
|
||||
|
@ -2207,7 +2213,7 @@ impl<T, Context> Format<Context> for FormatOnce<T, Context>
|
|||
where
|
||||
T: FnOnce(&mut Formatter<Context>) -> FormatResult<()>,
|
||||
{
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||
let formatter = self.formatter.take().expect("Tried to format a `format_once` at least twice. This is not allowed. You may want to use `format_with` or `format.memoized` instead.");
|
||||
|
||||
|
@ -2222,7 +2228,7 @@ impl<T, Context> std::fmt::Debug for FormatOnce<T, Context> {
|
|||
}
|
||||
|
||||
/// Builder to join together a sequence of content.
|
||||
/// See [Formatter::join]
|
||||
/// See [`Formatter::join`]
|
||||
#[must_use = "must eventually call `finish()` on Format builders"]
|
||||
pub struct JoinBuilder<'fmt, 'buf, Separator, Context> {
|
||||
result: FormatResult<()>,
|
||||
|
@ -2367,7 +2373,9 @@ impl<'a, Context> BestFitting<'a, Context> {
|
|||
/// You're looking for a way to create a `BestFitting` object, use the `best_fitting![least_expanded, most_expanded]` macro.
|
||||
///
|
||||
/// ## Safety
|
||||
|
||||
/// The slice must contain at least two variants.
|
||||
#[allow(unsafe_code)]
|
||||
pub unsafe fn from_arguments_unchecked(variants: Arguments<'a, Context>) -> Self {
|
||||
assert!(
|
||||
variants.0.len() >= 2,
|
||||
|
@ -2395,6 +2403,7 @@ impl<Context> Format<Context> for BestFitting<'_, Context> {
|
|||
|
||||
// SAFETY: The constructor guarantees that there are always at least two variants. It's, therefore,
|
||||
// safe to call into the unsafe `from_vec_unchecked` function
|
||||
#[allow(unsafe_code)]
|
||||
let element = unsafe {
|
||||
FormatElement::BestFitting {
|
||||
variants: format_element::BestFittingVariants::from_vec_unchecked(
|
||||
|
|
|
@ -13,7 +13,7 @@ use ruff_text_size::TextSize;
|
|||
|
||||
/// 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.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub enum FormatElement {
|
||||
/// A space token, see [crate::builders::space] for documentation.
|
||||
|
@ -88,9 +88,7 @@ impl std::fmt::Debug for FormatElement {
|
|||
.debug_struct("BestFitting")
|
||||
.field("variants", variants)
|
||||
.finish(),
|
||||
FormatElement::Interned(interned) => {
|
||||
fmt.debug_list().entries(interned.deref()).finish()
|
||||
}
|
||||
FormatElement::Interned(interned) => fmt.debug_list().entries(&**interned).finish(),
|
||||
FormatElement::Tag(tag) => fmt.debug_tuple("Tag").field(tag).finish(),
|
||||
FormatElement::SourcePosition(position) => {
|
||||
fmt.debug_tuple("SourcePosition").field(position).finish()
|
||||
|
@ -180,7 +178,7 @@ impl Deref for Interned {
|
|||
type Target = [FormatElement];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0.deref()
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,12 +215,12 @@ pub fn normalize_newlines<const N: usize>(text: &str, terminators: [char; N]) ->
|
|||
}
|
||||
|
||||
impl FormatElement {
|
||||
/// Returns `true` if self is a [FormatElement::Tag]
|
||||
/// Returns `true` if self is a [`FormatElement::Tag`]
|
||||
pub const fn is_tag(&self) -> bool {
|
||||
matches!(self, FormatElement::Tag(_))
|
||||
}
|
||||
|
||||
/// Returns `true` if self is a [FormatElement::Tag] and [Tag::is_start] is `true`.
|
||||
/// Returns `true` if self is a [`FormatElement::Tag`] and [`Tag::is_start`] is `true`.
|
||||
pub const fn is_start_tag(&self) -> bool {
|
||||
match self {
|
||||
FormatElement::Tag(tag) => tag.is_start(),
|
||||
|
@ -230,7 +228,7 @@ impl FormatElement {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if self is a [FormatElement::Tag] and [Tag::is_end] is `true`.
|
||||
/// Returns `true` if self is a [`FormatElement::Tag`] and [`Tag::is_end`] is `true`.
|
||||
pub const fn is_end_tag(&self) -> bool {
|
||||
match self {
|
||||
FormatElement::Tag(tag) => tag.is_end(),
|
||||
|
@ -313,6 +311,7 @@ impl BestFittingVariants {
|
|||
/// ## Safety
|
||||
/// The slice must contain at least two variants.
|
||||
#[doc(hidden)]
|
||||
#[allow(unsafe_code)]
|
||||
pub unsafe fn from_vec_unchecked(variants: Vec<Box<[FormatElement]>>) -> Self {
|
||||
debug_assert!(
|
||||
variants.len() >= 2,
|
||||
|
@ -359,9 +358,9 @@ impl<'a> IntoIterator for &'a BestFittingVariants {
|
|||
}
|
||||
|
||||
pub trait FormatElements {
|
||||
/// Returns true if this [FormatElement] is guaranteed to break across multiple lines by the printer.
|
||||
/// Returns true if this [`FormatElement`] is guaranteed to break across multiple lines by the printer.
|
||||
/// This is the case if this format element recursively contains a:
|
||||
/// - [crate::builders::empty_line] or [crate::builders::hard_line_break]
|
||||
/// - [`crate::builders::empty_line`] or [`crate::builders::hard_line_break`]
|
||||
/// - A token containing '\n'
|
||||
///
|
||||
/// Use this with caution, this is only a heuristic and the printer may print the element over multiple
|
||||
|
|
|
@ -21,9 +21,9 @@ pub struct Document {
|
|||
|
||||
impl Document {
|
||||
/// Sets [`expand`](tag::Group::expand) to [`GroupMode::Propagated`] if the group contains any of:
|
||||
/// - a group with [`expand`](tag::Group::expand) set to [GroupMode::Propagated] or [GroupMode::Expand].
|
||||
/// - a non-soft [line break](FormatElement::Line) with mode [LineMode::Hard], [LineMode::Empty], or [LineMode::Literal].
|
||||
/// - a [FormatElement::ExpandParent]
|
||||
/// - a group with [`expand`](tag::Group::expand) set to [`GroupMode::Propagated`] or [`GroupMode::Expand`].
|
||||
/// - a non-soft [line break](FormatElement::Line) with mode [`LineMode::Hard`], [`LineMode::Empty`], or [`LineMode::Literal`].
|
||||
/// - a [`FormatElement::ExpandParent`]
|
||||
///
|
||||
/// [`BestFitting`] elements act as expand boundaries, meaning that the fact that a
|
||||
/// [`BestFitting`]'s content expands is not propagated past the [`BestFitting`] element.
|
||||
|
@ -71,15 +71,16 @@ impl Document {
|
|||
Some(Enclosing::ConditionalGroup(group)) => !group.mode().is_flat(),
|
||||
_ => false,
|
||||
},
|
||||
FormatElement::Interned(interned) => match checked_interned.get(interned) {
|
||||
Some(interned_expands) => *interned_expands,
|
||||
None => {
|
||||
FormatElement::Interned(interned) => {
|
||||
if let Some(interned_expands) = checked_interned.get(interned) {
|
||||
*interned_expands
|
||||
} else {
|
||||
let interned_expands =
|
||||
propagate_expands(interned, enclosing, checked_interned);
|
||||
checked_interned.insert(interned, interned_expands);
|
||||
interned_expands
|
||||
}
|
||||
},
|
||||
}
|
||||
FormatElement::BestFitting { variants } => {
|
||||
enclosing.push(Enclosing::BestFitting);
|
||||
|
||||
|
@ -114,7 +115,7 @@ impl Document {
|
|||
|
||||
if element_expands {
|
||||
expands = true;
|
||||
expand_parent(enclosing)
|
||||
expand_parent(enclosing);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,6 +227,7 @@ impl FormatOptions for IrFormatOptions {
|
|||
|
||||
impl Format<IrFormatContext<'_>> for &[FormatElement] {
|
||||
fn fmt(&self, f: &mut Formatter<IrFormatContext>) -> FormatResult<()> {
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
use Tag::*;
|
||||
|
||||
write!(f, [ContentArrayStart])?;
|
||||
|
@ -245,16 +247,10 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
|
|||
first_element = false;
|
||||
|
||||
match element {
|
||||
element @ FormatElement::Space
|
||||
| element @ FormatElement::StaticText { .. }
|
||||
| element @ FormatElement::DynamicText { .. }
|
||||
| element @ FormatElement::SourceCodeSlice { .. } => {
|
||||
if !in_text {
|
||||
write!(f, [text("\"")])?;
|
||||
}
|
||||
|
||||
in_text = true;
|
||||
|
||||
element @ (FormatElement::Space
|
||||
| FormatElement::StaticText { .. }
|
||||
| FormatElement::DynamicText { .. }
|
||||
| FormatElement::SourceCodeSlice { .. }) => {
|
||||
fn write_escaped(
|
||||
element: &FormatElement,
|
||||
f: &mut Formatter<IrFormatContext>,
|
||||
|
@ -277,6 +273,12 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
|
|||
}
|
||||
}
|
||||
|
||||
if !in_text {
|
||||
write!(f, [text("\"")])?;
|
||||
}
|
||||
|
||||
in_text = true;
|
||||
|
||||
match element {
|
||||
FormatElement::Space => {
|
||||
write!(f, [text(" ")])?;
|
||||
|
@ -317,7 +319,7 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
|
|||
write!(
|
||||
f,
|
||||
[dynamic_text(
|
||||
&std::format!("source_position({:?})", position),
|
||||
&std::format!("source_position({position:?})"),
|
||||
None
|
||||
)]
|
||||
)?;
|
||||
|
@ -335,7 +337,7 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
|
|||
])?;
|
||||
|
||||
for variant in variants {
|
||||
write!(f, [variant.deref(), hard_line_break()])?;
|
||||
write!(f, [&**variant, hard_line_break()])?;
|
||||
}
|
||||
|
||||
f.write_elements([
|
||||
|
@ -359,7 +361,7 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
|
|||
[
|
||||
dynamic_text(&std::format!("<interned {index}>"), None),
|
||||
space(),
|
||||
&interned.deref(),
|
||||
&&**interned,
|
||||
]
|
||||
)?;
|
||||
}
|
||||
|
@ -621,7 +623,7 @@ struct ContentArrayStart;
|
|||
|
||||
impl Format<IrFormatContext<'_>> for ContentArrayStart {
|
||||
fn fmt(&self, f: &mut Formatter<IrFormatContext>) -> FormatResult<()> {
|
||||
use Tag::*;
|
||||
use Tag::{StartGroup, StartIndent};
|
||||
|
||||
write!(f, [text("[")])?;
|
||||
|
||||
|
@ -637,7 +639,7 @@ struct ContentArrayEnd;
|
|||
|
||||
impl Format<IrFormatContext<'_>> for ContentArrayEnd {
|
||||
fn fmt(&self, f: &mut Formatter<IrFormatContext>) -> FormatResult<()> {
|
||||
use Tag::*;
|
||||
use Tag::{EndGroup, EndIndent};
|
||||
f.write_elements([
|
||||
FormatElement::Tag(EndIndent),
|
||||
FormatElement::Line(LineMode::Soft),
|
||||
|
@ -650,7 +652,7 @@ impl Format<IrFormatContext<'_>> for ContentArrayEnd {
|
|||
|
||||
impl FormatElements for [FormatElement] {
|
||||
fn will_break(&self) -> bool {
|
||||
use Tag::*;
|
||||
use Tag::{EndLineSuffix, StartLineSuffix};
|
||||
let mut ignore_depth = 0usize;
|
||||
|
||||
for element in self {
|
||||
|
@ -687,9 +689,6 @@ impl FormatElements for [FormatElement] {
|
|||
}
|
||||
|
||||
fn start_tag(&self, kind: TagKind) -> Option<&Tag> {
|
||||
// Assert that the document ends at a tag with the specified kind;
|
||||
let _ = self.end_tag(kind)?;
|
||||
|
||||
fn traverse_slice<'a>(
|
||||
slice: &'a [FormatElement],
|
||||
kind: TagKind,
|
||||
|
@ -704,9 +703,8 @@ impl FormatElements for [FormatElement] {
|
|||
return None;
|
||||
} else if *depth == 1 {
|
||||
return Some(tag);
|
||||
} else {
|
||||
*depth -= 1;
|
||||
}
|
||||
*depth -= 1;
|
||||
} else {
|
||||
*depth += 1;
|
||||
}
|
||||
|
@ -731,6 +729,8 @@ impl FormatElements for [FormatElement] {
|
|||
|
||||
None
|
||||
}
|
||||
// Assert that the document ends at a tag with the specified kind;
|
||||
let _ = self.end_tag(kind)?;
|
||||
|
||||
let mut depth = 0usize;
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ impl Tag {
|
|||
}
|
||||
|
||||
pub const fn kind(&self) -> TagKind {
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
use Tag::*;
|
||||
|
||||
match self {
|
||||
|
@ -180,13 +181,14 @@ impl FitsExpanded {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_condition(mut self, condition: Option<Condition>) -> Self {
|
||||
self.condition = condition;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn propagate_expand(&self) {
|
||||
self.propagate_expand.set(true)
|
||||
self.propagate_expand.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,11 +206,13 @@ impl Group {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_id(mut self, id: Option<GroupId>) -> Self {
|
||||
self.id = id;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_mode(mut self, mode: GroupMode) -> Self {
|
||||
self.mode = Cell::new(mode);
|
||||
self
|
||||
|
@ -220,7 +224,7 @@ impl Group {
|
|||
|
||||
pub fn propagate_expand(&self) {
|
||||
if self.mode.get() == GroupMode::Flat {
|
||||
self.mode.set(GroupMode::Propagated)
|
||||
self.mode.set(GroupMode::Propagated);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,7 +252,7 @@ impl ConditionalGroup {
|
|||
}
|
||||
|
||||
pub fn propagate_expand(&self) {
|
||||
self.mode.set(GroupMode::Propagated)
|
||||
self.mode.set(GroupMode::Propagated);
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> GroupMode {
|
||||
|
@ -312,6 +316,7 @@ impl Condition {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_group_id(mut self, id: Option<GroupId>) -> Self {
|
||||
self.group_id = id;
|
||||
self
|
||||
|
@ -350,6 +355,7 @@ impl PartialEq for LabelId {
|
|||
}
|
||||
|
||||
impl LabelId {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn of<T: LabelDefinition>(label: T) -> Self {
|
||||
Self {
|
||||
value: label.value(),
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
use crate::prelude::*;
|
||||
use std::cell::RefCell;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::Buffer;
|
||||
|
||||
|
@ -149,7 +148,7 @@ where
|
|||
.get_or_insert_with(|| f.intern(&self.inner));
|
||||
|
||||
match result.as_ref() {
|
||||
Ok(Some(FormatElement::Interned(interned))) => Ok(interned.deref()),
|
||||
Ok(Some(FormatElement::Interned(interned))) => Ok(&**interned),
|
||||
Ok(Some(other)) => Ok(std::slice::from_ref(other)),
|
||||
Ok(None) => Ok(&[]),
|
||||
Err(error) => Err(*error),
|
||||
|
|
|
@ -35,7 +35,7 @@ impl<'buf, Context> Formatter<'buf, Context> {
|
|||
}
|
||||
|
||||
/// Creates a new group id that is unique to this document. The passed debug name is used in the
|
||||
/// [std::fmt::Debug] of the document if this is a debug build.
|
||||
/// [`std::fmt::Debug`] of the document if this is a debug build.
|
||||
/// The name is unused for production builds and has no meaning on the equality of two group ids.
|
||||
pub fn group_id(&self, debug_name: &'static str) -> GroupId {
|
||||
self.state().group_id(debug_name)
|
||||
|
@ -108,7 +108,7 @@ impl<'buf, Context> Formatter<'buf, Context> {
|
|||
JoinBuilder::with_separator(self, joiner)
|
||||
}
|
||||
|
||||
/// Concatenates a list of [crate::Format] objects with spaces and line breaks to fit
|
||||
/// Concatenates a list of [`crate::Format`] objects with spaces and line breaks to fit
|
||||
/// them on as few lines as possible. Each element introduces a conceptual group. The printer
|
||||
/// first tries to print the item in flat mode but then prints it in expanded mode if it doesn't fit.
|
||||
///
|
||||
|
@ -205,7 +205,7 @@ where
|
|||
impl<Context> Buffer for Formatter<'_, Context> {
|
||||
type Context = Context;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn write_element(&mut self, element: FormatElement) -> FormatResult<()> {
|
||||
self.buffer.write_element(element)
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ impl<Context> Buffer for Formatter<'_, Context> {
|
|||
self.buffer.elements()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn write_fmt(&mut self, arguments: Arguments<Self::Context>) -> FormatResult<()> {
|
||||
for argument in arguments.items() {
|
||||
argument.format(self)?;
|
||||
|
@ -235,7 +235,7 @@ impl<Context> Buffer for Formatter<'_, Context> {
|
|||
}
|
||||
|
||||
fn restore_snapshot(&mut self, snapshot: BufferSnapshot) {
|
||||
self.buffer.restore_snapshot(snapshot)
|
||||
self.buffer.restore_snapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ impl std::fmt::Debug for DebugGroupId {
|
|||
|
||||
/// Unique identification for a group.
|
||||
///
|
||||
/// See [crate::Formatter::group_id] on how to get a unique id.
|
||||
/// See [`crate::Formatter::group_id`] on how to get a unique id.
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct ReleaseGroupId {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
//! Infrastructure for code formatting
|
||||
//!
|
||||
//! This module defines [FormatElement], an IR to format code documents and provides a mean to print
|
||||
//! This module defines [`FormatElement`], an IR to format code documents and provides a mean to print
|
||||
//! such a document to a string. Objects that know how to format themselves implement the [Format] trait.
|
||||
//!
|
||||
//! ## Formatting Traits
|
||||
//!
|
||||
//! * [Format]: Implemented by objects that can be formatted.
|
||||
//! * [FormatRule]: Rule that knows how to format an object of another type. Necessary in the situation where
|
||||
//! * [`FormatRule`]: Rule that knows how to format an object of another type. Necessary in the situation where
|
||||
//! it's necessary to implement [Format] on an object from another crate. This module defines the
|
||||
//! [FormatRefWithRule] and [FormatOwnedWithRule] structs to pass an item with its corresponding rule.
|
||||
//! * [FormatWithRule] implemented by objects that know how to format another type. Useful for implementing
|
||||
//! [`FormatRefWithRule`] and [`FormatOwnedWithRule`] structs to pass an item with its corresponding rule.
|
||||
//! * [`FormatWithRule`] implemented by objects that know how to format another type. Useful for implementing
|
||||
//! some reusable formatting logic inside of this module if the type itself doesn't implement [Format]
|
||||
//!
|
||||
//! ## Formatting Macros
|
||||
|
@ -19,9 +19,6 @@
|
|||
//! * [`format_args!`]: Concatenates a sequence of Format objects.
|
||||
//! * [`write!`]: Writes a sequence of formatable objects into an output buffer.
|
||||
|
||||
#![allow(clippy::pedantic, unsafe_code)]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
|
||||
mod arguments;
|
||||
mod buffer;
|
||||
mod builders;
|
||||
|
@ -73,12 +70,12 @@ pub enum IndentStyle {
|
|||
impl IndentStyle {
|
||||
pub const DEFAULT_SPACES: u8 = 2;
|
||||
|
||||
/// Returns `true` if this is an [IndentStyle::Tab].
|
||||
/// Returns `true` if this is an [`IndentStyle::Tab`].
|
||||
pub const fn is_tab(&self) -> bool {
|
||||
matches!(self, IndentStyle::Tab)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is an [IndentStyle::Space].
|
||||
/// Returns `true` if this is an [`IndentStyle::Space`].
|
||||
pub const fn is_space(&self) -> bool {
|
||||
matches!(self, IndentStyle::Space(_))
|
||||
}
|
||||
|
@ -121,10 +118,10 @@ impl std::fmt::Display for IndentStyle {
|
|||
pub struct LineWidth(u16);
|
||||
|
||||
impl LineWidth {
|
||||
/// Maximum allowed value for a valid [LineWidth]
|
||||
/// Maximum allowed value for a valid [`LineWidth`]
|
||||
pub const MAX: u16 = 320;
|
||||
|
||||
/// Return the numeric value for this [LineWidth]
|
||||
/// Return the numeric value for this [`LineWidth`]
|
||||
pub fn value(&self) -> u16 {
|
||||
self.0
|
||||
}
|
||||
|
@ -136,7 +133,7 @@ impl Default for LineWidth {
|
|||
}
|
||||
}
|
||||
|
||||
/// Error type returned when parsing a [LineWidth] from a string fails
|
||||
/// Error type returned when parsing a [`LineWidth`] from a string fails
|
||||
pub enum ParseLineWidthError {
|
||||
/// The string could not be parsed as a valid [u16]
|
||||
ParseError(ParseIntError),
|
||||
|
@ -169,7 +166,7 @@ impl FromStr for LineWidth {
|
|||
}
|
||||
}
|
||||
|
||||
/// Error type returned when converting a u16 to a [LineWidth] fails
|
||||
/// Error type returned when converting a u16 to a [`LineWidth`] fails
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct LineWidthFromIntError(pub u16);
|
||||
|
||||
|
@ -238,6 +235,7 @@ impl SimpleFormatContext {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_source_code(mut self, code: &str) -> Self {
|
||||
self.source_code = String::from(code);
|
||||
self
|
||||
|
@ -390,20 +388,20 @@ impl Printed {
|
|||
self.range
|
||||
}
|
||||
|
||||
/// Returns a list of [SourceMarker] mapping byte positions
|
||||
/// Returns a list of [`SourceMarker`] mapping byte positions
|
||||
/// in the output string to the input source code.
|
||||
/// It's not guaranteed that the markers are sorted by source position.
|
||||
pub fn sourcemap(&self) -> &[SourceMarker] {
|
||||
&self.sourcemap
|
||||
}
|
||||
|
||||
/// Returns a list of [SourceMarker] mapping byte positions
|
||||
/// Returns a list of [`SourceMarker`] mapping byte positions
|
||||
/// in the output string to the input source code, consuming the result
|
||||
pub fn into_sourcemap(self) -> Vec<SourceMarker> {
|
||||
self.sourcemap
|
||||
}
|
||||
|
||||
/// Takes the list of [SourceMarker] mapping byte positions in the output string
|
||||
/// Takes the list of [`SourceMarker`] mapping byte positions in the output string
|
||||
/// to the input source code.
|
||||
pub fn take_sourcemap(&mut self) -> Vec<SourceMarker> {
|
||||
std::mem::take(&mut self.sourcemap)
|
||||
|
@ -441,7 +439,7 @@ impl Printed {
|
|||
pub type FormatResult<F> = Result<F, FormatError>;
|
||||
|
||||
/// Formatting trait for types that can create a formatted representation. The `ruff_formatter` equivalent
|
||||
/// to [std::fmt::Display].
|
||||
/// to [`std::fmt::Display`].
|
||||
///
|
||||
/// ## Example
|
||||
/// Implementing `Format` for a custom struct
|
||||
|
@ -480,7 +478,7 @@ impl<T, Context> Format<Context> for &T
|
|||
where
|
||||
T: ?Sized + Format<Context>,
|
||||
{
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||
Format::fmt(&**self, f)
|
||||
}
|
||||
|
@ -490,7 +488,7 @@ impl<T, Context> Format<Context> for &mut T
|
|||
where
|
||||
T: ?Sized + Format<Context>,
|
||||
{
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||
Format::fmt(&**self, f)
|
||||
}
|
||||
|
@ -518,7 +516,7 @@ impl<Context> Format<Context> for () {
|
|||
|
||||
/// Rule that knows how to format an object of type `T`.
|
||||
///
|
||||
/// Implementing [Format] on the object itself is preferred over implementing [FormatRule] but
|
||||
/// Implementing [Format] on the object itself is preferred over implementing [`FormatRule`] but
|
||||
/// this isn't possible inside of a dependent crate for external type.
|
||||
///
|
||||
/// For example, the `ruff_js_formatter` crate isn't able to implement [Format] on `JsIfStatement`
|
||||
|
@ -535,6 +533,7 @@ pub trait FormatRuleWithOptions<T, C>: FormatRule<T, C> {
|
|||
type Options;
|
||||
|
||||
/// Returns a new rule that uses the given options to format an object.
|
||||
#[must_use]
|
||||
fn with_options(self, options: Self::Options) -> Self;
|
||||
}
|
||||
|
||||
|
@ -547,9 +546,9 @@ pub trait FormatRuleWithOptions<T, C>: FormatRule<T, C> {
|
|||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// This can be useful if you want to format a `SyntaxNode` inside ruff_formatter.. `SyntaxNode` doesn't implement [Format]
|
||||
/// This can be useful if you want to format a `SyntaxNode` inside `ruff_formatter`.. `SyntaxNode` doesn't implement [Format]
|
||||
/// itself but the language specific crate implements `AsFormat` and `IntoFormat` for it and the returned [Format]
|
||||
/// implement [FormatWithRule].
|
||||
/// implement [`FormatWithRule`].
|
||||
///
|
||||
/// ```ignore
|
||||
/// use ruff_formatter::prelude::*;
|
||||
|
@ -597,6 +596,7 @@ impl<T, R, O, C> FormatRefWithRule<'_, T, R, C>
|
|||
where
|
||||
R: FormatRuleWithOptions<T, C, Options = O>,
|
||||
{
|
||||
#[must_use]
|
||||
pub fn with_options(mut self, options: O) -> Self {
|
||||
self.rule = self.rule.with_options(options);
|
||||
self
|
||||
|
@ -618,7 +618,7 @@ impl<T, R, C> Format<C> for FormatRefWithRule<'_, T, R, C>
|
|||
where
|
||||
R: FormatRule<T, C>,
|
||||
{
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<C>) -> FormatResult<()> {
|
||||
self.rule.fmt(self.item, f)
|
||||
}
|
||||
|
@ -647,6 +647,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_item(mut self, item: T) -> Self {
|
||||
self.item = item;
|
||||
self
|
||||
|
@ -661,7 +662,7 @@ impl<T, R, C> Format<C> for FormatOwnedWithRule<T, R, C>
|
|||
where
|
||||
R: FormatRule<T, C>,
|
||||
{
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<C>) -> FormatResult<()> {
|
||||
self.rule.fmt(&self.item, f)
|
||||
}
|
||||
|
@ -671,6 +672,7 @@ impl<T, R, O, C> FormatOwnedWithRule<T, R, C>
|
|||
where
|
||||
R: FormatRuleWithOptions<T, C, Options = O>,
|
||||
{
|
||||
#[must_use]
|
||||
pub fn with_options(mut self, options: O) -> Self {
|
||||
self.rule = self.rule.with_options(options);
|
||||
self
|
||||
|
@ -729,7 +731,7 @@ where
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn write<Context>(
|
||||
output: &mut dyn Buffer<Context = Context>,
|
||||
args: Arguments<Context>,
|
||||
|
@ -790,9 +792,9 @@ where
|
|||
|
||||
/// This structure stores the state that is relevant for the formatting of the whole document.
|
||||
///
|
||||
/// This structure is different from [crate::Formatter] in that the formatting infrastructure
|
||||
/// creates a new [crate::Formatter] for every [crate::write!] call, whereas this structure stays alive
|
||||
/// for the whole process of formatting a root with [crate::format!].
|
||||
/// This structure is different from [`crate::Formatter`] in that the formatting infrastructure
|
||||
/// creates a new [`crate::Formatter`] for every [`crate::write`!] call, whereas this structure stays alive
|
||||
/// for the whole process of formatting a root with [`crate::format`!].
|
||||
pub struct FormatState<Context> {
|
||||
context: Context,
|
||||
|
||||
|
@ -815,7 +817,7 @@ impl<Context> FormatState<Context> {
|
|||
pub fn new(context: Context) -> Self {
|
||||
Self {
|
||||
context,
|
||||
group_id_builder: Default::default(),
|
||||
group_id_builder: UniqueGroupIdBuilder::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -834,7 +836,7 @@ impl<Context> FormatState<Context> {
|
|||
}
|
||||
|
||||
/// Creates a new group id that is unique to this document. The passed debug name is used in the
|
||||
/// [std::fmt::Debug] of the document if this is a debug build.
|
||||
/// [`std::fmt::Debug`] of the document if this is a debug build.
|
||||
/// The name is unused for production builds and has no meaning on the equality of two group ids.
|
||||
pub fn group_id(&self, debug_name: &'static str) -> GroupId {
|
||||
self.group_id_builder.group_id(debug_name)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/// Constructs the parameters for other formatting macros.
|
||||
///
|
||||
/// This macro functions by taking a list of objects implementing [crate::Format]. It canonicalize the
|
||||
/// This macro functions by taking a list of objects implementing [`crate::Format`]. It canonicalize the
|
||||
/// arguments into a single type.
|
||||
///
|
||||
/// This macro produces a value of type [crate::Arguments]. This value can be passed to
|
||||
/// This macro produces a value of type [`crate::Arguments`]. This value can be passed to
|
||||
/// the macros within [crate]. All other formatting macros ([`format!`](crate::format!),
|
||||
/// [`write!`](crate::write!)) are proxied through this one. This macro avoids heap allocations.
|
||||
///
|
||||
|
@ -41,7 +41,7 @@ macro_rules! format_args {
|
|||
///
|
||||
/// This macro accepts a 'buffer' and a list of format arguments. Each argument will be formatted
|
||||
/// and the result will be passed to the buffer. The writer may be any value with a `write_fmt` method;
|
||||
/// generally this comes from an implementation of the [crate::Buffer] trait.
|
||||
/// generally this comes from an implementation of the [`crate::Buffer`] trait.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -116,8 +116,8 @@ macro_rules! dbg_write {
|
|||
|
||||
/// Creates the Format IR for a value.
|
||||
///
|
||||
/// The first argument `format!` receives is the [crate::FormatContext] that specify how elements must be formatted.
|
||||
/// Additional parameters passed get formatted by using their [crate::Format] implementation.
|
||||
/// The first argument `format!` receives is the [`crate::FormatContext`] that specify how elements must be formatted.
|
||||
/// Additional parameters passed get formatted by using their [`crate::Format`] implementation.
|
||||
///
|
||||
///
|
||||
/// ## Examples
|
||||
|
@ -314,13 +314,13 @@ macro_rules! format {
|
|||
/// ## Behavior
|
||||
/// This IR is similar to Prettier's `conditionalGroup`. The printer measures each variant, except the [`MostExpanded`], in [`Flat`] mode
|
||||
/// to find the first variant that fits and prints this variant in [`Flat`] mode. If no variant fits, then
|
||||
/// the printer falls back to printing the [`MostExpanded`] variant in `[`Expanded`] mode.
|
||||
/// the printer falls back to printing the [`MostExpanded`] variant in [`Expanded`] mode.
|
||||
///
|
||||
/// The definition of *fits* differs to groups in that the printer only tests if it is possible to print
|
||||
/// the content up to the first non-soft line break without exceeding the configured print width.
|
||||
/// This definition differs from groups as that non-soft line breaks make group expand.
|
||||
///
|
||||
/// [crate::BestFitting] acts as a "break" boundary, meaning that it is considered to fit
|
||||
/// [`crate::BestFitting`] acts as a "break" boundary, meaning that it is considered to fit
|
||||
///
|
||||
///
|
||||
/// [`Flat`]: crate::format_element::PrintMode::Flat
|
||||
|
@ -329,6 +329,7 @@ macro_rules! format {
|
|||
#[macro_export]
|
||||
macro_rules! best_fitting {
|
||||
($least_expanded:expr, $($tail:expr),+ $(,)?) => {{
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
$crate::BestFitting::from_arguments_unchecked($crate::format_args!($least_expanded, $($tail),+))
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@ pub(super) struct StackFrame {
|
|||
|
||||
/// Stores arguments passed to `print_element` call, holding the state specific to printing an element.
|
||||
/// E.g. the `indent` depends on the token the Printer's currently processing. That's why
|
||||
/// it must be stored outside of the [PrinterState] that stores the state common to all elements.
|
||||
/// it must be stored outside of the [`PrinterState`] that stores the state common to all elements.
|
||||
///
|
||||
/// The state is passed by value, which is why it's important that it isn't storing any heavy
|
||||
/// data structures. Such structures should be stored on the [PrinterState] instead.
|
||||
/// data structures. Such structures should be stored on the [`PrinterState`] instead.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub(super) struct PrintElementArgs {
|
||||
indent: Indention,
|
||||
|
@ -39,15 +39,15 @@ impl PrintElementArgs {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn mode(&self) -> PrintMode {
|
||||
pub(super) fn mode(self) -> PrintMode {
|
||||
self.mode
|
||||
}
|
||||
|
||||
pub(super) fn measure_mode(&self) -> MeasureMode {
|
||||
pub(super) fn measure_mode(self) -> MeasureMode {
|
||||
self.measure_mode
|
||||
}
|
||||
|
||||
pub(super) fn indention(&self) -> Indention {
|
||||
pub(super) fn indention(self) -> Indention {
|
||||
self.indent
|
||||
}
|
||||
|
||||
|
@ -92,9 +92,9 @@ impl Default for PrintElementArgs {
|
|||
}
|
||||
}
|
||||
|
||||
/// Call stack that stores the [PrintElementCallArgs].
|
||||
/// Call stack that stores the [`PrintElementCallArgs`].
|
||||
///
|
||||
/// New [PrintElementCallArgs] are pushed onto the stack for every [`start`](Tag::is_start) [`Tag`](FormatElement::Tag)
|
||||
/// New [`PrintElementCallArgs`] are pushed onto the stack for every [`start`](Tag::is_start) [`Tag`](FormatElement::Tag)
|
||||
/// and popped when reaching the corresponding [`end`](Tag::is_end) [`Tag`](FormatElement::Tag).
|
||||
pub(super) trait CallStack {
|
||||
type Stack: Stack<StackFrame> + Debug;
|
||||
|
@ -158,7 +158,7 @@ pub(super) trait CallStack {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the [PrintElementArgs] for the current stack frame.
|
||||
/// Returns the [`PrintElementArgs`] for the current stack frame.
|
||||
fn top(&self) -> PrintElementArgs {
|
||||
self.stack()
|
||||
.top()
|
||||
|
@ -166,7 +166,7 @@ pub(super) trait CallStack {
|
|||
.args
|
||||
}
|
||||
|
||||
/// Returns the [TagKind] of the current stack frame or [None] if this is the root stack frame.
|
||||
/// Returns the [`TagKind`] of the current stack frame or [None] if this is the root stack frame.
|
||||
fn top_kind(&self) -> Option<TagKind> {
|
||||
match self
|
||||
.stack()
|
||||
|
@ -179,16 +179,16 @@ pub(super) trait CallStack {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a new stack frame for a [FormatElement::Tag] of `kind` with `args` as the call arguments.
|
||||
/// Creates a new stack frame for a [`FormatElement::Tag`] of `kind` with `args` as the call arguments.
|
||||
fn push(&mut self, kind: TagKind, args: PrintElementArgs) {
|
||||
self.stack_mut().push(StackFrame {
|
||||
kind: StackFrameKind::Tag(kind),
|
||||
args,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Call stack used for printing the [FormatElement]s
|
||||
/// Call stack used for printing the [`FormatElement`]s
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct PrintCallStack(Vec<StackFrame>);
|
||||
|
||||
|
@ -215,7 +215,7 @@ impl CallStack for PrintCallStack {
|
|||
|
||||
/// Call stack used for measuring if some content fits on the line.
|
||||
///
|
||||
/// The stack is a view on top of the [PrintCallStack] because the stack frames are still necessary for printing.
|
||||
/// The stack is a view on top of the [`PrintCallStack`] because the stack frames are still necessary for printing.
|
||||
#[must_use]
|
||||
pub(super) struct FitsCallStack<'print> {
|
||||
stack: StackedStack<'print, StackFrame>,
|
||||
|
|
|
@ -84,6 +84,7 @@ impl<'a> Printer<'a> {
|
|||
queue: &mut PrintQueue<'a>,
|
||||
element: &'a FormatElement,
|
||||
) -> PrintResult<()> {
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
use Tag::*;
|
||||
|
||||
let args = stack.top();
|
||||
|
@ -94,7 +95,7 @@ impl<'a> Printer<'a> {
|
|||
FormatElement::DynamicText { text } => self.print_text(text, None),
|
||||
FormatElement::SourceCodeSlice { slice, .. } => {
|
||||
let text = slice.text(self.source_code);
|
||||
self.print_text(text, Some(slice.range()))
|
||||
self.print_text(text, Some(slice.range()));
|
||||
}
|
||||
FormatElement::Line(line_mode) => {
|
||||
if args.mode().is_flat()
|
||||
|
@ -221,6 +222,8 @@ impl<'a> Printer<'a> {
|
|||
|
||||
FormatElement::Tag(StartVerbatim(kind)) => {
|
||||
if let VerbatimKind::Verbatim { length } = kind {
|
||||
// SAFETY: Ruff only supports formatting files <= 4GB
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
self.state.verbatim_markers.push(TextRange::at(
|
||||
TextSize::from(self.state.buffer.len() as u32),
|
||||
*length,
|
||||
|
@ -291,7 +294,7 @@ impl<'a> Printer<'a> {
|
|||
kind: TagKind,
|
||||
mode: GroupMode,
|
||||
args: PrintElementArgs,
|
||||
queue: &mut PrintQueue<'a>,
|
||||
queue: &PrintQueue<'a>,
|
||||
stack: &mut PrintCallStack,
|
||||
) -> PrintResult<PrintMode> {
|
||||
let group_mode = match mode {
|
||||
|
@ -384,7 +387,7 @@ impl<'a> Printer<'a> {
|
|||
|
||||
if let Some(last) = self.state.source_markers.last() {
|
||||
if last != &marker {
|
||||
self.state.source_markers.push(marker)
|
||||
self.state.source_markers.push(marker);
|
||||
}
|
||||
} else {
|
||||
self.state.source_markers.push(marker);
|
||||
|
@ -411,10 +414,11 @@ impl<'a> Printer<'a> {
|
|||
queue.push(suffix);
|
||||
}
|
||||
LineSuffixEntry::Args(args) => {
|
||||
stack.push(TagKind::LineSuffix, args);
|
||||
const LINE_SUFFIX_END: &FormatElement =
|
||||
&FormatElement::Tag(Tag::EndLineSuffix);
|
||||
|
||||
stack.push(TagKind::LineSuffix, args);
|
||||
|
||||
queue.push(LINE_SUFFIX_END);
|
||||
}
|
||||
}
|
||||
|
@ -437,7 +441,7 @@ impl<'a> Printer<'a> {
|
|||
self.state.measured_group_fits = true;
|
||||
let normal_variants = &variants[..variants.len() - 1];
|
||||
|
||||
for variant in normal_variants.iter() {
|
||||
for variant in normal_variants {
|
||||
// Test if this variant fits and if so, use it. Otherwise try the next
|
||||
// variant.
|
||||
|
||||
|
@ -614,7 +618,7 @@ impl<'a> Printer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Semantic alias for [Self::print_entry] for fill items.
|
||||
/// Semantic alias for [`Self::print_entry`] for fill items.
|
||||
fn print_fill_item(
|
||||
&mut self,
|
||||
queue: &mut PrintQueue<'a>,
|
||||
|
@ -624,7 +628,7 @@ impl<'a> Printer<'a> {
|
|||
self.print_entry(queue, stack, args)
|
||||
}
|
||||
|
||||
/// Semantic alias for [Self::print_entry] for fill separators.
|
||||
/// Semantic alias for [`Self::print_entry`] for fill separators.
|
||||
fn print_fill_separator(
|
||||
&mut self,
|
||||
queue: &mut PrintQueue<'a>,
|
||||
|
@ -636,7 +640,7 @@ impl<'a> Printer<'a> {
|
|||
|
||||
/// Fully print an element (print the element itself and all its descendants)
|
||||
///
|
||||
/// Unlike [print_element], this function ensures the entire element has
|
||||
/// Unlike [`print_element`], this function ensures the entire element has
|
||||
/// been printed when it returns and the queue is back to its original state
|
||||
fn print_entry(
|
||||
&mut self,
|
||||
|
@ -703,9 +707,11 @@ impl<'a> Printer<'a> {
|
|||
} else {
|
||||
self.state.buffer.push(char);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let char_width = if char == '\t' {
|
||||
self.options.tab_width as u32
|
||||
u32::from(self.options.tab_width)
|
||||
} else {
|
||||
// SAFETY: A u32 is sufficient to represent the width of a file <= 4GB
|
||||
char.width().unwrap_or(0) as u32
|
||||
};
|
||||
|
||||
|
@ -791,7 +797,7 @@ enum Indention {
|
|||
}
|
||||
|
||||
impl Indention {
|
||||
const fn is_empty(&self) -> bool {
|
||||
const fn is_empty(self) -> bool {
|
||||
matches!(self, Indention::Level(0))
|
||||
}
|
||||
|
||||
|
@ -801,27 +807,27 @@ impl Indention {
|
|||
}
|
||||
|
||||
/// Returns the indention level
|
||||
fn level(&self) -> u16 {
|
||||
fn level(self) -> u16 {
|
||||
match self {
|
||||
Indention::Level(count) => *count,
|
||||
Indention::Align { level: indent, .. } => *indent,
|
||||
Indention::Level(count) => count,
|
||||
Indention::Align { level: indent, .. } => indent,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of trailing align spaces or 0 if none
|
||||
fn align(&self) -> u8 {
|
||||
fn align(self) -> u8 {
|
||||
match self {
|
||||
Indention::Level(_) => 0,
|
||||
Indention::Align { align, .. } => (*align).into(),
|
||||
Indention::Align { align, .. } => align.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Increments the level by one.
|
||||
///
|
||||
/// The behaviour depends on the [`indent_style`][IndentStyle] if this is an [Indent::Align]:
|
||||
/// The behaviour depends on the [`indent_style`][IndentStyle] if this is an [`Indent::Align`]:
|
||||
/// - **Tabs**: `align` is converted into an indent. This results in `level` increasing by two: once for the align, once for the level increment
|
||||
/// - **Spaces**: Increments the `level` by one and keeps the `align` unchanged.
|
||||
/// Keeps any the current value is [Indent::Align] and increments the level by one.
|
||||
/// Keeps any the current value is [`Indent::Align`] and increments the level by one.
|
||||
fn increment_level(self, indent_style: IndentStyle) -> Self {
|
||||
match self {
|
||||
Indention::Level(count) => Indention::Level(count + 1),
|
||||
|
@ -838,8 +844,8 @@ impl Indention {
|
|||
}
|
||||
|
||||
/// Decrements the indent by one by:
|
||||
/// - Reducing the level by one if this is [Indent::Level]
|
||||
/// - Removing the `align` if this is [Indent::Align]
|
||||
/// - Reducing the level by one if this is [`Indent::Level`]
|
||||
/// - Removing the `align` if this is [`Indent::Align`]
|
||||
///
|
||||
/// No-op if the level is already zero.
|
||||
fn decrement(self) -> Self {
|
||||
|
@ -851,7 +857,7 @@ impl Indention {
|
|||
|
||||
/// Adds an `align` of `count` spaces to the current indention.
|
||||
///
|
||||
/// It increments the `level` value if the current value is [Indent::IndentAlign].
|
||||
/// It increments the `level` value if the current value is [`Indent::IndentAlign`].
|
||||
fn set_align(self, count: NonZeroU8) -> Self {
|
||||
match self {
|
||||
Indention::Level(indent_count) => Indention::Align {
|
||||
|
@ -955,9 +961,9 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
Ok(true)
|
||||
}
|
||||
|
||||
/// Tests if the content of a `Fill` item fits in [PrintMode::Flat].
|
||||
/// Tests if the content of a `Fill` item fits in [`PrintMode::Flat`].
|
||||
///
|
||||
/// Returns `Err` if the top element of the queue is not a [Tag::StartEntry]
|
||||
/// Returns `Err` if the top element of the queue is not a [`Tag::StartEntry`]
|
||||
/// or if the document has any mismatching start/end tags.
|
||||
fn fill_item_fits(&mut self) -> PrintResult<bool> {
|
||||
self.fill_entry_fits(PrintMode::Flat)
|
||||
|
@ -965,17 +971,17 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
|
||||
/// Tests if the content of a `Fill` separator fits with `mode`.
|
||||
///
|
||||
/// Returns `Err` if the top element of the queue is not a [Tag::StartEntry]
|
||||
/// Returns `Err` if the top element of the queue is not a [`Tag::StartEntry`]
|
||||
/// or if the document has any mismatching start/end tags.
|
||||
fn fill_separator_fits(&mut self, mode: PrintMode) -> PrintResult<bool> {
|
||||
self.fill_entry_fits(mode)
|
||||
}
|
||||
|
||||
/// Tests if the elements between the [Tag::StartEntry] and [Tag::EndEntry]
|
||||
/// Tests if the elements between the [`Tag::StartEntry`] and [`Tag::EndEntry`]
|
||||
/// of a fill item or separator fits with `mode`.
|
||||
///
|
||||
/// Returns `Err` if the queue isn't positioned at a [Tag::StartEntry] or if
|
||||
/// the matching [Tag::EndEntry] is missing.
|
||||
/// Returns `Err` if the queue isn't positioned at a [`Tag::StartEntry`] or if
|
||||
/// the matching [`Tag::EndEntry`] is missing.
|
||||
fn fill_entry_fits(&mut self, mode: PrintMode) -> PrintResult<bool> {
|
||||
let start_entry = self.queue.top();
|
||||
|
||||
|
@ -997,6 +1003,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
|
||||
/// Tests if the passed element fits on the current line or not.
|
||||
fn fits_element(&mut self, element: &'a FormatElement) -> PrintResult<Fits> {
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
use Tag::*;
|
||||
|
||||
let args = self.stack.top();
|
||||
|
@ -1093,7 +1100,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
}
|
||||
|
||||
FormatElement::Tag(StartGroup(group)) => {
|
||||
return self.fits_group(TagKind::Group, group.mode(), group.id(), args);
|
||||
return Ok(self.fits_group(TagKind::Group, group.mode(), group.id(), args));
|
||||
}
|
||||
|
||||
FormatElement::Tag(StartConditionalGroup(group)) => {
|
||||
|
@ -1108,10 +1115,14 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
};
|
||||
|
||||
if condition.mode == print_mode {
|
||||
return self.fits_group(TagKind::ConditionalGroup, group.mode(), None, args);
|
||||
} else {
|
||||
self.stack.push(TagKind::ConditionalGroup, args);
|
||||
return Ok(self.fits_group(
|
||||
TagKind::ConditionalGroup,
|
||||
group.mode(),
|
||||
None,
|
||||
args,
|
||||
));
|
||||
}
|
||||
self.stack.push(TagKind::ConditionalGroup, args);
|
||||
}
|
||||
|
||||
FormatElement::Tag(StartConditionalContent(condition)) => {
|
||||
|
@ -1183,14 +1194,14 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
TagKind::FitsExpanded,
|
||||
args.with_print_mode(PrintMode::Expanded)
|
||||
.with_measure_mode(MeasureMode::AllLines),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
if propagate_expand.get() && args.mode().is_flat() {
|
||||
return Ok(Fits::No);
|
||||
}
|
||||
|
||||
// As usual
|
||||
self.stack.push(TagKind::FitsExpanded, args)
|
||||
self.stack.push(TagKind::FitsExpanded, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1227,17 +1238,17 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
mode: GroupMode,
|
||||
id: Option<GroupId>,
|
||||
args: PrintElementArgs,
|
||||
) -> PrintResult<Fits> {
|
||||
) -> Fits {
|
||||
if self.must_be_flat && !mode.is_flat() {
|
||||
return Ok(Fits::No);
|
||||
return Fits::No;
|
||||
}
|
||||
|
||||
// Continue printing groups in expanded mode if measuring a `best_fitting` element where
|
||||
// a group expands.
|
||||
let print_mode = if !mode.is_flat() {
|
||||
PrintMode::Expanded
|
||||
} else {
|
||||
let print_mode = if mode.is_flat() {
|
||||
args.mode()
|
||||
} else {
|
||||
PrintMode::Expanded
|
||||
};
|
||||
|
||||
self.stack.push(kind, args.with_print_mode(print_mode));
|
||||
|
@ -1246,21 +1257,22 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
self.group_modes_mut().insert_print_mode(id, print_mode);
|
||||
}
|
||||
|
||||
Ok(Fits::Maybe)
|
||||
Fits::Maybe
|
||||
}
|
||||
|
||||
fn fits_text(&mut self, text: &str, args: PrintElementArgs) -> Fits {
|
||||
let indent = std::mem::take(&mut self.state.pending_indent);
|
||||
self.state.line_width +=
|
||||
indent.level() as u32 * self.options().indent_width() as u32 + indent.align() as u32;
|
||||
self.state.line_width += u32::from(indent.level())
|
||||
* u32::from(self.options().indent_width())
|
||||
+ u32::from(indent.align());
|
||||
|
||||
for c in text.chars() {
|
||||
let char_width = match c {
|
||||
'\t' => self.options().tab_width as u32,
|
||||
'\t' => u32::from(self.options().tab_width),
|
||||
'\n' => {
|
||||
if self.must_be_flat {
|
||||
return Fits::No;
|
||||
} else {
|
||||
}
|
||||
match args.measure_mode() {
|
||||
MeasureMode::FirstLine => return Fits::Yes,
|
||||
MeasureMode::AllLines => {
|
||||
|
@ -1268,8 +1280,9 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
// SAFETY: A u32 is sufficient to format files <= 4GB
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
c => c.width().unwrap_or(0) as u32,
|
||||
};
|
||||
self.state.line_width += char_width;
|
||||
|
@ -1352,9 +1365,10 @@ enum Fits {
|
|||
|
||||
impl From<bool> for Fits {
|
||||
fn from(value: bool) -> Self {
|
||||
match value {
|
||||
true => Fits::Yes,
|
||||
false => Fits::No,
|
||||
if value {
|
||||
Fits::Yes
|
||||
} else {
|
||||
Fits::No
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1418,7 +1432,7 @@ mod tests {
|
|||
],
|
||||
});
|
||||
|
||||
assert_eq!(r#"["a", "b", "c", "d"]"#, result.as_code())
|
||||
assert_eq!(r#"["a", "b", "c", "d"]"#, result.as_code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1447,7 +1461,7 @@ mod tests {
|
|||
b
|
||||
a"#,
|
||||
formatted.as_code()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1489,13 +1503,13 @@ two lines`,
|
|||
"b",
|
||||
]"#,
|
||||
result.as_code()
|
||||
)
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn it_breaks_a_group_if_it_contains_a_hard_line_break() {
|
||||
let result = format(&group(&format_args![text("a"), block_indent(&text("b"))]));
|
||||
|
||||
assert_eq!("a\n b\n", result.as_code())
|
||||
assert_eq!("a\n b\n", result.as_code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1559,7 +1573,7 @@ two lines`,
|
|||
text("b"),
|
||||
]);
|
||||
|
||||
assert_eq!("a\nb", result.as_code())
|
||||
assert_eq!("a\nb", result.as_code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1572,7 +1586,7 @@ two lines`,
|
|||
text("b"),
|
||||
]);
|
||||
|
||||
assert_eq!("a\n\n\n\nb", result.as_code())
|
||||
assert_eq!("a\n\n\n\nb", result.as_code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1586,7 +1600,7 @@ two lines`,
|
|||
text("b"),
|
||||
]);
|
||||
|
||||
assert_eq!("a\n\n\nb", result.as_code())
|
||||
assert_eq!("a\n\n\nb", result.as_code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1648,7 +1662,7 @@ two lines`,
|
|||
assert_eq!(
|
||||
printed.as_code(),
|
||||
"1, 2, 3,\n723493294,\n[5],\n[\n\t123456789\n]"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1678,7 +1692,7 @@ two lines`,
|
|||
&line_suffix(&format_args![space(), text("// trailing")])
|
||||
]);
|
||||
|
||||
assert_eq!(printed.as_code(), "[1, 2, 3]; // trailing")
|
||||
assert_eq!(printed.as_code(), "[1, 2, 3]; // trailing");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{FormatOptions, IndentStyle, LineWidth};
|
||||
|
||||
/// Options that affect how the [crate::Printer] prints the format tokens
|
||||
/// Options that affect how the [`crate::Printer`] prints the format tokens
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct PrinterOptions {
|
||||
/// Width of a single tab character (does it equal 2, 4, ... spaces?)
|
||||
|
@ -33,7 +33,7 @@ impl Default for PrintWidth {
|
|||
|
||||
impl From<LineWidth> for PrintWidth {
|
||||
fn from(width: LineWidth) -> Self {
|
||||
Self(u16::from(width) as u32)
|
||||
Self(u32::from(u16::from(width)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,11 +61,13 @@ where
|
|||
}
|
||||
|
||||
impl PrinterOptions {
|
||||
#[must_use]
|
||||
pub fn with_print_width(mut self, width: PrintWidth) -> Self {
|
||||
self.print_width = width;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_indent(mut self, style: IndentStyle) -> Self {
|
||||
self.indent_style = style;
|
||||
|
||||
|
@ -114,7 +116,7 @@ impl Default for PrinterOptions {
|
|||
PrinterOptions {
|
||||
tab_width: 2,
|
||||
print_width: PrintWidth::default(),
|
||||
indent_style: Default::default(),
|
||||
indent_style: IndentStyle::default(),
|
||||
line_ending: LineEnding::LineFeed,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::fmt::Debug;
|
|||
use std::iter::FusedIterator;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Queue of [FormatElement]s.
|
||||
/// Queue of [`FormatElement`]s.
|
||||
pub(super) trait Queue<'a> {
|
||||
type Stack: Stack<&'a [FormatElement]>;
|
||||
|
||||
|
@ -40,19 +40,19 @@ pub(super) trait Queue<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the next element, not traversing into [FormatElement::Interned].
|
||||
/// Returns the next element, not traversing into [`FormatElement::Interned`].
|
||||
fn top_with_interned(&self) -> Option<&'a FormatElement> {
|
||||
self.stack()
|
||||
.top()
|
||||
.map(|top_slice| &top_slice[self.next_index()])
|
||||
}
|
||||
|
||||
/// Returns the next element, recursively resolving the first element of [FormatElement::Interned].
|
||||
/// Returns the next element, recursively resolving the first element of [`FormatElement::Interned`].
|
||||
fn top(&self) -> Option<&'a FormatElement> {
|
||||
let mut top = self.top_with_interned();
|
||||
|
||||
while let Some(FormatElement::Interned(interned)) = top {
|
||||
top = interned.first()
|
||||
top = interned.first();
|
||||
}
|
||||
|
||||
top
|
||||
|
@ -60,7 +60,7 @@ pub(super) trait Queue<'a> {
|
|||
|
||||
/// Queues a single element to process before the other elements in this queue.
|
||||
fn push(&mut self, element: &'a FormatElement) {
|
||||
self.extend_back(std::slice::from_ref(element))
|
||||
self.extend_back(std::slice::from_ref(element));
|
||||
}
|
||||
|
||||
/// Queues a slice of elements to process before the other elements in this queue.
|
||||
|
@ -73,7 +73,7 @@ pub(super) trait Queue<'a> {
|
|||
let next_index = self.next_index();
|
||||
let stack = self.stack_mut();
|
||||
if let Some(top) = stack.pop() {
|
||||
stack.push(&top[next_index..])
|
||||
stack.push(&top[next_index..]);
|
||||
}
|
||||
|
||||
stack.push(slice);
|
||||
|
@ -150,14 +150,14 @@ impl<'a> Queue<'a> for PrintQueue<'a> {
|
|||
}
|
||||
|
||||
fn set_next_index(&mut self, index: usize) {
|
||||
self.next_index = index
|
||||
self.next_index = index;
|
||||
}
|
||||
}
|
||||
|
||||
/// Queue for measuring if an element fits on the line.
|
||||
///
|
||||
/// The queue is a view on top of the [PrintQueue] because no elements should be removed
|
||||
/// from the [PrintQueue] while measuring.
|
||||
/// The queue is a view on top of the [`PrintQueue`] because no elements should be removed
|
||||
/// from the [`PrintQueue`] while measuring.
|
||||
#[must_use]
|
||||
#[derive(Debug)]
|
||||
pub(super) struct FitsQueue<'a, 'print> {
|
||||
|
@ -203,9 +203,9 @@ impl<'a, 'print> Queue<'a> for FitsQueue<'a, 'print> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Iterator that calls [Queue::pop] until it reaches the end of the document.
|
||||
/// Iterator that calls [`Queue::pop`] until it reaches the end of the document.
|
||||
///
|
||||
/// The iterator traverses into the content of any [FormatElement::Interned].
|
||||
/// The iterator traverses into the content of any [`FormatElement::Interned`].
|
||||
pub(super) struct QueueIterator<'a, 'q, Q: Queue<'a>> {
|
||||
queue: &'q mut Q,
|
||||
lifetime: PhantomData<&'a ()>,
|
||||
|
@ -252,9 +252,9 @@ where
|
|||
type Item = &'a FormatElement;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.depth {
|
||||
0 => None,
|
||||
_ => {
|
||||
if self.depth == 0 {
|
||||
None
|
||||
} else {
|
||||
let mut top = self.queue.pop();
|
||||
|
||||
while let Some(FormatElement::Interned(interned)) = top {
|
||||
|
@ -280,14 +280,13 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Q> FusedIterator for QueueContentIterator<'a, '_, Q> where Q: Queue<'a> {}
|
||||
|
||||
/// A predicate determining when to end measuring if some content fits on the line.
|
||||
///
|
||||
/// Called for every [`element`](FormatElement) in the [FitsQueue] when measuring if a content
|
||||
/// Called for every [`element`](FormatElement) in the [`FitsQueue`] when measuring if a content
|
||||
/// fits on the line. The measuring of the content ends after the first element [`element`](FormatElement) for which this
|
||||
/// predicate returns `true` (similar to a take while iterator except that it takes while the predicate returns `false`).
|
||||
pub(super) trait FitsEndPredicate {
|
||||
|
@ -303,7 +302,7 @@ impl FitsEndPredicate for AllPredicate {
|
|||
}
|
||||
}
|
||||
|
||||
/// Filter that takes all elements between two matching [Tag::StartEntry] and [Tag::EndEntry] tags.
|
||||
/// Filter that takes all elements between two matching [`Tag::StartEntry`] and [`Tag::EndEntry`] tags.
|
||||
#[derive(Debug)]
|
||||
pub(super) enum SingleEntryPredicate {
|
||||
Entry { depth: usize },
|
||||
|
|
|
@ -19,7 +19,7 @@ impl<T> Stack<T> for Vec<T> {
|
|||
}
|
||||
|
||||
fn push(&mut self, value: T) {
|
||||
self.push(value)
|
||||
self.push(value);
|
||||
}
|
||||
|
||||
fn top(&self) -> Option<&T> {
|
||||
|
|
|
@ -715,23 +715,19 @@ pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a P
|
|||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>(
|
||||
visitor: &mut V,
|
||||
expr_context: &'a ExprContext,
|
||||
) {
|
||||
}
|
||||
pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>(visitor: &V, expr_context: &'a ExprContext) {}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, bool_op: &'a BoolOp) {}
|
||||
pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(visitor: &V, bool_op: &'a BoolOp) {}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, operator: &'a Operator) {}
|
||||
pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(visitor: &V, operator: &'a Operator) {}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn walk_unary_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, unary_op: &'a UnaryOp) {}
|
||||
pub fn walk_unary_op<'a, V: Visitor<'a> + ?Sized>(visitor: &V, unary_op: &'a UnaryOp) {}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn walk_cmp_op<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, cmp_op: &'a CmpOp) {}
|
||||
pub fn walk_cmp_op<'a, V: Visitor<'a> + ?Sized>(visitor: &V, cmp_op: &'a CmpOp) {}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, alias: &'a Alias) {}
|
||||
pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(visitor: &V, alias: &'a Alias) {}
|
||||
|
|
|
@ -341,7 +341,7 @@ impl AsciiEscape<'_> {
|
|||
let mut single_count = 0;
|
||||
let mut double_count = 0;
|
||||
|
||||
for ch in source.iter() {
|
||||
for ch in source {
|
||||
let incr = match ch {
|
||||
b'\'' => {
|
||||
single_count += 1;
|
||||
|
@ -425,7 +425,7 @@ impl<'a> Escape for AsciiEscape<'a> {
|
|||
|
||||
#[cold]
|
||||
fn write_body_slow(&self, formatter: &mut impl std::fmt::Write) -> std::fmt::Result {
|
||||
for ch in self.source.iter() {
|
||||
for ch in self.source {
|
||||
Self::write_char(*ch, self.layout().quote, formatter)?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -775,7 +775,7 @@ type X[T] \
|
|||
|
||||
#[test]
|
||||
fn test_type_as_identifier() {
|
||||
let source = r#"\
|
||||
let source = r"\
|
||||
type *a + b, c # ((type * a) + b), c
|
||||
type *(a + b), c # (type * (a + b)), c
|
||||
type (*a + b, c) # type ((*(a + b)), c)
|
||||
|
@ -806,7 +806,7 @@ type (
|
|||
type = 1
|
||||
type = x = 1
|
||||
x = type = 1
|
||||
"#;
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
}
|
||||
|
||||
|
@ -863,7 +863,7 @@ y = 100(no)
|
|||
|
||||
#[test]
|
||||
fn test_match_as_identifier() {
|
||||
let source = r#"\
|
||||
let source = r"\
|
||||
match *a + b, c # ((match * a) + b), c
|
||||
match *(a + b), c # (match * (a + b)), c
|
||||
match (*a + b, c) # match ((*(a + b)), c)
|
||||
|
@ -885,7 +885,7 @@ match match:
|
|||
pass
|
||||
match = lambda query: query == event
|
||||
print(match(12))
|
||||
"#;
|
||||
";
|
||||
insta::assert_debug_snapshot!(parse_suite(source, "<test>").unwrap());
|
||||
}
|
||||
|
||||
|
@ -1124,7 +1124,7 @@ class Abcd:
|
|||
#[test]
|
||||
fn test_ipython_escape_commands() {
|
||||
let parse_ast = parse(
|
||||
r#"
|
||||
r"
|
||||
# Normal Python code
|
||||
(
|
||||
a
|
||||
|
@ -1189,7 +1189,7 @@ foo[0]??
|
|||
foo[0][1]?
|
||||
foo.bar[0].baz[1]??
|
||||
foo.bar[0].baz[2].egg??
|
||||
"#
|
||||
"
|
||||
.trim(),
|
||||
Mode::Jupyter,
|
||||
"<test>",
|
||||
|
|
|
@ -387,7 +387,7 @@ impl<'a> StringParser<'a> {
|
|||
'{' => {
|
||||
if !constant_piece.is_empty() {
|
||||
spec_constructor.push(Expr::from(ast::ExprConstant {
|
||||
value: constant_piece.drain(..).collect::<String>().into(),
|
||||
value: std::mem::take(&mut constant_piece).into(),
|
||||
kind: None,
|
||||
range: self.range(start_location),
|
||||
}));
|
||||
|
@ -408,7 +408,7 @@ impl<'a> StringParser<'a> {
|
|||
}
|
||||
if !constant_piece.is_empty() {
|
||||
spec_constructor.push(Expr::from(ast::ExprConstant {
|
||||
value: constant_piece.drain(..).collect::<String>().into(),
|
||||
value: std::mem::take(&mut constant_piece).into(),
|
||||
kind: None,
|
||||
range: self.range(start_location),
|
||||
}));
|
||||
|
@ -446,7 +446,7 @@ impl<'a> StringParser<'a> {
|
|||
}
|
||||
if !content.is_empty() {
|
||||
values.push(Expr::from(ast::ExprConstant {
|
||||
value: content.drain(..).collect::<String>().into(),
|
||||
value: std::mem::take(&mut content).into(),
|
||||
kind: None,
|
||||
range: self.range(start_location),
|
||||
}));
|
||||
|
@ -1003,7 +1003,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_escape_char_in_byte_literal() {
|
||||
// backslash does not escape
|
||||
let source = r##"b"omkmok\Xaa""##; // spell-checker:ignore omkmok
|
||||
let source = r#"b"omkmok\Xaa""#; // spell-checker:ignore omkmok
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
@ -1024,7 +1024,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_escape_octet() {
|
||||
let source = r##"b'\43a\4\1234'"##;
|
||||
let source = r"b'\43a\4\1234'";
|
||||
let parse_ast = parse_suite(source, "<test>").unwrap();
|
||||
insta::assert_debug_snapshot!(parse_ast);
|
||||
}
|
||||
|
|
|
@ -877,8 +877,8 @@ mod tests {
|
|||
#[test]
|
||||
fn single_quoted_multiline_string_containing_comment() {
|
||||
let test_case = tokenize(
|
||||
r#"'This string contains a hash looking like a comment\
|
||||
# This is not a comment'"#,
|
||||
r"'This string contains a hash looking like a comment\
|
||||
# This is not a comment'",
|
||||
);
|
||||
|
||||
assert_debug_snapshot!(test_case.tokenize_reverse());
|
||||
|
@ -928,14 +928,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn string_with_escaped_quote() {
|
||||
let test_case = tokenize(r#"'a string \' # containing a hash ' # finally a comment"#);
|
||||
let test_case = tokenize(r"'a string \' # containing a hash ' # finally a comment");
|
||||
|
||||
assert_debug_snapshot!(test_case.tokenize_reverse());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_with_double_escaped_backslash() {
|
||||
let test_case = tokenize(r#"'a string \\' # a comment '"#);
|
||||
let test_case = tokenize(r"'a string \\' # a comment '");
|
||||
|
||||
assert_debug_snapshot!(test_case.tokenize_reverse());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue