Skip to content

Commit

Permalink
fix(js_formatter): fix indention when huggable expressions break in a…
Browse files Browse the repository at this point in the history
…rrow chains (#1036)
  • Loading branch information
faultyserver authored Dec 5, 2023
1 parent 1e999b5 commit 5ff507e
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ impl Format<JsFormatContext> for ArrowChain {
let head_parent = head.syntax().parent();
let tail_body = tail.body()?;
let is_assignment_rhs = self.options.assignment_layout.is_some();
let is_grouped_call_arg_layout = self.options.call_arg_layout.is_some();
let ancestor_call_expr_or_logical_expr = head.syntax().ancestors().any(|ancestor| {
matches!(
ancestor.kind(),
Expand Down Expand Up @@ -537,8 +538,6 @@ impl Format<JsFormatContext> for ArrowChain {
write!(f, [soft_line_break()])?;
}

let is_grouped_call_arg_layout = self.options.call_arg_layout.is_some();

let join_signatures = format_with(|f: &mut JsFormatter| {
let mut is_first_in_chain = true;
for arrow in self.arrows() {
Expand Down Expand Up @@ -637,25 +636,18 @@ impl Format<JsFormatContext> for ArrowChain {
}
} else {
let should_add_parens = should_add_parens(&tail_body);
write!(
f,
[format_with(|f| {
if should_add_parens {
write!(
f,
[
if_group_fits_on_line(&text("(")),
format_tail_body,
if_group_fits_on_line(&text(")"))
]
)?;
} else {
write!(f, [format_tail_body])?;
}

Ok(())
})]
)?;
if should_add_parens {
write!(
f,
[
if_group_fits_on_line(&text("(")),
format_tail_body,
if_group_fits_on_line(&text(")"))
]
)?;
} else {
write!(f, [format_tail_body])?;
}
}

// Format the trailing comments of all arrow function EXCEPT the first one because
Expand Down Expand Up @@ -704,10 +696,15 @@ impl Format<JsFormatContext> for ArrowChain {
.should_expand(break_signatures),
space(),
tail.fat_arrow_token().format(),
indent_if_group_breaks(&format_tail_body, group_id),
]
)?;

if is_grouped_call_arg_layout {
write!(f, [group(&format_tail_body)])?;
} else {
write!(f, [indent_if_group_breaks(&format_tail_body, group_id)])?;
}

if is_callee {
write!(
f,
Expand Down
20 changes: 3 additions & 17 deletions crates/biome_js_formatter/tests/quick_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,13 @@ mod language {
include!("language.rs");
}

// #[ignore]
#[ignore]
#[test]
// use this test check if your snippet prints as you wish, without using a snapshot
fn quick_test() {
let src = r#"
const foo = ({normal: something, n: {yes: what, layout: {h}}}: LE) => {
bar();
}
const obj = {
func(id, { blog: { title } }) {
return id + title;
},
};
class A {
func(id, { blog: { title } }) {
return id + title;
}
}
((C) => (props) => <C {...props} />);
(({C}) => (props) => <C {...props} />);
"#;
let source_type = JsFileSource::tsx();
let tree = parse(
Expand Down
34 changes: 34 additions & 0 deletions crates/biome_js_formatter/tests/specs/js/module/arrow/currying.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,37 @@ const mw = store => next => action => {
const middleware = options => (req, res, next) => {
// ...
};

// Ensure tail bodies only indent a single level when necessary
somePromise.then(({default: ComponentName}) => (props) => [longerSingleElement]);

somePromise.then((reallyLongArguments) => (makeTheChainFullyBreak) => (moreThanItWould) => [longerSingleElement]);

somePromise.then(({ reallyLongArguments }) => (makeTheChainFullyBreak) => [
dontIndentTwice,
]);
somePromise.then(({ reallyLongArguments }) => (makeTheChainFullyBreak) => {
dontIndentTwice();
});

somePromise.then(({ reallyLongArguments }) => (makeTheChainFullyBreak) => (andNowAllLines) => (keepGoing) =>
dontIndentTwice());

somePromise.then(
({ reallyLongArguments }) =>
(makeTheChainFullyBreak) =>
() => {
dontIndentTwice();
},
);
function foo() {
// Unmount clean up
React.useLayoutEffect(() => () => {
callSomeLongNamedFunction();
});
}

function foo() {
// Unmount clean up
React.useLayoutEffect(() => () => [hello, what, is, this, going, too, doehwharht]);
}
135 changes: 135 additions & 0 deletions crates/biome_js_formatter/tests/specs/js/module/arrow/currying.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,39 @@ const middleware = options => (req, res, next) => {
// ...
};

// Ensure tail bodies only indent a single level when necessary
somePromise.then(({default: ComponentName}) => (props) => [longerSingleElement]);

somePromise.then((reallyLongArguments) => (makeTheChainFullyBreak) => (moreThanItWould) => [longerSingleElement]);

somePromise.then(({ reallyLongArguments }) => (makeTheChainFullyBreak) => [
dontIndentTwice,
]);
somePromise.then(({ reallyLongArguments }) => (makeTheChainFullyBreak) => {
dontIndentTwice();
});

somePromise.then(({ reallyLongArguments }) => (makeTheChainFullyBreak) => (andNowAllLines) => (keepGoing) =>
dontIndentTwice());

somePromise.then(
({ reallyLongArguments }) =>
(makeTheChainFullyBreak) =>
() => {
dontIndentTwice();
},
);
function foo() {
// Unmount clean up
React.useLayoutEffect(() => () => {
callSomeLongNamedFunction();
});
}

function foo() {
// Unmount clean up
React.useLayoutEffect(() => () => [hello, what, is, this, going, too, doehwharht]);
}
```


Expand Down Expand Up @@ -66,6 +99,59 @@ const mw = (store) => (next) => (action) => {
const middleware = (options) => (req, res, next) => {
// ...
};

// Ensure tail bodies only indent a single level when necessary
somePromise.then(({ default: ComponentName }) => (props) => [
longerSingleElement,
]);

somePromise.then(
(reallyLongArguments) => (makeTheChainFullyBreak) => (moreThanItWould) => [
longerSingleElement,
],
);

somePromise.then(({ reallyLongArguments }) => (makeTheChainFullyBreak) => [
dontIndentTwice,
]);
somePromise.then(({ reallyLongArguments }) => (makeTheChainFullyBreak) => {
dontIndentTwice();
});

somePromise.then(
({ reallyLongArguments }) =>
(makeTheChainFullyBreak) =>
(andNowAllLines) =>
(keepGoing) =>
dontIndentTwice(),
);

somePromise.then(
({ reallyLongArguments }) =>
(makeTheChainFullyBreak) =>
() => {
dontIndentTwice();
},
);
function foo() {
// Unmount clean up
React.useLayoutEffect(() => () => {
callSomeLongNamedFunction();
});
}

function foo() {
// Unmount clean up
React.useLayoutEffect(() => () => [
hello,
what,
is,
this,
going,
too,
doehwharht,
]);
}
```

## Output 2
Expand Down Expand Up @@ -103,6 +189,55 @@ const mw = store => next => action => {
const middleware = options => (req, res, next) => {
// ...
};

// Ensure tail bodies only indent a single level when necessary
somePromise.then(({ default: ComponentName }) => props => [
longerSingleElement,
]);

somePromise.then(
reallyLongArguments => makeTheChainFullyBreak => moreThanItWould => [
longerSingleElement,
],
);

somePromise.then(({ reallyLongArguments }) => makeTheChainFullyBreak => [
dontIndentTwice,
]);
somePromise.then(({ reallyLongArguments }) => makeTheChainFullyBreak => {
dontIndentTwice();
});

somePromise.then(
({ reallyLongArguments }) =>
makeTheChainFullyBreak =>
andNowAllLines =>
keepGoing =>
dontIndentTwice(),
);

somePromise.then(({ reallyLongArguments }) => makeTheChainFullyBreak => () => {
dontIndentTwice();
});
function foo() {
// Unmount clean up
React.useLayoutEffect(() => () => {
callSomeLongNamedFunction();
});
}

function foo() {
// Unmount clean up
React.useLayoutEffect(() => () => [
hello,
what,
is,
this,
going,
too,
doehwharht,
]);
}
```


0 comments on commit 5ff507e

Please sign in to comment.