Skip to content

Commit

Permalink
fix(formatter): dedent logic inconsistent with prettier where the ind…
Browse files Browse the repository at this point in the history
…ent-style is space and the indent-width is not 2. (#2134)
  • Loading branch information
mdm317 authored Apr 10, 2024
1 parent 44fc265 commit 17641a1
Show file tree
Hide file tree
Showing 13 changed files with 670 additions and 121 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

- Complete the well-known file lists for JSON-like files. Trailing commas are allowed in `.jsonc` files by default. Some well-known files like `tsconfig.json` and `.babelrc` don't use the `.jsonc` extension but still allow comments and trailing commas. While others, such as `.eslintrc.json`, only allow comments. Biome is able to identify these files and adjusts the `json.parser.allowTrailingCommas` option accordingly to ensure they are correctly parsed. Contributed by @Sec-ant

- Fix dedent logic inconsistent with prettier where the indent-style is space and the indent-width is not 2. Contributed by @mdm317

### CLI

#### New features
Expand Down
122 changes: 120 additions & 2 deletions crates/biome_formatter/src/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,35 @@ impl<Context> Format<Context> for HardSpace {
/// # Ok(())
/// # }
/// ```
///
/// When the indent_style is tab, [indent] convert the preceding alignments to indents
/// ```
/// use biome_formatter::prelude::*;
/// use biome_formatter::{format, format_args};
///
/// # fn main() -> FormatResult<()> {
/// let block = format!(
/// SimpleFormatContext::default(),
/// [
/// text("root"),
/// indent(&format_args![align(
/// 2,
/// &format_args![indent(&format_args![
/// hard_line_break(),
/// text("shoud be 3 tabs"),
/// ])]
/// )])
/// ]
/// )?;
///
/// assert_eq!(
/// "root\n\t\t\tshoud be 3 tabs",
/// block.print()?.as_code()
/// );
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn indent<Content, Context>(content: &Content) -> Indent<Context>
where
Expand Down Expand Up @@ -814,6 +843,95 @@ impl<Context> std::fmt::Debug for Indent<'_, Context> {
/// # Ok(())
/// # }
/// ```
///
/// ```
/// use biome_formatter::prelude::*;
/// use biome_formatter::{format, format_args, IndentStyle, IndentWidth, SimpleFormatOptions};
///
/// # fn main() -> FormatResult<()> {
/// let context = SimpleFormatContext::new(SimpleFormatOptions {
/// indent_width: IndentWidth::try_from(8).unwrap(),
/// indent_style: IndentStyle::Space,
/// ..SimpleFormatOptions::default()
/// });
/// let elements = format!(
/// context,
/// [
/// text("root"),
/// indent(&format_args![
/// hard_line_break(),
/// text("Indented"),
/// align(
/// 2,
/// &format_args![
/// hard_line_break(),
/// text("Indented and aligned"),
/// dedent(&format_args![
/// hard_line_break(),
/// text("Indented, not aligned"),
/// ]),
/// ]
/// ),
/// ]),
/// align(
/// 2,
/// &format_args![
/// hard_line_break(),
/// text("Aligned"),
/// indent(&format_args![
/// hard_line_break(),
/// text("Aligned, and indented"),
/// dedent(&format_args![
/// hard_line_break(),
/// text("aligned, not Intended"),
/// ]),
/// ])
/// ]
/// ),
/// dedent(&format_args![hard_line_break(), text("root level")])
/// ]
/// )?;
/// assert_eq!(
/// "root\n Indented\n Indented and aligned\n Indented, not aligned\n Aligned\n Aligned, and indented\n aligned, not Intended\nroot level",
/// elements.print()?.as_code()
/// );
/// # Ok(())
/// # }
/// ```
///
/// ```
/// use biome_formatter::prelude::*;
/// use biome_formatter::{format, format_args};
///
/// # fn main() -> FormatResult<()> {
/// let block = format!(
/// SimpleFormatContext::default(),
/// [
/// text("root"),
/// indent(&format_args![align(
/// 2,
/// &format_args![align(
/// 2,
/// &format_args![indent(&format_args![
/// hard_line_break(),
/// text("should be 4 tabs"),
/// dedent(&format_args![
/// hard_line_break(),
/// text("should be 1 tab and 4 spaces"),
/// ]),
/// ])]
/// ),]
/// )])
/// ]
/// )?;
/// assert_eq!(
/// "root\n\t\t\t\tshould be 4 tabs\n\t should be 1 tab and 4 spaces",
/// block.print()?.as_code()
/// );
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn dedent<Content, Context>(content: &Content) -> Dedent<Context>
where
Expand All @@ -835,7 +953,7 @@ impl<Context> Format<Context> for Dedent<'_, Context> {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
f.write_element(FormatElement::Tag(StartDedent(self.mode)))?;
Arguments::from(&self.content).fmt(f)?;
f.write_element(FormatElement::Tag(EndDedent))
f.write_element(FormatElement::Tag(EndDedent(self.mode)))
}
}

