prettier 2.1.0 → 3.0.0

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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -6
  3. data/README.md +16 -16
  4. data/exe/rbprettier +2 -2
  5. data/lib/prettier/rake/task.rb +5 -5
  6. data/lib/prettier.rb +11 -11
  7. data/package.json +9 -23
  8. data/rubocop.yml +6 -6
  9. data/{dist/parser → src}/getInfo.js +0 -1
  10. data/{dist/parser → src}/netcat.js +0 -1
  11. data/src/parseSync.js +212 -0
  12. data/src/plugin.js +161 -0
  13. data/{dist/parser → src}/server.rb +45 -31
  14. metadata +94 -78
  15. data/bin/console +0 -7
  16. data/dist/haml/embed.js +0 -53
  17. data/dist/haml/parser.js +0 -31
  18. data/dist/haml/parser.rb +0 -149
  19. data/dist/haml/printer.js +0 -336
  20. data/dist/parser/parseSync.js +0 -179
  21. data/dist/plugin.js +0 -143
  22. data/dist/prettier.js +0 -15
  23. data/dist/rbs/parser.js +0 -34
  24. data/dist/rbs/parser.rb +0 -155
  25. data/dist/rbs/printer.js +0 -525
  26. data/dist/ruby/embed.js +0 -115
  27. data/dist/ruby/location.js +0 -19
  28. data/dist/ruby/nodes/alias.js +0 -60
  29. data/dist/ruby/nodes/aref.js +0 -51
  30. data/dist/ruby/nodes/args.js +0 -138
  31. data/dist/ruby/nodes/arrays.js +0 -122
  32. data/dist/ruby/nodes/assign.js +0 -37
  33. data/dist/ruby/nodes/blocks.js +0 -90
  34. data/dist/ruby/nodes/calls.js +0 -263
  35. data/dist/ruby/nodes/case.js +0 -50
  36. data/dist/ruby/nodes/class.js +0 -54
  37. data/dist/ruby/nodes/commands.js +0 -138
  38. data/dist/ruby/nodes/conditionals.js +0 -246
  39. data/dist/ruby/nodes/constants.js +0 -35
  40. data/dist/ruby/nodes/flow.js +0 -59
  41. data/dist/ruby/nodes/hashes.js +0 -126
  42. data/dist/ruby/nodes/heredocs.js +0 -30
  43. data/dist/ruby/nodes/hooks.js +0 -35
  44. data/dist/ruby/nodes/ints.js +0 -27
  45. data/dist/ruby/nodes/lambdas.js +0 -70
  46. data/dist/ruby/nodes/loops.js +0 -75
  47. data/dist/ruby/nodes/massign.js +0 -60
  48. data/dist/ruby/nodes/methods.js +0 -50
  49. data/dist/ruby/nodes/operators.js +0 -68
  50. data/dist/ruby/nodes/params.js +0 -95
  51. data/dist/ruby/nodes/patterns.js +0 -119
  52. data/dist/ruby/nodes/regexp.js +0 -45
  53. data/dist/ruby/nodes/rescue.js +0 -86
  54. data/dist/ruby/nodes/return.js +0 -100
  55. data/dist/ruby/nodes/statements.js +0 -110
  56. data/dist/ruby/nodes/strings.js +0 -220
  57. data/dist/ruby/nodes/super.js +0 -26
  58. data/dist/ruby/nodes/undef.js +0 -31
  59. data/dist/ruby/nodes.js +0 -177
  60. data/dist/ruby/parser.js +0 -35
  61. data/dist/ruby/parser.rb +0 -9134
  62. data/dist/ruby/printer.js +0 -67
  63. data/dist/ruby/toProc.js +0 -91
  64. data/dist/types/haml.js +0 -4
  65. data/dist/types/plugin.js +0 -3
  66. data/dist/types/rbs.js +0 -4
  67. data/dist/types/ruby.js +0 -4
  68. data/dist/types/utils.js +0 -2
  69. data/dist/types.js +0 -34
  70. data/dist/utils/containsAssignment.js +0 -18
  71. data/dist/utils/getChildNodes.js +0 -305
  72. data/dist/utils/getTrailingComma.js +0 -6
  73. data/dist/utils/hasAncestor.js +0 -15
  74. data/dist/utils/inlineEnsureParens.js +0 -49
  75. data/dist/utils/isEmptyBodyStmt.js +0 -10
  76. data/dist/utils/isEmptyParams.js +0 -12
  77. data/dist/utils/isEmptyStmts.js +0 -10
  78. data/dist/utils/literal.js +0 -8
  79. data/dist/utils/literallineWithoutBreakParent.js +0 -8
  80. data/dist/utils/makeCall.js +0 -14
  81. data/dist/utils/noIndent.js +0 -11
  82. data/dist/utils/printEmptyCollection.js +0 -46
  83. data/dist/utils/skipAssignIndent.js +0 -19
  84. data/dist/utils.js +0 -32
