prettier 0.21.0 → 0.22.0
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 +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
data/src/nodes/arrays.js
CHANGED
@@ -1,40 +1,72 @@
|
|
1
1
|
const {
|
2
2
|
concat,
|
3
3
|
group,
|
4
|
+
hardline,
|
4
5
|
ifBreak,
|
5
6
|
indent,
|
6
7
|
join,
|
7
8
|
line,
|
8
|
-
literalline,
|
9
9
|
softline
|
10
10
|
} = require("../prettier");
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
// Checks that every argument within this args node is a string_literal node
|
13
|
+
// that has no spaces or interpolations. This means we're dealing with an array
|
14
|
+
// that looks something like:
|
15
|
+
//
|
16
|
+
// ['a', 'b', 'c']
|
17
|
+
//
|
18
|
+
function isStringArray(args) {
|
19
|
+
return args.body.every((arg) => {
|
20
|
+
// We want to verify that every node inside of this array is a string
|
21
|
+
// literal. We also want to make sure none of them have comments attached.
|
22
|
+
if (arg.type !== "string_literal" || arg.comments) {
|
23
|
+
return false;
|
24
|
+
}
|
25
|
+
|
26
|
+
// If the string has multiple parts (meaning plain string content but also
|
27
|
+
// interpolated content) then we know it's not a simple string.
|
28
|
+
if (arg.body.length !== 1) {
|
29
|
+
return false;
|
30
|
+
}
|
24
31
|
|
25
|
-
const
|
26
|
-
args.body.every((arg) => arg.type === "symbol_literal");
|
32
|
+
const part = arg.body[0];
|
27
33
|
|
28
|
-
|
29
|
-
|
34
|
+
// If the only part of this string is not @tstring_content then it's
|
35
|
+
// interpolated, so again we can return false.
|
36
|
+
if (part.type !== "@tstring_content") {
|
37
|
+
return false;
|
38
|
+
}
|
30
39
|
|
31
|
-
|
32
|
-
|
33
|
-
|
40
|
+
// Finally, verify that the string doesn't contain a space or an escape
|
41
|
+
// character so that we know it can be put into a string literal array.
|
42
|
+
return !part.body.includes(" ") && !part.body.includes("\\");
|
43
|
+
});
|
44
|
+
}
|
45
|
+
|
46
|
+
// Checks that every argument within this args node is a symbol_literal node (as
|
47
|
+
// opposed to a dyna_symbol) so it has no interpolation. This means we're
|
48
|
+
// dealing with an array that looks something like:
|
49
|
+
//
|
50
|
+
// [:a, :b, :c]
|
51
|
+
//
|
52
|
+
function isSymbolArray(args) {
|
53
|
+
return args.body.every(
|
54
|
+
(arg) => arg.type === "symbol_literal" && !arg.comments
|
34
55
|
);
|
35
|
-
|
36
|
-
|
37
|
-
|
56
|
+
}
|
57
|
+
|
58
|
+
// Prints out a word that is a part of a special array literal that accepts
|
59
|
+
// interpolation. The body is an array of either plain strings or interpolated
|
60
|
+
// expressions.
|
61
|
+
function printSpecialArrayWord(path, opts, print) {
|
62
|
+
return concat(path.map(print, "body"));
|
63
|
+
}
|
64
|
+
|
65
|
+
// Prints out a special array literal. Accepts the parts of the array literal as
|
66
|
+
// an argument, where the first element of the parts array is a string that
|
67
|
+
// contains the special start.
|
68
|
+
function printSpecialArrayParts(parts) {
|
69
|
+
return group(
|
38
70
|
concat([
|
39
71
|
parts[0],
|
40
72
|
"[",
|
@@ -42,93 +74,99 @@ const printSpecialArray = (parts) =>
|
|
42
74
|
concat([softline, "]"])
|
43
75
|
])
|
44
76
|
);
|
45
|
-
|
46
|
-
|
47
|
-
//
|
48
|
-
//
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
77
|
+
}
|
78
|
+
|
79
|
+
// Generates a print function with an embedded special start character for the
|
80
|
+
// specific type of array literal that we're dealing with. The print function
|
81
|
+
// returns an array as it expects to eventually be handed off to
|
82
|
+
// printSpecialArrayParts.
|
83
|
+
function printSpecialArray(start) {
|
84
|
+
return function printSpecialArrayWithStart(path, opts, print) {
|
85
|
+
return [start].concat(path.map(print, "body"));
|
86
|
+
};
|
87
|
+
}
|
88
|
+
|
89
|
+
function printEmptyArrayWithComments(path, opts) {
|
90
|
+
const arrayNode = path.getValue();
|
91
|
+
|
92
|
+
const printComment = (commentPath, index) => {
|
93
|
+
arrayNode.comments[index].printed = true;
|
94
|
+
return opts.printer.printComment(commentPath);
|
95
|
+
};
|
96
|
+
|
97
|
+
return concat([
|
98
|
+
"[",
|
99
|
+
indent(
|
100
|
+
concat([hardline, join(hardline, path.map(printComment, "comments"))])
|
101
|
+
),
|
102
|
+
line,
|
103
|
+
"]"
|
104
|
+
]);
|
105
|
+
}
|
106
|
+
|
107
|
+
// An array node is any literal array in Ruby. This includes all of the special
|
108
|
+
// array literals as well as regular arrays. If it is a special array literal
|
109
|
+
// then it will have one child that represents the special array, otherwise it
|
110
|
+
// will have one child that contains all of the elements of the array.
|
111
|
+
function printArray(path, opts, print) {
|
112
|
+
const array = path.getValue();
|
113
|
+
const args = array.body[0];
|
114
|
+
|
115
|
+
// If there is no inner arguments node, then we're dealing with an empty
|
116
|
+
// array, so we can go ahead and return.
|
117
|
+
if (args === null) {
|
118
|
+
return array.comments ? printEmptyArrayWithComments(path, opts) : "[]";
|
55
119
|
}
|
56
120
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
);
|
63
|
-
};
|
121
|
+
// If we have an array that contains only simple string literals with no
|
122
|
+
// spaces or interpolation, then we're going to print a %w array.
|
123
|
+
if (isStringArray(args)) {
|
124
|
+
const printString = (stringPath) => stringPath.call(print, "body", 0);
|
125
|
+
const parts = path.map(printString, "body", 0, "body");
|
64
126
|
|
65
|
-
|
66
|
-
|
67
|
-
const args = path.getValue().body[0];
|
127
|
+
return printSpecialArrayParts(["%w"].concat(parts));
|
128
|
+
}
|
68
129
|
|
69
|
-
|
70
|
-
|
71
|
-
|
130
|
+
// If we have an array that contains only simple symbol literals with no
|
131
|
+
// interpolation, then we're going to print a %i array.
|
132
|
+
if (isSymbolArray(args)) {
|
133
|
+
const printSymbol = (symbolPath) => symbolPath.call(print, "body", 0);
|
134
|
+
const parts = path.map(printSymbol, "body", 0, "body");
|
72
135
|
|
73
|
-
|
74
|
-
|
75
|
-
["%w"].concat(getSpecialArrayParts(path, print, args))
|
76
|
-
);
|
77
|
-
}
|
136
|
+
return printSpecialArrayParts(["%i"].concat(parts));
|
137
|
+
}
|
78
138
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
139
|
+
// If we don't have a regular args node at this point then we have a special
|
140
|
+
// array literal. In that case we're going to print out the body (which will
|
141
|
+
// return to us an array with the first one being the start of the array) and
|
142
|
+
// send that over to the printSpecialArrayParts function.
|
143
|
+
if (!["args", "args_add_star"].includes(args.type)) {
|
144
|
+
return printSpecialArrayParts(path.call(print, "body", 0));
|
145
|
+
}
|
84
146
|
|
85
|
-
|
86
|
-
|
87
|
-
|
147
|
+
// Here we have a normal array of any type of object with no special literal
|
148
|
+
// types or anything.
|
149
|
+
return group(
|
150
|
+
concat([
|
151
|
+
"[",
|
152
|
+
indent(
|
153
|
+
concat([
|
154
|
+
softline,
|
155
|
+
join(concat([",", line]), path.call(print, "body", 0)),
|
156
|
+
opts.addTrailingCommas ? ifBreak(",", "") : ""
|
157
|
+
])
|
158
|
+
),
|
159
|
+
softline,
|
160
|
+
"]"
|
161
|
+
])
|
162
|
+
);
|
163
|
+
}
|
88
164
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
// opposed to at the end).
|
97
|
-
elements.forEach(({ element, elementPath }, index) => {
|
98
|
-
const isInner = index !== elements.length - 1;
|
99
|
-
|
100
|
-
if (element.type === "heredoc") {
|
101
|
-
normalDocs.push(
|
102
|
-
element.beging,
|
103
|
-
isInner || addTrailingCommas ? "," : "",
|
104
|
-
literalline,
|
105
|
-
concat(
|
106
|
-
path.map.apply(path, [print].concat(elementPath).concat("body"))
|
107
|
-
),
|
108
|
-
element.ending,
|
109
|
-
isInner ? line : ""
|
110
|
-
);
|
111
|
-
} else {
|
112
|
-
normalDocs.push(elementDocs[index]);
|
113
|
-
|
114
|
-
if (isInner) {
|
115
|
-
normalDocs.push(concat([",", line]));
|
116
|
-
} else if (addTrailingCommas) {
|
117
|
-
normalDocs.push(ifBreak(",", ""));
|
118
|
-
}
|
119
|
-
}
|
120
|
-
});
|
121
|
-
|
122
|
-
return group(
|
123
|
-
concat([
|
124
|
-
"[",
|
125
|
-
indent(concat([softline].concat(normalDocs))),
|
126
|
-
concat([softline, "]"])
|
127
|
-
])
|
128
|
-
);
|
129
|
-
},
|
130
|
-
qsymbols: makeArray("%i"),
|
131
|
-
qwords: makeArray("%w"),
|
132
|
-
symbols: makeArray("%I"),
|
133
|
-
words: makeArray("%W")
|
165
|
+
module.exports = {
|
166
|
+
array: printArray,
|
167
|
+
qsymbols: printSpecialArray("%i"),
|
168
|
+
qwords: printSpecialArray("%w"),
|
169
|
+
symbols: printSpecialArray("%I"),
|
170
|
+
word: printSpecialArrayWord,
|
171
|
+
words: printSpecialArray("%W")
|
134
172
|
};
|
data/src/nodes/assign.js
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
const { concat, group, indent, join, line } = require("../prettier");
|
2
2
|
const { concatBody, 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
|
-
),
|
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
37
|
var_field: concatBody,
|
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,64 +1,119 @@
|
|
1
|
-
const {
|
2
|
-
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
hardline,
|
5
|
+
ifBreak,
|
6
|
+
indent,
|
7
|
+
softline
|
8
|
+
} = require("../prettier");
|
3
9
|
const { concatBody, first, makeCall } = require("../utils");
|
4
10
|
|
11
|
+
const toProc = require("../toProc");
|
12
|
+
|
13
|
+
const chained = ["call", "method_add_arg"];
|
5
14
|
const noIndent = ["array", "hash", "if", "method_add_block", "xstring_literal"];
|
6
15
|
|
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
|
-
}
|
16
|
+
function printCall(path, opts, print) {
|
17
|
+
const callNode = path.getValue();
|
18
|
+
const [receiverNode, _operatorNode, messageNode] = callNode.body;
|
35
19
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
20
|
+
const receiverDoc = path.call(print, "body", 0);
|
21
|
+
const operatorDoc = makeCall(path, opts, print);
|
22
|
+
|
23
|
+
// You can call lambdas with a special syntax that looks like func.(*args).
|
24
|
+
// In this case, "call" is returned for the 3rd child node.
|
25
|
+
const messageDoc =
|
26
|
+
messageNode === "call" ? messageNode : path.call(print, "body", 2);
|
27
|
+
|
28
|
+
// For certain left sides of the call nodes, we want to attach directly to
|
29
|
+
// the } or end.
|
30
|
+
if (noIndent.includes(receiverNode.type)) {
|
31
|
+
return concat([receiverDoc, operatorDoc, messageDoc]);
|
32
|
+
}
|
41
33
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
34
|
+
// The right side of the call node, as in everything including the operator
|
35
|
+
// and beyond.
|
36
|
+
const rightSideDoc = indent(
|
37
|
+
concat([
|
38
|
+
receiverNode.comments ? hardline : softline,
|
39
|
+
operatorDoc,
|
40
|
+
messageDoc
|
41
|
+
])
|
42
|
+
);
|
43
|
+
|
44
|
+
// Get a reference to the parent node so we can check if we're inside a chain
|
45
|
+
const parentNode = path.getParentNode();
|
46
|
+
|
47
|
+
// If our parent node is a chained node then we're not going to group the
|
48
|
+
// right side of the expression, as we want to have a nice multi-line layout.
|
49
|
+
if (chained.includes(parentNode.type)) {
|
50
|
+
parentNode.chain = (callNode.chain || 0) + 1;
|
51
|
+
parentNode.breakDoc = (callNode.breakDoc || [receiverDoc]).concat(
|
52
|
+
rightSideDoc
|
47
53
|
);
|
48
|
-
}
|
49
|
-
fcall: concatBody,
|
50
|
-
method_add_arg: (path, opts, print) => {
|
51
|
-
const [method, args] = path.map(print, "body");
|
52
|
-
const argNode = path.getValue().body[1];
|
53
|
-
|
54
|
-
// This case will ONLY be hit if we can successfully turn the block into a
|
55
|
-
// to_proc call. In that case, we just explicitly add the parens around it.
|
56
|
-
if (argNode.type === "args" && args.length > 0) {
|
57
|
-
return concat([method, "("].concat(args).concat(")"));
|
58
|
-
}
|
54
|
+
}
|
59
55
|
|
60
|
-
|
61
|
-
|
56
|
+
// If we're at the top of a chain, then we're going to print out a nice
|
57
|
+
// multi-line layout if this doesn't break into multiple lines.
|
58
|
+
if (!chained.includes(parentNode.type) && (callNode.chain || 0) >= 3) {
|
59
|
+
return ifBreak(
|
60
|
+
group(concat(callNode.breakDoc.concat(rightSideDoc))),
|
61
|
+
concat([receiverDoc, group(rightSideDoc)])
|
62
|
+
);
|
63
|
+
}
|
64
|
+
|
65
|
+
return group(concat([receiverDoc, group(rightSideDoc)]));
|
66
|
+
}
|
67
|
+
|
68
|
+
function printMethodAddArg(path, opts, print) {
|
69
|
+
const methodAddArgNode = path.getValue();
|
70
|
+
const argNode = methodAddArgNode.body[1];
|
71
|
+
|
72
|
+
const [methodDoc, argsDoc] = path.map(print, "body");
|
73
|
+
|
74
|
+
// You can end up here if you have a method with a ? ending, presumably
|
75
|
+
// because the parser knows that it cannot be a local variable.
|
76
|
+
if (argsDoc.length === 0) {
|
77
|
+
return methodDoc;
|
78
|
+
}
|
79
|
+
|
80
|
+
// This case will ONLY be hit if we can successfully turn the block into a
|
81
|
+
// to_proc call. In that case, we just explicitly add the parens around it.
|
82
|
+
if (argNode.type === "args" && argsDoc.length > 0) {
|
83
|
+
return concat([methodDoc, "("].concat(argsDoc).concat(")"));
|
84
|
+
}
|
85
|
+
|
86
|
+
// Get a reference to the parent node so we can check if we're inside a chain
|
87
|
+
const parentNode = path.getParentNode();
|
88
|
+
|
89
|
+
// If our parent node is a chained node then we're not going to group the
|
90
|
+
// right side of the expression, as we want to have a nice multi-line layout.
|
91
|
+
if (chained.includes(parentNode.type)) {
|
92
|
+
parentNode.chain = (methodAddArgNode.chain || 0) + 1;
|
93
|
+
parentNode.breakDoc = (methodAddArgNode.breakDoc || [methodDoc]).concat(
|
94
|
+
argsDoc
|
95
|
+
);
|
96
|
+
}
|
97
|
+
|
98
|
+
// If we're at the top of a chain, then we're going to print out a nice
|
99
|
+
// multi-line layout if this doesn't break into multiple lines.
|
100
|
+
if (
|
101
|
+
!chained.includes(parentNode.type) &&
|
102
|
+
(methodAddArgNode.chain || 0) >= 3
|
103
|
+
) {
|
104
|
+
return ifBreak(
|
105
|
+
group(concat(methodAddArgNode.breakDoc.concat(argsDoc))),
|
106
|
+
concat([methodDoc, argsDoc])
|
107
|
+
);
|
108
|
+
}
|
109
|
+
|
110
|
+
return concat([methodDoc, argsDoc]);
|
111
|
+
}
|
112
|
+
|
113
|
+
module.exports = {
|
114
|
+
call: printCall,
|
115
|
+
fcall: concatBody,
|
116
|
+
method_add_arg: printMethodAddArg,
|
62
117
|
method_add_block: (path, opts, print) => {
|
63
118
|
const [method, block] = path.getValue().body;
|
64
119
|
const proc = toProc(path, opts, block);
|