prettier 1.2.3 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +349 -358
  3. data/README.md +21 -93
  4. data/node_modules/prettier/index.js +54 -54
  5. data/package.json +1 -2
  6. data/rubocop.yml +26 -0
  7. data/src/haml/embed.js +87 -0
  8. data/src/haml/nodes/comment.js +27 -0
  9. data/src/haml/nodes/doctype.js +34 -0
  10. data/src/haml/nodes/filter.js +16 -0
  11. data/src/haml/nodes/hamlComment.js +21 -0
  12. data/src/haml/nodes/plain.js +6 -0
  13. data/src/haml/nodes/root.js +8 -0
  14. data/src/haml/nodes/script.js +33 -0
  15. data/src/haml/nodes/silentScript.js +59 -0
  16. data/src/haml/nodes/tag.js +193 -0
  17. data/src/haml/parser.js +22 -0
  18. data/src/haml/parser.rb +138 -0
  19. data/src/haml/printer.js +28 -0
  20. data/src/parser/getLang.js +32 -0
  21. data/src/parser/getNetcat.js +50 -0
  22. data/src/parser/netcat.js +15 -0
  23. data/src/parser/parseSync.js +33 -0
  24. data/src/parser/requestParse.js +74 -0
  25. data/src/parser/server.rb +61 -0
  26. data/src/plugin.js +26 -4
  27. data/src/prettier.js +1 -0
  28. data/src/rbs/parser.js +39 -0
  29. data/src/rbs/parser.rb +94 -0
  30. data/src/rbs/printer.js +605 -0
  31. data/src/ruby/embed.js +58 -8
  32. data/src/ruby/nodes/args.js +20 -6
  33. data/src/ruby/nodes/blocks.js +64 -59
  34. data/src/ruby/nodes/calls.js +12 -43
  35. data/src/ruby/nodes/class.js +17 -27
  36. data/src/ruby/nodes/commands.js +7 -2
  37. data/src/ruby/nodes/conditionals.js +1 -1
  38. data/src/ruby/nodes/hashes.js +28 -14
  39. data/src/ruby/nodes/hooks.js +9 -19
  40. data/src/ruby/nodes/loops.js +4 -10
  41. data/src/ruby/nodes/methods.js +8 -17
  42. data/src/ruby/nodes/params.js +22 -14
  43. data/src/ruby/nodes/patterns.js +9 -5
  44. data/src/ruby/nodes/rescue.js +32 -25
  45. data/src/ruby/nodes/return.js +0 -4
  46. data/src/ruby/nodes/statements.js +11 -13
  47. data/src/ruby/nodes/strings.js +27 -35
  48. data/src/ruby/parser.js +2 -49
  49. data/src/ruby/parser.rb +256 -232
  50. data/src/ruby/printer.js +0 -2
  51. data/src/ruby/toProc.js +4 -8
  52. data/src/utils.js +1 -0
  53. data/src/utils/isEmptyBodyStmt.js +7 -0
  54. data/src/utils/isEmptyStmts.js +9 -5
  55. data/src/utils/makeCall.js +3 -0
  56. data/src/utils/noIndent.js +1 -0
  57. data/src/utils/printEmptyCollection.js +9 -2
  58. metadata +26 -2
