prettier 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,52 +1,72 @@
1
1
  const { concat, group, indent, line, softline } = require("../prettier");
2
2
 
3
- module.exports = {
4
- binary: (path, opts, print) => {
5
- const operator = path.getValue().body[1];
6
- const useNoSpace = operator === "**";
7
-
8
- return group(
9
- concat([
10
- group(path.call(print, "body", 0)),
11
- indent(
12
- concat([
13
- useNoSpace ? "" : " ",
14
- group(
15
- concat([
16
- operator,
17
- useNoSpace ? softline : line,
18
- path.call(print, "body", 2)
19
- ])
20
- )
21
- ])
22
- )
23
- ])
24
- );
25
- },
26
- dot2: (path, opts, print) =>
27
- concat([
28
- path.call(print, "body", 0),
29
- "..",
30
- path.getValue().body[1] ? path.call(print, "body", 1) : ""
31
- ]),
32
- dot3: (path, opts, print) =>
3
+ function printBinary(path, opts, print) {
4
+ const operator = path.getValue().body[1];
5
+ const useNoSpace = operator === "**";
6
+
7
+ return group(
33
8
  concat([
34
- path.call(print, "body", 0),
35
- "...",
36
- path.getValue().body[1] ? path.call(print, "body", 1) : ""
37
- ]),
38
- unary: (path, opts, print) => {
39
- const oper = path.getValue().body[0];
40
- const doc = path.call(print, "body", 1);
41
-
42
- if (oper === "not") {
43
- // For the `not` operator, we're explicitly making the space character
44
- // another element in the `concat` because there are some circumstances
45
- // where we need to force parentheses (e.g., ternaries). In that case the
46
- // printer for those nodes can just take out the space and put in parens.
47
- return concat(["not", " ", doc]);
48
- }
9
+ group(path.call(print, "body", 0)),
10
+ indent(
11
+ concat([
12
+ useNoSpace ? "" : " ",
13
+ group(
14
+ concat([
15
+ operator,
16
+ useNoSpace ? softline : line,
17
+ path.call(print, "body", 2)
18
+ ])
19
+ )
20
+ ])
21
+ )
22
+ ])
23
+ );
24
+ }
25
+
26
+ // dot2 nodes are used with ranges (or flip-flops). They can optionally drop
27
+ // their left side for beginless ranges or their right side for endless ranges.
28
+ function printDot2(path, opts, print) {
29
+ const [leftNode, rightNode] = path.getValue().body;
30
+
31
+ return concat([
32
+ leftNode ? path.call(print, "body", 0) : "",
33
+ "..",
34
+ rightNode ? path.call(print, "body", 1) : ""
35
+ ]);
36
+ }
37
+
38
+ // dot3 nodes are used with ranges (or flip-flops). They can optionally drop
39
+ // their left side for beginless ranges or their right side for endless ranges.
40
+ function printDot3(path, opts, print) {
41
+ const [leftNode, rightNode] = path.getValue().body;
49
42
 
50
- return concat([oper[0], doc]);
43
+ return concat([
44
+ leftNode ? path.call(print, "body", 0) : "",
45
+ "...",
46
+ rightNode ? path.call(print, "body", 1) : ""
47
+ ]);
48
+ }
49
+
50
+ function printUnary(path, opts, print) {
51
+ const node = path.getValue();
52
+ const contentsDoc = path.call(print, "body", 0);
53
+
54
+ if (node.oper === "not") {
55
+ // Here we defer to the original source, as it's kind of difficult to
56
+ // determine if we can actually remove the parentheses being used.
57
+ if (node.paren) {
58
+ return concat(["not", "(", contentsDoc, ")"]);
59
+ } else {
60
+ return concat(["not", " ", contentsDoc]);
61
+ }
51
62
  }
63
+
64
+ return concat([node.oper, contentsDoc]);
65
+ }
66
+
67
+ module.exports = {
68
+ binary: printBinary,
69
+ dot2: printDot2,
70
+ dot3: printDot3,
71
+ unary: printUnary
52
72
  };
@@ -1,12 +1,15 @@
1
1
  const { concat, group, join, line } = require("../prettier");
2
2
  const { literal } = require("../utils");
3
3
 
