prettier 1.6.1 → 2.0.0.pre.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +348 -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 +179 -0
  13. data/dist/parser/server.rb +141 -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 +87 -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 +85 -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 +1195 -254
  54. data/dist/ruby/printer.js +129 -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/exe/rbprettier +1 -2
  76. data/lib/prettier.rb +36 -5
  77. data/node_modules/prettier/bin-prettier.js +313 -190
  78. data/node_modules/prettier/doc.js +191 -323
  79. data/node_modules/prettier/index.js +2753 -3677
  80. data/node_modules/prettier/package.json +1 -1
  81. data/node_modules/prettier/parser-angular.js +13 -14
  82. data/node_modules/prettier/parser-babel.js +7 -7
  83. data/node_modules/prettier/parser-espree.js +7 -7
  84. data/node_modules/prettier/parser-flow.js +7 -7
  85. data/node_modules/prettier/parser-glimmer.js +1 -1
  86. data/node_modules/prettier/parser-graphql.js +1 -1
  87. data/node_modules/prettier/parser-html.js +17 -17
  88. data/node_modules/prettier/parser-markdown.js +9 -9
  89. data/node_modules/prettier/parser-meriyah.js +7 -7
  90. data/node_modules/prettier/parser-postcss.js +2 -2
  91. data/node_modules/prettier/parser-typescript.js +7 -7
  92. data/node_modules/prettier/parser-yaml.js +2 -2
  93. data/node_modules/prettier/third-party.js +143 -78
  94. data/package.json +26 -18
  95. metadata +74 -67
  96. data/src/haml/embed.js +0 -87
  97. data/src/haml/parser.js +0 -23
  98. data/src/haml/printer.js +0 -438
  99. data/src/parser/parseSync.js +0 -172
  100. data/src/parser/server.rb +0 -66
  101. data/src/plugin.js +0 -148
  102. data/src/prettier.js +0 -16
  103. data/src/rbs/parser.js +0 -37
  104. data/src/rbs/printer.js +0 -643
  105. data/src/ruby/embed.js +0 -142
  106. data/src/ruby/nodes/alias.js +0 -73
  107. data/src/ruby/nodes/args.js +0 -222
  108. data/src/ruby/nodes/arrays.js +0 -162
  109. data/src/ruby/nodes/assign.js +0 -47
  110. data/src/ruby/nodes/blocks.js +0 -90
  111. data/src/ruby/nodes/calls.js +0 -246
  112. data/src/ruby/nodes/case.js +0 -65
  113. data/src/ruby/nodes/class.js +0 -64
  114. data/src/ruby/nodes/commands.js +0 -131
  115. data/src/ruby/nodes/conditionals.js +0 -282
  116. data/src/ruby/nodes/constants.js +0 -43
  117. data/src/ruby/nodes/flow.js +0 -74
  118. data/src/ruby/nodes/hashes.js +0 -155
  119. data/src/ruby/nodes/heredocs.js +0 -36
  120. data/src/ruby/nodes/hooks.js +0 -34
  121. data/src/ruby/nodes/ints.js +0 -31
  122. data/src/ruby/nodes/lambdas.js +0 -76
  123. data/src/ruby/nodes/loops.js +0 -98
  124. data/src/ruby/nodes/massign.js +0 -98
  125. data/src/ruby/nodes/methods.js +0 -74
  126. data/src/ruby/nodes/operators.js +0 -83
  127. data/src/ruby/nodes/params.js +0 -106
  128. data/src/ruby/nodes/patterns.js +0 -157
  129. data/src/ruby/nodes/regexp.js +0 -56
  130. data/src/ruby/nodes/rescue.js +0 -101
  131. data/src/ruby/nodes/return.js +0 -94
  132. data/src/ruby/nodes/statements.js +0 -142
  133. data/src/ruby/nodes/strings.js +0 -272
  134. data/src/ruby/nodes/super.js +0 -35
  135. data/src/ruby/nodes/undef.js +0 -42
  136. data/src/ruby/nodes.js +0 -34
  137. data/src/ruby/parser.js +0 -37
  138. data/src/ruby/printer.js +0 -147
  139. data/src/ruby/toProc.js +0 -105
  140. data/src/utils/containsAssignment.js +0 -11
  141. data/src/utils/getTrailingComma.js +0 -5
  142. data/src/utils/hasAncestor.js +0 -17
  143. data/src/utils/isEmptyBodyStmt.js +0 -7
  144. data/src/utils/isEmptyStmts.js +0 -11
  145. data/src/utils/literal.js +0 -7
  146. data/src/utils/literallineWithoutBreakParent.js +0 -7
  147. data/src/utils/makeCall.js +0 -14
  148. data/src/utils/noIndent.js +0 -10
  149. data/src/utils/printEmptyCollection.js +0 -49
  150. data/src/utils/skipAssignIndent.js +0 -17
  151. data/src/utils.js +0 -13
