prettier 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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);