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
data/src/nodes/case.js
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
const {
|
2
|
-
align,
|
3
|
-
concat,
|
4
|
-
fill,
|
5
|
-
group,
|
6
|
-
hardline,
|
7
|
-
indent,
|
8
|
-
line
|
9
|
-
} = require("../prettier");
|
10
|
-
|
11
|
-
module.exports = {
|
12
|
-
case: (path, opts, print) => {
|
13
|
-
const statement = ["case"];
|
14
|
-
|
15
|
-
// You don't need to explicitly have something to test against in a case
|
16
|
-
// statement (without it it effectively becomes an if/elsif chain).
|
17
|
-
if (path.getValue().body[0]) {
|
18
|
-
statement.push(" ", path.call(print, "body", 0));
|
19
|
-
}
|
20
|
-
|
21
|
-
return concat(
|
22
|
-
statement.concat([hardline, path.call(print, "body", 1), hardline, "end"])
|
23
|
-
);
|
24
|
-
},
|
25
|
-
when: (path, opts, print) => {
|
26
|
-
const [_preds, _stmts, addition] = path.getValue().body;
|
27
|
-
|
28
|
-
// The `fill` builder command expects an array of docs alternating with
|
29
|
-
// line breaks. This is so it can loop through and determine where to break.
|
30
|
-
const preds = fill(
|
31
|
-
path.call(print, "body", 0).reduce((accum, pred, index) => {
|
32
|
-
if (index === 0) {
|
33
|
-
return [pred];
|
34
|
-
}
|
35
|
-
|
36
|
-
// Pull off the last element and make it concat with a comma so that
|
37
|
-
// we can maintain alternating lines and docs.
|
38
|
-
return accum
|
39
|
-
.slice(0, -1)
|
40
|
-
.concat([concat([accum[accum.length - 1], ","]), line, pred]);
|
41
|
-
}, null)
|
42
|
-
);
|
43
|
-
|
44
|
-
const stmts = path.call(print, "body", 1);
|
45
|
-
const parts = [concat(["when ", align("when ".length, preds)])];
|
46
|
-
|
47
|
-
// It's possible in a when to just have empty void statements, in which case
|
48
|
-
// we would skip adding the body.
|
49
|
-
if (!stmts.parts.every((part) => !part)) {
|
50
|
-
parts.push(indent(concat([hardline, stmts])));
|
51
|
-
}
|
52
|
-
|
53
|
-
// This is the next clause on the case statement, either another `when` or
|
54
|
-
// an `else` clause.
|
55
|
-
if (addition) {
|
56
|
-
parts.push(hardline, path.call(print, "body", 2));
|
57
|
-
}
|
58
|
-
|
59
|
-
return group(concat(parts));
|
60
|
-
}
|
61
|
-
};
|
data/src/nodes/commands.js
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
const {
|
2
|
-
align,
|
3
|
-
concat,
|
4
|
-
group,
|
5
|
-
ifBreak,
|
6
|
-
indent,
|
7
|
-
join,
|
8
|
-
line,
|
9
|
-
softline
|
10
|
-
} = require("../prettier");
|
11
|
-
const { docLength, makeCall } = require("../utils");
|
12
|
-
|
13
|
-
const hasDef = (node) =>
|
14
|
-
node.body[1].type === "args_add_block" &&
|
15
|
-
node.body[1].body[0].type === "args" &&
|
16
|
-
node.body[1].body[0].body[0] &&
|
17
|
-
["def", "defs"].includes(node.body[1].body[0].body[0].type);
|
18
|
-
|
19
|
-
// Very special handling case for rspec matchers. In general with rspec matchers
|
20
|
-
// you expect to see something like:
|
21
|
-
//
|
22
|
-
// expect(foo).to receive(:bar).with(
|
23
|
-
// 'one',
|
24
|
-
// 'two',
|
25
|
-
// 'three',
|
26
|
-
// 'four',
|
27
|
-
// 'five'
|
28
|
-
// )
|
29
|
-
//
|
30
|
-
// In this case the arguments are aligned to the left side as opposed to being
|
31
|
-
// aligned with the `receive` call.
|
32
|
-
const skipArgsAlign = (path) =>
|
33
|
-
["to", "not_to"].includes(path.getValue().body[2].body);
|
34
|
-
|
35
|
-
// If there is a ternary argument to a command and it's going to get broken
|
36
|
-
// into multiple lines, then we're going to have to use parentheses around the
|
37
|
-
// command in order to make sure operator precedence doesn't get messed up.
|
38
|
-
const hasTernaryArg = (path) =>
|
39
|
-
path.getValue().body[1].body[0].body.some((node) => node.type === "ifop");
|
40
|
-
|
41
|
-
module.exports = {
|
42
|
-
command: (path, opts, print) => {
|
43
|
-
const command = path.call(print, "body", 0);
|
44
|
-
const joinedArgs = join(concat([",", line]), path.call(print, "body", 1));
|
45
|
-
|
46
|
-
const hasTernary = hasTernaryArg(path);
|
47
|
-
let breakArgs;
|
48
|
-
|
49
|
-
if (hasTernary) {
|
50
|
-
breakArgs = indent(concat([softline, joinedArgs]));
|
51
|
-
} else if (hasDef(path.getValue())) {
|
52
|
-
breakArgs = joinedArgs;
|
53
|
-
} else {
|
54
|
-
breakArgs = align(command.length + 1, joinedArgs);
|
55
|
-
}
|
56
|
-
|
57
|
-
return group(
|
58
|
-
ifBreak(
|
59
|
-
concat([
|
60
|
-
command,
|
61
|
-
hasTernary ? "(" : " ",
|
62
|
-
breakArgs,
|
63
|
-
hasTernary ? concat([softline, ")"]) : ""
|
64
|
-
]),
|
65
|
-
concat([command, " ", joinedArgs])
|
66
|
-
)
|
67
|
-
);
|
68
|
-
},
|
69
|
-
command_call: (path, opts, print) => {
|
70
|
-
const parts = [
|
71
|
-
path.call(print, "body", 0),
|
72
|
-
makeCall(path, opts, print),
|
73
|
-
path.call(print, "body", 2)
|
74
|
-
];
|
75
|
-
|
76
|
-
if (!path.getValue().body[3]) {
|
77
|
-
return concat(parts);
|
78
|
-
}
|
79
|
-
|
80
|
-
parts.push(" ");
|
81
|
-
|
82
|
-
const joinedArgs = join(concat([",", line]), path.call(print, "body", 3));
|
83
|
-
const breakArgs = skipArgsAlign(path)
|
84
|
-
? joinedArgs
|
85
|
-
: align(docLength(concat(parts)), joinedArgs);
|
86
|
-
|
87
|
-
return group(
|
88
|
-
ifBreak(concat(parts.concat(breakArgs)), concat(parts.concat(joinedArgs)))
|
89
|
-
);
|
90
|
-
}
|
91
|
-
};
|
data/src/nodes/hooks.js
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
const { concat, group, indent, line } = require("../prettier");
|
2
|
-
const { isEmptyStmts } = require("../utils");
|
3
|
-
|
4
|
-
// The `BEGIN` and `END` keywords are used to hook into the Ruby process. Any
|
5
|
-
// `BEGIN` blocks are executed right when the process starts up, and the `END`
|
6
|
-
// blocks are executed right before exiting.
|
7
|
-
//
|
8
|
-
// BEGIN {
|
9
|
-
// # content goes here
|
10
|
-
// }
|
11
|
-
//
|
12
|
-
// END {
|
13
|
-
// # content goes here
|
14
|
-
// }
|
15
|
-
//
|
16
|
-
// Interesting side note, you don't use `do...end` blocks with these hooks. Both
|
17
|
-
// nodes contain one child which is a `stmts` node.
|
18
|
-
function printHook(name) {
|
19
|
-
return function printHookWithName(path, opts, print) {
|
20
|
-
const stmtsNode = path.getValue().body[1];
|
21
|
-
const printedStmts = path.call(print, "body", 1);
|
22
|
-
|
23
|
-
const parts = [
|
24
|
-
name,
|
25
|
-
" ",
|
26
|
-
path.call(print, "body", 0),
|
27
|
-
indent(concat([line, printedStmts])),
|
28
|
-
concat([line, "}"])
|
29
|
-
];
|
30
|
-
|
31
|
-
// If there are no statements but there are comments, then we want to skip
|
32
|
-
// printing the newline so that we don't end up with multiple spaces.
|
33
|
-
if (isEmptyStmts(stmtsNode) && stmtsNode.comments) {
|
34
|
-
parts[1] = indent(printedStmts);
|
35
|
-
}
|
36
|
-
|
37
|
-
return group(concat(parts));
|
38
|
-
};
|
39
|
-
}
|
40
|
-
|
41
|
-
module.exports = {
|
42
|
-
BEGIN: printHook("BEGIN"),
|
43
|
-
END: printHook("END")
|
44
|
-
};
|
data/src/nodes/return.js
DELETED
@@ -1,72 +0,0 @@
|
|
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 the `and` or `or` operator,
|
13
|
-
// because they have low enough operator precedence that you need to explicitly
|
14
|
-
// keep them in there.
|
15
|
-
const canSkipParens = (args) => {
|
16
|
-
const statement = args.body[0].body[0].body[0];
|
17
|
-
return (
|
18
|
-
statement.type !== "binary" || !["and", "or"].includes(statement.body[1])
|
19
|
-
);
|
20
|
-
};
|
21
|
-
|
22
|
-
const printReturn = (path, opts, print) => {
|
23
|
-
let args = path.getValue().body[0].body[0];
|
24
|
-
let steps = ["body", 0, "body", 0];
|
25
|
-
|
26
|
-
if (!args) {
|
27
|
-
return "return";
|
28
|
-
}
|
29
|
-
|
30
|
-
// If the body of the return contains parens, then just skip directly to the
|
31
|
-
// content of the parens so that we can skip printing parens if we don't
|
32
|
-
// want them.
|
33
|
-
if (args.body[0] && args.body[0].type === "paren" && canSkipParens(args)) {
|
34
|
-
args = args.body[0].body[0];
|
35
|
-
steps = steps.concat("body", 0, "body", 0);
|
36
|
-
}
|
37
|
-
|
38
|
-
// If we're returning an array literal that isn't a special array, single
|
39
|
-
// element array, or an empty array, then we want to grab the arguments so
|
40
|
-
// that we can print them out as if they were normal return arguments.
|
41
|
-
if (
|
42
|
-
args.body[0] &&
|
43
|
-
args.body[0].type === "array" &&
|
44
|
-
args.body[0].body[0] &&
|
45
|
-
args.body[0].body[0].body.length > 1 &&
|
46
|
-
["args", "args_add_star"].includes(args.body[0].body[0].type)
|
47
|
-
) {
|
48
|
-
steps = steps.concat("body", 0, "body", 0);
|
49
|
-
}
|
50
|
-
|
51
|
-
// Now that we've established which actual node is the arguments to return,
|
52
|
-
// we grab it out of the path by diving down the steps that we've set up.
|
53
|
-
const parts = path.call.apply(path, [print].concat(steps));
|
54
|
-
|
55
|
-
// If we got the value straight out of the parens, then `parts` would only
|
56
|
-
// be a singular doc as opposed to an array.
|
57
|
-
const value = Array.isArray(parts) ? join(concat([",", line]), parts) : parts;
|
58
|
-
|
59
|
-
return group(
|
60
|
-
concat([
|
61
|
-
"return",
|
62
|
-
ifBreak(parts.length > 1 ? " [" : "(", " "),
|
63
|
-
indent(concat([softline, value])),
|
64
|
-
concat([softline, ifBreak(parts.length > 1 ? "]" : ")", "")])
|
65
|
-
])
|
66
|
-
);
|
67
|
-
};
|
68
|
-
|
69
|
-
module.exports = {
|
70
|
-
return: printReturn,
|
71
|
-
return0: literal("return")
|
72
|
-
};
|