prettier 1.2.1 → 1.3.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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -1
  3. data/CONTRIBUTING.md +2 -2
  4. data/README.md +21 -91
  5. data/lib/prettier.rb +2 -2
  6. data/node_modules/prettier/index.js +54 -54
  7. data/package.json +3 -4
  8. data/rubocop.yml +26 -0
  9. data/src/haml/embed.js +87 -0
  10. data/src/haml/nodes/comment.js +27 -0
  11. data/src/haml/nodes/doctype.js +34 -0
  12. data/src/haml/nodes/filter.js +16 -0
  13. data/src/haml/nodes/hamlComment.js +21 -0
  14. data/src/haml/nodes/plain.js +6 -0
  15. data/src/haml/nodes/root.js +8 -0
  16. data/src/haml/nodes/script.js +33 -0
  17. data/src/haml/nodes/silentScript.js +59 -0
  18. data/src/haml/nodes/tag.js +193 -0
  19. data/src/haml/parser.js +33 -0
  20. data/src/haml/parser.rb +141 -0
  21. data/src/haml/printer.js +28 -0
  22. data/src/{ruby.js → plugin.js} +25 -4
  23. data/src/prettier.js +1 -0
  24. data/src/rbs/parser.js +51 -0
  25. data/src/rbs/parser.rb +91 -0
  26. data/src/rbs/printer.js +605 -0
  27. data/src/{embed.js → ruby/embed.js} +6 -2
  28. data/src/{nodes.js → ruby/nodes.js} +0 -0
  29. data/src/{nodes → ruby/nodes}/alias.js +1 -1
  30. data/src/{nodes → ruby/nodes}/aref.js +8 -1
  31. data/src/{nodes → ruby/nodes}/args.js +2 -2
  32. data/src/{nodes → ruby/nodes}/arrays.js +2 -3
  33. data/src/{nodes → ruby/nodes}/assign.js +7 -3
  34. data/src/ruby/nodes/blocks.js +90 -0
  35. data/src/{nodes → ruby/nodes}/calls.js +18 -11
  36. data/src/{nodes → ruby/nodes}/case.js +1 -1
  37. data/src/{nodes → ruby/nodes}/class.js +1 -1
  38. data/src/ruby/nodes/commands.js +131 -0
  39. data/src/{nodes → ruby/nodes}/conditionals.js +3 -3
  40. data/src/{nodes → ruby/nodes}/constants.js +2 -2
  41. data/src/{nodes → ruby/nodes}/flow.js +2 -2
  42. data/src/{nodes → ruby/nodes}/hashes.js +32 -10
  43. data/src/{nodes → ruby/nodes}/heredocs.js +2 -2
  44. data/src/ruby/nodes/hooks.js +34 -0
  45. data/src/{nodes → ruby/nodes}/ints.js +0 -0
  46. data/src/{nodes → ruby/nodes}/lambdas.js +2 -2
  47. data/src/{nodes → ruby/nodes}/loops.js +10 -7
  48. data/src/{nodes → ruby/nodes}/massign.js +8 -1
  49. data/src/{nodes → ruby/nodes}/methods.js +10 -9
  50. data/src/{nodes → ruby/nodes}/operators.js +2 -2
  51. data/src/{nodes → ruby/nodes}/params.js +31 -16
  52. data/src/{nodes → ruby/nodes}/patterns.js +17 -6
  53. data/src/{nodes → ruby/nodes}/regexp.js +2 -2
  54. data/src/{nodes → ruby/nodes}/rescue.js +2 -2
  55. data/src/ruby/nodes/return.js +94 -0
  56. data/src/{nodes → ruby/nodes}/statements.js +6 -9
  57. data/src/{nodes → ruby/nodes}/strings.js +27 -36
  58. data/src/{nodes → ruby/nodes}/super.js +2 -2
  59. data/src/{nodes → ruby/nodes}/undef.js +1 -1
  60. data/src/{parser.js → ruby/parser.js} +4 -3
  61. data/src/{parser.rb → ruby/parser.rb} +450 -501
  62. data/src/{printer.js → ruby/printer.js} +33 -1
  63. data/src/{toProc.js → ruby/toProc.js} +4 -8
  64. data/src/utils.js +10 -93
  65. data/src/utils/containsAssignment.js +11 -0
  66. data/src/utils/getTrailingComma.js +5 -0
  67. data/src/utils/hasAncestor.js +17 -0
  68. data/src/utils/literal.js +7 -0
  69. data/src/utils/makeCall.js +14 -0
  70. data/src/utils/noIndent.js +11 -0
  71. data/src/utils/skipAssignIndent.js +10 -0
  72. metadata +65 -41
  73. data/src/nodes/blocks.js +0 -85
  74. data/src/nodes/commands.js +0 -91
  75. data/src/nodes/hooks.js +0 -44
  76. data/src/nodes/return.js +0 -72
