Skip to content
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
41 changes: 41 additions & 0 deletions .changeset/mighty-seals-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
"@biomejs/biome": minor
---

Added a new option to Biome's JavaScript formatter, `javascript.formatter.operatorLinebreak`, to configure whether long lines should be broken before or after binary operators.

For example, the following configuration:

```json
{
"formatter": {
"javascript": {
"operatorLinebreak": "before" // defaults to "after"
}
}
}
```

Will cause this JavaScript file:

```js
const VERY_LONG_CONDITION_1234123412341234123412341234 = false;

if (VERY_LONG_CONDITION_1234123412341234123412341234 && VERY_LONG_CONDITION_1234123412341234123412341234 && VERY_LONG_CONDITION_1234123412341234123412341234 && VERY_LONG_CONDITION_1234123412341234123412341234) {
console.log("DONE")
}
```

to be formatted like this:

```js
const VERY_LONG_CONDITION_1234123412341234123412341234 = false;
if (
VERY_LONG_CONDITION_1234123412341234123412341234
&& VERY_LONG_CONDITION_1234123412341234123412341234
&& VERY_LONG_CONDITION_1234123412341234123412341234
&& VERY_LONG_CONDITION_1234123412341234123412341234
) {
console.log("DONE")
}
```
1 change: 1 addition & 0 deletions crates/biome_cli/src/execute/migrate/prettier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ impl TryFrom<PrettierConfiguration> for biome_configuration::Configuration {
bracket_spacing: Some(value.bracket_spacing.into()),
jsx_quote_style: Some(jsx_quote_style),
attribute_position: Some(AttributePosition::default()),
operator_linebreak: None,
};
let js_config = biome_configuration::JsConfiguration {
formatter: Some(js_formatter),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ The configuration that is contained inside the file `biome.json`
formatted on a single line if it fits in the line. When formatting
`package.json`, Biome will use `always` unless configured otherwise.
Defaults to "auto".
--javascript-formatter-operator-linebreak=<before|after> When breaking binary expressions
into multiple lines, whether to break them before or after the binary
operator. Defaults to "after".
--javascript-linter-enabled=<true|false> Control the linter for JavaScript (and its super
languages) files.
--javascript-assist-enabled=<true|false> Control the assist for JavaScript (and its super
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ The configuration that is contained inside the file `biome.json`
formatted on a single line if it fits in the line. When formatting
`package.json`, Biome will use `always` unless configured otherwise.
Defaults to "auto".
--javascript-formatter-operator-linebreak=<before|after> When breaking binary expressions
into multiple lines, whether to break them before or after the binary
operator. Defaults to "after".
--javascript-linter-enabled=<true|false> Control the linter for JavaScript (and its super
languages) files.
--javascript-assist-enabled=<true|false> Control the assist for JavaScript (and its super
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ Formatting options specific to the JavaScript files
formatted on a single line if it fits in the line. When formatting
`package.json`, Biome will use `always` unless configured otherwise.
Defaults to "auto".
--javascript-formatter-operator-linebreak=<before|after> When breaking binary expressions
into multiple lines, whether to break them before or after the binary
operator. Defaults to "after".

Set of properties to integrate Biome with a VCS software.
--vcs-enabled=<true|false> Whether Biome should integrate itself with the VCS client
Expand Down
15 changes: 14 additions & 1 deletion crates/biome_configuration/src/javascript/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use biome_formatter::{
LineEnding, LineWidth, QuoteStyle,
};
use biome_js_formatter::context::{
ArrowParentheses, QuoteProperties, Semicolons, trailing_commas::TrailingCommas,
ArrowParentheses, OperatorLinebreak, QuoteProperties, Semicolons,
trailing_commas::TrailingCommas,
};
use bpaf::Bpaf;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -116,6 +117,14 @@ pub struct JsFormatterConfiguration {
#[bpaf(long("javascript-formatter-expand"), argument("auto|always|never"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub expand: Option<Expand>,

/// When breaking binary expressions into multiple lines, whether to break them before or after the binary operator. Defaults to "after".
#[bpaf(
long("javascript-formatter-operator-linebreak"),
argument("before|after")
)]
#[serde(skip_serializing_if = "Option::is_none")]
pub operator_linebreak: Option<OperatorLinebreak>,
}

impl JsFormatterConfiguration {
Expand Down Expand Up @@ -154,4 +163,8 @@ impl JsFormatterConfiguration {
pub fn expand_resolved(&self) -> Expand {
self.expand.unwrap_or_default()
}

pub fn operator_linebreak_resolved(&self) -> OperatorLinebreak {
self.operator_linebreak.unwrap_or_default()
}
}
66 changes: 65 additions & 1 deletion crates/biome_js_formatter/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ pub struct JsFormatOptions {

/// Whether to expand object and array literals to multiple lines. Defaults to "auto".
expand: Expand,

/// When formatting binary expressions, whether to break the line before or after the operator. Defaults to "after".
operator_linebreak: OperatorLinebreak,
}

impl JsFormatOptions {
Expand All @@ -196,6 +199,7 @@ impl JsFormatOptions {
bracket_same_line: BracketSameLine::default(),
attribute_position: AttributePosition::default(),
expand: Expand::default(),
operator_linebreak: OperatorLinebreak::default(),
}
}

Expand Down Expand Up @@ -269,6 +273,11 @@ impl JsFormatOptions {
self
}

pub fn with_operator_linebreak(mut self, operator_linebreak: OperatorLinebreak) -> Self {
self.operator_linebreak = operator_linebreak;
self
}

pub fn set_arrow_parentheses(&mut self, arrow_parentheses: ArrowParentheses) {
self.arrow_parentheses = arrow_parentheses;
}
Expand Down Expand Up @@ -325,6 +334,10 @@ impl JsFormatOptions {
self.semicolons = semicolons;
}

pub fn set_operator_linebreak(&mut self, operator_linebreak: OperatorLinebreak) {
self.operator_linebreak = operator_linebreak;
}

pub fn arrow_parentheses(&self) -> ArrowParentheses {
self.arrow_parentheses
}
Expand Down Expand Up @@ -372,6 +385,10 @@ impl JsFormatOptions {
pub fn expand(&self) -> Expand {
self.expand
}

pub fn operator_linebreak(&self) -> OperatorLinebreak {
self.operator_linebreak
}
}

impl FormatOptions for JsFormatOptions {
Expand Down Expand Up @@ -411,7 +428,8 @@ impl fmt::Display for JsFormatOptions {
writeln!(f, "Bracket spacing: {}", self.bracket_spacing.value())?;
writeln!(f, "Bracket same line: {}", self.bracket_same_line.value())?;
writeln!(f, "Attribute Position: {}", self.attribute_position)?;
writeln!(f, "Expand lists: {}", self.expand)
writeln!(f, "Expand lists: {}", self.expand)?;
writeln!(f, "Operator linebreak: {}", self.operator_linebreak)
}
}

Expand Down Expand Up @@ -542,3 +560,49 @@ impl fmt::Display for ArrowParentheses {
}
}
}

