Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/arrowfunction with conditional expression body #1929

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
- Fix [#1827](https://github.com/biomejs/biome/issues/1827) by properly analyzing nested `try-finally` statements. Contributed by @ah-yu

- Fix [#1924](https://github.com/biomejs/biome/issues/1924) Use the correct export name to sort in the import clause. Contributed by @ah-yu
- Fix [#1805](https://github.com/biomejs/biome/issues/1805) fix formatting arrow function which has conditional expression body Contributed by @mdm317

### CLI

Expand Down
182 changes: 181 additions & 1 deletion crates/biome_formatter/src/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,72 @@ pub const fn space() -> Space {
Space
}

/// Inserts a single space.
/// The main difference with space is that
/// it always adds a space even when it's the last element of a group.
///
/// # Examples
///
/// ```
/// use biome_formatter::{format, format_args, LineWidth, SimpleFormatOptions};
/// use biome_formatter::prelude::*;
///
/// # fn main() -> FormatResult<()> {
/// let context = SimpleFormatContext::new(SimpleFormatOptions {
/// line_width: LineWidth::try_from(20).unwrap(),
/// ..SimpleFormatOptions::default()
/// });
///
/// let elements = format!(context, [
/// group(&format_args![
/// text("nineteen_characters"),
/// soft_line_break(),
/// text("1"),
/// hard_space(),
/// ])
/// ])?;
/// assert_eq!(
/// "nineteen_characters\n1",
/// elements.print()?.as_code()
/// );
/// # Ok(())
/// # }
/// ```
/// # Examples
///
/// Without HardSpace
///
/// ```
/// use biome_formatter::{format, format_args, LineWidth, SimpleFormatOptions};
/// use biome_formatter::prelude::*;
///
/// # fn main() -> FormatResult<()> {
/// let context = SimpleFormatContext::new(SimpleFormatOptions {
/// line_width: LineWidth::try_from(20).unwrap(),
/// ..SimpleFormatOptions::default()
/// });
///
/// let elements = format!(context, [
/// group(&format_args![
/// text("nineteen_characters"),
/// soft_line_break(),
/// text("1"),
/// space(),
/// ])
/// ])?;
/// assert_eq!(
/// "nineteen_characters1",
/// elements.print()?.as_code()
/// );
/// # Ok(())
/// # }
/// ```

#[inline]
pub const fn hard_space() -> HardSpace {
HardSpace
}

/// Optionally inserts a single space if the given condition is true.
///
/// # Examples
Expand Down Expand Up @@ -636,6 +702,14 @@ impl<Context> Format<Context> for Space {
}
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct HardSpace;

impl<Context> Format<Context> for HardSpace {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
f.write_element(FormatElement::HardSpace)
}
}
/// It adds a level of indentation to the given content
///
/// It doesn't add any line breaks at the edges of the content, meaning that
Expand Down Expand Up @@ -1251,6 +1325,109 @@ pub fn soft_line_indent_or_space<Context>(content: &impl Format<Context>) -> Blo
}
}

/// It functions similarly to soft_line_indent_or_space, but instead of a regular space, it inserts a hard space.
///
/// # Examples
///
/// Indents the content by one level and puts in new lines if the enclosing `Group` doesn't
/// fit on a single line. Otherwise, just inserts a space.
///
/// ```
/// use biome_formatter::{format, format_args, LineWidth, SimpleFormatOptions};
/// use biome_formatter::prelude::*;
///
/// # fn main() -> FormatResult<()> {
/// let context = SimpleFormatContext::new(SimpleFormatOptions {
/// line_width: LineWidth::try_from(10).unwrap(),
/// ..SimpleFormatOptions::default()
/// });
///
/// let elements = format!(context, [
/// group(&format_args![
/// text("name"),
/// space(),
/// text("="),
/// soft_line_indent_or_hard_space(&format_args![
/// text("firstName"),
/// space(),
/// text("+"),
/// space(),
/// text("lastName"),
/// ]),
/// ])
/// ])?;
///
/// assert_eq!(
/// "name =\n\tfirstName + lastName",
/// elements.print()?.as_code()
/// );
/// # Ok(())
/// # }
/// ```
///
/// Only adds a space if the enclosing `Group` fits on a single line
/// ```
/// use biome_formatter::{format, format_args};
/// use biome_formatter::prelude::*;
///
/// # fn main() -> FormatResult<()> {
/// let elements = format!(SimpleFormatContext::default(), [
/// group(&format_args![
/// text("a"),
/// space(),
/// text("="),
/// soft_line_indent_or_hard_space(&text("10")),
/// ])
/// ])?;
///
/// assert_eq!(
/// "a = 10",
/// elements.print()?.as_code()
/// );
/// # Ok(())
/// # }
/// ```
///
/// It enforces a space after the "=" assignment operators
/// ```
/// use biome_formatter::{format, format_args, LineWidth, SimpleFormatOptions};
/// use biome_formatter::prelude::*;
///
/// # fn main() -> FormatResult<()> {
/// let context = SimpleFormatContext::new(SimpleFormatOptions {
/// line_width: LineWidth::try_from(8).unwrap(),
/// ..SimpleFormatOptions::default()
/// });
///
/// let elements = format!(context, [
/// group(&format_args![
/// text("value"),
/// soft_line_break_or_space(),
/// text("="),
/// soft_line_indent_or_hard_space(&format_args![
/// text("10"),
/// ]),
/// ])
/// ])?;
///
/// assert_eq!(
/// "value\n=\n\t10",
/// elements.print()?.as_code()
/// );
/// # Ok(())
/// # }
/// ```