@@ -105,8 +105,13 @@ function printCommandCall(path, opts, print) {
105
105
  let breakDoc;
106
106
 
107
107
  if (hasTernaryArg(node.body[3])) {
108
- parts.push("(");
109
- breakDoc = parts.concat(indent(concat([softline, argDocs])), softline, ")");
108
+ breakDoc = parts.concat(
109
+ "(",
110
+ indent(concat([softline, argDocs])),
111
+ softline,
112
+ ")"
113
+ );
114
+ parts.push(" ");
110
115
  } else if (skipArgsAlign(path)) {
111
116
  parts.push(" ");
112
117
  breakDoc = parts.concat(argDocs);
@@ -219,7 +219,7 @@ const printConditional = (keyword) => (path, { rubyModifier }, print) => {
219
219
 
220
220
  // If the body of the conditional is empty, then we explicitly have to use the
221
221
  // block form.
222
- if (isEmptyStmts(statements) && !statements.body[0].comments) {
222
+ if (isEmptyStmts(statements)) {
223
223
  return concat([
224
224
  `${keyword} `,
225
225
  align(keyword.length + 1, path.call(print, "body", 0)),
@@ -6,6 +6,7 @@ const {
6
6
  join,
7
7
  line
8
8
  } = require("../../prettier");
9
+
9
10
  const {
10
11
  getTrailingComma,
11
12
  printEmptyCollection,
@@ -89,6 +90,13 @@ function printAssocNew(path, opts, print) {
89
90
  const parts = [path.call((keyPath) => keyPrinter(keyPath, print), "body", 0)];
90
91
  const valueDoc = path.call(print, "body", 1);
91
92
 
93
+ // If we're printing a child hash then we want it to break along with its
94
+ // parent hash, so we don't group the parts.
95
+ if (valueNode.type === "hash") {
96
+ parts.push(" ", valueDoc);
97
+ return concat(parts);
98
+ }
99
+
92
100
  if (!skipAssignIndent(valueNode) || keyNode.comments) {
93
101
  parts.push(indent(concat([line, valueDoc])));
94
102
  } else {
@@ -125,20 +133,26 @@ function printHash(path, opts, print) {
125
133
  return printEmptyCollection(path, opts, "{", "}");
126
134
  }
127
135
 
128
- return group(
129
- concat([
130
- "{",
131
- indent(
132
- concat([
133
- line,
134
- path.call(print, "body", 0),
135
- getTrailingComma(opts) ? ifBreak(",", "") : ""
136
- ])
137
- ),
138
- line,
139
- "}"
140
- ])
141
- );
136
+ let hashDoc = concat([
137
+ "{",
138
+ indent(
139
+ concat([
140
+ line,
141
+ path.call(print, "body", 0),
142
+ getTrailingComma(opts) ? ifBreak(",", "") : ""
143
+ ])
144
+ ),
145
+ line,
146
+ "}"
147
+ ]);
148
+
149
+ // If we're inside another hash, then we don't want to group our contents
150
+ // because we want this hash to break along with its parent hash.
151
+ if (path.getParentNode().type === "assoc_new") {
152
+ return hashDoc;
153
+ }
154
+
155
+ return group(hashDoc);
142
156
  }
143
157
 
144
158
  module.exports = {
@@ -1,5 +1,4 @@
1
1
  const { concat, group, indent, line } = require("../../prettier");
2
- const { isEmptyStmts } = require("../../utils");
3
2
 
4
3
  // The `BEGIN` and `END` keywords are used to hook into the Ruby process. Any
5
4
  // `BEGIN` blocks are executed right when the process starts up, and the `END`
@@ -17,24 +16,15 @@ const { isEmptyStmts } = require("../../utils");
17
16
  // nodes contain one child which is a `stmts` node.
18
17
  function printHook(name) {
19
18
  return function printHookWithName(path, opts, print) {
20
- const stmtsNode = path.getValue().body[1];
21
- const printedStmts = path.call(print, "body", 1);
22
-
23
- const parts = [
24
- name,
25
- " ",
26
- path.call(print, "body", 0),
27
- indent(concat([line, printedStmts])),
28
- concat([line, "}"])
29
- ];
30
-
31
- // If there are no statements but there are comments, then we want to skip
32
- // printing the newline so that we don't end up with multiple spaces.
33
- if (isEmptyStmts(stmtsNode) && stmtsNode.comments) {
34
- parts[1] = indent(printedStmts);
35
- }
36
-
37
- return group(concat(parts));
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
+ );
38
28
  };
39
29
  }
40
30
 
@@ -10,7 +10,7 @@ const {
10
10
  softline
11
11
  } = require("../../prettier");
12
12
 
13
- const { containsAssignment } = require("../../utils");
13
+ const { containsAssignment, isEmptyStmts } = require("../../utils");
14
14
  const inlineEnsureParens = require("../../utils/inlineEnsureParens");
15
15
 
16
16
  function printLoop(keyword, modifier) {
@@ -19,17 +19,11 @@ function printLoop(keyword, modifier) {
19
19
 
20
20
  // If the only statement inside this while loop is a void statement, then we
21
21
  // can shorten to just displaying the predicate and then a semicolon.
22
- if (
23
- stmts.body.length === 1 &&
24
- stmts.body[0].type === "void_stmt" &&
25
- !stmts.body[0].comments
26
- ) {
22
+ if (isEmptyStmts(stmts)) {
27
23
  return group(
28
24
  concat([
29
- keyword,
30
- " ",
31
- path.call(print, "body", 0),
32
- ifBreak(softline, "; "),
25
+ group(concat([keyword, " ", path.call(print, "body", 0)])),
26
+ hardline,
33
27
  "end"
34
28
  ])
35
29
  );
@@ -1,8 +1,9 @@
1
1
  const { concat, group, hardline, indent, line } = require("../../prettier");
2
+ const { isEmptyBodyStmt } = require("../../utils");
2
3
 
3
4
  function printMethod(offset) {
4
5
  return function printMethodWithOffset(path, opts, print) {
5
- const [_name, params, body] = path.getValue().body.slice(offset);
6
+ const [_name, params, bodystmt] = path.getValue().body.slice(offset);
6
7
  const declaration = ["def "];
7
8
 
8
9
  // In this case, we're printing a method that's defined as a singleton, so
@@ -24,16 +25,8 @@ function printMethod(offset) {
24
25
  parens ? ")" : ""
25
26
  );
26
27
 
27
- // If the body is empty, we can replace with a ;
28
- const stmts = body.body[0].body;
29
-
30
- if (
31
- !body.body.slice(1).some((node) => node) &&
32
- stmts.length === 1 &&
33
- stmts[0].type === "void_stmt" &&
34
- !stmts[0].comments
35
- ) {
36
- return group(concat(declaration.concat(["; end"])));
28
+ if (isEmptyBodyStmt(bodystmt)) {
29
+ return group(concat(declaration.concat("; end")));
37
30
  }
38
31
 
39
32
  return group(
@@ -47,15 +40,13 @@ function printMethod(offset) {
47
40
  }
48
41
 
49
42
  function printSingleLineMethod(path, opts, print) {
50
- let paramsNode = path.getValue().body[1];
43
+ let parensNode = path.getValue().body[1];
51
44
  let paramsDoc = "";
52
45
 
53
- if (paramsNode) {
54
- if (paramsNode.body[0].type === "params") {
55
- paramsNode = paramsNode.body[0];
56
- }
46
+ if (parensNode) {
47
+ const paramsNode = parensNode.body[0];
57
48
 
58
- if (paramsNode.type === "params" && paramsNode.body.some((type) => type)) {
49
+ if (paramsNode.body.some((type) => type)) {
59
50
  paramsDoc = path.call(print, "body", 1);
60
51
  }
61
52
  }
@@ -29,18 +29,22 @@ function printParams(path, opts, print) {
29
29
  let parts = [];
30
30
 
31
31
  if (reqs) {
32
- 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
+ );
33
43
  }
34
44
 
35
45
  if (optls) {
36
46
  parts = parts.concat(
37
- optls.map((_, index) =>
38
- concat([
39
- path.call(print, "body", 1, index, 0),
40
- " = ",
41
- path.call(print, "body", 1, index, 1)
42
- ])
43
- )
47
+ path.map((optlPath) => join(" = ", optlPath.map(print)), "body", 1)
44
48
  );
45
49
  }
46
50
 
@@ -54,12 +58,16 @@ function printParams(path, opts, print) {
54
58
 
55
59
  if (kwargs) {
56
60
  parts = parts.concat(
57
- kwargs.map(([, value], index) => {
58
- if (!value) {
59
- return path.call(print, "body", 4, index, 0);
60
- }
61
- return group(join(" ", path.map(print, "body", 4, index)));
62
- })
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
+ )
63
71
  );
64
72
  }
65
73
 
@@ -1,4 +1,5 @@
1
1
  const {
2
+ align,
2
3
  concat,
3
4
  group,
4
5
  hardline,
@@ -74,7 +75,7 @@ function printHshPtn(path, opts, print) {
74
75
  const [constant, keyValuePairs, keyValueRest] = path.getValue().body;
75
76
  let args = [];
76
77
 
77
- if (keyValuePairs) {
78
+ if (keyValuePairs.length > 0) {
78
79
  const printPair = (pairPath) => {
79
80
  const parts = [pairPath.call(print, 0)];
80
81
 
@@ -116,10 +117,13 @@ function printHshPtn(path, opts, print) {
116
117
  function printIn(path, opts, print) {
117
118
  const parts = [
118
119
  "in ",
119
- path.call(
120
- (valuePath) => printPatternArg(valuePath, opts, print),
121
- "body",
122
- 0
120
+ align(
121
+ "in ".length,
122
+ path.call(
123
+ (valuePath) => printPatternArg(valuePath, opts, print),
124
+ "body",
125
+ 0
126
+ )
123
127
  ),
124
128
  indent(concat([hardline, path.call(print, "body", 1)]))
125
129
  ];
@@ -26,28 +26,10 @@ function printEnsure(path, opts, print) {
26
26
  }
27
27
 
28
28
  function printRescue(path, opts, print) {
29
- const [exception, variable, _stmts, addition] = path.getValue().body;
30
29
  const parts = ["rescue"];
31
30
 
32
- if (exception || variable) {
33
- if (exception) {
34
- if (Array.isArray(exception)) {
35
- // In this case, it's actually only the one exception (it's an array
36
- // of length 1).
37
- parts.push(" ", path.call(print, "body", 0, 0));
38
- } else {
39
- // Here we have multiple exceptions from which we're rescuing, so we
40
- // need to align them and join them together.
41
- const joiner = concat([",", line]);
42
- const exceptions = group(join(joiner, path.call(print, "body", 0)));
43
-
44
- parts.push(" ", align("rescue ".length, exceptions));
45
- }
46
- }
47
-
48
- if (variable) {
49
- parts.push(" => ", path.call(print, "body", 1));
50
- }
31
+ if (path.getValue().body[0]) {
32
+ parts.push(align("rescue ".length, path.call(print, "body", 0)));
51
33
  } else {
52
34
  // If you don't specify an error to rescue in a `begin/rescue` block, then
53
35
  // implicitly you're rescuing from `StandardError`. In this case, we're
@@ -55,16 +37,40 @@ function printRescue(path, opts, print) {
55
37
  parts.push(" StandardError");
56
38
  }
57
39
 
58
- const rescueBody = path.call(print, "body", 2);
40
+ const bodystmt = path.call(print, "body", 1);
59
41
 
60
- if (rescueBody.parts.length > 0) {
61
- parts.push(indent(concat([hardline, rescueBody])));
42
+ if (bodystmt.parts.length > 0) {
43
+ parts.push(indent(concat([hardline, bodystmt])));
62
44
  }
63
45
 
64
46
  // This is the next clause on the `begin` statement, either another
65
47
  // `rescue`, and `ensure`, or an `else` clause.
66
- if (addition) {
67
- parts.push(concat([hardline, path.call(print, "body", 3)]));
48
+ if (path.getValue().body[2]) {
49
+ parts.push(concat([hardline, path.call(print, "body", 2)]));
50
+ }
51
+
52
+ return group(concat(parts));
53
+ }
54
+
55
+ // This is a container node that we're adding into the AST that isn't present in
56
+ // Ripper solely so that we have a nice place to attach inline comments.
57
+ function printRescueEx(path, opts, print) {
58
+ const [exception, variable] = path.getValue().body;
59
+ const parts = [];
60
+
61
+ if (exception) {
62
+ let exceptionDoc = path.call(print, "body", 0);
63
+
64
+ if (Array.isArray(exceptionDoc)) {
65
+ const joiner = concat([",", line]);
66
+ exceptionDoc = group(join(joiner, exceptionDoc));
67
+ }
68
+
69
+ parts.push(" ", exceptionDoc);
70
+ }
71
+
72
+ if (variable) {
73
+ parts.push(" => ", path.call(print, "body", 1));
68
74
  }
69
75
 
70
76
  return group(concat(parts));
@@ -89,6 +95,7 @@ module.exports = {
89
95
  ensure: printEnsure,
90
96
  redo: literal("redo"),
91
97
  rescue: printRescue,
98
+ rescue_ex: printRescueEx,
92
99
  rescue_mod: printRescueMod,
93
100
  retry: literal("retry")
94
101
  };
@@ -41,10 +41,6 @@ const printReturn = (path, opts, print) => {
41
41
  let args = path.getValue().body[0].body[0];
42
42
  let steps = ["body", 0, "body", 0];
43
43
 
44
- if (!args) {
45
- return "return";
46
- }
47
-
48
44
  if (args.body.length === 1) {
49
45
  // If the body of the return contains parens, then just skip directly to the
50
46
  // content of the parens so that we can skip printing parens if we don't
@@ -12,15 +12,13 @@ const {
12
12
  trim
13
13
  } = require("../../prettier");
14
14
 
15
+ const { isEmptyStmts } = require("../../utils");
16
+
15
17
  function printBodyStmt(path, opts, print) {
16
18
  const [stmts, rescue, elseClause, ensure] = path.getValue().body;
17
19
  const parts = [];
18
20
 
19
- if (
20
- stmts.body.length > 1 ||
21
- stmts.body[0].type != "void_stmt" ||
22
- stmts.body[0].comments
23
- ) {
21
+ if (!isEmptyStmts(stmts)) {
24
22
  parts.push(path.call(print, "body", 0));
25
23
  }
26
24
 
@@ -30,6 +28,7 @@ function printBodyStmt(path, opts, print) {
30
28
 
31
29
  if (elseClause) {
32
30
  // Before Ruby 2.6, this piece of bodystmt was an explicit "else" node
31
+ /* istanbul ignore next */
33
32
  const stmts =
34
33
  elseClause.type === "else"
35
34
  ? path.call(print, "body", 2, "body", 0)
@@ -69,11 +68,7 @@ function printParen(path, opts, print) {
69
68
  }
70
69
 
71
70
  return group(
72
- concat([
73
- "(",
74
- indent(concat([softline, contentDoc])),
75
- concat([softline, ")"])
76
- ])
71
+ concat(["(", indent(concat([softline, contentDoc])), softline, ")"])
77
72
  );
78
73
  }
79
74
 
@@ -82,6 +77,9 @@ module.exports = {
82
77
  const { body } = path.getValue();
83
78
  return concat([trim, "__END__", literalline, body]);
84
79
  },
80
+ "@comment"(path, opts, _print) {
81
+ return opts.printer.printComment(path);
82
+ },
85
83
  bodystmt: printBodyStmt,
86
84
  paren: printParen,
87
85
  program: (path, opts, print) =>
@@ -123,12 +121,12 @@ module.exports = {
123
121
  if (lineNo === null) {
124
122
  parts.push(printed);
125
123
  } else if (
126
- stmt.start - lineNo > 1 ||
124
+ stmt.sl - lineNo > 1 ||
127
125
  [stmt.type, stmts[index - 1].type].includes("access_ctrl")
128
126
  ) {
129
127
  parts.push(hardline, hardline, printed);
130
128
  } else if (
131
- stmt.start !== lineNo ||
129
+ stmt.sl !== lineNo ||
132
130
  path.getParentNode().type !== "string_embexpr"
133
131
  ) {
134
132
  parts.push(hardline, printed);
@@ -136,7 +134,7 @@ module.exports = {
136
134
  parts.push("; ", printed);
137
135
  }
138
136
 
139
- lineNo = stmt.end;
137
+ lineNo = stmt.el;
140
138
  });
141
139
 
142
140
  return concat(parts);