prettier 2.0.0 → 3.1.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -6
  3. data/README.md +17 -16
  4. data/exe/rbprettier +2 -2
  5. data/lib/prettier/rake/task.rb +5 -5
  6. data/lib/prettier.rb +12 -11
  7. data/node_modules/prettier/bin-prettier.js +48 -18924
  8. data/node_modules/prettier/cli.js +12335 -0
  9. data/node_modules/prettier/doc.js +1306 -4755
  10. data/node_modules/prettier/index.js +37468 -57614
  11. data/node_modules/prettier/package.json +3 -2
  12. data/node_modules/prettier/parser-angular.js +2 -66
  13. data/node_modules/prettier/parser-babel.js +27 -22
  14. data/node_modules/prettier/parser-espree.js +26 -22
  15. data/node_modules/prettier/parser-flow.js +26 -22
  16. data/node_modules/prettier/parser-glimmer.js +27 -1
  17. data/node_modules/prettier/parser-graphql.js +15 -1
  18. data/node_modules/prettier/parser-html.js +21 -117
  19. data/node_modules/prettier/parser-markdown.js +61 -19
  20. data/node_modules/prettier/parser-meriyah.js +19 -22
  21. data/node_modules/prettier/parser-postcss.js +76 -22
  22. data/node_modules/prettier/parser-typescript.js +280 -22
  23. data/node_modules/prettier/parser-yaml.js +150 -15
  24. data/node_modules/prettier/third-party.js +8660 -11030
  25. data/package.json +11 -25
  26. data/rubocop.yml +6 -6
  27. data/src/getInfo.js +23 -0
  28. data/{dist/parser → src}/netcat.js +0 -1
  29. data/src/parseSync.js +216 -0
  30. data/src/plugin.js +170 -0
  31. data/{dist/parser → src}/server.rb +50 -27
  32. metadata +95 -75
  33. data/bin/console +0 -7
  34. data/dist/haml/embed.js +0 -53
  35. data/dist/haml/parser.js +0 -31
  36. data/dist/haml/parser.rb +0 -143
  37. data/dist/haml/printer.js +0 -336
  38. data/dist/parser/getInfo.js +0 -17
  39. data/dist/parser/parseSync.js +0 -179
  40. data/dist/plugin.js +0 -143
  41. data/dist/prettier.js +0 -15
  42. data/dist/rbs/parser.js +0 -34
  43. data/dist/rbs/parser.rb +0 -98
  44. data/dist/rbs/printer.js +0 -517
  45. data/dist/ruby/embed.js +0 -110
  46. data/dist/ruby/nodes/alias.js +0 -59
  47. data/dist/ruby/nodes/aref.js +0 -53
  48. data/dist/ruby/nodes/args.js +0 -165
  49. data/dist/ruby/nodes/arrays.js +0 -126
  50. data/dist/ruby/nodes/assign.js +0 -41
  51. data/dist/ruby/nodes/blocks.js +0 -87
  52. data/dist/ruby/nodes/calls.js +0 -260
  53. data/dist/ruby/nodes/case.js +0 -50
  54. data/dist/ruby/nodes/class.js +0 -54
  55. data/dist/ruby/nodes/commands.js +0 -124
  56. data/dist/ruby/nodes/conditionals.js +0 -242
  57. data/dist/ruby/nodes/constants.js +0 -38
  58. data/dist/ruby/nodes/flow.js +0 -66
  59. data/dist/ruby/nodes/hashes.js +0 -130
  60. data/dist/ruby/nodes/heredocs.js +0 -30
  61. data/dist/ruby/nodes/hooks.js +0 -35
  62. data/dist/ruby/nodes/ints.js +0 -27
  63. data/dist/ruby/nodes/lambdas.js +0 -69
  64. data/dist/ruby/nodes/loops.js +0 -73
  65. data/dist/ruby/nodes/massign.js +0 -73
  66. data/dist/ruby/nodes/methods.js +0 -70
  67. data/dist/ruby/nodes/operators.js +0 -70
  68. data/dist/ruby/nodes/params.js +0 -89
  69. data/dist/ruby/nodes/patterns.js +0 -122
  70. data/dist/ruby/nodes/regexp.js +0 -45
  71. data/dist/ruby/nodes/rescue.js +0 -85
  72. data/dist/ruby/nodes/return.js +0 -75
  73. data/dist/ruby/nodes/statements.js +0 -111
  74. data/dist/ruby/nodes/strings.js +0 -218
  75. data/dist/ruby/nodes/super.js +0 -30
  76. data/dist/ruby/nodes/undef.js +0 -26
  77. data/dist/ruby/nodes.js +0 -151
  78. data/dist/ruby/parser.js +0 -34
  79. data/dist/ruby/parser.rb +0 -3636
  80. data/dist/ruby/printer.js +0 -129
  81. data/dist/ruby/toProc.js +0 -93
  82. data/dist/types/haml.js +0 -4
  83. data/dist/types/plugin.js +0 -3
  84. data/dist/types/rbs.js +0 -4
  85. data/dist/types/ruby.js +0 -4
  86. data/dist/types/utils.js +0 -2
  87. data/dist/types.js +0 -30
  88. data/dist/utils/containsAssignment.js +0 -15
  89. data/dist/utils/getTrailingComma.js +0 -6
  90. data/dist/utils/hasAncestor.js +0 -15
  91. data/dist/utils/inlineEnsureParens.js +0 -49
  92. data/dist/utils/isEmptyBodyStmt.js +0 -10
  93. data/dist/utils/isEmptyStmts.js +0 -10
  94. data/dist/utils/literal.js +0 -8
  95. data/dist/utils/literallineWithoutBreakParent.js +0 -8
  96. data/dist/utils/makeCall.js +0 -13
  97. data/dist/utils/noIndent.js +0 -11
  98. data/dist/utils/printEmptyCollection.js +0 -44
  99. data/dist/utils/skipAssignIndent.js +0 -15
  100. data/dist/utils.js +0 -30
