prettier 0.21.0 → 0.22.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.
@@ -0,0 +1,34 @@
1
+ const { concat, group, lineSuffix, join } = require("../prettier");
2
+ const { literalLineNoBreak } = require("../utils");
3
+
4
+ function printHeredoc(path, opts, print) {
5
+ const { beging, body, ending } = path.getValue();
6
+
7
+ const parts = body.map((part, index) => {
8
+ if (part.type !== "@tstring_content") {
9
+ // In this case, the part of the string is an embedded expression
10
+ return path.call(print, "body", index);
11
+ }
12
+
13
+ // In this case, the part of the string is just regular string content
14
+ return join(literalLineNoBreak, part.body.split("\n"));
15
+ });
16
+
17
+ // We use a literalline break because matching indentation is required
18
+ // for the heredoc contents and ending. If the line suffix contains a
19
+ // break-parent, all ancestral groups are broken, and heredocs automatically
20
+ // break lines in groups they appear in. We prefer them to appear in-line if
21
+ // possible, so we use a literalline without the break-parent.
22
+ return group(
23
+ concat([
24
+ beging,
25
+ lineSuffix(
26
+ group(concat([literalLineNoBreak].concat(parts).concat(ending)))
27
+ )
28
+ ])
29
+ );
30
+ }
31
+
32
+ module.exports = {
33
+ heredoc: printHeredoc
34
+ };
@@ -1,23 +1,22 @@
1
1
  const { concat, group, indent, line } = require("../prettier");
2
2
  const { isEmptyStmts } = require("../utils");
3
3
 
4
- /* The `BEGIN` and `END` keywords are used to hook into the Ruby process. Any
5
- * `BEGIN` blocks are executed right when the process starts up, and the `END`
6
- * blocks are executed right before exiting.
7
- *
8
- * BEGIN {
9
- * # content goes here
10
- * }
11
- *
12
- * END {
13
- * # content goes here
14
- * }
15
- *
16
- * Interesting side note, you don't use `do...end` blocks with these hooks. Both
17
- * nodes contain one child which is a `stmts` node.
18
- */
4
+ // The `BEGIN` and `END` keywords are used to hook into the Ruby process. Any
5
+ // `BEGIN` blocks are executed right when the process starts up, and the `END`
6
+ // blocks are executed right before exiting.
7
+ //
8
+ // BEGIN {
9
+ // # content goes here
10
+ // }
11
+ //
12
+ // END {
13
+ // # content goes here
14
+ // }
15
+ //
16
+ // Interesting side note, you don't use `do...end` blocks with these hooks. Both
17
+ // nodes contain one child which is a `stmts` node.
19
18
  function printHook(name) {
20
- function printHookWithName(path, opts, print) {
19
+ return function printHookWithName(path, opts, print) {
21
20
  const stmtsNode = path.getValue().body[0];
22
21
  const printedStmts = path.call(print, "body", 0);
23
22
 
@@ -34,9 +33,7 @@ function printHook(name) {
34
33
  }
35
34
 
36
35
  return group(concat(parts));
37
- }
38
-
39
- return printHookWithName;
36
+ };
40
37
  }
41
38
 
