prettier 1.1.0 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +16 -1
- data/lib/prettier.rb +2 -2
- data/package.json +2 -2
- data/rubocop.yml +26 -0
- data/src/{ruby.js → plugin.js} +2 -2
- data/src/prettier.js +1 -0
- data/src/{embed.js → ruby/embed.js} +6 -2
- data/src/{nodes.js → ruby/nodes.js} +0 -0
- data/src/{nodes → ruby/nodes}/alias.js +1 -1
- data/src/{nodes → ruby/nodes}/aref.js +8 -1
- data/src/{nodes → ruby/nodes}/args.js +2 -2
- data/src/{nodes → ruby/nodes}/arrays.js +2 -3
- data/src/{nodes → ruby/nodes}/assign.js +12 -4
- data/src/ruby/nodes/blocks.js +90 -0
- data/src/{nodes → ruby/nodes}/calls.js +18 -9
- data/src/ruby/nodes/case.js +65 -0
- data/src/{nodes → ruby/nodes}/class.js +1 -1
- data/src/ruby/nodes/commands.js +126 -0
- data/src/{nodes → ruby/nodes}/conditionals.js +3 -3
- data/src/{nodes → ruby/nodes}/constants.js +2 -2
- data/src/{nodes → ruby/nodes}/flow.js +2 -2
- data/src/{nodes → ruby/nodes}/hashes.js +32 -10
- data/src/{nodes → ruby/nodes}/heredocs.js +2 -2
- data/src/ruby/nodes/hooks.js +34 -0
- data/src/{nodes → ruby/nodes}/ints.js +0 -0
- data/src/{nodes → ruby/nodes}/lambdas.js +2 -2
- data/src/{nodes → ruby/nodes}/loops.js +10 -7
- data/src/{nodes → ruby/nodes}/massign.js +8 -1
- data/src/{nodes → ruby/nodes}/methods.js +32 -6
- data/src/{nodes → ruby/nodes}/operators.js +2 -2
- data/src/{nodes → ruby/nodes}/params.js +31 -16
- data/src/{nodes → ruby/nodes}/patterns.js +54 -15
- data/src/{nodes → ruby/nodes}/regexp.js +2 -2
- data/src/{nodes → ruby/nodes}/rescue.js +2 -2
- data/src/ruby/nodes/return.js +94 -0
- data/src/{nodes → ruby/nodes}/statements.js +6 -9
- data/src/{nodes → ruby/nodes}/strings.js +27 -36
- data/src/{nodes → ruby/nodes}/super.js +2 -2
- data/src/{nodes → ruby/nodes}/undef.js +1 -1
- data/src/{parser.js → ruby/parser.js} +4 -3
- data/src/{parser.rb → ruby/parser.rb} +498 -492
- data/src/{printer.js → ruby/printer.js} +33 -1
- data/src/{toProc.js → ruby/toProc.js} +4 -8
- data/src/utils.js +10 -93
- data/src/utils/containsAssignment.js +11 -0
- data/src/utils/getTrailingComma.js +5 -0
- data/src/utils/hasAncestor.js +17 -0
- data/src/utils/literal.js +7 -0
- data/src/utils/makeCall.js +14 -0
- data/src/utils/noIndent.js +10 -0
- data/src/utils/skipAssignIndent.js +10 -0
- metadata +49 -41
- data/src/nodes/blocks.js +0 -85
- data/src/nodes/case.js +0 -61
- data/src/nodes/commands.js +0 -91
- data/src/nodes/hooks.js +0 -44
- data/src/nodes/return.js +0 -72
@@ -1,5 +1,5 @@
|
|
1
|
-
const { concat, group, indent, line, softline } = require("
|
2
|
-
const { noIndent } = require("
|
1
|
+
const { concat, group, indent, line, softline } = require("../../prettier");
|
2
|
+
const { noIndent } = require("../../utils");
|
3
3
|
|
4
4
|
function printBinary(path, opts, print) {
|
5
5
|
const [_leftNode, operator, rightNode] = path.getValue().body;
|
@@ -1,5 +1,12 @@
|
|
1
|
-
const {
|
2
|
-
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
join,
|
5
|
+
indent,
|
6
|
+
line,
|
7
|
+
softline
|
8
|
+
} = require("../../prettier");
|
9
|
+
const { literal } = require("../../utils");
|
3
10
|
|
4
11
|
function printRestParam(symbol) {
|
5
12
|
return function printRestParamWithSymbol(path, opts, print) {
|
@@ -22,18 +29,22 @@ function printParams(path, opts, print) {
|
|
22
29
|
let parts = [];
|
23
30
|
|
24
31
|
if (reqs) {
|
25
|
-
|
32
|
+
path.each(
|
33
|
+
(reqPath) => {
|
34
|
+
// For some very strange reason, if you have a comment attached to a
|
35
|
+
// rest_param, it shows up here in the list of required params.
|
36
|
+
if (reqPath.getValue().type !== "rest_param") {
|
37
|
+
parts.push(print(reqPath));
|
38
|
+
}
|
39
|
+
},
|
40
|
+
"body",
|
41
|
+
0
|
42
|
+
);
|
26
43
|
}
|
27
44
|
|
28
45
|
if (optls) {
|
29
46
|
parts = parts.concat(
|
30
|
-
|
31
|
-
concat([
|
32
|
-
path.call(print, "body", 1, index, 0),
|
33
|
-
" = ",
|
34
|
-
path.call(print, "body", 1, index, 1)
|
35
|
-
])
|
36
|
-
)
|
47
|
+
path.map((optlPath) => join(" = ", optlPath.map(print)), "body", 1)
|
37
48
|
);
|
38
49
|
}
|
39
50
|
|
@@ -47,12 +58,16 @@ function printParams(path, opts, print) {
|
|
47
58
|
|
48
59
|
if (kwargs) {
|
49
60
|
parts = parts.concat(
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
61
|
+
path.map(
|
62
|
+
(kwargPath) => {
|
63
|
+
if (!kwargPath.getValue()[1]) {
|
64
|
+
return kwargPath.call(print, 0);
|
65
|
+
}
|
66
|
+
return group(join(" ", kwargPath.map(print)));
|
67
|
+
},
|
68
|
+
"body",
|
69
|
+
4
|
70
|
+
)
|
56
71
|
);
|
57
72
|
}
|
58
73
|
|
@@ -1,4 +1,14 @@
|
|
1
|
-
const {
|
1
|
+
const {
|
2
|
+
align,
|
3
|
+
concat,
|
4
|
+
group,
|
5
|
+
hardline,
|
6
|
+
indent,
|
7
|
+
join,
|
8
|
+
line
|
9
|
+
} = require("../../prettier");
|
10
|
+
|
11
|
+
const patterns = ["aryptn", "binary", "fndptn", "hshptn", "rassign"];
|
2
12
|
|
3
13
|
function printPatternArg(path, opts, print) {
|
4
14
|
// Pinning is a really special syntax in pattern matching that's not really
|
@@ -34,10 +44,7 @@ function printAryPtn(path, opts, print) {
|
|
34
44
|
|
35
45
|
args = group(join(concat([",", line]), args));
|
36
46
|
|
37
|
-
if (
|
38
|
-
constant ||
|
39
|
-
["aryptn", "binary", "hshptn"].includes(path.getParentNode().type)
|
40
|
-
) {
|
47
|
+
if (constant || patterns.includes(path.getParentNode().type)) {
|
41
48
|
args = concat(["[", args, "]"]);
|
42
49
|
}
|
43
50
|
|
@@ -48,11 +55,27 @@ function printAryPtn(path, opts, print) {
|
|
48
55
|
return args;
|
49
56
|
}
|
50
57
|
|
58
|
+
function printFndPtn(path, opts, print) {
|
59
|
+
const [constant] = path.getValue().body;
|
60
|
+
|
61
|
+
let args = [concat(["*", path.call(print, "body", 1)])]
|
62
|
+
.concat(path.map(print, "body", 2))
|
63
|
+
.concat(concat(["*", path.call(print, "body", 3)]));
|
64
|
+
|
65
|
+
args = concat(["[", group(join(concat([",", line]), args)), "]"]);
|
66
|
+
|
67
|
+
if (constant) {
|
68
|
+
return concat([path.call(print, "body", 0), args]);
|
69
|
+
}
|
70
|
+
|
71
|
+
return args;
|
72
|
+
}
|
73
|
+
|
51
74
|
function printHshPtn(path, opts, print) {
|
52
75
|
const [constant, keyValuePairs, keyValueRest] = path.getValue().body;
|
53
76
|
let args = [];
|
54
77
|
|
55
|
-
if (keyValuePairs) {
|
78
|
+
if (keyValuePairs.length > 0) {
|
56
79
|
const printPair = (pairPath) => {
|
57
80
|
const parts = [pairPath.call(print, 0)];
|
58
81
|
|
@@ -80,10 +103,8 @@ function printHshPtn(path, opts, print) {
|
|
80
103
|
|
81
104
|
if (constant) {
|
82
105
|
args = concat(["[", args, "]"]);
|
83
|
-
} else if (
|
84
|
-
["
|
85
|
-
) {
|
86
|
-
args = concat(["{", args, "}"]);
|
106
|
+
} else if (patterns.includes(path.getParentNode().type)) {
|
107
|
+
args = concat(["{ ", args, " }"]);
|
87
108
|
}
|
88
109
|
|
89
110
|
if (constant) {
|
@@ -96,10 +117,13 @@ function printHshPtn(path, opts, print) {
|
|
96
117
|
function printIn(path, opts, print) {
|
97
118
|
const parts = [
|
98
119
|
"in ",
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
120
|
+
align(
|
121
|
+
"in ".length,
|
122
|
+
path.call(
|
123
|
+
(valuePath) => printPatternArg(valuePath, opts, print),
|
124
|
+
"body",
|
125
|
+
0
|
126
|
+
)
|
103
127
|
),
|
104
128
|
indent(concat([hardline, path.call(print, "body", 1)]))
|
105
129
|
];
|
@@ -111,8 +135,23 @@ function printIn(path, opts, print) {
|
|
111
135
|
return group(concat(parts));
|
112
136
|
}
|
113
137
|
|
138
|
+
function printRAssign(path, opts, print) {
|
139
|
+
const { keyword } = path.getValue();
|
140
|
+
const [leftDoc, rightDoc] = path.map(print, "body");
|
141
|
+
|
142
|
+
return group(
|
143
|
+
concat([
|
144
|
+
leftDoc,
|
145
|
+
keyword ? " in" : " =>",
|
146
|
+
group(indent(concat([line, rightDoc])))
|
147
|
+
])
|
148
|
+
);
|
149
|
+
}
|
150
|
+
|
114
151
|
module.exports = {
|
115
152
|
aryptn: printAryPtn,
|
153
|
+
fndptn: printFndPtn,
|
116
154
|
hshptn: printHshPtn,
|
117
|
-
in: printIn
|
155
|
+
in: printIn,
|
156
|
+
rassign: printRAssign
|
118
157
|
};
|
@@ -0,0 +1,94 @@
|
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
ifBreak,
|
5
|
+
indent,
|
6
|
+
line,
|
7
|
+
join,
|
8
|
+
softline
|
9
|
+
} = require("../../prettier");
|
10
|
+
const { literal } = require("../../utils");
|
11
|
+
|
12
|
+
// You can't skip the parentheses if you have comments or certain operators with
|
13
|
+
// lower precedence than the return keyword.
|
14
|
+
const canSkipParens = (args) => {
|
15
|
+
const stmts = args.body[0].body[0];
|
16
|
+
|
17
|
+
// return(
|
18
|
+
// # a
|
19
|
+
// b
|
20
|
+
// )
|
21
|
+
if (stmts.comments) {
|
22
|
+
return false;
|
23
|
+
}
|
24
|
+
|
25
|
+
const stmt = stmts.body[0];
|
26
|
+
|
27
|
+
// return (a or b)
|
28
|
+
if (stmt.type === "binary" && ["and", "or"].includes(stmt.body[1])) {
|
29
|
+
return false;
|
30
|
+
}
|
31
|
+
|
32
|
+
// return (not a)
|
33
|
+
if (stmt.type === "unary" && stmt.oper === "not") {
|
34
|
+
return false;
|
35
|
+
}
|
36
|
+
|
37
|
+
return true;
|
38
|
+
};
|
39
|
+
|
40
|
+
const printReturn = (path, opts, print) => {
|
41
|
+
let args = path.getValue().body[0].body[0];
|
42
|
+
let steps = ["body", 0, "body", 0];
|
43
|
+
|
44
|
+
if (args.body.length === 1) {
|
45
|
+
// If the body of the return contains parens, then just skip directly to the
|
46
|
+
// content of the parens so that we can skip printing parens if we don't
|
47
|
+
// want them.
|
48
|
+
if (args.body[0] && args.body[0].type === "paren" && canSkipParens(args)) {
|
49
|
+
args = args.body[0].body[0];
|
50
|
+
steps = steps.concat("body", 0, "body", 0);
|
51
|
+
}
|
52
|
+
|
53
|
+
// If we're returning an array literal that isn't a special array, single
|
54
|
+
// element array, or an empty array, then we want to grab the arguments so
|
55
|
+
// that we can print them out as if they were normal return arguments.
|
56
|
+
if (
|
57
|
+
args.body[0] &&
|
58
|
+
args.body[0].type === "array" &&
|
59
|
+
args.body[0].body[0] &&
|
60
|
+
args.body[0].body[0].body.length > 1 &&
|
61
|
+
["args", "args_add_star"].includes(args.body[0].body[0].type)
|
62
|
+
) {
|
63
|
+
steps = steps.concat("body", 0, "body", 0);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
// Now that we've established which actual node is the arguments to return,
|
68
|
+
// we grab it out of the path by diving down the steps that we've set up.
|
69
|
+
const parts = path.call.apply(path, [print].concat(steps));
|
70
|
+
|
71
|
+
// If we got the value straight out of the parens, then `parts` would only
|
72
|
+
// be a singular doc as opposed to an array.
|
73
|
+
const value = Array.isArray(parts) ? join(concat([",", line]), parts) : parts;
|
74
|
+
|
75
|
+
// We only get here if we have comments somewhere that would prevent us from
|
76
|
+
// skipping the parentheses.
|
77
|
+
if (args.body.length === 1 && args.body[0].type === "paren") {
|
78
|
+
return concat(["return", value]);
|
79
|
+
}
|
80
|
+
|
81
|
+
return group(
|
82
|
+
concat([
|
83
|
+
"return",
|
84
|
+
ifBreak(parts.length > 1 ? " [" : "(", " "),
|
85
|
+
indent(concat([softline, value])),
|
86
|
+
concat([softline, ifBreak(parts.length > 1 ? "]" : ")", "")])
|
87
|
+
])
|
88
|
+
);
|
89
|
+
};
|
90
|
+
|
91
|
+
module.exports = {
|
92
|
+
return: printReturn,
|
93
|
+
return0: literal("return")
|
94
|
+
};
|
@@ -10,7 +10,7 @@ const {
|
|
10
10
|
literalline,
|
11
11
|
softline,
|
12
12
|
trim
|
13
|
-
} = require("
|
13
|
+
} = require("../../prettier");
|
14
14
|
|
15
15
|
function printBodyStmt(path, opts, print) {
|
16
16
|
const [stmts, rescue, elseClause, ensure] = path.getValue().body;
|
@@ -30,6 +30,7 @@ function printBodyStmt(path, opts, print) {
|
|
30
30
|
|
31
31
|
if (elseClause) {
|
32
32
|
// Before Ruby 2.6, this piece of bodystmt was an explicit "else" node
|
33
|
+
/* istanbul ignore next */
|
33
34
|
const stmts =
|
34
35
|
elseClause.type === "else"
|
35
36
|
? path.call(print, "body", 2, "body", 0)
|
@@ -69,11 +70,7 @@ function printParen(path, opts, print) {
|
|
69
70
|
}
|
70
71
|
|
71
72
|
return group(
|
72
|
-
concat([
|
73
|
-
"(",
|
74
|
-
indent(concat([softline, contentDoc])),
|
75
|
-
concat([softline, ")"])
|
76
|
-
])
|
73
|
+
concat(["(", indent(concat([softline, contentDoc])), softline, ")"])
|
77
74
|
);
|
78
75
|
}
|
79
76
|
|
@@ -123,12 +120,12 @@ module.exports = {
|
|
123
120
|
if (lineNo === null) {
|
124
121
|
parts.push(printed);
|
125
122
|
} else if (
|
126
|
-
stmt.
|
123
|
+
stmt.sl - lineNo > 1 ||
|
127
124
|
[stmt.type, stmts[index - 1].type].includes("access_ctrl")
|
128
125
|
) {
|
129
126
|
parts.push(hardline, hardline, printed);
|
130
127
|
} else if (
|
131
|
-
stmt.
|
128
|
+
stmt.sl !== lineNo ||
|
132
129
|
path.getParentNode().type !== "string_embexpr"
|
133
130
|
) {
|
134
131
|
parts.push(hardline, printed);
|
@@ -136,7 +133,7 @@ module.exports = {
|
|
136
133
|
parts.push("; ", printed);
|
137
134
|
}
|
138
135
|
|
139
|
-
lineNo = stmt.
|
136
|
+
lineNo = stmt.el;
|
140
137
|
});
|
141
138
|
|
142
139
|
return concat(parts);
|
@@ -6,7 +6,7 @@ const {
|
|
6
6
|
literalline,
|
7
7
|
softline,
|
8
8
|
join
|
9
|
-
} = require("
|
9
|
+
} = require("../../prettier");
|
10
10
|
|
11
11
|
// If there is some part of this string that matches an escape sequence or that
|
12
12
|
// contains the interpolation pattern ("#{"), then we are locked into whichever
|
@@ -31,17 +31,10 @@ function isSingleQuotable(node) {
|
|
31
31
|
|
32
32
|
const quotePattern = new RegExp("\\\\([\\s\\S])|(['\"])", "g");
|
33
33
|
|
34
|
-
function normalizeQuotes(content, enclosingQuote
|
35
|
-
const replaceOther = originalQuote === '"';
|
36
|
-
const otherQuote = enclosingQuote === '"' ? "'" : '"';
|
37
|
-
|
34
|
+
function normalizeQuotes(content, enclosingQuote) {
|
38
35
|
// Escape and unescape single and double quotes as needed to be able to
|
39
36
|
// enclose `content` with `enclosingQuote`.
|
40
37
|
return content.replace(quotePattern, (match, escaped, quote) => {
|
41
|
-
if (replaceOther && escaped === otherQuote) {
|
42
|
-
return escaped;
|
43
|
-
}
|
44
|
-
|
45
38
|
if (quote === enclosingQuote) {
|
46
39
|
return `\\${quote}`;
|
47
40
|
}
|
@@ -97,12 +90,34 @@ function printDynaSymbol(path, opts, print) {
|
|
97
90
|
return concat([":", quote].concat(path.map(print, "body")).concat(quote));
|
98
91
|
}
|
99
92
|
|
93
|
+
function printStringConcat(path, opts, print) {
|
94
|
+
const [leftDoc, rightDoc] = path.map(print, "body");
|
95
|
+
|
96
|
+
return group(concat([leftDoc, " \\", indent(concat([hardline, rightDoc]))]));
|
97
|
+
}
|
98
|
+
|
100
99
|
// Prints out an interpolated variable in the string by converting it into an
|
101
100
|
// embedded expression.
|
102
101
|
function printStringDVar(path, opts, print) {
|
103
102
|
return concat(["#{", path.call(print, "body", 0), "}"]);
|
104
103
|
}
|
105
104
|
|
105
|
+
function printStringEmbExpr(path, opts, print) {
|
106
|
+
const parts = path.call(print, "body", 0);
|
107
|
+
|
108
|
+
// If the interpolated expression is inside of a heredoc or an xstring
|
109
|
+
// literal (a string that gets sent to the command line) then we don't want
|
110
|
+
// to automatically indent, as this can lead to some very odd looking
|
111
|
+
// expressions
|
112
|
+
if (["heredoc", "xstring_literal"].includes(path.getParentNode().type)) {
|
113
|
+
return concat(["#{", parts, "}"]);
|
114
|
+
}
|
115
|
+
|
116
|
+
return group(
|
117
|
+
concat(["#{", indent(concat([softline, parts])), concat([softline, "}"])])
|
118
|
+
);
|
119
|
+
}
|
120
|
+
|
106
121
|
// Prints out a literal string. This function does its best to respect the
|
107
122
|
// wishes of the user with regards to single versus double quotes, but if the
|
108
123
|
// string contains any escape expressions then it will just keep the original
|
@@ -131,10 +146,7 @@ function printStringLiteral(path, { rubySingleQuote }, print) {
|
|
131
146
|
}
|
132
147
|
|
133
148
|
// In this case, the part of the string is just regular string content
|
134
|
-
return join(
|
135
|
-
literalline,
|
136
|
-
normalizeQuotes(part.body, quote, node.quote).split("\n")
|
137
|
-
);
|
149
|
+
return join(literalline, normalizeQuotes(part.body, quote).split("\n"));
|
138
150
|
});
|
139
151
|
|
140
152
|
return concat([quote].concat(parts).concat(getClosingQuote(quote)));
|
@@ -155,30 +167,9 @@ function printXStringLiteral(path, opts, print) {
|
|
155
167
|
module.exports = {
|
156
168
|
"@CHAR": printChar,
|
157
169
|
dyna_symbol: printDynaSymbol,
|
158
|
-
string_concat:
|
159
|
-
group(
|
160
|
-
concat([
|
161
|
-
path.call(print, "body", 0),
|
162
|
-
" \\",
|
163
|
-
indent(concat([hardline, path.call(print, "body", 1)]))
|
164
|
-
])
|
165
|
-
),
|
170
|
+
string_concat: printStringConcat,
|
166
171
|
string_dvar: printStringDVar,
|
167
|
-
string_embexpr:
|
168
|
-
const parts = path.call(print, "body", 0);
|
169
|
-
|
170
|
-
// If the interpolated expression is inside of a heredoc or an xstring
|
171
|
-
// literal (a string that gets sent to the command line) then we don't want
|
172
|
-
// to automatically indent, as this can lead to some very odd looking
|
173
|
-
// expressions
|
174
|
-
if (["heredoc", "xstring_literal"].includes(path.getParentNode().type)) {
|
175
|
-
return concat(["#{", parts, "}"]);
|
176
|
-
}
|
177
|
-
|
178
|
-
return group(
|
179
|
-
concat(["#{", indent(concat([softline, parts])), concat([softline, "}"])])
|
180
|
-
);
|
181
|
-
},
|
172
|
+
string_embexpr: printStringEmbExpr,
|
182
173
|
string_literal: printStringLiteral,
|
183
174
|
symbol_literal: printSymbolLiteral,
|
184
175
|
xstring_literal: printXStringLiteral
|