#[derive(Clone, Copy, Debug, Default, Deserializable, Eq, Hash, Merge, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum OperatorLinebreak {
#[default]
After,
Before,
}

impl OperatorLinebreak {
pub const fn is_before(&self) -> bool {
matches!(self, Self::Before)
}

pub const fn is_after(&self) -> bool {
matches!(self, Self::After)
}
}

impl FromStr for OperatorLinebreak {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"after" => Ok(Self::After),
"before" => Ok(Self::Before),
_ => Err(
"Value not supported for Operator linebreak. Supported values are 'before' and 'after'.",
),
}
}
}

impl fmt::Display for OperatorLinebreak {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::After => write!(f, "After"),
Self::Before => write!(f, "Before"),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ use biome_formatter::{Buffer, CstFormatContext, format_args, write};
use biome_js_syntax::binary_like_expression::{
AnyJsBinaryLikeExpression, AnyJsBinaryLikeLeftExpression,
};

use crate::{JsFormatOptions, context::OperatorLinebreak};
use biome_js_syntax::{AnyJsExpression, JsSyntaxKind, JsSyntaxNode, JsUnaryExpression};

use crate::js::expressions::static_member_expression::AnyJsStaticMemberLike;
Expand Down Expand Up @@ -275,13 +277,21 @@ impl Format<JsFormatContext> for BinaryLeftOrRightSide {

let operator_and_right_expression = format_with(|f| {
let should_inline = binary_like_expression.should_inline_logical_expression();

write!(f, [space(), operator_token.format()])?;
let options: &JsFormatOptions = f.options();
let op_linebreak = options.operator_linebreak();

if should_inline {
write!(f, [space()])?;
write!(f, [space(), operator_token.format(), space()])?;
} else if let OperatorLinebreak::Before = op_linebreak {
write!(
f,
[soft_line_break_or_space(), operator_token.format(), space()]
)?;
} else {
write!(f, [soft_line_break_or_space()])?;
write!(
f,
[space(), operator_token.format(), soft_line_break_or_space()]
)?;
}

write!(f, [right.format()])?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down Expand Up @@ -78,6 +79,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Always
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down Expand Up @@ -74,6 +75,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down Expand Up @@ -74,6 +75,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down Expand Up @@ -93,6 +94,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down Expand Up @@ -77,6 +78,7 @@ Bracket spacing: true
Bracket same line: false
Attribute Position: Auto
Expand lists: Auto
Operator linebreak: After
-----

```js
Expand Down
Loading