prettier 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -1
- data/CONTRIBUTING.md +3 -3
- data/README.md +4 -0
- data/package.json +3 -3
- data/src/embed.js +20 -5
- data/src/nodes.js +5 -2
- data/src/nodes/alias.js +29 -31
- data/src/nodes/aref.js +26 -26
- data/src/nodes/args.js +56 -28
- data/src/nodes/arrays.js +142 -104
- data/src/nodes/assign.js +30 -30
- data/src/nodes/blocks.js +8 -3
- data/src/nodes/calls.js +108 -53
- data/src/nodes/class.js +74 -0
- data/src/nodes/commands.js +36 -31
- data/src/nodes/conditionals.js +42 -28
- data/src/nodes/constants.js +39 -21
- data/src/nodes/flow.js +11 -1
- data/src/nodes/hashes.js +60 -87
- data/src/nodes/heredocs.js +34 -0
- data/src/nodes/hooks.js +16 -19
- data/src/nodes/ints.js +33 -20
- data/src/nodes/lambdas.js +15 -12
- data/src/nodes/loops.js +6 -2
- data/src/nodes/massign.js +87 -65
- data/src/nodes/methods.js +46 -73
- data/src/nodes/operators.js +66 -46
- data/src/nodes/params.js +12 -14
- data/src/nodes/patterns.js +108 -33
- data/src/nodes/regexp.js +22 -13
- data/src/nodes/rescue.js +72 -59
- data/src/nodes/statements.js +23 -1
- data/src/nodes/strings.js +89 -80
- data/src/nodes/super.js +35 -0
- data/src/nodes/undef.js +42 -0
- data/src/parser.js +71 -0
- data/src/parser.rb +2269 -625
- data/src/printer.js +88 -0
- data/src/ruby.js +4 -20
- data/src/toProc.js +2 -2
- data/src/utils.js +10 -86
- data/src/utils/literalLineNoBreak.js +7 -0
- metadata +9 -5
- data/src/nodes/scopes.js +0 -61
- data/src/parse.js +0 -37
- data/src/print.js +0 -23
@@ -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
|
+
};
|
data/src/nodes/hooks.js
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
const { concat, group, indent, line } = require("../prettier");
|
2
2
|
const { isEmptyStmts } = require("../utils");
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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 = {
|
data/src/nodes/ints.js
CHANGED
@@ -1,24 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
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
|
};
|
data/src/nodes/lambdas.js
CHANGED
@@ -6,36 +6,39 @@ const {
|
|
6
6
|
line,
|
7
7
|
softline
|
8
8
|
} = require("../prettier");
|
9
|
-
const { hasAncestor
|
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
|
-
|
16
|
-
const
|
17
|
-
let
|
15
|
+
function printLambdaParams(path, print) {
|
16
|
+
const paramsPath = [print, "body", 0];
|
17
|
+
let paramsNode = path.getValue().body[0];
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
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 (
|
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,
|
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
|
-
|
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
|
data/src/nodes/loops.js
CHANGED
@@ -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,
|
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 (
|
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,
|
data/src/nodes/massign.js
CHANGED
@@ -1,69 +1,91 @@
|
|
1
1
|
const { concat, group, indent, join, line, softline } = require("../prettier");
|
2
|
-
const { makeList } = require("../utils");
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
[
|
10
|
-
|
11
|
-
|
12
|
-
)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
};
|
data/src/nodes/methods.js
CHANGED
@@ -1,80 +1,53 @@
|
|
1
|
-
const {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
};
|