@@ -1,5 +1,5 @@
1
- const { concat, join } = require("../prettier");
2
- const { literal } = require("../utils");
1
+ const { concat, join } = require("../../prettier");
2
+ const { literal } = require("../../utils");
3
3
 
4
4
  const nodeDive = (node, steps) => {
5
5
  let current = node;
@@ -1,11 +1,16 @@
1
- const { concat, group, ifBreak, indent, join, line } = require("../prettier");
2
-
1
+ const {
2
+ concat,
3
+ group,
4
+ ifBreak,
5
+ indent,
6
+ join,
7
+ line
8
+ } = require("../../prettier");
3
9
  const {
4
10
  getTrailingComma,
5
- prefix,
6
11
  printEmptyCollection,
7
12
  skipAssignIndent
8
- } = require("../utils");
13
+ } = require("../../utils");
9
14
 
10
15
  // When attempting to convert a hash rocket into a hash label, you need to take
11
16
  // care because only certain patterns are allowed. Ruby source says that they
@@ -49,8 +54,20 @@ function printHashKeyLabel(path, print) {
49
54
  return print(path);
50
55
  case "symbol_literal":
51
56
  return concat([path.call(print, "body", 0), ":"]);
52
- case "dyna_symbol":
53
- return concat(print(path).parts.slice(1).concat(":"));
57
+ case "dyna_symbol": {
58
+ const { parts } = print(path);
59
+
60
+ // We're going to slice off the starting colon character so that we can
61
+ // move it to the end. If there are comments, then we're going to go
62
+ // further into the printed doc nodes.
63
+ if (parts[0] === ":") {
64
+ parts.splice(0, 1);
65
+ } else {
66
+ parts[1].parts.splice(0, 1);
67
+ }
68
+
69
+ return concat(parts.concat(":"));
70
+ }
54
71
  }
55
72
  }
56
73
 
@@ -66,20 +83,25 @@ function printHashKeyRocket(path, print) {
66
83
  }
67
84
 
