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.
data/src/nodes/alias.js CHANGED
@@ -1,4 +1,4 @@
1
- const { concat, join } = require("../builders");
1
+ const { concat, join } = require("../prettier");
2
2
 
3
3
  const usingSymbols = path => {
4
4
  const [left, right] = path.getValue().body.map(node => node.body[0].type);
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
@@ -7,7 +7,7 @@ const {
7
7
  line,
8
8
  literalline,
9
9
  softline
10
- } = require("../builders");
10
+ } = require("../prettier");
11
11
 
12
12
  const isStringArray = args =>
13
13
  args.body.every(
@@ -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("../builders");
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("../builders");
2
- const { makeCall } = require("../utils");
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
@@ -6,7 +6,7 @@ const {
6
6
  hardline,
7
7
  indent,
8
8
  line
9
- } = require("../builders");
9
+ } = require("../prettier");
10
10
 
11
11
  module.exports = {
12
12
  case: (path, opts, print) => {
@@ -1,9 +1,10 @@
1
- const { align, concat, group, ifBreak, join, line } = require("../builders");
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 = {
@@ -7,7 +7,7 @@ const {
7
7
  ifBreak,
8
8
  indent,
9
9
  softline
10
- } = require("../builders");
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
- const printTernaryConditions = (keyword, truthyValue, falsyValue) => {
51
- const parts = [truthyValue, " : ", falsyValue];
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
- const canTernary = stmts =>
56
- stmts.body.length === 1 && !noTernary.includes(stmts.body[0].type);
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
- const printConditional = keyword => (path, { inlineConditionals }, print) => {
59
- const [_predicate, stmts, addition] = path.getValue().body;
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
- // If the addition is not an elsif or an else, then it's the second half of a
62
- // ternary expression
63
- if (addition && addition.type !== "elsif" && addition.type !== "else") {
64
- const parts = [path.call(print, "body", 0), " ? "];
65
- const truthyValue = path.call(print, "body", 1);
66
- const falsyValue = path.call(print, "body", 2);
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
- return group(
69
- ifBreak(
70
- concat([
71
- `${keyword} `,
72
- path.call(print, "body", 0),
73
- indent(concat([softline, path.call(print, "body", 1)])),
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
- // If there is an else and only an else, attempt to shorten to a ternary
86
- if (
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
- canTernary(stmts) &&
90
- canTernary(addition.body[0])
91
- ) {
92
- const ternary = printTernaryConditions(
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(ternary))
166
+ concat([path.call(print, "body", 0), " ? "].concat(ternaryConditions))
102
167
  )
103
168
  );
104
169
  }
105
170
 
106
- // If there's an additional clause, we know we can't go for the inline option
107
- if (addition) {
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
- // If it's short enough, favor the inline conditional
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: printConditional("if"),
151
- if_mod: printConditional("if"),
211
+ ifop: printTernary,
212
+ if_mod: printSingle("if"),
152
213
  unless: printConditional("unless"),
153
- unless_mod: printConditional("unless")
214
+ unless_mod: printSingle("unless")
154
215
  };