@@ -1,60 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printAlias = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const { addTrailingComment, align, group, hardline, line } = prettier_1.default;
9
- // The `alias` keyword is used to make a method respond to another name as well
10
- // as the current one. For example, to get the method `foo` to also respond to
11
- // `bar`, you would:
12
- //
13
- // alias bar foo
14
- //
15
- // Now, in the current context you can call `bar` and it will execute the `foo`
16
- // method.
17
- //
18
- // When you're aliasing two methods, you can either provide bare words (like the
19
- // example above) or you can provide symbols (note that this includes dynamic
20
- // symbols like :"foo-#{bar}-baz"). In general, to be consistent with the ruby
21
- // style guide, we prefer bare words:
22
- //
23
- // https://github.com/rubocop-hq/ruby-style-guide#alias-method-lexically
24
- //
25
- // The `alias` node contains two children. The left and right align with the
26
- // arguments passed to the keyword. So, for the above example the left would be
27
- // the symbol literal `bar` and the right could be the symbol literal `foo`.
28
- const printAlias = (path, opts, print) => {
29
- const keyword = "alias ";
30
- const node = path.getValue();
31
- // In general, return the printed doc of the argument at the provided index.
32
- // Special handling is given for symbol literals that are not bare words, as
33
- // we convert those into bare words by just pulling out the ident node.
34
- const printAliasArg = (argPath) => {
35
- const argNode = argPath.getValue();
36
- if (argNode.type === "symbol_literal") {
37
- // If we're going to descend into the symbol literal to grab out the ident
38
- // node, then we need to make sure we copy over any comments as well,
39
- // otherwise we could accidentally skip printing them.
40
- if (argNode.comments) {
41
- argNode.comments.forEach((comment) => {
42
- addTrailingComment(argNode.value, comment);
43
- });
44
- }
45
- return argPath.call(print, "value");
46
- }
47
- return print(argPath);
48
- };
49
- return group([
50
- keyword,
51
- path.call(printAliasArg, "left"),
52
- group(align(keyword.length, [
53
- // If the left child has any comments, then we need to explicitly break
54
- // this into two lines
55
- node.left.comments ? hardline : line,
56
- path.call(printAliasArg, "right")
57
- ]))
58
- ]);
59
- };
60
- exports.printAlias = printAlias;
@@ -1,51 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printArefField = exports.printAref = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const { group, indent, join, line, softline } = prettier_1.default;
9
- // `aref` nodes are when you're pulling a value out of a collection at a
10
- // specific index. Put another way, it's any time you're calling the method
11
- // `#[]`.
12
- //
13
- // The nodes usually contains two children, details below in the
14
- // `printArefField` function. In some cases, you don't necessarily have the
15
- // second child node, because you can call procs with a pretty esoteric syntax.
16
- // In the following example, you wouldn't have a second child, and `"foo"` would
17
- // be the first child.
18
- //
19
- // foo[]
20
- //
21
- const printAref = (path, opts, print) => {
22
- if (!path.getValue().index) {
23
- return [path.call(print, "collection"), "[]"];
24
- }
25
- return (0, exports.printArefField)(path, opts, print);
26
- };
27
- exports.printAref = printAref;
28
- // `aref_field` nodes are for assigning values into collections at specific
29
- // indices. Put another way, it's any time you're calling the method `#[]=`.
30
- // The `aref_field` node itself is just the left side of the assignment, and
31
- // they're always wrapped in `assign` nodes.
32
- //
33
- // The nodes always contain two children, the name of the array (usually a
34
- // `vcall` node and the index (usually an `args_add_block` node). The
35
- // `args_add_block` is one of a couple nodes that has special handling where its
36
- // printed form is actually an array to make joining easier.
37
- //
38
- // So in the following example, `"foo"` is the array and `["bar"]` is the index.
39
- //
40
- // foo[bar] = baz
41
- //
42
- const printArefField = (path, opts, print) => {
43
- return group([
44
- path.call(print, "collection"),
45
- "[",
46
- indent([softline, join([",", line], path.call(print, "index"))]),
47
- softline,
48
- "]"
49
- ]);
50
- };
51
- exports.printArefField = printArefField;
@@ -1,138 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printArgStar = exports.printBlockArg = exports.printArgsAddBlock = exports.printArgs = exports.printArgParen = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const toProc_1 = __importDefault(require("../toProc"));
10
- const { group, ifBreak, indent, join, line, softline } = prettier_1.default;
11
- const noTrailingComma = ["command", "command_call"];
12
- function getArgs(node) {
13
- switch (node.type) {
14
- case "args":
15
- return node.parts;
16
- case "args_add_block": {
17
- const args = getArgs(node.args);
18
- return node.block ? [...args, node.block] : args;
19
- }
20
- }
21
- }
22
- function getArgParenTrailingComma(node) {
23
- // If we have a block, then we don't want to add a trailing comma.
24
- if (node.type === "args_add_block" && node.block) {
25
- return "";
26
- }
27
- // If we only have one argument and that first argument necessitates that we
28
- // skip putting a comma (because it would interfere with parsing the argument)
29
- // then we don't want to add a trailing comma.
30
- const args = getArgs(node);
31
- if (args.length === 1 && noTrailingComma.includes(args[0].type)) {
32
- return "";
33
- }
34
- return ifBreak(",", "");
35
- }
36
- const printArgParen = (path, opts, print) => {
37
- const argsNode = path.getValue().args;
38
- if (argsNode === null) {
39
- return "";
40
- }
41
- // Here we can skip the entire rest of the method by just checking if it's
42
- // an args_forward node, as we're guaranteed that there are no other arg
43
- // nodes.
44
- if (argsNode.type === "args_forward") {
45
- return group([
46
- "(",
47
- indent([softline, path.call(print, "args")]),
48
- softline,
49
- ")"
50
- ]);
51
- }
52
- // Now here we return a doc that represents the whole grouped expression,
53
- // including the surrouding parentheses.
54
- return group([
55
- "(",
56
- indent([
57
- softline,
58
- join([",", line], path.call(print, "args")),
59
- (0, utils_1.getTrailingComma)(opts) ? getArgParenTrailingComma(argsNode) : ""
60
- ]),
61
- softline,
62
- ")"
63
- ]);
64
- };
65
- exports.printArgParen = printArgParen;
66
- const printArgs = (path, { rubyToProc }, print) => {
67
- const args = path.map(print, "parts");
68
- // Don't bother trying to do any kind of fancy toProc transform if the
69
- // option is disabled.
70
- if (rubyToProc) {
71
- let blockNode = null;
72
- // Look up the chain to see if these arguments are contained within a
73
- // method_add_block node, and if they are that that node has a block
74
- // associated with it. If it does, we're going to attempt to transform it
75
- // into the to_proc shorthand and add it to the list of arguments.
76
- [1, 2, 3].find((parent) => {
77
- const parentNode = path.getParentNode(parent);
78
- blockNode =
79
- parentNode &&
80
- parentNode.type === "method_add_block" &&
81
- parentNode.block;
82
- return blockNode;
83
- });
84
- const proc = blockNode && (0, toProc_1.default)(path, blockNode);
85
- // If we have a successful to_proc transformation, but we're part of an
86
- // aref node, that means it's something to the effect of
87
- //
88
- // foo[:bar].each(&:to_s)
89
- //
90
- // In this case we need to just return regular arguments, otherwise we
91
- // would end up putting &:to_s inside the brackets accidentally.
92
- if (proc && path.getParentNode(1).type !== "aref") {
93
- args.push(proc);
94
- }
95
- }
96
- return args;
97
- };
98
- exports.printArgs = printArgs;
99
- const printArgsAddBlock = (path, opts, print) => {
100
- const node = path.getValue();
101
- const parts = path.call(print, "args");
102
- if (node.block) {
103
- let blockDoc = path.call(print, "block");
104
- if (!(node.block.comments || []).some(({ leading }) => leading)) {
105
- // If we don't have any leading comments, we can just prepend the
106
- // operator.
107
- blockDoc = ["&", blockDoc];
108
- }
109
- else {
110
- // If we have a method call like:
111
- //
112
- // foo(
113
- // # comment
114
- // &block
115
- // )
116
- //
117
- // then we need to make sure we don't accidentally prepend the operator
118
- // before the comment.
119
- //
120
- // In prettier >= 2.3.0, the comments are printed as an array before the
121
- // content. I don't love this kind of reflection, but it's the simplest
122
- // way at the moment to get this right.
123
- blockDoc = blockDoc[0].concat(["&", blockDoc[1]], blockDoc.slice(2));
124
- }
125
- parts.push(blockDoc);
126
- }
127
- return parts;
128
- };
129
- exports.printArgsAddBlock = printArgsAddBlock;
130
- const printBlockArg = (path, opts, print) => {
131
- return ["&", path.call(print, "name")];
132
- };
133
- exports.printBlockArg = printBlockArg;
134
- const printArgStar = (path, opts, print) => {
135
- const node = path.getValue();
136
- return node.value ? ["*", path.call(print, "value")] : "*";
137
- };
138
- exports.printArgStar = printArgStar;
@@ -1,122 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printArray = exports.printWords = exports.printSymbols = exports.printQwords = exports.printQsymbols = exports.printWord = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const { group, ifBreak, indent, join, line, softline } = prettier_1.default;
10
- // Checks that every argument within this args node is a string_literal node
11
- // that has no spaces or interpolations. This means we're dealing with an array
12
- // that looks something like:
13
- //
14
- // ['a', 'b', 'c']
15
- //
16
- function isStringArray(args) {
17
- return (args.parts.length > 1 &&
18
- args.parts.every((arg) => {
19
- // We want to verify that every node inside of this array is a string
20
- // literal. We also want to make sure none of them have comments attached.
21
- if (arg.type !== "string_literal" || arg.comments) {
22
- return false;
23
- }
24
- // If the string has multiple parts (meaning plain string content but also
25
- // interpolated content) then we know it's not a simple string.
26
- if (arg.parts.length !== 1) {
27
- return false;
28
- }
29
- const part = arg.parts[0];
30
- // If the only part of this string is not @tstring_content then it's
31
- // interpolated, so again we can return false.
32
- if (part.type !== "tstring_content") {
33
- return false;
34
- }
35
- // Finally, verify that the string doesn't contain a space, an escape
36
- // character, or brackets so that we know it can be put into a string
37
- // literal array.
38
- return !/[\s\\[\]]/.test(part.value);
39
- }));
40
- }
41
- // Checks that every argument within this args node is a symbol_literal node (as
42
- // opposed to a dyna_symbol) so it has no interpolation. This means we're
43
- // dealing with an array that looks something like:
44
- //
45
- // [:a, :b, :c]
46
- //
47
- function isSymbolArray(args) {
48
- return (args.parts.length > 1 &&
49
- args.parts.every((arg) => arg.type === "symbol_literal" && !arg.comments));
50
- }
51
- // Prints out a word that is a part of a special array literal that accepts
52
- // interpolation. The body is an array of either plain strings or interpolated
53
- // expressions.
54
- const printWord = (path, opts, print) => {
55
- return path.map(print, "parts");
56
- };
57
- exports.printWord = printWord;
58
- // Prints out a special array literal. Accepts the parts of the array literal as
59
- // an argument, where the first element of the parts array is a string that
60
- // contains the special start.
61
- function printArrayLiteralParts(start, parts) {
62
- return group([
63
- start,
64
- "[",
65
- indent([softline, join(line, parts)]),
66
- softline,
67
- "]"
68
- ]);
69
- }
70
- function printArrayLiteral(start) {
71
- return function printArrayLiteralWithStart(path, opts, print) {
72
- return printArrayLiteralParts(start, path.map(print, "elems"));
73
- };
74
- }
75
- exports.printQsymbols = printArrayLiteral("%i");
76
- exports.printQwords = printArrayLiteral("%w");
77
- exports.printSymbols = printArrayLiteral("%I");
78
- exports.printWords = printArrayLiteral("%W");
79
- // An array node is any literal array in Ruby. This includes all of the special
80
- // array literals as well as regular arrays. If it is a special array literal
81
- // then it will have one child that represents the special array, otherwise it
82
- // will have one child that contains all of the elements of the array.
83
- const printArray = (path, opts, print) => {
84
- const array = path.getValue();
85
- const contents = array.cnts;
86
- // If there is no inner arguments node, then we're dealing with an empty
87
- // array, so we can go ahead and return.
88
- if (contents === null) {
89
- return (0, utils_1.printEmptyCollection)(path, opts, "[", "]");
90
- }
91
- if (opts.rubyArrayLiteral) {
92
- // If we have an array that contains only simple string literals with no
93
- // spaces or interpolation, then we're going to print a %w array.
94
- if (isStringArray(contents)) {
95
- const printString = (stringPath) => stringPath.call(print, "parts", 0);
96
- const nodePath = path;
97
- const parts = nodePath.map(printString, "cnts", "parts");
98
- return printArrayLiteralParts("%w", parts);
99
- }
100
- // If we have an array that contains only simple symbol literals with no
101
- // interpolation, then we're going to print a %i array.
102
- if (isSymbolArray(contents)) {
103
- const printSymbol = (symbolPath) => symbolPath.call(print, "value");
104
- const nodePath = path;
105
- const parts = nodePath.map(printSymbol, "cnts", "parts");
106
- return printArrayLiteralParts("%i", parts);
107
- }
108
- }
109
- // Here we have a normal array of any type of object with no special literal
110
- // types or anything.
111
- return group([
112
- "[",
113
- indent([
114
- softline,
115
- join([",", line], path.call(print, "cnts")),
116
- (0, utils_1.getTrailingComma)(opts) ? ifBreak(",", "") : ""
117
- ]),
118
- softline,
119
- "]"
120
- ]);
121
- };
122
- exports.printArray = printArray;
@@ -1,37 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printVarRef = exports.printVarField = exports.printOpAssign = exports.printAssign = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const { group, indent, join, line } = prettier_1.default;
10
- const printAssign = (...args) => {
11
- return printOpAssignOrAssign("=", ...args);
12
- };
13
- exports.printAssign = printAssign;
14
- const printOpAssign = (path, opts, print) => {
15
- const opDoc = path.call(print, "op");
16
- return printOpAssignOrAssign(opDoc, path, opts, print);
17
- };
18
- exports.printOpAssign = printOpAssign;
19
- function printOpAssignOrAssign(opDoc, path, opts, print) {
20
- const valueNode = path.getValue().value;
21
- const targetDoc = path.call(print, "target");
22
- const valueDoc = path.call(print, "value");
23
- let rightSideDoc = valueDoc;
24
- // If the right side of this assignment is a multiple assignment, then we need
25
- // to join it together with commas.
26
- if (["mrhs", "mrhs_add_star", "mrhs_new_from_args"].includes(valueNode.type)) {
27
- rightSideDoc = group(join([",", line], valueDoc));
28
- }
29
- if ((0, utils_1.skipAssignIndent)(valueNode)) {
30
- return group([targetDoc, " ", opDoc, " ", rightSideDoc]);
31
- }
32
- return group([targetDoc, " ", opDoc, indent([line, rightSideDoc])]);
33
- }
34
- const printVarField = (path, opts, print) => (path.getValue().value ? path.call(print, "value") : "");
35
- exports.printVarField = printVarField;
36
- const printVarRef = (path, opts, print) => path.call(print, "value");
37
- exports.printVarRef = printVarRef;
@@ -1,90 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.printDoBlock = exports.printBraceBlock = exports.printBlockVar = void 0;
7
- const prettier_1 = __importDefault(require("../../prettier"));
8
- const utils_1 = require("../../utils");
9
- const { breakParent, group, ifBreak, indent, join, removeLines, softline } = prettier_1.default;
10
- const printBlockVar = (path, opts, print) => {
11
- const parts = ["|", removeLines(path.call(print, "params"))];
12
- // The second part of this node is a list of optional block-local variables
13
- if (path.getValue().locals.length > 0) {
14
- parts.push("; ", join(", ", path.map(print, "locals")));
15
- }
16
- parts.push("| ");
17
- return parts;
18
- };
19
- exports.printBlockVar = printBlockVar;
20
- // You have to go through the main print function if you could potentially have
21
- // comments attached. So we're doing this weird reflection on the printed docs
22
- // to retroactively change the printed keyword depending on if we're using
23
- // braces or not. Ideally we wouldn't do this, we would instead do this
24
- // reflection in the child printer, but this keeps the logic to just this file
25
- // and contains it, so keeping it here for now.
26
- function printBlockBegin(path, print, useBraces) {
27
- let docs = print(path);
28
- const doc = useBraces && !path.getValue().comments ? "{" : "do";
29
- if (Array.isArray(docs)) {
30
- docs[1] = doc;
31
- }
32
- else {
33
- docs = doc;
34
- }
35
- return docs;
36
- }
37
- function printBlock(braces) {
38
- return function printBlockWithBraces(path, opts, print) {
39
- const node = path.getValue();
40
- const stmts = node.type === "brace_block" ? node.stmts.body : node.bodystmt.stmts.body;
41
- let doBlockBody = "";
42
- if (stmts.length !== 1 ||
43
- stmts[0].type !== "void_stmt" ||
44
- stmts[0].comments) {
45
- doBlockBody = indent([
46
- softline,
47
- path.call(print, node.type === "brace_block" ? "stmts" : "bodystmt")
48
- ]);
49
- }
50
- // If this block is nested underneath a command or command_call node, then
51
- // we can't use `do...end` because that will get associated with the parent
52
- // node as opposed to the current node (because of the difference in
53
- // operator precedence). Instead, we still use a multi-line format but
54
- // switch to using braces instead.
55
- const useBraces = braces && (0, utils_1.hasAncestor)(path, ["command", "command_call"]);
56
- const doBlock = [
57
- " ",
58
- path.call((beginPath) => printBlockBegin(beginPath, print, useBraces), node.type === "brace_block" ? "lbrace" : "keyword"),
59
- node.block_var ? [" ", path.call(print, "block_var")] : "",
60
- doBlockBody,
61
- [softline, useBraces ? "}" : "end"]
62
- ];
63
- // We can hit this next pattern if within the block the only statement is a
64
- // comment.
65
- if (stmts.length === 1 &&
66
- stmts[0].type === "void_stmt" &&
67
- stmts[0].comments) {
68
- return [breakParent, doBlock];
69
- }
70
- const blockReceiver = path.getParentNode().call;
71
- // If the parent node is a command node, then there are no parentheses
72
- // around the arguments to that command, so we need to break the block
73
- if (["command", "command_call"].includes(blockReceiver.type)) {
74
- return [breakParent, doBlock];
75
- }
76
- const hasBody = stmts.some(({ type }) => type !== "void_stmt");
77
- const braceBlock = [
78
- " ",
79
- path.call((beginPath) => printBlockBegin(beginPath, print, true), node.type === "brace_block" ? "lbrace" : "keyword"),
80
- hasBody || node.block_var ? " " : "",
81
- node.block_var ? path.call(print, "block_var") : "",
82
- path.call(print, node.type === "brace_block" ? "stmts" : "bodystmt"),
83
- hasBody ? " " : "",
84
- "}"
85
- ];
86
- return group(ifBreak(doBlock, braceBlock));
87
- };
88
- }
89
- exports.printBraceBlock = printBlock(true);
90
- exports.printDoBlock = printBlock(false);