42
39
  module.exports = {
@@ -1,24 +1,37 @@
1
- module.exports = {
2
- "@int": (path, _opts, _print) => {
3
- const { body } = path.getValue();
4
-
5
- // If the number is octal and does not contain the optional "o" character
6
- // after the leading 0, add it in.
7
- if (/^0[0-9]/.test(body)) {
8
- return `0o${body.slice(1)}`;
9
- }
1
+ // An @int node is any literal integer in Ruby. They can come in a number of
2
+ // bases, and look like the following:
3
+ //
4
+ // Binary (2) - 0b0110
5
+ // Octal (8) - 0o34 or 034
6
+ // Decimal (10) - a normal number like 159
7
+ // Hexidecimal (16) - 0xac5
8
+ //
9
+ // If it's a decimal number, it can be optional separated by any number of
10
+ // arbitrarily places underscores. This can be useful for dollars and cents
11
+ // (34_99), dates (2020_11_30), and normal 3 digit separation (1_222_333).
12
+ function printInt(path, _opts, _print) {
13
+ const { body } = path.getValue();
10
14
 
11
- // If the number is a base 10 number, is sufficiently large, and is not
12
- // already formatted with underscores, then add them in in between the
13
- // numbers every three characters starting from the right.
14
- if (!body.startsWith("0") && body.length >= 5 && !body.includes("_")) {
15
- return ` ${body}`
16
- .slice((body.length + 2) % 3)
17
- .match(/.{3}/g)
18
- .join("_")
19
- .trim();
20
- }
15
+ // If the number is octal and does not contain the optional "o" character
16
+ // after the leading 0, add it in.
17
+ if (/^0[0-9]/.test(body)) {
18
+ return `0o${body.slice(1)}`;
19
+ }
21
20
 
22
- return body;
21
+ // If the number is a base 10 number, is sufficiently large, and is not
22
+ // already formatted with underscores, then add them in in between the
23
+ // numbers every three characters starting from the right.
24
+ if (!body.startsWith("0") && body.length >= 5 && !body.includes("_")) {
25
+ return ` ${body}`
26
+ .slice((body.length + 2) % 3)
27
+ .match(/.{3}/g)
28
+ .join("_")
29
+ .trim();
23
30
  }
31
+
32
+ return body;
33
+ }
34
+
35
+ module.exports = {
36
+ "@int": printInt
24
37
  };
@@ -6,36 +6,39 @@ const {
6
6
  line,
7
7
  softline
8
8
  } = require("../prettier");
9
- const { hasAncestor, nodeDive } = require("../utils");
9
+ const { hasAncestor } = require("../utils");
10
10
 
11
11
  // We can have our params coming in as the first child of the main lambda node,
12
12
  // or if we have them wrapped in parens then they'll be one level deeper. Even
13
13
  // though it's possible to omit the parens if you only have one argument, we're
14
14
  // going to keep them in no matter what for consistency.
15
- const printLambdaParams = (path, print) => {
16
- const steps = ["body", 0];
17
- let params = nodeDive(path.getValue(), steps);
15
+ function printLambdaParams(path, print) {
16
+ const paramsPath = [print, "body", 0];
17
+ let paramsNode = path.getValue().body[0];
18
18
 
19
- if (params.type !== "params") {
20
- steps.push("body", 0);
21
- params = nodeDive(path.getValue(), steps);
19
+ // In this case we had something like -> (foo) { bar } which would mean that
20
+ // we're looking at a paren node, so we'll descend one level deeper to get at
21
+ // the actual params node.
22
+ if (paramsNode.type !== "params") {
23
+ paramsPath.push("body", 0);
24
+ paramsNode = paramsNode.body[0];
22
25
  }
23
26
 
24
27
  // If we don't have any params at all, then we're just going to bail out and
25
28
  // print nothing. This is to avoid printing an empty set of parentheses.
26
- if (params.body.every((type) => !type)) {
29
+ if (paramsNode.body.every((type) => !type)) {
27
30
  return "";
28
31
  }
29
32
 
30
33
  return group(
31
34
  concat([
32
35
  "(",
33
- indent(concat([softline, path.call.apply(path, [print].concat(steps))])),
36
+ indent(concat([softline, path.call.apply(path, paramsPath)])),
34
37
  softline,
35
38
  ")"
36
39
  ])
37
40
  );
38
- };
41
+ }
39
42
 
40
43
  // Lambda nodes represent stabby lambda literals, which can come in a couple of
41
44
  // flavors. They can use either braces or do...end for their block, and their
@@ -64,7 +67,7 @@ const printLambdaParams = (path, print) => {
64
67
  // for the single-line form. However, if we have an ancestor that is a command
65
68
  // or command_call node, then we'll need to use braces either way because of
66
69
  // operator precendence.
67
- const printLambda = (path, opts, print) => {
70
+ function printLambda(path, opts, print) {
68
71
  const params = printLambdaParams(path, print);
69
72
  const inCommand = hasAncestor(path, ["command", "command_call"]);
70
73
 
@@ -82,7 +85,7 @@ const printLambda = (path, opts, print) => {
82
85
  concat(["->", params, " { ", path.call(print, "body", 1), " }"])
83
86
  )
84
87
  );
85
- };
88
+ }
86
89
 
87
90
  module.exports = {
88
91
  lambda: printLambda
@@ -12,11 +12,15 @@ const { containsAssignment } = require("../utils");
12
12
  const inlineEnsureParens = require("../utils/inlineEnsureParens");
13
13
 
14
14
  const printLoop = (keyword, modifier) => (path, { inlineLoops }, print) => {
15
- const [_predicate, statements] = path.getValue().body;
15
+ const [_predicate, stmts] = path.getValue().body;
16
16
 
17
17
  // If the only statement inside this while loop is a void statement, then we
18
18
  // can shorten to just displaying the predicate and then a semicolon.
19
- if (statements.body.length === 1 && statements.body[0].type === "void_stmt") {
19
+ if (
20
+ stmts.body.length === 1 &&
21
+ stmts.body[0].type === "void_stmt" &&
22
+ !stmts.body[0].comments
23
+ ) {
20
24
  return group(
21
25
  concat([
22
26
  keyword,
@@ -1,69 +1,91 @@
1
1
  const { concat, group, indent, join, line, softline } = require("../prettier");
2
- const { makeList } = require("../utils");
3
2
 
4
- module.exports = {
5
- massign: (path, opts, print) => {
6
- let right = path.call(print, "body", 1);
7
-
8
- if (
9
- ["mrhs_add_star", "mrhs_new_from_args"].includes(
10
- path.getValue().body[1].type
11
- )
12
- ) {
13
- right = group(join(concat([",", line]), right));
14
- }
15
-
16
- const parts = [join(concat([",", line]), path.call(print, "body", 0))];
17
- if (path.getValue().body[0].comma) {
18
- parts.push(",");
19
- }
20
-
21
- return group(
22
- concat([group(concat(parts)), " =", indent(concat([line, right]))])
23
- );
24
- },
25
- mlhs: makeList,
26
- mlhs_add_post: (path, opts, print) =>
27
- path.call(print, "body", 0).concat(path.call(print, "body", 1)),
28
- mlhs_add_star: (path, opts, print) =>
29
- path
30
- .call(print, "body", 0)
31
- .concat([
32
- path.getValue().body[1]
33
- ? concat(["*", path.call(print, "body", 1)])
34
- : "*"
35
- ]),
36
- mlhs_paren: (path, opts, print) => {
37
- if (["massign", "mlhs_paren"].includes(path.getParentNode().type)) {
38
- // If we're nested in brackets as part of the left hand side of an
39
- // assignment, i.e., (a, b, c) = 1, 2, 3
40
- // ignore the current node and just go straight to the content
41
- return path.call(print, "body", 0);
42
- }
43
-
44
- const parts = [
45
- softline,
46
- join(concat([",", line]), path.call(print, "body", 0))
47
- ];
48
-
49
- if (path.getValue().body[0].comma) {
50
- parts.push(",");
51
- }
52
-
53
- return group(concat(["(", indent(concat(parts)), concat([softline, ")"])]));
54
- },
55
- mrhs: makeList,
56
- mrhs_add_star: (path, opts, print) =>
57
- path
58
- .call(print, "body", 0)
59
- .concat([concat(["*", path.call(print, "body", 1)])]),
60
- mrhs_new_from_args: (path, opts, print) => {
61
- const parts = path.call(print, "body", 0);
62
-
63
- if (path.getValue().body.length > 1) {
64
- parts.push(path.call(print, "body", 1));
65
- }
66
-
67
- return parts;
3
+ function printMAssign(path, opts, print) {
4
+ let right = path.call(print, "body", 1);
5
+
6
+ if (
7
+ ["mrhs_add_star", "mrhs_new_from_args"].includes(
8
+ path.getValue().body[1].type
9
+ )
10
+ ) {
11
+ right = group(join(concat([",", line]), right));
12
+ }
13
+
14
+ const parts = [join(concat([",", line]), path.call(print, "body", 0))];
15
+ if (path.getValue().body[0].comma) {
16
+ parts.push(",");
17
+ }
18
+
19
+ return group(
20
+ concat([group(concat(parts)), " =", indent(concat([line, right]))])
21
+ );
22
+ }
23
+
24
+ function printMLHS(path, opts, print) {
25
+ return path.map(print, "body");
26
+ }
27
+
28
+ function printMLHSAddPost(path, opts, print) {
29
+ return path.call(print, "body", 0).concat(path.call(print, "body", 1));
30
+ }
31
+
32
+ function printMLHSAddStar(path, opts, print) {
33
+ const rightParts = ["*"];
34
+
35
+ if (path.getValue().body[1]) {
36
+ rightParts.push(path.call(print, "body", 1));
37
+ }
38
+
39
+ return path.call(print, "body", 0).concat(concat(rightParts));
40
+ }
41
+
42
+ function printMLHSParen(path, opts, print) {
43
+ if (["massign", "mlhs_paren"].includes(path.getParentNode().type)) {
44
+ // If we're nested in brackets as part of the left hand side of an
45
+ // assignment, i.e., (a, b, c) = 1, 2, 3
46
+ // ignore the current node and just go straight to the content
47
+ return path.call(print, "body", 0);
68
48
  }
49
+
50
+ const parts = [
51
+ softline,
52
+ join(concat([",", line]), path.call(print, "body", 0))
53
+ ];
54
+
55
+ if (path.getValue().body[0].comma) {
56
+ parts.push(",");
57
+ }
58
+
59
+ return group(concat(["(", indent(concat(parts)), concat([softline, ")"])]));
60
+ }
61
+
62
+ function printMRHS(path, opts, print) {
63
+ return path.map(print, "body");
64
+ }
65
+
66
+ function printMRHSAddStar(path, opts, print) {
67
+ const [leftDoc, rightDoc] = path.map(print, "body");
68
+
69
+ return leftDoc.concat([concat(["*", rightDoc])]);
70
+ }
71
+
72
+ function printMRHSNewFromArgs(path, opts, print) {
73
+ const parts = path.call(print, "body", 0);
74
+
75
+ if (path.getValue().body[1]) {
76
+ parts.push(path.call(print, "body", 1));
77
+ }
78
+
79
+ return parts;
80
+ }
81
+
82
+ module.exports = {
83
+ massign: printMAssign,
84
+ mlhs: printMLHS,
85
+ mlhs_add_post: printMLHSAddPost,
86
+ mlhs_add_star: printMLHSAddStar,
87
+ mlhs_paren: printMLHSParen,
88
+ mrhs: printMRHS,
89
+ mrhs_add_star: printMRHSAddStar,
90
+ mrhs_new_from_args: printMRHSNewFromArgs
69
91
  };
@@ -1,80 +1,53 @@
1
- const {
2
- align,
3
- concat,
4
- group,
5
- hardline,
6
- indent,
7
- join,
8
- line
9
- } = require("../prettier");
10
- const { first, literal } = require("../utils");
11
-
12
- const printMethod = (offset) => (path, opts, print) => {
13
- const [_name, params, body] = path.getValue().body.slice(offset);
14
- const declaration = ["def "];
15
-
16
- // In this case, we're printing a method that's defined as a singleton, so we
17
- // need to include the target and the operator
18
- if (offset > 0) {
19
- declaration.push(path.call(print, "body", 0), path.call(print, "body", 1));
20
- }
21
-
22
- // In case there are no parens but there are arguments
23
- const parens =
24
- params.type === "params" && params.body.some((paramType) => paramType);
25
-
26
- declaration.push(
27
- path.call(print, "body", offset),
28
- parens ? "(" : "",
29
- path.call(print, "body", offset + 1),
30
- parens ? ")" : ""
31
- );
1
+ const { concat, group, hardline, indent } = require("../prettier");
2
+ const { first } = require("../utils");
3
+
4
+ function printMethod(offset) {
5
+ return function printMethodWithOffset(path, opts, print) {
6
+ const [_name, params, body] = path.getValue().body.slice(offset);
7
+ const declaration = ["def "];
8
+
9
+ // In this case, we're printing a method that's defined as a singleton, so
10
+ // we need to include the target and the operator
11
+ if (offset > 0) {
12
+ declaration.push(
13
+ path.call(print, "body", 0),
14
+ path.call(print, "body", 1)
15
+ );
16
+ }
32
17
 
33
- // If the body is empty, we can replace with a ;
34
- const stmts = body.body[0].body;
35
- if (stmts.length === 1 && stmts[0].type === "void_stmt") {
36
- return group(concat(declaration.concat(["; end"])));
37
- }
18
+ // In case there are no parens but there are arguments
19
+ const parens =
20
+ params.type === "params" && params.body.some((paramType) => paramType);
21
+
22
+ declaration.push(
23
+ path.call(print, "body", offset),
24
+ parens ? "(" : "",
25
+ path.call(print, "body", offset + 1),
26
+ parens ? ")" : ""
27
+ );
28
+
29
+ // If the body is empty, we can replace with a ;
30
+ const stmts = body.body[0].body;
31
+ if (
32
+ stmts.length === 1 &&
33
+ stmts[0].type === "void_stmt" &&
34
+ !stmts[0].comments
35
+ ) {
36
+ return group(concat(declaration.concat(["; end"])));
37
+ }
38
38
 
39
- return group(
40
- concat([
41
- group(concat(declaration)),
42
- indent(concat([hardline, path.call(print, "body", offset + 2)])),
43
- group(concat([hardline, "end"]))
44
- ])
45
- );
46
- };
39
+ return group(
40
+ concat([
41
+ group(concat(declaration)),
42
+ indent(concat([hardline, path.call(print, "body", offset + 2)])),
43
+ group(concat([hardline, "end"]))
44
+ ])
45
+ );
46
+ };
47
+ }
47
48
 
48
49
  module.exports = {
49
50
  access_ctrl: first,
50
51
  def: printMethod(0),
51
- defs: printMethod(2),
52
- methref: (path, opts, print) => join(".:", path.map(print, "body")),
53
- super: (path, opts, print) => {
54
- const args = path.getValue().body[0];
55
-
56
- if (args.type === "arg_paren") {
57
- // In case there are explicitly no arguments but they are using parens,
58
- // we assume they are attempting to override the initializer and pass no
59
- // arguments up.
60
- if (args.body[0] === null) {
61
- return "super()";
62
- }
63
-
64
- return concat(["super", path.call(print, "body", 0)]);
65
- }
66
-
67
- return concat(["super ", join(", ", path.call(print, "body", 0))]);
68
- },
69
- undef: (path, opts, print) =>
70
- group(
71
- concat([
72
- "undef ",
73
- align(
74
- "undef ".length,
75
- join(concat([",", line]), path.map(print, "body", 0))
76
- )
77
- ])
78
- ),
79
- zsuper: literal("super")
52
+ defs: printMethod(2)
80
53
  };