#[inline]
pub fn soft_line_indent_or_hard_space<Context>(
content: &impl Format<Context>,
) -> BlockIndent<Context> {
BlockIndent {
content: Argument::new(content),
mode: IndentMode::HardSpace,
}
}

#[derive(Copy, Clone)]
pub struct BlockIndent<'a, Context> {
content: Argument<'a, Context>,
Expand All @@ -1262,6 +1439,7 @@ enum IndentMode {
Soft,
Block,
SoftSpace,
HardSpace,
SoftLineOrSpace,
}

Expand All @@ -1277,6 +1455,7 @@ impl<Context> Format<Context> for BlockIndent<'_, Context> {
IndentMode::SoftLineOrSpace | IndentMode::SoftSpace => {
write!(f, [soft_line_break_or_space()])?
}
IndentMode::HardSpace => write!(f, [hard_space(), soft_line_break()])?,
}

let is_empty = {
Expand All @@ -1296,7 +1475,7 @@ impl<Context> Format<Context> for BlockIndent<'_, Context> {
IndentMode::Soft => write!(f, [soft_line_break()]),
IndentMode::Block => write!(f, [hard_line_break()]),
IndentMode::SoftSpace => write!(f, [soft_line_break_or_space()]),
IndentMode::SoftLineOrSpace => Ok(()),
IndentMode::SoftLineOrSpace | IndentMode::HardSpace => Ok(()),
}
}
}
Expand All @@ -1308,6 +1487,7 @@ impl<Context> std::fmt::Debug for BlockIndent<'_, Context> {
IndentMode::Block => "HardBlockIndent",
IndentMode::SoftLineOrSpace => "SoftLineIndentOrSpace",
IndentMode::SoftSpace => "SoftSpaceBlockIndent",
IndentMode::HardSpace => "HardSpaceBlockIndent",
};

f.debug_tuple(name).field(&"{{content}}").finish()
Expand Down
15 changes: 9 additions & 6 deletions crates/biome_formatter/src/format_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ use std::rc::Rc;
pub enum FormatElement {
/// A space token, see [crate::builders::space] for documentation.
Space,

HardSpace,
/// A new line, see [crate::builders::soft_line_break], [crate::builders::hard_line_break], and [crate::builders::soft_line_break_or_space] for documentation.
Line(LineMode),

/// Forces the parent group to print in expanded mode.
ExpandParent,

/// Token constructed by the formatter from a static string
StaticText { text: &'static str },
StaticText {
text: &'static str,
},

/// Token constructed from the input source as a dynamic
/// string with its start position in the input document.
Expand Down Expand Up @@ -66,7 +68,7 @@ pub enum FormatElement {
impl std::fmt::Debug for FormatElement {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
FormatElement::Space => write!(fmt, "Space"),
FormatElement::Space | FormatElement::HardSpace => write!(fmt, "Space"),
FormatElement::Line(mode) => fmt.debug_tuple("Line").field(mode).finish(),
FormatElement::ExpandParent => write!(fmt, "ExpandParent"),
FormatElement::StaticText { text } => {
Expand Down Expand Up @@ -251,9 +253,10 @@ impl FormatElements for FormatElement {
// Traverse into the most flat version because the content is guaranteed to expand when even
// the most flat version contains some content that forces a break.
FormatElement::BestFitting(best_fitting) => best_fitting.most_flat().will_break(),
FormatElement::LineSuffixBoundary | FormatElement::Space | FormatElement::Tag(_) => {
false
}
FormatElement::LineSuffixBoundary
| FormatElement::Space
| FormatElement::Tag(_)
| FormatElement::HardSpace => false,
}
}

Expand Down
3 changes: 2 additions & 1 deletion crates/biome_formatter/src/format_element/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ impl Format<IrFormatContext> for &[FormatElement] {

match element {
element @ (FormatElement::Space
| FormatElement::HardSpace
| FormatElement::StaticText { .. }
| FormatElement::DynamicText { .. }
| FormatElement::LocatedTokenText { .. }) => {
Expand All @@ -246,7 +247,7 @@ impl Format<IrFormatContext> for &[FormatElement] {
in_text = true;

match element {
FormatElement::Space => {
FormatElement::Space | FormatElement::HardSpace => {
write!(f, [text(" ")])?;
}
element if element.is_text() => f.write_element(element.clone())?,
Expand Down
10 changes: 7 additions & 3 deletions crates/biome_formatter/src/printer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl<'a> Printer<'a> {
let args = stack.top();

match element {
FormatElement::Space => {
FormatElement::Space | FormatElement::HardSpace => {
if self.state.line_width > 0 {
self.state.pending_space = true;
}
Expand Down Expand Up @@ -985,7 +985,12 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
self.state.pending_space = true;
}
}

FormatElement::HardSpace => {
self.state.line_width += 1;
if self.state.line_width > self.options().print_width.into() {
return Ok(Fits::No);
}
}
FormatElement::Line(line_mode) => {
if args.mode().is_flat() {
match line_mode {
Expand Down Expand Up @@ -1628,7 +1633,6 @@ two lines`,

assert_eq!(printed.as_code(), "[1, 2, 3]; // trailing")
}

#[test]
fn conditional_with_group_id_in_fits() {
let content = format_with(|f| {
Expand Down
Loading
Loading