prettier 0.21.0 → 1.0.1
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 +112 -7
- data/CONTRIBUTING.md +4 -4
- data/README.md +18 -14
- data/package.json +9 -6
- data/src/embed.js +27 -8
- 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 +55 -47
- data/src/nodes/arrays.js +132 -106
- data/src/nodes/assign.js +32 -32
- data/src/nodes/blocks.js +8 -3
- data/src/nodes/calls.js +163 -60
- data/src/nodes/case.js +11 -7
- data/src/nodes/class.js +74 -0
- data/src/nodes/commands.js +36 -31
- data/src/nodes/conditionals.js +44 -30
- data/src/nodes/constants.js +39 -21
- data/src/nodes/flow.js +11 -1
- data/src/nodes/hashes.js +90 -109
- data/src/nodes/heredocs.js +34 -0
- data/src/nodes/hooks.js +21 -22
- data/src/nodes/ints.js +27 -20
- data/src/nodes/lambdas.js +14 -27
- data/src/nodes/loops.js +10 -5
- data/src/nodes/massign.js +87 -65
- data/src/nodes/methods.js +48 -73
- data/src/nodes/operators.js +70 -39
- data/src/nodes/params.js +26 -16
- data/src/nodes/patterns.js +108 -33
- data/src/nodes/regexp.js +45 -14
- data/src/nodes/rescue.js +72 -59
- data/src/nodes/statements.js +86 -44
- data/src/nodes/strings.js +95 -85
- data/src/nodes/super.js +35 -0
- data/src/nodes/undef.js +42 -0
- data/src/parser.js +86 -0
- data/src/parser.rb +2400 -621
- data/src/printer.js +90 -0
- data/src/ruby.js +19 -41
- data/src/toProc.js +4 -4
- data/src/utils.js +24 -88
- data/src/utils/literalLineNoBreak.js +7 -0
- data/src/utils/printEmptyCollection.js +42 -0
- metadata +12 -49
- data/src/nodes/scopes.js +0 -61
- data/src/parse.js +0 -37
- data/src/print.js +0 -23
data/src/nodes/aref.js
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
const { concat, group, indent, join, line, softline } = require("../prettier");
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
// `aref` nodes are when you're pulling a value out of a collection at a
|
4
|
+
// specific index. Put another way, it's any time you're calling the method
|
5
|
+
// `#[]`.
|
6
|
+
//
|
7
|
+
// The nodes usually contains two children, details below in the
|
8
|
+
// `printArefField` function. In some cases, you don't necessarily have the
|
9
|
+
// second child node, because you can call procs with a pretty esoteric syntax.
|
10
|
+
// In the following example, you wouldn't have a second child, and `"foo"` would
|
11
|
+
// be the first child.
|
12
|
+
//
|
13
|
+
// foo[]
|
14
|
+
//
|
15
15
|
function printAref(path, opts, print) {
|
16
16
|
const indexNode = path.getValue().body[1];
|
17
17
|
|
@@ -22,20 +22,20 @@ function printAref(path, opts, print) {
|
|
22
22
|
return printArefField(path, opts, print);
|
23
23
|
}
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
25
|
+
// `aref_field` nodes are for assigning values into collections at specific
|
26
|
+
// indices. Put another way, it's any time you're calling the method `#[]=`.
|
27
|
+
// The `aref_field` node itself is just the left side of the assignment, and
|
28
|
+
// they're always wrapped in `assign` nodes.
|
29
|
+
//
|
30
|
+
// The nodes always contain two children, the name of the array (usually a
|
31
|
+
// `vcall` node and the index (usually an `args_add_block` node). The
|
32
|
+
// `args_add_block` is one of a couple nodes that has special handling where its
|
33
|
+
// printed form is actually an array to make joining easier.
|
34
|
+
//
|
35
|
+
// So in the following example, `"foo"` is the array and `["bar"]` is the index.
|
36
|
+
//
|
37
|
+
// foo[bar] = baz
|
38
|
+
//
|
39
39
|
function printArefField(path, opts, print) {
|
40
40
|
const [printedArray, printedIndex] = path.map(print, "body");
|
41
41
|
|
data/src/nodes/args.js
CHANGED
@@ -9,53 +9,56 @@ const {
|
|
9
9
|
} = require("../prettier");
|
10
10
|
|
11
11
|
const toProc = require("../toProc");
|
12
|
-
const {
|
12
|
+
const { getTrailingComma } = require("../utils");
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
if (path.getValue().body[0] === null) {
|
17
|
-
return "";
|
18
|
-
}
|
19
|
-
|
20
|
-
// Here we can skip the entire rest of the method by just checking if it's
|
21
|
-
// an args_forward node, as we're guaranteed that there are no other arg
|
22
|
-
// nodes.
|
23
|
-
if (path.getValue().body[0].type === "args_forward") {
|
24
|
-
return "(...)";
|
25
|
-
}
|
14
|
+
function printArgParen(path, opts, print) {
|
15
|
+
const argsNode = path.getValue().body[0];
|
26
16
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
const argsNode = path.getValue().body[0];
|
31
|
-
const hasBlock = argsNode.type === "args_add_block" && argsNode.body[1];
|
32
|
-
|
33
|
-
if (heredocs.length > 1) {
|
34
|
-
return concat(["(", join(", ", args), ")"].concat(heredocs));
|
35
|
-
}
|
17
|
+
if (argsNode === null) {
|
18
|
+
return "";
|
19
|
+
}
|
36
20
|
|
37
|
-
|
21
|
+
// Here we can skip the entire rest of the method by just checking if it's
|
22
|
+
// an args_forward node, as we're guaranteed that there are no other arg
|
23
|
+
// nodes.
|
24
|
+
if (argsNode.type === "args_forward") {
|
25
|
+
return group(
|
38
26
|
concat([
|
39
27
|
"(",
|
40
|
-
indent(
|
41
|
-
|
42
|
-
|
43
|
-
join(concat([",", line]), args),
|
44
|
-
addTrailingCommas && !hasBlock ? ifBreak(",", "") : ""
|
45
|
-
])
|
46
|
-
),
|
47
|
-
concat([softline, ")"])
|
28
|
+
indent(concat([softline, path.call(print, "body", 0)])),
|
29
|
+
softline,
|
30
|
+
")"
|
48
31
|
])
|
49
32
|
);
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
33
|
+
}
|
34
|
+
|
35
|
+
const args = path.call(print, "body", 0);
|
36
|
+
const hasBlock = argsNode.type === "args_add_block" && argsNode.body[1];
|
37
|
+
|
38
|
+
// Now here we return a doc that represents the whole grouped expression,
|
39
|
+
// including the surrouding parentheses.
|
40
|
+
return group(
|
41
|
+
concat([
|
42
|
+
"(",
|
43
|
+
indent(
|
44
|
+
concat([
|
45
|
+
softline,
|
46
|
+
join(concat([",", line]), args),
|
47
|
+
getTrailingComma(opts) && !hasBlock ? ifBreak(",", "") : ""
|
48
|
+
])
|
49
|
+
),
|
50
|
+
softline,
|
51
|
+
")"
|
52
|
+
])
|
53
|
+
);
|
54
|
+
}
|
55
|
+
|
56
|
+
function printArgs(path, { rubyToProc }, print) {
|
57
|
+
const args = path.map(print, "body");
|
58
|
+
|
59
|
+
// Don't bother trying to do any kind of fancy toProc transform if the
|
60
|
+
// option is disabled.
|
61
|
+
if (rubyToProc) {
|
59
62
|
let blockNode = null;
|
60
63
|
|
61
64
|
// Look up the chain to see if these arguments are contained within a
|
@@ -72,21 +75,26 @@ module.exports = {
|
|
72
75
|
return blockNode;
|
73
76
|
});
|
74
77
|
|
75
|
-
const proc = blockNode && toProc(path,
|
78
|
+
const proc = blockNode && toProc(path, blockNode);
|
76
79
|
|
77
|
-
// If we have a successful to_proc transformation, but we're part of an
|
78
|
-
// node, that means it's something to the effect of
|
80
|
+
// If we have a successful to_proc transformation, but we're part of an
|
81
|
+
// aref node, that means it's something to the effect of
|
79
82
|
//
|
80
83
|
// foo[:bar].each(&:to_s)
|
81
84
|
//
|
82
|
-
// In this case we need to just return regular arguments, otherwise we
|
83
|
-
// end up putting &:to_s inside the brackets accidentally.
|
85
|
+
// In this case we need to just return regular arguments, otherwise we
|
86
|
+
// would end up putting &:to_s inside the brackets accidentally.
|
84
87
|
if (proc && path.getParentNode(1).type !== "aref") {
|
85
88
|
args.push(proc);
|
86
89
|
}
|
90
|
+
}
|
87
91
|
|
88
|
-
|
89
|
-
|
92
|
+
return args;
|
93
|
+
}
|
94
|
+
|
95
|
+
module.exports = {
|
96
|
+
arg_paren: printArgParen,
|
97
|
+
args: printArgs,
|
90
98
|
args_add_block: (path, opts, print) => {
|
91
99
|
const parts = path.call(print, "body", 0);
|
92
100
|
|
data/src/nodes/arrays.js
CHANGED
@@ -5,36 +5,74 @@ const {
|
|
5
5
|
indent,
|
6
6
|
join,
|
7
7
|
line,
|
8
|
-
literalline,
|
9
8
|
softline
|
10
9
|
} = require("../prettier");
|
11
10
|
|
12
|
-
const
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
11
|
+
const { getTrailingComma, printEmptyCollection } = require("../utils");
|
12
|
+
|
13
|
+
// Checks that every argument within this args node is a string_literal node
|
14
|
+
// that has no spaces or interpolations. This means we're dealing with an array
|
15
|
+
// that looks something like:
|
16
|
+
//
|
17
|
+
// ['a', 'b', 'c']
|
18
|
+
//
|
19
|
+
function isStringArray(args) {
|
20
|
+
return (
|
21
|
+
args.body.length > 1 &&
|
22
|
+
args.body.every((arg) => {
|
23
|
+
// We want to verify that every node inside of this array is a string
|
24
|
+
// literal. We also want to make sure none of them have comments attached.
|
25
|
+
if (arg.type !== "string_literal" || arg.comments) {
|
26
|
+
return false;
|
27
|
+
}
|
24
28
|
|
25
|
-
|
26
|
-
|
29
|
+
// If the string has multiple parts (meaning plain string content but also
|
30
|
+
// interpolated content) then we know it's not a simple string.
|
31
|
+
if (arg.body.length !== 1) {
|
32
|
+
return false;
|
33
|
+
}
|
27
34
|
|
28
|
-
const
|
29
|
-
[start].concat(path.map(print, "body"));
|
35
|
+
const part = arg.body[0];
|
30
36
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
// If the only part of this string is not @tstring_content then it's
|
38
|
+
// interpolated, so again we can return false.
|
39
|
+
if (part.type !== "@tstring_content") {
|
40
|
+
return false;
|
41
|
+
}
|
35
42
|
|
36
|
-
|
37
|
-
|
43
|
+
// Finally, verify that the string doesn't contain a space, an escape
|
44
|
+
// character, or brackets so that we know it can be put into a string
|
45
|
+
// literal array.
|
46
|
+
return !/[\s\\[\]]/.test(part.body);
|
47
|
+
})
|
48
|
+
);
|
49
|
+
}
|
50
|
+
|
51
|
+
// Checks that every argument within this args node is a symbol_literal node (as
|
52
|
+
// opposed to a dyna_symbol) so it has no interpolation. This means we're
|
53
|
+
// dealing with an array that looks something like:
|
54
|
+
//
|
55
|
+
// [:a, :b, :c]
|
56
|
+
//
|
57
|
+
function isSymbolArray(args) {
|
58
|
+
return (
|
59
|
+
args.body.length > 1 &&
|
60
|
+
args.body.every((arg) => arg.type === "symbol_literal" && !arg.comments)
|
61
|
+
);
|
62
|
+
}
|
63
|
+
|
64
|
+
// Prints out a word that is a part of a special array literal that accepts
|
65
|
+
// interpolation. The body is an array of either plain strings or interpolated
|
66
|
+
// expressions.
|
67
|
+
function printSpecialArrayWord(path, opts, print) {
|
68
|
+
return concat(path.map(print, "body"));
|
69
|
+
}
|
70
|
+
|
71
|
+
// Prints out a special array literal. Accepts the parts of the array literal as
|
72
|
+
// an argument, where the first element of the parts array is a string that
|
73
|
+
// contains the special start.
|
74
|
+
function printSpecialArrayParts(parts) {
|
75
|
+
return group(
|
38
76
|
concat([
|
39
77
|
parts[0],
|
40
78
|
"[",
|
@@ -42,93 +80,81 @@ const printSpecialArray = (parts) =>
|
|
42
80
|
concat([softline, "]"])
|
43
81
|
])
|
44
82
|
);
|
83
|
+
}
|
84
|
+
|
85
|
+
// Generates a print function with an embedded special start character for the
|
86
|
+
// specific type of array literal that we're dealing with. The print function
|
87
|
+
// returns an array as it expects to eventually be handed off to
|
88
|
+
// printSpecialArrayParts.
|
89
|
+
function printSpecialArray(start) {
|
90
|
+
return function printSpecialArrayWithStart(path, opts, print) {
|
91
|
+
return [start].concat(path.map(print, "body"));
|
92
|
+
};
|
93
|
+
}
|
94
|
+
|
95
|
+
// An array node is any literal array in Ruby. This includes all of the special
|
96
|
+
// array literals as well as regular arrays. If it is a special array literal
|
97
|
+
// then it will have one child that represents the special array, otherwise it
|
98
|
+
// will have one child that contains all of the elements of the array.
|
99
|
+
function printArray(path, opts, print) {
|
100
|
+
const array = path.getValue();
|
101
|
+
const args = array.body[0];
|
102
|
+
|
103
|
+
// If there is no inner arguments node, then we're dealing with an empty
|
104
|
+
// array, so we can go ahead and return.
|
105
|
+
if (args === null) {
|
106
|
+
return printEmptyCollection(path, opts, "[", "]");
|
107
|
+
}
|
45
108
|
|
46
|
-
//
|
47
|
-
//
|
48
|
-
|
49
|
-
const
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
elementPath: elementPath.concat(["body", index])
|
54
|
-
}));
|
109
|
+
// If we have an array that contains only simple string literals with no
|
110
|
+
// spaces or interpolation, then we're going to print a %w array.
|
111
|
+
if (opts.rubyArrayLiteral && isStringArray(args)) {
|
112
|
+
const printString = (stringPath) => stringPath.call(print, "body", 0);
|
113
|
+
const parts = path.map(printString, "body", 0, "body");
|
114
|
+
|
115
|
+
return printSpecialArrayParts(["%w"].concat(parts));
|
55
116
|
}
|
56
117
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
118
|
+
// If we have an array that contains only simple symbol literals with no
|
119
|
+
// interpolation, then we're going to print a %i array.
|
120
|
+
if (opts.rubyArrayLiteral && isSymbolArray(args)) {
|
121
|
+
const printSymbol = (symbolPath) => symbolPath.call(print, "body", 0);
|
122
|
+
const parts = path.map(printSymbol, "body", 0, "body");
|
123
|
+
|
124
|
+
return printSpecialArrayParts(["%i"].concat(parts));
|
125
|
+
}
|
126
|
+
|
127
|
+
// If we don't have a regular args node at this point then we have a special
|
128
|
+
// array literal. In that case we're going to print out the body (which will
|
129
|
+
// return to us an array with the first one being the start of the array) and
|
130
|
+
// send that over to the printSpecialArrayParts function.
|
131
|
+
if (!["args", "args_add_star"].includes(args.type)) {
|
132
|
+
return printSpecialArrayParts(path.call(print, "body", 0));
|
133
|
+
}
|
134
|
+
|
135
|
+
// Here we have a normal array of any type of object with no special literal
|
136
|
+
// types or anything.
|
137
|
+
return group(
|
138
|
+
concat([
|
139
|
+
"[",
|
140
|
+
indent(
|
141
|
+
concat([
|
142
|
+
softline,
|
143
|
+
join(concat([",", line]), path.call(print, "body", 0)),
|
144
|
+
getTrailingComma(opts) ? ifBreak(",", "") : ""
|
145
|
+
])
|
146
|
+
),
|
147
|
+
softline,
|
148
|
+
"]"
|
149
|
+
])
|
62
150
|
);
|
63
|
-
}
|
151
|
+
}
|
64
152
|
|
65
153
|
module.exports = {
|
66
|
-
array:
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
if (isStringArray(args)) {
|
74
|
-
return printSpecialArray(
|
75
|
-
["%w"].concat(getSpecialArrayParts(path, print, args))
|
76
|
-
);
|
77
|
-
}
|
78
|
-
|
79
|
-
if (isSymbolArray(args)) {
|
80
|
-
return printSpecialArray(
|
81
|
-
["%i"].concat(getSpecialArrayParts(path, print, args))
|
82
|
-
);
|
83
|
-
}
|
84
|
-
|
85
|
-
if (!["args", "args_add_star"].includes(args.type)) {
|
86
|
-
return printSpecialArray(path.call(print, "body", 0));
|
87
|
-
}
|
88
|
-
|
89
|
-
const normalDocs = [];
|
90
|
-
|
91
|
-
const elementDocs = path.call(print, "body", 0);
|
92
|
-
const elements = getElements(path.getValue().body[0], ["body", 0]);
|
93
|
-
|
94
|
-
// We need to manually loop through the elements in the array in order to
|
95
|
-
// take care of heredocs printing (their commas go after the opening, as
|
96
|
-
// opposed to at the end).
|
97
|
-
elements.forEach(({ element, elementPath }, index) => {
|
98
|
-
const isInner = index !== elements.length - 1;
|
99
|
-
|
100
|
-
if (element.type === "heredoc") {
|
101
|
-
normalDocs.push(
|
102
|
-
element.beging,
|
103
|
-
isInner || addTrailingCommas ? "," : "",
|
104
|
-
literalline,
|
105
|
-
concat(
|
106
|
-
path.map.apply(path, [print].concat(elementPath).concat("body"))
|
107
|
-
),
|
108
|
-
element.ending,
|
109
|
-
isInner ? line : ""
|
110
|
-
);
|
111
|
-
} else {
|
112
|
-
normalDocs.push(elementDocs[index]);
|
113
|
-
|
114
|
-
if (isInner) {
|
115
|
-
normalDocs.push(concat([",", line]));
|
116
|
-
} else if (addTrailingCommas) {
|
117
|
-
normalDocs.push(ifBreak(",", ""));
|
118
|
-
}
|
119
|
-
}
|
120
|
-
});
|
121
|
-
|
122
|
-
return group(
|
123
|
-
concat([
|
124
|
-
"[",
|
125
|
-
indent(concat([softline].concat(normalDocs))),
|
126
|
-
concat([softline, "]"])
|
127
|
-
])
|
128
|
-
);
|
129
|
-
},
|
130
|
-
qsymbols: makeArray("%i"),
|
131
|
-
qwords: makeArray("%w"),
|
132
|
-
symbols: makeArray("%I"),
|
133
|
-
words: makeArray("%W")
|
154
|
+
array: printArray,
|
155
|
+
qsymbols: printSpecialArray("%i"),
|
156
|
+
qwords: printSpecialArray("%w"),
|
157
|
+
symbols: printSpecialArray("%I"),
|
158
|
+
word: printSpecialArrayWord,
|
159
|
+
words: printSpecialArray("%W")
|
134
160
|
};
|