prettier 1.0.0 → 1.2.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +59 -1
- data/README.md +5 -0
- data/lib/prettier.rb +2 -2
- data/node_modules/prettier/index.js +54 -54
- data/package.json +3 -1
- data/src/nodes/arrays.js +2 -21
- data/src/nodes/assign.js +5 -1
- data/src/nodes/calls.js +46 -7
- data/src/nodes/case.js +53 -49
- data/src/nodes/hashes.js +8 -31
- data/src/nodes/loops.js +66 -66
- data/src/nodes/methods.js +29 -4
- data/src/nodes/patterns.js +37 -9
- data/src/nodes/regexp.js +30 -23
- data/src/nodes/return.js +33 -22
- data/src/nodes/statements.js +2 -2
- data/src/parser.rb +71 -11
- data/src/printer.js +45 -0
- data/src/utils.js +2 -0
- data/src/utils/printEmptyCollection.js +42 -0
- metadata +4 -3
data/src/nodes/return.js
CHANGED
@@ -13,10 +13,13 @@ const { literal } = require("../utils");
|
|
13
13
|
// because they have low enough operator precedence that you need to explicitly
|
14
14
|
// keep them in there.
|
15
15
|
const canSkipParens = (args) => {
|
16
|
-
const
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
const stmts = args.body[0].body[0];
|
17
|
+
if (stmts.comments) {
|
18
|
+
return false;
|
19
|
+
}
|
20
|
+
|
21
|
+
const stmt = stmts.body[0];
|
22
|
+
return stmt.type !== "binary" || !["and", "or"].includes(stmt.body[1]);
|
20
23
|
};
|
21
24
|
|
22
25
|
const printReturn = (path, opts, print) => {
|
@@ -27,25 +30,27 @@ const printReturn = (path, opts, print) => {
|
|
27
30
|
return "return";
|
28
31
|
}
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
if (args.body.length === 1) {
|
34
|
+
// If the body of the return contains parens, then just skip directly to the
|
35
|
+
// content of the parens so that we can skip printing parens if we don't
|
36
|
+
// want them.
|
37
|
+
if (args.body[0] && args.body[0].type === "paren" && canSkipParens(args)) {
|
38
|
+
args = args.body[0].body[0];
|
39
|
+
steps = steps.concat("body", 0, "body", 0);
|
40
|
+
}
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
// If we're returning an array literal that isn't a special array, single
|
43
|
+
// element array, or an empty array, then we want to grab the arguments so
|
44
|
+
// that we can print them out as if they were normal return arguments.
|
45
|
+
if (
|
46
|
+
args.body[0] &&
|
47
|
+
args.body[0].type === "array" &&
|
48
|
+
args.body[0].body[0] &&
|
49
|
+
args.body[0].body[0].body.length > 1 &&
|
50
|
+
["args", "args_add_star"].includes(args.body[0].body[0].type)
|
51
|
+
) {
|
52
|
+
steps = steps.concat("body", 0, "body", 0);
|
53
|
+
}
|
49
54
|
}
|
50
55
|
|
51
56
|
// Now that we've established which actual node is the arguments to return,
|
@@ -56,6 +61,12 @@ const printReturn = (path, opts, print) => {
|
|
56
61
|
// be a singular doc as opposed to an array.
|
57
62
|
const value = Array.isArray(parts) ? join(concat([",", line]), parts) : parts;
|
58
63
|
|
64
|
+
// We only get here if we have comments somewhere that would prevent us from
|
65
|
+
// skipping the parentheses.
|
66
|
+
if (args.body.length === 1 && args.body[0].type === "paren") {
|
67
|
+
return concat(["return", value]);
|
68
|
+
}
|
69
|
+
|
59
70
|
return group(
|
60
71
|
concat([
|
61
72
|
"return",
|
data/src/nodes/statements.js
CHANGED
@@ -98,8 +98,8 @@ module.exports = {
|
|
98
98
|
stmts[0].comments
|
99
99
|
) {
|
100
100
|
const comments = path.map(
|
101
|
-
(commentPath
|
102
|
-
|
101
|
+
(commentPath) => {
|
102
|
+
commentPath.getValue().printed = true;
|
103
103
|
return opts.printer.printComment(commentPath);
|
104
104
|
},
|
105
105
|
"body",
|
data/src/parser.rb
CHANGED
@@ -63,14 +63,14 @@ class Prettier::Parser < Ripper
|
|
63
63
|
# would happen to be the innermost keyword). Then the outer one would only be
|
64
64
|
# able to grab the first one. In this way all of the scanner events act as
|
65
65
|
# their own stack.
|
66
|
-
def find_scanner_event(type, body = :any)
|
66
|
+
def find_scanner_event(type, body = :any, consume: true)
|
67
67
|
index =
|
68
68
|
scanner_events.rindex do |scanner_event|
|
69
69
|
scanner_event[:type] == type &&
|
70
70
|
(body == :any || (scanner_event[:body] == body))
|
71
71
|
end
|
72
72
|
|
73
|
-
scanner_events.delete_at(index)
|
73
|
+
consume ? scanner_events.delete_at(index) : (index && scanner_events[index])
|
74
74
|
end
|
75
75
|
|
76
76
|
# Scanner events occur when the lexer hits a new token, like a keyword or an
|
@@ -675,8 +675,15 @@ class Prettier::Parser < Ripper
|
|
675
675
|
# It accepts as arguments the switch of the case and the consequent
|
676
676
|
# clause.
|
677
677
|
def on_case(switch, consequent)
|
678
|
-
|
679
|
-
|
678
|
+
beging =
|
679
|
+
if event = find_scanner_event(:@kw, 'case', consume: false)
|
680
|
+
scanner_events.delete(event).merge!(type: :case)
|
681
|
+
else
|
682
|
+
keyword = find_scanner_event(:@kw, 'in', consume: false)
|
683
|
+
switch.merge(type: :rassign, keyword: keyword)
|
684
|
+
end
|
685
|
+
|
686
|
+
beging.merge!(
|
680
687
|
body: [switch, consequent],
|
681
688
|
end: consequent[:end],
|
682
689
|
char_end: consequent[:char_end]
|
@@ -746,6 +753,11 @@ class Prettier::Parser < Ripper
|
|
746
753
|
# of the method, the operator being used to send the method, the name of
|
747
754
|
# the method, and the arguments being passed to the method.
|
748
755
|
def on_command_call(receiver, oper, ident, args)
|
756
|
+
# Make sure we take the operator out of the scanner events so that it
|
757
|
+
# doesn't get confused for a unary operator later.
|
758
|
+
scanner_events.delete(oper)
|
759
|
+
|
760
|
+
# Grab the ending from either the arguments or the method being sent
|
749
761
|
ending = args || ident
|
750
762
|
|
751
763
|
{
|
@@ -814,18 +826,43 @@ class Prettier::Parser < Ripper
|
|
814
826
|
# │ └> params
|
815
827
|
# └> ident
|
816
828
|
#
|
829
|
+
# You can also have single-line methods since Ruby 3.0+, which have slightly
|
830
|
+
# different syntax but still flow through this method. Those look like:
|
831
|
+
#
|
832
|
+
# def foo = bar
|
833
|
+
# | |
|
834
|
+
# | └> stmt
|
835
|
+
# └> ident
|
836
|
+
#
|
817
837
|
def on_def(ident, params, bodystmt)
|
818
838
|
# Make sure to delete this scanner event in case you're defining something
|
819
839
|
# like def class which would lead to this being a kw and causing all kinds
|
820
840
|
# of trouble
|
821
841
|
scanner_events.delete(ident)
|
822
842
|
|
843
|
+
# Find the beginning of the method definition, which works for single-line
|
844
|
+
# and normal method definitions.
|
845
|
+
beging = find_scanner_event(:@kw, 'def')
|
846
|
+
|
847
|
+
# If we don't have a bodystmt node, then we have a single-line method
|
848
|
+
if bodystmt[:type] != :bodystmt
|
849
|
+
return(
|
850
|
+
{
|
851
|
+
type: :defsl,
|
852
|
+
body: [ident, params, bodystmt],
|
853
|
+
start: beging[:start],
|
854
|
+
char_start: beging[:char_start],
|
855
|
+
end: bodystmt[:end],
|
856
|
+
char_end: bodystmt[:char_end]
|
857
|
+
}
|
858
|
+
)
|
859
|
+
end
|
860
|
+
|
823
861
|
if params[:type] == :params && !params[:body].any?
|
824
862
|
location = ident[:char_end]
|
825
863
|
params.merge!(char_start: location, char_end: location)
|
826
864
|
end
|
827
865
|
|
828
|
-
beging = find_scanner_event(:@kw, 'def')
|
829
866
|
ending = find_scanner_event(:@kw, 'end')
|
830
867
|
|
831
868
|
bodystmt.bind(
|
@@ -981,7 +1018,7 @@ class Prettier::Parser < Ripper
|
|
981
1018
|
#
|
982
1019
|
# which would be the same symbol as above.
|
983
1020
|
def on_dyna_symbol(string)
|
984
|
-
if
|
1021
|
+
if find_scanner_event(:@symbeg, consume: false)
|
985
1022
|
# A normal dynamic symbol
|
986
1023
|
beging = find_scanner_event(:@symbeg)
|
987
1024
|
ending = find_scanner_event(:@tstring_end)
|
@@ -1157,6 +1194,24 @@ class Prettier::Parser < Ripper
|
|
1157
1194
|
}
|
1158
1195
|
end
|
1159
1196
|
|
1197
|
+
# fndptn is a parser event that represents matching against a pattern where
|
1198
|
+
# you find a pattern in an array using the Ruby 3.0+ pattern matching syntax.
|
1199
|
+
def on_fndptn(const, presplat, args, postsplat)
|
1200
|
+
beging = const || find_scanner_event(:@lbracket)
|
1201
|
+
ending = find_scanner_event(:@rbracket)
|
1202
|
+
|
1203
|
+
pieces = [const, presplat, *args, postsplat].compact
|
1204
|
+
|
1205
|
+
{
|
1206
|
+
type: :fndptn,
|
1207
|
+
body: [const, presplat, args, postsplat],
|
1208
|
+
start: beging[:start],
|
1209
|
+
char_start: beging[:char_start],
|
1210
|
+
end: ending[:end],
|
1211
|
+
char_end: ending[:char_end]
|
1212
|
+
}
|
1213
|
+
end
|
1214
|
+
|
1160
1215
|
# for is a parser event that represents using the somewhat esoteric for
|
1161
1216
|
# loop. It accepts as arguments an ident which is the iterating variable,
|
1162
1217
|
# an enumerable for that which is being enumerated, and a stmts event that
|
@@ -1302,8 +1357,12 @@ class Prettier::Parser < Ripper
|
|
1302
1357
|
end
|
1303
1358
|
|
1304
1359
|
# in is a parser event that represents using the in keyword within the
|
1305
|
-
# Ruby 2.7+ pattern matching syntax.
|
1360
|
+
# Ruby 2.7+ pattern matching syntax. Alternatively in Ruby 3+ it is also used
|
1361
|
+
# to handle rightward assignment for pattern matching.
|
1306
1362
|
def on_in(pattern, stmts, consequent)
|
1363
|
+
# Here we have a rightward assignment
|
1364
|
+
return pattern unless stmts
|
1365
|
+
|
1307
1366
|
beging = find_scanner_event(:@kw, 'in')
|
1308
1367
|
ending = consequent || find_scanner_event(:@kw, 'end')
|
1309
1368
|
|
@@ -1341,8 +1400,8 @@ class Prettier::Parser < Ripper
|
|
1341
1400
|
def on_lambda(params, stmts)
|
1342
1401
|
beging = find_scanner_event(:@tlambda)
|
1343
1402
|
|
1344
|
-
if
|
1345
|
-
opening =
|
1403
|
+
if event = find_scanner_event(:@tlambeg, consume: false)
|
1404
|
+
opening = scanner_events.delete(event)
|
1346
1405
|
closing = find_scanner_event(:@rbrace)
|
1347
1406
|
else
|
1348
1407
|
opening = find_scanner_event(:@kw, 'do')
|
@@ -1719,7 +1778,8 @@ class Prettier::Parser < Ripper
|
|
1719
1778
|
# expression literal, like /foo/. It can be followed by any number of
|
1720
1779
|
# regexp_add events, which we'll append onto an array body.
|
1721
1780
|
def on_regexp_new
|
1722
|
-
find_scanner_event(:@regexp_beg)
|
1781
|
+
beging = find_scanner_event(:@regexp_beg)
|
1782
|
+
beging.merge!(type: :regexp, body: [], beging: beging[:body])
|
1723
1783
|
end
|
1724
1784
|
|
1725
1785
|
# regexp_add is a parser event that represents a piece of a regular
|
@@ -2305,7 +2365,7 @@ class Prettier::Parser < Ripper
|
|
2305
2365
|
else
|
2306
2366
|
# You can hit this pattern if you're assigning to a splat using pattern
|
2307
2367
|
# matching syntax in Ruby 2.7+
|
2308
|
-
{ type: :var_field, body:
|
2368
|
+
{ type: :var_field, body: nil }
|
2309
2369
|
end
|
2310
2370
|
end
|
2311
2371
|
|
data/src/printer.js
CHANGED
@@ -20,6 +20,18 @@ function printNode(path, opts, print) {
|
|
20
20
|
throw new Error(`Unsupported node encountered: ${type}\n${ast}`);
|
21
21
|
}
|
22
22
|
|
23
|
+
// This is an escape-hatch to ignore nodes in the tree. If you have a comment
|
24
|
+
// that includes this pattern, then the entire node will be ignored and just the
|
25
|
+
// original source will be printed out.
|
26
|
+
function hasPrettierIgnore(path) {
|
27
|
+
const node = path.getValue();
|
28
|
+
|
29
|
+
return (
|
30
|
+
node.comments &&
|
31
|
+
node.comments.some((comment) => comment.value.includes("prettier-ignore"))
|
32
|
+
);
|
33
|
+
}
|
34
|
+
|
23
35
|
const noComments = [
|
24
36
|
"args",
|
25
37
|
"args_add_block",
|
@@ -55,6 +67,38 @@ function getCommentChildNodes(node) {
|
|
55
67
|
|
56
68
|
return [node.body[0]].concat(values).concat(node.body[2]);
|
57
69
|
}
|
70
|
+
case "params": {
|
71
|
+
const [reqs, optls, rest, post, kwargs, kwargRest, block] = node.body;
|
72
|
+
let parts = reqs || [];
|
73
|
+
|
74
|
+
(optls || []).forEach((optl) => {
|
75
|
+
parts = parts.concat(optl);
|
76
|
+
});
|
77
|
+
|
78
|
+
if (rest) {
|
79
|
+
parts.push(rest);
|
80
|
+
}
|
81
|
+
|
82
|
+
parts = parts.concat(post || []);
|
83
|
+
|
84
|
+
(kwargs || []).forEach((kwarg) => {
|
85
|
+
if (kwarg[1]) {
|
86
|
+
parts = parts.concat(kwarg);
|
87
|
+
} else {
|
88
|
+
parts.push(kwarg[0]);
|
89
|
+
}
|
90
|
+
});
|
91
|
+
|
92
|
+
if (kwargRest && kwargRest !== "nil") {
|
93
|
+
parts.push(kwargRest);
|
94
|
+
}
|
95
|
+
|
96
|
+
if (block) {
|
97
|
+
parts.push(block);
|
98
|
+
}
|
99
|
+
|
100
|
+
return parts;
|
101
|
+
}
|
58
102
|
default:
|
59
103
|
return node.body;
|
60
104
|
}
|
@@ -83,6 +127,7 @@ function isBlockComment(comment) {
|
|
83
127
|
module.exports = {
|
84
128
|
embed,
|
85
129
|
print: printNode,
|
130
|
+
hasPrettierIgnore,
|
86
131
|
canAttachComment,
|
87
132
|
getCommentChildNodes,
|
88
133
|
printComment,
|
data/src/utils.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
const { concat } = require("./prettier");
|
2
2
|
const isEmptyStmts = require("./utils/isEmptyStmts");
|
3
3
|
const literalLineNoBreak = require("./utils/literalLineNoBreak");
|
4
|
+
const printEmptyCollection = require("./utils/printEmptyCollection");
|
4
5
|
|
5
6
|
// If the node is a type of assignment or if the node is a paren and nested
|
6
7
|
// inside that paren is a node that is a type of assignment.
|
@@ -89,5 +90,6 @@ module.exports = {
|
|
89
90
|
makeCall,
|
90
91
|
noIndent,
|
91
92
|
prefix,
|
93
|
+
printEmptyCollection,
|
92
94
|
skipAssignIndent
|
93
95
|
};
|
@@ -0,0 +1,42 @@
|
|
1
|
+
const { concat, group, hardline, indent, join, line } = require("../prettier");
|
2
|
+
|
3
|
+
// Empty collections are array or hash literals that do not contain any
|
4
|
+
// contents. They can, however, have comments inside the body. You can solve
|
5
|
+
// this by having a child node inside the array that gets the comments attached
|
6
|
+
// to it, but that requires modifying the parser. Instead, we can just manually
|
7
|
+
// print out the non-leading comments here.
|
8
|
+
function printEmptyCollection(path, opts, startToken, endToken) {
|
9
|
+
const node = path.getValue();
|
10
|
+
|
11
|
+
// If there are no comments or only leading comments, then we can just print
|
12
|
+
// out the start and end token and be done, as there are no comments inside
|
13
|
+
// the body of this node.
|
14
|
+
if (!node.comments || !node.comments.some((comment) => !comment.leading)) {
|
15
|
+
return `${startToken}${endToken}`;
|
16
|
+
}
|
17
|
+
|
18
|
+
const comments = [];
|
19
|
+
|
20
|
+
// For each comment, go through its path and print it out manually.
|
21
|
+
const printComment = (commentPath) => {
|
22
|
+
const comment = commentPath.getValue();
|
23
|
+
|
24
|
+
if (!comment.leading) {
|
25
|
+
comment.printed = true;
|
26
|
+
comments.push(opts.printer.printComment(commentPath));
|
27
|
+
}
|
28
|
+
};
|
29
|
+
|
30
|
+
path.each(printComment, "comments");
|
31
|
+
|
32
|
+
return group(
|
33
|
+
concat([
|
34
|
+
startToken,
|
35
|
+
indent(concat([hardline, join(hardline, comments)])),
|
36
|
+
line,
|
37
|
+
endToken
|
38
|
+
])
|
39
|
+
);
|
40
|
+
}
|
41
|
+
|
42
|
+
module.exports = printEmptyCollection;
|
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: 1.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Deisz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- src/utils/inlineEnsureParens.js
|
74
74
|
- src/utils/isEmptyStmts.js
|
75
75
|
- src/utils/literalLineNoBreak.js
|
76
|
+
- src/utils/printEmptyCollection.js
|
76
77
|
homepage: https://github.com/prettier/plugin-ruby#readme
|
77
78
|
licenses:
|
78
79
|
- MIT
|
@@ -92,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
93
|
- !ruby/object:Gem::Version
|
93
94
|
version: '0'
|
94
95
|
requirements: []
|
95
|
-
rubygems_version: 3.
|
96
|
+
rubygems_version: 3.2.3
|
96
97
|
signing_key:
|
97
98
|
specification_version: 4
|
98
99
|
summary: prettier plugin for the Ruby programming language
|