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
data/src/printer.js
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
const { concat, trim } = require("./prettier");
|
2
|
+
|
3
|
+
const embed = require("./embed");
|
4
|
+
const nodes = require("./nodes");
|
5
|
+
|
6
|
+
// This is the generic node print function, used to convert any node in the AST
|
7
|
+
// into its equivalent Doc representation.
|
8
|
+
function printNode(path, opts, print) {
|
9
|
+
const { type, body } = path.getValue();
|
10
|
+
|
11
|
+
if (type in nodes) {
|
12
|
+
return nodes[type](path, opts, print);
|
13
|
+
}
|
14
|
+
|
15
|
+
if (type[0] === "@") {
|
16
|
+
return body;
|
17
|
+
}
|
18
|
+
|
19
|
+
const ast = JSON.stringify(body, null, 2);
|
20
|
+
throw new Error(`Unsupported node encountered: ${type}\n${ast}`);
|
21
|
+
}
|
22
|
+
|
23
|
+
const noComments = [
|
24
|
+
"args",
|
25
|
+
"args_add_block",
|
26
|
+
"args_add_star",
|
27
|
+
"mlhs",
|
28
|
+
"mlhs_add_post",
|
29
|
+
"mlhs_add_star"
|
30
|
+
];
|
31
|
+
|
32
|
+
// Certain nodes are used more for organizational purposed than for actually
|
33
|
+
// displaying content, so we tell prettier that we don't want comments attached
|
34
|
+
// to them.
|
35
|
+
function canAttachComment(node) {
|
36
|
+
return !noComments.includes(node.type);
|
37
|
+
}
|
38
|
+
|
39
|
+
// This function tells prettier how to recurse down our AST so that it can find
|
40
|
+
// where it needs to attach the comments.
|
41
|
+
function getCommentChildNodes(node) {
|
42
|
+
switch (node.type) {
|
43
|
+
case "rescue":
|
44
|
+
return node.body[0].concat(node.body.slice(1));
|
45
|
+
case "aryptn":
|
46
|
+
return [node.body[0]]
|
47
|
+
.concat(node.body[1])
|
48
|
+
.concat(node.body[2])
|
49
|
+
.concat(node.body[3]);
|
50
|
+
case "hshptn": {
|
51
|
+
const pairs = node.body[1];
|
52
|
+
const values = pairs.reduce((left, right) => left.concat(right), []);
|
53
|
+
|
54
|
+
return [node.body[0]].concat(values).concat(node.body[2]);
|
55
|
+
}
|
56
|
+
default:
|
57
|
+
return node.body;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
// This is the generic print function for any comment in the AST. It handles
|
62
|
+
// both regular comments that begin with a # and embdoc comments, which are
|
63
|
+
// surrounded by =begin..=end.
|
64
|
+
function printComment(path, _opts) {
|
65
|
+
const comment = path.getValue();
|
66
|
+
|
67
|
+
if (comment.type === "@comment") {
|
68
|
+
return `#${comment.value}`;
|
69
|
+
}
|
70
|
+
|
71
|
+
return concat([trim, comment.value]);
|
72
|
+
}
|
73
|
+
|
74
|
+
// To be honest I'm not 100% sure this function is actually necessary, but it
|
75
|
+
// *feels* like a block comment equivalent in JavaScript so I'm going to leave
|
76
|
+
// it in place for now.
|
77
|
+
function isBlockComment(comment) {
|
78
|
+
return comment.type === "@embdoc";
|
79
|
+
}
|
80
|
+
|
81
|
+
module.exports = {
|
82
|
+
embed,
|
83
|
+
print: printNode,
|
84
|
+
canAttachComment,
|
85
|
+
getCommentChildNodes,
|
86
|
+
printComment,
|
87
|
+
isBlockComment
|
88
|
+
};
|
data/src/ruby.js
CHANGED
@@ -1,12 +1,5 @@
|
|
1
|
-
const
|
2
|
-
const
|
3
|
-
const print = require("./print");
|
4
|
-
|
5
|
-
const pragmaPattern = /#\s*@(prettier|format)/;
|
6
|
-
const hasPragma = (text) => pragmaPattern.test(text);
|
7
|
-
|
8
|
-
const locStart = (node) => node.char_start;
|
9
|
-
const locEnd = (node) => node.char_end;
|
1
|
+
const printer = require("./printer");
|
2
|
+
const parser = require("./parser");
|
10
3
|
|
11
4
|
/*
|
12
5
|
* metadata mostly pulled from linguist and rubocop:
|
@@ -77,19 +70,10 @@ module.exports = {
|
|
77
70
|
}
|
78
71
|
],
|
79
72
|
parsers: {
|
80
|
-
ruby:
|
81
|
-
parse,
|
82
|
-
astFormat: "ruby",
|
83
|
-
hasPragma,
|
84
|
-
locStart,
|
85
|
-
locEnd
|
86
|
-
}
|
73
|
+
ruby: parser
|
87
74
|
},
|
88
75
|
printers: {
|
89
|
-
ruby:
|
90
|
-
embed,
|
91
|
-
print
|
92
|
-
}
|
76
|
+
ruby: printer
|
93
77
|
},
|
94
78
|
options: {
|
95
79
|
addTrailingCommas: {
|
data/src/toProc.js
CHANGED
@@ -57,9 +57,9 @@ const toProc = (path, opts, node) => {
|
|
57
57
|
return null;
|
58
58
|
}
|
59
59
|
|
60
|
-
// Ensure that statement is a call
|
60
|
+
// Ensure that statement is a call and that it has no comments attached
|
61
61
|
const [statement] = statements.body;
|
62
|
-
if (statement.type !== "call") {
|
62
|
+
if (statement.type !== "call" || statement.comments) {
|
63
63
|
return null;
|
64
64
|
}
|
65
65
|
|
data/src/utils.js
CHANGED
@@ -1,19 +1,15 @@
|
|
1
|
-
const {
|
2
|
-
breakParent,
|
3
|
-
concat,
|
4
|
-
hardline,
|
5
|
-
lineSuffix,
|
6
|
-
literalline
|
7
|
-
} = require("./prettier");
|
1
|
+
const { concat } = require("./prettier");
|
8
2
|
const isEmptyStmts = require("./utils/isEmptyStmts");
|
3
|
+
const literalLineNoBreak = require("./utils/literalLineNoBreak");
|
9
4
|
|
10
5
|
const concatBody = (path, opts, print) => concat(path.map(print, "body"));
|
11
6
|
|
12
7
|
// If the node is a type of assignment or if the node is a paren and nested
|
13
8
|
// inside that paren is a node that is a type of assignment.
|
14
9
|
const containsAssignment = (node) =>
|
15
|
-
|
16
|
-
(
|
10
|
+
node &&
|
11
|
+
(["assign", "massign", "opassign"].includes(node.type) ||
|
12
|
+
(Array.isArray(node.body) && node.body.some(containsAssignment)));
|
17
13
|
|
18
14
|
const docLength = (doc) => {
|
19
15
|
if (doc.length) {
|
@@ -53,34 +49,6 @@ const hasAncestor = (path, types) => {
|
|
53
49
|
|
54
50
|
const literal = (value) => () => value;
|
55
51
|
|
56
|
-
const makeArgs = (path, opts, print, argsIndex) => {
|
57
|
-
let argNodes = path.getValue().body[argsIndex];
|
58
|
-
const argPattern = [print, "body", argsIndex, "body"];
|
59
|
-
|
60
|
-
if (argNodes.type === "args_add_block") {
|
61
|
-
[argNodes] = argNodes.body;
|
62
|
-
argPattern.push(0, "body");
|
63
|
-
}
|
64
|
-
|
65
|
-
const args = path.call(print, "body", argsIndex);
|
66
|
-
const heredocs = [];
|
67
|
-
|
68
|
-
argNodes.body.forEach((argNode, index) => {
|
69
|
-
if (argNode.type === "heredoc") {
|
70
|
-
const content = path.map.apply(
|
71
|
-
path,
|
72
|
-
argPattern.slice().concat([index, "body"])
|
73
|
-
);
|
74
|
-
heredocs.push(
|
75
|
-
concat([literalline].concat(content).concat([argNode.ending]))
|
76
|
-
);
|
77
|
-
args[index] = argNode.beging;
|
78
|
-
}
|
79
|
-
});
|
80
|
-
|
81
|
-
return { args, heredocs };
|
82
|
-
};
|
83
|
-
|
84
52
|
const makeCall = (path, opts, print) => {
|
85
53
|
const operation = path.getValue().body[1];
|
86
54
|
|
@@ -91,53 +59,13 @@ const makeCall = (path, opts, print) => {
|
|
91
59
|
return operation === "::" ? "." : path.call(print, "body", 1);
|
92
60
|
};
|
93
61
|
|
94
|
-
const makeList = (path, opts, print) => path.map(print, "body");
|
95
|
-
|
96
|
-
const nodeDive = (node, steps) => {
|
97
|
-
let current = node;
|
98
|
-
|
99
|
-
steps.forEach((step) => {
|
100
|
-
current = current[step];
|
101
|
-
});
|
102
|
-
|
103
|
-
return current;
|
104
|
-
};
|
105
|
-
|
106
62
|
const prefix = (value) => (path, opts, print) =>
|
107
63
|
concat([value, path.call(print, "body", 0)]);
|
108
64
|
|
109
|
-
const
|
110
|
-
let node = printed;
|
111
|
-
|
112
|
-
comments.forEach((comment) => {
|
113
|
-
if (comment.start < start) {
|
114
|
-
node = concat([
|
115
|
-
comment.break ? breakParent : "",
|
116
|
-
comment.body,
|
117
|
-
hardline,
|
118
|
-
node
|
119
|
-
]);
|
120
|
-
} else {
|
121
|
-
node = concat([
|
122
|
-
node,
|
123
|
-
comment.break ? breakParent : "",
|
124
|
-
lineSuffix(` ${comment.body}`)
|
125
|
-
]);
|
126
|
-
}
|
127
|
-
});
|
128
|
-
|
129
|
-
return node;
|
130
|
-
};
|
131
|
-
|
65
|
+
const skippable = ["array", "hash", "heredoc", "lambda", "regexp_literal"];
|
132
66
|
const skipAssignIndent = (node) =>
|
133
|
-
|
134
|
-
|
135
|
-
) ||
|
136
|
-
(node.type === "call" && skipAssignIndent(node.body[0])) ||
|
137
|
-
(node.type === "string_literal" && node.body[0].type === "heredoc");
|
138
|
-
|
139
|
-
const surround = (left, right) => (path, opts, print) =>
|
140
|
-
concat([left, path.call(print, "body", 0), right]);
|
67
|
+
skippable.includes(node.type) ||
|
68
|
+
(node.type === "call" && skipAssignIndent(node.body[0]));
|
141
69
|
|
142
70
|
module.exports = {
|
143
71
|
concatBody,
|
@@ -148,12 +76,8 @@ module.exports = {
|
|
148
76
|
hasAncestor,
|
149
77
|
isEmptyStmts,
|
150
78
|
literal,
|
151
|
-
|
79
|
+
literalLineNoBreak,
|
152
80
|
makeCall,
|
153
|
-
makeList,
|
154
|
-
nodeDive,
|
155
81
|
prefix,
|
156
|
-
|
157
|
-
skipAssignIndent,
|
158
|
-
surround
|
82
|
+
skipAssignIndent
|
159
83
|
};
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prettier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Deisz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
11
|
+
date: 2020-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -82,11 +82,13 @@ files:
|
|
82
82
|
- src/nodes/blocks.js
|
83
83
|
- src/nodes/calls.js
|
84
84
|
- src/nodes/case.js
|
85
|
+
- src/nodes/class.js
|
85
86
|
- src/nodes/commands.js
|
86
87
|
- src/nodes/conditionals.js
|
87
88
|
- src/nodes/constants.js
|
88
89
|
- src/nodes/flow.js
|
89
90
|
- src/nodes/hashes.js
|
91
|
+
- src/nodes/heredocs.js
|
90
92
|
- src/nodes/hooks.js
|
91
93
|
- src/nodes/ints.js
|
92
94
|
- src/nodes/lambdas.js
|
@@ -99,18 +101,20 @@ files:
|
|
99
101
|
- src/nodes/regexp.js
|
100
102
|
- src/nodes/rescue.js
|
101
103
|
- src/nodes/return.js
|
102
|
-
- src/nodes/scopes.js
|
103
104
|
- src/nodes/statements.js
|
104
105
|
- src/nodes/strings.js
|
105
|
-
- src/
|
106
|
+
- src/nodes/super.js
|
107
|
+
- src/nodes/undef.js
|
108
|
+
- src/parser.js
|
106
109
|
- src/parser.rb
|
107
110
|
- src/prettier.js
|
108
|
-
- src/
|
111
|
+
- src/printer.js
|
109
112
|
- src/ruby.js
|
110
113
|
- src/toProc.js
|
111
114
|
- src/utils.js
|
112
115
|
- src/utils/inlineEnsureParens.js
|
113
116
|
- src/utils/isEmptyStmts.js
|
117
|
+
- src/utils/literalLineNoBreak.js
|
114
118
|
homepage: https://github.com/prettier/plugin-ruby#readme
|
115
119
|
licenses:
|
116
120
|
- MIT
|
data/src/nodes/scopes.js
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
const {
|
2
|
-
concat,
|
3
|
-
group,
|
4
|
-
hardline,
|
5
|
-
ifBreak,
|
6
|
-
indent,
|
7
|
-
line
|
8
|
-
} = require("../prettier");
|
9
|
-
|
10
|
-
module.exports = {
|
11
|
-
class: (path, opts, print) => {
|
12
|
-
const [_constant, superclass, statements] = path.getValue().body;
|
13
|
-
|
14
|
-
const parts = ["class ", path.call(print, "body", 0)];
|
15
|
-
if (superclass) {
|
16
|
-
parts.push(" < ", path.call(print, "body", 1));
|
17
|
-
}
|
18
|
-
|
19
|
-
// If the body is empty, we can replace with a ;
|
20
|
-
const stmts = statements.body[0].body;
|
21
|
-
if (stmts.length === 1 && stmts[0].type === "void_stmt") {
|
22
|
-
return group(concat([concat(parts), ifBreak(line, "; "), "end"]));
|
23
|
-
}
|
24
|
-
|
25
|
-
return group(
|
26
|
-
concat([
|
27
|
-
concat(parts),
|
28
|
-
indent(concat([hardline, path.call(print, "body", 2)])),
|
29
|
-
concat([hardline, "end"])
|
30
|
-
])
|
31
|
-
);
|
32
|
-
},
|
33
|
-
class_name_error: (_path, _opts, _print) => {
|
34
|
-
throw new Error("class/module name must be CONSTANT");
|
35
|
-
},
|
36
|
-
module: (path, opts, print) => {
|
37
|
-
const declaration = group(concat(["module ", path.call(print, "body", 0)]));
|
38
|
-
|
39
|
-
// If the body is empty, we can replace with a ;
|
40
|
-
const stmts = path.getValue().body[1].body[0].body;
|
41
|
-
if (stmts.length === 1 && stmts[0].type === "void_stmt") {
|
42
|
-
return group(concat([declaration, ifBreak(line, "; "), "end"]));
|
43
|
-
}
|
44
|
-
|
45
|
-
return group(
|
46
|
-
concat([
|
47
|
-
declaration,
|
48
|
-
indent(concat([hardline, path.call(print, "body", 1)])),
|
49
|
-
concat([hardline, "end"])
|
50
|
-
])
|
51
|
-
);
|
52
|
-
},
|
53
|
-
sclass: (path, opts, print) =>
|
54
|
-
group(
|
55
|
-
concat([
|
56
|
-
concat(["class << ", path.call(print, "body", 0)]),
|
57
|
-
indent(concat([hardline, path.call(print, "body", 1)])),
|
58
|
-
concat([hardline, "end"])
|
59
|
-
])
|
60
|
-
)
|
61
|
-
};
|
data/src/parse.js
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
const { spawnSync } = require("child_process");
|
2
|
-
const path = require("path");
|
3
|
-
|
4
|
-
// In order to properly parse ruby code, we need to tell the ruby process to
|
5
|
-
// parse using UTF-8. Unfortunately, the way that you accomplish this looks
|
6
|
-
// differently depending on your platform. This object below represents all of
|
7
|
-
// the possible values of process.platform per:
|
8
|
-
// https://nodejs.org/api/process.html#process_process_platform
|
9
|
-
const LANG = {
|
10
|
-
aix: "C.UTF-8",
|
11
|
-
darwin: "en_US.UTF-8",
|
12
|
-
freebsd: "C.UTF-8",
|
13
|
-
linux: "C.UTF-8",
|
14
|
-
openbsd: "C.UTF-8",
|
15
|
-
sunos: "C.UTF-8",
|
16
|
-
win32: ".UTF-8"
|
17
|
-
}[process.platform];
|
18
|
-
|
19
|
-
module.exports = (text, _parsers, _opts) => {
|
20
|
-
const child = spawnSync(
|
21
|
-
"ruby",
|
22
|
-
["--disable-gems", path.join(__dirname, "./parser.rb")],
|
23
|
-
{
|
24
|
-
env: Object.assign({}, process.env, { LANG }),
|
25
|
-
input: text,
|
26
|
-
maxBuffer: 10 * 1024 * 1024 // 10MB
|
27
|
-
}
|
28
|
-
);
|
29
|
-
|
30
|
-
const error = child.stderr.toString();
|
31
|
-
if (error) {
|
32
|
-
throw new Error(error);
|
33
|
-
}
|
34
|
-
|
35
|
-
const response = child.stdout.toString();
|
36
|
-
return JSON.parse(response);
|
37
|
-
};
|
data/src/print.js
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
const { printComments } = require("./utils");
|
2
|
-
const nodes = require("./nodes");
|
3
|
-
|
4
|
-
module.exports = (path, opts, print) => {
|
5
|
-
const { type, body, comments, start } = path.getValue();
|
6
|
-
|
7
|
-
if (type in nodes) {
|
8
|
-
const printed = nodes[type](path, opts, print);
|
9
|
-
|
10
|
-
if (comments) {
|
11
|
-
return printComments(printed, start, comments);
|
12
|
-
}
|
13
|
-
return printed;
|
14
|
-
}
|
15
|
-
|
16
|
-
if (type[0] === "@") {
|
17
|
-
return body;
|
18
|
-
}
|
19
|
-
|
20
|
-
throw new Error(
|
21
|
-
`Unsupported node encountered: ${type}\n${JSON.stringify(body, null, 2)}`
|
22
|
-
);
|
23
|
-
};
|