Expand Down Expand Up @@ -2107,7 +2225,7 @@ impl<Context> Format<Context> for IndentIfGroupBreaks<'_, Context> {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
f.write_element(FormatElement::Tag(StartIndentIfGroupBreaks(self.group_id)))?;
Arguments::from(&self.content).fmt(f)?;
f.write_element(FormatElement::Tag(EndIndentIfGroupBreaks))
f.write_element(FormatElement::Tag(EndIndentIfGroupBreaks(self.group_id)))
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/biome_formatter/src/format_element/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,12 +514,12 @@ impl Format<IrFormatContext> for &[FormatElement] {
EndFill
| EndLabelled
| EndConditionalContent
| EndIndentIfGroupBreaks
| EndIndentIfGroupBreaks(_)
| EndAlign
| EndIndent
| EndGroup
| EndLineSuffix
| EndDedent
| EndDedent(_)
| EndVerbatim => {
write!(f, [ContentArrayEnd, text(")")])?;
}
Expand Down
8 changes: 4 additions & 4 deletions crates/biome_formatter/src/format_element/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub enum Tag {
/// Reduces the indention of the specified content either by one level or to the root, depending on the mode.
/// Reverse operation of `Indent` and can be used to *undo* an `Align` for nested content.
StartDedent(DedentMode),
EndDedent,
EndDedent(DedentMode),

/// Creates a logical group where its content is either consistently printed:
/// * on a single line: Omitting `LineMode::Soft` line breaks and printing spaces for `LineMode::SoftOrSpace`
Expand All @@ -41,7 +41,7 @@ pub enum Tag {
/// Optimized version of [Tag::StartConditionalContent] for the case where some content
/// should be indented if the specified group breaks.
StartIndentIfGroupBreaks(GroupId),
EndIndentIfGroupBreaks,
EndIndentIfGroupBreaks(GroupId),

/// Concatenates multiple elements together with a given separator printed in either
/// flat or expanded mode to fill the print width. Expect that the content is a list of alternating
Expand Down Expand Up @@ -99,10 +99,10 @@ impl Tag {
match self {
StartIndent | EndIndent => TagKind::Indent,
StartAlign(_) | EndAlign => TagKind::Align,
StartDedent(_) | EndDedent => TagKind::Dedent,
StartDedent(_) | EndDedent(_) => TagKind::Dedent,
StartGroup(_) | EndGroup => TagKind::Group,
StartConditionalContent(_) | EndConditionalContent => TagKind::ConditionalContent,
StartIndentIfGroupBreaks(_) | EndIndentIfGroupBreaks => TagKind::IndentIfGroupBreaks,
StartIndentIfGroupBreaks(_) | EndIndentIfGroupBreaks(_) => TagKind::IndentIfGroupBreaks,
StartFill | EndFill => TagKind::Fill,
StartEntry | EndEntry => TagKind::Entry,
StartLineSuffix | EndLineSuffix => TagKind::LineSuffix,
Expand Down
Loading

0 comments on commit 17641a1

Please sign in to comment.