prettier 1.0.1 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +6 -1
- data/lib/prettier.rb +2 -2
- data/node_modules/prettier/index.js +54 -54
- data/package.json +4 -2
- data/src/{ruby.js → plugin.js} +2 -2
- data/src/{embed.js → ruby/embed.js} +2 -2
- data/src/{nodes.js → ruby/nodes.js} +0 -0
- data/src/{nodes → ruby/nodes}/alias.js +1 -1
- data/src/{nodes → ruby/nodes}/aref.js +8 -1
- data/src/{nodes → ruby/nodes}/args.js +2 -2
- data/src/{nodes → ruby/nodes}/arrays.js +2 -3
- data/src/{nodes → ruby/nodes}/assign.js +12 -4
- data/src/{nodes → ruby/nodes}/blocks.js +3 -3
- data/src/{nodes → ruby/nodes}/calls.js +54 -11
- data/src/ruby/nodes/case.js +65 -0
- data/src/{nodes → ruby/nodes}/class.js +1 -1
- data/src/ruby/nodes/commands.js +126 -0
- data/src/{nodes → ruby/nodes}/conditionals.js +3 -3
- data/src/{nodes → ruby/nodes}/constants.js +2 -2
- data/src/{nodes → ruby/nodes}/flow.js +2 -2
- data/src/{nodes → ruby/nodes}/hashes.js +32 -10
- data/src/{nodes → ruby/nodes}/heredocs.js +2 -2
- data/src/{nodes → ruby/nodes}/hooks.js +2 -2
- data/src/{nodes → ruby/nodes}/ints.js +0 -0
- data/src/{nodes → ruby/nodes}/lambdas.js +2 -2
- data/src/ruby/nodes/loops.js +104 -0
- data/src/{nodes → ruby/nodes}/massign.js +8 -1
- data/src/{nodes → ruby/nodes}/methods.js +34 -6
- data/src/{nodes → ruby/nodes}/operators.js +2 -2
- data/src/{nodes → ruby/nodes}/params.js +9 -2
- data/src/{nodes → ruby/nodes}/patterns.js +45 -10
- data/src/ruby/nodes/regexp.js +56 -0
- data/src/{nodes → ruby/nodes}/rescue.js +2 -2
- data/src/ruby/nodes/return.js +98 -0
- data/src/{nodes → ruby/nodes}/statements.js +1 -1
- data/src/{nodes → ruby/nodes}/strings.js +1 -1
- data/src/{nodes → ruby/nodes}/super.js +2 -2
- data/src/{nodes → ruby/nodes}/undef.js +1 -1
- data/src/{parser.js → ruby/parser.js} +2 -2
- data/src/{parser.rb → ruby/parser.rb} +323 -317
- data/src/{printer.js → ruby/printer.js} +46 -1
- data/src/{toProc.js → ruby/toProc.js} +0 -0
- data/src/utils.js +10 -93
- data/src/utils/containsAssignment.js +11 -0
- data/src/utils/getTrailingComma.js +5 -0
- data/src/utils/hasAncestor.js +17 -0
- data/src/utils/literal.js +7 -0
- data/src/utils/makeCall.js +11 -0
- data/src/utils/noIndent.js +10 -0
- data/src/utils/skipAssignIndent.js +10 -0
- metadata +48 -41
- data/src/nodes/case.js +0 -61
- data/src/nodes/commands.js +0 -91
- data/src/nodes/loops.js +0 -101
- data/src/nodes/regexp.js +0 -49
- data/src/nodes/return.js +0 -72
@@ -6,9 +6,8 @@ const {
|
|
6
6
|
join,
|
7
7
|
line,
|
8
8
|
softline
|
9
|
-
} = require("
|
10
|
-
|
11
|
-
const { getTrailingComma, printEmptyCollection } = require("../utils");
|
9
|
+
} = require("../../prettier");
|
10
|
+
const { getTrailingComma, printEmptyCollection } = require("../../utils");
|
12
11
|
|
13
12
|
// Checks that every argument within this args node is a string_literal node
|
14
13
|
// that has no spaces or interpolations. This means we're dealing with an array
|
@@ -1,5 +1,5 @@
|
|
1
|
-
const { concat, group, indent, join, line } = require("
|
2
|
-
const {
|
1
|
+
const { concat, group, indent, join, line } = require("../../prettier");
|
2
|
+
const { skipAssignIndent } = require("../../utils");
|
3
3
|
|
4
4
|
function printAssign(path, opts, print) {
|
5
5
|
const [_targetNode, valueNode] = path.getValue().body;
|
@@ -31,9 +31,17 @@ function printOpAssign(path, opts, print) {
|
|
31
31
|
);
|
32
32
|
}
|
33
33
|
|
34
|
+
function printVarField(path, opts, print) {
|
35
|
+
return path.getValue().body ? path.call(print, "body", 0) : "";
|
36
|
+
}
|
37
|
+
|
38
|
+
function printVarRef(path, opts, print) {
|
39
|
+
return path.call(print, "body", 0);
|
40
|
+
}
|
41
|
+
|
34
42
|
module.exports = {
|
35
43
|
assign: printAssign,
|
36
44
|
opassign: printOpAssign,
|
37
|
-
var_field:
|
38
|
-
var_ref:
|
45
|
+
var_field: printVarField,
|
46
|
+
var_ref: printVarRef
|
39
47
|
};
|
@@ -7,8 +7,8 @@ const {
|
|
7
7
|
join,
|
8
8
|
removeLines,
|
9
9
|
softline
|
10
|
-
} = require("
|
11
|
-
const {
|
10
|
+
} = require("../../prettier");
|
11
|
+
const { hasAncestor } = require("../../utils");
|
12
12
|
|
13
13
|
const printBlock = (braces) => (path, opts, print) => {
|
14
14
|
const [variables, statements] = path.getValue().body;
|
@@ -81,5 +81,5 @@ module.exports = {
|
|
81
81
|
},
|
82
82
|
brace_block: printBlock(true),
|
83
83
|
do_block: printBlock(false),
|
84
|
-
excessed_comma:
|
84
|
+
excessed_comma: () => ""
|
85
85
|
};
|
@@ -5,8 +5,8 @@ const {
|
|
5
5
|
ifBreak,
|
6
6
|
indent,
|
7
7
|
softline
|
8
|
-
} = require("
|
9
|
-
const {
|
8
|
+
} = require("../../prettier");
|
9
|
+
const { makeCall, noIndent } = require("../../utils");
|
10
10
|
|
11
11
|
const toProc = require("../toProc");
|
12
12
|
|
@@ -39,16 +39,20 @@ function printCall(path, opts, print) {
|
|
39
39
|
// right side of the expression, as we want to have a nice multi-line layout.
|
40
40
|
if (chained.includes(parentNode.type)) {
|
41
41
|
parentNode.chain = (node.chain || 0) + 1;
|
42
|
+
parentNode.callChain = (node.callChain || 0) + 1;
|
42
43
|
parentNode.breakDoc = (node.breakDoc || [receiverDoc]).concat(rightSideDoc);
|
44
|
+
parentNode.firstReceiverType = node.firstReceiverType || receiverNode.type;
|
43
45
|
}
|
44
46
|
|
45
47
|
// If we're at the top of a chain, then we're going to print out a nice
|
46
48
|
// multi-line layout if this doesn't break into multiple lines.
|
47
49
|
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
50
|
+
let breakDoc = concat(node.breakDoc.concat(rightSideDoc));
|
51
|
+
if (!noIndent.includes(node.firstReceiverType)) {
|
52
|
+
breakDoc = indent(breakDoc);
|
53
|
+
}
|
54
|
+
|
55
|
+
return ifBreak(group(breakDoc), concat([receiverDoc, group(rightSideDoc)]));
|
52
56
|
}
|
53
57
|
|
54
58
|
// For certain left sides of the call nodes, we want to attach directly to
|
@@ -62,13 +66,31 @@ function printCall(path, opts, print) {
|
|
62
66
|
|
63
67
|
function printMethodAddArg(path, opts, print) {
|
64
68
|
const node = path.getValue();
|
65
|
-
const argNode = node.body[1];
|
66
69
|
|
70
|
+
const [methodNode, argNode] = node.body;
|
67
71
|
const [methodDoc, argsDoc] = path.map(print, "body");
|
68
72
|
|
69
73
|
// 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.
|
74
|
+
// because the parser knows that it cannot be a local variable. You can also
|
75
|
+
// end up here if you are explicitly using an empty set of parentheses.
|
71
76
|
if (argsDoc.length === 0) {
|
77
|
+
// If you're using an explicit set of parentheses on something that looks
|
78
|
+
// like a constant, then we need to match that in order to maintain valid
|
79
|
+
// Ruby. For example, you could do something like Foo(), on which we would
|
80
|
+
// need to keep the parentheses to make it look like a method call.
|
81
|
+
if (methodNode.type === "fcall" && methodNode.body[0].type === "@const") {
|
82
|
+
return concat([methodDoc, "()"]);
|
83
|
+
}
|
84
|
+
|
85
|
+
// If you're using an explicit set parentheses with the special call syntax,
|
86
|
+
// then we need to explicitly print out an extra set of parentheses. For
|
87
|
+
// example, if you call something like Foo.new.() (implicitly calling the
|
88
|
+
// #call method on a new instance of the Foo class), then we have to print
|
89
|
+
// out those parentheses, otherwise we'll end up with Foo.new.
|
90
|
+
if (methodNode.type === "call" && methodNode.body[2] === "call") {
|
91
|
+
return concat([methodDoc, "()"]);
|
92
|
+
}
|
93
|
+
|
72
94
|
return methodDoc;
|
73
95
|
}
|
74
96
|
|
@@ -86,11 +108,27 @@ function printMethodAddArg(path, opts, print) {
|
|
86
108
|
if (chained.includes(parentNode.type)) {
|
87
109
|
parentNode.chain = (node.chain || 0) + 1;
|
88
110
|
parentNode.breakDoc = (node.breakDoc || [methodDoc]).concat(argsDoc);
|
111
|
+
parentNode.firstReceiverType = node.firstReceiverType;
|
89
112
|
}
|
90
113
|
|
91
114
|
// If we're at the top of a chain, then we're going to print out a nice
|
92
115
|
// multi-line layout if this doesn't break into multiple lines.
|
93
116
|
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
|
117
|
+
// This is pretty specialized behavior. Basically if we're at the top of a
|
118
|
+
// chain but we've only had method calls without arguments and now we have
|
119
|
+
// arguments, then we're effectively trying to call a method with arguments
|
120
|
+
// that is nested under a bunch of stuff. So we group together to first part
|
121
|
+
// to make it so just the arguments break. This looks like, for example:
|
122
|
+
//
|
123
|
+
// config.action_dispatch.rescue_responses.merge!(
|
124
|
+
// 'ActiveRecord::ConnectionTimeoutError' => :service_unavailable,
|
125
|
+
// 'ActiveRecord::QueryCanceled' => :service_unavailable
|
126
|
+
// )
|
127
|
+
//
|
128
|
+
if (node.callChain === node.chain) {
|
129
|
+
return concat([group(indent(concat(node.breakDoc))), group(argsDoc)]);
|
130
|
+
}
|
131
|
+
|
94
132
|
return ifBreak(
|
95
133
|
group(indent(concat(node.breakDoc.concat(argsDoc)))),
|
96
134
|
concat([methodDoc, argsDoc])
|
@@ -118,7 +156,7 @@ function isSorbetTypeAnnotation(node) {
|
|
118
156
|
callNode.body[0].body[0].body === "sig" &&
|
119
157
|
callNode.body[1].type === "args" &&
|
120
158
|
callNode.body[1].body.length === 0 &&
|
121
|
-
blockNode
|
159
|
+
blockNode
|
122
160
|
);
|
123
161
|
}
|
124
162
|
|
@@ -164,6 +202,7 @@ function printMethodAddBlock(path, opts, print) {
|
|
164
202
|
if (chained.includes(parentNode.type)) {
|
165
203
|
parentNode.chain = (node.chain || 0) + 1;
|
166
204
|
parentNode.breakDoc = (node.breakDoc || [callDoc]).concat(blockDoc);
|
205
|
+
parentNode.firstReceiverType = node.firstReceiverType;
|
167
206
|
}
|
168
207
|
|
169
208
|
// If we're at the top of a chain, then we're going to print out a nice
|
@@ -178,10 +217,14 @@ function printMethodAddBlock(path, opts, print) {
|
|
178
217
|
return concat([callDoc, blockDoc]);
|
179
218
|
}
|
180
219
|
|
220
|
+
function printCallContainer(path, opts, print) {
|
221
|
+
return path.call(print, "body", 0);
|
222
|
+
}
|
223
|
+
|
181
224
|
module.exports = {
|
182
225
|
call: printCall,
|
183
|
-
fcall:
|
226
|
+
fcall: printCallContainer,
|
184
227
|
method_add_arg: printMethodAddArg,
|
185
228
|
method_add_block: printMethodAddBlock,
|
186
|
-
vcall:
|
229
|
+
vcall: printCallContainer
|
187
230
|
};
|
@@ -0,0 +1,65 @@
|
|
1
|
+
const {
|
2
|
+
align,
|
3
|
+
concat,
|
4
|
+
fill,
|
5
|
+
group,
|
6
|
+
hardline,
|
7
|
+
indent,
|
8
|
+
line
|
9
|
+
} = require("../../prettier");
|
10
|
+
|
11
|
+
function printCase(path, opts, print) {
|
12
|
+
const statement = ["case"];
|
13
|
+
|
14
|
+
// You don't need to explicitly have something to test against in a case
|
15
|
+
// statement (without it it effectively becomes an if/elsif chain).
|
16
|
+
if (path.getValue().body[0]) {
|
17
|
+
statement.push(" ", path.call(print, "body", 0));
|
18
|
+
}
|
19
|
+
|
20
|
+
return concat(
|
21
|
+
statement.concat([hardline, path.call(print, "body", 1), hardline, "end"])
|
22
|
+
);
|
23
|
+
}
|
24
|
+
|
25
|
+
function printWhen(path, opts, print) {
|
26
|
+
const [_preds, _stmts, addition] = path.getValue().body;
|
27
|
+
|
28
|
+
// The `fill` builder command expects an array of docs alternating with
|
29
|
+
// line breaks. This is so it can loop through and determine where to break.
|
30
|
+
const preds = fill(
|
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)
|
42
|
+
);
|
43
|
+
|
44
|
+
const stmts = path.call(print, "body", 1);
|
45
|
+
const parts = [concat(["when ", align("when ".length, preds)])];
|
46
|
+
|
47
|
+
// It's possible in a when to just have empty void statements, in which case
|
48
|
+
// we would skip adding the body.
|
49
|
+
if (!stmts.parts.every((part) => !part)) {
|
50
|
+
parts.push(indent(concat([hardline, stmts])));
|
51
|
+
}
|
52
|
+
|
53
|
+
// This is the next clause on the case statement, either another `when` or
|
54
|
+
// an `else` clause.
|
55
|
+
if (addition) {
|
56
|
+
parts.push(hardline, path.call(print, "body", 2));
|
57
|
+
}
|
58
|
+
|
59
|
+
return group(concat(parts));
|
60
|
+
}
|
61
|
+
|
62
|
+
module.exports = {
|
63
|
+
case: printCase,
|
64
|
+
when: printWhen
|
65
|
+
};
|
@@ -0,0 +1,126 @@
|
|
1
|
+
const {
|
2
|
+
align,
|
3
|
+
concat,
|
4
|
+
group,
|
5
|
+
ifBreak,
|
6
|
+
indent,
|
7
|
+
join,
|
8
|
+
line,
|
9
|
+
softline
|
10
|
+
} = require("../../prettier");
|
11
|
+
const { makeCall } = require("../../utils");
|
12
|
+
|
13
|
+
function docLength(doc) {
|
14
|
+
if (doc.length) {
|
15
|
+
return doc.length;
|
16
|
+
}
|
17
|
+
|
18
|
+
if (doc.parts) {
|
19
|
+
return doc.parts.reduce((sum, child) => sum + docLength(child), 0);
|
20
|
+
}
|
21
|
+
|
22
|
+
if (doc.contents) {
|
23
|
+
return docLength(doc.contents);
|
24
|
+
}
|
25
|
+
|
26
|
+
return 0;
|
27
|
+
}
|
28
|
+
|
29
|
+
function hasDef(node) {
|
30
|
+
return (
|
31
|
+
node.body[1].type === "args_add_block" &&
|
32
|
+
node.body[1].body[0].type === "args" &&
|
33
|
+
node.body[1].body[0].body[0] &&
|
34
|
+
["def", "defs"].includes(node.body[1].body[0].body[0].type)
|
35
|
+
);
|
36
|
+
}
|
37
|
+
|
38
|
+
// Very special handling case for rspec matchers. In general with rspec matchers
|
39
|
+
// you expect to see something like:
|
40
|
+
//
|
41
|
+
// expect(foo).to receive(:bar).with(
|
42
|
+
// 'one',
|
43
|
+
// 'two',
|
44
|
+
// 'three',
|
45
|
+
// 'four',
|
46
|
+
// 'five'
|
47
|
+
// )
|
48
|
+
//
|
49
|
+
// In this case the arguments are aligned to the left side as opposed to being
|
50
|
+
// aligned with the `receive` call.
|
51
|
+
function skipArgsAlign(path) {
|
52
|
+
return ["to", "not_to"].includes(path.getValue().body[2].body);
|
53
|
+
}
|
54
|
+
|
55
|
+
// If there is a ternary argument to a command and it's going to get broken
|
56
|
+
// into multiple lines, then we're going to have to use parentheses around the
|
57
|
+
// command in order to make sure operator precedence doesn't get messed up.
|
58
|
+
function hasTernaryArg(node) {
|
59
|
+
return node.body[0].body.some((child) => child.type === "ifop");
|
60
|
+
}
|
61
|
+
|
62
|
+
function printCommand(path, opts, print) {
|
63
|
+
const node = path.getValue();
|
64
|
+
|
65
|
+
const command = path.call(print, "body", 0);
|
66
|
+
const joinedArgs = join(concat([",", line]), path.call(print, "body", 1));
|
67
|
+
|
68
|
+
const hasTernary = hasTernaryArg(node.body[1]);
|
69
|
+
let breakArgs;
|
70
|
+
|
71
|
+
if (hasTernary) {
|
72
|
+
breakArgs = indent(concat([softline, joinedArgs]));
|
73
|
+
} else if (hasDef(path.getValue())) {
|
74
|
+
breakArgs = joinedArgs;
|
75
|
+
} else {
|
76
|
+
breakArgs = align(command.length + 1, joinedArgs);
|
77
|
+
}
|
78
|
+
|
79
|
+
return group(
|
80
|
+
ifBreak(
|
81
|
+
concat([
|
82
|
+
command,
|
83
|
+
hasTernary ? "(" : " ",
|
84
|
+
breakArgs,
|
85
|
+
hasTernary ? concat([softline, ")"]) : ""
|
86
|
+
]),
|
87
|
+
concat([command, " ", joinedArgs])
|
88
|
+
)
|
89
|
+
);
|
90
|
+
}
|
91
|
+
|
92
|
+
function printCommandCall(path, opts, print) {
|
93
|
+
const node = path.getValue();
|
94
|
+
const parts = [
|
95
|
+
path.call(print, "body", 0),
|
96
|
+
makeCall(path, opts, print),
|
97
|
+
path.call(print, "body", 2)
|
98
|
+
];
|
99
|
+
|
100
|
+
if (!node.body[3]) {
|
101
|
+
return concat(parts);
|
102
|
+
}
|
103
|
+
|
104
|
+
const argDocs = join(concat([",", line]), path.call(print, "body", 3));
|
105
|
+
let breakDoc;
|
106
|
+
|
107
|
+
if (hasTernaryArg(node.body[3])) {
|
108
|
+
parts.push("(");
|
109
|
+
breakDoc = parts.concat(indent(concat([softline, argDocs])), softline, ")");
|
110
|
+
} else if (skipArgsAlign(path)) {
|
111
|
+
parts.push(" ");
|
112
|
+
breakDoc = parts.concat(argDocs);
|
113
|
+
} else {
|
114
|
+
parts.push(" ");
|
115
|
+
breakDoc = parts.concat(align(docLength(concat(parts)), argDocs));
|
116
|
+
}
|
117
|
+
|
118
|
+
const joinedDoc = parts.concat(argDocs);
|
119
|
+
|
120
|
+
return group(ifBreak(concat(breakDoc), concat(joinedDoc)));
|
121
|
+
}
|
122
|
+
|
123
|
+
module.exports = {
|
124
|
+
command: printCommand,
|
125
|
+
command_call: printCommandCall
|
126
|
+
};
|
@@ -7,10 +7,10 @@ const {
|
|
7
7
|
ifBreak,
|
8
8
|
indent,
|
9
9
|
softline
|
10
|
-
} = require("
|
10
|
+
} = require("../../prettier");
|
11
11
|
|
12
|
-
const { containsAssignment, isEmptyStmts } = require("
|
13
|
-
const inlineEnsureParens = require("
|
12
|
+
const { containsAssignment, isEmptyStmts } = require("../../utils");
|
13
|
+
const inlineEnsureParens = require("../../utils/inlineEnsureParens");
|
14
14
|
|
15
15
|
const printWithAddition = (keyword, path, print, { breaking = false } = {}) =>
|
16
16
|
concat([
|
@@ -1,5 +1,5 @@
|
|
1
|
-
const { concat, group, indent, join, softline } = require("
|
2
|
-
const { makeCall } = require("
|
1
|
+
const { concat, group, indent, join, softline } = require("../../prettier");
|
2
|
+
const { makeCall } = require("../../utils");
|
3
3
|
|
4
4
|
function printConstPath(path, opts, print) {
|
5
5
|
return join("::", path.map(print, "body"));
|
@@ -1,11 +1,16 @@
|
|
1
|
-
const {
|
2
|
-
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
ifBreak,
|
5
|
+
indent,
|
6
|
+
join,
|
7
|
+
line
|
8
|
+
} = require("../../prettier");
|
3
9
|
const {
|
4
10
|
getTrailingComma,
|
5
|
-
prefix,
|
6
11
|
printEmptyCollection,
|
7
12
|
skipAssignIndent
|
8
|
-
} = require("
|
13
|
+
} = require("../../utils");
|
9
14
|
|
10
15
|
// When attempting to convert a hash rocket into a hash label, you need to take
|
11
16
|
// care because only certain patterns are allowed. Ruby source says that they
|
@@ -49,8 +54,20 @@ function printHashKeyLabel(path, print) {
|
|
49
54
|
return print(path);
|
50
55
|
case "symbol_literal":
|
51
56
|
return concat([path.call(print, "body", 0), ":"]);
|
52
|
-
case "dyna_symbol":
|
53
|
-
|
57
|
+
case "dyna_symbol": {
|
58
|
+
const { parts } = print(path);
|
59
|
+
|
60
|
+
// We're going to slice off the starting colon character so that we can
|
61
|
+
// move it to the end. If there are comments, then we're going to go
|
62
|
+
// further into the printed doc nodes.
|
63
|
+
if (parts[0] === ":") {
|
64
|
+
parts.splice(0, 1);
|
65
|
+
} else {
|
66
|
+
parts[1].parts.splice(0, 1);
|
67
|
+
}
|
68
|
+
|
69
|
+
return concat(parts.concat(":"));
|
70
|
+
}
|
54
71
|
}
|
55
72
|
}
|
56
73
|
|
@@ -66,20 +83,25 @@ function printHashKeyRocket(path, print) {
|
|
66
83
|
}
|
67
84
|
|
68
85
|
function printAssocNew(path, opts, print) {
|
86
|
+
const [keyNode, valueNode] = path.getValue().body;
|
69
87
|
const { keyPrinter } = path.getParentNode();
|
70
88
|
|
71
89
|
const parts = [path.call((keyPath) => keyPrinter(keyPath, print), "body", 0)];
|
72
90
|
const valueDoc = path.call(print, "body", 1);
|
73
91
|
|
74
|
-
if (skipAssignIndent(
|
75
|
-
parts.push(" ", valueDoc);
|
76
|
-
} else {
|
92
|
+
if (!skipAssignIndent(valueNode) || keyNode.comments) {
|
77
93
|
parts.push(indent(concat([line, valueDoc])));
|
94
|
+
} else {
|
95
|
+
parts.push(" ", valueDoc);
|
78
96
|
}
|
79
97
|
|
80
98
|
return group(concat(parts));
|
81
99
|
}
|
82
100
|
|
101
|
+
function printAssocSplat(path, opts, print) {
|
102
|
+
return concat(["**", path.call(print, "body", 0)]);
|
103
|
+
}
|
104
|
+
|
83
105
|
function printHashContents(path, opts, print) {
|
84
106
|
const node = path.getValue();
|
85
107
|
|
@@ -121,7 +143,7 @@ function printHash(path, opts, print) {
|
|
121
143
|
|
122
144
|
module.exports = {
|
123
145
|
assoc_new: printAssocNew,
|
124
|
-
assoc_splat:
|
146
|
+
assoc_splat: printAssocSplat,
|
125
147
|
assoclist_from_args: printHashContents,
|
126
148
|
bare_assoc_hash: printHashContents,
|
127
149
|
hash: printHash
|