prettier 1.0.1 → 1.2.3
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 +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
|
+
};
|