prettier 1.6.1 → 2.0.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +316 -293
  3. data/CONTRIBUTING.md +6 -9
  4. data/LICENSE +1 -1
  5. data/README.md +11 -12
  6. data/dist/haml/embed.js +53 -0
  7. data/dist/haml/parser.js +31 -0
  8. data/{src → dist}/haml/parser.rb +0 -0
  9. data/dist/haml/printer.js +336 -0
  10. data/dist/parser/getInfo.js +17 -0
  11. data/{src → dist}/parser/netcat.js +1 -0
  12. data/dist/parser/parseSync.js +128 -0
  13. data/dist/parser/server.rb +140 -0
  14. data/dist/plugin.js +143 -0
  15. data/dist/prettier.js +15 -0
  16. data/dist/rbs/parser.js +34 -0
  17. data/{src → dist}/rbs/parser.rb +0 -0
  18. data/dist/rbs/printer.js +517 -0
  19. data/dist/ruby/embed.js +110 -0
  20. data/dist/ruby/nodes/alias.js +59 -0
  21. data/{src → dist}/ruby/nodes/aref.js +26 -35
  22. data/dist/ruby/nodes/args.js +165 -0
  23. data/dist/ruby/nodes/arrays.js +126 -0
  24. data/dist/ruby/nodes/assign.js +41 -0
  25. data/dist/ruby/nodes/blocks.js +68 -0
  26. data/dist/ruby/nodes/calls.js +220 -0
  27. data/dist/ruby/nodes/case.js +50 -0
  28. data/dist/ruby/nodes/class.js +54 -0
  29. data/dist/ruby/nodes/commands.js +124 -0
  30. data/dist/ruby/nodes/conditionals.js +242 -0
  31. data/dist/ruby/nodes/constants.js +38 -0
  32. data/dist/ruby/nodes/flow.js +66 -0
  33. data/dist/ruby/nodes/hashes.js +130 -0
  34. data/dist/ruby/nodes/heredocs.js +30 -0
  35. data/dist/ruby/nodes/hooks.js +35 -0
  36. data/dist/ruby/nodes/ints.js +27 -0
  37. data/dist/ruby/nodes/lambdas.js +69 -0
  38. data/dist/ruby/nodes/loops.js +73 -0
  39. data/dist/ruby/nodes/massign.js +73 -0
  40. data/dist/ruby/nodes/methods.js +70 -0
  41. data/dist/ruby/nodes/operators.js +70 -0
  42. data/dist/ruby/nodes/params.js +89 -0
  43. data/dist/ruby/nodes/patterns.js +109 -0
  44. data/dist/ruby/nodes/regexp.js +45 -0
  45. data/dist/ruby/nodes/rescue.js +82 -0
  46. data/dist/ruby/nodes/return.js +75 -0
  47. data/dist/ruby/nodes/statements.js +111 -0
  48. data/dist/ruby/nodes/strings.js +218 -0
  49. data/dist/ruby/nodes/super.js +30 -0
  50. data/dist/ruby/nodes/undef.js +26 -0
  51. data/dist/ruby/nodes.js +151 -0
  52. data/dist/ruby/parser.js +34 -0
  53. data/{src → dist}/ruby/parser.rb +1215 -252
  54. data/dist/ruby/printer.js +125 -0
  55. data/dist/ruby/toProc.js +93 -0
  56. data/dist/types/haml.js +4 -0
  57. data/dist/types/plugin.js +3 -0
  58. data/dist/types/rbs.js +4 -0
  59. data/dist/types/ruby.js +4 -0
  60. data/dist/types/utils.js +2 -0
  61. data/dist/types.js +30 -0
  62. data/dist/utils/containsAssignment.js +15 -0
  63. data/dist/utils/getTrailingComma.js +6 -0
  64. data/dist/utils/hasAncestor.js +15 -0
  65. data/{src → dist}/utils/inlineEnsureParens.js +16 -17
  66. data/dist/utils/isEmptyBodyStmt.js +10 -0
  67. data/dist/utils/isEmptyStmts.js +10 -0
  68. data/dist/utils/literal.js +8 -0
  69. data/dist/utils/literallineWithoutBreakParent.js +8 -0
  70. data/dist/utils/makeCall.js +13 -0
  71. data/dist/utils/noIndent.js +11 -0
  72. data/dist/utils/printEmptyCollection.js +44 -0
  73. data/dist/utils/skipAssignIndent.js +15 -0
  74. data/dist/utils.js +30 -0
  75. data/node_modules/prettier/bin-prettier.js +313 -190
  76. data/node_modules/prettier/doc.js +191 -323
  77. data/node_modules/prettier/index.js +2753 -3677
  78. data/node_modules/prettier/package.json +1 -1
  79. data/node_modules/prettier/parser-angular.js +13 -14
  80. data/node_modules/prettier/parser-babel.js +7 -7
  81. data/node_modules/prettier/parser-espree.js +7 -7
  82. data/node_modules/prettier/parser-flow.js +7 -7
  83. data/node_modules/prettier/parser-glimmer.js +1 -1
  84. data/node_modules/prettier/parser-graphql.js +1 -1
  85. data/node_modules/prettier/parser-html.js +17 -17
  86. data/node_modules/prettier/parser-markdown.js +9 -9
  87. data/node_modules/prettier/parser-meriyah.js +7 -7
  88. data/node_modules/prettier/parser-postcss.js +2 -2
  89. data/node_modules/prettier/parser-typescript.js +7 -7
  90. data/node_modules/prettier/parser-yaml.js +2 -2
  91. data/node_modules/prettier/third-party.js +143 -78
  92. data/package.json +26 -18
  93. metadata +74 -67
  94. data/src/haml/embed.js +0 -87
  95. data/src/haml/parser.js +0 -23
  96. data/src/haml/printer.js +0 -438
  97. data/src/parser/parseSync.js +0 -172
  98. data/src/parser/server.rb +0 -66
  99. data/src/plugin.js +0 -148
  100. data/src/prettier.js +0 -16
  101. data/src/rbs/parser.js +0 -37
  102. data/src/rbs/printer.js +0 -643
  103. data/src/ruby/embed.js +0 -142
  104. data/src/ruby/nodes/alias.js +0 -73
  105. data/src/ruby/nodes/args.js +0 -222
  106. data/src/ruby/nodes/arrays.js +0 -162
  107. data/src/ruby/nodes/assign.js +0 -47
  108. data/src/ruby/nodes/blocks.js +0 -90
  109. data/src/ruby/nodes/calls.js +0 -246
  110. data/src/ruby/nodes/case.js +0 -65
  111. data/src/ruby/nodes/class.js +0 -64
  112. data/src/ruby/nodes/commands.js +0 -131
  113. data/src/ruby/nodes/conditionals.js +0 -282
  114. data/src/ruby/nodes/constants.js +0 -43
  115. data/src/ruby/nodes/flow.js +0 -74
  116. data/src/ruby/nodes/hashes.js +0 -155
  117. data/src/ruby/nodes/heredocs.js +0 -36
  118. data/src/ruby/nodes/hooks.js +0 -34
  119. data/src/ruby/nodes/ints.js +0 -31
  120. data/src/ruby/nodes/lambdas.js +0 -76
  121. data/src/ruby/nodes/loops.js +0 -98
  122. data/src/ruby/nodes/massign.js +0 -98
  123. data/src/ruby/nodes/methods.js +0 -74
  124. data/src/ruby/nodes/operators.js +0 -83
  125. data/src/ruby/nodes/params.js +0 -106
  126. data/src/ruby/nodes/patterns.js +0 -157
  127. data/src/ruby/nodes/regexp.js +0 -56
  128. data/src/ruby/nodes/rescue.js +0 -101
  129. data/src/ruby/nodes/return.js +0 -94
  130. data/src/ruby/nodes/statements.js +0 -142
  131. data/src/ruby/nodes/strings.js +0 -272
  132. data/src/ruby/nodes/super.js +0 -35
  133. data/src/ruby/nodes/undef.js +0 -42
  134. data/src/ruby/nodes.js +0 -34
  135. data/src/ruby/parser.js +0 -37
  136. data/src/ruby/printer.js +0 -147
  137. data/src/ruby/toProc.js +0 -105
  138. data/src/utils/containsAssignment.js +0 -11
  139. data/src/utils/getTrailingComma.js +0 -5
  140. data/src/utils/hasAncestor.js +0 -17
  141. data/src/utils/isEmptyBodyStmt.js +0 -7
  142. data/src/utils/isEmptyStmts.js +0 -11
  143. data/src/utils/literal.js +0 -7
  144. data/src/utils/literallineWithoutBreakParent.js +0 -7
  145. data/src/utils/makeCall.js +0 -14
  146. data/src/utils/noIndent.js +0 -10
  147. data/src/utils/printEmptyCollection.js +0 -49
  148. data/src/utils/skipAssignIndent.js +0 -17
  149. data/src/utils.js +0 -13
