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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
- [@rindek], [@kddeisz] - Do not remove parentheses when using the special `call` syntax with no arguments.
- [@ykpythemind] - Do not change regexp bounds if the body has certain content.
- [@karanmandal], [@kddeisz] - Correctly print for loops.
- [@rafbm], [@kddeisz] - If there are method chains with arguments only at the end, we should group the method chain and the method args.

## [1.0.1] - 2020-12-12

Expand Down Expand Up @@ -1071,6 +1072,7 @@ would previously result in `array[]`, but now prints properly.
[@overload119]: https://github.com/Overload119
[@petevk]: https://github.com/petevk
[@pje]: https://github.com/pje
[@rafbm]: https://github.com/rafbm
[@rindek]: https://github.com/rindek
[@rosskinsella]: https://github.com/RossKinsella
[@rsullivan00]: https://github.com/Rsullivan00
Expand Down
16 changes: 16 additions & 0 deletions src/nodes/calls.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function printCall(path, opts, print) {
// right side of the expression, as we want to have a nice multi-line layout.
if (chained.includes(parentNode.type)) {
parentNode.chain = (node.chain || 0) + 1;
parentNode.callChain = (node.callChain || 0) + 1;
parentNode.breakDoc = (node.breakDoc || [receiverDoc]).concat(rightSideDoc);
}

Expand Down Expand Up @@ -109,6 +110,21 @@ function printMethodAddArg(path, opts, print) {
// If we're at the top of a chain, then we're going to print out a nice
// multi-line layout if this doesn't break into multiple lines.
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
// This is pretty specialized behavior. Basically if we're at the top of a
// chain but we've only had method calls without arguments and now we have
// arguments, then we're effectively trying to call a method with arguments
// that is nested under a bunch of stuff. So we group together to first part
// to make it so just the arguments break. This looks like, for example:
//
// config.action_dispatch.rescue_responses.merge!(
// 'ActiveRecord::ConnectionTimeoutError' => :service_unavailable,
// 'ActiveRecord::QueryCanceled' => :service_unavailable
// )
//
if (node.callChain === node.chain) {
return concat([group(indent(concat(node.breakDoc))), group(argsDoc)]);
}

return ifBreak(
group(indent(concat(node.breakDoc.concat(argsDoc)))),
concat([methodDoc, argsDoc])
Expand Down
13 changes: 12 additions & 1 deletion test/js/nodes/calls.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { ruby } = require("../utils");
const { long, ruby } = require("../utils");

describe("calls", () => {
test("simple calls", () => {
Expand Down Expand Up @@ -26,6 +26,17 @@ describe("calls", () => {
return expect(before).toChangeFormat(after);
});

test("chains of methods with one with arguments right at the top", () => {
const content = ruby(`
aaa.bbb.ccc.ddd.eee.merge(
${long.slice(0, 30)}: 'aaa',
${long.slice(0, 31)}: 'bbb'
)
`);

return expect(content).toMatchFormat();
});

test("tons of calls that fit on one line", () => {
const content = "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z";

Expand Down