prettier 1.6.1 → 2.0.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +316 -293
  3. data/CONTRIBUTING.md +6 -9
  4. data/LICENSE +1 -1
  5. data/README.md +11 -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 +128 -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 +220 -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 +1215 -252
  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 -17
  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 +313 -190
  76. data/node_modules/prettier/doc.js +191 -323
  77. data/node_modules/prettier/index.js +2753 -3677
  78. data/node_modules/prettier/package.json +1 -1
  79. data/node_modules/prettier/parser-angular.js +13 -14
  80. data/node_modules/prettier/parser-babel.js +7 -7
  81. data/node_modules/prettier/parser-espree.js +7 -7
  82. data/node_modules/prettier/parser-flow.js +7 -7
  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 +17 -17
  86. data/node_modules/prettier/parser-markdown.js +9 -9
  87. data/node_modules/prettier/parser-meriyah.js +7 -7
  88. data/node_modules/prettier/parser-postcss.js +2 -2
  89. data/node_modules/prettier/parser-typescript.js +7 -7
  90. data/node_modules/prettier/parser-yaml.js +2 -2
  91. data/node_modules/prettier/third-party.js +143 -78
  92. data/package.json +26 -18
  93. metadata +74 -67
  94. data/src/haml/embed.js +0 -87
  95. data/src/haml/parser.js +0 -23
  96. data/src/haml/printer.js +0 -438
  97. data/src/parser/parseSync.js +0 -172
  98. data/src/parser/server.rb +0 -66
  99. data/src/plugin.js +0 -148
  100. data/src/prettier.js +0 -16
  101. data/src/rbs/parser.js +0 -37
  102. data/src/rbs/printer.js +0 -643
  103. data/src/ruby/embed.js +0 -142
  104. data/src/ruby/nodes/alias.js +0 -73
  105. data/src/ruby/nodes/args.js +0 -222
  106. data/src/ruby/nodes/arrays.js +0 -162
  107. data/src/ruby/nodes/assign.js +0 -47
  108. data/src/ruby/nodes/blocks.js +0 -90
  109. data/src/ruby/nodes/calls.js +0 -246
  110. data/src/ruby/nodes/case.js +0 -65
  111. data/src/ruby/nodes/class.js +0 -64
  112. data/src/ruby/nodes/commands.js +0 -131
  113. data/src/ruby/nodes/conditionals.js +0 -282
  114. data/src/ruby/nodes/constants.js +0 -43
  115. data/src/ruby/nodes/flow.js +0 -74
  116. data/src/ruby/nodes/hashes.js +0 -155
  117. data/src/ruby/nodes/heredocs.js +0 -36
  118. data/src/ruby/nodes/hooks.js +0 -34
  119. data/src/ruby/nodes/ints.js +0 -31
  120. data/src/ruby/nodes/lambdas.js +0 -76
  121. data/src/ruby/nodes/loops.js +0 -98
  122. data/src/ruby/nodes/massign.js +0 -98
  123. data/src/ruby/nodes/methods.js +0 -74
  124. data/src/ruby/nodes/operators.js +0 -83
  125. data/src/ruby/nodes/params.js +0 -106
  126. data/src/ruby/nodes/patterns.js +0 -157
  127. data/src/ruby/nodes/regexp.js +0 -56
  128. data/src/ruby/nodes/rescue.js +0 -101
  129. data/src/ruby/nodes/return.js +0 -94
  130. data/src/ruby/nodes/statements.js +0 -142
  131. data/src/ruby/nodes/strings.js +0 -272
  132. data/src/ruby/nodes/super.js +0 -35
  133. data/src/ruby/nodes/undef.js +0 -42
  134. data/src/ruby/nodes.js +0 -34
  135. data/src/ruby/parser.js +0 -37
  136. data/src/ruby/printer.js +0 -147
  137. data/src/ruby/toProc.js +0 -105
  138. data/src/utils/containsAssignment.js +0 -11
  139. data/src/utils/getTrailingComma.js +0 -5
  140. data/src/utils/hasAncestor.js +0 -17
  141. data/src/utils/isEmptyBodyStmt.js +0 -7
  142. data/src/utils/isEmptyStmts.js +0 -11
  143. data/src/utils/literal.js +0 -7
  144. data/src/utils/literallineWithoutBreakParent.js +0 -7
  145. data/src/utils/makeCall.js +0 -14
  146. data/src/utils/noIndent.js +0 -10
  147. data/src/utils/printEmptyCollection.js +0 -49
  148. data/src/utils/skipAssignIndent.js +0 -17
  149. data/src/utils.js +0 -13
