prettier 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  };