prettier 2.1.0 → 3.0.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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -6
  3. data/README.md +16 -16
  4. data/exe/rbprettier +2 -2
  5. data/lib/prettier/rake/task.rb +5 -5
  6. data/lib/prettier.rb +11 -11
  7. data/package.json +9 -23
  8. data/rubocop.yml +6 -6
  9. data/{dist/parser → src}/getInfo.js +0 -1
  10. data/{dist/parser → src}/netcat.js +0 -1
  11. data/src/parseSync.js +212 -0
  12. data/src/plugin.js +161 -0
  13. data/{dist/parser → src}/server.rb +45 -31
  14. metadata +94 -78
  15. data/bin/console +0 -7
  16. data/dist/haml/embed.js +0 -53
  17. data/dist/haml/parser.js +0 -31
  18. data/dist/haml/parser.rb +0 -149
  19. data/dist/haml/printer.js +0 -336
  20. data/dist/parser/parseSync.js +0 -179
  21. data/dist/plugin.js +0 -143
  22. data/dist/prettier.js +0 -15
  23. data/dist/rbs/parser.js +0 -34
  24. data/dist/rbs/parser.rb +0 -155
  25. data/dist/rbs/printer.js +0 -525
  26. data/dist/ruby/embed.js +0 -115
  27. data/dist/ruby/location.js +0 -19
  28. data/dist/ruby/nodes/alias.js +0 -60
  29. data/dist/ruby/nodes/aref.js +0 -51
  30. data/dist/ruby/nodes/args.js +0 -138
  31. data/dist/ruby/nodes/arrays.js +0 -122
  32. data/dist/ruby/nodes/assign.js +0 -37
  33. data/dist/ruby/nodes/blocks.js +0 -90
  34. data/dist/ruby/nodes/calls.js +0 -263
  35. data/dist/ruby/nodes/case.js +0 -50
  36. data/dist/ruby/nodes/class.js +0 -54
  37. data/dist/ruby/nodes/commands.js +0 -138
  38. data/dist/ruby/nodes/conditionals.js +0 -246
  39. data/dist/ruby/nodes/constants.js +0 -35
  40. data/dist/ruby/nodes/flow.js +0 -59
  41. data/dist/ruby/nodes/hashes.js +0 -126
  42. data/dist/ruby/nodes/heredocs.js +0 -30
  43. data/dist/ruby/nodes/hooks.js +0 -35
  44. data/dist/ruby/nodes/ints.js +0 -27
  45. data/dist/ruby/nodes/lambdas.js +0 -70
  46. data/dist/ruby/nodes/loops.js +0 -75
  47. data/dist/ruby/nodes/massign.js +0 -60
  48. data/dist/ruby/nodes/methods.js +0 -50
  49. data/dist/ruby/nodes/operators.js +0 -68
  50. data/dist/ruby/nodes/params.js +0 -95
  51. data/dist/ruby/nodes/patterns.js +0 -119
  52. data/dist/ruby/nodes/regexp.js +0 -45
  53. data/dist/ruby/nodes/rescue.js +0 -86
  54. data/dist/ruby/nodes/return.js +0 -100
  55. data/dist/ruby/nodes/statements.js +0 -110
  56. data/dist/ruby/nodes/strings.js +0 -220
  57. data/dist/ruby/nodes/super.js +0 -26
  58. data/dist/ruby/nodes/undef.js +0 -31
  59. data/dist/ruby/nodes.js +0 -177
  60. data/dist/ruby/parser.js +0 -35
  61. data/dist/ruby/parser.rb +0 -9134
  62. data/dist/ruby/printer.js +0 -67
  63. data/dist/ruby/toProc.js +0 -91
  64. data/dist/types/haml.js +0 -4
  65. data/dist/types/plugin.js +0 -3
  66. data/dist/types/rbs.js +0 -4
  67. data/dist/types/ruby.js +0 -4
  68. data/dist/types/utils.js +0 -2
  69. data/dist/types.js +0 -34
  70. data/dist/utils/containsAssignment.js +0 -18
  71. data/dist/utils/getChildNodes.js +0 -305
  72. data/dist/utils/getTrailingComma.js +0 -6
  73. data/dist/utils/hasAncestor.js +0 -15
  74. data/dist/utils/inlineEnsureParens.js +0 -49
  75. data/dist/utils/isEmptyBodyStmt.js +0 -10
  76. data/dist/utils/isEmptyParams.js +0 -12
  77. data/dist/utils/isEmptyStmts.js +0 -10
  78. data/dist/utils/literal.js +0 -8
  79. data/dist/utils/literallineWithoutBreakParent.js +0 -8
  80. data/dist/utils/makeCall.js +0 -14
  81. data/dist/utils/noIndent.js +0 -11
  82. data/dist/utils/printEmptyCollection.js +0 -46
  83. data/dist/utils/skipAssignIndent.js +0 -19
  84. data/dist/utils.js +0 -32