data/src/haml/parser.js DELETED
@@ -1,23 +0,0 @@
1
- const parseSync = require("../parser/parseSync");
2
-
3
- function parse(text, _parsers, opts) {
4
- return parseSync("haml", text, opts);
5
- }
6
-
7
- function hasPragma(text) {
8
- return /^\s*-#\s*@(prettier|format)/.test(text);
9
- }
10
-
11
- // These functions are just placeholders until we can actually perform this
12
- // properly. The functions are necessary otherwise the format with cursor
13
- // functions break.
14
- const locStart = (_node) => 0;
15
- const locEnd = (_node) => 0;
16
-
17
- module.exports = {
18
- parse,
19
- astFormat: "haml",
20
- hasPragma,
21
- locStart,
22
- locEnd
23
- };
data/src/haml/printer.js DELETED
@@ -1,438 +0,0 @@
1
- const {
2
- align,
3
- concat,
4
- fill,
5
- group,
6
- hardline,
7
- ifBreak,
8
- indent,
9
- join,
10
- line,
11
- softline
12
- } = require("../prettier");
13
- const embed = require("./embed");
14
-
15
- const docTypes = {
16
- basic: "Basic",
17
- frameset: "Frameset",
18
- mobile: "Mobile",
19
- rdfa: "RDFa",
20
- strict: "Strict",
21
- xml: "XML"
22
- };
23
-
24
- const docVersions = ["1.1", "5"];
25
-
26
- // Prints out a hash key according to the configured prettier options.
27
- function printHashKey(key, opts) {
28
- let quoted = key;
29
- const joiner = opts.rubyHashLabel ? ":" : " =>";
30
-
31
- if (key.includes(":") || key.includes("-")) {
32
- const quote = opts.rubySingleQuote ? "'" : '"';
33
- quoted = `${quote}${key}${quote}`;
34
- }
35
-
36
- return `${opts.rubyHashLabel ? "" : ":"}${quoted}${joiner}`;
37
- }
38
-
39
- // Prints out the value inside of a hash key-value pair according to the
40
- // configured prettier options.
41
- function printHashValue(value, opts) {
42
- if (typeof value !== "string") {
43
- return value.toString();
44
- }
45
-
46
- // This is a very special syntax created by the parser to let us know that
47
- // this should be printed literally instead of as a string.
48
- if (value.startsWith("&")) {
49
- return value.slice(1);
50
- }
51
-
52
- const quote = opts.rubySingleQuote && !value.includes("#{") ? "'" : '"';
53
- return `${quote}${value}${quote}`;
54
- }
55
-
56
- // This will print an attributes object to a Doc node. It handles nesting on
57
- // multiple levels and will print out according to whether or not the version of
58
- // HAML being used supports multi-line attributes.
59
- function printAttributes(object, opts, level = 0) {
60
- if (typeof object !== "object") {
61
- return printHashValue(object, opts);
62
- }
63
-
64
- const boundary = level === 0 ? softline : line;
65
- const parts = Object.keys(object).map((key) =>
66
- concat([
67
- printHashKey(key, opts),
68
- " ",
69
- printAttributes(object[key], opts, level + 1)
70
- ])
71
- );
72
-
73
- // If we have support for multi-line attributes laid out like a regular hash,
74
- // then we print them that way here.
75
- if (opts.supportsMultiline) {
76
- return group(
77
- concat([
78
- "{",
79
- indent(group(concat([boundary, join(concat([",", line]), parts)]))),
80
- boundary,
81
- "}"
82
- ])
83
- );
84
- }
85
-
86
- // Otherwise, if we only have one attribute, then just print it inline
87
- // regardless of how long it is.
88
- if (parts.length === 0) {
89
- return group(concat(["{", parts[0], "}"]));
90
- }
91
-
92
- // Otherwise, depending on how long the line is it will split the content into
93
- // multi-line attributes that old Haml understands.
94
- return group(
95
- concat([
96
- "{",
97
- parts[0],
98
- ",",
99
- align(
100
- opts.headerLength + 1,
101
- concat([line, join(concat([",", line]), parts.slice(1))])
102
- ),
103
- "}"
104
- ])
105
- );
106
- }
107
-
108
- // A utility function used in a silent script that is meant to determine if a
109
- // child node is a continuation of a parent node (as in a when clause within a
110
- // case statement or an else clause within an if).
111
- function isContinuation(parentNode, childNode) {
112
- if (childNode.type !== "silent_script") {
113
- return false;
114
- }
115
-
116
- const parent = parentNode.value.keyword;
117
- const child = childNode.value.keyword;
118
-
119
- return (
120
- (parent === "case" && ["when", "else"].includes(child)) ||
121
- (["if", "unless"].includes(parent) && ["elsif", "else"].includes(child))
122
- );
123
- }
124
-
125
- // This is our printer's main print function that will switch on the type of
126
- // node and print it out by returning a Doc tree.
127
- function printNode(path, opts, print) {
128
- const node = path.getValue();
129
- const { value } = node;
130
-
131
- switch (node.type) {
132
- case "comment":
133
- return printComment();
134
- case "doctype":
135
- return printDoctype();
136
- case "filter":
137
- return printFilter();
138
- case "haml_comment":
139
- return printHamlComment();
140
- case "plain":
141
- return printPlain();
142
- case "root":
143
- return printRoot();
144
- case "script":
145
- return printScript();
146
- case "silent_script":
147
- return printSilentScript();
148
- case "tag":
149
- return printTag();
150
- default:
151
- throw new Error(`Unsupported node encountered: ${node.type}`);
152
- }
153
-
154
- // It's common to a couple of nodes to attach nested child nodes on the
155
- // children property. This utility prints them out grouped together with their
156
- // parent node docs.
157
- function printWithChildren(docs) {
158
- if (node.children.length === 0) {
159
- return docs;
160
- }
161
-
162
- return group(
163
- concat([
164
- docs,
165
- indent(concat([hardline, join(hardline, path.map(print, "children"))]))
166
- ])
167
- );
168
- }
169
-
170
- // https://haml.info/docs/yardoc/file.REFERENCE.html#html-comments-
171
- function printComment() {
172
- const parts = ["/"];
173
-
174
- if (value.revealed) {
175
- parts.push("!");
176
- }
177
-
178
- if (value.conditional) {
179
- parts.push(value.conditional);
180
- } else if (value.text) {
181
- parts.push(" ", value.text);
182
- }
183
-
184
- return printWithChildren(group(concat(parts)));
185
- }
186
-
187
- // https://haml.info/docs/yardoc/file.REFERENCE.html#doctype-
188
- function printDoctype() {
189
- const parts = ["!!!"];
190
-
191
- if (value.type in docTypes) {
192
- parts.push(docTypes[value.type]);
193
- } else if (docVersions.includes(value.version)) {
194
- parts.push(value.version);
195
- } else {
196
- parts.push(value.type);
197
- }
198
-
199
- if (value.encoding) {
200
- parts.push(value.encoding);
201
- }
202
-
203
- return group(join(" ", parts));
204
- }
205
-
206
- // https://haml.info/docs/yardoc/file.REFERENCE.html#filters
207
- function printFilter() {
208
- return group(
209
- concat([
210
- ":",
211
- value.name,
212
- indent(
213
- concat([hardline, join(hardline, value.text.trim().split("\n"))])
214
- )
215
- ])
216
- );
217
- }
218
-
219
- // https://haml.info/docs/yardoc/file.REFERENCE.html#haml-comments--
220
- function printHamlComment() {
221
- const parts = ["-#"];
222
-
223
- if (value.text) {
224
- if (opts.originalText.split("\n")[node.line - 1].trim() === "-#") {
225
- const lines = value.text.trim().split("\n");
226
-
227
- parts.push(indent(concat([hardline, join(hardline, lines)])));
228
- } else {
229
- parts.push(" ", value.text.trim());
230
- }
231
- }
232
-
233
- return concat(parts);
234
- }
235
-
236
- // https://haml.info/docs/yardoc/file.REFERENCE.html#plain-text
237
- function printPlain() {
238
- return value.text;
239
- }
240
-
241
- // The root node in the AST that we build in the parser.
242
- function printRoot() {
243
- return concat([join(hardline, path.map(print, "children")), hardline]);
244
- }
245
-
246
- // https://haml.info/docs/yardoc/file.REFERENCE.html#inserting_ruby
247
- function printScript() {
248
- const parts = [];
249
-
250
- if (value.escape_html) {
251
- parts.unshift("&");
252
- }
253
-
254
- if (value.preserve) {
255
- parts.push("~");
256
- } else if (!value.interpolate) {
257
- parts.push("=");
258
- }
259
-
260
- if (value.escape_html && !value.preserve && value.interpolate) {
261
- parts.push(" ", value.text.trim().slice(1, -1));
262
- } else {
263
- parts.push(" ", value.text.trim());
264
- }
265
-
266
- return printWithChildren(group(concat(parts)));
267
- }
268
-
269
- // https://haml.info/docs/yardoc/file.REFERENCE.html#running-ruby--
270
- function printSilentScript() {
271
- const parts = [`- ${value.text.trim()}`];
272
-
273
- if (node.children.length > 0) {
274
- parts.push(
275
- concat(
276
- path.map((childPath) => {
277
- const child = childPath.getValue();
278
- const concated = concat([hardline, print(childPath)]);
279
-
280
- return isContinuation(node, child) ? concated : indent(concated);
281
- }, "children")
282
- )
283
- );
284
- }
285
-
286
- return group(concat(parts));
287
- }
288
-
289
- // https://haml.info/docs/yardoc/file.REFERENCE.html#element-name-
290
- function printTag() {
291
- const { attributes, dynamic_attributes } = value;
292
- const parts = [];
293
-
294
- // If we have a tag that isn't a div, then we need to print out that name of
295
- // that tag first. If it is a div, first we'll check if there are any other
296
- // things that would force us to print out the div explicitly, and otherwise
297
- // we'll leave it off.
298
- if (value.name !== "div") {
299
- parts.push(`%${value.name}`);
300
- }
301
-
302
- // If we have a class attribute, then we're going to print that here using
303
- // the special class syntax.
304
- if (attributes.class) {
305
- parts.push(`.${attributes.class.replace(/ /g, ".")}`);
306
- }
307
-
308
- // If we have an id attribute, then we're going to print that here using the
309
- // special id syntax.
310
- if (attributes.id) {
311
- parts.push(`#${attributes.id}`);
312
- }
313
-
314
- // If we're using dynamic attributes on this tag, then they come in as a
315
- // string that looks like the output of Hash#inspect from Ruby. So here
316
- // we're going to split it all up and print it out nicely.
317
- if (dynamic_attributes.new) {
318
- const pairs = dynamic_attributes.new
319
- .slice(1, -2)
320
- .split(",")
321
- .map((pair) => join("=", pair.slice(1).split('" => ')));
322
-
323
- parts.push(
324
- group(
325
- concat([
326
- "(",
327
- align(parts.join("").length + 1, fill(join(line, pairs).parts)),
328
- ")"
329
- ])
330
- )
331
- );
332
- }
333
-
334
- // If there are any static attributes that are not class or id (because we
335
- // already took care of those), then we're going to print them out here.
336
- const staticAttributes = Object.keys(attributes).filter(
337
- (name) => !["class", "id"].includes(name)
338
- );
339
-
340
- if (staticAttributes.length > 0) {
341
- const docs = staticAttributes.reduce((accum, key) => {
342
- const doc = `${printHashKey(key, opts)} ${printHashValue(
343
- attributes[key],
344
- opts
345
- )}`;
346
-
347
- return accum.length === 0 ? [doc] : accum.concat(",", line, doc);
348
- }, []);
349
-
350
- parts.push(
351
- group(concat(["{", align(parts.join("").length + 1, fill(docs)), "}"]))
352
- );
353
- }
354
-
355
- // If there are dynamic attributes that don't use the newer syntax, then
356
- // we're going to print them out here.
357
- if (dynamic_attributes.old) {
358
- if (parts.length === 0) {
359
- parts.push("%div");
360
- }
361
-
362
- if (typeof dynamic_attributes.old === "string") {
363
- parts.push(dynamic_attributes.old);
364
- } else {
365
- const attrOptions = {
366
- // This is kind of a total hack in that I don't think you're really
367
- // supposed to directly use `path.stack`, but it's the easiest way to
368
- // get the root node without having to know how many levels deep we
369
- // are.
370
- supportsMultiline: path.stack[0].supports_multiline,
371
- headerLength: parts.join("").length
372
- };
373
-
374
- parts.push(
375
- printAttributes(
376
- dynamic_attributes.old,
377
- Object.assign({}, opts, attrOptions)
378
- )
379
- );
380
- }
381
- }
382
-
383
- // https://haml.info/docs/yardoc/file.REFERENCE.html#object-reference-
384
- if (value.object_ref) {
385
- if (parts.length === 0) {
386
- parts.push("%div");
387
- }
388
- parts.push(value.object_ref);
389
- }
390
-
391
- // https://haml.info/docs/yardoc/file.REFERENCE.html#whitespace-removal--and-
392
- if (value.nuke_outer_whitespace) {
393
- parts.push(">");
394
- }
395
-
396
- if (value.nuke_inner_whitespace) {
397
- parts.push("<");
398
- }
399
-
400
- // https://haml.info/docs/yardoc/file.REFERENCE.html#empty-void-tags-
401
- if (value.self_closing) {
402
- parts.push("/");
403
- }
404
-
405
- if (value.value) {
406
- const prefix = value.parse ? "= " : ifBreak("", " ");
407
-
408
- return printWithChildren(
409
- group(
410
- concat([
411
- group(concat(parts)),
412
- indent(concat([softline, prefix, value.value]))
413
- ])
414
- )
415
- );
416
- }
417
-
418
- // In case none of the other if statements have matched and we're printing
419
- // a div, we need to explicitly add it back into the array.
420
- if (parts.length === 0 && value.name === "div") {
421
- parts.push("%div");
422
- }
423
-
424
- return printWithChildren(group(concat(parts)));
425
- }
426
- }
427
-
428
- // This function handles adding the format pragma to a source string. This is an
429
- // optional workflow for incremental adoption.
430
- function insertPragma(text) {
431
- return `-# @format${text.startsWith("-#") ? "\n" : "\n\n"}${text}`;
432
- }
433
-
434
- module.exports = {
435
- embed,
436
- print: printNode,
437
- insertPragma
438
- };
@@ -1,172 +0,0 @@
1
- const { spawn, spawnSync, execSync } = require("child_process");
2
- const { existsSync, mkdtempSync } = require("fs");
3
- const os = require("os");
4
- const path = require("path");
5
- const process = require("process");
6
-
7
- let sockfile = process.env.PRETTIER_RUBY_HOST;
8
- let netcat;
9
-
10
- // In order to properly parse ruby code, we need to tell the ruby process to
11
- // parse using UTF-8. Unfortunately, the way that you accomplish this looks
12
- // differently depending on your platform.
13
- /* istanbul ignore next */
14
- function getLang() {
15
- const { env, platform } = process;
16
- const envValue = env.LC_ALL || env.LC_CTYPE || env.LANG;
17
-
18
- // If an env var is set for the locale that already includes UTF-8 in the
19
- // name, then assume we can go with that.
20
- if (envValue && envValue.includes("UTF-8")) {
21
- return envValue;
22
- }
23
-
24
- // Otherwise, we're going to guess which encoding to use based on the system.
25
- // This is probably not the best approach in the world, as you could be on
26
- // linux and not have C.UTF-8, but in that case you're probably passing an env
27
- // var for it. This object below represents all of the possible values of
28
- // process.platform per:
29
- // https://nodejs.org/api/process.html#process_process_platform
30
- return {
31
- aix: "C.UTF-8",
32
- darwin: "en_US.UTF-8",
33
- freebsd: "C.UTF-8",
34
- linux: "C.UTF-8",
35
- openbsd: "C.UTF-8",
36
- sunos: "C.UTF-8",
37
- win32: ".UTF-8"
38
- }[platform];
39
- }
40
-
41
- // Spawn the parser.rb subprocess. We do this since booting Ruby is slow, and we
42
- // can re-use the parser process multiple times since it is statelesss.
43
- function spawnParseServer() {
44
- const tmpDir = mkdtempSync(path.join(os.tmpdir(), "prettier-ruby"));
45
- const tmpFile = path.join(tmpDir, `${process.pid}.sock`);
46
-
47
- const server = spawn("ruby", [path.join(__dirname, "./server.rb"), tmpFile], {
48
- env: Object.assign({}, process.env, { LANG: getLang() }),
49
- detached: true,
50
- stdio: "inherit"
51
- });
52
-
53
- process.on("exit", () => {
54
- try {
55
- process.kill(-server.pid);
56
- } catch (e) {
57
- // ignore
58
- }
59
- });
60
-
61
- server.unref();
62
- const now = new Date();
63
-
64
- // Wait for server to go live.
65
- while (!existsSync(tmpFile) && new Date() - now < 3000) {
66
- execSync("sleep 0.1");
67
- }
68
-
69
- return tmpFile;
70
- }
71
-
72
- // Checks to see if an executable is available.
73
- function hasCommand(name) {
74
- let result;
75
-
76
- if (os.type() === "Windows_NT") {
77
- result = spawnSync("where", [name]);
78
- } else {
79
- result = spawnSync("command", ["-v", name]);
80
- }
81
-
82
- return result.status === 0;
83
- }
84
-
85
- // Finds a netcat-like adapter to use for sending data to a socket. We order
86
- // these by likelihood of being found so we can avoid some shell-outs.
87
- function findNetcat(opts) {
88
- if (opts.rubyNetcatCommand) {
89
- const splits = opts.rubyNetcatCommand.split(" ");
90
- return { command: splits[0], args: splits.slice(1) };
91
- }
92
-
93
- if (hasCommand("nc")) {
94
- return { command: "nc", args: ["-U"] };
95
- }
96
-
97
- if (hasCommand("telnet")) {
98
- return { command: "telnet", args: ["-u"] };
99
- }
100
-
101
- if (hasCommand("ncat")) {
102
- return { command: "ncat", args: ["-U"] };
103
- }
104
-
105
- if (hasCommand("socat")) {
106
- return { command: "socat", args: ["-"] };
107
- }
108
-
109
- return { command: "node", args: [require.resolve("./netcat.js")] };
110
- }
111
-
112
- // Formats and sends a request to the parser server. We use netcat (or something
113
- // like it) here since Prettier requires the results of `parse` to be
114
- // synchronous and Node.js does not offer a mechanism for synchronous socket
115
- // requests.
116
- function parseSync(parser, source, opts) {
117
- if (!sockfile) {
118
- sockfile = spawnParseServer();
119
- }
120
-
121
- if (!netcat) {
122
- netcat = findNetcat(opts);
123
- }
124
-
125
- const response = spawnSync(netcat.command, netcat.args.concat(sockfile), {
126
- input: `${parser}|${source}`,
127
- maxBuffer: 15 * 1024 * 1024
128
- });
129
-
130
- const stdout = response.stdout.toString();
131
- const stderr = response.stderr.toString();
132
- const { status } = response;
133
-
134
- // We need special handling in case the user's version of nc doesn't support
135
- // using unix sockets.
136
- if (
137
- stderr.includes("invalid option -- U") ||
138
- stderr.includes("invalid option -- 'u'") ||
139
- stderr.includes("Protocol not supported")
140
- ) {
141
- throw new Error(`
142
- @prettier/plugin-ruby uses unix sockets to communicate between the node.js
143
- process running prettier and an underlying Ruby process used for parsing.
144
- Unfortunately the command that it tried to use to do that
145
- (${netcat.command}) does not support unix sockets. To solve this either
146
- uninstall the version of ${netcat.command} that you're using and use a
147
- different implementation, or change the value of the rubyNetcatCommand
148
- option in your prettier configuration.
149
- `);
150
- }
151
-
152
- // If we didn't receive anything over stdout or we have a bad exit status,
153
- // then throw whatever we can.
154
- if (stdout.length === 0 || (status !== null && status !== 0)) {
155
- throw new Error(stderr || "An unknown error occurred");
156
- }
157
-
158
- const parsed = JSON.parse(stdout);
159
-
160
- if (parsed.error) {
161
- const error = new Error(parsed.error);
162
- if (parsed.loc) {
163
- error.loc = parsed.loc;
164
- }
165
-
166
- throw error;
167
- }
168
-
169
- return parsed;
170
- }
171
-
172
- module.exports = parseSync;
data/src/parser/server.rb DELETED
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup' if ENV['PLUGIN_RUBY_CI']
4
- require 'socket'
5
- require 'json'
6
-
7
- require_relative '../ruby/parser'
8
- require_relative '../rbs/parser'
9
- require_relative '../haml/parser'
10
-
11
- # Set the program name so that it's easy to find if we need it
12
- $PROGRAM_NAME = 'prettier-ruby-parser'
13
-
14
- # Make sure we trap these signals to be sure we get the quit command coming from
15
- # the parent node process
16
- quit = false
17
- trap(:QUIT) { quit = true } if RUBY_PLATFORM != 'java'
18
- trap(:INT) { quit = true }
19
- trap(:TERM) { quit = true }
20
-
21
- sockfile = ARGV.first || "/tmp/#{$PROGRAM_NAME}.sock"
22
- server = UNIXServer.new(sockfile)
23
-
24
- at_exit do
25
- server.close
26
- File.unlink(sockfile)
27
- end
28
-
29
- loop do
30
- break if quit
31
-
32
- # Start up a new thread that will handle each successive connection.
33
- Thread.new(server.accept_nonblock) do |socket|
34
- parser, source = socket.read.force_encoding('UTF-8').split('|', 2)
35
-
36
- response =
37
- case parser
38
- when 'ruby'
39
- Prettier::Parser.parse(source)
40
- when 'rbs'
41
- Prettier::RBSParser.parse(source)
42
- when 'haml'
43
- Prettier::HAMLParser.parse(source)
44
- end
45
-
46
- if response
47
- socket.write(JSON.fast_generate(response))
48
- else
49
- socket.write('{ "error": true }')
50
- end
51
- rescue Prettier::Parser::ParserError => error
52
- loc = { start: { line: error.lineno, column: error.column } }
53
- socket.write(JSON.fast_generate(error: error.message, loc: loc))
54
- rescue StandardError => error
55
- socket.write(JSON.fast_generate(error: error.message))
56
- ensure
57
- socket.close
58
- end
59
- rescue IO::WaitReadable, Errno::EINTR
60
- # Wait for select(2) to give us a connection that has content for 1 second.
61
- # Otherwise timeout and continue on (so that we hit our "break if quit"
62
- # pretty often).
63
- IO.select([server], nil, nil, 1)
64
-
65
- retry unless quit
66
- end