prettier 0.21.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +112 -7
- data/CONTRIBUTING.md +4 -4
- data/README.md +18 -14
- data/package.json +9 -6
- data/src/embed.js +27 -8
- 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 +55 -47
- data/src/nodes/arrays.js +132 -106
- data/src/nodes/assign.js +32 -32
- data/src/nodes/blocks.js +8 -3
- data/src/nodes/calls.js +163 -60
- data/src/nodes/case.js +11 -7
- data/src/nodes/class.js +74 -0
- data/src/nodes/commands.js +36 -31
- data/src/nodes/conditionals.js +44 -30
- data/src/nodes/constants.js +39 -21
- data/src/nodes/flow.js +11 -1
- data/src/nodes/hashes.js +90 -109
- data/src/nodes/heredocs.js +34 -0
- data/src/nodes/hooks.js +21 -22
- data/src/nodes/ints.js +27 -20
- data/src/nodes/lambdas.js +14 -27
- data/src/nodes/loops.js +10 -5
- data/src/nodes/massign.js +87 -65
- data/src/nodes/methods.js +48 -73
- data/src/nodes/operators.js +70 -39
- data/src/nodes/params.js +26 -16
- data/src/nodes/patterns.js +108 -33
- data/src/nodes/regexp.js +45 -14
- data/src/nodes/rescue.js +72 -59
- data/src/nodes/statements.js +86 -44
- data/src/nodes/strings.js +95 -85
- data/src/nodes/super.js +35 -0
- data/src/nodes/undef.js +42 -0
- data/src/parser.js +86 -0
- data/src/parser.rb +2400 -621
- data/src/printer.js +90 -0
- data/src/ruby.js +19 -41
- data/src/toProc.js +4 -4
- data/src/utils.js +24 -88
- data/src/utils/literalLineNoBreak.js +7 -0
- data/src/utils/printEmptyCollection.js +42 -0
- metadata +12 -49
- data/src/nodes/scopes.js +0 -61
- data/src/parse.js +0 -37
- data/src/print.js +0 -23
data/src/nodes/assign.js
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
const { concat, group, indent, join, line } = require("../prettier");
|
2
|
-
const {
|
2
|
+
const { first, skipAssignIndent } = require("../utils");
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
function printAssign(path, opts, print) {
|
5
|
+
const [_targetNode, valueNode] = path.getValue().body;
|
6
|
+
const [targetDoc, valueDoc] = path.map(print, "body");
|
7
|
+
|
8
|
+
let rightSideDoc = valueDoc;
|
9
|
+
|
10
|
+
// If the right side of this assignment is a multiple assignment, then we need
|
11
|
+
// to join it together with commas.
|
12
|
+
if (["mrhs_add_star", "mrhs_new_from_args"].includes(valueNode.type)) {
|
13
|
+
rightSideDoc = group(join(concat([",", line]), valueDoc));
|
14
|
+
}
|
8
15
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
)
|
13
|
-
) {
|
14
|
-
adjustedValue = group(join(concat([",", line]), printedValue));
|
15
|
-
}
|
16
|
+
if (skipAssignIndent(valueNode)) {
|
17
|
+
return group(concat([targetDoc, " = ", rightSideDoc]));
|
18
|
+
}
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
}
|
20
|
+
return group(concat([targetDoc, " =", indent(concat([line, rightSideDoc]))]));
|
21
|
+
}
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
),
|
37
|
-
var_field: concatBody,
|
23
|
+
function printOpAssign(path, opts, print) {
|
24
|
+
return group(
|
25
|
+
concat([
|
26
|
+
path.call(print, "body", 0),
|
27
|
+
" ",
|
28
|
+
path.call(print, "body", 1),
|
29
|
+
indent(concat([line, path.call(print, "body", 2)]))
|
30
|
+
])
|
31
|
+
);
|
32
|
+
}
|
33
|
+
|
34
|
+
module.exports = {
|
35
|
+
assign: printAssign,
|
36
|
+
opassign: printOpAssign,
|
37
|
+
var_field: first,
|
38
38
|
var_ref: first
|
39
39
|
};
|
data/src/nodes/blocks.js
CHANGED
@@ -16,7 +16,11 @@ const printBlock = (braces) => (path, opts, print) => {
|
|
16
16
|
statements.type === "stmts" ? statements.body : statements.body[0].body;
|
17
17
|
|
18
18
|
let doBlockBody = "";
|
19
|
-
if (
|
19
|
+
if (
|
20
|
+
stmts.length !== 1 ||
|
21
|
+
stmts[0].type !== "void_stmt" ||
|
22
|
+
stmts[0].comments
|
23
|
+
) {
|
20
24
|
doBlockBody = indent(concat([softline, path.call(print, "body", 1)]));
|
21
25
|
}
|
22
26
|
|
@@ -37,8 +41,9 @@ const printBlock = (braces) => (path, opts, print) => {
|
|
37
41
|
// We can hit this next pattern if within the block the only statement is a
|
38
42
|
// comment.
|
39
43
|
if (
|
40
|
-
stmts.length
|
41
|
-
stmts.
|
44
|
+
stmts.length === 1 &&
|
45
|
+
stmts[0].type === "void_stmt" &&
|
46
|
+
stmts[0].comments
|
42
47
|
) {
|
43
48
|
return concat([breakParent, doBlock]);
|
44
49
|
}
|
data/src/nodes/calls.js
CHANGED
@@ -1,69 +1,146 @@
|
|
1
|
-
const {
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
hardline,
|
5
|
+
ifBreak,
|
6
|
+
indent,
|
7
|
+
softline
|
8
|
+
} = require("../prettier");
|
9
|
+
const { first, makeCall, noIndent } = require("../utils");
|
10
|
+
|
2
11
|
const toProc = require("../toProc");
|
3
|
-
const { concatBody, first, makeCall } = require("../utils");
|
4
12
|
|
5
|
-
const
|
13
|
+
const chained = ["call", "method_add_arg", "method_add_block"];
|
6
14
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
const printedReceiver = path.call(print, "body", 0);
|
12
|
-
const printedOperator = makeCall(path, opts, print);
|
13
|
-
|
14
|
-
// You can call lambdas with a special syntax that looks like func.(*args).
|
15
|
-
// In this case, "call" is returned for the 3rd child node.
|
16
|
-
const printedMessage =
|
17
|
-
messageNode === "call" ? messageNode : path.call(print, "body", 2);
|
18
|
-
|
19
|
-
// If we have a heredoc as a receiver, then we need to move the operator and
|
20
|
-
// the message up to start of the heredoc declaration, as in:
|
21
|
-
//
|
22
|
-
// <<~TEXT.strip
|
23
|
-
// content
|
24
|
-
// TEXT
|
25
|
-
if (receiverNode.type === "heredoc") {
|
26
|
-
return concat([
|
27
|
-
receiverNode.beging,
|
28
|
-
printedOperator,
|
29
|
-
printedMessage,
|
30
|
-
literalline,
|
31
|
-
concat(path.map(print, "body", 0, "body")),
|
32
|
-
receiverNode.ending
|
33
|
-
]);
|
34
|
-
}
|
15
|
+
function printCall(path, opts, print) {
|
16
|
+
const node = path.getValue();
|
17
|
+
const [receiverNode, _operatorNode, messageNode] = node.body;
|
35
18
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
19
|
+
const receiverDoc = path.call(print, "body", 0);
|
20
|
+
const operatorDoc = makeCall(path, opts, print);
|
21
|
+
|
22
|
+
// You can call lambdas with a special syntax that looks like func.(*args).
|
23
|
+
// In this case, "call" is returned for the 3rd child node. We don't alter
|
24
|
+
// call syntax so if `call` is implicit, we don't print it out.
|
25
|
+
const messageDoc = messageNode === "call" ? "" : path.call(print, "body", 2);
|
26
|
+
|
27
|
+
// The right side of the call node, as in everything including the operator
|
28
|
+
// and beyond.
|
29
|
+
const rightSideDoc = concat([
|
30
|
+
receiverNode.comments ? hardline : softline,
|
31
|
+
operatorDoc,
|
32
|
+
messageDoc
|
33
|
+
]);
|
34
|
+
|
35
|
+
// Get a reference to the parent node so we can check if we're inside a chain
|
36
|
+
const parentNode = path.getParentNode();
|
37
|
+
|
38
|
+
// If our parent node is a chained node then we're not going to group the
|
39
|
+
// right side of the expression, as we want to have a nice multi-line layout.
|
40
|
+
if (chained.includes(parentNode.type)) {
|
41
|
+
parentNode.chain = (node.chain || 0) + 1;
|
42
|
+
parentNode.breakDoc = (node.breakDoc || [receiverDoc]).concat(rightSideDoc);
|
43
|
+
}
|
41
44
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
// If we're at the top of a chain, then we're going to print out a nice
|
46
|
+
// multi-line layout if this doesn't break into multiple lines.
|
47
|
+
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
|
48
|
+
return ifBreak(
|
49
|
+
group(indent(concat(node.breakDoc.concat(rightSideDoc)))),
|
50
|
+
concat([receiverDoc, group(rightSideDoc)])
|
47
51
|
);
|
48
|
-
}
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
}
|
53
|
+
|
54
|
+
// For certain left sides of the call nodes, we want to attach directly to
|
55
|
+
// the } or end.
|
56
|
+
if (noIndent.includes(receiverNode.type)) {
|
57
|
+
return concat([receiverDoc, operatorDoc, messageDoc]);
|
58
|
+
}
|
59
|
+
|
60
|
+
return group(concat([receiverDoc, group(indent(rightSideDoc))]));
|
61
|
+
}
|
62
|
+
|
63
|
+
function printMethodAddArg(path, opts, print) {
|
64
|
+
const node = path.getValue();
|
65
|
+
const argNode = node.body[1];
|
66
|
+
|
67
|
+
const [methodDoc, argsDoc] = path.map(print, "body");
|
68
|
+
|
69
|
+
// You can end up here if you have a method with a ? ending, presumably
|
70
|
+
// because the parser knows that it cannot be a local variable.
|
71
|
+
if (argsDoc.length === 0) {
|
72
|
+
return methodDoc;
|
73
|
+
}
|
74
|
+
|
75
|
+
// This case will ONLY be hit if we can successfully turn the block into a
|
76
|
+
// to_proc call. In that case, we just explicitly add the parens around it.
|
77
|
+
if (argNode.type === "args" && argsDoc.length > 0) {
|
78
|
+
return concat([methodDoc, "("].concat(argsDoc).concat(")"));
|
79
|
+
}
|
80
|
+
|
81
|
+
// Get a reference to the parent node so we can check if we're inside a chain
|
82
|
+
const parentNode = path.getParentNode();
|
59
83
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
84
|
+
// If our parent node is a chained node then we're not going to group the
|
85
|
+
// right side of the expression, as we want to have a nice multi-line layout.
|
86
|
+
if (chained.includes(parentNode.type)) {
|
87
|
+
parentNode.chain = (node.chain || 0) + 1;
|
88
|
+
parentNode.breakDoc = (node.breakDoc || [methodDoc]).concat(argsDoc);
|
89
|
+
}
|
65
90
|
|
66
|
-
|
91
|
+
// If we're at the top of a chain, then we're going to print out a nice
|
92
|
+
// multi-line layout if this doesn't break into multiple lines.
|
93
|
+
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
|
94
|
+
return ifBreak(
|
95
|
+
group(indent(concat(node.breakDoc.concat(argsDoc)))),
|
96
|
+
concat([methodDoc, argsDoc])
|
97
|
+
);
|
98
|
+
}
|
99
|
+
|
100
|
+
return concat([methodDoc, argsDoc]);
|
101
|
+
}
|
102
|
+
|
103
|
+
// Sorbet type annotations look like the following:
|
104
|
+
//
|
105
|
+
// {method_add_block
|
106
|
+
// [{method_add_arg
|
107
|
+
// [{fcall
|
108
|
+
// [{@ident "sig"}]},
|
109
|
+
// {args []}]},
|
110
|
+
// {brace_block [nil, {stmts}]}}]}
|
111
|
+
//
|
112
|
+
function isSorbetTypeAnnotation(node) {
|
113
|
+
const [callNode, blockNode] = node.body;
|
114
|
+
|
115
|
+
return (
|
116
|
+
callNode.type === "method_add_arg" &&
|
117
|
+
callNode.body[0].type === "fcall" &&
|
118
|
+
callNode.body[0].body[0].body === "sig" &&
|
119
|
+
callNode.body[1].type === "args" &&
|
120
|
+
callNode.body[1].body.length === 0 &&
|
121
|
+
blockNode.type === "brace_block"
|
122
|
+
);
|
123
|
+
}
|
124
|
+
|
125
|
+
function printMethodAddBlock(path, opts, print) {
|
126
|
+
const node = path.getValue();
|
127
|
+
|
128
|
+
const [callNode, blockNode] = node.body;
|
129
|
+
const [callDoc, blockDoc] = path.map(print, "body");
|
130
|
+
|
131
|
+
// Very special handling here for sorbet type annotations. They look like Ruby
|
132
|
+
// code, but they're not actually Ruby code, so we're not going to mess with
|
133
|
+
// them at all.
|
134
|
+
if (isSorbetTypeAnnotation(node)) {
|
135
|
+
return opts.originalText.slice(opts.locStart(node), opts.locEnd(node));
|
136
|
+
}
|
137
|
+
|
138
|
+
// Don't bother trying to do any kind of fancy toProc transform if the option
|
139
|
+
// is disabled.
|
140
|
+
if (opts.rubyToProc) {
|
141
|
+
const proc = toProc(path, blockNode);
|
142
|
+
|
143
|
+
if (proc && callNode.type === "call") {
|
67
144
|
return group(
|
68
145
|
concat([
|
69
146
|
path.call(print, "body", 0),
|
@@ -77,8 +154,34 @@ module.exports = {
|
|
77
154
|
if (proc) {
|
78
155
|
return path.call(print, "body", 0);
|
79
156
|
}
|
157
|
+
}
|
158
|
+
|
159
|
+
// Get a reference to the parent node so we can check if we're inside a chain
|
160
|
+
const parentNode = path.getParentNode();
|
80
161
|
|
81
|
-
|
82
|
-
|
162
|
+
// If our parent node is a chained node then we're not going to group the
|
163
|
+
// right side of the expression, as we want to have a nice multi-line layout.
|
164
|
+
if (chained.includes(parentNode.type)) {
|
165
|
+
parentNode.chain = (node.chain || 0) + 1;
|
166
|
+
parentNode.breakDoc = (node.breakDoc || [callDoc]).concat(blockDoc);
|
167
|
+
}
|
168
|
+
|
169
|
+
// If we're at the top of a chain, then we're going to print out a nice
|
170
|
+
// multi-line layout if this doesn't break into multiple lines.
|
171
|
+
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
|
172
|
+
return ifBreak(
|
173
|
+
group(indent(concat(node.breakDoc.concat(blockDoc)))),
|
174
|
+
concat([callDoc, blockDoc])
|
175
|
+
);
|
176
|
+
}
|
177
|
+
|
178
|
+
return concat([callDoc, blockDoc]);
|
179
|
+
}
|
180
|
+
|
181
|
+
module.exports = {
|
182
|
+
call: printCall,
|
183
|
+
fcall: first,
|
184
|
+
method_add_arg: printMethodAddArg,
|
185
|
+
method_add_block: printMethodAddBlock,
|
83
186
|
vcall: first
|
84
187
|
};
|
data/src/nodes/case.js
CHANGED
@@ -28,13 +28,17 @@ module.exports = {
|
|
28
28
|
// The `fill` builder command expects an array of docs alternating with
|
29
29
|
// line breaks. This is so it can loop through and determine where to break.
|
30
30
|
const preds = fill(
|
31
|
-
path
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
path.call(print, "body", 0).reduce((accum, pred, index) => {
|
32
|
+
if (index === 0) {
|
33
|
+
return [pred];
|
34
|
+
}
|
35
|
+
|
36
|
+
// Pull off the last element and make it concat with a comma so that
|
37
|
+
// we can maintain alternating lines and docs.
|
38
|
+
return accum
|
39
|
+
.slice(0, -1)
|
40
|
+
.concat([concat([accum[accum.length - 1], ","]), line, pred]);
|
41
|
+
}, null)
|
38
42
|
);
|
39
43
|
|
40
44
|
const stmts = path.call(print, "body", 1);
|
data/src/nodes/class.js
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
hardline,
|
5
|
+
ifBreak,
|
6
|
+
indent,
|
7
|
+
line
|
8
|
+
} = require("../prettier");
|
9
|
+
|
10
|
+
function printClass(path, opts, print) {
|
11
|
+
const [_constant, superclass, bodystmt] = path.getValue().body;
|
12
|
+
const stmts = bodystmt.body[0];
|
13
|
+
|
14
|
+
const parts = ["class ", path.call(print, "body", 0)];
|
15
|
+
if (superclass) {
|
16
|
+
parts.push(" < ", path.call(print, "body", 1));
|
17
|
+
}
|
18
|
+
|
19
|
+
// If the body is empty and does not contain any comments, we can just
|
20
|
+
// replace the body with a semi-colon.
|
21
|
+
if (
|
22
|
+
stmts.body.length === 1 &&
|
23
|
+
stmts.body[0].type === "void_stmt" &&
|
24
|
+
!stmts.body[0].comments
|
25
|
+
) {
|
26
|
+
return group(concat([concat(parts), ifBreak(line, "; "), "end"]));
|
27
|
+
}
|
28
|
+
|
29
|
+
return group(
|
30
|
+
concat([
|
31
|
+
concat(parts),
|
32
|
+
indent(concat([hardline, path.call(print, "body", 2)])),
|
33
|
+
concat([hardline, "end"])
|
34
|
+
])
|
35
|
+
);
|
36
|
+
}
|
37
|
+
|
38
|
+
function printModule(path, opts, print) {
|
39
|
+
const declaration = group(concat(["module ", path.call(print, "body", 0)]));
|
40
|
+
|
41
|
+
// If the body is empty, we can replace with a ;
|
42
|
+
const stmts = path.getValue().body[1].body[0];
|
43
|
+
if (
|
44
|
+
stmts.body.length === 1 &&
|
45
|
+
stmts.body[0].type === "void_stmt" &&
|
46
|
+
!stmts.body[0].comments
|
47
|
+
) {
|
48
|
+
return group(concat([declaration, ifBreak(line, "; "), "end"]));
|
49
|
+
}
|
50
|
+
|
51
|
+
return group(
|
52
|
+
concat([
|
53
|
+
declaration,
|
54
|
+
indent(concat([hardline, path.call(print, "body", 1)])),
|
55
|
+
concat([hardline, "end"])
|
56
|
+
])
|
57
|
+
);
|
58
|
+
}
|
59
|
+
|
60
|
+
function printSClass(path, opts, print) {
|
61
|
+
return group(
|
62
|
+
concat([
|
63
|
+
concat(["class << ", path.call(print, "body", 0)]),
|
64
|
+
indent(concat([hardline, path.call(print, "body", 1)])),
|
65
|
+
concat([hardline, "end"])
|
66
|
+
])
|
67
|
+
);
|
68
|
+
}
|
69
|
+
|
70
|
+
module.exports = {
|
71
|
+
class: printClass,
|
72
|
+
module: printModule,
|
73
|
+
sclass: printSClass
|
74
|
+
};
|
data/src/nodes/commands.js
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
-
const {
|
2
|
-
|
1
|
+
const {
|
2
|
+
align,
|
3
|
+
concat,
|
4
|
+
group,
|
5
|
+
ifBreak,
|
6
|
+
indent,
|
7
|
+
join,
|
8
|
+
line,
|
9
|
+
softline
|
10
|
+
} = require("../prettier");
|
11
|
+
const { docLength, makeCall } = require("../utils");
|
3
12
|
|
4
13
|
const hasDef = (node) =>
|
5
14
|
node.body[1].type === "args_add_block" &&
|
@@ -23,32 +32,39 @@ const hasDef = (node) =>
|
|
23
32
|
const skipArgsAlign = (path) =>
|
24
33
|
["to", "not_to"].includes(path.getValue().body[2].body);
|
25
34
|
|
35
|
+
// If there is a ternary argument to a command and it's going to get broken
|
36
|
+
// into multiple lines, then we're going to have to use parentheses around the
|
37
|
+
// command in order to make sure operator precedence doesn't get messed up.
|
38
|
+
const hasTernaryArg = (path) =>
|
39
|
+
path.getValue().body[1].body[0].body.some((node) => node.type === "ifop");
|
40
|
+
|
26
41
|
module.exports = {
|
27
42
|
command: (path, opts, print) => {
|
28
43
|
const command = path.call(print, "body", 0);
|
29
|
-
const
|
44
|
+
const joinedArgs = join(concat([",", line]), path.call(print, "body", 1));
|
30
45
|
|
31
|
-
|
32
|
-
|
33
|
-
}
|
46
|
+
const hasTernary = hasTernaryArg(path);
|
47
|
+
let breakArgs;
|
34
48
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
49
|
+
if (hasTernary) {
|
50
|
+
breakArgs = indent(concat([softline, joinedArgs]));
|
51
|
+
} else if (hasDef(path.getValue())) {
|
52
|
+
breakArgs = joinedArgs;
|
53
|
+
} else {
|
54
|
+
breakArgs = align(command.length + 1, joinedArgs);
|
55
|
+
}
|
39
56
|
|
40
|
-
|
57
|
+
return group(
|
41
58
|
ifBreak(
|
42
|
-
concat([
|
59
|
+
concat([
|
60
|
+
command,
|
61
|
+
hasTernary ? "(" : " ",
|
62
|
+
breakArgs,
|
63
|
+
hasTernary ? concat([softline, ")"]) : ""
|
64
|
+
]),
|
43
65
|
concat([command, " ", joinedArgs])
|
44
66
|
)
|
45
67
|
);
|
46
|
-
|
47
|
-
if (heredocs.length === 1) {
|
48
|
-
return group(concat([commandDoc].concat(heredocs)));
|
49
|
-
}
|
50
|
-
|
51
|
-
return commandDoc;
|
52
68
|
},
|
53
69
|
command_call: (path, opts, print) => {
|
54
70
|
const parts = [
|
@@ -62,25 +78,14 @@ module.exports = {
|
|
62
78
|
}
|
63
79
|
|
64
80
|
parts.push(" ");
|
65
|
-
const { args, heredocs } = makeArgs(path, opts, print, 3);
|
66
|
-
|
67
|
-
if (heredocs.length > 1) {
|
68
|
-
return concat(parts.concat([join(", ", args)]).concat(heredocs));
|
69
|
-
}
|
70
81
|
|
71
|
-
const joinedArgs = join(concat([",", line]),
|
82
|
+
const joinedArgs = join(concat([",", line]), path.call(print, "body", 3));
|
72
83
|
const breakArgs = skipArgsAlign(path)
|
73
84
|
? joinedArgs
|
74
85
|
: align(docLength(concat(parts)), joinedArgs);
|
75
86
|
|
76
|
-
|
87
|
+
return group(
|
77
88
|
ifBreak(concat(parts.concat(breakArgs)), concat(parts.concat(joinedArgs)))
|
78
89
|
);
|
79
|
-
|
80
|
-
if (heredocs.length === 1) {
|
81
|
-
return group(concat([commandDoc].concat(heredocs)));
|
82
|
-
}
|
83
|
-
|
84
|
-
return commandDoc;
|
85
90
|
}
|
86
91
|
};
|