@@ -1,246 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printUnlessModifier = exports.printUnless = exports.printIfModifier = exports.printIf = exports.printElsif = exports.printElse = exports.printTernary = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const { align, breakParent, hardline, group, ifBreak, indent, softline } = prettier_1.default;
10
- // If the statements are just a single if/unless, in block or modifier form, or
11
- // a ternary
12
- function containsSingleConditional(stmts) {
13
- return (stmts.body.length === 1 &&
14
- ["if", "if_mod", "ifop", "unless", "unless_mod"].includes(stmts.body[0].type));
15
- }
16
- function printWithAddition(keyword, path, print, breaking) {
17
- return [
18
- `${keyword} `,
19
- align(keyword.length + 1, path.call(print, "pred")),
20
- indent([softline, path.call(print, "stmts")]),
21
- [softline, path.call(print, "cons")],
22
- [softline, "end"],
23
- breaking ? breakParent : ""
24
- ];
25
- }
26
- // For the unary `not` operator, we need to explicitly add parentheses to it in
27
- // order for it to be valid from within a ternary. Otherwise if the clause of
28
- // the ternary isn't a unary `not`, we can just pass it along.
29
- function printTernaryClause(clause) {
30
- if (Array.isArray(clause)) {
31
- const [part] = clause;
32
- if (Array.isArray(part) && part[0] === "not") {
33
- // We are inside of a statements list and the statement is a unary `not`.
34
- return ["not(", part[2], ")"];
35
- }
36
- if (clause[0] === "not") {
37
- // We are inside a ternary condition and the clause is a unary `not`.
38
- return ["not(", clause[2], ")"];
39
- }
40
- }
41
- return clause;
42
- }
43
- // The conditions for a ternary look like `foo : bar` where `foo` represents
44
- // the truthy clause and `bar` represents the falsy clause. In the case that the
45
- // parent node is an `unless`, these have to flip in order.
46
- function printTernaryClauses(keyword, truthyClause, falsyClause) {
47
- const parts = [
48
- printTernaryClause(truthyClause),
49
- " : ",
50
- printTernaryClause(falsyClause)
51
- ];
52
- return keyword === "if" ? parts : parts.reverse();
53
- }
54
- // Handles ternary nodes. If it does not fit on one line, then we break out into
55
- // an if/else statement. Otherwise we remain as a ternary.
56
- const printTernary = (path, _opts, print) => {
57
- const predicateDoc = path.call(print, "pred");
58
- const truthyDoc = path.call(print, "tthy");
59
- const falsyDoc = path.call(print, "flsy");
60
- return group(ifBreak([
61
- "if ",
62
- align(3, predicateDoc),
63
- indent([softline, truthyDoc]),
64
- [softline, "else"],
65
- indent([softline, falsyDoc]),
66
- [softline, "end"]
67
- ], [predicateDoc, " ? ", ...printTernaryClauses("if", truthyDoc, falsyDoc)]));
68
- };
69
- exports.printTernary = printTernary;
70
- function isModifier(node) {
71
- return node.type === "if_mod" || node.type === "unless_mod";
72
- }
73
- // Prints an `if_mod` or `unless_mod` node. Because it was previously in the
74
- // modifier form, we're guaranteed to not have an additional node, so we can
75
- // just work with the predicate and the body.
76
- function printSingle(keyword) {
77
- return function printSingleWithKeyword(path, { rubyModifier }, print) {
78
- const node = path.getValue();
79
- const predicateDoc = path.call(print, "pred");
80
- const statementsDoc = path.call(print, isModifier(node) ? "stmt" : "stmts");
81
- const multilineParts = [
82
- `${keyword} `,
83
- align(keyword.length + 1, predicateDoc),
84
- indent([softline, statementsDoc]),
85
- softline,
86
- "end"
87
- ];
88
- // If we do not allow modifier form conditionals or there are comments
89
- // inside of the body of the conditional, then we must print in the
90
- // multiline form.
91
- if (!rubyModifier || (!isModifier(node) && node.stmts.body[0].comments)) {
92
- return [multilineParts, breakParent];
93
- }
94
- const inline = (0, utils_1.inlineEnsureParens)(path, [
95
- statementsDoc,
96
- ` ${keyword} `,
97
- predicateDoc
98
- ]);
99
- // With an expression with a conditional modifier (expression if true), the
100
- // conditional body is parsed before the predicate expression, meaning that
101
- // if the parser encountered a variable declaration, it would initialize
102
- // that variable first before evaluating the predicate expression. That
103
- // parse order means the difference between a NameError or not. #591
104
- // https://docs.ruby-lang.org/en/2.0.0/syntax/control_expressions_rdoc.html#label-Modifier+if+and+unless
105
- if (isModifier(node) && (0, utils_1.containsAssignment)(node.stmt)) {
106
- return inline;
107
- }
108
- return group(ifBreak(multilineParts, inline));
109
- };
110
- }
111
- const noTernary = [
112
- "alias",
113
- "assign",
114
- "break",
115
- "command",
116
- "command_call",
117
- "heredoc",
118
- "if",
119
- "if_mod",
120
- "ifop",
121
- "lambda",
122
- "massign",
123
- "next",
124
- "opassign",
125
- "rescue_mod",
126
- "return",
127
- "return0",
128
- "super",
129
- "undef",
130
- "unless",
131
- "unless_mod",
132
- "until_mod",
133
- "var_alias",
134
- "void_stmt",
135
- "while_mod",
136
- "yield",
137
- "yield0",
138
- "zsuper"
139
- ];
140
- // Certain expressions cannot be reduced to a ternary without adding parens
141
- // around them. In this case we say they cannot be ternaried and default instead
142
- // to breaking them into multiple lines.
143
- function canTernaryStmts(stmts) {
144
- if (stmts.body.length !== 1) {
145
- return false;
146
- }
147
- const stmt = stmts.body[0];
148
- // If the user is using one of the lower precedence "and" or "or" operators,
149
- // then we can't use a ternary expression as it would break the flow control.
150
- if (stmt.type === "binary" && ["and", "or"].includes(stmt.op)) {
151
- return false;
152
- }
153
- // Check against the blocklist of statement types that are not allowed to be
154
- // a part of a ternary expression.
155
- return !noTernary.includes(stmt.type);
156
- }
157
- // In order for an `if` or `unless` expression to be shortened to a ternary,
158
- // there has to be one and only one "addition" (another clause attached) which
159
- // is of the "else" type. Both the body of the main node and the body of the
160
- // additional node must have only one statement, and that statement list must
161
- // pass the `canTernaryStmts` check.
162
- function canTernary(path) {
163
- const node = path.getValue();
164
- return (!["assign", "opassign", "command_call", "command"].includes(node.pred.type) &&
165
- node.cons &&
166
- node.cons.type === "else" &&
167
- canTernaryStmts(node.stmts) &&
168
- canTernaryStmts(node.cons.stmts));
169
- }
170
- // A normalized print function for both `if` and `unless` nodes.
171
- function printConditional(keyword) {
172
- return function printConditionalWithKeyword(path, opts, print) {
173
- if (canTernary(path)) {
174
- let ternaryParts = [
175
- path.call(print, "pred"),
176
- " ? ",
177
- ...printTernaryClauses(keyword, path.call(print, "stmts"), path.call(print, "cons", "stmts"))
178
- ];
179
- if (["binary", "call"].includes(path.getParentNode().type)) {
180
- ternaryParts = ["(", ...ternaryParts, ")"];
181
- }
182
- return group(ifBreak(printWithAddition(keyword, path, print, false), ternaryParts));
183
- }
184
- const node = path.getValue();
185
- // If there's an additional clause that wasn't matched earlier, we know we
186
- // can't go for the inline option.
187
- if (node.cons) {
188
- return group(printWithAddition(keyword, path, print, true));
189
- }
190
- // If the body of the conditional is empty, then we explicitly have to use
191
- // the block form.
192
- if ((0, utils_1.isEmptyStmts)(node.stmts)) {
193
- return [
194
- `${keyword} `,
195
- align(keyword.length + 1, path.call(print, "pred")),
196
- hardline,
197
- "end"
198
- ];
199
- }
200
- // Two situations in which we need to use the block form:
201
- //
202
- // 1. If the predicate of the conditional contains an assignment, then we
203
- // can't know for sure that it doesn't impact the body of the conditional.
204
- //
205
- // 2. If the conditional contains just another conditional, then collapsing
206
- // it would result in double modifiers on the same line.
207
- if ((0, utils_1.containsAssignment)(node.pred) ||
208
- containsSingleConditional(node.stmts)) {
209
- return [
210
- `${keyword} `,
211
- align(keyword.length + 1, path.call(print, "pred")),
212
- indent([hardline, path.call(print, "stmts")]),
213
- hardline,
214
- "end"
215
- ];
216
- }
217
- return printSingle(keyword)(path, opts, print);
218
- };
219
- }
220
- const printElse = (path, opts, print) => {
221
- const node = path.getValue();
222
- return [
223
- node.stmts.body.length === 1 && node.stmts.body[0].type === "command"
224
- ? breakParent
225
- : "",
226
- "else",
227
- indent([softline, path.call(print, "stmts")])
228
- ];
229
- };
230
- exports.printElse = printElse;
231
- const printElsif = (path, opts, print) => {
232
- const node = path.getValue();
233
- const parts = [
234
- group(["elsif ", align("elsif".length - 1, path.call(print, "pred"))]),
235
- indent([hardline, path.call(print, "stmts")])
236
- ];
237
- if (node.cons) {
238
- parts.push(group([hardline, path.call(print, "cons")]));
239
- }
240
- return group(parts);
241
- };
242
- exports.printElsif = printElsif;
243
- exports.printIf = printConditional("if");
244
- exports.printIfModifier = printSingle("if");
245
- exports.printUnless = printConditional("unless");
246
- exports.printUnlessModifier = printSingle("unless");
@@ -1,35 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printTopConst = exports.printField = exports.printDefined = exports.printConstRef = exports.printConstPath = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const { group, indent, softline } = prettier_1.default;
10
- const printConstPath = (path, opts, print) => [path.call(print, "parent"), "::", path.call(print, "constant")];
11
- exports.printConstPath = printConstPath;
12
- const printConstRef = (path, opts, print) => path.call(print, "constant");
13
- exports.printConstRef = printConstRef;
14
- const printDefined = (path, opts, print) => {
15
- return group([
16
- "defined?(",
17
- indent([softline, path.call(print, "value")]),
18
- softline,
19
- ")"
20
- ]);
21
- };
22
- exports.printDefined = printDefined;
23
- const printField = (path, opts, print) => {
24
- return group([
25
- path.call(print, "parent"),
26
- (0, utils_1.makeCall)(path, opts, print),
27
- path.call(print, "name")
28
- ]);
29
- };
30
- exports.printField = printField;
31
- const printTopConst = (path, opts, print) => [
32
- "::",
33
- path.call(print, "constant")
34
- ];
35
- exports.printTopConst = printTopConst;
@@ -1,59 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printYield0 = exports.printYield = exports.printNext = exports.printBreak = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const { join } = prettier_1.default;
9
- // If there are parentheses around these nodes, then we can't skip printing them
10
- // without changing the semantic meaning of the statement.
11
- const unskippableParens = [
12
- "if_mod",
13
- "rescue_mod",
14
- "unless_mod",
15
- "until_mod",
16
- "while_mod"
17
- ];
18
- function printFlowControl(keyword) {
19
- return function printFlowControlWithKeyword(path, opts, print) {
20
- const node = path.getValue();
21
- // If we don't have any arguments to the keyword, then it's always going to
22
- // come in as an args node, in which case we can just print the keyword.
23
- if (node.args.type === "args") {
24
- return keyword;
25
- }
26
- // Special handling if we've got parentheses on this call to the keyword. If
27
- // we do and we can skip them, then we will. If we don't, then we'll print
28
- // them right after the keyword with no space.
29
- const paren = node.args.args.type === "args" && node.args.args.parts[0];
30
- if (paren && paren.type === "paren") {
31
- const stmts = paren.cnts.body;
32
- // Here we're checking if we can skip past the parentheses entirely.
33
- if (stmts.length === 1 && !unskippableParens.includes(stmts[0].type)) {
34
- return [
35
- `${keyword} `,
36
- path.call(print, "args", "args", "parts", 0, "cnts")
37
- ];
38
- }
39
- // Here we know we can't, so just printing out the parentheses as normal.
40
- return [keyword, path.call(print, "args", "args", "parts", 0)];
41
- }
42
- // If we didn't hit the super special handling, then we're just going to
43
- // print out the arguments to the keyword like normal.
44
- return [`${keyword} `, join(", ", path.call(print, "args"))];
45
- };
46
- }
47
- exports.printBreak = printFlowControl("break");
48
- exports.printNext = printFlowControl("next");
49
- const printYield = (path, opts, print) => {
50
- const node = path.getValue();
51
- const argsDoc = path.call(print, "args");
52
- if (node.args.type === "paren") {
53
- return ["yield", argsDoc];
54
- }
55
- return ["yield ", join(", ", argsDoc)];
56
- };
57
- exports.printYield = printYield;
58
- const printYield0 = (path) => path.getValue().value;
59
- exports.printYield0 = printYield0;
@@ -1,126 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printHash = exports.printHashContents = exports.printAssocSplat = exports.printAssoc = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const { group, ifBreak, indent, join, line } = prettier_1.default;
10
- // When attempting to convert a hash rocket into a hash label, you need to take
11
- // care because only certain patterns are allowed. Ruby source says that they
12
- // have to match keyword arguments to methods, but don't specify what that is.
13
- // After some experimentation, it looks like it's:
14
- //
15
- // * Starts with a letter (either case) or an underscore
16
- // * Does not end in equal
17
- //
18
- // This function represents that check, as it determines if it can convert the
19
- // symbol node into a hash label.
20
- function isValidHashLabel(symbolLiteral) {
21
- const label = symbolLiteral.value.value;
22
- return label.match(/^[_A-Za-z]/) && !label.endsWith("=");
23
- }
24
- function canUseHashLabels(contentsNode) {
25
- return contentsNode.assocs.every((assocNode) => {
26
- if (assocNode.type === "assoc_splat") {
27
- return true;
28
- }
29
- switch (assocNode.key.type) {
30
- case "label":
31
- return true;
32
- case "symbol_literal":
33
- return isValidHashLabel(assocNode.key);
34
- case "dyna_symbol":
35
- return true;
36
- default:
37
- return false;
38
- }
39
- });
40
- }
41
- const printHashKeyLabel = (path, print) => {
42
- const node = path.getValue();
43
- switch (node.type) {
44
- case "label":
45
- return print(path);
46
- case "symbol_literal":
47
- return [path.call(print, "value"), ":"];
48
- case "dyna_symbol":
49
- return [print(path), ":"];
50
- default:
51
- // This should never happen, but keeping it here so that the two key
52
- // printers can maintain the same signature.
53
- return "";
54
- }
55
- };
56
- const printHashKeyRocket = (path, print) => {
57
- const node = path.getValue();
58
- let doc = print(path);
59
- if (node.type === "label") {
60
- const sDoc = doc; // since we know this is a label
61
- doc = [":", sDoc.slice(0, sDoc.length - 1)];
62
- }
63
- else if (node.type === "dyna_symbol") {
64
- doc = [":", doc];
65
- }
66
- return [doc, " =>"];
67
- };
68
- const printAssoc = (path, opts, print) => {
69
- const node = path.getValue();
70
- const { keyPrinter } = path.getParentNode();
71
- const parts = [path.call((keyPath) => keyPrinter(keyPath, print), "key")];
72
- const valueDoc = path.call(print, "value");
73
- // If we're printing a child hash then we want it to break along with its
74
- // parent hash, so we don't group the parts.
75
- if (node.value.type === "hash") {
76
- parts.push(" ", valueDoc);
77
- return parts;
78
- }
79
- if (!(0, utils_1.skipAssignIndent)(node.value) || node.key.comments) {
80
- parts.push(indent([line, valueDoc]));
81
- }
82
- else {
83
- parts.push(" ", valueDoc);
84
- }
85
- return group(parts);
86
- };
87
- exports.printAssoc = printAssoc;
88
- const printAssocSplat = (path, opts, print) => ["**", path.call(print, "value")];
89
- exports.printAssocSplat = printAssocSplat;
90
- const printHashContents = (path, opts, print) => {
91
- const node = path.getValue();
92
- // First determine which key printer we're going to use, so that the child
93
- // nodes can reference it when they go to get printed.
94
- node.keyPrinter =
95
- opts.rubyHashLabel && canUseHashLabels(path.getValue())
96
- ? printHashKeyLabel
97
- : printHashKeyRocket;
98
- return join([",", line], path.map(print, "assocs"));
99
- };
100
- exports.printHashContents = printHashContents;
101
- const printHash = (path, opts, print) => {
102
- const node = path.getValue();
103
- // Hashes normally have a single assoclist_from_args child node. If it's
104
- // missing, then it means we're dealing with an empty hash, so we can just
105
- // exit here and print.
106
- if (node.cnts === null) {
107
- return (0, utils_1.printEmptyCollection)(path, opts, "{", "}");
108
- }
109
- const doc = [
110
- "{",
111
- indent([
112
- line,
113
- path.call(print, "cnts"),
114
- (0, utils_1.getTrailingComma)(opts) ? ifBreak(",", "") : ""
115
- ]),
116
- line,
117
- "}"
118
- ];
119
- // If we're inside another hash, then we don't want to group our contents
120
- // because we want this hash to break along with its parent hash.
121
- if (path.getParentNode().type === "assoc") {
122
- return doc;
123
- }
124
- return group(doc);
125
- };
126
- exports.printHash = printHash;
@@ -1,30 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printHeredoc = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const { group, lineSuffix, join } = prettier_1.default;
10
- const printHeredoc = (path, opts, print) => {
11
- const node = path.getValue();
12
- // Print out each part of the heredoc to its own doc node.
13
- const parts = path.map((partPath) => {
14
- const part = partPath.getValue();
15
- if (part.type !== "tstring_content") {
16
- return print(partPath);
17
- }
18
- return join(utils_1.literallineWithoutBreakParent, part.value.split(/\r?\n/));
19
- }, "parts");
20
- // We use a literalline break because matching indentation is required
21
- // for the heredoc contents and ending. If the line suffix contains a
22
- // break-parent, all ancestral groups are broken, and heredocs automatically
23
- // break lines in groups they appear in. We prefer them to appear in-line if
24
- // possible, so we use a literalline without the break-parent.
25
- return group([
26
- path.call(print, "beging"),
27
- lineSuffix(group([utils_1.literallineWithoutBreakParent, ...parts, node.ending]))
28
- ]);
29
- };
30
- exports.printHeredoc = printHeredoc;
@@ -1,35 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printEND = exports.printBEGIN = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const { group, indent, line } = prettier_1.default;
9
- // The `BEGIN` and `END` keywords are used to hook into the Ruby process. Any
10
- // `BEGIN` blocks are executed right when the process starts up, and the `END`
11
- // blocks are executed right before exiting.
12
- //
13
- // BEGIN {
14
- // # content goes here
15
- // }
16
- //
17
- // END {
18
- // # content goes here
19
- // }
20
- //
21
- // Interesting side note, you don't use `do...end` blocks with these hooks. Both
22
- // nodes contain one child which is a `stmts` node.
23
- function printHook(name) {
24
- return function printHookWithName(path, opts, print) {
25
- return group([
26
- name,
27
- " ",
28
- path.call(print, "lbrace"),
29
- indent([line, path.call(print, "stmts")]),
30
- [line, "}"]
31
- ]);
32
- };
33
- }
34
- exports.printBEGIN = printHook("BEGIN");
35
- exports.printEND = printHook("END");
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.printInt = void 0;
4
- // An @int node is any literal integer in Ruby. They can come in a number of
5
- // bases, and look like the following:
6
- //
7
- // Binary (2) - 0b0110
8
- // Octal (8) - 0o34 or 034
9
- // Decimal (10) - 159 or 0d159
10
- // Hexidecimal (16) - 0xac5
11
- //
12
- // If it's a decimal number, it can be optional separated by any number of
13
- // arbitrarily places underscores. This can be useful for dollars and cents
14
- // (34_99), dates (2020_11_30), and normal 3 digit separation (1_222_333).
15
- const printInt = (path) => {
16
- const { value } = path.getValue();
17
- // If the number is a base 10 number, is sufficiently large, and is not
18
- // already formatted with underscores, then add them in in between the
19
- // numbers every three characters starting from the right.
20
- if (!value.startsWith("0") && value.length >= 5 && !value.includes("_")) {
21
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
22
- const segments = ` ${value}`.slice((value.length + 2) % 3).match(/.{3}/g);
23
- return segments.join("_").trim();
24
- }
25
- return value;
26
- };
27
- exports.printInt = printInt;
@@ -1,70 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printLambda = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const { group, ifBreak, indent, line } = prettier_1.default;
10
- // We can have our params coming in as the first child of the main lambda node,
11
- // or if we have them wrapped in parens then they'll be one level deeper. Even
12
- // though it's possible to omit the parens if you only have one argument, we're
13
- // going to keep them in no matter what for consistency.
14
- function printLambdaParams(path, print) {
15
- let node = path.getValue().params;
16
- // In this case we had something like -> (foo) { bar } which would mean that
17
- // we're looking at a paren node, so we'll descend one level deeper to get at
18
- // the actual params node.
19
- if (node.type !== "params") {
20
- node = node.cnts;
21
- }
22
- // If we don't have any params at all, then we're just going to bail out and
23
- // print nothing. This is to avoid printing an empty set of parentheses.
24
- if ((0, utils_1.isEmptyParams)(node)) {
25
- return "";
26
- }
27
- return path.call(print, "params");
28
- }
29
- // Lambda nodes represent stabby lambda literals, which can come in a couple of
30
- // flavors. They can use either braces or do...end for their block, and their
31
- // arguments can be not present, have no parentheses for a single argument, or
32
- // have parentheses for multiple arguments. Below are a couple of examples:
33
- //
34
- // -> { 1 }
35
- // -> a { a + 1 }
36
- // ->(a) { a + 1 }
37
- // ->(a, b) { a + b }
38
- // ->(a, b = 1) { a + b }
39
- //
40
- // -> do
41
- // 1
42
- // end
43
- //
44
- // -> a do
45
- // a + 1
46
- // end
47
- //
48
- // ->(a, b) do
49
- // a + b
50
- // end
51
- //
52
- // Generally, we're going to favor do...end for the multi-line form and braces
53
- // for the single-line form. However, if we have an ancestor that is a command
54
- // or command_call node, then we'll need to use braces either way because of
55
- // operator precendence.
56
- const printLambda = (path, opts, print) => {
57
- const params = printLambdaParams(path, print);
58
- const inCommand = (0, utils_1.hasAncestor)(path, ["command", "command_call"]);
59
- const stmtsDoc = path.call(print, "stmts");
60
- return group(ifBreak([
61
- "->",
62
- params,
63
- " ",
64
- inCommand ? "{" : "do",
65
- indent([line, stmtsDoc]),
66
- line,
67
- inCommand ? "}" : "end"
68
- ], ["->", params, " { ", stmtsDoc, " }"]));
69
- };
70
- exports.printLambda = printLambda;