@@ -0,0 +1,260 @@
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.printCallContainer = exports.printMethodAddBlock = exports.printMethodAddArg = exports.printCall = void 0;
7
+ const prettier_1 = __importDefault(require("../../prettier"));
8
+ const utils_1 = require("../../utils");
9
+ const toProc_1 = __importDefault(require("../toProc"));
10
+ const { group, hardline, ifBreak, indent, join, softline } = prettier_1.default;
11
+ const chained = ["call", "method_add_arg", "method_add_block"];
12
+ function hasLeadingComments(node) {
13
+ var _a;
14
+ return (_a = node.comments) === null || _a === void 0 ? void 0 : _a.some(({ leading }) => leading);
15
+ }
16
+ const printCall = (path, opts, print) => {
17
+ const node = path.getValue();
18
+ const [receiverNode, , messageNode] = node.body;
19
+ const receiverDoc = path.call(print, "body", 0);
20
+ const operatorDoc = (0, utils_1.makeCall)(path, opts, print);
21
+ // You can call lambdas with a special syntax that looks like func.(*args).
22
+ // In this case, "call" is returned for the 3rd child node. We don't alter
23
+ // call syntax so if `call` is implicit, we don't print it out.
24
+ const messageDoc = messageNode === "call" ? "" : path.call(print, "body", 2);
25
+ // Create some arrays that are going to represent each side of our call.
26
+ let leftSideDoc = [receiverDoc];
27
+ let rightSideDoc = [operatorDoc, messageDoc];
28
+ // If there are leading comments on the right side of the call, then it means
29
+ // we have a structure where there's a receiver and an operator together, then
30
+ // a comment, then the message, as in:
31
+ //
32
+ // foo.
33
+ // # comment
34
+ // baz
35
+ //
36
+ // In the case we need to group the receiver and the operator together or
37
+ // we'll end up with a syntax error.
38
+ const operatorIsTrailing = messageNode !== "call" && hasLeadingComments(messageNode);
39
+ if (operatorIsTrailing) {
40
+ leftSideDoc = [receiverDoc, operatorDoc];
41
+ rightSideDoc = [messageDoc];
42
+ }
43
+ // For certain left sides of the call nodes, we want to attach directly to
44
+ // the } or end.
45
+ if (utils_1.noIndent.includes(receiverNode.type)) {
46
+ return [leftSideDoc, rightSideDoc];
47
+ }
48
+ if (receiverNode.type === "call" &&
49
+ receiverNode.body[2] !== "call" &&
50
+ receiverNode.body[2].body === "where" &&
51
+ messageDoc === "not") {
52
+ // This is very specialized behavior wherein we group .where.not calls
53
+ // together because it looks better. For more information, see
54
+ // https://github.com/prettier/plugin-ruby/issues/862.
55
+ }
56
+ else {
57
+ // Otherwise, we're going to put a line node into the right side doc.
58
+ rightSideDoc.unshift(receiverNode.comments ? hardline : softline);
59
+ }
60
+ // Get a reference to the parent node so we can check if we're inside a chain
61
+ const parentNode = path.getParentNode();
62
+ // If our parent node is a chained node then we're not going to group the
63
+ // right side of the expression, as we want to have a nice multi-line layout.
64
+ if (chained.includes(parentNode.type) && !node.comments) {
65
+ parentNode.chain = (node.chain || 0) + 1;
66
+ parentNode.callChain = (node.callChain || 0) + 1;
67
+ parentNode.firstReceiverType = node.firstReceiverType || receiverNode.type;
68
+ // Here we're going to determine what doc nodes to send up to the parent
69
+ // node to represent when we're in the multi-line form.
70
+ let breakDocLHS;
71
+ if (node.breakDoc && operatorIsTrailing) {
72
+ // Here we already have a child node that has passed up its
73
+ // representation. In this case node.breakDoc represents the receiver
74
+ // without any lines inserted. With regard to this node, it means it's
75
+ // everything up until the operator. So we're just going to append the
76
+ // operator.
77
+ breakDocLHS = node.breakDoc.concat(operatorDoc);
78
+ }
79
+ else if (node.breakDoc) {
80
+ // Here we don't need a trailing operator, so we're just going to use the
81
+ // existing node.breakDoc. The operator will be a part of the rightSideDoc
82
+ // variable.
83
+ breakDocLHS = node.breakDoc;
84
+ }
85
+ else {
86
+ // Here we're at the bottom of the chain, so there's no representation yet
87
+ // for the receiver. So we're just going to pass up the left side.
88
+ breakDocLHS = leftSideDoc;
89
+ }
90
+ parentNode.breakDoc = breakDocLHS.concat(rightSideDoc);
91
+ }
92
+ // If we're at the top of a chain, then we're going to print out a nice
93
+ // multi-line layout if this doesn't break into multiple lines.
94
+ if (!chained.includes(parentNode.type) &&
95
+ (node.chain || 0) >= 3 &&
96
+ node.breakDoc) {
97
+ return ifBreak(group(indent(node.breakDoc.concat(rightSideDoc))), [
98
+ leftSideDoc,
99
+ group(rightSideDoc)
100
+ ]);
101
+ }
102
+ return group([leftSideDoc, group(indent(rightSideDoc))]);
103
+ };
104
+ exports.printCall = printCall;
105
+ const printMethodAddArg = (path, opts, print) => {
106
+ const node = path.getValue();
107
+ const [methodNode, argNode] = node.body;
108
+ const [methodDoc, argsDoc] = path.map(print, "body");
109
+ // You can end up here if you have a method with a ? ending, presumably
110
+ // because the parser knows that it cannot be a local variable. You can also
111
+ // end up here if you are explicitly using an empty set of parentheses.
112
+ if (argsDoc.length === 0) {
113
+ // If you're using an explicit set of parentheses on something that looks
114
+ // like a constant, then we need to match that in order to maintain valid
115
+ // Ruby. For example, you could do something like Foo(), on which we would
116
+ // need to keep the parentheses to make it look like a method call.
117
+ if (methodNode.type === "fcall" && methodNode.body[0].type === "@const") {
118
+ return [methodDoc, "()"];
119
+ }
120
+ // If you're using an explicit set parentheses with the special call syntax,
121
+ // then we need to explicitly print out an extra set of parentheses. For
122
+ // example, if you call something like Foo.new.() (implicitly calling the
123
+ // #call method on a new instance of the Foo class), then we have to print
124
+ // out those parentheses, otherwise we'll end up with Foo.new.
125
+ if (methodNode.type === "call" && methodNode.body[2] === "call") {
126
+ return [methodDoc, "()"];
127
+ }
128
+ return methodDoc;
129
+ }
130
+ // This case will ONLY be hit if we can successfully turn the block into a
131
+ // to_proc call. In that case, we just explicitly add the parens around it.
132
+ if (argNode.type === "args" && argsDoc.length > 0) {
133
+ return [methodDoc, "(", ...argsDoc, ")"];
134
+ }
135
+ // Get a reference to the parent node so we can check if we're inside a chain
136
+ const parentNode = path.getParentNode();
137
+ // If our parent node is a chained node then we're not going to group the
138
+ // right side of the expression, as we want to have a nice multi-line layout.
139
+ if (chained.includes(parentNode.type) && !node.comments) {
140
+ parentNode.chain = (node.chain || 0) + 1;
141
+ parentNode.breakDoc = (node.breakDoc || [methodDoc]).concat(argsDoc);
142
+ parentNode.firstReceiverType = node.firstReceiverType;
143
+ }
144
+ // This is the threshold at which we will start to try to make a nicely
145
+ // indented call chain. For the most part, it's always 3.
146
+ let threshold = 3;
147
+ // Here, we have very specialized behavior where if we're within a sig block,
148
+ // then we're going to assume we're creating a Sorbet type signature. In that
149
+ // case, we really want the threshold to be lowered to 2 so that we create
150
+ // method chains off of any two method calls within the block. For more
151
+ // details, see
152
+ // https://github.com/prettier/plugin-ruby/issues/863.
153
+ let sigBlock = path.getParentNode(2);
154
+ if (sigBlock) {
155
+ // If we're at a do_block, then we want to go one more level up. This is
156
+ // because do_blocks have bodystmt nodes instead of just stmt nodes.
157
+ if (sigBlock.type === "do_block") {
158
+ sigBlock = path.getParentNode(3);
159
+ }
160
+ if (sigBlock.type === "method_add_block" &&
161
+ sigBlock.body[1] &&
162
+ sigBlock.body[0].type === "method_add_arg" &&
163
+ sigBlock.body[0].body[0].type === "fcall" &&
164
+ sigBlock.body[0].body[0].body[0].body === "sig") {
165
+ threshold = 2;
166
+ }
167
+ }
168
+ // If we're at the top of a chain, then we're going to print out a nice
169
+ // multi-line layout if this doesn't break into multiple lines.
170
+ if (!chained.includes(parentNode.type) &&
171
+ (node.chain || 0) >= threshold &&
172
+ node.breakDoc) {
173
+ // This is pretty specialized behavior. Basically if we're at the top of a
174
+ // chain but we've only had method calls without arguments and now we have
175
+ // arguments, then we're effectively trying to call a method with arguments
176
+ // that is nested under a bunch of stuff. So we group together to first part
177
+ // to make it so just the arguments break. This looks like, for example:
178
+ //
179
+ // config.action_dispatch.rescue_responses.merge!(
180
+ // 'ActiveRecord::ConnectionTimeoutError' => :service_unavailable,
181
+ // 'ActiveRecord::QueryCanceled' => :service_unavailable
182
+ // )
183
+ //
184
+ if (node.callChain === node.chain) {
185
+ return [group(indent(node.breakDoc)), group(argsDoc)];
186
+ }
187
+ return ifBreak(group(indent(node.breakDoc.concat(argsDoc))), [
188
+ methodDoc,
189
+ argsDoc
190
+ ]);
191
+ }
192
+ // If there are already parentheses, then we can just use the doc that's
193
+ // already printed.
194
+ if (argNode.type == "arg_paren") {
195
+ return [methodDoc, argsDoc];
196
+ }
197
+ return [methodDoc, " ", join(", ", argsDoc), " "];
198
+ };
199
+ exports.printMethodAddArg = printMethodAddArg;
200
+ const printMethodAddBlock = (path, opts, print) => {
201
+ const node = path.getValue();
202
+ const [callNode, blockNode] = node.body;
203
+ const [callDoc, blockDoc] = path.map(print, "body");
204
+ // Don't bother trying to do any kind of fancy toProc transform if the option
205
+ // is disabled.
206
+ if (opts.rubyToProc) {
207
+ const proc = (0, toProc_1.default)(path, blockNode);
208
+ if (proc && callNode.type === "call") {
209
+ return group([
210
+ path.call(print, "body", 0),
211
+ "(",
212
+ indent([softline, proc]),
213
+ [softline, ")"]
214
+ ]);
215
+ }
216
+ if (proc) {
217
+ return path.call(print, "body", 0);
218
+ }
219
+ }
220
+ // Get a reference to the parent node so we can check if we're inside a chain
221
+ const parentNode = path.getParentNode();
222
+ // If our parent node is a chained node then we're not going to group the
223
+ // right side of the expression, as we want to have a nice multi-line layout.
224
+ if (chained.includes(parentNode.type)) {
225
+ parentNode.chain = (node.chain || 0) + 1;
226
+ parentNode.breakDoc = (node.breakDoc || [callDoc]).concat(blockDoc);
227
+ parentNode.firstReceiverType = node.firstReceiverType;
228
+ }
229
+ // If we're at the top of a chain, then we're going to print out a nice
230
+ // multi-line layout if this doesn't break into multiple lines.
231
+ if (!chained.includes(parentNode.type) &&
232
+ (node.chain || 0) >= 3 &&
233
+ node.breakDoc) {
234
+ // This is pretty specialized behavior. Basically if we're at the top of a
235
+ // chain but we've only had method calls without arguments and now we have
236
+ // a method call with a block, then we're effectively trying to call a
237
+ // method with arguments that is nested under a bunch of stuff. So we group
238
+ // together to first part to make it so just the block breaks. This looks
239
+ // like, for example:
240
+ //
241
+ // Rails.application.routes.draw do
242
+ // root 'articles#index'
243
+ // resources :articles
244
+ // end
245
+ //
246
+ if (node.callChain === node.chain) {
247
+ return [group(indent(node.breakDoc)), group(blockDoc)];
248
+ }
249
+ return ifBreak(group(indent(node.breakDoc.concat(blockDoc))), [
250
+ callDoc,
251
+ blockDoc
252
+ ]);
253
+ }
254
+ return [callDoc, blockDoc];
255
+ };
256
+ exports.printMethodAddBlock = printMethodAddBlock;
257
+ const printCallContainer = (path, opts, print) => {
258
+ return path.call(print, "body", 0);
259
+ };
260
+ exports.printCallContainer = printCallContainer;
@@ -0,0 +1,50 @@
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.printWhen = exports.printCase = void 0;
7
+ const prettier_1 = __importDefault(require("../../prettier"));
8
+ const { align, fill, group, hardline, indent, line } = prettier_1.default;
9
+ const printCase = (path, opts, print) => {
10
+ const parts = ["case"];
11
+ // You don't need to explicitly have something to test against in a case
12
+ // statement (without it it effectively becomes an if/elsif chain).
13
+ if (path.getValue().body[0]) {
14
+ parts.push(" ", path.call(print, "body", 0));
15
+ }
16
+ return [...parts, hardline, path.call(print, "body", 1), hardline, "end"];
17
+ };
18
+ exports.printCase = printCase;
19
+ const printWhen = (path, opts, print) => {
20
+ const [, , addition] = path.getValue().body;
21
+ // The `fill` builder command expects an array of docs alternating with
22
+ // line breaks. This is so it can loop through and determine where to break.
23
+ const preds = fill(path.call(print, "body", 0).reduce((accum, pred, index) => {
24
+ if (index === 0) {
25
+ return [pred];
26
+ }
27
+ // Pull off the last element and make it concat with a comma so that
28
+ // we can maintain alternating lines and docs.
29
+ return [
30
+ ...accum.slice(0, -1),
31
+ [accum[accum.length - 1], ","],
32
+ line,
33
+ pred
34
+ ];
35
+ }, []));
36
+ const stmts = path.call(print, "body", 1);
37
+ const parts = [["when ", align("when ".length, preds)]];
38
+ // It's possible in a when to just have empty void statements, in which case
39
+ // we would skip adding the body.
40
+ if (!stmts.every((part) => !part)) {
41
+ parts.push(indent([hardline, stmts]));
42
+ }
43
+ // This is the next clause on the case statement, either another `when` or
44
+ // an `else` clause.
45
+ if (addition) {
46
+ parts.push(hardline, path.call(print, "body", 2));
47
+ }
48
+ return group(parts);
49
+ };
50
+ exports.printWhen = printWhen;
@@ -0,0 +1,54 @@
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.printSClass = exports.printModule = exports.printClass = void 0;
7
+ const prettier_1 = __importDefault(require("../../prettier"));
8
+ const utils_1 = require("../../utils");
9
+ const { group, hardline, indent } = prettier_1.default;
10
+ const printClass = (path, opts, print) => {
11
+ const [, superclass, bodystmt] = path.getValue().body;
12
+ const parts = ["class ", path.call(print, "body", 0)];
13
+ if (superclass) {
14
+ parts.push(" < ", path.call(print, "body", 1));
15
+ }
16
+ const declaration = group(parts);
17
+ if ((0, utils_1.isEmptyBodyStmt)(bodystmt)) {
18
+ return group([declaration, hardline, "end"]);
19
+ }
20
+ return group([
21
+ declaration,
22
+ indent([hardline, path.call(print, "body", 2)]),
23
+ [hardline, "end"]
24
+ ]);
25
+ };
26
+ exports.printClass = printClass;
27
+ const printModule = (path, opts, print) => {
28
+ const node = path.getValue();
29
+ const declaration = group(["module ", path.call(print, "body", 0)]);
30
+ if ((0, utils_1.isEmptyBodyStmt)(node.body[1])) {
31
+ return group([declaration, hardline, "end"]);
32
+ }
33
+ return group([
34
+ declaration,
35
+ indent([hardline, path.call(print, "body", 1)]),
36
+ hardline,
37
+ "end"
38
+ ]);
39
+ };
40
+ exports.printModule = printModule;
41
+ const printSClass = (path, opts, print) => {
42
+ const bodystmt = path.getValue().body[1];
43
+ const declaration = ["class << ", path.call(print, "body", 0)];
44
+ if ((0, utils_1.isEmptyBodyStmt)(bodystmt)) {
45
+ return group([declaration, hardline, "end"]);
46
+ }
47
+ return group([
48
+ declaration,
49
+ indent([hardline, path.call(print, "body", 1)]),
50
+ hardline,
51
+ "end"
52
+ ]);
53
+ };
54
+ exports.printSClass = printSClass;
@@ -0,0 +1,124 @@
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.printCommandCall = exports.printCommand = void 0;
7
+ const prettier_1 = __importDefault(require("../../prettier"));
8
+ const utils_1 = require("../../utils");
9
+ const { align, group, ifBreak, indent, join, line, softline } = prettier_1.default;
10
+ function throwBadDoc(doc) {
11
+ throw new Error(`Unknown doc ${doc}`);
12
+ }
13
+ // Loop through the already created doc nodes and determine the overall length
14
+ // so that we can properly align the command arguments.
15
+ function docLength(doc) {
16
+ if (Array.isArray(doc)) {
17
+ return doc.reduce((sum, child) => sum + docLength(child), 0);
18
+ }
19
+ if (typeof doc === "string") {
20
+ return doc.length;
21
+ }
22
+ switch (doc.type) {
23
+ case "concat":
24
+ case "fill":
25
+ return doc.parts.reduce((sum, child) => sum + docLength(child), 0);
26
+ case "align":
27
+ case "group":
28
+ case "indent":
29
+ case "line-suffix":
30
+ return docLength(doc.contents);
31
+ case "if-break":
32
+ return docLength(doc.flatContents);
33
+ case "line":
34
+ return doc.soft ? 0 : 1;
35
+ case "break-parent":
36
+ case "cursor":
37
+ case "indent-if-break":
38
+ case "label":
39
+ case "line-suffix-boundary":
40
+ case "trim":
41
+ return 0;
42
+ default:
43
+ throwBadDoc(doc);
44
+ }
45
+ }
46
+ function hasDef(node) {
47
+ return (node.body[1].type === "args_add_block" &&
48
+ node.body[1].body[0].type === "args" &&
49
+ node.body[1].body[0].body[0] &&
50
+ ["def", "defs"].includes(node.body[1].body[0].body[0].type));
51
+ }
52
+ // Very special handling case for rspec matchers. In general with rspec matchers
53
+ // you expect to see something like:
54
+ //
55
+ // expect(foo).to receive(:bar).with(
56
+ // 'one',
57
+ // 'two',
58
+ // 'three',
59
+ // 'four',
60
+ // 'five'
61
+ // )
62
+ //
63
+ // In this case the arguments are aligned to the left side as opposed to being
64
+ // aligned with the `receive` call.
65
+ function skipArgsAlign(node) {
66
+ return ["to", "not_to", "to_not"].includes(node.body[2].body);
67
+ }
68
+ // If there is a ternary argument to a command and it's going to get broken
69
+ // into multiple lines, then we're going to have to use parentheses around the
70
+ // command in order to make sure operator precedence doesn't get messed up.
71
+ function hasTernaryArg(node) {
72
+ return node.body[0].body.some((child) => child.type === "ifop");
73
+ }
74
+ const printCommand = (path, opts, print) => {
75
+ const node = path.getValue();
76
+ const command = path.call(print, "body", 0);
77
+ const joinedArgs = join([",", line], path.call(print, "body", 1));
78
+ const hasTernary = hasTernaryArg(node.body[1]);
79
+ let breakArgs;
80
+ if (hasTernary) {
81
+ breakArgs = indent([softline, joinedArgs]);
82
+ }
83
+ else if (hasDef(node)) {
84
+ breakArgs = joinedArgs;
85
+ }
86
+ else {
87
+ breakArgs = align(docLength(command) + 1, joinedArgs);
88
+ }
89
+ return group(ifBreak([
90
+ command,
91
+ hasTernary ? "(" : " ",
92
+ breakArgs,
93
+ hasTernary ? [softline, ")"] : ""
94
+ ], [command, " ", joinedArgs]));
95
+ };
96
+ exports.printCommand = printCommand;
97
+ const printCommandCall = (path, opts, print) => {
98
+ const node = path.getValue();
99
+ const parts = [
100
+ path.call(print, "body", 0),
101
+ (0, utils_1.makeCall)(path, opts, print),
102
+ path.call(print, "body", 2)
103
+ ];
104
+ if (!node.body[3]) {
105
+ return parts;
106
+ }
107
+ const argDocs = join([",", line], path.call(print, "body", 3));
108
+ let breakDoc;
109
+ if (hasTernaryArg(node.body[3])) {
110
+ breakDoc = parts.concat("(", indent([softline, argDocs]), softline, ")");
111
+ parts.push(" ");
112
+ }
113
+ else if (skipArgsAlign(node)) {
114
+ parts.push(" ");
115
+ breakDoc = parts.concat(argDocs);
116
+ }
117
+ else {
118
+ parts.push(" ");
119
+ breakDoc = parts.concat(align(docLength(parts), argDocs));
120
+ }
121
+ const joinedDoc = parts.concat(argDocs);
122
+ return group(ifBreak(breakDoc, joinedDoc));
123
+ };
124
+ exports.printCommandCall = printCommandCall;