Remove allow(pedantic) from formatter (#6549)

This commit is contained in:
Micha Reiser 2023-08-14 14:02:06 +02:00 committed by GitHub
parent c39bcbadff
commit 9584f613b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 348 additions and 316 deletions

View file

@ -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()

View file

@ -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))
}
}

View file

@ -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(),

View file

@ -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);

View file

@ -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)

View file

@ -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)
}

View file

@ -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(

View file

@ -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

View file

@ -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;

View file

@ -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(),

View file

@ -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),

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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)

View file

@ -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),+))
}

View file

@ -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>,

View file

@ -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]

View file

@ -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,
}
}

View file

@ -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 },

View file

@ -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> {

View file

@ -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) {}

View file

@ -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(())

View file

@ -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>",

View file

@ -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);
}

View file

@ -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());
}