prettier 1.5.5 → 2.0.0.pre.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +344 -282
  3. data/CONTRIBUTING.md +8 -11
  4. data/LICENSE +1 -1
  5. data/README.md +30 -12
  6. data/dist/haml/embed.js +53 -0
  7. data/dist/haml/parser.js +31 -0
  8. data/{src → dist}/haml/parser.rb +0 -0
  9. data/dist/haml/printer.js +336 -0
  10. data/dist/parser/getInfo.js +17 -0
  11. data/{src → dist}/parser/netcat.js +1 -0
  12. data/dist/parser/parseSync.js +142 -0
  13. data/dist/parser/server.rb +140 -0
  14. data/dist/plugin.js +143 -0
  15. data/dist/prettier.js +15 -0
  16. data/dist/rbs/parser.js +34 -0
  17. data/{src → dist}/rbs/parser.rb +0 -0
  18. data/dist/rbs/printer.js +517 -0
  19. data/dist/ruby/embed.js +110 -0
  20. data/dist/ruby/nodes/alias.js +59 -0
  21. data/{src → dist}/ruby/nodes/aref.js +26 -35
  22. data/dist/ruby/nodes/args.js +165 -0
  23. data/dist/ruby/nodes/arrays.js +126 -0
  24. data/dist/ruby/nodes/assign.js +41 -0
  25. data/dist/ruby/nodes/blocks.js +68 -0
  26. data/dist/ruby/nodes/calls.js +260 -0
  27. data/dist/ruby/nodes/case.js +50 -0
  28. data/dist/ruby/nodes/class.js +54 -0
  29. data/dist/ruby/nodes/commands.js +124 -0
  30. data/dist/ruby/nodes/conditionals.js +242 -0
  31. data/dist/ruby/nodes/constants.js +38 -0
  32. data/dist/ruby/nodes/flow.js +66 -0
  33. data/dist/ruby/nodes/hashes.js +130 -0
  34. data/dist/ruby/nodes/heredocs.js +30 -0
  35. data/dist/ruby/nodes/hooks.js +35 -0
  36. data/dist/ruby/nodes/ints.js +27 -0
  37. data/dist/ruby/nodes/lambdas.js +69 -0
  38. data/dist/ruby/nodes/loops.js +73 -0
  39. data/dist/ruby/nodes/massign.js +73 -0
  40. data/dist/ruby/nodes/methods.js +70 -0
  41. data/dist/ruby/nodes/operators.js +70 -0
  42. data/dist/ruby/nodes/params.js +89 -0
  43. data/dist/ruby/nodes/patterns.js +109 -0
  44. data/dist/ruby/nodes/regexp.js +45 -0
  45. data/dist/ruby/nodes/rescue.js +82 -0
  46. data/dist/ruby/nodes/return.js +75 -0
  47. data/dist/ruby/nodes/statements.js +111 -0
  48. data/dist/ruby/nodes/strings.js +218 -0
  49. data/dist/ruby/nodes/super.js +30 -0
  50. data/dist/ruby/nodes/undef.js +26 -0
  51. data/dist/ruby/nodes.js +151 -0
  52. data/dist/ruby/parser.js +34 -0
  53. data/{src → dist}/ruby/parser.rb +1274 -288
  54. data/dist/ruby/printer.js +125 -0
  55. data/dist/ruby/toProc.js +93 -0
  56. data/dist/types/haml.js +4 -0
  57. data/dist/types/plugin.js +3 -0
  58. data/dist/types/rbs.js +4 -0
  59. data/dist/types/ruby.js +4 -0
  60. data/dist/types/utils.js +2 -0
  61. data/dist/types.js +30 -0
  62. data/dist/utils/containsAssignment.js +15 -0
  63. data/dist/utils/getTrailingComma.js +6 -0
  64. data/dist/utils/hasAncestor.js +15 -0
  65. data/{src → dist}/utils/inlineEnsureParens.js +16 -16
  66. data/dist/utils/isEmptyBodyStmt.js +10 -0
  67. data/dist/utils/isEmptyStmts.js +10 -0
  68. data/dist/utils/literal.js +8 -0
  69. data/dist/utils/literallineWithoutBreakParent.js +8 -0
  70. data/dist/utils/makeCall.js +13 -0
  71. data/dist/utils/noIndent.js +11 -0
  72. data/dist/utils/printEmptyCollection.js +44 -0
  73. data/dist/utils/skipAssignIndent.js +15 -0
  74. data/dist/utils.js +30 -0
  75. data/node_modules/prettier/bin-prettier.js +13343 -10961
  76. data/node_modules/prettier/doc.js +4829 -0
  77. data/node_modules/prettier/index.js +23988 -22229
  78. data/node_modules/prettier/package.json +23 -0
  79. data/node_modules/prettier/parser-angular.js +60 -40
  80. data/node_modules/prettier/parser-babel.js +22 -1
  81. data/node_modules/prettier/parser-espree.js +22 -1
  82. data/node_modules/prettier/parser-flow.js +22 -1
  83. data/node_modules/prettier/parser-glimmer.js +1 -1
  84. data/node_modules/prettier/parser-graphql.js +1 -1
  85. data/node_modules/prettier/parser-html.js +82 -63
  86. data/node_modules/prettier/parser-markdown.js +24 -9
  87. data/node_modules/prettier/parser-meriyah.js +22 -1
  88. data/node_modules/prettier/parser-postcss.js +22 -1
  89. data/node_modules/prettier/parser-typescript.js +22 -1
  90. data/node_modules/prettier/parser-yaml.js +2 -2
  91. data/node_modules/prettier/third-party.js +1734 -862
  92. data/package.json +27 -19
  93. data/rubocop.yml +9 -0
  94. metadata +77 -77
  95. data/src/haml/embed.js +0 -87
  96. data/src/haml/nodes/comment.js +0 -27
  97. data/src/haml/nodes/doctype.js +0 -34
  98. data/src/haml/nodes/filter.js +0 -16
  99. data/src/haml/nodes/hamlComment.js +0 -21
  100. data/src/haml/nodes/plain.js +0 -6
  101. data/src/haml/nodes/root.js +0 -8
  102. data/src/haml/nodes/script.js +0 -33
  103. data/src/haml/nodes/silentScript.js +0 -59
  104. data/src/haml/nodes/tag.js +0 -232
  105. data/src/haml/parser.js +0 -22
  106. data/src/haml/printer.js +0 -28
  107. data/src/parser/parseSync.js +0 -170
  108. data/src/parser/server.rb +0 -66
  109. data/src/plugin.js +0 -148
  110. data/src/prettier.js +0 -16
  111. data/src/rbs/parser.js +0 -39
  112. data/src/rbs/printer.js +0 -615
  113. data/src/ruby/embed.js +0 -142
  114. data/src/ruby/nodes/alias.js +0 -73
  115. data/src/ruby/nodes/args.js +0 -178
  116. data/src/ruby/nodes/arrays.js +0 -162
  117. data/src/ruby/nodes/assign.js +0 -47
  118. data/src/ruby/nodes/blocks.js +0 -90
  119. data/src/ruby/nodes/calls.js +0 -199
  120. data/src/ruby/nodes/case.js +0 -65
  121. data/src/ruby/nodes/class.js +0 -64
  122. data/src/ruby/nodes/commands.js +0 -131
  123. data/src/ruby/nodes/conditionals.js +0 -280
  124. data/src/ruby/nodes/constants.js +0 -43
  125. data/src/ruby/nodes/flow.js +0 -74
  126. data/src/ruby/nodes/hashes.js +0 -164
  127. data/src/ruby/nodes/heredocs.js +0 -36
  128. data/src/ruby/nodes/hooks.js +0 -34
  129. data/src/ruby/nodes/ints.js +0 -31
  130. data/src/ruby/nodes/lambdas.js +0 -76
  131. data/src/ruby/nodes/loops.js +0 -98
  132. data/src/ruby/nodes/massign.js +0 -98
  133. data/src/ruby/nodes/methods.js +0 -74
  134. data/src/ruby/nodes/operators.js +0 -83
  135. data/src/ruby/nodes/params.js +0 -113
  136. data/src/ruby/nodes/patterns.js +0 -157
  137. data/src/ruby/nodes/regexp.js +0 -56
  138. data/src/ruby/nodes/rescue.js +0 -101
  139. data/src/ruby/nodes/return.js +0 -94
  140. data/src/ruby/nodes/statements.js +0 -142
  141. data/src/ruby/nodes/strings.js +0 -177
  142. data/src/ruby/nodes/super.js +0 -35
  143. data/src/ruby/nodes/undef.js +0 -42
  144. data/src/ruby/nodes.js +0 -34
  145. data/src/ruby/parser.js +0 -39
  146. data/src/ruby/printer.js +0 -138
  147. data/src/ruby/toProc.js +0 -105
  148. data/src/utils/containsAssignment.js +0 -11
  149. data/src/utils/getTrailingComma.js +0 -5
  150. data/src/utils/hasAncestor.js +0 -17
  151. data/src/utils/isEmptyBodyStmt.js +0 -7
  152. data/src/utils/isEmptyStmts.js +0 -11
  153. data/src/utils/literal.js +0 -7
  154. data/src/utils/literallineWithoutBreakParent.js +0 -7
  155. data/src/utils/makeCall.js +0 -14
  156. data/src/utils/noIndent.js +0 -11
  157. data/src/utils/printEmptyCollection.js +0 -49
  158. data/src/utils/skipAssignIndent.js +0 -10
  159. data/src/utils.js +0 -13
