Skip to content

Commit

Permalink
Merge pull request #912 from prettier/fix-863
Browse files Browse the repository at this point in the history
Fix for #863
  • Loading branch information
Kevin Newton authored Jun 23, 2021
2 parents 939ac67 + 55465ab commit 4b94875
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
### Changed

- [#862](https://github.com/prettier/plugin-ruby/issues/862) - azz, kddeisz - Group together `.where.not` calls in method chains.
- [#863](https://github.com/prettier/plugin-ruby/issues/863) - azz, kddeisz - Fix up Sorbet `sig` block formatting when chaining method calls.

## [1.6.0] - 2021-06-23

Expand Down
31 changes: 30 additions & 1 deletion src/ruby/nodes/calls.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,38 @@ function printMethodAddArg(path, opts, print) {
parentNode.firstReceiverType = node.firstReceiverType;
}

// This is the threshold at which we will start to try to make a nicely
// indented call chain. For the most part, it's always 3.
let threshold = 3;

// Here, we have very specialized behavior where if we're within a sig block,
// then we're going to assume we're creating a Sorbet type signature. In that
// case, we really want the threshold to be lowered to 2 so that we create
// method chains off of any two method calls within the block. For more
// details, see
// https://github.com/prettier/plugin-ruby/issues/863.
let sigBlock = path.getParentNode(2);
if (sigBlock) {
// If we're at a do_block, then we want to go one more level up. This is
// because do_blocks have bodystmt nodes instead of just stmt nodes.
if (sigBlock.type === "do_block") {
sigBlock = path.getParentNode(3);
}

if (
sigBlock.type === "method_add_block" &&
sigBlock.body[1] &&
sigBlock.body[0].type === "method_add_arg" &&
sigBlock.body[0].body[0].type === "fcall" &&
sigBlock.body[0].body[0].body[0].body === "sig"
) {
threshold = 2;
}
}

// 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) {
if (!chained.includes(parentNode.type) && (node.chain || 0) >= threshold) {
// 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
Expand Down
25 changes: 25 additions & 0 deletions test/js/ruby/nodes/calls.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,31 @@ describe("calls", () => {
return expect(content).toMatchFormat();
});

describe("within sig blocks", () => {
test("basic chains", () => {
const content = ruby(`
sig do
params(contacts: Contact::ActiveRecord_Relation)
.returns(Customer::ActiveRecord_Relation)
end
`);

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

test("chains with other methods", () => {
const content = ruby(`
sig do
overridable
.params(contacts: Contact::ActiveRecord_Relation)
.returns(Customer::ActiveRecord_Relation)
end
`);

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

test("no explicit call doesn't add call", () =>
expect("a.(1, 2, 3)").toMatchFormat());

Expand Down

0 comments on commit 4b94875

Please sign in to comment.