prettier 1.0.0.pre.rc1 → 1.2.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 +60 -2
- data/README.md +14 -10
- data/node_modules/prettier/index.js +54 -54
- data/package.json +10 -5
- data/src/embed.js +6 -2
- data/src/nodes/args.js +59 -78
- data/src/nodes/arrays.js +36 -51
- data/src/nodes/assign.js +10 -2
- data/src/nodes/calls.js +129 -46
- data/src/nodes/case.js +11 -7
- data/src/nodes/hashes.js +58 -51
- data/src/nodes/ints.js +0 -6
- data/src/nodes/lambdas.js +6 -22
- data/src/nodes/loops.js +66 -66
- data/src/nodes/methods.js +11 -2
- data/src/nodes/params.js +15 -3
- data/src/nodes/patterns.js +17 -0
- data/src/nodes/regexp.js +32 -18
- data/src/nodes/statements.js +35 -25
- data/src/nodes/strings.js +1 -1
- data/src/parser.js +27 -12
- data/src/parser.rb +85 -17
- data/src/printer.js +13 -0
- data/src/ruby.js +11 -4
- data/src/toProc.js +2 -2
- data/src/utils.js +2 -3
- data/src/utils/printEmptyCollection.js +42 -0
- metadata +7 -48
data/src/nodes/arrays.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
const {
|
2
2
|
concat,
|
3
3
|
group,
|
4
|
-
hardline,
|
5
4
|
ifBreak,
|
6
5
|
indent,
|
7
6
|
join,
|
@@ -9,7 +8,7 @@ const {
|
|
9
8
|
softline
|
10
9
|
} = require("../prettier");
|
11
10
|
|
12
|
-
const { getTrailingComma } = require("../utils");
|
11
|
+
const { getTrailingComma, printEmptyCollection } = require("../utils");
|
13
12
|
|
14
13
|
// Checks that every argument within this args node is a string_literal node
|
15
14
|
// that has no spaces or interpolations. This means we're dealing with an array
|
@@ -18,32 +17,35 @@ const { getTrailingComma } = require("../utils");
|
|
18
17
|
// ['a', 'b', 'c']
|
19
18
|
//
|
20
19
|
function isStringArray(args) {
|
21
|
-
return
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
return false
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
20
|
+
return (
|
21
|
+
args.body.length > 1 &&
|
22
|
+
args.body.every((arg) => {
|
23
|
+
// We want to verify that every node inside of this array is a string
|
24
|
+
// literal. We also want to make sure none of them have comments attached.
|
25
|
+
if (arg.type !== "string_literal" || arg.comments) {
|
26
|
+
return false;
|
27
|
+
}
|
28
|
+
|
29
|
+
// If the string has multiple parts (meaning plain string content but also
|
30
|
+
// interpolated content) then we know it's not a simple string.
|
31
|
+
if (arg.body.length !== 1) {
|
32
|
+
return false;
|
33
|
+
}
|
34
|
+
|
35
|
+
const part = arg.body[0];
|
36
|
+
|
37
|
+
// If the only part of this string is not @tstring_content then it's
|
38
|
+
// interpolated, so again we can return false.
|
39
|
+
if (part.type !== "@tstring_content") {
|
40
|
+
return false;
|
41
|
+
}
|
42
|
+
|
43
|
+
// Finally, verify that the string doesn't contain a space, an escape
|
44
|
+
// character, or brackets so that we know it can be put into a string
|
45
|
+
// literal array.
|
46
|
+
return !/[\s\\[\]]/.test(part.body);
|
47
|
+
})
|
48
|
+
);
|
47
49
|
}
|
48
50
|
|
49
51
|
// Checks that every argument within this args node is a symbol_literal node (as
|
@@ -53,8 +55,9 @@ function isStringArray(args) {
|
|
53
55
|
// [:a, :b, :c]
|
54
56
|
//
|
55
57
|
function isSymbolArray(args) {
|
56
|
-
return
|
57
|
-
|
58
|
+
return (
|
59
|
+
args.body.length > 1 &&
|
60
|
+
args.body.every((arg) => arg.type === "symbol_literal" && !arg.comments)
|
58
61
|
);
|
59
62
|
}
|
60
63
|
|
@@ -89,24 +92,6 @@ function printSpecialArray(start) {
|
|
89
92
|
};
|
90
93
|
}
|
91
94
|
|
92
|
-
function printEmptyArrayWithComments(path, opts) {
|
93
|
-
const arrayNode = path.getValue();
|
94
|
-
|
95
|
-
const printComment = (commentPath, index) => {
|
96
|
-
arrayNode.comments[index].printed = true;
|
97
|
-
return opts.printer.printComment(commentPath);
|
98
|
-
};
|
99
|
-
|
100
|
-
return concat([
|
101
|
-
"[",
|
102
|
-
indent(
|
103
|
-
concat([hardline, join(hardline, path.map(printComment, "comments"))])
|
104
|
-
),
|
105
|
-
line,
|
106
|
-
"]"
|
107
|
-
]);
|
108
|
-
}
|
109
|
-
|
110
95
|
// An array node is any literal array in Ruby. This includes all of the special
|
111
96
|
// array literals as well as regular arrays. If it is a special array literal
|
112
97
|
// then it will have one child that represents the special array, otherwise it
|
@@ -118,12 +103,12 @@ function printArray(path, opts, print) {
|
|
118
103
|
// If there is no inner arguments node, then we're dealing with an empty
|
119
104
|
// array, so we can go ahead and return.
|
120
105
|
if (args === null) {
|
121
|
-
return
|
106
|
+
return printEmptyCollection(path, opts, "[", "]");
|
122
107
|
}
|
123
108
|
|
124
109
|
// If we have an array that contains only simple string literals with no
|
125
110
|
// spaces or interpolation, then we're going to print a %w array.
|
126
|
-
if (isStringArray(args)) {
|
111
|
+
if (opts.rubyArrayLiteral && isStringArray(args)) {
|
127
112
|
const printString = (stringPath) => stringPath.call(print, "body", 0);
|
128
113
|
const parts = path.map(printString, "body", 0, "body");
|
129
114
|
|
@@ -132,7 +117,7 @@ function printArray(path, opts, print) {
|
|
132
117
|
|
133
118
|
// If we have an array that contains only simple symbol literals with no
|
134
119
|
// interpolation, then we're going to print a %i array.
|
135
|
-
if (isSymbolArray(args)) {
|
120
|
+
if (opts.rubyArrayLiteral && isSymbolArray(args)) {
|
136
121
|
const printSymbol = (symbolPath) => symbolPath.call(print, "body", 0);
|
137
122
|
const parts = path.map(printSymbol, "body", 0, "body");
|
138
123
|
|
data/src/nodes/assign.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
const { concat, group, indent, join, line } = require("../prettier");
|
2
|
-
const {
|
2
|
+
const { first, 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
|
+
if (path.getValue().body) {
|
36
|
+
return path.call(print, "body", 0);
|
37
|
+
}
|
38
|
+
|
39
|
+
return "*";
|
40
|
+
}
|
41
|
+
|
34
42
|
module.exports = {
|
35
43
|
assign: printAssign,
|
36
44
|
opassign: printOpAssign,
|
37
|
-
var_field:
|
45
|
+
var_field: printVarField,
|
38
46
|
var_ref: first
|
39
47
|
};
|
data/src/nodes/calls.js
CHANGED
@@ -6,15 +6,15 @@ const {
|
|
6
6
|
indent,
|
7
7
|
softline
|
8
8
|
} = require("../prettier");
|
9
|
-
const {
|
9
|
+
const { first, makeCall, noIndent } = require("../utils");
|
10
10
|
|
11
11
|
const toProc = require("../toProc");
|
12
12
|
|
13
|
-
const chained = ["call", "method_add_arg"];
|
13
|
+
const chained = ["call", "method_add_arg", "method_add_block"];
|
14
14
|
|
15
15
|
function printCall(path, opts, print) {
|
16
|
-
const
|
17
|
-
const [receiverNode, _operatorNode, messageNode] =
|
16
|
+
const node = path.getValue();
|
17
|
+
const [receiverNode, _operatorNode, messageNode] = node.body;
|
18
18
|
|
19
19
|
const receiverDoc = path.call(print, "body", 0);
|
20
20
|
const operatorDoc = makeCall(path, opts, print);
|
@@ -24,21 +24,13 @@ function printCall(path, opts, print) {
|
|
24
24
|
// call syntax so if `call` is implicit, we don't print it out.
|
25
25
|
const messageDoc = messageNode === "call" ? "" : path.call(print, "body", 2);
|
26
26
|
|
27
|
-
// For certain left sides of the call nodes, we want to attach directly to
|
28
|
-
// the } or end.
|
29
|
-
if (noIndent.includes(receiverNode.type)) {
|
30
|
-
return concat([receiverDoc, operatorDoc, messageDoc]);
|
31
|
-
}
|
32
|
-
|
33
27
|
// The right side of the call node, as in everything including the operator
|
34
28
|
// and beyond.
|
35
|
-
const rightSideDoc =
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
])
|
41
|
-
);
|
29
|
+
const rightSideDoc = concat([
|
30
|
+
receiverNode.comments ? hardline : softline,
|
31
|
+
operatorDoc,
|
32
|
+
messageDoc
|
33
|
+
]);
|
42
34
|
|
43
35
|
// Get a reference to the parent node so we can check if we're inside a chain
|
44
36
|
const parentNode = path.getParentNode();
|
@@ -46,33 +38,56 @@ function printCall(path, opts, print) {
|
|
46
38
|
// If our parent node is a chained node then we're not going to group the
|
47
39
|
// right side of the expression, as we want to have a nice multi-line layout.
|
48
40
|
if (chained.includes(parentNode.type)) {
|
49
|
-
parentNode.chain = (
|
50
|
-
parentNode.
|
51
|
-
|
52
|
-
);
|
41
|
+
parentNode.chain = (node.chain || 0) + 1;
|
42
|
+
parentNode.callChain = (node.callChain || 0) + 1;
|
43
|
+
parentNode.breakDoc = (node.breakDoc || [receiverDoc]).concat(rightSideDoc);
|
53
44
|
}
|
54
45
|
|
55
46
|
// If we're at the top of a chain, then we're going to print out a nice
|
56
47
|
// multi-line layout if this doesn't break into multiple lines.
|
57
|
-
if (!chained.includes(parentNode.type) && (
|
48
|
+
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
|
58
49
|
return ifBreak(
|
59
|
-
group(concat(
|
50
|
+
group(indent(concat(node.breakDoc.concat(rightSideDoc)))),
|
60
51
|
concat([receiverDoc, group(rightSideDoc)])
|
61
52
|
);
|
62
53
|
}
|
63
54
|
|
64
|
-
|
55
|
+
// For certain left sides of the call nodes, we want to attach directly to
|
56
|
+
// the } or end.
|
57
|
+
if (noIndent.includes(receiverNode.type)) {
|
58
|
+
return concat([receiverDoc, operatorDoc, messageDoc]);
|
59
|
+
}
|
60
|
+
|
61
|
+
return group(concat([receiverDoc, group(indent(rightSideDoc))]));
|
65
62
|
}
|
66
63
|
|
67
64
|
function printMethodAddArg(path, opts, print) {
|
68
|
-
const
|
69
|
-
const argNode = methodAddArgNode.body[1];
|
65
|
+
const node = path.getValue();
|
70
66
|
|
67
|
+
const [methodNode, argNode] = node.body;
|
71
68
|
const [methodDoc, argsDoc] = path.map(print, "body");
|
72
69
|
|
73
70
|
// You can end up here if you have a method with a ? ending, presumably
|
74
|
-
// because the parser knows that it cannot be a local variable.
|
71
|
+
// because the parser knows that it cannot be a local variable. You can also
|
72
|
+
// end up here if you are explicitly using an empty set of parentheses.
|
75
73
|
if (argsDoc.length === 0) {
|
74
|
+
// If you're using an explicit set of parentheses on something that looks
|
75
|
+
// like a constant, then we need to match that in order to maintain valid
|
76
|
+
// Ruby. For example, you could do something like Foo(), on which we would
|
77
|
+
// need to keep the parentheses to make it look like a method call.
|
78
|
+
if (methodNode.type === "fcall" && methodNode.body[0].type === "@const") {
|
79
|
+
return concat([methodDoc, "()"]);
|
80
|
+
}
|
81
|
+
|
82
|
+
// If you're using an explicit set parentheses with the special call syntax,
|
83
|
+
// then we need to explicitly print out an extra set of parentheses. For
|
84
|
+
// example, if you call something like Foo.new.() (implicitly calling the
|
85
|
+
// #call method on a new instance of the Foo class), then we have to print
|
86
|
+
// out those parentheses, otherwise we'll end up with Foo.new.
|
87
|
+
if (methodNode.type === "call" && methodNode.body[2] === "call") {
|
88
|
+
return concat([methodDoc, "()"]);
|
89
|
+
}
|
90
|
+
|
76
91
|
return methodDoc;
|
77
92
|
}
|
78
93
|
|
@@ -88,20 +103,30 @@ function printMethodAddArg(path, opts, print) {
|
|
88
103
|
// If our parent node is a chained node then we're not going to group the
|
89
104
|
// right side of the expression, as we want to have a nice multi-line layout.
|
90
105
|
if (chained.includes(parentNode.type)) {
|
91
|
-
parentNode.chain = (
|
92
|
-
parentNode.breakDoc = (
|
93
|
-
argsDoc
|
94
|
-
);
|
106
|
+
parentNode.chain = (node.chain || 0) + 1;
|
107
|
+
parentNode.breakDoc = (node.breakDoc || [methodDoc]).concat(argsDoc);
|
95
108
|
}
|
96
109
|
|
97
110
|
// If we're at the top of a chain, then we're going to print out a nice
|
98
111
|
// multi-line layout if this doesn't break into multiple lines.
|
99
|
-
if (
|
100
|
-
|
101
|
-
|
102
|
-
|
112
|
+
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
|
113
|
+
// This is pretty specialized behavior. Basically if we're at the top of a
|
114
|
+
// chain but we've only had method calls without arguments and now we have
|
115
|
+
// arguments, then we're effectively trying to call a method with arguments
|
116
|
+
// that is nested under a bunch of stuff. So we group together to first part
|
117
|
+
// to make it so just the arguments break. This looks like, for example:
|
118
|
+
//
|
119
|
+
// config.action_dispatch.rescue_responses.merge!(
|
120
|
+
// 'ActiveRecord::ConnectionTimeoutError' => :service_unavailable,
|
121
|
+
// 'ActiveRecord::QueryCanceled' => :service_unavailable
|
122
|
+
// )
|
123
|
+
//
|
124
|
+
if (node.callChain === node.chain) {
|
125
|
+
return concat([group(indent(concat(node.breakDoc))), group(argsDoc)]);
|
126
|
+
}
|
127
|
+
|
103
128
|
return ifBreak(
|
104
|
-
group(concat(
|
129
|
+
group(indent(concat(node.breakDoc.concat(argsDoc)))),
|
105
130
|
concat([methodDoc, argsDoc])
|
106
131
|
);
|
107
132
|
}
|
@@ -109,15 +134,47 @@ function printMethodAddArg(path, opts, print) {
|
|
109
134
|
return concat([methodDoc, argsDoc]);
|
110
135
|
}
|
111
136
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
137
|
+
// Sorbet type annotations look like the following:
|
138
|
+
//
|
139
|
+
// {method_add_block
|
140
|
+
// [{method_add_arg
|
141
|
+
// [{fcall
|
142
|
+
// [{@ident "sig"}]},
|
143
|
+
// {args []}]},
|
144
|
+
// {brace_block [nil, {stmts}]}}]}
|
145
|
+
//
|
146
|
+
function isSorbetTypeAnnotation(node) {
|
147
|
+
const [callNode, blockNode] = node.body;
|
148
|
+
|
149
|
+
return (
|
150
|
+
callNode.type === "method_add_arg" &&
|
151
|
+
callNode.body[0].type === "fcall" &&
|
152
|
+
callNode.body[0].body[0].body === "sig" &&
|
153
|
+
callNode.body[1].type === "args" &&
|
154
|
+
callNode.body[1].body.length === 0 &&
|
155
|
+
blockNode.type === "brace_block"
|
156
|
+
);
|
157
|
+
}
|
119
158
|
|
120
|
-
|
159
|
+
function printMethodAddBlock(path, opts, print) {
|
160
|
+
const node = path.getValue();
|
161
|
+
|
162
|
+
const [callNode, blockNode] = node.body;
|
163
|
+
const [callDoc, blockDoc] = path.map(print, "body");
|
164
|
+
|
165
|
+
// Very special handling here for sorbet type annotations. They look like Ruby
|
166
|
+
// code, but they're not actually Ruby code, so we're not going to mess with
|
167
|
+
// them at all.
|
168
|
+
if (isSorbetTypeAnnotation(node)) {
|
169
|
+
return opts.originalText.slice(opts.locStart(node), opts.locEnd(node));
|
170
|
+
}
|
171
|
+
|
172
|
+
// Don't bother trying to do any kind of fancy toProc transform if the option
|
173
|
+
// is disabled.
|
174
|
+
if (opts.rubyToProc) {
|
175
|
+
const proc = toProc(path, blockNode);
|
176
|
+
|
177
|
+
if (proc && callNode.type === "call") {
|
121
178
|
return group(
|
122
179
|
concat([
|
123
180
|
path.call(print, "body", 0),
|
@@ -131,8 +188,34 @@ module.exports = {
|
|
131
188
|
if (proc) {
|
132
189
|
return path.call(print, "body", 0);
|
133
190
|
}
|
191
|
+
}
|
134
192
|
|
135
|
-
|
136
|
-
|
193
|
+
// Get a reference to the parent node so we can check if we're inside a chain
|
194
|
+
const parentNode = path.getParentNode();
|
195
|
+
|
196
|
+
// If our parent node is a chained node then we're not going to group the
|
197
|
+
// right side of the expression, as we want to have a nice multi-line layout.
|
198
|
+
if (chained.includes(parentNode.type)) {
|
199
|
+
parentNode.chain = (node.chain || 0) + 1;
|
200
|
+
parentNode.breakDoc = (node.breakDoc || [callDoc]).concat(blockDoc);
|
201
|
+
}
|
202
|
+
|
203
|
+
// If we're at the top of a chain, then we're going to print out a nice
|
204
|
+
// multi-line layout if this doesn't break into multiple lines.
|
205
|
+
if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
|
206
|
+
return ifBreak(
|
207
|
+
group(indent(concat(node.breakDoc.concat(blockDoc)))),
|
208
|
+
concat([callDoc, blockDoc])
|
209
|
+
);
|
210
|
+
}
|
211
|
+
|
212
|
+
return concat([callDoc, blockDoc]);
|
213
|
+
}
|
214
|
+
|
215
|
+
module.exports = {
|
216
|
+
call: printCall,
|
217
|
+
fcall: first,
|
218
|
+
method_add_arg: printMethodAddArg,
|
219
|
+
method_add_block: printMethodAddBlock,
|
137
220
|
vcall: first
|
138
221
|
};
|
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/hashes.js
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
const {
|
2
|
-
concat,
|
3
|
-
group,
|
4
|
-
hardline,
|
5
|
-
ifBreak,
|
6
|
-
indent,
|
7
|
-
join,
|
8
|
-
line
|
9
|
-
} = require("../prettier");
|
1
|
+
const { concat, group, ifBreak, indent, join, line } = require("../prettier");
|
10
2
|
|
11
|
-
const {
|
3
|
+
const {
|
4
|
+
getTrailingComma,
|
5
|
+
prefix,
|
6
|
+
printEmptyCollection,
|
7
|
+
skipAssignIndent
|
8
|
+
} = require("../utils");
|
12
9
|
|
13
10
|
// When attempting to convert a hash rocket into a hash label, you need to take
|
14
11
|
// care because only certain patterns are allowed. Ruby source says that they
|
@@ -25,35 +22,54 @@ function isValidHashLabel(symbolLiteral) {
|
|
25
22
|
return label.match(/^[_A-Za-z]/) && !label.endsWith("=");
|
26
23
|
}
|
27
24
|
|
28
|
-
function
|
29
|
-
|
30
|
-
|
25
|
+
function canUseHashLabels(contentsNode) {
|
26
|
+
return contentsNode.body.every((assocNode) => {
|
27
|
+
if (assocNode.type === "assoc_splat") {
|
28
|
+
return true;
|
29
|
+
}
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
return
|
41
|
-
}
|
42
|
-
return concat([labelDoc, " =>"]);
|
31
|
+
switch (assocNode.body[0].type) {
|
32
|
+
case "@label":
|
33
|
+
return true;
|
34
|
+
case "symbol_literal":
|
35
|
+
return isValidHashLabel(assocNode.body[0]);
|
36
|
+
case "dyna_symbol":
|
37
|
+
return true;
|
38
|
+
default:
|
39
|
+
return false;
|
43
40
|
}
|
41
|
+
});
|
42
|
+
}
|
43
|
+
|
44
|
+
function printHashKeyLabel(path, print) {
|
45
|
+
const node = path.getValue();
|
46
|
+
|
47
|
+
switch (node.type) {
|
48
|
+
case "@label":
|
49
|
+
return print(path);
|
50
|
+
case "symbol_literal":
|
51
|
+
return concat([path.call(print, "body", 0), ":"]);
|
44
52
|
case "dyna_symbol":
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
53
|
+
return concat(print(path).parts.slice(1).concat(":"));
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
function printHashKeyRocket(path, print) {
|
58
|
+
const node = path.getValue();
|
59
|
+
const doc = print(path);
|
60
|
+
|
61
|
+
if (node.type === "@label") {
|
62
|
+
return `:${doc.slice(0, doc.length - 1)} =>`;
|
51
63
|
}
|
64
|
+
|
65
|
+
return concat([doc, " =>"]);
|
52
66
|
}
|
53
67
|
|
54
68
|
function printAssocNew(path, opts, print) {
|
69
|
+
const { keyPrinter } = path.getParentNode();
|
70
|
+
|
71
|
+
const parts = [path.call((keyPath) => keyPrinter(keyPath, print), "body", 0)];
|
55
72
|
const valueDoc = path.call(print, "body", 1);
|
56
|
-
const parts = [printHashKey(path, opts, print)];
|
57
73
|
|
58
74
|
if (skipAssignIndent(path.getValue().body[1])) {
|
59
75
|
parts.push(" ", valueDoc);
|
@@ -64,22 +80,17 @@ function printAssocNew(path, opts, print) {
|
|
64
80
|
return group(concat(parts));
|
65
81
|
}
|
66
82
|
|
67
|
-
function
|
68
|
-
const
|
83
|
+
function printHashContents(path, opts, print) {
|
84
|
+
const node = path.getValue();
|
85
|
+
|
86
|
+
// First determine which key printer we're going to use, so that the child
|
87
|
+
// nodes can reference it when they go to get printed.
|
88
|
+
node.keyPrinter =
|
89
|
+
opts.rubyHashLabel && canUseHashLabels(path.getValue())
|
90
|
+
? printHashKeyLabel
|
91
|
+
: printHashKeyRocket;
|
69
92
|
|
70
|
-
|
71
|
-
hashNode.comments[index].printed = true;
|
72
|
-
return opts.printer.printComment(commentPath);
|
73
|
-
};
|
74
|
-
|
75
|
-
return concat([
|
76
|
-
"{",
|
77
|
-
indent(
|
78
|
-
concat([hardline, join(hardline, path.map(printComment, "comments"))])
|
79
|
-
),
|
80
|
-
line,
|
81
|
-
"}"
|
82
|
-
]);
|
93
|
+
return join(concat([",", line]), path.map(print, "body"));
|
83
94
|
}
|
84
95
|
|
85
96
|
function printHash(path, opts, print) {
|
@@ -89,7 +100,7 @@ function printHash(path, opts, print) {
|
|
89
100
|
// missing, then it means we're dealing with an empty hash, so we can just
|
90
101
|
// exit here and print.
|
91
102
|
if (hashNode.body[0] === null) {
|
92
|
-
return
|
103
|
+
return printEmptyCollection(path, opts, "{", "}");
|
93
104
|
}
|
94
105
|
|
95
106
|
return group(
|
@@ -108,10 +119,6 @@ function printHash(path, opts, print) {
|
|
108
119
|
);
|
109
120
|
}
|
110
121
|
|
111
|
-
function printHashContents(path, opts, print) {
|
112
|
-
return group(join(concat([",", line]), path.map(print, "body")));
|
113
|
-
}
|
114
|
-
|
115
122
|
module.exports = {
|
116
123
|
assoc_new: printAssocNew,
|
117
124
|
assoc_splat: prefix("**"),
|