68
85
  function printAssocNew(path, opts, print) {
86
+ const [keyNode, valueNode] = path.getValue().body;
69
87
  const { keyPrinter } = path.getParentNode();
70
88
 
71
89
  const parts = [path.call((keyPath) => keyPrinter(keyPath, print), "body", 0)];
72
90
  const valueDoc = path.call(print, "body", 1);
73
91
 
74
- if (skipAssignIndent(path.getValue().body[1])) {
75
- parts.push(" ", valueDoc);
76
- } else {
92
+ if (!skipAssignIndent(valueNode) || keyNode.comments) {
77
93
  parts.push(indent(concat([line, valueDoc])));
94
+ } else {
95
+ parts.push(" ", valueDoc);
78
96
  }
79
97
 
80
98
  return group(concat(parts));
81
99
  }
82
100
 
101
+ function printAssocSplat(path, opts, print) {
102
+ return concat(["**", path.call(print, "body", 0)]);
103
+ }
104
+
83
105
  function printHashContents(path, opts, print) {
84
106
  const node = path.getValue();
85
107
 
@@ -121,7 +143,7 @@ function printHash(path, opts, print) {
121
143
 
122
144
  module.exports = {
123
145
  assoc_new: printAssocNew,
124
- assoc_splat: prefix("**"),
146
+ assoc_splat: printAssocSplat,
125
147
  assoclist_from_args: printHashContents,
126
148
  bare_assoc_hash: printHashContents,
127
149
  hash: printHash
@@ -1,5 +1,5 @@
1
- const { concat, group, lineSuffix, join } = require("../prettier");
2
- const { literalLineNoBreak } = require("../utils");
1
+ const { concat, group, lineSuffix, join } = require("../../prettier");
2
+ const { literalLineNoBreak } = require("../../utils");
3
3
 
4
4
  function printHeredoc(path, opts, print) {
5
5
  const { body, ending } = path.getValue();
@@ -0,0 +1,34 @@
1
+ const { concat, group, indent, line } = require("../../prettier");
2
+
3
+ // The `BEGIN` and `END` keywords are used to hook into the Ruby process. Any
4
+ // `BEGIN` blocks are executed right when the process starts up, and the `END`
5
+ // blocks are executed right before exiting.
6
+ //
7
+ // BEGIN {
8
+ // # content goes here
9
+ // }
10
+ //
11
+ // END {
12
+ // # content goes here
13
+ // }
14
+ //
15
+ // Interesting side note, you don't use `do...end` blocks with these hooks. Both
16
+ // nodes contain one child which is a `stmts` node.
17
+ function printHook(name) {
18
+ return function printHookWithName(path, opts, print) {
19
+ return group(
20
+ concat([
21
+ name,
22
+ " ",
23
+ path.call(print, "body", 0),
24
+ indent(concat([line, path.call(print, "body", 1)])),
25
+ concat([line, "}"])
26
+ ])
27
+ );
28
+ };
29
+ }
30
+
31
+ module.exports = {
32
+ BEGIN: printHook("BEGIN"),
33
+ END: printHook("END")
34
+ };
File without changes
@@ -1,5 +1,5 @@
1
- const { concat, group, ifBreak, indent, line } = require("../prettier");
2
- const { hasAncestor } = require("../utils");
1
+ const { concat, group, ifBreak, indent, line } = require("../../prettier");
2
+ const { hasAncestor } = require("../../utils");
3
3
 
4
4
  // We can have our params coming in as the first child of the main lambda node,
5
5
  // or if we have them wrapped in parens then they'll be one level deeper. Even
@@ -6,11 +6,12 @@ const {
6
6
  hardline,
7
7
  ifBreak,
8
8
  indent,
9
+ join,
9
10
  softline
10
- } = require("../prettier");
11
+ } = require("../../prettier");
11
12
 
12
- const { containsAssignment } = require("../utils");
13
- const inlineEnsureParens = require("../utils/inlineEnsureParens");
13
+ const { containsAssignment } = require("../../utils");
14
+ const inlineEnsureParens = require("../../utils/inlineEnsureParens");
14
15
 
15
16
  function printLoop(keyword, modifier) {
16
17
  return function printLoopWithOptions(path, { rubyModifier }, print) {
@@ -78,15 +79,17 @@ function printLoop(keyword, modifier) {
78
79
  }
79
80
 
80
81
  function printFor(path, opts, print) {
81
- const [variable, range, stmts] = path.map(print, "body");
82
+ const [varDoc, rangeDoc, stmtsDoc] = path.map(print, "body");
83
+ const varsDoc =
84
+ path.getValue().body[0].type === "mlhs" ? join(", ", varDoc) : varDoc;
82
85
 
83
86
  return group(
84
87
  concat([
85
88
  "for ",
86
- variable,
89
+ varsDoc,
87
90
  " in ",
88
- range,
89
- indent(concat([hardline, stmts])),
91
+ rangeDoc,
92
+ indent(concat([hardline, stmtsDoc])),
90
93
  concat([hardline, "end"])
91
94
  ])
92
95
  );
@@ -1,4 +1,11 @@
1
- const { concat, group, indent, join, line, softline } = require("../prettier");
1
+ const {
2
+ concat,
3
+ group,
4
+ indent,
5
+ join,
6
+ line,
7
+ softline
8
+ } = require("../../prettier");
2
9
 
3
10
  function printMAssign(path, opts, print) {
4
11
  let right = path.call(print, "body", 1);
@@ -1,5 +1,4 @@
1
- const { concat, group, hardline, indent, line } = require("../prettier");
2
- const { first } = require("../utils");
1
+ const { concat, group, hardline, indent, line } = require("../../prettier");
3
2
 
4
3
  function printMethod(offset) {
5
4
  return function printMethodWithOffset(path, opts, print) {
@@ -48,15 +47,13 @@ function printMethod(offset) {
48
47
  }
49
48
 
50
49
  function printSingleLineMethod(path, opts, print) {
51
- let paramsNode = path.getValue().body[1];
50
+ let parensNode = path.getValue().body[1];
52
51
  let paramsDoc = "";
53
52
 
54
- if (paramsNode) {
55
- if (paramsNode.body[0].type === "params") {
56
- paramsNode = paramsNode.body[0];
57
- }
53
+ if (parensNode) {
54
+ const paramsNode = parensNode.body[0];
58
55
 
59
- if (paramsNode.type === "params" && paramsNode.body.some((type) => type)) {
56
+ if (paramsNode.body.some((type) => type)) {
60
57
  paramsDoc = path.call(print, "body", 1);
61
58
  }
62
59
  }
@@ -72,8 +69,12 @@ function printSingleLineMethod(path, opts, print) {
72
69
  );
73
70
  }
74
71
 
72
+ function printAccessControl(path, opts, print) {
73
+ return path.call(print, "body", 0);
74
+ }
75
+
75
76
  module.exports = {
76
- access_ctrl: first,
77
+ access_ctrl: printAccessControl,
77
78
  def: printMethod(0),
78
79
  defs: printMethod(2),
79
80
  defsl: printSingleLineMethod
@@ -1,5 +1,5 @@
1
- const { concat, group, indent, line, softline } = require("../prettier");
2
- const { noIndent } = require("../utils");
1
+ const { concat, group, indent, line, softline } = require("../../prettier");
2
+ const { noIndent } = require("../../utils");
3
3
 
4
4
  function printBinary(path, opts, print) {
5
5
  const [_leftNode, operator, rightNode] = path.getValue().body;
@@ -1,5 +1,12 @@
1
- const { concat, group, join, indent, line, softline } = require("../prettier");
2
- const { literal } = require("../utils");
1
+ const {
2
+ concat,
3
+ group,
4
+ join,
5
+ indent,
6
+ line,
7
+ softline
8
+ } = require("../../prettier");
9
+ const { literal } = require("../../utils");
3
10
 
4
11
  function printRestParam(symbol) {
5
12
  return function printRestParamWithSymbol(path, opts, print) {
@@ -22,18 +29,22 @@ function printParams(path, opts, print) {
22
29
  let parts = [];
23
30
 
24
31
  if (reqs) {
25
- parts = parts.concat(path.map(print, "body", 0));
32
+ path.each(
33
+ (reqPath) => {
34
+ // For some very strange reason, if you have a comment attached to a
35
+ // rest_param, it shows up here in the list of required params.
36
+ if (reqPath.getValue().type !== "rest_param") {
37
+ parts.push(print(reqPath));
38
+ }
39
+ },
40
+ "body",
41
+ 0
42
+ );
26
43
  }
27
44
 
28
45
  if (optls) {
29
46
  parts = parts.concat(
30
- optls.map((_, index) =>
31
- concat([
32
- path.call(print, "body", 1, index, 0),
33
- " = ",
34
- path.call(print, "body", 1, index, 1)
35
- ])
36
- )
47
+ path.map((optlPath) => join(" = ", optlPath.map(print)), "body", 1)
37
48
  );
38
49
  }
39
50
 
@@ -47,12 +58,16 @@ function printParams(path, opts, print) {
47
58
 
48
59
  if (kwargs) {
49
60
  parts = parts.concat(
50
- kwargs.map(([, value], index) => {
51
- if (!value) {
52
- return path.call(print, "body", 4, index, 0);
53
- }
54
- return group(join(" ", path.map(print, "body", 4, index)));
55
- })
61
+ path.map(
62
+ (kwargPath) => {
63
+ if (!kwargPath.getValue()[1]) {
64
+ return kwargPath.call(print, 0);
65
+ }
66
+ return group(join(" ", kwargPath.map(print)));
67
+ },
68
+ "body",
69
+ 4
70
+ )
56
71
  );
57
72
  }
58
73
 
@@ -1,4 +1,12 @@
1
- const { concat, group, hardline, indent, join, line } = require("../prettier");
1
+ const {
2
+ align,
3
+ concat,
4
+ group,
5
+ hardline,
6
+ indent,
7
+ join,
8
+ line
9
+ } = require("../../prettier");
2
10
 
3
11
  const patterns = ["aryptn", "binary", "fndptn", "hshptn", "rassign"];
4
12
 
@@ -67,7 +75,7 @@ function printHshPtn(path, opts, print) {
67
75
  const [constant, keyValuePairs, keyValueRest] = path.getValue().body;
68
76
  let args = [];
69
77
 
70
- if (keyValuePairs) {
78
+ if (keyValuePairs.length > 0) {
71
79
  const printPair = (pairPath) => {
72
80
  const parts = [pairPath.call(print, 0)];
73
81
 
@@ -109,10 +117,13 @@ function printHshPtn(path, opts, print) {
109
117
  function printIn(path, opts, print) {
110
118
  const parts = [
111
119
  "in ",
112
- path.call(
113
- (valuePath) => printPatternArg(valuePath, opts, print),
114
- "body",
115
- 0
120
+ align(
121
+ "in ".length,
122
+ path.call(
123
+ (valuePath) => printPatternArg(valuePath, opts, print),
124
+ "body",
125
+ 0
126
+ )
116
127
  ),
117
128
  indent(concat([hardline, path.call(print, "body", 1)]))
118
129
  ];
@@ -1,5 +1,5 @@
1
- const { concat } = require("../prettier");
2
- const { hasAncestor } = require("../utils");
1
+ const { concat } = require("../../prettier");
2
+ const { hasAncestor } = require("../../utils");
3
3
 
4
4
  function hasContent(node, pattern) {
5
5
  return node.body.some(
@@ -6,8 +6,8 @@ const {
6
6
  indent,
7
7
  join,
8
8
  line
9
- } = require("../prettier");
10
- const { literal } = require("../utils");
9
+ } = require("../../prettier");
10
+ const { literal } = require("../../utils");
11
11
 
12
12
  function printBegin(path, opts, print) {
13
13
  return concat([
@@ -0,0 +1,94 @@
1
+ const {
2
+ concat,
3
+ group,
4
+ ifBreak,
5
+ indent,
6
+ line,
7
+ join,
8
+ softline
9
+ } = require("../../prettier");
10
+ const { literal } = require("../../utils");
11
+
12
+ // You can't skip the parentheses if you have comments or certain operators with
13
+ // lower precedence than the return keyword.
14
+ const canSkipParens = (args) => {
15
+ const stmts = args.body[0].body[0];
16
+
17
+ // return(
18
+ // # a
19
+ // b
20
+ // )
21
+ if (stmts.comments) {
22
+ return false;
23
+ }
24
+
25
+ const stmt = stmts.body[0];
26
+
27
+ // return (a or b)
28
+ if (stmt.type === "binary" && ["and", "or"].includes(stmt.body[1])) {
29
+ return false;
30
+ }
31
+
32
+ // return (not a)
33
+ if (stmt.type === "unary" && stmt.oper === "not") {
34
+ return false;
35
+ }
36
+
37
+ return true;
38
+ };
39
+
40
+ const printReturn = (path, opts, print) => {
41
+ let args = path.getValue().body[0].body[0];
42
+ let steps = ["body", 0, "body", 0];
43
+
44
+ if (args.body.length === 1) {
45
+ // If the body of the return contains parens, then just skip directly to the
46
+ // content of the parens so that we can skip printing parens if we don't
47
+ // want them.
48
+ if (args.body[0] && args.body[0].type === "paren" && canSkipParens(args)) {
49
+ args = args.body[0].body[0];
50
+ steps = steps.concat("body", 0, "body", 0);
51
+ }
52
+
53
+ // If we're returning an array literal that isn't a special array, single
54
+ // element array, or an empty array, then we want to grab the arguments so
55
+ // that we can print them out as if they were normal return arguments.
56
+ if (
57
+ args.body[0] &&
58
+ args.body[0].type === "array" &&
59
+ args.body[0].body[0] &&
60
+ args.body[0].body[0].body.length > 1 &&
61
+ ["args", "args_add_star"].includes(args.body[0].body[0].type)
62
+ ) {
63
+ steps = steps.concat("body", 0, "body", 0);
64
+ }
65
+ }
66
+
67
+ // Now that we've established which actual node is the arguments to return,
68
+ // we grab it out of the path by diving down the steps that we've set up.
69
+ const parts = path.call.apply(path, [print].concat(steps));
70
+
71
+ // If we got the value straight out of the parens, then `parts` would only
72
+ // be a singular doc as opposed to an array.
73
+ const value = Array.isArray(parts) ? join(concat([",", line]), parts) : parts;
74
+
75
+ // We only get here if we have comments somewhere that would prevent us from
76
+ // skipping the parentheses.
77
+ if (args.body.length === 1 && args.body[0].type === "paren") {
78
+ return concat(["return", value]);
79
+ }
80
+
81
+ return group(
82
+ concat([
83
+ "return",
84
+ ifBreak(parts.length > 1 ? " [" : "(", " "),
85
+ indent(concat([softline, value])),
86
+ concat([softline, ifBreak(parts.length > 1 ? "]" : ")", "")])
87
+ ])
88
+ );
89
+ };
90
+
91
+ module.exports = {
92
+ return: printReturn,
93
+ return0: literal("return")
94
+ };