prettier 0.12.2 → 0.12.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 +49 -1
- data/CONTRIBUTING.md +1 -1
- data/README.md +34 -18
- data/node_modules/prettier/bin-prettier.js +22 -13
- data/node_modules/prettier/index.js +22 -13
- data/package.json +2 -2
- data/src/nodes.js +10 -576
- data/src/nodes/alias.js +1 -1
- data/src/nodes/args.js +88 -0
- data/src/nodes/arrays.js +1 -1
- data/src/nodes/assign.js +39 -0
- data/src/nodes/blocks.js +18 -3
- data/src/nodes/calls.js +37 -3
- data/src/nodes/case.js +1 -1
- data/src/nodes/commands.js +2 -1
- data/src/nodes/conditionals.js +118 -57
- data/src/nodes/constants.js +25 -0
- data/src/nodes/flow.js +64 -0
- data/src/nodes/hashes.js +3 -2
- data/src/nodes/hooks.js +1 -1
- data/src/nodes/ints.js +24 -0
- data/src/nodes/lambdas.js +1 -1
- data/src/nodes/loops.js +1 -1
- data/src/nodes/massign.js +70 -0
- data/src/nodes/methods.js +40 -2
- data/src/nodes/operators.js +44 -0
- data/src/nodes/params.js +14 -3
- data/src/nodes/regexp.js +1 -1
- data/src/nodes/rescue.js +1 -1
- data/src/nodes/scopes.js +61 -0
- data/src/nodes/statements.js +105 -0
- data/src/nodes/strings.js +9 -2
- data/src/{builders.js → prettier.js} +9 -2
- data/src/ripper.rb +412 -353
- data/src/utils.js +1 -1
- metadata +40 -3
data/src/nodes/alias.js
CHANGED
data/src/nodes/args.js
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
const {
|
2
|
+
concat,
|
3
|
+
group,
|
4
|
+
ifBreak,
|
5
|
+
indent,
|
6
|
+
join,
|
7
|
+
line,
|
8
|
+
softline
|
9
|
+
} = require("../prettier");
|
10
|
+
|
11
|
+
const toProc = require("../toProc");
|
12
|
+
const { makeArgs } = require("../utils");
|
13
|
+
|
14
|
+
module.exports = {
|
15
|
+
arg_paren: (path, opts, print) => {
|
16
|
+
if (path.getValue().body[0] === null) {
|
17
|
+
return "";
|
18
|
+
}
|
19
|
+
|
20
|
+
const { addTrailingCommas } = opts;
|
21
|
+
const { args, heredocs } = makeArgs(path, opts, print, 0);
|
22
|
+
|
23
|
+
const argsNode = path.getValue().body[0];
|
24
|
+
const hasBlock = argsNode.type === "args_add_block" && argsNode.body[1];
|
25
|
+
|
26
|
+
if (heredocs.length > 1) {
|
27
|
+
return concat(["(", join(", ", args), ")"].concat(heredocs));
|
28
|
+
}
|
29
|
+
|
30
|
+
const parenDoc = group(
|
31
|
+
concat([
|
32
|
+
"(",
|
33
|
+
indent(
|
34
|
+
concat([
|
35
|
+
softline,
|
36
|
+
join(concat([",", line]), args),
|
37
|
+
addTrailingCommas && !hasBlock ? ifBreak(",", "") : ""
|
38
|
+
])
|
39
|
+
),
|
40
|
+
concat([softline, ")"])
|
41
|
+
])
|
42
|
+
);
|
43
|
+
|
44
|
+
if (heredocs.length === 1) {
|
45
|
+
return group(concat([parenDoc].concat(heredocs)));
|
46
|
+
}
|
47
|
+
|
48
|
+
return parenDoc;
|
49
|
+
},
|
50
|
+
args: (path, opts, print) => {
|
51
|
+
const args = path.map(print, "body");
|
52
|
+
let blockNode = null;
|
53
|
+
|
54
|
+
[1, 2, 3].find(parent => {
|
55
|
+
const parentNode = path.getParentNode(parent);
|
56
|
+
blockNode =
|
57
|
+
parentNode &&
|
58
|
+
parentNode.type === "method_add_block" &&
|
59
|
+
parentNode.body[1];
|
60
|
+
return blockNode;
|
61
|
+
});
|
62
|
+
|
63
|
+
const proc = blockNode && toProc(blockNode);
|
64
|
+
if (proc) {
|
65
|
+
args.push(proc);
|
66
|
+
}
|
67
|
+
|
68
|
+
return args;
|
69
|
+
},
|
70
|
+
args_add_block: (path, opts, print) => {
|
71
|
+
const parts = path.call(print, "body", 0);
|
72
|
+
|
73
|
+
if (path.getValue().body[1]) {
|
74
|
+
parts.push(concat(["&", path.call(print, "body", 1)]));
|
75
|
+
}
|
76
|
+
|
77
|
+
return parts;
|
78
|
+
},
|
79
|
+
args_add_star: (path, opts, print) => {
|
80
|
+
const printed = path.map(print, "body");
|
81
|
+
const parts = printed[0]
|
82
|
+
.concat([concat(["*", printed[1]])])
|
83
|
+
.concat(printed.slice(2));
|
84
|
+
|
85
|
+
return parts;
|
86
|
+
},
|
87
|
+
blockarg: (path, opts, print) => concat(["&", path.call(print, "body", 0)])
|
88
|
+
};
|
data/src/nodes/arrays.js
CHANGED
data/src/nodes/assign.js
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
const { concat, group, indent, join, line } = require("../prettier");
|
2
|
+
const { concatBody, first, skipAssignIndent } = require("../utils");
|
3
|
+
|
4
|
+
module.exports = {
|
5
|
+
assign: (path, opts, print) => {
|
6
|
+
const [printedTarget, printedValue] = path.map(print, "body");
|
7
|
+
let adjustedValue = printedValue;
|
8
|
+
|
9
|
+
if (
|
10
|
+
["mrhs_add_star", "mrhs_new_from_args"].includes(
|
11
|
+
path.getValue().body[1].type
|
12
|
+
)
|
13
|
+
) {
|
14
|
+
adjustedValue = group(join(concat([",", line]), printedValue));
|
15
|
+
}
|
16
|
+
|
17
|
+
if (skipAssignIndent(path.getValue().body[1])) {
|
18
|
+
return group(concat([printedTarget, " = ", adjustedValue]));
|
19
|
+
}
|
20
|
+
|
21
|
+
return group(
|
22
|
+
concat([printedTarget, " =", indent(concat([line, adjustedValue]))])
|
23
|
+
);
|
24
|
+
},
|
25
|
+
assign_error: (_path, _opts, _print) => {
|
26
|
+
throw new Error("Can't set variable");
|
27
|
+
},
|
28
|
+
opassign: (path, opts, print) =>
|
29
|
+
group(
|
30
|
+
concat([
|
31
|
+
path.call(print, "body", 0),
|
32
|
+
" ",
|
33
|
+
path.call(print, "body", 1),
|
34
|
+
indent(concat([line, path.call(print, "body", 2)]))
|
35
|
+
])
|
36
|
+
),
|
37
|
+
var_field: concatBody,
|
38
|
+
var_ref: first
|
39
|
+
};
|
data/src/nodes/blocks.js
CHANGED
@@ -4,9 +4,11 @@ const {
|
|
4
4
|
group,
|
5
5
|
ifBreak,
|
6
6
|
indent,
|
7
|
+
join,
|
8
|
+
removeLines,
|
7
9
|
softline
|
8
|
-
} = require("../
|
9
|
-
const { hasAncestor } = require("../utils");
|
10
|
+
} = require("../prettier");
|
11
|
+
const { empty, first, hasAncestor } = require("../utils");
|
10
12
|
|
11
13
|
const printBlock = (path, opts, print) => {
|
12
14
|
const [variables, statements] = path.getValue().body;
|
@@ -61,6 +63,19 @@ const printBlock = (path, opts, print) => {
|
|
61
63
|
};
|
62
64
|
|
63
65
|
module.exports = {
|
66
|
+
block_var: (path, opts, print) => {
|
67
|
+
const parts = ["|", removeLines(path.call(print, "body", 0))];
|
68
|
+
|
69
|
+
// The second part of this node is a list of optional block-local variables
|
70
|
+
if (path.getValue().body[1]) {
|
71
|
+
parts.push("; ", join(", ", path.map(print, "body", 1)));
|
72
|
+
}
|
73
|
+
|
74
|
+
parts.push("| ");
|
75
|
+
return concat(parts);
|
76
|
+
},
|
64
77
|
brace_block: printBlock,
|
65
|
-
do_block: printBlock
|
78
|
+
do_block: printBlock,
|
79
|
+
excessed_comma: empty,
|
80
|
+
number_arg: first
|
66
81
|
};
|
data/src/nodes/calls.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
const { concat, group, indent, softline } = require("../
|
2
|
-
const
|
1
|
+
const { concat, group, indent, softline } = require("../prettier");
|
2
|
+
const toProc = require("../toProc");
|
3
|
+
const { concatBody, first, makeCall } = require("../utils");
|
3
4
|
|
4
5
|
const noIndent = ["array", "hash", "method_add_block", "xstring_literal"];
|
5
6
|
|
@@ -24,5 +25,38 @@ module.exports = {
|
|
24
25
|
return group(
|
25
26
|
concat([receiver, indent(concat([softline, operator, name]))])
|
26
27
|
);
|
27
|
-
}
|
28
|
+
},
|
29
|
+
fcall: concatBody,
|
30
|
+
method_add_arg: (path, opts, print) => {
|
31
|
+
const [method, args] = path.map(print, "body");
|
32
|
+
const argNode = path.getValue().body[1];
|
33
|
+
|
34
|
+
// This case will ONLY be hit if we can successfully turn the block into a
|
35
|
+
// to_proc call. In that case, we just explicitly add the parens around it.
|
36
|
+
if (argNode.type === "args" && args.length > 0) {
|
37
|
+
return concat([method, "("].concat(args).concat(")"));
|
38
|
+
}
|
39
|
+
|
40
|
+
return concat([method, args]);
|
41
|
+
},
|
42
|
+
method_add_block: (path, opts, print) => {
|
43
|
+
const [method, block] = path.getValue().body;
|
44
|
+
const proc = toProc(block);
|
45
|
+
|
46
|
+
if (proc && method.type === "call") {
|
47
|
+
return group(
|
48
|
+
concat([
|
49
|
+
path.call(print, "body", 0),
|
50
|
+
"(",
|
51
|
+
indent(concat([softline, proc])),
|
52
|
+
concat([softline, ")"])
|
53
|
+
])
|
54
|
+
);
|
55
|
+
}
|
56
|
+
if (proc) {
|
57
|
+
return path.call(print, "body", 0);
|
58
|
+
}
|
59
|
+
return concat(path.map(print, "body"));
|
60
|
+
},
|
61
|
+
vcall: first
|
28
62
|
};
|
data/src/nodes/case.js
CHANGED
data/src/nodes/commands.js
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
const { align, concat, group, ifBreak, join, line } = require("../
|
1
|
+
const { align, concat, group, ifBreak, join, line } = require("../prettier");
|
2
2
|
const { docLength, makeArgs, makeCall } = require("../utils");
|
3
3
|
|
4
4
|
const hasDef = node =>
|
5
5
|
node.body[1].type === "args_add_block" &&
|
6
6
|
node.body[1].body[0].type === "args" &&
|
7
|
+
node.body[1].body[0].body[0] &&
|
7
8
|
node.body[1].body[0].body[0].type === "def";
|
8
9
|
|
9
10
|
module.exports = {
|
data/src/nodes/conditionals.js
CHANGED
@@ -7,7 +7,7 @@ const {
|
|
7
7
|
ifBreak,
|
8
8
|
indent,
|
9
9
|
softline
|
10
|
-
} = require("../
|
10
|
+
} = require("../prettier");
|
11
11
|
|
12
12
|
const noTernary = [
|
13
13
|
"@comment",
|
@@ -47,49 +47,114 @@ const printWithAddition = (keyword, path, print, { breaking = false } = {}) =>
|
|
47
47
|
breaking ? breakParent : ""
|
48
48
|
]);
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
// For the unary `not` operator, we need to explicitly add parentheses to it in
|
51
|
+
// order for it to be valid from within a ternary. Otherwise if the clause of
|
52
|
+
// the ternary isn't a unary `not`, we can just pass it along.
|
53
|
+
const printTernaryClause = clause => {
|
54
|
+
if (clause.type === "concat") {
|
55
|
+
const [part] = clause.parts;
|
56
|
+
|
57
|
+
if (part.type === "concat" && part.parts[0] === "not") {
|
58
|
+
// We are inside of a statements list and the statement is a unary `not`.
|
59
|
+
return concat(["not(", part.parts[2], ")"]);
|
60
|
+
}
|
61
|
+
|
62
|
+
if (clause.parts[0] === "not") {
|
63
|
+
// We are inside a ternary condition and the clause is a unary `not`.
|
64
|
+
return concat(["not(", clause.parts[2], ")"]);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
return clause;
|
69
|
+
};
|
70
|
+
|
71
|
+
// The conditions for a ternary look like `foo : bar` where `foo` represents
|
72
|
+
// the truthy clause and `bar` represents the falsy clause. In the case that the
|
73
|
+
// parent node is an `unless`, these have to flip in order.
|
74
|
+
const printTernaryClauses = (keyword, truthyClause, falsyClause) => {
|
75
|
+
const parts = [
|
76
|
+
printTernaryClause(truthyClause),
|
77
|
+
" : ",
|
78
|
+
printTernaryClause(falsyClause)
|
79
|
+
];
|
80
|
+
|
52
81
|
return keyword === "if" ? parts : parts.reverse();
|
53
82
|
};
|
54
83
|
|
55
|
-
|
56
|
-
|
84
|
+
// Handles ternary nodes. If it does not fit on one line, then we break out into
|
85
|
+
// an if/else statement. Otherwise we remain as a ternary.
|
86
|
+
const printTernary = (path, _opts, print) => {
|
87
|
+
const [predicate, truthyClause, falsyClause] = path.map(print, "body");
|
88
|
+
const ternaryClauses = printTernaryClauses("if", truthyClause, falsyClause);
|
57
89
|
|
58
|
-
|
59
|
-
|
90
|
+
return group(
|
91
|
+
ifBreak(
|
92
|
+
concat([
|
93
|
+
"if ",
|
94
|
+
predicate,
|
95
|
+
indent(concat([softline, truthyClause])),
|
96
|
+
concat([softline, "else"]),
|
97
|
+
indent(concat([softline, falsyClause])),
|
98
|
+
concat([softline, "end"])
|
99
|
+
]),
|
100
|
+
concat([predicate, " ? "].concat(ternaryClauses))
|
101
|
+
)
|
102
|
+
);
|
103
|
+
};
|
60
104
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
105
|
+
// Prints an `if_mod` or `unless_mod` node. Because it was previously in the
|
106
|
+
// modifier form, we're guaranteed to not have an additional node, so we can
|
107
|
+
// just work with the predicate and the body.
|
108
|
+
const printSingle = keyword => (path, { inlineConditionals }, print) => {
|
109
|
+
const multiline = concat([
|
110
|
+
`${keyword} `,
|
111
|
+
align(keyword.length - 1, path.call(print, "body", 0)),
|
112
|
+
indent(concat([softline, path.call(print, "body", 1)])),
|
113
|
+
concat([softline, "end"])
|
114
|
+
]);
|
67
115
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
concat([softline, "else"]),
|
75
|
-
indent(concat([softline, path.call(print, "body", 2)])),
|
76
|
-
concat([softline, "end"])
|
77
|
-
]),
|
78
|
-
concat(
|
79
|
-
parts.concat(printTernaryConditions(keyword, truthyValue, falsyValue))
|
80
|
-
)
|
81
|
-
)
|
82
|
-
);
|
116
|
+
const stmts = path.getValue().body[1];
|
117
|
+
const hasComments =
|
118
|
+
stmts.type === "stmts" && stmts.body.some(stmt => stmt.type === "@comment");
|
119
|
+
|
120
|
+
if (!inlineConditionals || hasComments) {
|
121
|
+
return multiline;
|
83
122
|
}
|
84
123
|
|
85
|
-
|
86
|
-
|
124
|
+
const inline = concat([
|
125
|
+
path.call(print, "body", 1),
|
126
|
+
` ${keyword} `,
|
127
|
+
path.call(print, "body", 0)
|
128
|
+
]);
|
129
|
+
|
130
|
+
return group(ifBreak(multiline, inline));
|
131
|
+
};
|
132
|
+
|
133
|
+
// Certain expressions cannot be reduced to a ternary without adding parens
|
134
|
+
// around them. In this case we say they cannot be ternaried and default instead
|
135
|
+
// to breaking them into multiple lines.
|
136
|
+
const canTernaryStmts = stmts =>
|
137
|
+
stmts.body.length === 1 && !noTernary.includes(stmts.body[0].type);
|
138
|
+
|
139
|
+
// In order for an `if` or `unless` expression to be shortened to a ternary,
|
140
|
+
// there has to be one and only one "addition" (another clause attached) which
|
141
|
+
// is of the "else" type. Both the body of the main node and the body of the
|
142
|
+
// additional node must have only one statement, and that statement list must
|
143
|
+
// pass the `canTernaryStmts` check.
|
144
|
+
const canTernary = path => {
|
145
|
+
const [_pred, stmts, addition] = path.getValue().body;
|
146
|
+
|
147
|
+
return (
|
87
148
|
addition &&
|
88
149
|
addition.type === "else" &&
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
150
|
+
[stmts, addition.body[0]].every(canTernaryStmts)
|
151
|
+
);
|
152
|
+
};
|
153
|
+
|
154
|
+
// A normalized print function for both `if` and `unless` nodes.
|
155
|
+
const printConditional = keyword => (path, { inlineConditionals }, print) => {
|
156
|
+
if (canTernary(path)) {
|
157
|
+
const ternaryConditions = printTernaryClauses(
|
93
158
|
keyword,
|
94
159
|
path.call(print, "body", 1),
|
95
160
|
path.call(print, "body", 2, "body", 0)
|
@@ -98,36 +163,32 @@ const printConditional = keyword => (path, { inlineConditionals }, print) => {
|
|
98
163
|
return group(
|
99
164
|
ifBreak(
|
100
165
|
printWithAddition(keyword, path, print),
|
101
|
-
concat([path.call(print, "body", 0), " ? "].concat(
|
166
|
+
concat([path.call(print, "body", 0), " ? "].concat(ternaryConditions))
|
102
167
|
)
|
103
168
|
);
|
104
169
|
}
|
105
170
|
|
106
|
-
// If there's an additional clause
|
107
|
-
|
171
|
+
// If there's an additional clause that wasn't matched earlier, we know we
|
172
|
+
// can't go for the inline option.
|
173
|
+
if (path.getValue().body[2]) {
|
108
174
|
return group(printWithAddition(keyword, path, print, { breaking: true }));
|
109
175
|
}
|
110
176
|
|
111
|
-
|
112
|
-
return group(
|
113
|
-
ifBreak(
|
114
|
-
concat([
|
115
|
-
`${keyword} `,
|
116
|
-
align(keyword.length - 1, path.call(print, "body", 0)),
|
117
|
-
indent(concat([softline, path.call(print, "body", 1)])),
|
118
|
-
concat([softline, "end"])
|
119
|
-
]),
|
120
|
-
concat([
|
121
|
-
inlineConditionals ? "" : breakParent,
|
122
|
-
path.call(print, "body", 1),
|
123
|
-
` ${keyword} `,
|
124
|
-
path.call(print, "body", 0)
|
125
|
-
])
|
126
|
-
)
|
127
|
-
);
|
177
|
+
return printSingle(keyword)(path, { inlineConditionals }, print);
|
128
178
|
};
|
129
179
|
|
130
180
|
module.exports = {
|
181
|
+
else: (path, opts, print) => {
|
182
|
+
const stmts = path.getValue().body[0];
|
183
|
+
|
184
|
+
return concat([
|
185
|
+
stmts.body.length === 1 && stmts.body[0].type === "command"
|
186
|
+
? breakParent
|
187
|
+
: "",
|
188
|
+
"else",
|
189
|
+
indent(concat([softline, path.call(print, "body", 0)]))
|
190
|
+
]);
|
191
|
+
},
|
131
192
|
elsif: (path, opts, print) => {
|
132
193
|
const [_predicate, _statements, addition] = path.getValue().body;
|
133
194
|
const parts = [
|
@@ -147,8 +208,8 @@ module.exports = {
|
|
147
208
|
return group(concat(parts));
|
148
209
|
},
|
149
210
|
if: printConditional("if"),
|
150
|
-
ifop:
|
151
|
-
if_mod:
|
211
|
+
ifop: printTernary,
|
212
|
+
if_mod: printSingle("if"),
|
152
213
|
unless: printConditional("unless"),
|
153
|
-
unless_mod:
|
214
|
+
unless_mod: printSingle("unless")
|
154
215
|
};
|