data/dist/prettier.js DELETED
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- // If `RBPRETTIER` is set, then this is being run from the `Prettier::run` ruby
4
- // method. In that case, we need to pull `prettier` from the node_modules
5
- // directly, as it's been shipped with the gem.
6
- /* istanbul ignore next */
7
- // eslint-disable-next-line @typescript-eslint/no-var-requires
8
- const source = require(process.env.RBPRETTIER
9
- ? "../node_modules/prettier"
10
- : "prettier");
11
- // Cramming everything together to make it simpler to pull in all of the right
12
- // utilities and builders.
13
- const builders = source.doc.builders;
14
- const exported = { ...builders, ...source.doc.utils, ...source.util };
15
- exports.default = exported;
data/dist/rbs/parser.js DELETED
@@ -1,34 +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
- const parseSync_1 = __importDefault(require("../parser/parseSync"));
7
- const parser = {
8
- // This function is responsible for taking an input string of text and
9
- // returning to prettier a JavaScript object that is the equivalent AST that
10
- // represents the code stored in that string. We accomplish this by spawning a
11
- // new Ruby process of parser.rb and reading JSON off STDOUT.
12
- parse(text) {
13
- return (0, parseSync_1.default)("rbs", text);
14
- },
15
- astFormat: "rbs",
16
- // This function handles checking whether or not the source string has the
17
- // pragma for prettier. This is an optional workflow for incremental adoption.
18
- hasPragma(text) {
19
- return /^\s*#[^\S\n]*@(format|prettier)\s*(\n|$)/.test(text);
20
- },
21
- // This function is critical for comments and cursor support, and is
22
- // responsible for returning the index of the character within the source
23
- // string that is the beginning of the given node.
24
- locStart(node) {
25
- return node.location.start_pos;
26
- },
27
- // This function is critical for comments and cursor support, and is
28
- // responsible for returning the index of the character within the source
29
- // string that is the ending of the given node.
30
- locEnd(node) {
31
- return node.location.end_pos;
32
- }
33
- };
34
- exports.default = parser;
data/dist/rbs/parser.rb DELETED
@@ -1,98 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- begin
4
- require 'rbs'
5
- rescue LoadError
6
- # If we can't load the rbs gem, then we're going to provide a shim parser that
7
- # will warn and bail out.
8
- class Prettier::RBSParser
9
- def self.parse(text)
10
- warn(
11
- 'The `rbs` gem could not be loaded. Please ensure you have it ' \
12
- 'installed and that it is available in the gem path.'
13
- )
14
-
15
- false
16
- end
17
- end
18
-
19
- return
20
- end
21
-
22
- # Monkey-patch this so that we can get the character positions.
23
- class RBS::Location
24
- def to_json(*args)
25
- {
26
- start: {
27
- line: start_line,
28
- column: start_column
29
- },
30
- end: {
31
- line: end_line,
32
- column: end_column
33
- },
34
- start_pos: start_pos,
35
- end_pos: end_pos
36
- }.to_json(*args)
37
- end
38
- end
39
-
40
- # Monkey-patch this so that we get whether or not it needs to be escaped.
41
- class RBS::Types::Function::Param
42
- def to_json(*a)
43
- escaped = name && /\A#{RBS::Parser::KEYWORDS_RE}\z/.match?(name)
44
- { type: type, name: name, escaped: escaped }.to_json(*a)
45
- end
46
- end
47
-
48
- # Monkey-patch this so that we get the name field in the serialized JSON, as
49
- # well as information about whether or not we need to escape it.
50
- class RBS::AST::Members::MethodDefinition
51
- def to_json(*a)
52
- {
53
- member: :method_definition,
54
- name: name,
55
- kind: kind,
56
- types: types,
57
- annotations: annotations,
58
- location: location,
59
- comment: comment,
60
- overload: overload
61
- }.to_json(*a)
62
- end
63
- end
64
-
65
- # Monkey-patch this so that we get the information we need about how to join the
66
- # key-value pairs of the record.
67
- class RBS::Types::Record
68
- def to_json(*a)
69
- fields_extra = {}
70
-
71
- # Explicitly not using Enumerable#to_h here to support Ruby 2.5
72
- fields.each do |key, type|
73
- if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_]*\z/) &&
74
- !key.match?(RBS::Parser::KEYWORDS_RE)
75
- fields_extra[key] = { type: type, joiner: :label }
76
- else
77
- fields_extra[key.inspect] = { type: type, joiner: :rocket }
78
- end
79
- end
80
-
81
- { class: :record, fields: fields_extra, location: location }.to_json(*a)
82
- end
83
- end
84
-
85
- # The main parser interface.
86
- module Prettier
87
- class RBSParser
88
- def self.parse(text)
89
- {
90
- declarations: RBS::Parser.parse_signature(text),
91
- location: {
92
- start_pos: 0,
93
- end_pos: text.length
94
- }
95
- }
96
- end
97
- end
98
- end
data/dist/rbs/printer.js DELETED
@@ -1,517 +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
- const prettier_1 = __importDefault(require("../prettier"));
7
- const { group, hardline, indent, makeString, join, line, softline } = prettier_1.default;
8
- // For some lists of entities in the AST, the parser returns them as an unsorted
9
- // object (presumably because Ruby hashes have implicit ordering). We do not
10
- // have that in JavaScript, so here we sort each object by its position in the
11
- // source string.
12
- function getSortedKeys(object) {
13
- return Object.keys(object).sort((left, right) => object[left].type.location.start_pos -
14
- object[right].type.location.start_pos);
15
- }
16
- // In some cases, we want to just defer to whatever was in the source.
17
- function getSource(node, opts) {
18
- const { location } = node;
19
- return opts.originalText.slice(location.start_pos, location.end_pos);
20
- }
21
- const printer = {
22
- // This is the generic node print function, used to convert any node in the
23
- // AST into its equivalent Doc representation.
24
- print(path, opts, print) {
25
- const node = path.getValue();
26
- let doc = null;
27
- if (node.declarations) {
28
- // Prints out the root of the tree, which includes zero or more
29
- // declarations.
30
- return [
31
- join([hardline, hardline], path.map(print, "declarations")),
32
- hardline
33
- ];
34
- }
35
- /* istanbul ignore else */
36
- if (node.declaration) {
37
- switch (node.declaration) {
38
- // Prints out a type alias, which is a declaration that looks like:
39
- // type foo = String
40
- case "alias": {
41
- doc = group([
42
- "type ",
43
- node.name,
44
- " =",
45
- indent(group([line, path.call(printType, "type")]))
46
- ]);
47
- break;
48
- }
49
- // Prints out a class declarations, which looks like:
50
- // class Foo end
51
- case "class": {
52
- const nodePath = path;
53
- const parts = [
54
- "class ",
55
- printNameAndTypeParams(nodePath, node)
56
- ];
57
- if (node.super_class) {
58
- const superPath = nodePath;
59
- parts.push(" < ", superPath.call(printNameAndArgs, "super_class"));
60
- }
61
- parts.push(indent(printMembers(nodePath)), hardline, "end");
62
- doc = group(parts);
63
- break;
64
- }
65
- // Prints out a constant or a global declaration, which looks like:
66
- // Foo: String
67
- // $foo: String
68
- case "constant":
69
- case "global": {
70
- doc = group([node.name, ": ", path.call(printType, "type")]);
71
- break;
72
- }
73
- // Prints out an interface declaration, which looks like:
74
- // interface _Foo end
75
- case "interface": {
76
- const nodePath = path;
77
- doc = group([
78
- "interface ",
79
- printNameAndTypeParams(nodePath, node),
80
- indent(printMembers(nodePath)),
81
- hardline,
82
- "end"
83
- ]);
84
- break;
85
- }
86
- // Prints out a module declaration, which looks like:
87
- // module Foo end
88
- case "module": {
89
- const nodePath = path;
90
- const parts = [
91
- "module ",
92
- printNameAndTypeParams(nodePath, node)
93
- ];
94
- if (node.self_types.length > 0) {
95
- parts.push(" : ", join(", ", nodePath.map(printNameAndArgs, "self_types")));
96
- }
97
- parts.push(indent(printMembers(nodePath)), hardline, "end");
98
- doc = group(parts);
99
- break;
100
- }
101
- /* istanbul ignore next */
102
- default:
103
- throw new Error(`unknown declaration: ${node.declaration}`);
104
- }
105
- }
106
- else if (node.member) {
107
- switch (node.member) {
108
- // Prints out an alias within a declaration, which looks like:
109
- // alias foo bar
110
- // alias self.foo self.bar
111
- case "alias": {
112
- if (node.kind === "singleton") {
113
- doc = ["alias self.", node.new_name, " self.", node.old_name];
114
- }
115
- else {
116
- doc = ["alias ", node.new_name, " ", node.old_name];
117
- }
118
- break;
119
- }
120
- // Prints out an attr_* meta method, which looks like:
121
- // attr_accessor foo
122
- // attr_reader self.foo()
123
- // attr_writer self.foo(@bar): String
124
- case "attr_accessor":
125
- case "attr_reader":
126
- case "attr_writer": {
127
- const parts = [node.member, " "];
128
- if (node.kind === "singleton") {
129
- parts.push("self.");
130
- }
131
- parts.push(node.name);
132
- if (node.ivar_name === false) {
133
- parts.push("()");
134
- }
135
- else if (node.ivar_name) {
136
- parts.push("(", node.ivar_name, ")");
137
- }
138
- parts.push(": ", path.call(printType, "type"));
139
- doc = group(parts);
140
- break;
141
- }
142
- // Prints out a class or instance variable member, which looks like:
143
- // @foo: String
144
- // @@foo: String
145
- case "class_variable":
146
- case "instance_variable": {
147
- doc = group([node.name, ": ", path.call(printType, "type")]);
148
- break;
149
- }
150
- // Prints out a class instance variable member, which looks like:
151
- // self.@foo: String
152
- case "class_instance_variable": {
153
- doc = ["self.", node.name, ": ", path.call(printType, "type")];
154
- break;
155
- }
156
- // Prints out a mixin, which looks like:
157
- // include Foo
158
- // prepend Foo
159
- // extend Foo
160
- case "include":
161
- case "extend":
162
- case "prepend": {
163
- const nodePath = path;
164
- doc = group([node.member, " ", printNameAndArgs(nodePath)]);
165
- break;
166
- }
167
- case "public":
168
- case "private": {
169
- doc = node.member;
170
- break;
171
- }
172
- case "method_definition": {
173
- const nodePath = path;
174
- doc = printMethodDefinition(nodePath, node);
175
- break;
176
- }
177
- /* istanbul ignore next */
178
- default:
179
- throw new Error(`unknown member: ${node.member}`);
180
- }
181
- }
182
- else {
183
- const ast = JSON.stringify(node, null, 2);
184
- throw new Error(`Unsupported node encountered:\n${ast}`);
185
- }
186
- // An annotation can be attached to most kinds of nodes, and should be
187
- // printed using %a{}. Certain nodes can't have annotations at all.
188
- if (node.annotations && node.annotations.length > 0) {
189
- const annotationsPath = path;
190
- doc = [
191
- join(hardline, annotationsPath.map((annotationPath) => {
192
- const annotationNode = annotationPath.getValue();
193
- // If there are already braces inside the annotation, then we're
194
- // just going to print out the original string to avoid having to
195
- // escape anything.
196
- if (/[{}]/.test(annotationNode.string)) {
197
- return getSource(annotationNode, opts);
198
- }
199
- return ["%a{", annotationNode.string, "}"];
200
- }, "annotations")),
201
- hardline,
202
- doc
203
- ];
204
- }
205
- // Comments come in as one whole string, so here we split it up into
206
- // multiple lines and then prefix it with the pound sign.
207
- if (node.comment) {
208
- doc = [
209
- join(hardline, node.comment.string
210
- .slice(0, -1)
211
- .split("\n")
212
- .map((segment) => `# ${segment}`)),
213
- hardline,
214
- doc
215
- ];
216
- }
217
- return doc;
218
- // Prints out a string in the source, which looks like:
219
- // 'foo'
220
- function printString(node) {
221
- // We're going to go straight to the source here, as if we don't then
222
- // we're going to end up with the result of String#inspect, which does
223
- // weird things to escape sequences.
224
- const value = getSource(node, opts);
225
- // Get the quote that was used in the source and the quote that we want to
226
- // be using.
227
- const originalQuote = value[0];
228
- const preferredQuote = opts.rubySingleQuote ? "'" : '"';
229
- // Determine if we're allowed to change the quote based on whether or not
230
- // there is an escape sequence in the source string.
231
- const quote = node.literal.includes("\\")
232
- ? originalQuote
233
- : preferredQuote;
234
- return makeString(value.slice(1, -1), quote, false);
235
- }
236
- // Certain nodes are names with optional arguments attached, as in Array[A].
237
- // We handle all of that printing centralized here.
238
- function printNameAndArgs(path) {
239
- const node = path.getValue();
240
- if (node.args.length === 0) {
241
- return node.name;
242
- }
243
- return group([
244
- node.name,
245
- "[",
246
- join(", ", path.map(printType, "args")),
247
- "]"
248
- ]);
249
- }
250
- // This is the big function that prints out any individual type, which can
251
- // look like all kinds of things, listed in the case statement below.
252
- function printType(path, options) {
253
- const node = path.getValue();
254
- const forceParens = typeof options === "object" && options.forceParens;
255
- switch (node.class) {
256
- case "literal":
257
- if (node.literal[0] === '"') {
258
- return printString(node);
259
- }
260
- return node.literal;
261
- case "optional": {
262
- const nodePath = path;
263
- return [
264
- nodePath.call((typePath) => printType(typePath, { forceParens: true }), "type"),
265
- "?"
266
- ];
267
- }
268
- case "tuple": {
269
- // If we don't have any sub types, we explicitly need the space in
270
- // between the brackets to not confuse the parser.
271
- if (node.types.length === 0) {
272
- return "[ ]";
273
- }
274
- const nodePath = path;
275
- return group([
276
- "[",
277
- join(", ", nodePath.map(printType, "types")),
278
- "]"
279
- ]);
280
- }
281
- case "union": {
282
- const nodePath = path;
283
- const doc = group(join([line, "| "], nodePath.map(printType, "types")));
284
- if (forceParens) {
285
- return ["(", doc, ")"];
286
- }
287
- return doc;
288
- }
289
- case "intersection": {
290
- const nodePath = path;
291
- const doc = group(join([line, "& "], nodePath.map((typePath) => printType(typePath, { forceParens: true }), "types")));
292
- if (forceParens) {
293
- return ["(", doc, ")"];
294
- }
295
- return doc;
296
- }
297
- case "class_singleton":
298
- return ["singleton(", node.name, ")"];
299
- case "proc":
300
- return [
301
- "^",
302
- printMethodSignature(path)
303
- ];
304
- case "record": {
305
- const nodePath = path;
306
- const parts = [];
307
- getSortedKeys(node.fields).forEach((field) => {
308
- const fieldParts = [];
309
- if (node.fields[field].joiner === "rocket") {
310
- fieldParts.push(`${field} => `);
311
- }
312
- else {
313
- fieldParts.push(`${field}: `);
314
- }
315
- fieldParts.push(nodePath.call(printType, "fields", field, "type"));
316
- parts.push(fieldParts);
317
- });
318
- return group([
319
- "{",
320
- indent([line, join([",", line], parts)]),
321
- line,
322
- "}"
323
- ]);
324
- }
325
- case "class_instance":
326
- case "interface": {
327
- const nodePath = path;
328
- return printNameAndArgs(nodePath);
329
- }
330
- case "alias":
331
- case "variable":
332
- return node.name;
333
- case "bool":
334
- case "bot":
335
- case "class":
336
- case "instance":
337
- case "nil":
338
- case "self":
339
- case "top":
340
- case "untyped":
341
- case "void":
342
- return node.class;
343
- /* istanbul ignore next */
344
- default:
345
- throw new Error(`unknown type: ${node.class}`);
346
- }
347
- }
348
- // Prints out the members of a class, module, or interface.
349
- function printMembers(path) {
350
- let lastLine = null;
351
- const docs = [];
352
- path.each((memberPath) => {
353
- const memberNode = memberPath.getValue();
354
- if (lastLine !== null &&
355
- memberNode.location.start.line - lastLine >= 2) {
356
- docs.push([hardline, hardline]);
357
- }
358
- else {
359
- docs.push(hardline);
360
- }
361
- docs.push(print(memberPath));
362
- lastLine = memberNode.location.end.line;
363
- }, "members");
364
- return docs;
365
- }
366
- // Prints out the name of a class, interface, or module declaration.
367
- // Additionally loops through each type parameter if there are any and print
368
- // them out joined by commas. Checks for validation and variance.
369
- function printNameAndTypeParams(path, node) {
370
- if (node.type_params.params.length === 0) {
371
- return node.name;
372
- }
373
- const docs = path.map((paramPath) => {
374
- const node = paramPath.getValue();
375
- const parts = [];
376
- if (node.skip_validation) {
377
- parts.push("unchecked");
378
- }
379
- if (node.variance === "covariant") {
380
- parts.push("out");
381
- }
382
- else if (node.variance === "contravariant") {
383
- parts.push("in");
384
- }
385
- return join(" ", [...parts, node.name]);
386
- }, "type_params", "params");
387
- return [node.name, "[", join(", ", docs), "]"];
388
- }
389
- // Returns an array of printed parameters so that the calling function can
390
- // join them together in whatever way.
391
- function printMethodParams(path) {
392
- const node = path.getValue();
393
- let parts = [];
394
- // required positionals, as in (A)
395
- parts = parts.concat(path.map(printMethodParam, "required_positionals"));
396
- // optional positionals, as in (?A)
397
- parts = parts.concat(path.map((paramPath) => ["?", printMethodParam(paramPath)], "optional_positionals"));
398
- // rest positional, as in (*A)
399
- if (node.rest_positionals) {
400
- const restPositionalsPath = path;
401
- parts.push([
402
- "*",
403
- restPositionalsPath.call(printMethodParam, "rest_positionals")
404
- ]);
405
- }
406
- // trailing positionals are required positionals after a rest
407
- parts = parts.concat(path.map(printMethodParam, "trailing_positionals"));
408
- // required keywords, as in (a: A)
409
- getSortedKeys(node.required_keywords).forEach((name) => {
410
- parts.push([
411
- name,
412
- ": ",
413
- path.call(printMethodParam, "required_keywords", name)
414
- ]);
415
- });
416
- // optional keywords, as in (?a: A)
417
- getSortedKeys(node.optional_keywords).forEach((name) => {
418
- parts.push([
419
- "?",
420
- name,
421
- ": ",
422
- path.call(printMethodParam, "optional_keywords", name)
423
- ]);
424
- });
425
- // rest keyword, as in (**A)
426
- if (node.rest_keywords) {
427
- const restKeywordsPath = path;
428
- parts.push([
429
- "**",
430
- restKeywordsPath.call(printMethodParam, "rest_keywords")
431
- ]);
432
- }
433
- return parts;
434
- // Prints out a method parameter at a given path. Handles printing out the
435
- // name if there is one (and whether or not it's escaped).
436
- function printMethodParam(path) {
437
- const node = path.getValue();
438
- const parts = [path.call(printType, "type")];
439
- if (node.name) {
440
- parts.push(" ");
441
- if (node.escaped) {
442
- parts.push("`", node.name, "`");
443
- }
444
- else {
445
- parts.push(node.name);
446
- }
447
- }
448
- return parts;
449
- }
450
- }
451
- // Prints out a specific method signature, which looks like:
452
- // (T t) -> void
453
- function printMethodSignature(path) {
454
- const node = path.getValue();
455
- const parts = [];
456
- // We won't have a type_params key if we're printing a block
457
- if (node.type_params && node.type_params.length > 0) {
458
- parts.push("[", join(", ", node.type_params), "] ");
459
- }
460
- const params = path.call(printMethodParams, "type");
461
- if (params.length > 0) {
462
- parts.push("(", indent([softline, join([",", line], params)]), softline, ") ");
463
- }
464
- if (node.block) {
465
- if (!node.block.required) {
466
- parts.push("?");
467
- }
468
- parts.push("{", indent([line, path.call(printMethodSignature, "block")]), line, "} ");
469
- }
470
- parts.push("-> ", path.call((typePath) => printType(typePath, { forceParens: true }), "type", "return_type"));
471
- return group(parts);
472
- }
473
- // Prints out a method definition, which looks like:
474
- // def t: (T t) -> void
475
- function printMethodDefinition(path, node) {
476
- let typeDocs = path.map(printMethodSignature, "types");
477
- if (node.overload) {
478
- typeDocs.push("...");
479
- }
480
- if (typeDocs.length === 1) {
481
- typeDocs = [" ", typeDocs[0]];
482
- }
483
- else {
484
- typeDocs = indent(group([line, join([line, "| "], typeDocs)]));
485
- }
486
- const parts = ["def "];
487
- if (node.kind === "singleton") {
488
- parts.push("self.");
489
- }
490
- else if (node.kind === "singleton_instance") {
491
- parts.push("self?.");
492
- }
493
- const escaped = isMethodNameEscaped();
494
- parts.push(escaped ? `\`${node.name}\`` : node.name, ":", typeDocs);
495
- return group(parts);
496
- // Determine if a method name is escaped in the original source.
497
- function isMethodNameEscaped() {
498
- const pos = node.location.start_pos + 4;
499
- const name = opts.originalText.slice(pos, pos + 2).trimStart();
500
- return name[0] === "`" && name[1] !== ":";
501
- }
502
- }
503
- },
504
- // This is an escape-hatch to ignore nodes in the tree. If you have a comment
505
- // that includes this pattern, then the entire node will be ignored and just
506
- // the original source will be printed out.
507
- hasPrettierIgnore(path) {
508
- const node = path.getValue();
509
- return ((node.comment && node.comment.string.includes("prettier-ignore")) || false);
510
- },
511
- // This function handles adding the format pragma to a source string. This is
512
- // an optional workflow for incremental adoption.
513
- insertPragma(text) {
514
- return `# @format${text[0] === "#" ? "\n" : "\n\n"}${text}`;
515
- }
516
- };
517
- exports.default = printer;