prettier 1.0.1 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +6 -1
- data/lib/prettier.rb +2 -2
- data/node_modules/prettier/index.js +54 -54
- data/package.json +4 -2
- data/src/{ruby.js → plugin.js} +2 -2
- data/src/{embed.js → ruby/embed.js} +2 -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/{nodes → ruby/nodes}/blocks.js +3 -3
- data/src/{nodes → ruby/nodes}/calls.js +54 -11
- 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/{nodes → ruby/nodes}/hooks.js +2 -2
- data/src/{nodes → ruby/nodes}/ints.js +0 -0
- data/src/{nodes → ruby/nodes}/lambdas.js +2 -2
- data/src/ruby/nodes/loops.js +104 -0
- data/src/{nodes → ruby/nodes}/massign.js +8 -1
- data/src/{nodes → ruby/nodes}/methods.js +34 -6
- data/src/{nodes → ruby/nodes}/operators.js +2 -2
- data/src/{nodes → ruby/nodes}/params.js +9 -2
- data/src/{nodes → ruby/nodes}/patterns.js +45 -10
- data/src/ruby/nodes/regexp.js +56 -0
- data/src/{nodes → ruby/nodes}/rescue.js +2 -2
- data/src/ruby/nodes/return.js +98 -0
- data/src/{nodes → ruby/nodes}/statements.js +1 -1
- data/src/{nodes → ruby/nodes}/strings.js +1 -1
- 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} +2 -2
- data/src/{parser.rb → ruby/parser.rb} +323 -317
- data/src/{printer.js → ruby/printer.js} +46 -1
- data/src/{toProc.js → ruby/toProc.js} +0 -0
- 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 +11 -0
- data/src/utils/noIndent.js +10 -0
- data/src/utils/skipAssignIndent.js +10 -0
- metadata +48 -41
- data/src/nodes/case.js +0 -61
- data/src/nodes/commands.js +0 -91
- data/src/nodes/loops.js +0 -101
- data/src/nodes/regexp.js +0 -49
- data/src/nodes/return.js +0 -72
@@ -1,5 +1,5 @@
|
|
1
|
-
const { concat, group, lineSuffix, join } = require("
|
2
|
-
const { literalLineNoBreak } = require("
|
1
|
+
const { concat, group, lineSuffix, join } = require("../../prettier");
|
2
|
+
const { literalLineNoBreak } = require("../../utils");
|
3
3
|
|
4
4
|
function printHeredoc(path, opts, print) {
|
5
5
|
const { body, ending } = path.getValue();
|
@@ -1,5 +1,5 @@
|
|
1
|
-
const { concat, group, indent, line } = require("
|
2
|
-
const { isEmptyStmts } = require("
|
1
|
+
const { concat, group, indent, line } = require("../../prettier");
|
2
|
+
const { isEmptyStmts } = require("../../utils");
|
3
3
|
|
4
4
|
// The `BEGIN` and `END` keywords are used to hook into the Ruby process. Any
|
5
5
|
// `BEGIN` blocks are executed right when the process starts up, and the `END`
|
File without changes
|
@@ -1,5 +1,5 @@
|
|
1
|
-
const { concat, group, ifBreak, indent, line } = require("
|
2
|
-
const { hasAncestor } = require("
|
1
|
+
const { concat, group, ifBreak, indent, line } = require("../../prettier");
|
2
|
+
const { hasAncestor } = require("../../utils");
|
3
3
|
|
4
4
|
// We can have our params coming in as the first child of the main lambda node,
|
5
5
|
// or if we have them wrapped in parens then they'll be one level deeper. Even
|
@@ -0,0 +1,104 @@
|
|
1
|
+
const {
|
2
|
+
align,
|
3
|
+
breakParent,
|
4
|
+
concat,
|
5
|
+
group,
|
6
|
+
hardline,
|
7
|
+
ifBreak,
|
8
|
+
indent,
|
9
|
+
join,
|
10
|
+
softline
|
11
|
+
} = require("../../prettier");
|
12
|
+
|
13
|
+
const { containsAssignment } = require("../../utils");
|
14
|
+
const inlineEnsureParens = require("../../utils/inlineEnsureParens");
|
15
|
+
|
16
|
+
function printLoop(keyword, modifier) {
|
17
|
+
return function printLoopWithOptions(path, { rubyModifier }, print) {
|
18
|
+
const [_predicate, stmts] = path.getValue().body;
|
19
|
+
|
20
|
+
// If the only statement inside this while loop is a void statement, then we
|
21
|
+
// can shorten to just displaying the predicate and then a semicolon.
|
22
|
+
if (
|
23
|
+
stmts.body.length === 1 &&
|
24
|
+
stmts.body[0].type === "void_stmt" &&
|
25
|
+
!stmts.body[0].comments
|
26
|
+
) {
|
27
|
+
return group(
|
28
|
+
concat([
|
29
|
+
keyword,
|
30
|
+
" ",
|
31
|
+
path.call(print, "body", 0),
|
32
|
+
ifBreak(softline, "; "),
|
33
|
+
"end"
|
34
|
+
])
|
35
|
+
);
|
36
|
+
}
|
37
|
+
|
38
|
+
const inlineLoop = concat(
|
39
|
+
inlineEnsureParens(path, [
|
40
|
+
path.call(print, "body", 1),
|
41
|
+
` ${keyword} `,
|
42
|
+
path.call(print, "body", 0)
|
43
|
+
])
|
44
|
+
);
|
45
|
+
|
46
|
+
// If we're in the modifier form and we're modifying a `begin`, then this is
|
47
|
+
// a special case where we need to explicitly use the modifier form because
|
48
|
+
// otherwise the semantic meaning changes. This looks like:
|
49
|
+
//
|
50
|
+
// begin
|
51
|
+
// foo
|
52
|
+
// end while bar
|
53
|
+
//
|
54
|
+
// The above is effectively a `do...while` loop (which we don't have in
|
55
|
+
// ruby).
|
56
|
+
if (modifier && path.getValue().body[1].type === "begin") {
|
57
|
+
return inlineLoop;
|
58
|
+
}
|
59
|
+
|
60
|
+
const blockLoop = concat([
|
61
|
+
concat([
|
62
|
+
`${keyword} `,
|
63
|
+
align(keyword.length + 1, path.call(print, "body", 0))
|
64
|
+
]),
|
65
|
+
indent(concat([softline, path.call(print, "body", 1)])),
|
66
|
+
concat([softline, "end"])
|
67
|
+
]);
|
68
|
+
|
69
|
+
// If we're disallowing inline loops or if the predicate of the loop
|
70
|
+
// contains an assignment (in which case we can't know for certain that that
|
71
|
+
// assignment doesn't impact the statements inside the loop) then we can't
|
72
|
+
// use the modifier form and we must use the block form.
|
73
|
+
if (!rubyModifier || containsAssignment(path.getValue().body[0])) {
|
74
|
+
return concat([breakParent, blockLoop]);
|
75
|
+
}
|
76
|
+
|
77
|
+
return group(ifBreak(blockLoop, inlineLoop));
|
78
|
+
};
|
79
|
+
}
|
80
|
+
|
81
|
+
function printFor(path, opts, print) {
|
82
|
+
const [varDoc, rangeDoc, stmtsDoc] = path.map(print, "body");
|
83
|
+
const varsDoc =
|
84
|
+
path.getValue().body[0].type === "mlhs" ? join(", ", varDoc) : varDoc;
|
85
|
+
|
86
|
+
return group(
|
87
|
+
concat([
|
88
|
+
"for ",
|
89
|
+
varsDoc,
|
90
|
+
" in ",
|
91
|
+
rangeDoc,
|
92
|
+
indent(concat([hardline, stmtsDoc])),
|
93
|
+
concat([hardline, "end"])
|
94
|
+
])
|
95
|
+
);
|
96
|
+
}
|
97
|
+
|
98
|
+
module.exports = {
|
99
|
+
while: printLoop("while", false),
|
100
|
+
while_mod: printLoop("while", true),
|
101
|
+
until: printLoop("until", false),
|
102
|
+
until_mod: printLoop("until", true),
|
103
|
+
for: printFor
|
104
|
+
};
|
@@ -1,4 +1,11 @@
|
|
1
|
-
const {
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
indent,
|
5
|
+
join,
|
6
|
+
line,
|
7
|
+
softline
|
8
|
+
} = require("../../prettier");
|
2
9
|
|
3
10
|
function printMAssign(path, opts, print) {
|
4
11
|
let right = path.call(print, "body", 1);
|
@@ -1,5 +1,4 @@
|
|
1
|
-
const { concat, group, hardline, indent } = require("
|
2
|
-
const { first } = require("../utils");
|
1
|
+
const { concat, group, hardline, indent, line } = require("../../prettier");
|
3
2
|
|
4
3
|
function printMethod(offset) {
|
5
4
|
return function printMethodWithOffset(path, opts, print) {
|
@@ -16,8 +15,7 @@ function printMethod(offset) {
|
|
16
15
|
}
|
17
16
|
|
18
17
|
// In case there are no parens but there are arguments
|
19
|
-
const parens =
|
20
|
-
params.type === "params" && params.body.some((paramType) => paramType);
|
18
|
+
const parens = params.type === "params" && params.body.some((type) => type);
|
21
19
|
|
22
20
|
declaration.push(
|
23
21
|
path.call(print, "body", offset),
|
@@ -48,8 +46,38 @@ function printMethod(offset) {
|
|
48
46
|
};
|
49
47
|
}
|
50
48
|
|
49
|
+
function printSingleLineMethod(path, opts, print) {
|
50
|
+
let paramsNode = path.getValue().body[1];
|
51
|
+
let paramsDoc = "";
|
52
|
+
|
53
|
+
if (paramsNode) {
|
54
|
+
if (paramsNode.body[0].type === "params") {
|
55
|
+
paramsNode = paramsNode.body[0];
|
56
|
+
}
|
57
|
+
|
58
|
+
if (paramsNode.type === "params" && paramsNode.body.some((type) => type)) {
|
59
|
+
paramsDoc = path.call(print, "body", 1);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
return group(
|
64
|
+
concat([
|
65
|
+
"def ",
|
66
|
+
path.call(print, "body", 0),
|
67
|
+
paramsDoc,
|
68
|
+
" =",
|
69
|
+
indent(group(concat([line, path.call(print, "body", 2)])))
|
70
|
+
])
|
71
|
+
);
|
72
|
+
}
|
73
|
+
|
74
|
+
function printAccessControl(path, opts, print) {
|
75
|
+
return path.call(print, "body", 0);
|
76
|
+
}
|
77
|
+
|
51
78
|
module.exports = {
|
52
|
-
access_ctrl:
|
79
|
+
access_ctrl: printAccessControl,
|
53
80
|
def: printMethod(0),
|
54
|
-
defs: printMethod(2)
|
81
|
+
defs: printMethod(2),
|
82
|
+
defsl: printSingleLineMethod
|
55
83
|
};
|
@@ -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) {
|
@@ -1,4 +1,13 @@
|
|
1
|
-
const {
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
hardline,
|
5
|
+
indent,
|
6
|
+
join,
|
7
|
+
line
|
8
|
+
} = require("../../prettier");
|
9
|
+
|
10
|
+
const patterns = ["aryptn", "binary", "fndptn", "hshptn", "rassign"];
|
2
11
|
|
3
12
|
function printPatternArg(path, opts, print) {
|
4
13
|
// Pinning is a really special syntax in pattern matching that's not really
|
@@ -34,10 +43,7 @@ function printAryPtn(path, opts, print) {
|
|
34
43
|
|
35
44
|
args = group(join(concat([",", line]), args));
|
36
45
|
|
37
|
-
if (
|
38
|
-
constant ||
|
39
|
-
["aryptn", "binary", "hshptn"].includes(path.getParentNode().type)
|
40
|
-
) {
|
46
|
+
if (constant || patterns.includes(path.getParentNode().type)) {
|
41
47
|
args = concat(["[", args, "]"]);
|
42
48
|
}
|
43
49
|
|
@@ -48,6 +54,22 @@ function printAryPtn(path, opts, print) {
|
|
48
54
|
return args;
|
49
55
|
}
|
50
56
|
|
57
|
+
function printFndPtn(path, opts, print) {
|
58
|
+
const [constant] = path.getValue().body;
|
59
|
+
|
60
|
+
let args = [concat(["*", path.call(print, "body", 1)])]
|
61
|
+
.concat(path.map(print, "body", 2))
|
62
|
+
.concat(concat(["*", path.call(print, "body", 3)]));
|
63
|
+
|
64
|
+
args = concat(["[", group(join(concat([",", line]), args)), "]"]);
|
65
|
+
|
66
|
+
if (constant) {
|
67
|
+
return concat([path.call(print, "body", 0), args]);
|
68
|
+
}
|
69
|
+
|
70
|
+
return args;
|
71
|
+
}
|
72
|
+
|
51
73
|
function printHshPtn(path, opts, print) {
|
52
74
|
const [constant, keyValuePairs, keyValueRest] = path.getValue().body;
|
53
75
|
let args = [];
|
@@ -80,10 +102,8 @@ function printHshPtn(path, opts, print) {
|
|
80
102
|
|
81
103
|
if (constant) {
|
82
104
|
args = concat(["[", args, "]"]);
|
83
|
-
} else if (
|
84
|
-
["
|
85
|
-
) {
|
86
|
-
args = concat(["{", args, "}"]);
|
105
|
+
} else if (patterns.includes(path.getParentNode().type)) {
|
106
|
+
args = concat(["{ ", args, " }"]);
|
87
107
|
}
|
88
108
|
|
89
109
|
if (constant) {
|
@@ -111,8 +131,23 @@ function printIn(path, opts, print) {
|
|
111
131
|
return group(concat(parts));
|
112
132
|
}
|
113
133
|
|
134
|
+
function printRAssign(path, opts, print) {
|
135
|
+
const { keyword } = path.getValue();
|
136
|
+
const [leftDoc, rightDoc] = path.map(print, "body");
|
137
|
+
|
138
|
+
return group(
|
139
|
+
concat([
|
140
|
+
leftDoc,
|
141
|
+
keyword ? " in" : " =>",
|
142
|
+
group(indent(concat([line, rightDoc])))
|
143
|
+
])
|
144
|
+
);
|
145
|
+
}
|
146
|
+
|
114
147
|
module.exports = {
|
115
148
|
aryptn: printAryPtn,
|
149
|
+
fndptn: printFndPtn,
|
116
150
|
hshptn: printHshPtn,
|
117
|
-
in: printIn
|
151
|
+
in: printIn,
|
152
|
+
rassign: printRAssign
|
118
153
|
};
|
@@ -0,0 +1,56 @@
|
|
1
|
+
const { concat } = require("../../prettier");
|
2
|
+
const { hasAncestor } = require("../../utils");
|
3
|
+
|
4
|
+
function hasContent(node, pattern) {
|
5
|
+
return node.body.some(
|
6
|
+
(child) => child.type === "@tstring_content" && pattern.test(child.body)
|
7
|
+
);
|
8
|
+
}
|
9
|
+
|
10
|
+
// If the first part of this regex is plain string content, we have a space
|
11
|
+
// or an =, and we're contained within a command or command_call node, then we
|
12
|
+
// want to use braces because otherwise we could end up with an ambiguous
|
13
|
+
// operator, e.g. foo / bar/ or foo /=bar/
|
14
|
+
function forwardSlashIsAmbiguous(path) {
|
15
|
+
const node = path.getValue();
|
16
|
+
const firstChildNode = node.body[0];
|
17
|
+
|
18
|
+
return (
|
19
|
+
firstChildNode &&
|
20
|
+
firstChildNode.type === "@tstring_content" &&
|
21
|
+
[" ", "="].includes(firstChildNode.body[0]) &&
|
22
|
+
hasAncestor(path, ["command", "command_call"])
|
23
|
+
);
|
24
|
+
}
|
25
|
+
|
26
|
+
// This function is responsible for printing out regexp_literal nodes. They can
|
27
|
+
// either use the special %r literal syntax or they can use forward slashes. At
|
28
|
+
// the end of either of those they can have modifiers like m or x that have
|
29
|
+
// special meaning for the regex engine.
|
30
|
+
//
|
31
|
+
// We favor the use of forward slashes unless the regex contains a forward slash
|
32
|
+
// itself. In that case we switch over to using %r with braces.
|
33
|
+
function printRegexpLiteral(path, opts, print) {
|
34
|
+
const node = path.getValue();
|
35
|
+
const docs = path.map(print, "body");
|
36
|
+
|
37
|
+
// We should use braces if using a forward slash would be ambiguous in the
|
38
|
+
// current context or if there's a forward slash in the content of the regexp.
|
39
|
+
const useBraces = forwardSlashIsAmbiguous(path) || hasContent(node, /\//);
|
40
|
+
|
41
|
+
// If we should be using braces but we have braces in the body of the regexp,
|
42
|
+
// then we're just going to resort to using whatever the original content was.
|
43
|
+
if (useBraces && hasContent(node, /[{}]/)) {
|
44
|
+
return concat([node.beging].concat(docs).concat(node.ending));
|
45
|
+
}
|
46
|
+
|
47
|
+
return concat(
|
48
|
+
[useBraces ? "%r{" : "/"]
|
49
|
+
.concat(docs)
|
50
|
+
.concat(useBraces ? "}" : "/", node.ending.slice(1))
|
51
|
+
);
|
52
|
+
}
|
53
|
+
|
54
|
+
module.exports = {
|
55
|
+
regexp_literal: printRegexpLiteral
|
56
|
+
};
|
@@ -0,0 +1,98 @@
|
|
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) {
|
45
|
+
return "return";
|
46
|
+
}
|
47
|
+
|
48
|
+
if (args.body.length === 1) {
|
49
|
+
// If the body of the return contains parens, then just skip directly to the
|
50
|
+
// content of the parens so that we can skip printing parens if we don't
|
51
|
+
// want them.
|
52
|
+
if (args.body[0] && args.body[0].type === "paren" && canSkipParens(args)) {
|
53
|
+
args = args.body[0].body[0];
|
54
|
+
steps = steps.concat("body", 0, "body", 0);
|
55
|
+
}
|
56
|
+
|
57
|
+
// If we're returning an array literal that isn't a special array, single
|
58
|
+
// element array, or an empty array, then we want to grab the arguments so
|
59
|
+
// that we can print them out as if they were normal return arguments.
|
60
|
+
if (
|
61
|
+
args.body[0] &&
|
62
|
+
args.body[0].type === "array" &&
|
63
|
+
args.body[0].body[0] &&
|
64
|
+
args.body[0].body[0].body.length > 1 &&
|
65
|
+
["args", "args_add_star"].includes(args.body[0].body[0].type)
|
66
|
+
) {
|
67
|
+
steps = steps.concat("body", 0, "body", 0);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
// Now that we've established which actual node is the arguments to return,
|
72
|
+
// we grab it out of the path by diving down the steps that we've set up.
|
73
|
+
const parts = path.call.apply(path, [print].concat(steps));
|
74
|
+
|
75
|
+
// If we got the value straight out of the parens, then `parts` would only
|
76
|
+
// be a singular doc as opposed to an array.
|
77
|
+
const value = Array.isArray(parts) ? join(concat([",", line]), parts) : parts;
|
78
|
+
|
79
|
+
// We only get here if we have comments somewhere that would prevent us from
|
80
|
+
// skipping the parentheses.
|
81
|
+
if (args.body.length === 1 && args.body[0].type === "paren") {
|
82
|
+
return concat(["return", value]);
|
83
|
+
}
|
84
|
+
|
85
|
+
return group(
|
86
|
+
concat([
|
87
|
+
"return",
|
88
|
+
ifBreak(parts.length > 1 ? " [" : "(", " "),
|
89
|
+
indent(concat([softline, value])),
|
90
|
+
concat([softline, ifBreak(parts.length > 1 ? "]" : ")", "")])
|
91
|
+
])
|
92
|
+
);
|
93
|
+
};
|
94
|
+
|
95
|
+
module.exports = {
|
96
|
+
return: printReturn,
|
97
|
+
return0: literal("return")
|
98
|
+
};
|