4
- const printGenericRestParam = (symbol) => (path, opts, print) =>
5
- path.getValue().body[0]
6
- ? concat([symbol, path.call(print, "body", 0)])
7
- : symbol;
4
+ function printRestParam(symbol) {
5
+ return function printRestParamWithSymbol(path, opts, print) {
6
+ return path.getValue().body[0]
7
+ ? concat([symbol, path.call(print, "body", 0)])
8
+ : symbol;
9
+ };
10
+ }
8
11
 
9
- const printParams = (path, opts, print) => {
12
+ function printParams(path, opts, print) {
10
13
  const [
11
14
  reqs,
12
15
  optls,
@@ -73,16 +76,11 @@ const printParams = (path, opts, print) => {
73
76
  const comma = rest === 0 || (rest && rest.type === "excessed_comma");
74
77
 
75
78
  return group(concat([join(concat([",", line]), parts), comma ? "," : ""]));
76
- };
77
-
78
- const paramError = () => {
79
- throw new Error("formal argument cannot be a global variable");
80
- };
79
+ }
81
80
 
82
81
  module.exports = {
83
82
  args_forward: literal("..."),
84
- kwrest_param: printGenericRestParam("**"),
85
- rest_param: printGenericRestParam("*"),
86
- params: printParams,
87
- param_error: paramError
83
+ kwrest_param: printRestParam("**"),
84
+ rest_param: printRestParam("*"),
85
+ params: printParams
88
86
  };
@@ -1,43 +1,118 @@
1
1
  const { concat, group, hardline, indent, join, line } = require("../prettier");
2
2
 
3
- module.exports = {
4
- aryptn: (path, opts, print) => {
5
- const [constant, preargs, splatarg, postargs] = path.getValue().body;
6
- let args = [];
3
+ function printPatternArg(path, opts, print) {
4
+ // Pinning is a really special syntax in pattern matching that's not really
5
+ // all that well supported in ripper. Here we're just going to the original
6
+ // source to see if the variable is pinned.
7
+ if (
8
+ opts.originalText &&
9
+ opts.originalText[opts.locStart(path.getValue()) - 1] === "^"
10
+ ) {
11
+ return concat(["^", path.call(print)]);
12
+ }
7
13
 
8
- if (preargs) {
9
- args = args.concat(path.map(print, "body", 1));
10
- }
14
+ return path.call(print);
15
+ }
11
16
 
12
- if (splatarg) {
13
- args.push(concat(["*", path.call(print, "body", 2)]));
14
- }
17
+ function printAryPtn(path, opts, print) {
18
+ const [constant, preargs, splatarg, postargs] = path.getValue().body;
19
+ let args = [];
15
20
 
16
- if (postargs) {
17
- args = args.concat(path.map(print, "body", 3));
18
- }
21
+ if (preargs) {
22
+ args = args.concat(
23
+ path.map((argPath) => printPatternArg(argPath, opts, print), "body", 1)
24
+ );
25
+ }
19
26
 
20
- args = group(join(concat([",", line]), args));
27
+ if (splatarg) {
28
+ args.push(concat(["*", path.call(print, "body", 2)]));
29
+ }
21
30
 
22
- if (constant || path.getParentNode().type === "binary") {
23
- args = concat(["[", args, "]"]);
24
- }
31
+ if (postargs) {
32
+ args = args.concat(path.map(print, "body", 3));
33
+ }
25
34
 
26
- if (constant) {
27
- return concat([path.call(print, "body", 0), args]);
28
- }
35
+ args = group(join(concat([",", line]), args));
29
36
 
30
- return args;
31
- },
32
- hshptn: () => {
33
- throw new Error(
34
- "Hash pattern not currently supported (https://bugs.ruby-lang.org/issues/16008)"
35
- );
36
- },
37
- in: (path, opts, print) =>
38
- concat([
39
- "in ",
40
- path.call(print, "body", 0),
41
- indent(concat([hardline, path.call(print, "body", 1)]))
42
- ])
37
+ if (
38
+ constant ||
39
+ ["aryptn", "binary", "hshptn"].includes(path.getParentNode().type)
40
+ ) {
41
+ args = concat(["[", args, "]"]);
42
+ }
43
+
44
+ if (constant) {
45
+ return concat([path.call(print, "body", 0), args]);
46
+ }
47
+
48
+ return args;
49
+ }
50
+
51
+ function printHshPtn(path, opts, print) {
52
+ const [constant, keyValuePairs, keyValueRest] = path.getValue().body;
53
+ let args = [];
54
+
55
+ if (keyValuePairs) {
56
+ const printPair = (pairPath) => {
57
+ const parts = [pairPath.call(print, 0)];
58
+
59
+ if (pairPath.getValue()[1]) {
60
+ parts.push(
61
+ " ",
62
+ pairPath.call(
63
+ (pairValuePath) => printPatternArg(pairValuePath, opts, print),
64
+ 1
65
+ )
66
+ );
67
+ }
68
+
69
+ return concat(parts);
70
+ };
71
+
72
+ args = args.concat(path.map(printPair, "body", 1));
73
+ }
74
+
75
+ if (keyValueRest) {
76
+ args.push(concat(["**", path.call(print, "body", 2)]));
77
+ }
78
+
79
+ args = group(join(concat([",", line]), args));
80
+
81
+ if (constant) {
82
+ args = concat(["[", args, "]"]);
83
+ } else if (
84
+ ["aryptn", "binary", "hshptn"].includes(path.getParentNode().type)
85
+ ) {
86
+ args = concat(["{", args, "}"]);
87
+ }
88
+
89
+ if (constant) {
90
+ return concat([path.call(print, "body", 0), args]);
91
+ }
92
+
93
+ return args;
94
+ }
95
+
96
+ function printIn(path, opts, print) {
97
+ const parts = [
98
+ "in ",
99
+ path.call(
100
+ (valuePath) => printPatternArg(valuePath, opts, print),
101
+ "body",
102
+ 0
103
+ ),
104
+ indent(concat([hardline, path.call(print, "body", 1)]))
105
+ ];
106
+
107
+ if (path.getValue().body[2]) {
108
+ parts.push(hardline, path.call(print, "body", 2));
109
+ }
110
+
111
+ return group(concat(parts));
112
+ }
113
+
114
+ module.exports = {
115
+ aryptn: printAryPtn,
116
+ hshptn: printHshPtn,
117
+ in: printIn
43
118
  };
@@ -1,18 +1,27 @@
1
1
  const { concat } = require("../prettier");
2
- const { makeList } = require("../utils");
3
2
 
4
- module.exports = {
5
- regexp: makeList,
6
- regexp_literal: (path, opts, print) => {
7
- const [contents, ending] = path.map(print, "body");
3
+ // This function is responsible for printing out regexp_literal nodes. They can
4
+ // either use the special %r literal syntax or they can use forward slashes. At
5
+ // the end of either of those they can have modifiers like m or x that have
6
+ // special meaning for the regex engine.
7
+ //
8
+ // We favor the use of forward slashes unless the regex contains a forward slash
9
+ // itself. In that case we switch over to using %r with braces.
10
+ function printRegexpLiteral(path, opts, print) {
11
+ const { ending } = path.getValue();
12
+ const contents = path.map(print, "body");
13
+
14
+ const useBraces = contents.some(
15
+ (content) => typeof content === "string" && content.includes("/")
16
+ );
8
17
 
9
- const useBraces = contents.some(
10
- (content) => typeof content === "string" && content.includes("/")
11
- );
12
- const parts = [useBraces ? "%r{" : "/"]
13
- .concat(contents)
14
- .concat([useBraces ? "}" : "/", ending.slice(1)]);
18
+ const parts = [useBraces ? "%r{" : "/"]
19
+ .concat(contents)
20
+ .concat([useBraces ? "}" : "/", ending.slice(1)]);
15
21
 
16
- return concat(parts);
17
- }
22
+ return concat(parts);
23
+ }
24
+
25
+ module.exports = {
26
+ regexp_literal: printRegexpLiteral
18
27
  };
@@ -9,73 +9,86 @@ const {
9
9
  } = require("../prettier");
10
10
  const { literal } = require("../utils");
11
11
 
12
- module.exports = {
13
- begin: (path, opts, print) =>
14
- concat([
15
- "begin",
16
- indent(concat([hardline, concat(path.map(print, "body"))])),
17
- hardline,
18
- "end"
19
- ]),
20
- ensure: (path, opts, print) =>
21
- concat([
22
- "ensure",
23
- indent(concat([hardline, concat(path.map(print, "body"))]))
24
- ]),
25
- redo: literal("redo"),
26
- rescue: (path, opts, print) => {
27
- const [exception, variable, _stmts, addition] = path.getValue().body;
28
- const parts = ["rescue"];
12
+ function printBegin(path, opts, print) {
13
+ return concat([
14
+ "begin",
15
+ indent(concat([hardline, concat(path.map(print, "body"))])),
16
+ hardline,
17
+ "end"
18
+ ]);
19
+ }
29
20
 
30
- if (exception || variable) {
31
- if (exception) {
32
- if (Array.isArray(exception)) {
33
- // In this case, it's actually only the one exception (it's an array
34
- // of length 1).
35
- parts.push(" ", path.call(print, "body", 0, 0));
36
- } else {
37
- // Here we have multiple exceptions from which we're rescuing, so we
38
- // need to align them and join them together.
39
- const joiner = concat([",", line]);
40
- const exceptions = group(join(joiner, path.call(print, "body", 0)));
21
+ function printEnsure(path, opts, print) {
22
+ return concat([
23
+ "ensure",
24
+ indent(concat([hardline, concat(path.map(print, "body"))]))
25
+ ]);
26
+ }
41
27
 
42
- parts.push(" ", align("rescue ".length, exceptions));
43
- }
44
- }
28
+ function printRescue(path, opts, print) {
29
+ const [exception, variable, _stmts, addition] = path.getValue().body;
30
+ const parts = ["rescue"];
31
+
32
+ if (exception || variable) {
33
+ if (exception) {
34
+ if (Array.isArray(exception)) {
35
+ // In this case, it's actually only the one exception (it's an array
36
+ // of length 1).
37
+ parts.push(" ", path.call(print, "body", 0, 0));
38
+ } else {
39
+ // Here we have multiple exceptions from which we're rescuing, so we
40
+ // need to align them and join them together.
41
+ const joiner = concat([",", line]);
42
+ const exceptions = group(join(joiner, path.call(print, "body", 0)));
45
43
 
46
- if (variable) {
47
- parts.push(" => ", path.call(print, "body", 1));
44
+ parts.push(" ", align("rescue ".length, exceptions));
48
45
  }
49
- } else {
50
- // If you don't specify an error to rescue in a `begin/rescue` block, then
51
- // implicitly you're rescuing from `StandardError`. In this case, we're
52
- // just going to explicitly add it.
53
- parts.push(" StandardError");
54
46
  }
55
47
 
56
- const rescueBody = path.call(print, "body", 2);
57
-
58
- if (rescueBody.parts.length > 0) {
59
- parts.push(indent(concat([hardline, rescueBody])));
48
+ if (variable) {
49
+ parts.push(" => ", path.call(print, "body", 1));
60
50
  }
51
+ } else {
52
+ // If you don't specify an error to rescue in a `begin/rescue` block, then
53
+ // implicitly you're rescuing from `StandardError`. In this case, we're
54
+ // just going to explicitly add it.
55
+ parts.push(" StandardError");
56
+ }
61
57
 
62
- // This is the next clause on the `begin` statement, either another
63
- // `rescue`, and `ensure`, or an `else` clause.
64
- if (addition) {
65
- parts.push(concat([hardline, path.call(print, "body", 3)]));
66
- }
58
+ const rescueBody = path.call(print, "body", 2);
59
+
60
+ if (rescueBody.parts.length > 0) {
61
+ parts.push(indent(concat([hardline, rescueBody])));
62
+ }
67
63
 
68
- return group(concat(parts));
69
- },
70
- rescue_mod: (path, opts, print) =>
71
- concat([
72
- "begin",
73
- indent(concat([hardline, path.call(print, "body", 0)])),
74
- hardline,
75
- "rescue StandardError",
76
- indent(concat([hardline, path.call(print, "body", 1)])),
77
- hardline,
78
- "end"
79
- ]),
64
+ // This is the next clause on the `begin` statement, either another
65
+ // `rescue`, and `ensure`, or an `else` clause.
66
+ if (addition) {
67
+ parts.push(concat([hardline, path.call(print, "body", 3)]));
68
+ }
69
+
70
+ return group(concat(parts));
71
+ }
72
+
73
+ function printRescueMod(path, opts, print) {
74
+ const [statementDoc, valueDoc] = path.map(print, "body");
75
+
76
+ return concat([
77
+ "begin",
78
+ indent(concat([hardline, statementDoc])),
79
+ hardline,
80
+ "rescue StandardError",
81
+ indent(concat([hardline, valueDoc])),
82
+ hardline,
83
+ "end"
84
+ ]);
85
+ }
86
+
87
+ module.exports = {
88
+ begin: printBegin,
89
+ ensure: printEnsure,
90
+ redo: literal("redo"),
91
+ rescue: printRescue,
92
+ rescue_mod: printRescueMod,
80
93
  retry: literal("retry")
81
94
  };