prettier 0.12.2 → 0.12.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 +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
|
};
|