prettier 2.0.0.pre.rc4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +58 -10
  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 +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 +10 -24
  26. data/rubocop.yml +14 -8
  27. data/src/getInfo.js +23 -0
  28. data/{dist/parser → src}/netcat.js +0 -1
  29. data/src/parseSync.js +212 -0
  30. data/src/plugin.js +161 -0
  31. data/{dist/parser → src}/server.rb +45 -27
  32. metadata +97 -77
  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 -109
  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;