@@ -1,280 +0,0 @@
1
- const {
2
- align,
3
- breakParent,
4
- concat,
5
- hardline,
6
- group,
7
- ifBreak,
8
- indent,
9
- softline
10
- } = require("../../prettier");
11
-
12
- const { containsAssignment, isEmptyStmts } = require("../../utils");
13
- const inlineEnsureParens = require("../../utils/inlineEnsureParens");
14
-
15
- const printWithAddition = (keyword, path, print, { breaking = false } = {}) =>
16
- concat([
17
- `${keyword} `,
18
- align(keyword.length + 1, path.call(print, "body", 0)),
19
- indent(concat([softline, path.call(print, "body", 1)])),
20
- concat([softline, path.call(print, "body", 2)]),
21
- concat([softline, "end"]),
22
- breaking ? breakParent : ""
23
- ]);
24
-
25
- // For the unary `not` operator, we need to explicitly add parentheses to it in
26
- // order for it to be valid from within a ternary. Otherwise if the clause of
27
- // the ternary isn't a unary `not`, we can just pass it along.
28
- const printTernaryClause = (clause) => {
29
- if (clause.type === "concat") {
30
- const [part] = clause.parts;
31
-
32
- if (part.type === "concat" && part.parts[0] === "not") {
33
- // We are inside of a statements list and the statement is a unary `not`.
34
- return concat(["not(", part.parts[2], ")"]);
35
- }
36
-
37
- if (clause.parts[0] === "not") {
38
- // We are inside a ternary condition and the clause is a unary `not`.
39
- return concat(["not(", clause.parts[2], ")"]);
40
- }
41
- }
42
-
43
- return clause;
44
- };
45
-
46
- // The conditions for a ternary look like `foo : bar` where `foo` represents
47
- // the truthy clause and `bar` represents the falsy clause. In the case that the
48
- // parent node is an `unless`, these have to flip in order.
49
- const printTernaryClauses = (keyword, truthyClause, falsyClause) => {
50
- const parts = [
51
- printTernaryClause(truthyClause),
52
- " : ",
53
- printTernaryClause(falsyClause)
54
- ];
55
-
56
- return keyword === "if" ? parts : parts.reverse();
57
- };
58
-
59
- // Handles ternary nodes. If it does not fit on one line, then we break out into
60
- // an if/else statement. Otherwise we remain as a ternary.
61
- const printTernary = (path, _opts, print) => {
62
- const [predicate, truthyClause, falsyClause] = path.map(print, "body");
63
- const ternaryClauses = printTernaryClauses("if", truthyClause, falsyClause);
64
-
65
- return group(
66
- ifBreak(
67
- concat([
68
- "if ",
69
- align(3, predicate),
70
- indent(concat([softline, truthyClause])),
71
- concat([softline, "else"]),
72
- indent(concat([softline, falsyClause])),
73
- concat([softline, "end"])
74
- ]),
75
- concat([predicate, " ? "].concat(ternaryClauses))
76
- )
77
- );
78
- };
79
-
80
- // Prints an `if_mod` or `unless_mod` node. Because it was previously in the
81
- // modifier form, we're guaranteed to not have an additional node, so we can
82
- // just work with the predicate and the body.
83
- function printSingle(keyword, modifier = false) {
84
- return function printSingleWithKeyword(path, { rubyModifier }, print) {
85
- const [_predicateNode, statementsNode] = path.getValue().body;
86
- const predicateDoc = path.call(print, "body", 0);
87
- const statementsDoc = path.call(print, "body", 1);
88
-
89
- const multilineParts = [
90
- `${keyword} `,
91
- align(keyword.length + 1, predicateDoc),
92
- indent(concat([softline, statementsDoc])),
93
- softline,
94
- "end"
95
- ];
96
-
97
- // If we do not allow modifier form conditionals or there are comments
98
- // inside of the body of the conditional, then we must print in the
99
- // multiline form.
100
- if (!rubyModifier || (!modifier && statementsNode.body[0].comments)) {
101
- return concat([concat(multilineParts), breakParent]);
102
- }
103
-
104
- const inline = concat(
105
- inlineEnsureParens(path, [
106
- path.call(print, "body", 1),
107
- ` ${keyword} `,
108
- path.call(print, "body", 0)
109
- ])
110
- );
111
-
112
- // An expression with a conditional modifier (expression if true), the
113
- // conditional body is parsed before the predicate expression, meaning that
114
- // if the parser encountered a variable declaration, it would initialize
115
- // that variable first before evaluating the predicate expression. That
116
- // parse order means the difference between a NameError or not. #591
117
- // https://docs.ruby-lang.org/en/2.0.0/syntax/control_expressions_rdoc.html#label-Modifier+if+and+unless
118
- if (modifier && containsAssignment(statementsNode)) {
119
- return inline;
120
- }
121
-
122
- return group(ifBreak(concat(multilineParts), inline));
123
- };
124
- }
125
-
126
- const noTernary = [
127
- "alias",
128
- "assign",
129
- "break",
130
- "command",
131
- "command_call",
132
- "if_mod",
133
- "ifop",
134
- "lambda",
135
- "massign",
136
- "next",
137
- "opassign",
138
- "rescue_mod",
139
- "return",
140
- "return0",
141
- "super",
142
- "undef",
143
- "unless_mod",
144
- "until_mod",
145
- "var_alias",
146
- "void_stmt",
147
- "while_mod",
148
- "yield",
149
- "yield0",
150
- "zsuper"
151
- ];
152
-
153
- // Certain expressions cannot be reduced to a ternary without adding parens
154
- // around them. In this case we say they cannot be ternaried and default instead
155
- // to breaking them into multiple lines.
156
- const canTernaryStmts = (stmts) => {
157
- if (stmts.body.length !== 1) {
158
- return false;
159
- }
160
-
161
- const stmt = stmts.body[0];
162
-
163
- // If the user is using one of the lower precedence "and" or "or" operators,
164
- // then we can't use a ternary expression as it would break the flow control.
165
- if (stmt.type === "binary" && ["and", "or"].includes(stmt.body[1])) {
166
- return false;
167
- }
168
-
169
- // Check against the blocklist of statement types that are not allowed to be
170
- // a part of a ternary expression.
171
- return !noTernary.includes(stmt.type);
172
- };
173
-
174
- // In order for an `if` or `unless` expression to be shortened to a ternary,
175
- // there has to be one and only one "addition" (another clause attached) which
176
- // is of the "else" type. Both the body of the main node and the body of the
177
- // additional node must have only one statement, and that statement list must
178
- // pass the `canTernaryStmts` check.
179
- const canTernary = (path) => {
180
- const [predicate, stmts, addition] = path.getValue().body;
181
-
182
- return (
183
- !["assign", "opassign", "command_call", "command"].includes(
184
- predicate.type
185
- ) &&
186
- addition &&
187
- addition.type === "else" &&
188
- [stmts, addition.body[0]].every(canTernaryStmts)
189
- );
190
- };
191
-
192
- // A normalized print function for both `if` and `unless` nodes.
193
- const printConditional = (keyword) => (path, { rubyModifier }, print) => {
194
- if (canTernary(path)) {
195
- let ternaryParts = [path.call(print, "body", 0), " ? "].concat(
196
- printTernaryClauses(
197
- keyword,
198
- path.call(print, "body", 1),
199
- path.call(print, "body", 2, "body", 0)
200
- )
201
- );
202
-
203
- if (["binary", "call"].includes(path.getParentNode().type)) {
204
- ternaryParts = ["("].concat(ternaryParts).concat(")");
205
- }
206
-
207
- return group(
208
- ifBreak(printWithAddition(keyword, path, print), concat(ternaryParts))
209
- );
210
- }
211
-
212
- const [predicate, statements, addition] = path.getValue().body;
213
-
214
- // If there's an additional clause that wasn't matched earlier, we know we
215
- // can't go for the inline option.
216
- if (addition) {
217
- return group(printWithAddition(keyword, path, print, { breaking: true }));
218
- }
219
-
220
- // If the body of the conditional is empty, then we explicitly have to use the
221
- // block form.
222
- if (isEmptyStmts(statements)) {
223
- return concat([
224
- `${keyword} `,
225
- align(keyword.length + 1, path.call(print, "body", 0)),
226
- concat([hardline, "end"])
227
- ]);
228
- }
229
-
230
- // If the predicate of the conditional contains an assignment, then we can't
231
- // know for sure that it doesn't impact the body of the conditional, so we
232
- // have to default to the block form.
233
- if (containsAssignment(predicate)) {
234
- return concat([
235
- `${keyword} `,
236
- align(keyword.length + 1, path.call(print, "body", 0)),
237
- indent(concat([hardline, path.call(print, "body", 1)])),
238
- concat([hardline, "end"])
239
- ]);
240
- }
241
-
242
- return printSingle(keyword)(path, { rubyModifier }, print);
243
- };
244
-
245
- module.exports = {
246
- else: (path, opts, print) => {
247
- const stmts = path.getValue().body[0];
248
-
249
- return concat([
250
- stmts.body.length === 1 && stmts.body[0].type === "command"
251
- ? breakParent
252
- : "",
253
- "else",
254
- indent(concat([softline, path.call(print, "body", 0)]))
255
- ]);
256
- },
257
- elsif: (path, opts, print) => {
258
- const [_predicate, _statements, addition] = path.getValue().body;
259
- const parts = [
260
- group(
261
- concat([
262
- "elsif ",
263
- align("elsif".length - 1, path.call(print, "body", 0))
264
- ])
265
- ),
266
- indent(concat([hardline, path.call(print, "body", 1)]))
267
- ];
268
-
269
- if (addition) {
270
- parts.push(group(concat([hardline, path.call(print, "body", 2)])));
271
- }
272
-
273
- return group(concat(parts));
274
- },
275
- if: printConditional("if"),
276
- ifop: printTernary,
277
- if_mod: printSingle("if", true),
278
- unless: printConditional("unless"),
279
- unless_mod: printSingle("unless", true)
280
- };
@@ -1,43 +0,0 @@
1
- const { concat, group, indent, join, softline } = require("../../prettier");
2
- const { makeCall } = require("../../utils");
3
-
4
- function printConstPath(path, opts, print) {
5
- return join("::", path.map(print, "body"));
6
- }
7
-
8
- function printConstRef(path, opts, print) {
9
- return path.call(print, "body", 0);
10
- }
11
-
12
- function printDefined(path, opts, print) {
13
- return group(
14
- concat([
15
- "defined?(",
16
- indent(concat([softline, path.call(print, "body", 0)])),
17
- concat([softline, ")"])
18
- ])
19
- );
20
- }
21
-
22
- function printField(path, opts, print) {
23
- return group(
24
- concat([
25
- path.call(print, "body", 0),
26
- concat([makeCall(path, opts, print), path.call(print, "body", 2)])
27
- ])
28
- );
29
- }
30
-
31
- function printTopConst(path, opts, print) {
32
- return concat(["::", path.call(print, "body", 0)]);
33
- }
34
-
35
- module.exports = {
36
- const_path_field: printConstPath,
37
- const_path_ref: printConstPath,
38
- const_ref: printConstRef,
39
- defined: printDefined,
40
- field: printField,
41
- top_const_field: printTopConst,
42
- top_const_ref: printTopConst
43
- };
@@ -1,74 +0,0 @@
1
- const { concat, join } = require("../../prettier");
2
- const { literal } = require("../../utils");
3
-
4
- const nodeDive = (node, steps) => {
5
- let current = node;
6
-
7
- steps.forEach((step) => {
8
- current = current[step];
9
- });
10
-
11
- return current;
12
- };
13
-
14
- const unskippableParens = [
15
- "if_mod",
16
- "rescue_mod",
17
- "unless_mod",
18
- "until_mod",
19
- "while_mod"
20
- ];
21
-
22
- const maybeHandleParens = (path, print, keyword, steps) => {
23
- const node = nodeDive(path.getValue(), steps);
24
- if (node.type !== "paren") {
25
- return null;
26
- }
27
-
28
- const stmts = node.body[0].body;
29
- if (stmts.length === 1 && !unskippableParens.includes(stmts[0].type)) {
30
- return concat([
31
- `${keyword} `,
32
- path.call.apply(path, [print].concat(steps).concat("body", 0))
33
- ]);
34
- }
35
-
36
- return concat([keyword, path.call.apply(path, [print].concat(steps))]);
37
- };
38
-
39
- module.exports = {
40
- break: (path, opts, print) => {
41
- const content = path.getValue().body[0];
42
-
43
- if (content.body.length === 0) {
44
- return "break";
45
- }
46
-
47
- const steps = ["body", 0, "body", 0, "body", 0];
48
- return (
49
- maybeHandleParens(path, print, "break", steps) ||
50
- concat(["break ", join(", ", path.call(print, "body", 0))])
51
- );
52
- },
53
- next: (path, opts, print) => {
54
- const args = path.getValue().body[0].body[0];
55
-
56
- if (!args) {
57
- return "next";
58
- }
59
-
60
- const steps = ["body", 0, "body", 0, "body", 0];
61
- return (
62
- maybeHandleParens(path, print, "next", steps) ||
63
- concat(["next ", join(", ", path.call(print, "body", 0))])
64
- );
65
- },
66
- yield: (path, opts, print) => {
67
- if (path.getValue().body[0].type === "paren") {
68
- return concat(["yield", path.call(print, "body", 0)]);
69
- }
70
-
71
- return concat(["yield ", join(", ", path.call(print, "body", 0))]);
72
- },
73
- yield0: literal("yield")
74
- };
@@ -1,164 +0,0 @@
1
- const {
2
- concat,
3
- group,
4
- ifBreak,
5
- indent,
6
- join,
7
- line
8
- } = require("../../prettier");
9
-
10
- const {
11
- getTrailingComma,
12
- printEmptyCollection,
13
- skipAssignIndent
14
- } = require("../../utils");
15
-
16
- // When attempting to convert a hash rocket into a hash label, you need to take
17
- // care because only certain patterns are allowed. Ruby source says that they
18
- // have to match keyword arguments to methods, but don't specify what that is.
19
- // After some experimentation, it looks like it's:
20
- //
21
- // * Starts with a letter (either case) or an underscore
22
- // * Does not end in equal
23
- //
24
- // This function represents that check, as it determines if it can convert the
25
- // symbol node into a hash label.
26
- function isValidHashLabel(symbolLiteral) {
27
- const label = symbolLiteral.body[0].body;
28
- return label.match(/^[_A-Za-z]/) && !label.endsWith("=");
29
- }
30
-
31
- function canUseHashLabels(contentsNode) {
32
- return contentsNode.body.every((assocNode) => {
33
- if (assocNode.type === "assoc_splat") {
34
- return true;
35
- }
36
-
37
- switch (assocNode.body[0].type) {
38
- case "@label":
39
- return true;
40
- case "symbol_literal":
41
- return isValidHashLabel(assocNode.body[0]);
42
- case "dyna_symbol":
43
- return true;
44
- default:
45
- return false;
46
- }
47
- });
48
- }
49
-
50
- function printHashKeyLabel(path, print) {
51
- const node = path.getValue();
52
-
53
- switch (node.type) {
54
- case "@label":
55
- return print(path);
56
- case "symbol_literal":
57
- return concat([path.call(print, "body", 0), ":"]);
58
- case "dyna_symbol": {
59
- const { parts } = print(path);
60
-
61
- // We're going to slice off the starting colon character so that we can
62
- // move it to the end. If there are comments, then we're going to go
63
- // further into the printed doc nodes.
64
- if (parts[0] === ":") {
65
- parts.splice(0, 1);
66
- } else {
67
- parts[1].parts.splice(0, 1);
68
- }
69
-
70
- return concat(parts.concat(":"));
71
- }
72
- }
73
- }
74
-
75
- function printHashKeyRocket(path, print) {
76
- const node = path.getValue();
77
- const doc = print(path);
78
-
79
- if (node.type === "@label") {
80
- return `:${doc.slice(0, doc.length - 1)} =>`;
81
- }
82
-
83
- return concat([doc, " =>"]);
84
- }
85
-
86
- function printAssocNew(path, opts, print) {
87
- const [keyNode, valueNode] = path.getValue().body;
88
- const { keyPrinter } = path.getParentNode();
89
-
90
- const parts = [path.call((keyPath) => keyPrinter(keyPath, print), "body", 0)];
91
- const valueDoc = path.call(print, "body", 1);
92
-
93
- // If we're printing a child hash then we want it to break along with its
94
- // parent hash, so we don't group the parts.
95
- if (valueNode.type === "hash") {
96
- parts.push(" ", valueDoc);
97
- return concat(parts);
98
- }
99
-
100
- if (!skipAssignIndent(valueNode) || keyNode.comments) {
101
- parts.push(indent(concat([line, valueDoc])));
102
- } else {
103
- parts.push(" ", valueDoc);
104
- }
105
-
106
- return group(concat(parts));
107
- }
108
-
109
- function printAssocSplat(path, opts, print) {
110
- return concat(["**", path.call(print, "body", 0)]);
111
- }
112
-
113
- function printHashContents(path, opts, print) {
114
- const node = path.getValue();
115
-
116
- // First determine which key printer we're going to use, so that the child
117
- // nodes can reference it when they go to get printed.
118
- node.keyPrinter =
119
- opts.rubyHashLabel && canUseHashLabels(path.getValue())
120
- ? printHashKeyLabel
121
- : printHashKeyRocket;
122
-
123
- return join(concat([",", line]), path.map(print, "body"));
124
- }
125
-
126
- function printHash(path, opts, print) {
127
- const hashNode = path.getValue();
128
-
129
- // Hashes normally have a single assoclist_from_args child node. If it's
130
- // missing, then it means we're dealing with an empty hash, so we can just
131
- // exit here and print.
132
- if (hashNode.body[0] === null) {
133
- return printEmptyCollection(path, opts, "{", "}");
134
- }
135
-
136
- let hashDoc = concat([
137
- "{",
138
- indent(
139
- concat([
140
- line,
141
- path.call(print, "body", 0),
142
- getTrailingComma(opts) ? ifBreak(",", "") : ""
143
- ])
144
- ),
145
- line,
146
- "}"
147
- ]);
148
-
149
- // If we're inside another hash, then we don't want to group our contents
150
- // because we want this hash to break along with its parent hash.
151
- if (path.getParentNode().type === "assoc_new") {
152
- return hashDoc;
153
- }
154
-
155
- return group(hashDoc);
156
- }
157
-
158
- module.exports = {
159
- assoc_new: printAssocNew,
160
- assoc_splat: printAssocSplat,
161
- assoclist_from_args: printHashContents,
162
- bare_assoc_hash: printHashContents,
163
- hash: printHash
164
- };
@@ -1,36 +0,0 @@
1
- const { concat, group, lineSuffix, join } = require("../../prettier");
2
- const { literallineWithoutBreakParent } = require("../../utils");
3
-
4
- function printHeredoc(path, opts, print) {
5
- const { body, ending } = path.getValue();
6
-
7
- const parts = body.map((part, index) => {
8
- if (part.type !== "@tstring_content") {
9
- // In this case, the part of the string is an embedded expression
10
- return path.call(print, "body", index);
11
- }
12
-
13
- // In this case, the part of the string is just regular string content
14
- return join(literallineWithoutBreakParent, part.body.split("\n"));
15
- });
16
-
17
- // We use a literalline break because matching indentation is required
18
- // for the heredoc contents and ending. If the line suffix contains a
19
- // break-parent, all ancestral groups are broken, and heredocs automatically
20
- // break lines in groups they appear in. We prefer them to appear in-line if
21
- // possible, so we use a literalline without the break-parent.
22
- return group(
23
- concat([
24
- path.call(print, "beging"),
25
- lineSuffix(
26
- group(
27
- concat([literallineWithoutBreakParent].concat(parts).concat(ending))
28
- )
29
- )
30
- ])
31
- );
32
- }
33
-
34
- module.exports = {
35
- heredoc: printHeredoc
36
- };
@@ -1,34 +0,0 @@
1
- const { concat, group, indent, line } = require("../../prettier");
2
-
3
- // The `BEGIN` and `END` keywords are used to hook into the Ruby process. Any
4
- // `BEGIN` blocks are executed right when the process starts up, and the `END`
5
- // blocks are executed right before exiting.
6
- //
7
- // BEGIN {
8
- // # content goes here
9
- // }
10
- //
11
- // END {
12
- // # content goes here
13
- // }
14
- //
15
- // Interesting side note, you don't use `do...end` blocks with these hooks. Both
16
- // nodes contain one child which is a `stmts` node.
17
- function printHook(name) {
18
- return function printHookWithName(path, opts, print) {
19
- return group(
20
- concat([
21
- name,
22
- " ",
23
- path.call(print, "body", 0),
24
- indent(concat([line, path.call(print, "body", 1)])),
25
- concat([line, "}"])
26
- ])
27
- );
28
- };
29
- }
30
-
31
- module.exports = {
32
- BEGIN: printHook("BEGIN"),
33
- END: printHook("END")
34
- };
@@ -1,31 +0,0 @@
1
- // An @int node is any literal integer in Ruby. They can come in a number of
2
- // bases, and look like the following:
3
- //
4
- // Binary (2) - 0b0110
5
- // Octal (8) - 0o34 or 034
6
- // Decimal (10) - a normal number like 159
7
- // Hexidecimal (16) - 0xac5
8
- //
9
- // If it's a decimal number, it can be optional separated by any number of
10
- // arbitrarily places underscores. This can be useful for dollars and cents
11
- // (34_99), dates (2020_11_30), and normal 3 digit separation (1_222_333).
12
- function printInt(path, _opts, _print) {
13
- const { body } = path.getValue();
14
-
15
- // If the number is a base 10 number, is sufficiently large, and is not
16
- // already formatted with underscores, then add them in in between the
17
- // numbers every three characters starting from the right.
18
- if (!body.startsWith("0") && body.length >= 5 && !body.includes("_")) {
19
- return ` ${body}`
20
- .slice((body.length + 2) % 3)
21
- .match(/.{3}/g)
22
- .join("_")
23
- .trim();
24
- }
25
-
26
- return body;
27
- }
28
-
29
- module.exports = {
30
- "@int": printInt
31
- };