@@ -1,282 +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 =
194
- (keyword) =>
195
- (path, { rubyModifier }, print) => {
196
- if (canTernary(path)) {
197
- let ternaryParts = [path.call(print, "body", 0), " ? "].concat(
198
- printTernaryClauses(
199
- keyword,
200
- path.call(print, "body", 1),
201
- path.call(print, "body", 2, "body", 0)
202
- )
203
- );
204
-
205
- if (["binary", "call"].includes(path.getParentNode().type)) {
206
- ternaryParts = ["("].concat(ternaryParts).concat(")");
207
- }
208
-
209
- return group(
210
- ifBreak(printWithAddition(keyword, path, print), concat(ternaryParts))
211
- );
212
- }
213
-
214
- const [predicate, statements, addition] = path.getValue().body;
215
-
216
- // If there's an additional clause that wasn't matched earlier, we know we
217
- // can't go for the inline option.
218
- if (addition) {
219
- return group(printWithAddition(keyword, path, print, { breaking: true }));
220
- }
221
-
222
- // If the body of the conditional is empty, then we explicitly have to use the
223
- // block form.
224
- if (isEmptyStmts(statements)) {
225
- return concat([
226
- `${keyword} `,
227
- align(keyword.length + 1, path.call(print, "body", 0)),
228
- concat([hardline, "end"])
229
- ]);
230
- }
231
-
232
- // If the predicate of the conditional contains an assignment, then we can't
233
- // know for sure that it doesn't impact the body of the conditional, so we
234
- // have to default to the block form.
235
- if (containsAssignment(predicate)) {
236
- return concat([
237
- `${keyword} `,
238
- align(keyword.length + 1, path.call(print, "body", 0)),
239
- indent(concat([hardline, path.call(print, "body", 1)])),
240
- concat([hardline, "end"])
241
- ]);
242
- }
243
-
244
- return printSingle(keyword)(path, { rubyModifier }, print);
245
- };
246
-
247
- module.exports = {
248
- else: (path, opts, print) => {
249
- const stmts = path.getValue().body[0];
250
-
251
- return concat([
252
- stmts.body.length === 1 && stmts.body[0].type === "command"
253
- ? breakParent
254
- : "",
255
- "else",
256
- indent(concat([softline, path.call(print, "body", 0)]))
257
- ]);
258
- },
259
- elsif: (path, opts, print) => {
260
- const [_predicate, _statements, addition] = path.getValue().body;
261
- const parts = [
262
- group(
263
- concat([
264
- "elsif ",
265
- align("elsif".length - 1, path.call(print, "body", 0))
266
- ])
267
- ),
268
- indent(concat([hardline, path.call(print, "body", 1)]))
269
- ];
270
-
271
- if (addition) {
272
- parts.push(group(concat([hardline, path.call(print, "body", 2)])));
273
- }
274
-
275
- return group(concat(parts));
276
- },
277
- if: printConditional("if"),
278
- ifop: printTernary,
279
- if_mod: printSingle("if", true),
280
- unless: printConditional("unless"),
281
- unless_mod: printSingle("unless", true)
282
- };
@@ -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,155 +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
- return concat([print(path), ":"]);
60
- }
61
- }
62
- }
63
-
64
- function printHashKeyRocket(path, print) {
65
- const node = path.getValue();
66
- let doc = print(path);
67
-
68
- if (node.type === "@label") {
69
- doc = concat([":", doc.slice(0, doc.length - 1)]);
70
- } else if (node.type === "dyna_symbol") {
71
- doc = concat([":", doc]);
72
- }
73
-
74
- return concat([doc, " =>"]);
75
- }
76
-
77
- function printAssocNew(path, opts, print) {
78
- const [keyNode, valueNode] = path.getValue().body;
79
- const { keyPrinter } = path.getParentNode();
80
-
81
- const parts = [path.call((keyPath) => keyPrinter(keyPath, print), "body", 0)];
82
- const valueDoc = path.call(print, "body", 1);
83
-
84
- // If we're printing a child hash then we want it to break along with its
85
- // parent hash, so we don't group the parts.
86
- if (valueNode.type === "hash") {
87
- parts.push(" ", valueDoc);
88
- return concat(parts);
89
- }
90
-
91
- if (!skipAssignIndent(valueNode) || keyNode.comments) {
92
- parts.push(indent(concat([line, valueDoc])));
93
- } else {
94
- parts.push(" ", valueDoc);
95
- }
96
-
97
- return group(concat(parts));
98
- }
99
-
100
- function printAssocSplat(path, opts, print) {
101
- return concat(["**", path.call(print, "body", 0)]);
102
- }
103
-
104
- function printHashContents(path, opts, print) {
105
- const node = path.getValue();
106
-
107
- // First determine which key printer we're going to use, so that the child
108
- // nodes can reference it when they go to get printed.
109
- node.keyPrinter =
110
- opts.rubyHashLabel && canUseHashLabels(path.getValue())
111
- ? printHashKeyLabel
112
- : printHashKeyRocket;
113
-
114
- return join(concat([",", line]), path.map(print, "body"));
115
- }
116
-
117
- function printHash(path, opts, print) {
118
- const hashNode = path.getValue();
119
-
120
- // Hashes normally have a single assoclist_from_args child node. If it's
121
- // missing, then it means we're dealing with an empty hash, so we can just
122
- // exit here and print.
123
- if (hashNode.body[0] === null) {
124
- return printEmptyCollection(path, opts, "{", "}");
125
- }
126
-
127
- let hashDoc = concat([
128
- "{",
129
- indent(
130
- concat([
131
- line,
132
- path.call(print, "body", 0),
133
- getTrailingComma(opts) ? ifBreak(",", "") : ""
134
- ])
135
- ),
136
- line,
137
- "}"
138
- ]);
139
-
140
- // If we're inside another hash, then we don't want to group our contents
141
- // because we want this hash to break along with its parent hash.
142
- if (path.getParentNode().type === "assoc_new") {
143
- return hashDoc;
144
- }
145
-
146
- return group(hashDoc);
147
- }
148
-
149
- module.exports = {
150
- assoc_new: printAssocNew,
151
- assoc_splat: printAssocSplat,
152
- assoclist_from_args: printHashContents,
153
- bare_assoc_hash: printHashContents,
154
- hash: printHash
155
- };
@@ -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
- };