prettier 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -1
- data/CONTRIBUTING.md +3 -3
- data/README.md +4 -0
- data/package.json +3 -3
- data/src/embed.js +20 -5
- data/src/nodes.js +5 -2
- data/src/nodes/alias.js +29 -31
- data/src/nodes/aref.js +26 -26
- data/src/nodes/args.js +56 -28
- data/src/nodes/arrays.js +142 -104
- data/src/nodes/assign.js +30 -30
- data/src/nodes/blocks.js +8 -3
- data/src/nodes/calls.js +108 -53
- data/src/nodes/class.js +74 -0
- data/src/nodes/commands.js +36 -31
- data/src/nodes/conditionals.js +42 -28
- data/src/nodes/constants.js +39 -21
- data/src/nodes/flow.js +11 -1
- data/src/nodes/hashes.js +60 -87
- data/src/nodes/heredocs.js +34 -0
- data/src/nodes/hooks.js +16 -19
- data/src/nodes/ints.js +33 -20
- data/src/nodes/lambdas.js +15 -12
- data/src/nodes/loops.js +6 -2
- data/src/nodes/massign.js +87 -65
- data/src/nodes/methods.js +46 -73
- data/src/nodes/operators.js +66 -46
- data/src/nodes/params.js +12 -14
- data/src/nodes/patterns.js +108 -33
- data/src/nodes/regexp.js +22 -13
- data/src/nodes/rescue.js +72 -59
- data/src/nodes/statements.js +23 -1
- data/src/nodes/strings.js +89 -80
- data/src/nodes/super.js +35 -0
- data/src/nodes/undef.js +42 -0
- data/src/parser.js +71 -0
- data/src/parser.rb +2269 -625
- data/src/printer.js +88 -0
- data/src/ruby.js +4 -20
- data/src/toProc.js +2 -2
- data/src/utils.js +10 -86
- data/src/utils/literalLineNoBreak.js +7 -0
- metadata +9 -5
- data/src/nodes/scopes.js +0 -61
- data/src/parse.js +0 -37
- data/src/print.js +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c098ce338da8191c1a6a46d6817aa38997aa0fbc318dbc045ae191600654d1a0
|
4
|
+
data.tar.gz: d75cc10cf135ffbcbd35f2bb0404dc07b5f645024d57fefdb598cbe99d54bcb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a4c41e7c19215101dee83152d3fd0dab79ee4d43c485254e4f65d963ffbab55e8b68cc5f6a670375552caba832071bfcf609668249139edd81d89a7960274c1
|
7
|
+
data.tar.gz: 655bd92259ffb6346cfd1120b8533dfb0ccf37bc78e7d9ed7041fc14c915abdbe7413a451f9bc9061153721110670603e4a4b5fbc638497033b5c0305a17144b
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
# [0.22.0] - 2020-12-08
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
- [@flyerhzm] - Print method chains by one indentation.
|
14
|
+
- [@mmcnl], [@kddeisz] - Handle heredocs and blocks being passed to the same method.
|
15
|
+
- [@johncsnyder], [@kddeisz] - Ensure correct formatting when breaking up conditionals with `inlineConditionals: false`.
|
16
|
+
- [@Rsullivan00] - Ensure that when ternaries as command arguments get broken into multiple lines we add the necessary parentheses.
|
17
|
+
- [@jbielick] - Maintain parse order during if/unless modifier expressions
|
18
|
+
- [@flyerhzm] - Slight prettifying of wrapped args if doc length is under a certain value.
|
19
|
+
- [@github0013], [@kddeisz] - Ensure `not` keeps parentheses if they are being used.
|
20
|
+
- [@jbielick] - Print heredocs consistently.
|
21
|
+
- [@kddeisz] - Completely revamp the way we handle comments.
|
22
|
+
- [@kddeisz] - Support `hshptn` and the remaining missing pattern matching syntax.
|
23
|
+
|
9
24
|
## [0.21.0] - 2020-12-02
|
10
25
|
|
11
26
|
### Changed
|
@@ -862,7 +877,8 @@ would previously result in `array[]`, but now prints properly.
|
|
862
877
|
|
863
878
|
- Initial release 🎉
|
864
879
|
|
865
|
-
[unreleased]: https://github.com/prettier/plugin-ruby/compare/v0.
|
880
|
+
[unreleased]: https://github.com/prettier/plugin-ruby/compare/v0.22.0...HEAD
|
881
|
+
[0.22.0]: https://github.com/prettier/plugin-ruby/compare/v0.21.0...v0.22.0
|
866
882
|
[0.21.0]: https://github.com/prettier/plugin-ruby/compare/v0.20.1...v0.21.0
|
867
883
|
[0.20.1]: https://github.com/prettier/plugin-ruby/compare/v0.20.0...v0.20.1
|
868
884
|
[0.20.0]: https://github.com/prettier/plugin-ruby/compare/v0.19.1...v0.20.0
|
@@ -964,3 +980,4 @@ would previously result in `array[]`, but now prints properly.
|
|
964
980
|
[@steobrien]: https://github.com/steobrien
|
965
981
|
[@jbielick]: https://github.com/jbielick
|
966
982
|
[@coiti]: https://github.com/coiti
|
983
|
+
[@johncsnyder]: https://github.com/johncsnyder
|
data/CONTRIBUTING.md
CHANGED
@@ -22,7 +22,7 @@ In order to get printed, the code goes through a couple of transformations. The
|
|
22
22
|
|
23
23
|
### Text to AST
|
24
24
|
|
25
|
-
When the prettier process first spins up, it examines which files it's going to print and selects an appropriate plugin for each one. Once selected, it runs that plugin's `parse` function, seen [here](src/
|
25
|
+
When the prettier process first spins up, it examines which files it's going to print and selects an appropriate plugin for each one. Once selected, it runs that plugin's `parse` function, seen [here](src/parser.js). For the case of the Ruby plugin, that entails spawning a Ruby process that runs [parser.rb](src/parser.rb) with the input code preloaded on stdin.
|
26
26
|
|
27
27
|
`parser.rb` will read the text off of stdin and then feed it to a new `Ripper` instance, which is a Ruby standard library recursive-descent parser. Briefly, the way that `Ripper` works is by tokenizing the input and then matching those tokens against a grammar to form s-expressions. To extend `Ripper`, you overwrite the methods that control how those s-expressions are formed, e.g., to modify the s-expression that is formed when `Ripper` encounters a string literal, you would override the `#on_string_literal` method. Below is an example for seeing that in action.
|
28
28
|
|
@@ -71,7 +71,7 @@ Now that the text has been transformed into an AST that we can work with, `parse
|
|
71
71
|
|
72
72
|
### AST to Doc
|
73
73
|
|
74
|
-
Once prettier has a working AST, it will take it and call the selected plugin's [`
|
74
|
+
Once prettier has a working AST, it will take it and call the selected plugin's [`printNode` function](src/printer.js), whose purpose is to convert that AST into prettier's intermediate representation called Docs. It does this by handing the print function a `FastPath` object that keeps track of the state of the printing as it goes, and allows accessing various parts of the AST quickly.
|
75
75
|
|
76
76
|
Effectively, it walks the AST in the reverse direction from the way `Ripper` built it (top-down instead of bottom-up). The first node that gets passed into the `print` function is the `program` node as that's always on top. Then it is the `program` node's responsibility to recursively call print on its child nodes as it best sees fit.
|
77
77
|
|
@@ -168,8 +168,8 @@ While developing, we've built a couple of small utilities for debugging the `pre
|
|
168
168
|
|
169
169
|
- `bin/lex [file|source]` - outputs the tokens as ripper sees them
|
170
170
|
- `bin/sexp [file|source]` - outputs the AST that ripper builds before it gets passed back to `prettier`
|
171
|
+
- `bin/pragma [file]` - runs the `hasPragma` function against the given input file
|
171
172
|
- `bin/print [file|source]` - outputs the printed source of a Ruby file after running it through `prettier`
|
172
|
-
- `bin/has-pragma [file]` - runs the `hasPragma` function against the given input file
|
173
173
|
|
174
174
|
## Testing
|
175
175
|
|
data/README.md
CHANGED
@@ -224,6 +224,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
224
224
|
<td align="center"><a href="https://joshbielick.com/"><img src="https://avatars2.githubusercontent.com/u/1413330?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Josh Bielick</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Ajbielick" title="Bug reports">🐛</a> <a href="https://github.com/prettier/plugin-ruby/commits?author=jbielick" title="Code">💻</a></td>
|
225
225
|
<td align="center"><a href="https://github.com/coiti"><img src="https://avatars3.githubusercontent.com/u/27384706?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Román Coitiño</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Acoiti" title="Bug reports">🐛</a></td>
|
226
226
|
</tr>
|
227
|
+
<tr>
|
228
|
+
<td align="center"><a href="https://github.com/mmcnl"><img src="https://avatars2.githubusercontent.com/u/1498727?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt McNeil</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Ammcnl" title="Bug reports">🐛</a></td>
|
229
|
+
<td align="center"><a href="https://github.com/johncsnyder"><img src="https://avatars2.githubusercontent.com/u/9882099?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Snyder</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Ajohncsnyder" title="Bug reports">🐛</a></td>
|
230
|
+
</tr>
|
227
231
|
</table>
|
228
232
|
|
229
233
|
<!-- markdownlint-restore -->
|
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@prettier/plugin-ruby",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.22.0",
|
4
4
|
"description": "prettier plugin for the Ruby programming language",
|
5
5
|
"main": "src/ruby.js",
|
6
6
|
"scripts": {
|
@@ -24,8 +24,8 @@
|
|
24
24
|
"devDependencies": {
|
25
25
|
"all-contributors-cli": "^6.14.1",
|
26
26
|
"eslint": "^7.8.1",
|
27
|
-
"eslint-config-prettier": "^
|
28
|
-
"husky": "^
|
27
|
+
"eslint-config-prettier": "^7.0.0",
|
28
|
+
"husky": "^5.0.4",
|
29
29
|
"jest": "^26.0.0",
|
30
30
|
"pretty-quick": "^3.0.0"
|
31
31
|
},
|
data/src/embed.js
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
const {
|
2
2
|
concat,
|
3
|
+
group,
|
3
4
|
indent,
|
4
|
-
|
5
|
+
lineSuffix,
|
5
6
|
mapDoc,
|
6
7
|
markAsRoot,
|
7
8
|
stripTrailingHardline
|
8
9
|
} = require("./prettier");
|
9
10
|
|
11
|
+
const { literalLineNoBreak } = require("./utils");
|
12
|
+
|
10
13
|
const parsers = {
|
11
14
|
css: "css",
|
12
15
|
javascript: "babel",
|
@@ -23,7 +26,7 @@ const replaceNewlines = (doc) =>
|
|
23
26
|
? concat(
|
24
27
|
currentDoc
|
25
28
|
.split(/(\n)/g)
|
26
|
-
.map((v, i) => (i % 2 === 0 ? v :
|
29
|
+
.map((v, i) => (i % 2 === 0 ? v : literalLineNoBreak))
|
27
30
|
)
|
28
31
|
: currentDoc
|
29
32
|
);
|
@@ -53,19 +56,31 @@ const embed = (path, _print, textToDoc, _opts) => {
|
|
53
56
|
// into the embedded parser. Get back the doc node.
|
54
57
|
const content = body.map((part) => part.body).join("");
|
55
58
|
const formatted = concat([
|
56
|
-
|
59
|
+
literalLineNoBreak,
|
57
60
|
replaceNewlines(stripTrailingHardline(textToDoc(content, { parser })))
|
58
61
|
]);
|
59
62
|
|
60
63
|
// If we're using a squiggly heredoc, then we can properly handle indentation
|
61
64
|
// ourselves.
|
62
65
|
if (beging[2] === "~") {
|
63
|
-
return concat([
|
66
|
+
return concat([
|
67
|
+
beging,
|
68
|
+
lineSuffix(
|
69
|
+
group(
|
70
|
+
concat([indent(markAsRoot(formatted)), literalLineNoBreak, ending])
|
71
|
+
)
|
72
|
+
)
|
73
|
+
]);
|
64
74
|
}
|
65
75
|
|
66
76
|
// Otherwise, we need to just assume it's formatted correctly and return the
|
67
77
|
// content as it is.
|
68
|
-
return markAsRoot(
|
78
|
+
return markAsRoot(
|
79
|
+
concat([
|
80
|
+
beging,
|
81
|
+
lineSuffix(group(concat([formatted, literalLineNoBreak, ending])))
|
82
|
+
])
|
83
|
+
);
|
69
84
|
};
|
70
85
|
|
71
86
|
module.exports = embed;
|
data/src/nodes.js
CHANGED
@@ -8,11 +8,13 @@ module.exports = Object.assign(
|
|
8
8
|
require("./nodes/blocks"),
|
9
9
|
require("./nodes/calls"),
|
10
10
|
require("./nodes/case"),
|
11
|
+
require("./nodes/class"),
|
11
12
|
require("./nodes/commands"),
|
12
13
|
require("./nodes/conditionals"),
|
13
14
|
require("./nodes/constants"),
|
14
15
|
require("./nodes/flow"),
|
15
16
|
require("./nodes/hashes"),
|
17
|
+
require("./nodes/heredocs"),
|
16
18
|
require("./nodes/hooks"),
|
17
19
|
require("./nodes/ints"),
|
18
20
|
require("./nodes/lambdas"),
|
@@ -25,7 +27,8 @@ module.exports = Object.assign(
|
|
25
27
|
require("./nodes/regexp"),
|
26
28
|
require("./nodes/rescue"),
|
27
29
|
require("./nodes/return"),
|
28
|
-
require("./nodes/scopes"),
|
29
30
|
require("./nodes/statements"),
|
30
|
-
require("./nodes/strings")
|
31
|
+
require("./nodes/strings"),
|
32
|
+
require("./nodes/super"),
|
33
|
+
require("./nodes/undef")
|
31
34
|
);
|
data/src/nodes/alias.js
CHANGED
@@ -7,49 +7,47 @@ const {
|
|
7
7
|
line
|
8
8
|
} = require("../prettier");
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
function printAliasArgument(path, _opts, print, argIndex) {
|
10
|
+
// In general, return the printed doc of the argument at the provided index.
|
11
|
+
// Special handling is given for symbol literals that are not bare words, as we
|
12
|
+
// convert those into bare words by just pulling out the ident node.
|
13
|
+
function printAliasArgument(path, print, argIndex) {
|
15
14
|
const node = path.getValue().body[argIndex];
|
16
15
|
|
17
|
-
if (node.type === "symbol_literal"
|
16
|
+
if (node.type === "symbol_literal") {
|
18
17
|
// If we're going to descend into the symbol literal to grab out the ident
|
19
18
|
// node, then we need to make sure we copy over any comments as well,
|
20
19
|
// otherwise we could accidentally skip printing them.
|
21
20
|
if (node.comments) {
|
22
21
|
node.comments.forEach((comment) => {
|
23
|
-
addTrailingComment(node.body[0]
|
22
|
+
addTrailingComment(node.body[0], comment);
|
24
23
|
});
|
25
24
|
}
|
26
25
|
|
27
|
-
return path.call(print, "body", argIndex, "body", 0
|
26
|
+
return path.call(print, "body", argIndex, "body", 0);
|
28
27
|
}
|
29
28
|
|
30
29
|
return path.call(print, "body", argIndex);
|
31
30
|
}
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
*/
|
32
|
+
// The `alias` keyword is used to make a method respond to another name as well
|
33
|
+
// as the current one. For example, to get the method `foo` to also respond to
|
34
|
+
// `bar`, you would:
|
35
|
+
//
|
36
|
+
// alias bar foo
|
37
|
+
//
|
38
|
+
// Now, in the current context you can call `bar` and it will execute the `foo`
|
39
|
+
// method.
|
40
|
+
//
|
41
|
+
// When you're aliasing two methods, you can either provide bare words (like the
|
42
|
+
// example above) or you can provide symbols (note that this includes dynamic
|
43
|
+
// symbols like :"foo-#{bar}-baz"). In general, to be consistent with the ruby
|
44
|
+
// style guide, we prefer bare words:
|
45
|
+
//
|
46
|
+
// https://github.com/rubocop-hq/ruby-style-guide#alias-method-lexically
|
47
|
+
//
|
48
|
+
// The `alias` node contains two children. The left and right align with the
|
49
|
+
// arguments passed to the keyword. So, for the above example the left would be
|
50
|
+
// the symbol literal `bar` and the right could be the symbol literal `foo`.
|
53
51
|
function printAlias(path, opts, print) {
|
54
52
|
const keyword = "alias ";
|
55
53
|
|
@@ -57,14 +55,14 @@ function printAlias(path, opts, print) {
|
|
57
55
|
// If the left child has any comments, then we need to explicitly break this
|
58
56
|
// into two lines
|
59
57
|
path.getValue().body[0].comments ? hardline : line,
|
60
|
-
printAliasArgument(path,
|
58
|
+
printAliasArgument(path, print, 1)
|
61
59
|
]);
|
62
60
|
|
63
61
|
return group(
|
64
62
|
concat([
|
65
63
|
keyword,
|
66
|
-
printAliasArgument(path,
|
67
|
-
group(align(keyword, rightSide))
|
64
|
+
printAliasArgument(path, print, 0),
|
65
|
+
group(align(keyword.length, rightSide))
|
68
66
|
])
|
69
67
|
);
|
70
68
|
}
|
data/src/nodes/aref.js
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
const { concat, group, indent, join, line, softline } = require("../prettier");
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
// `aref` nodes are when you're pulling a value out of a collection at a
|
4
|
+
// specific index. Put another way, it's any time you're calling the method
|
5
|
+
// `#[]`.
|
6
|
+
//
|
7
|
+
// The nodes usually contains two children, details below in the
|
8
|
+
// `printArefField` function. In some cases, you don't necessarily have the
|
9
|
+
// second child node, because you can call procs with a pretty esoteric syntax.
|
10
|
+
// In the following example, you wouldn't have a second child, and `"foo"` would
|
11
|
+
// be the first child.
|
12
|
+
//
|
13
|
+
// foo[]
|
14
|
+
//
|
15
15
|
function printAref(path, opts, print) {
|
16
16
|
const indexNode = path.getValue().body[1];
|
17
17
|
|
@@ -22,20 +22,20 @@ function printAref(path, opts, print) {
|
|
22
22
|
return printArefField(path, opts, print);
|
23
23
|
}
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
25
|
+
// `aref_field` nodes are for assigning values into collections at specific
|
26
|
+
// indices. Put another way, it's any time you're calling the method `#[]=`.
|
27
|
+
// The `aref_field` node itself is just the left side of the assignment, and
|
28
|
+
// they're always wrapped in `assign` nodes.
|
29
|
+
//
|
30
|
+
// The nodes always contain two children, the name of the array (usually a
|
31
|
+
// `vcall` node and the index (usually an `args_add_block` node). The
|
32
|
+
// `args_add_block` is one of a couple nodes that has special handling where its
|
33
|
+
// printed form is actually an array to make joining easier.
|
34
|
+
//
|
35
|
+
// So in the following example, `"foo"` is the array and `["bar"]` is the index.
|
36
|
+
//
|
37
|
+
// foo[bar] = baz
|
38
|
+
//
|
39
39
|
function printArefField(path, opts, print) {
|
40
40
|
const [printedArray, printedIndex] = path.map(print, "body");
|
41
41
|
|
data/src/nodes/args.js
CHANGED
@@ -9,50 +9,78 @@ const {
|
|
9
9
|
} = require("../prettier");
|
10
10
|
|
11
11
|
const toProc = require("../toProc");
|
12
|
-
const {
|
12
|
+
const { docLength } = require("../utils");
|
13
13
|
|
14
14
|
module.exports = {
|
15
15
|
arg_paren: (path, opts, print) => {
|
16
|
-
|
16
|
+
const argsNode = path.getValue().body[0];
|
17
|
+
const { addTrailingCommas } = opts;
|
18
|
+
|
19
|
+
if (argsNode === null) {
|
17
20
|
return "";
|
18
21
|
}
|
19
22
|
|
20
23
|
// Here we can skip the entire rest of the method by just checking if it's
|
21
24
|
// an args_forward node, as we're guaranteed that there are no other arg
|
22
25
|
// nodes.
|
23
|
-
if (
|
24
|
-
return
|
26
|
+
if (argsNode.type === "args_forward") {
|
27
|
+
return group(
|
28
|
+
concat([
|
29
|
+
"(",
|
30
|
+
indent(concat([softline, path.call(print, "body", 0)])),
|
31
|
+
softline,
|
32
|
+
")"
|
33
|
+
])
|
34
|
+
);
|
25
35
|
}
|
26
36
|
|
27
|
-
const
|
28
|
-
const { args, heredocs } = makeArgs(path, opts, print, 0);
|
29
|
-
|
30
|
-
const argsNode = path.getValue().body[0];
|
37
|
+
const args = path.call(print, "body", 0);
|
31
38
|
const hasBlock = argsNode.type === "args_add_block" && argsNode.body[1];
|
32
39
|
|
33
|
-
|
34
|
-
|
35
|
-
|
40
|
+
// These are the docs representing the actual arguments, without any
|
41
|
+
// parentheses or surrounding lines yet added.
|
42
|
+
let argsDocs = [
|
43
|
+
join(concat([",", line]), args),
|
44
|
+
addTrailingCommas && !hasBlock ? ifBreak(",", "") : ""
|
45
|
+
];
|
36
46
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
// Here we're going to make a determination on whether or not we should put
|
48
|
+
// a newline before the first argument. In some cases this makes the
|
49
|
+
// appearance a little better. For example, instead of taking this input:
|
50
|
+
//
|
51
|
+
// foo(arg1, arg2).bar(arg1, arg2).baz(arg1)
|
52
|
+
//
|
53
|
+
// and transforming it into this:
|
54
|
+
//
|
55
|
+
// foo(arg1, arg2).bar(arg1, arg2).baz(
|
56
|
+
// arg1
|
57
|
+
// )
|
58
|
+
//
|
59
|
+
// it instead gets transformed into this:
|
60
|
+
//
|
61
|
+
// foo(arg1, arg2).bar(arg1, arg2)
|
62
|
+
// .baz(arg1)
|
63
|
+
//
|
64
|
+
const maxDocLength = 15;
|
65
|
+
const firstArgDoc = args[0];
|
66
|
+
|
67
|
+
// prettier-ignore
|
68
|
+
const shouldWrapLine =
|
69
|
+
(args.reduce((sum, arg) => sum + docLength(arg), 0) > maxDocLength) ||
|
70
|
+
(args.length == 1 && firstArgDoc.type === "group" && docLength(firstArgDoc) > maxDocLength) ||
|
71
|
+
(firstArgDoc.type === "concat" && firstArgDoc.parts.some((part) => part.type === "group"));
|
72
|
+
|
73
|
+
// Here we're going to get all of the docs representing the doc that's
|
74
|
+
// inside the parentheses.
|
75
|
+
if (shouldWrapLine) {
|
76
|
+
argsDocs = [indent(concat([softline].concat(argsDocs))), softline];
|
77
|
+
} else {
|
78
|
+
argsDocs = [indent(concat(argsDocs))];
|
53
79
|
}
|
54
80
|
|
55
|
-
return
|
81
|
+
// Now here we return a doc that represents the whole grouped expression,
|
82
|
+
// including the surrouding parentheses.
|
83
|
+
return group(concat(["("].concat(argsDocs).concat(")")));
|
56
84
|
},
|
57
85
|
args: (path, opts, print) => {
|
58
86
|
const args = path.map(print, "body");
|