@prettier/plugin-php 0.19.3 → 0.19.5

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.
package/src/printer.js CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  const {
4
4
  breakParent,
5
- concat,
6
5
  join,
7
6
  line,
8
7
  lineSuffix,
@@ -18,11 +17,8 @@ const {
18
17
  dedentToRoot,
19
18
  } = require("prettier").doc.builders;
20
19
  const { willBreak } = require("prettier").doc.utils;
21
- const {
22
- isNextLineEmptyAfterIndex,
23
- hasNewline,
24
- hasNewlineInRange,
25
- } = require("prettier").util;
20
+ const { isNextLineEmptyAfterIndex, hasNewline, hasNewlineInRange } =
21
+ require("prettier").util;
26
22
  const comments = require("./comments");
27
23
  const pathNeedsParens = require("./needs-parens");
28
24
 
@@ -114,11 +110,11 @@ function genericPrint(path, options, print) {
114
110
  parts.push(hardline);
115
111
  }
116
112
 
117
- return concat(parts);
113
+ return parts;
118
114
  }
119
115
 
120
116
  function printPropertyLookup(path, options, print, nullsafe = false) {
121
- return concat([nullsafe ? "?" : "", "->", path.call(print, "offset")]);
117
+ return [nullsafe ? "?" : "", "->", path.call(print, "offset")];
122
118
  }
123
119
 
124
120
  function printNullsafePropertyLookup(path, options, print) {
@@ -129,12 +125,12 @@ function printStaticLookup(path, options, print) {
129
125
  const node = path.getValue();
130
126
  const needCurly = !["variable", "identifier"].includes(node.offset.kind);
131
127
 
132
- return concat([
128
+ return [
133
129
  "::",
134
130
  needCurly ? "{" : "",
135
131
  path.call(print, "offset"),
136
132
  needCurly ? "}" : "",
137
- ]);
133
+ ];
138
134
  }
139
135
 
140
136
  function printOffsetLookup(path, options, print) {
@@ -143,20 +139,16 @@ function printOffsetLookup(path, options, print) {
143
139
  (node.offset && node.offset.kind === "number") ||
144
140
  getAncestorNode(path, "encapsed");
145
141
 
146
- return concat([
142
+ return [
147
143
  "[",
148
144
  node.offset
149
- ? group(
150
- concat([
151
- indent(
152
- concat([shouldInline ? "" : softline, path.call(print, "offset")])
153
- ),
154
- shouldInline ? "" : softline,
155
- ])
156
- )
145
+ ? group([
146
+ indent([shouldInline ? "" : softline, path.call(print, "offset")]),
147
+ shouldInline ? "" : softline,
148
+ ])
157
149
  : "",
158
150
  "]",
159
- ]);
151
+ ];
160
152
  }
161
153
 
162
154
  // We detect calls on member expressions specially to format a
@@ -232,14 +224,14 @@ function printMemberChain(path, options, print) {
232
224
  ) {
233
225
  printedNodes.unshift({
234
226
  node,
235
- printed: concat([
227
+ printed: [
236
228
  comments.printAllComments(
237
229
  path,
238
- () => concat([printArgumentsList(path, options, print)]),
230
+ () => printArgumentsList(path, options, print),
239
231
  options
240
232
  ),
241
233
  shouldInsertEmptyLineAfter(node) ? hardline : "",
242
- ]),
234
+ ],
243
235
  });
244
236
  path.call((what) => traverse(what), "what");
245
237
  } else if (isLookupNode(node)) {
@@ -294,8 +286,8 @@ function printMemberChain(path, options, print) {
294
286
  ) &&
295
287
  printedNodes[i - 1].needsParens
296
288
  ) {
297
- printedNodes[0].printed = concat(["(", printedNodes[0].printed]);
298
- printedNodes[i - 1].printed = concat([printedNodes[i - 1].printed, ")"]);
289
+ printedNodes[0].printed = ["(", printedNodes[0].printed];
290
+ printedNodes[i - 1].printed = [printedNodes[i - 1].printed, ")"];
299
291
  }
300
292
  }
301
293
 
@@ -462,7 +454,7 @@ function printMemberChain(path, options, print) {
462
454
  }
463
455
  }
464
456
 
465
- return concat(result);
457
+ return result;
466
458
  }
467
459
 
468
460
  function printIndentedGroup(groups) {
@@ -470,13 +462,11 @@ function printMemberChain(path, options, print) {
470
462
  return "";
471
463
  }
472
464
 
473
- return indent(
474
- group(concat([hardline, join(hardline, groups.map(printGroup))]))
475
- );
465
+ return indent(group([hardline, join(hardline, groups.map(printGroup))]));
476
466
  }
477
467
 
478
468
  const printedGroups = groups.map(printGroup);
479
- const oneLine = concat(printedGroups);
469
+ const oneLine = printedGroups;
480
470
 
481
471
  // Indicates how many we should merge
482
472
  //
@@ -490,9 +480,7 @@ function printMemberChain(path, options, print) {
490
480
  // ->method()
491
481
  // ->otherMethod();
492
482
  const cutoff = shouldMerge ? 3 : 2;
493
- const flatGroups = groups
494
- .slice(0, cutoff)
495
- .reduce((res, group) => res.concat(group), []);
483
+ const flatGroups = groups.slice(0, cutoff).flat();
496
484
 
497
485
  const hasComment =
498
486
  flatGroups
@@ -521,12 +509,12 @@ function printMemberChain(path, options, print) {
521
509
  lastNodeBeforeIndent.kind !== "call" &&
522
510
  shouldInsertEmptyLineAfter(lastNodeBeforeIndent);
523
511
 
524
- const expanded = concat([
512
+ const expanded = [
525
513
  printGroup(groups[0]),
526
- shouldMerge ? concat(groups.slice(1, 2).map(printGroup)) : "",
514
+ shouldMerge ? groups.slice(1, 2).map(printGroup) : "",
527
515
  shouldHaveEmptyLineBeforeIndent ? hardline : "",
528
516
  printIndentedGroup(groups.slice(shouldMerge ? 2 : 1)),
529
- ]);
517
+ ];
530
518
 
531
519
  const callExpressionCount = printedNodes.filter(
532
520
  (tuple) => tuple.node.kind === "call"
@@ -545,13 +533,13 @@ function printMemberChain(path, options, print) {
545
533
  return group(expanded);
546
534
  }
547
535
 
548
- return concat([
536
+ return [
549
537
  // We only need to check `oneLine` because if `expanded` is chosen
550
538
  // that means that the parent group has already been broken
551
539
  // naturally
552
540
  willBreak(oneLine) || shouldHaveEmptyLineBeforeIndent ? breakParent : "",
553
541
  conditionalGroup([oneLine, expanded]),
554
- ]);
542
+ ];
555
543
  }
556
544
 
557
545
  function couldGroupArg(arg) {
@@ -598,11 +586,11 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
598
586
  const args = path.getValue()[argumentsKey];
599
587
 
600
588
  if (args.length === 0) {
601
- return concat([
589
+ return [
602
590
  "(",
603
591
  comments.printDanglingComments(path, options, /* sameIndent */ true),
604
592
  ")",
605
- ]);
593
+ ];
606
594
  }
607
595
 
608
596
  let anyArgEmptyLine = false;
@@ -626,7 +614,7 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
626
614
  parts.push(",", line);
627
615
  }
628
616
 
629
- return concat(parts);
617
+ return parts;
630
618
  }, argumentsKey);
631
619
 
632
620
  const node = path.getValue();
@@ -639,25 +627,17 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
639
627
  ["function", "closure", "method", "arrowfunc", "attribute"].includes(
640
628
  node.kind
641
629
  ))
642
- ? indent(
643
- concat([
644
- lastArg && shouldPrintHardlineBeforeTrailingComma(lastArg)
645
- ? hardline
646
- : "",
647
- ",",
648
- ])
649
- )
630
+ ? indent([
631
+ lastArg && shouldPrintHardlineBeforeTrailingComma(lastArg)
632
+ ? hardline
633
+ : "",
634
+ ",",
635
+ ])
650
636
  : "";
651
637
 
652
638
  function allArgsBrokenOut() {
653
639
  return group(
654
- concat([
655
- "(",
656
- indent(concat([line, concat(printedArguments)])),
657
- maybeTrailingComma,
658
- line,
659
- ")",
660
- ]),
640
+ ["(", indent([line, ...printedArguments]), maybeTrailingComma, line, ")"],
661
641
  { shouldBreak: true }
662
642
  );
663
643
  }
@@ -678,28 +658,28 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
678
658
  path.each((argPath) => {
679
659
  if (shouldGroupFirst && i === 0) {
680
660
  printedExpanded = [
681
- concat([
682
- argPath.call((p) => print(p, { expandFirstArg: true })),
683
- printedArguments.length > 1 ? "," : "",
684
- hasEmptyLineFollowingFirstArg ? hardline : line,
685
- hasEmptyLineFollowingFirstArg ? hardline : "",
686
- ]),
687
- ].concat(printedArguments.slice(1));
661
+ argPath.call((p) => print(p, { expandFirstArg: true })),
662
+ printedArguments.length > 1 ? "," : "",
663
+ hasEmptyLineFollowingFirstArg ? hardline : line,
664
+ hasEmptyLineFollowingFirstArg ? hardline : "",
665
+ printedArguments.slice(1),
666
+ ];
688
667
  }
689
668
 
690
669
  if (shouldGroupLast && i === args.length - 1) {
691
- printedExpanded = printedArguments
692
- .slice(0, -1)
693
- .concat(argPath.call((p) => print(p, { expandLastArg: true })));
670
+ printedExpanded = [
671
+ ...printedArguments.slice(0, -1),
672
+ argPath.call((p) => print(p, { expandLastArg: true })),
673
+ ];
694
674
  }
695
675
 
696
676
  i++;
697
677
  }, argumentsKey);
698
678
 
699
679
  const somePrintedArgumentsWillBreak = printedArguments.some(willBreak);
700
- const simpleConcat = concat(["(", concat(printedExpanded), ")"]);
680
+ const simpleConcat = ["(", ...printedExpanded, ")"];
701
681
 
702
- return concat([
682
+ return [
703
683
  somePrintedArgumentsWillBreak ? breakParent : "",
704
684
  conditionalGroup(
705
685
  [
@@ -707,44 +687,44 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
707
687
  ? simpleConcat
708
688
  : ifBreak(allArgsBrokenOut(), simpleConcat),
709
689
  shouldGroupFirst
710
- ? concat([
690
+ ? [
711
691
  "(",
712
692
  group(printedExpanded[0], { shouldBreak: true }),
713
- concat(printedExpanded.slice(1)),
693
+ ...printedExpanded.slice(1),
714
694
  ")",
715
- ])
716
- : concat([
695
+ ]
696
+ : [
717
697
  "(",
718
- concat(printedArguments.slice(0, -1)),
698
+ ...printedArguments.slice(0, -1),
719
699
  group(getLast(printedExpanded), {
720
700
  shouldBreak: true,
721
701
  }),
722
702
  ")",
723
- ]),
703
+ ],
724
704
  group(
725
- concat([
705
+ [
726
706
  "(",
727
- indent(concat([line, concat(printedArguments)])),
707
+ indent([line, ...printedArguments]),
728
708
  ifBreak(maybeTrailingComma),
729
709
  line,
730
710
  ")",
731
- ]),
711
+ ],
732
712
  { shouldBreak: true }
733
713
  ),
734
714
  ],
735
715
  { shouldBreak }
736
716
  ),
737
- ]);
717
+ ];
738
718
  }
739
719
 
740
720
  return group(
741
- concat([
721
+ [
742
722
  "(",
743
- indent(concat([softline, concat(printedArguments)])),
723
+ indent([softline, ...printedArguments]),
744
724
  ifBreak(maybeTrailingComma),
745
725
  softline,
746
726
  ")",
747
- ]),
727
+ ],
748
728
  {
749
729
  shouldBreak: printedArguments.some(willBreak) || anyArgEmptyLine,
750
730
  }
@@ -809,8 +789,8 @@ function printBinaryExpression(
809
789
  const shouldInline = shouldInlineLogicalExpression(node);
810
790
 
811
791
  const right = shouldInline
812
- ? concat([node.type, " ", path.call(print, "right")])
813
- : concat([node.type, line, path.call(print, "right")]);
792
+ ? [node.type, " ", path.call(print, "right")]
793
+ : [node.type, line, path.call(print, "right")];
814
794
 
815
795
  // If there's only a single binary expression, we want to create a group
816
796
  // in order to avoid having a small right part like -1 be on its own line.
@@ -837,7 +817,7 @@ function printBinaryExpression(
837
817
  // the other ones since we don't call the normal print on bin,
838
818
  // only for the left and right parts
839
819
  if (isNested && node.comments) {
840
- parts = comments.printAllComments(path, () => concat(parts), options);
820
+ parts = comments.printAllComments(path, () => parts, options);
841
821
  }
842
822
  } else {
843
823
  // Our stopping case. Simply print the node normally.
@@ -888,7 +868,7 @@ function printArrayItems(path, options, print) {
888
868
  let separatorParts = [];
889
869
 
890
870
  path.each((childPath) => {
891
- printedElements.push(concat(separatorParts));
871
+ printedElements.push(separatorParts);
892
872
  printedElements.push(group(print(childPath)));
893
873
 
894
874
  separatorParts = [",", line];
@@ -901,7 +881,7 @@ function printArrayItems(path, options, print) {
901
881
  }
902
882
  }, "items");
903
883
 
904
- return concat(printedElements);
884
+ return printedElements;
905
885
  }
906
886
 
907
887
  // Wrap parts into groups by indexes.
@@ -925,19 +905,17 @@ function wrapPartsIntoGroups(parts, indexes) {
925
905
 
926
906
  return indexes.reduce((accumulator, index) => {
927
907
  const { start, end, alignment, before, after } = index;
928
- const printedPartsForGrouping = concat([
908
+ const printedPartsForGrouping = [
929
909
  before || "",
930
- concat(parts.slice(start, end)),
910
+ ...parts.slice(start, end),
931
911
  after || "",
932
- ]);
912
+ ];
933
913
  const newArray = accumulator.concat(
934
914
  parts.slice(lastEnd, start),
935
915
  alignment
936
916
  ? dedentToRoot(
937
917
  group(
938
- concat([
939
- align(new Array(alignment).join(" "), printedPartsForGrouping),
940
- ])
918
+ align(new Array(alignment).join(" "), printedPartsForGrouping)
941
919
  )
942
920
  )
943
921
  : group(printedPartsForGrouping),
@@ -972,14 +950,14 @@ function printLines(path, options, print, childrenAttribute = "children") {
972
950
  ? !isFirstChildrenInlineNode(path)
973
951
  : nextNode && nextNode.kind !== "inline");
974
952
 
975
- let printed = concat([
953
+ let printed = [
976
954
  printedPath,
977
955
  canPrintBlankLine ? hardline : "",
978
956
  canPrintBlankLine &&
979
957
  isNextLineEmpty(options.originalText, childNode, options)
980
958
  ? hardline
981
959
  : "",
982
- ]);
960
+ ];
983
961
 
984
962
  const isFirstNode = index === 0;
985
963
  const isLastNode = children.length - 1 === index;
@@ -1040,7 +1018,7 @@ function printLines(path, options, print, childrenAttribute = "children") {
1040
1018
  : "<?php";
1041
1019
  const beforeInline =
1042
1020
  childNode.leadingComments && childNode.leadingComments.length
1043
- ? concat([
1021
+ ? [
1044
1022
  isFirstNode && node.kind !== "namespace" && !isBlockNestedNode
1045
1023
  ? "<?php"
1046
1024
  : "",
@@ -1048,30 +1026,29 @@ function printLines(path, options, print, childrenAttribute = "children") {
1048
1026
  comments.printComments(childNode.leadingComments, options),
1049
1027
  hardline,
1050
1028
  "?>",
1051
- ])
1029
+ ]
1052
1030
  : isProgramLikeNode(node) && isFirstNode && node.kind !== "namespace"
1053
1031
  ? ""
1054
- : concat([beforeCloseTagInlineNode, "?>"]);
1032
+ : [beforeCloseTagInlineNode, "?>"];
1055
1033
 
1056
1034
  const nextV = path.getNode(index + 1);
1057
1035
  const skipLastComment = nextV && nextV.children && nextV.children.length;
1058
1036
 
1059
1037
  const afterInline =
1060
1038
  childNode.comments && childNode.comments.length
1061
- ? concat([
1039
+ ? [
1062
1040
  openTag,
1063
1041
  hardline,
1064
1042
  skipLastComment
1065
1043
  ? comments.printComments(childNode.comments, options)
1066
1044
  : "",
1067
1045
  hardline,
1068
- skipLastComment ? "?>" : "",
1069
- ])
1046
+ ]
1070
1047
  : isProgramLikeNode(node) && isLastNode
1071
1048
  ? ""
1072
- : concat([openTag, " "]);
1049
+ : [openTag, " "];
1073
1050
 
1074
- printed = concat([beforeInline, printed, afterInline]);
1051
+ printed = [beforeInline, printed, afterInline];
1075
1052
  }
1076
1053
 
1077
1054
  parts.push(printed);
@@ -1087,73 +1064,74 @@ function printLines(path, options, print, childrenAttribute = "children") {
1087
1064
 
1088
1065
  if (hasStartTag) {
1089
1066
  const between = options.originalText.trim().match(/^<\?(php|=)(\s+)?\S/);
1090
- const afterOpenTag = concat([
1067
+ const afterOpenTag = [
1091
1068
  between && between[2] && between[2].includes("\n")
1092
- ? concat([
1093
- hardline,
1094
- between[2].split("\n").length > 2 ? hardline : "",
1095
- ])
1069
+ ? [hardline, between[2].split("\n").length > 2 ? hardline : ""]
1096
1070
  : " ",
1097
1071
  node.comments ? comments.printComments(node.comments, options) : "",
1098
- ]);
1072
+ ];
1099
1073
 
1100
1074
  const shortEcho =
1101
1075
  firstNode && firstNode.kind === "echo" && firstNode.shortForm;
1102
- parts.push(concat([shortEcho ? "<?=" : "<?php", afterOpenTag]));
1076
+ parts.push([shortEcho ? "<?=" : "<?php", afterOpenTag]);
1103
1077
  }
1104
1078
 
1105
- parts.push(concat(wrappedParts));
1079
+ parts.push(wrappedParts);
1106
1080
 
1107
- const hasEndTag = options.originalText.trim().endsWith("?>");
1081
+ const hasEndTag = /\?>\n?$/.test(options.originalText);
1108
1082
 
1109
1083
  if (hasEndTag) {
1110
1084
  const lastNode = getLast(node.children);
1111
1085
  const beforeCloseTag = lastNode
1112
- ? concat([
1086
+ ? [
1113
1087
  hasNewlineInRange(
1114
1088
  options.originalText.trimEnd(),
1115
1089
  options.locEnd(lastNode),
1116
1090
  options.locEnd(node)
1117
1091
  )
1118
- ? hardline
1092
+ ? !(
1093
+ lastNode.kind === "inline" &&
1094
+ lastNode.comments &&
1095
+ lastNode.comments.length
1096
+ )
1097
+ ? hardline
1098
+ : ""
1119
1099
  : " ",
1120
1100
  isNextLineEmpty(options.originalText, lastNode, options)
1121
1101
  ? hardline
1122
1102
  : "",
1123
- ])
1103
+ ]
1124
1104
  : node.comments
1125
1105
  ? hardline
1126
1106
  : "";
1127
1107
 
1128
- parts.push(lineSuffix(concat([beforeCloseTag, "?>"])));
1108
+ parts.push(lineSuffix([beforeCloseTag, "?>"]));
1129
1109
  }
1130
1110
 
1131
- return concat(parts);
1111
+ return parts;
1132
1112
  }
1133
1113
 
1134
- return concat(wrappedParts);
1114
+ return wrappedParts;
1135
1115
  }
1136
1116
 
1137
1117
  function printStatements(path, options, print, childrenAttribute) {
1138
- return concat(
1139
- path.map((childPath) => {
1140
- const parts = [];
1118
+ return path.map((childPath) => {
1119
+ const parts = [];
1141
1120
 
1142
- parts.push(print(childPath));
1121
+ parts.push(print(childPath));
1143
1122
 
1144
- if (!isLastStatement(childPath)) {
1145
- parts.push(hardline);
1123
+ if (!isLastStatement(childPath)) {
1124
+ parts.push(hardline);
1146
1125
 
1147
- if (
1148
- isNextLineEmpty(options.originalText, childPath.getValue(), options)
1149
- ) {
1150
- parts.push(hardline);
1151
- }
1126
+ if (
1127
+ isNextLineEmpty(options.originalText, childPath.getValue(), options)
1128
+ ) {
1129
+ parts.push(hardline);
1152
1130
  }
1131
+ }
1153
1132
 
1154
- return concat(parts);
1155
- }, childrenAttribute)
1156
- );
1133
+ return parts;
1134
+ }, childrenAttribute);
1157
1135
  }
1158
1136
 
1159
1137
  function printClassPart(
@@ -1166,46 +1144,40 @@ function printClassPart(
1166
1144
  ) {
1167
1145
  const node = path.getValue();
1168
1146
  const printedBeforePart = hasDanglingComments(node[part])
1169
- ? concat([
1147
+ ? [
1170
1148
  hardline,
1171
1149
  path.call(
1172
1150
  (partPath) => comments.printDanglingComments(partPath, options, true),
1173
1151
  part
1174
1152
  ),
1175
1153
  hardline,
1176
- ])
1154
+ ]
1177
1155
  : beforePart;
1178
1156
  const printedPartItems = Array.isArray(node[part])
1179
1157
  ? group(
1180
- concat([
1181
- join(
1182
- ",",
1183
- path.map((itemPartPath) => {
1184
- const printedPart = print(itemPartPath);
1185
- // Check if any of the implements nodes have comments
1186
- return hasDanglingComments(itemPartPath.getValue())
1187
- ? concat([
1188
- hardline,
1189
- comments.printDanglingComments(itemPartPath, options, true),
1190
- hardline,
1191
- printedPart,
1192
- ])
1193
- : concat([afterPart, printedPart]);
1194
- }, part)
1195
- ),
1196
- ])
1158
+ join(
1159
+ ",",
1160
+ path.map((itemPartPath) => {
1161
+ const printedPart = print(itemPartPath);
1162
+ // Check if any of the implements nodes have comments
1163
+ return hasDanglingComments(itemPartPath.getValue())
1164
+ ? [
1165
+ hardline,
1166
+ comments.printDanglingComments(itemPartPath, options, true),
1167
+ hardline,
1168
+ printedPart,
1169
+ ]
1170
+ : [afterPart, printedPart];
1171
+ }, part)
1172
+ )
1197
1173
  )
1198
- : concat([afterPart, path.call(print, part)]);
1199
-
1200
- return indent(
1201
- concat([
1202
- printedBeforePart,
1203
- part,
1204
- willBreak(printedBeforePart)
1205
- ? indent(printedPartItems)
1206
- : printedPartItems,
1207
- ])
1208
- );
1174
+ : [afterPart, path.call(print, part)];
1175
+
1176
+ return indent([
1177
+ printedBeforePart,
1178
+ part,
1179
+ willBreak(printedBeforePart) ? indent(printedPartItems) : printedPartItems,
1180
+ ]);
1209
1181
  }
1210
1182
 
1211
1183
  function printAttrs(path, options, print, { inline = false } = {}) {
@@ -1228,24 +1200,22 @@ function printAttrs(path, options, print, { inline = false } = {}) {
1228
1200
  if (attrNode.args.length > 0) {
1229
1201
  attrStmt.push(printArgumentsList(attrPath, options, print, "args"));
1230
1202
  }
1231
- attrGroup.push(group(concat(attrStmt)));
1203
+ attrGroup.push(group(attrStmt));
1232
1204
  }, "attrs");
1233
1205
  allAttrs.push(
1234
- group(
1235
- concat([
1236
- indent(concat(attrGroup)),
1237
- ifBreak(shouldPrintComma(options, "8.0") ? "," : ""),
1238
- softline,
1239
- "]",
1240
- inline ? ifBreak(softline, " ") : "",
1241
- ])
1242
- )
1206
+ group([
1207
+ indent(attrGroup),
1208
+ ifBreak(shouldPrintComma(options, "8.0") ? "," : ""),
1209
+ softline,
1210
+ "]",
1211
+ inline ? ifBreak(softline, " ") : "",
1212
+ ])
1243
1213
  );
1244
1214
  }, "attrGroups");
1245
1215
  if (allAttrs.length === 0) {
1246
1216
  return [];
1247
1217
  }
1248
- return [concat([...allAttrs, inline ? "" : hardline])];
1218
+ return [...allAttrs, inline ? "" : hardline];
1249
1219
  }
1250
1220
 
1251
1221
  function printClass(path, options, print) {
@@ -1282,15 +1252,15 @@ function printClass(path, options, print) {
1282
1252
  declaration.push(
1283
1253
  conditionalGroup(
1284
1254
  [
1285
- concat([
1255
+ [
1286
1256
  printClassPart(path, options, print, "extends"),
1287
1257
  printClassPart(path, options, print, "implements"),
1288
- ]),
1289
- concat([
1258
+ ],
1259
+ [
1290
1260
  printClassPart(path, options, print, "extends"),
1291
1261
  printClassPart(path, options, print, "implements", " ", hardline),
1292
- ]),
1293
- concat([
1262
+ ],
1263
+ [
1294
1264
  printClassPart(path, options, print, "extends", hardline, " "),
1295
1265
  printClassPart(
1296
1266
  path,
@@ -1300,7 +1270,7 @@ function printClass(path, options, print) {
1300
1270
  hardline,
1301
1271
  node.implements.length > 1 ? hardline : " "
1302
1272
  ),
1303
- ]),
1273
+ ],
1304
1274
  ],
1305
1275
  {
1306
1276
  shouldBreak: hasDanglingComments(node.extends),
@@ -1343,33 +1313,29 @@ function printClass(path, options, print) {
1343
1313
  }
1344
1314
  }
1345
1315
 
1346
- const printedDeclaration = group(
1347
- concat([
1348
- group(concat(declaration)),
1349
- shouldPrintHardlineForOpenBrace(options)
1350
- ? isAnonymousClass
1351
- ? line
1352
- : hardline
1353
- : " ",
1354
- ])
1355
- );
1316
+ const printedDeclaration = group([
1317
+ group(declaration),
1318
+ shouldPrintHardlineForOpenBrace(options)
1319
+ ? isAnonymousClass
1320
+ ? line
1321
+ : hardline
1322
+ : " ",
1323
+ ]);
1356
1324
 
1357
1325
  const hasEmptyClassBody =
1358
1326
  node.body && node.body.length === 0 && !hasDanglingComments(node);
1359
- const printedBody = concat([
1327
+ const printedBody = [
1360
1328
  "{",
1361
- indent(
1362
- concat([
1363
- hasEmptyClassBody ? "" : hardline,
1364
- printStatements(path, options, print, "body"),
1365
- ])
1366
- ),
1329
+ indent([
1330
+ hasEmptyClassBody ? "" : hardline,
1331
+ printStatements(path, options, print, "body"),
1332
+ ]),
1367
1333
  comments.printDanglingComments(path, options, true),
1368
1334
  isAnonymousClass && hasEmptyClassBody ? softline : hardline,
1369
1335
  "}",
1370
- ]);
1336
+ ];
1371
1337
 
1372
- return concat([printedDeclaration, printedBody]);
1338
+ return [printedDeclaration, printedBody];
1373
1339
  }
1374
1340
 
1375
1341
  function printFunction(path, options, print) {
@@ -1409,76 +1375,72 @@ function printFunction(path, options, print) {
1409
1375
 
1410
1376
  if (node.uses && node.uses.length > 0) {
1411
1377
  declaration.push(
1412
- group(concat([" use ", printArgumentsList(path, options, print, "uses")]))
1378
+ group([" use ", printArgumentsList(path, options, print, "uses")])
1413
1379
  );
1414
1380
  }
1415
1381
 
1416
1382
  if (node.type) {
1417
- declaration.push(
1418
- concat([
1419
- ": ",
1420
- hasDanglingComments(node.type)
1421
- ? concat([
1422
- path.call(
1423
- (typePath) =>
1424
- comments.printDanglingComments(typePath, options, true),
1425
- "type"
1426
- ),
1427
- " ",
1428
- ])
1429
- : "",
1430
- node.nullable ? "?" : "",
1431
- path.call(print, "type"),
1432
- ])
1433
- );
1383
+ declaration.push([
1384
+ ": ",
1385
+ hasDanglingComments(node.type)
1386
+ ? [
1387
+ path.call(
1388
+ (typePath) =>
1389
+ comments.printDanglingComments(typePath, options, true),
1390
+ "type"
1391
+ ),
1392
+ " ",
1393
+ ]
1394
+ : "",
1395
+ node.nullable ? "?" : "",
1396
+ path.call(print, "type"),
1397
+ ]);
1434
1398
  }
1435
1399
 
1436
- const printedDeclaration = concat(declaration);
1400
+ const printedDeclaration = declaration;
1437
1401
 
1438
1402
  if (!node.body) {
1439
- return concat([...declAttrs, printedDeclaration]);
1403
+ return [...declAttrs, printedDeclaration];
1440
1404
  }
1441
1405
 
1442
1406
  const isClosure = node.kind === "closure";
1443
- const printedBody = concat([
1407
+ const printedBody = [
1444
1408
  "{",
1445
- indent(
1446
- concat([hasEmptyBody(path) ? "" : hardline, path.call(print, "body")])
1447
- ),
1409
+ indent([hasEmptyBody(path) ? "" : hardline, path.call(print, "body")]),
1448
1410
  isClosure && hasEmptyBody(path) ? "" : hardline,
1449
1411
  "}",
1450
- ]);
1412
+ ];
1451
1413
 
1452
1414
  if (isClosure) {
1453
- return concat([...declAttrs, printedDeclaration, " ", printedBody]);
1415
+ return [...declAttrs, printedDeclaration, " ", printedBody];
1454
1416
  }
1455
1417
 
1456
1418
  if (node.arguments.length === 0) {
1457
- return concat([
1419
+ return [
1458
1420
  ...declAttrs,
1459
1421
  printedDeclaration,
1460
1422
  shouldPrintHardlineForOpenBrace(options) ? hardline : " ",
1461
1423
  printedBody,
1462
- ]);
1424
+ ];
1463
1425
  }
1464
1426
 
1465
1427
  const willBreakDeclaration = declaration.some(willBreak);
1466
1428
 
1467
1429
  if (willBreakDeclaration) {
1468
- return concat([printedDeclaration, " ", printedBody]);
1430
+ return [printedDeclaration, " ", printedBody];
1469
1431
  }
1470
1432
 
1471
- return concat([
1433
+ return [
1472
1434
  ...declAttrs,
1473
1435
  conditionalGroup([
1474
- concat([
1436
+ [
1475
1437
  printedDeclaration,
1476
1438
  shouldPrintHardlineForOpenBrace(options) ? hardline : " ",
1477
1439
  printedBody,
1478
- ]),
1479
- concat([printedDeclaration, " ", printedBody]),
1440
+ ],
1441
+ [printedDeclaration, " ", printedBody],
1480
1442
  ]),
1481
- ]);
1443
+ ];
1482
1444
  }
1483
1445
 
1484
1446
  function printBodyControlStructure(
@@ -1495,32 +1457,30 @@ function printBodyControlStructure(
1495
1457
 
1496
1458
  const printedBody = path.call(print, bodyProperty);
1497
1459
 
1498
- return concat([
1460
+ return [
1499
1461
  node.shortForm ? ":" : " {",
1500
1462
  indent(
1501
- concat([
1502
- node[bodyProperty].kind !== "block" ||
1463
+ node[bodyProperty].kind !== "block" ||
1503
1464
  (node[bodyProperty].children &&
1504
1465
  node[bodyProperty].children.length > 0) ||
1505
1466
  (node[bodyProperty].comments && node[bodyProperty].comments.length > 0)
1506
- ? concat([
1507
- shouldPrintHardLineAfterStartInControlStructure(path)
1508
- ? node.kind === "switch"
1509
- ? " "
1510
- : ""
1511
- : hardline,
1512
- printedBody,
1513
- ])
1514
- : "",
1515
- ])
1467
+ ? [
1468
+ shouldPrintHardLineAfterStartInControlStructure(path)
1469
+ ? node.kind === "switch"
1470
+ ? " "
1471
+ : ""
1472
+ : hardline,
1473
+ printedBody,
1474
+ ]
1475
+ : ""
1516
1476
  ),
1517
1477
  node.kind === "if" && bodyProperty === "body"
1518
1478
  ? ""
1519
- : concat([
1479
+ : [
1520
1480
  shouldPrintHardLineBeforeEndInControlStructure(path) ? hardline : "",
1521
- node.shortForm ? concat(["end", node.kind, ";"]) : "}",
1522
- ]),
1523
- ]);
1481
+ node.shortForm ? ["end", node.kind, ";"] : "}",
1482
+ ],
1483
+ ];
1524
1484
  }
1525
1485
 
1526
1486
  function printAssignment(
@@ -1544,7 +1504,7 @@ function printAssignment(
1544
1504
  options
1545
1505
  );
1546
1506
 
1547
- return group(concat([printedLeft, operator, printed]));
1507
+ return group([printedLeft, operator, printed]);
1548
1508
  }
1549
1509
 
1550
1510
  function isLookupNodeChain(node) {
@@ -1571,7 +1531,7 @@ function printAssignmentRight(
1571
1531
  if (
1572
1532
  comments.hasLeadingOwnLineComment(options.originalText, rightNode, options)
1573
1533
  ) {
1574
- return indent(concat([hardline, ref, printedRight]));
1534
+ return indent([hardline, ref, printedRight]);
1575
1535
  }
1576
1536
 
1577
1537
  const pureRightNode = rightNode.kind === "cast" ? rightNode.expr : rightNode;
@@ -1591,10 +1551,10 @@ function printAssignmentRight(
1591
1551
  isLookupNodeChain(pureRightNode)));
1592
1552
 
1593
1553
  if (canBreak) {
1594
- return group(indent(concat([line, ref, printedRight])));
1554
+ return group(indent([line, ref, printedRight]));
1595
1555
  }
1596
1556
 
1597
- return concat([" ", ref, printedRight]);
1557
+ return [" ", ref, printedRight];
1598
1558
  }
1599
1559
 
1600
1560
  function needsHardlineAfterDanglingComment(node) {
@@ -1625,12 +1585,9 @@ function isStringOnItsOwnLine(node, text, options) {
1625
1585
 
1626
1586
  function printComposedTypes(path, print, glue) {
1627
1587
  return group(
1628
- concat(
1629
- path.map(
1630
- (uPath, i) =>
1631
- concat(i === 0 ? [path.call(print)] : [glue, path.call(print)]),
1632
- "types"
1633
- )
1588
+ path.map(
1589
+ (uPath, i) => (i === 0 ? [path.call(print)] : [glue, path.call(print)]),
1590
+ "types"
1634
1591
  )
1635
1592
  );
1636
1593
  }
@@ -1640,76 +1597,74 @@ function printNode(path, options, print) {
1640
1597
 
1641
1598
  switch (node.kind) {
1642
1599
  case "program": {
1643
- return group(
1644
- concat([
1645
- printLines(path, options, print),
1646
- comments.printDanglingComments(
1647
- path,
1648
- options,
1649
- /* sameIndent */ true,
1650
- (c) => !c.printed
1651
- ),
1652
- ])
1653
- );
1600
+ return group([
1601
+ printLines(path, options, print),
1602
+ comments.printDanglingComments(
1603
+ path,
1604
+ options,
1605
+ /* sameIndent */ true,
1606
+ (c) => !c.printed
1607
+ ),
1608
+ ]);
1654
1609
  }
1655
1610
  case "expressionstatement":
1656
1611
  return path.call(print, "expression");
1657
1612
  case "block":
1658
- return concat([
1613
+ return [
1659
1614
  printLines(path, options, print),
1660
1615
  comments.printDanglingComments(path, options, true),
1661
- ]);
1616
+ ];
1662
1617
  case "declare": {
1663
1618
  const printDeclareArguments = (path) => {
1664
1619
  return join(
1665
1620
  ", ",
1666
- path.map((directive) => concat([print(directive)]), "directives")
1621
+ path.map((directive) => print(directive), "directives")
1667
1622
  );
1668
1623
  };
1669
1624
 
1670
1625
  if (["block", "short"].includes(node.mode)) {
1671
- return concat([
1626
+ return [
1672
1627
  "declare(",
1673
1628
  printDeclareArguments(path),
1674
1629
  ")",
1675
1630
  node.mode === "block" ? " {" : ":",
1676
1631
  node.children.length > 0
1677
- ? indent(concat([hardline, printLines(path, options, print)]))
1632
+ ? indent([hardline, printLines(path, options, print)])
1678
1633
  : "",
1679
1634
  comments.printDanglingComments(path, options),
1680
1635
  hardline,
1681
1636
  node.mode === "block" ? "}" : "enddeclare;",
1682
- ]);
1637
+ ];
1683
1638
  }
1684
1639
 
1685
1640
  const nextNode = getNextNode(path, node);
1686
1641
 
1687
- return concat([
1642
+ return [
1688
1643
  "declare(",
1689
1644
  printDeclareArguments(path),
1690
1645
  ")",
1691
1646
  nextNode && nextNode.kind === "inline" ? "" : ";",
1692
- ]);
1647
+ ];
1693
1648
  }
1694
1649
  case "declaredirective":
1695
- return concat([path.call(print, "key"), "=", path.call(print, "value")]);
1650
+ return [path.call(print, "key"), "=", path.call(print, "value")];
1696
1651
  case "namespace":
1697
- return concat([
1652
+ return [
1698
1653
  "namespace ",
1699
1654
  node.name && typeof node.name === "string"
1700
- ? concat([node.name, node.withBrackets ? " " : ""])
1655
+ ? [node.name, node.withBrackets ? " " : ""]
1701
1656
  : "",
1702
1657
  node.withBrackets ? "{" : ";",
1703
1658
  hasDanglingComments(node)
1704
- ? concat([" ", comments.printDanglingComments(path, options, true)])
1659
+ ? [" ", comments.printDanglingComments(path, options, true)]
1705
1660
  : "",
1706
1661
  node.children.length > 0
1707
1662
  ? node.withBrackets
1708
- ? indent(concat([hardline, printLines(path, options, print)]))
1709
- : concat([
1663
+ ? indent([hardline, printLines(path, options, print)])
1664
+ : [
1710
1665
  node.children[0].kind === "inline"
1711
1666
  ? ""
1712
- : concat([
1667
+ : [
1713
1668
  hardline,
1714
1669
  isNextLineEmptyAfterNamespace(
1715
1670
  options.originalText,
@@ -1718,121 +1673,109 @@ function printNode(path, options, print) {
1718
1673
  )
1719
1674
  ? hardline
1720
1675
  : "",
1721
- ]),
1676
+ ],
1722
1677
  printLines(path, options, print),
1723
- ])
1678
+ ]
1724
1679
  : "",
1725
- node.withBrackets ? concat([hardline, "}"]) : "",
1726
- ]);
1680
+ node.withBrackets ? [hardline, "}"] : "",
1681
+ ];
1727
1682
  case "usegroup":
1728
- return group(
1729
- concat([
1730
- "use ",
1731
- node.type ? concat([node.type, " "]) : "",
1732
- indent(
1733
- concat([
1734
- node.name
1735
- ? concat([
1736
- maybeStripLeadingSlashFromUse(node.name),
1737
- "\\{",
1738
- softline,
1739
- ])
1740
- : "",
1741
- join(
1742
- concat([",", line]),
1743
- path.map((item) => concat([print(item)]), "items")
1744
- ),
1745
- ])
1746
- ),
1683
+ return group([
1684
+ "use ",
1685
+ node.type ? [node.type, " "] : "",
1686
+ indent([
1747
1687
  node.name
1748
- ? concat([
1749
- ifBreak(shouldPrintComma(options, "7.2") ? "," : ""),
1750
- softline,
1751
- "}",
1752
- ])
1688
+ ? [maybeStripLeadingSlashFromUse(node.name), "\\{", softline]
1753
1689
  : "",
1754
- ])
1755
- );
1690
+ join(
1691
+ [",", line],
1692
+ path.map((item) => print(item), "items")
1693
+ ),
1694
+ ]),
1695
+ node.name
1696
+ ? [
1697
+ ifBreak(shouldPrintComma(options, "7.2") ? "," : ""),
1698
+ softline,
1699
+ "}",
1700
+ ]
1701
+ : "",
1702
+ ]);
1756
1703
  case "useitem":
1757
- return concat([
1758
- node.type ? concat([node.type, " "]) : "",
1704
+ return [
1705
+ node.type ? [node.type, " "] : "",
1759
1706
  maybeStripLeadingSlashFromUse(node.name),
1760
1707
  hasDanglingComments(node)
1761
- ? concat([" ", comments.printDanglingComments(path, options, true)])
1708
+ ? [" ", comments.printDanglingComments(path, options, true)]
1762
1709
  : "",
1763
- node.alias ? concat([" as ", path.call(print, "alias")]) : "",
1764
- ]);
1710
+ node.alias ? [" as ", path.call(print, "alias")] : "",
1711
+ ];
1765
1712
  case "class":
1766
1713
  case "enum":
1767
1714
  case "interface":
1768
1715
  case "trait":
1769
1716
  return printClass(path, options, print);
1770
1717
  case "traitprecedence":
1771
- return concat([
1718
+ return [
1772
1719
  path.call(print, "trait"),
1773
1720
  "::",
1774
1721
  path.call(print, "method"),
1775
1722
  " insteadof ",
1776
1723
  join(", ", path.map(print, "instead")),
1777
- ]);
1724
+ ];
1778
1725
  case "traitalias":
1779
- return concat([
1780
- node.trait ? concat([path.call(print, "trait"), "::"]) : "",
1726
+ return [
1727
+ node.trait ? [path.call(print, "trait"), "::"] : "",
1781
1728
  node.method ? path.call(print, "method") : "",
1782
1729
  " as ",
1783
1730
  join(" ", [
1784
1731
  ...(node.visibility ? [node.visibility] : []),
1785
1732
  ...(node.as ? [path.call(print, "as")] : []),
1786
1733
  ]),
1787
- ]);
1734
+ ];
1788
1735
  case "traituse":
1789
- return group(
1790
- concat([
1791
- "use ",
1792
- indent(group(join(concat([",", line]), path.map(print, "traits")))),
1793
- node.adaptations
1794
- ? concat([
1795
- " {",
1796
- node.adaptations.length > 0
1797
- ? concat([
1798
- indent(
1799
- concat([
1800
- hardline,
1801
- printStatements(path, options, print, "adaptations"),
1802
- ])
1803
- ),
1736
+ return group([
1737
+ "use ",
1738
+ indent(group(join([",", line], path.map(print, "traits")))),
1739
+ node.adaptations
1740
+ ? [
1741
+ " {",
1742
+ node.adaptations.length > 0
1743
+ ? [
1744
+ indent([
1804
1745
  hardline,
1805
- ])
1806
- : hasDanglingComments(node)
1807
- ? concat([
1808
- line,
1809
- comments.printDanglingComments(path, options, true),
1810
- line,
1811
- ])
1812
- : "",
1813
- "}",
1814
- ])
1815
- : "",
1816
- ])
1817
- );
1746
+ printStatements(path, options, print, "adaptations"),
1747
+ ]),
1748
+ hardline,
1749
+ ]
1750
+ : hasDanglingComments(node)
1751
+ ? [
1752
+ line,
1753
+ comments.printDanglingComments(path, options, true),
1754
+ line,
1755
+ ]
1756
+ : "",
1757
+ "}",
1758
+ ]
1759
+ : "",
1760
+ ]);
1818
1761
  case "function":
1819
1762
  case "closure":
1820
1763
  case "method":
1821
1764
  return printFunction(path, options, print);
1822
1765
  case "arrowfunc":
1823
- return concat([
1766
+ return [
1824
1767
  node.parenthesizedExpression ? "(" : "",
1825
1768
  ...printAttrs(path, options, print, { inline: true }),
1826
1769
  node.isStatic ? "static " : "",
1827
1770
  "fn",
1828
1771
  printArgumentsList(path, options, print),
1829
1772
  node.type
1830
- ? concat([": ", node.nullable ? "?" : "", path.call(print, "type")])
1773
+ ? [": ", node.nullable ? "?" : "", path.call(print, "type")]
1831
1774
  : "",
1832
1775
  " => ",
1833
1776
  path.call(print, "body"),
1834
1777
  node.parenthesizedExpression ? ")" : "",
1835
- ]);
1778
+ ];
1836
1779
  case "parameter": {
1837
1780
  let promoted = "";
1838
1781
  if (node.flags === 1) {
@@ -1842,28 +1785,51 @@ function printNode(path, options, print) {
1842
1785
  } else if (node.flags === 4) {
1843
1786
  promoted = "private ";
1844
1787
  }
1845
- const name = concat([
1788
+ const name = [
1846
1789
  ...printAttrs(path, options, print, { inline: true }),
1847
1790
  promoted,
1848
1791
  node.readonly ? "readonly " : "",
1849
1792
  node.nullable ? "?" : "",
1850
- node.type ? concat([path.call(print, "type"), " "]) : "",
1793
+ node.type ? [path.call(print, "type"), " "] : "",
1851
1794
  node.byref ? "&" : "",
1852
1795
  node.variadic ? "..." : "",
1853
1796
  "$",
1854
1797
  path.call(print, "name"),
1855
- ]);
1798
+ ];
1856
1799
 
1857
1800
  if (node.value) {
1858
- return group(
1859
- concat([
1860
- name,
1861
- // see handleFunctionParameter() in ./comments.js - since there's
1862
- // no node to attach comments that fall in between the parameter name
1863
- // and value, we store them as dangling comments
1864
- hasDanglingComments(node) ? " " : "",
1865
- comments.printDanglingComments(path, options, true),
1866
- concat([
1801
+ return group([
1802
+ name,
1803
+ // see handleFunctionParameter() in ./comments.js - since there's
1804
+ // no node to attach comments that fall in between the parameter name
1805
+ // and value, we store them as dangling comments
1806
+ hasDanglingComments(node) ? " " : "",
1807
+ comments.printDanglingComments(path, options, true),
1808
+ " =",
1809
+ printAssignmentRight(
1810
+ node.name,
1811
+ node.value,
1812
+ path.call(print, "value"),
1813
+ false,
1814
+ options
1815
+ ),
1816
+ ]);
1817
+ }
1818
+
1819
+ return name;
1820
+ }
1821
+ case "variadic":
1822
+ return ["...", path.call(print, "what")];
1823
+ case "property":
1824
+ return group([
1825
+ node.readonly ? "readonly " : "",
1826
+ node.type
1827
+ ? [node.nullable ? "?" : "", path.call(print, "type"), " "]
1828
+ : "",
1829
+ "$",
1830
+ path.call(print, "name"),
1831
+ node.value
1832
+ ? [
1867
1833
  " =",
1868
1834
  printAssignmentRight(
1869
1835
  node.name,
@@ -1872,38 +1838,9 @@ function printNode(path, options, print) {
1872
1838
  false,
1873
1839
  options
1874
1840
  ),
1875
- ]),
1876
- ])
1877
- );
1878
- }
1879
-
1880
- return name;
1881
- }
1882
- case "variadic":
1883
- return concat(["...", path.call(print, "what")]);
1884
- case "property":
1885
- return group(
1886
- concat([
1887
- node.readonly ? "readonly " : "",
1888
- node.type
1889
- ? concat([node.nullable ? "?" : "", path.call(print, "type"), " "])
1890
- : "",
1891
- "$",
1892
- path.call(print, "name"),
1893
- node.value
1894
- ? concat([
1895
- " =",
1896
- printAssignmentRight(
1897
- node.name,
1898
- node.value,
1899
- path.call(print, "value"),
1900
- false,
1901
- options
1902
- ),
1903
- ])
1904
- : "",
1905
- ])
1906
- );
1841
+ ]
1842
+ : "",
1843
+ ]);
1907
1844
  case "propertystatement": {
1908
1845
  const attrs = [];
1909
1846
  path.map(
@@ -1927,40 +1864,27 @@ function printNode(path, options, print) {
1927
1864
 
1928
1865
  const hasVisibility = node.visibility || node.visibility === null;
1929
1866
 
1930
- return group(
1931
- concat([
1932
- ...attrs,
1933
- hasVisibility
1934
- ? concat([node.visibility === null ? "var" : node.visibility, ""])
1935
- : "",
1936
- node.isStatic ? concat([hasVisibility ? " " : "", "static"]) : "",
1937
- firstProperty ? concat([" ", firstProperty]) : "",
1938
- indent(
1939
- concat(
1940
- printed
1941
- .slice(1)
1942
- .map((p) => concat([",", hasValue ? hardline : line, p]))
1943
- )
1944
- ),
1945
- ])
1946
- );
1867
+ return group([
1868
+ ...attrs,
1869
+ hasVisibility
1870
+ ? [node.visibility === null ? "var" : node.visibility, ""]
1871
+ : "",
1872
+ node.isStatic ? [hasVisibility ? " " : "", "static"] : "",
1873
+ firstProperty ? [" ", firstProperty] : "",
1874
+ indent(
1875
+ printed.slice(1).map((p) => [",", hasValue ? hardline : line, p])
1876
+ ),
1877
+ ]);
1947
1878
  }
1948
1879
  case "if": {
1949
1880
  const parts = [];
1950
1881
  const body = printBodyControlStructure(path, options, print, "body");
1951
- const opening = group(
1952
- concat([
1953
- "if (",
1954
- group(
1955
- concat([
1956
- indent(concat([softline, path.call(print, "test")])),
1957
- softline,
1958
- ])
1959
- ),
1960
- ")",
1961
- body,
1962
- ])
1963
- );
1882
+ const opening = group([
1883
+ "if (",
1884
+ group([indent([softline, path.call(print, "test")]), softline]),
1885
+ ")",
1886
+ body,
1887
+ ]);
1964
1888
 
1965
1889
  parts.push(
1966
1890
  opening,
@@ -2001,37 +1925,25 @@ function printNode(path, options, print) {
2001
1925
  parts.push(node.body ? (node.shortForm ? "endif;" : "}") : "");
2002
1926
  }
2003
1927
 
2004
- return concat(parts);
1928
+ return parts;
2005
1929
  }
2006
1930
  case "do":
2007
- return concat([
1931
+ return [
2008
1932
  "do",
2009
1933
  printBodyControlStructure(path, options, print, "body"),
2010
1934
  " while (",
2011
- group(
2012
- concat([
2013
- indent(concat([softline, path.call(print, "test")])),
2014
- softline,
2015
- ])
2016
- ),
1935
+ group([indent([softline, path.call(print, "test")]), softline]),
2017
1936
  ")",
2018
- ]);
1937
+ ];
2019
1938
  case "while":
2020
1939
  case "switch":
2021
- return group(
2022
- concat([
2023
- node.kind,
2024
- " (",
2025
- group(
2026
- concat([
2027
- indent(concat([softline, path.call(print, "test")])),
2028
- softline,
2029
- ])
2030
- ),
2031
- ")",
2032
- printBodyControlStructure(path, options, print, "body"),
2033
- ])
2034
- );
1940
+ return group([
1941
+ node.kind,
1942
+ " (",
1943
+ group([indent([softline, path.call(print, "test")]), softline]),
1944
+ ")",
1945
+ printBodyControlStructure(path, options, print, "body"),
1946
+ ]);
2035
1947
  case "for": {
2036
1948
  const body = printBodyControlStructure(path, options, print, "body");
2037
1949
 
@@ -2043,49 +1955,33 @@ function printNode(path, options, print) {
2043
1955
  options,
2044
1956
  /* sameLine */ true
2045
1957
  );
2046
- const printedComments = dangling ? concat([dangling, softline]) : "";
1958
+ const printedComments = dangling ? [dangling, softline] : "";
2047
1959
 
2048
1960
  if (!node.init.length && !node.test.length && !node.increment.length) {
2049
- return concat([printedComments, group(concat(["for (;;)", body]))]);
1961
+ return [printedComments, group(["for (;;)", body])];
2050
1962
  }
2051
1963
 
2052
- return concat([
1964
+ return [
2053
1965
  printedComments,
2054
- group(
2055
- concat([
2056
- "for (",
2057
- group(
2058
- concat([
2059
- indent(
2060
- concat([
2061
- softline,
2062
- group(
2063
- concat([
2064
- join(concat([",", line]), path.map(print, "init")),
2065
- ])
2066
- ),
2067
- ";",
2068
- line,
2069
- group(
2070
- concat([
2071
- join(concat([",", line]), path.map(print, "test")),
2072
- ])
2073
- ),
2074
- ";",
2075
- line,
2076
- group(
2077
- join(concat([",", line]), path.map(print, "increment"))
2078
- ),
2079
- ])
2080
- ),
2081
- softline,
2082
- ])
2083
- ),
2084
- ")",
2085
- body,
2086
- ])
2087
- ),
2088
- ]);
1966
+ group([
1967
+ "for (",
1968
+ group([
1969
+ indent([
1970
+ softline,
1971
+ group(join([",", line], path.map(print, "init"))),
1972
+ ";",
1973
+ line,
1974
+ group(join([",", line], path.map(print, "test"))),
1975
+ ";",
1976
+ line,
1977
+ group(join([",", line], path.map(print, "increment"))),
1978
+ ]),
1979
+ softline,
1980
+ ]),
1981
+ ")",
1982
+ body,
1983
+ ]),
1984
+ ];
2089
1985
  }
2090
1986
  case "foreach": {
2091
1987
  const body = printBodyControlStructure(path, options, print, "body");
@@ -2098,41 +1994,35 @@ function printNode(path, options, print) {
2098
1994
  options,
2099
1995
  /* sameLine */ true
2100
1996
  );
2101
- const printedComments = dangling ? concat([dangling, softline]) : "";
1997
+ const printedComments = dangling ? [dangling, softline] : "";
2102
1998
 
2103
- return concat([
1999
+ return [
2104
2000
  printedComments,
2105
- group(
2106
- concat([
2107
- "foreach (",
2108
- group(
2109
- concat([
2110
- indent(
2111
- concat([
2112
- softline,
2113
- path.call(print, "source"),
2114
- line,
2115
- "as ",
2116
- group(
2117
- node.key
2118
- ? indent(
2119
- join(concat([" =>", line]), [
2120
- path.call(print, "key"),
2121
- path.call(print, "value"),
2122
- ])
2123
- )
2124
- : path.call(print, "value")
2125
- ),
2126
- ])
2127
- ),
2128
- softline,
2129
- ])
2130
- ),
2131
- ")",
2132
- body,
2133
- ])
2134
- ),
2135
- ]);
2001
+ group([
2002
+ "foreach (",
2003
+ group([
2004
+ indent([
2005
+ softline,
2006
+ path.call(print, "source"),
2007
+ line,
2008
+ "as ",
2009
+ group(
2010
+ node.key
2011
+ ? indent(
2012
+ join(
2013
+ [" =>", line],
2014
+ [path.call(print, "key"), path.call(print, "value")]
2015
+ )
2016
+ )
2017
+ : path.call(print, "value")
2018
+ ),
2019
+ ]),
2020
+ softline,
2021
+ ]),
2022
+ ")",
2023
+ body,
2024
+ ]),
2025
+ ];
2136
2026
  }
2137
2027
  case "try": {
2138
2028
  const parts = [];
@@ -2143,7 +2033,7 @@ function printNode(path, options, print) {
2143
2033
  );
2144
2034
 
2145
2035
  if (node.catches) {
2146
- parts.push(concat(path.map(print, "catches")));
2036
+ parts.push(path.map(print, "catches"));
2147
2037
  }
2148
2038
 
2149
2039
  if (node.always) {
@@ -2153,49 +2043,47 @@ function printNode(path, options, print) {
2153
2043
  );
2154
2044
  }
2155
2045
 
2156
- return concat(parts);
2046
+ return parts;
2157
2047
  }
2158
2048
  case "catch": {
2159
- return concat([
2049
+ return [
2160
2050
  " catch",
2161
2051
  node.what
2162
- ? concat([
2052
+ ? [
2163
2053
  " (",
2164
2054
  join(" | ", path.map(print, "what")),
2165
- node.variable ? concat([" ", path.call(print, "variable")]) : "",
2055
+ node.variable ? [" ", path.call(print, "variable")] : "",
2166
2056
  ")",
2167
- ])
2057
+ ]
2168
2058
  : "",
2169
2059
  printBodyControlStructure(path, options, print, "body"),
2170
- ]);
2060
+ ];
2171
2061
  }
2172
2062
  case "case":
2173
- return concat([
2063
+ return [
2174
2064
  node.test
2175
- ? concat([
2065
+ ? [
2176
2066
  "case ",
2177
2067
  node.test.comments
2178
2068
  ? indent(path.call(print, "test"))
2179
2069
  : path.call(print, "test"),
2180
2070
  ":",
2181
- ])
2071
+ ]
2182
2072
  : "default:",
2183
2073
  node.body
2184
2074
  ? node.body.children && node.body.children.length
2185
- ? indent(
2186
- concat([
2187
- isFirstChildrenInlineNode(path) ? "" : hardline,
2188
- path.call(print, "body"),
2189
- ])
2190
- )
2075
+ ? indent([
2076
+ isFirstChildrenInlineNode(path) ? "" : hardline,
2077
+ path.call(print, "body"),
2078
+ ])
2191
2079
  : ""
2192
2080
  : "",
2193
- ]);
2081
+ ];
2194
2082
  case "break":
2195
2083
  case "continue":
2196
2084
  if (node.level) {
2197
2085
  if (node.level.kind === "number" && node.level.value !== "1") {
2198
- return concat([`${node.kind} `, path.call(print, "level")]);
2086
+ return [`${node.kind} `, path.call(print, "level")];
2199
2087
  }
2200
2088
 
2201
2089
  return node.kind;
@@ -2208,10 +2096,12 @@ function printNode(path, options, print) {
2208
2096
  node.arguments.length === 1 &&
2209
2097
  isStringOnItsOwnLine(node.arguments[0], options.originalText, options)
2210
2098
  ) {
2211
- return concat([
2099
+ return [
2212
2100
  path.call(print, "what"),
2213
- concat(["(", join(", ", path.map(print, "arguments")), ")"]),
2214
- ]);
2101
+ "(",
2102
+ join(", ", path.map(print, "arguments")),
2103
+ ")",
2104
+ ];
2215
2105
  }
2216
2106
 
2217
2107
  // chain: Call (*LookupNode (Call (*LookupNode (...))))
@@ -2219,10 +2109,10 @@ function printNode(path, options, print) {
2219
2109
  return printMemberChain(path, options, print);
2220
2110
  }
2221
2111
 
2222
- return concat([
2112
+ return [
2223
2113
  path.call(print, "what"),
2224
2114
  printArgumentsList(path, options, print),
2225
- ]);
2115
+ ];
2226
2116
  }
2227
2117
  case "new": {
2228
2118
  const isAnonymousClassNode =
@@ -2234,14 +2124,14 @@ function printNode(path, options, print) {
2234
2124
  node.arguments.length === 1 &&
2235
2125
  isStringOnItsOwnLine(node.arguments[0], options.originalText, options)
2236
2126
  ) {
2237
- return concat([
2127
+ return [
2238
2128
  "new ",
2239
2129
  ...path.call(printAttrs, "what"),
2240
2130
  path.call(print, "what"),
2241
2131
  "(",
2242
2132
  join(", ", path.map(print, "arguments")),
2243
2133
  ")",
2244
- ]);
2134
+ ];
2245
2135
  }
2246
2136
 
2247
2137
  const parts = [];
@@ -2252,10 +2142,7 @@ function printNode(path, options, print) {
2252
2142
  parts.push(
2253
2143
  node.what.leadingComments &&
2254
2144
  node.what.leadingComments[0].kind === "commentblock"
2255
- ? concat([
2256
- comments.printComments(node.what.leadingComments, options),
2257
- " ",
2258
- ])
2145
+ ? [comments.printComments(node.what.leadingComments, options), " "]
2259
2146
  : "",
2260
2147
  ...path.call(
2261
2148
  (pa) => printAttrs(pa, options, print, { inline: true }),
@@ -2263,31 +2150,31 @@ function printNode(path, options, print) {
2263
2150
  ),
2264
2151
  "class",
2265
2152
  node.arguments.length > 0
2266
- ? concat([" ", printArgumentsList(path, options, print)])
2153
+ ? [" ", printArgumentsList(path, options, print)]
2267
2154
  : "",
2268
2155
  group(path.call(print, "what"))
2269
2156
  );
2270
2157
  } else {
2271
2158
  const isExpression = ["call", "offsetlookup"].includes(node.what.kind);
2272
- const printed = concat([
2159
+ const printed = [
2273
2160
  isExpression ? "(" : "",
2274
2161
  path.call(print, "what"),
2275
2162
  isExpression ? ")" : "",
2276
2163
  printArgumentsList(path, options, print),
2277
- ]);
2164
+ ];
2278
2165
 
2279
2166
  parts.push(hasLeadingComment(node.what) ? indent(printed) : printed);
2280
2167
  }
2281
2168
 
2282
- return concat(parts);
2169
+ return parts;
2283
2170
  }
2284
2171
  case "clone":
2285
- return concat([
2172
+ return [
2286
2173
  "clone ",
2287
2174
  node.what.comments
2288
2175
  ? indent(path.call(print, "what"))
2289
2176
  : path.call(print, "what"),
2290
- ]);
2177
+ ];
2291
2178
  case "propertylookup":
2292
2179
  case "nullsafepropertylookup":
2293
2180
  case "staticlookup":
@@ -2317,92 +2204,74 @@ function printNode(path, options, print) {
2317
2204
  parent &&
2318
2205
  !isLookupNode(parent));
2319
2206
 
2320
- return concat([
2207
+ return [
2321
2208
  path.call(print, "what"),
2322
2209
  shouldInline
2323
2210
  ? printLookupNodes(path, options, print)
2324
- : group(
2325
- indent(concat([softline, printLookupNodes(path, options, print)]))
2326
- ),
2327
- ]);
2211
+ : group(indent([softline, printLookupNodes(path, options, print)])),
2212
+ ];
2328
2213
  }
2329
2214
  case "exit":
2330
- return group(
2331
- concat([
2332
- node.useDie ? "die" : "exit",
2333
- "(",
2334
- node.expression
2335
- ? isStringOnItsOwnLine(
2336
- node.expression,
2337
- options.originalText,
2338
- options
2339
- )
2340
- ? path.call(print, "expression")
2341
- : concat([
2342
- indent(concat([softline, path.call(print, "expression")])),
2343
- softline,
2344
- ])
2345
- : comments.printDanglingComments(path, options),
2346
- ")",
2347
- ])
2348
- );
2215
+ return group([
2216
+ node.useDie ? "die" : "exit",
2217
+ "(",
2218
+ node.expression
2219
+ ? isStringOnItsOwnLine(node.expression, options.originalText, options)
2220
+ ? path.call(print, "expression")
2221
+ : [indent([softline, path.call(print, "expression")]), softline]
2222
+ : comments.printDanglingComments(path, options),
2223
+ ")",
2224
+ ]);
2349
2225
  case "global":
2350
- return group(
2351
- concat([
2352
- "global ",
2353
- indent(concat([join(concat([",", line]), path.map(print, "items"))])),
2354
- ])
2355
- );
2226
+ return group([
2227
+ "global ",
2228
+ indent(join([",", line], path.map(print, "items"))),
2229
+ ]);
2356
2230
  case "include":
2357
- return concat([
2231
+ return [
2358
2232
  node.require ? "require" : "include",
2359
2233
  node.once ? "_once" : "",
2360
2234
  " ",
2361
2235
  node.target.comments
2362
2236
  ? indent(path.call(print, "target"))
2363
2237
  : path.call(print, "target"),
2364
- ]);
2238
+ ];
2365
2239
  case "label":
2366
- return concat([path.call(print, "name"), ":"]);
2240
+ return [path.call(print, "name"), ":"];
2367
2241
  case "goto":
2368
- return concat(["goto ", path.call(print, "label")]);
2242
+ return ["goto ", path.call(print, "label")];
2369
2243
  case "throw":
2370
- return concat([
2244
+ return [
2371
2245
  "throw ",
2372
2246
  node.what.comments
2373
2247
  ? indent(path.call(print, "what"))
2374
2248
  : path.call(print, "what"),
2375
- ]);
2249
+ ];
2376
2250
  case "silent":
2377
- return concat(["@", path.call(print, "expr")]);
2251
+ return ["@", path.call(print, "expr")];
2378
2252
  case "halt":
2379
- return concat([
2253
+ return [
2380
2254
  hasDanglingComments(node)
2381
- ? concat([
2255
+ ? [
2382
2256
  comments.printDanglingComments(
2383
2257
  path,
2384
2258
  options,
2385
2259
  /* sameIndent */ true
2386
2260
  ),
2387
2261
  hardline,
2388
- ])
2262
+ ]
2389
2263
  : "",
2390
2264
  "__halt_compiler();",
2391
2265
  node.after,
2392
- ]);
2266
+ ];
2393
2267
  case "eval":
2394
- return group(
2395
- concat([
2396
- "eval(",
2397
- isStringOnItsOwnLine(node.source, options.originalText, options)
2398
- ? path.call(print, "source")
2399
- : concat([
2400
- indent(concat([softline, path.call(print, "source")])),
2401
- softline,
2402
- ]),
2403
- ")",
2404
- ])
2405
- );
2268
+ return group([
2269
+ "eval(",
2270
+ isStringOnItsOwnLine(node.source, options.originalText, options)
2271
+ ? path.call(print, "source")
2272
+ : [indent([softline, path.call(print, "source")]), softline],
2273
+ ")",
2274
+ ]);
2406
2275
  case "echo": {
2407
2276
  const printedArguments = path.map((childPath) => {
2408
2277
  return print(childPath);
@@ -2419,23 +2288,19 @@ function printNode(path, options, print) {
2419
2288
  : dedent(printedArguments[0]);
2420
2289
  }
2421
2290
 
2422
- return group(
2423
- concat([
2424
- node.shortForm ? "" : "echo ",
2425
- firstVariable ? firstVariable : "",
2426
- indent(
2427
- concat(printedArguments.slice(1).map((p) => concat([",", line, p])))
2428
- ),
2429
- ])
2430
- );
2291
+ return group([
2292
+ node.shortForm ? "" : "echo ",
2293
+ firstVariable ? firstVariable : "",
2294
+ indent(printedArguments.slice(1).map((p) => [",", line, p])),
2295
+ ]);
2431
2296
  }
2432
2297
  case "print": {
2433
- return concat([
2298
+ return [
2434
2299
  "print ",
2435
2300
  node.expression.comments
2436
2301
  ? indent(path.call(print, "expression"))
2437
2302
  : path.call(print, "expression"),
2438
- ]);
2303
+ ];
2439
2304
  }
2440
2305
  case "return": {
2441
2306
  const parts = [];
@@ -2455,25 +2320,21 @@ function printNode(path, options, print) {
2455
2320
  );
2456
2321
  }
2457
2322
 
2458
- return concat(parts);
2323
+ return parts;
2459
2324
  }
2460
2325
  case "isset":
2461
2326
  case "unset":
2462
- return group(
2463
- concat([
2464
- node.kind,
2465
- printArgumentsList(path, options, print, "variables"),
2466
- ])
2467
- );
2327
+ return group([
2328
+ node.kind,
2329
+ printArgumentsList(path, options, print, "variables"),
2330
+ ]);
2468
2331
  case "empty":
2469
- return group(
2470
- concat([
2471
- "empty(",
2472
- indent(concat([softline, path.call(print, "expression")])),
2473
- softline,
2474
- ")",
2475
- ])
2476
- );
2332
+ return group([
2333
+ "empty(",
2334
+ indent([softline, path.call(print, "expression")]),
2335
+ softline,
2336
+ ")",
2337
+ ]);
2477
2338
  case "variable": {
2478
2339
  const parent = path.getParentNode();
2479
2340
  const parentParent = path.getParentNode(1);
@@ -2492,13 +2353,13 @@ function printNode(path, options, print) {
2492
2353
  const openCurly = node.curly ? "{" : "";
2493
2354
  const closeCurly = node.curly ? "}" : "";
2494
2355
 
2495
- return concat([
2356
+ return [
2496
2357
  ampersand,
2497
2358
  dollar,
2498
2359
  openCurly,
2499
2360
  path.call(print, "name"),
2500
2361
  closeCurly,
2501
- ]);
2362
+ ];
2502
2363
  }
2503
2364
  case "constantstatement":
2504
2365
  case "classconstant": {
@@ -2514,17 +2375,13 @@ function printNode(path, options, print) {
2514
2375
  firstVariable = indent(printed[0]);
2515
2376
  }
2516
2377
 
2517
- return group(
2518
- concat([
2519
- ...attrs,
2520
- node.visibility ? concat([node.visibility, " "]) : "",
2521
- "const",
2522
- firstVariable ? concat([" ", firstVariable]) : "",
2523
- indent(
2524
- concat(printed.slice(1).map((p) => concat([",", hardline, p])))
2525
- ),
2526
- ])
2527
- );
2378
+ return group([
2379
+ ...attrs,
2380
+ node.visibility ? [node.visibility, " "] : "",
2381
+ "const",
2382
+ firstVariable ? [" ", firstVariable] : "",
2383
+ indent(printed.slice(1).map((p) => [",", hardline, p])),
2384
+ ]);
2528
2385
  }
2529
2386
  case "constant":
2530
2387
  return printAssignment(
@@ -2552,19 +2409,13 @@ function printNode(path, options, print) {
2552
2409
  firstVariable = indent(printed[0]);
2553
2410
  }
2554
2411
 
2555
- return group(
2556
- concat([
2557
- "static",
2558
- firstVariable ? concat([" ", firstVariable]) : "",
2559
- indent(
2560
- concat(
2561
- printed
2562
- .slice(1)
2563
- .map((p) => concat([",", hasValue ? hardline : line, p]))
2564
- )
2565
- ),
2566
- ])
2567
- );
2412
+ return group([
2413
+ "static",
2414
+ firstVariable ? [" ", firstVariable] : "",
2415
+ indent(
2416
+ printed.slice(1).map((p) => [",", hasValue ? hardline : line, p])
2417
+ ),
2418
+ ]);
2568
2419
  }
2569
2420
  case "staticvariable": {
2570
2421
  return printAssignment(
@@ -2583,22 +2434,20 @@ function printNode(path, options, print) {
2583
2434
  (node.kind === "array" && isMinVersion(options.phpVersion, "5.4")) ||
2584
2435
  (node.kind === "list" &&
2585
2436
  (node.shortForm || isMinVersion(options.phpVersion, "7.1")));
2586
- const open = useShortForm ? "[" : concat([node.kind, "("]);
2437
+ const open = useShortForm ? "[" : [node.kind, "("];
2587
2438
  const close = useShortForm ? "]" : ")";
2588
2439
 
2589
2440
  if (node.items.length === 0) {
2590
2441
  if (!hasDanglingComments(node)) {
2591
- return concat([open, close]);
2442
+ return [open, close];
2592
2443
  }
2593
2444
 
2594
- return group(
2595
- concat([
2596
- open,
2597
- comments.printDanglingComments(path, options),
2598
- softline,
2599
- close,
2600
- ])
2601
- );
2445
+ return group([
2446
+ open,
2447
+ comments.printDanglingComments(path, options),
2448
+ softline,
2449
+ close,
2450
+ ]);
2602
2451
  }
2603
2452
 
2604
2453
  const lastElem = getLast(node.items);
@@ -2629,24 +2478,24 @@ function printNode(path, options, print) {
2629
2478
  );
2630
2479
 
2631
2480
  return group(
2632
- concat([
2481
+ [
2633
2482
  open,
2634
- indent(concat([softline, printArrayItems(path, options, print)])),
2483
+ indent([softline, printArrayItems(path, options, print)]),
2635
2484
  needsForcedTrailingComma ? "," : "",
2636
2485
  ifBreak(
2637
2486
  !needsForcedTrailingComma && shouldPrintComma(options, "5.0")
2638
- ? concat([
2487
+ ? [
2639
2488
  lastElem && shouldPrintHardlineBeforeTrailingComma(lastElem)
2640
2489
  ? hardline
2641
2490
  : "",
2642
2491
  ",",
2643
- ])
2492
+ ]
2644
2493
  : ""
2645
2494
  ),
2646
2495
  comments.printDanglingComments(path, options, true),
2647
2496
  softline,
2648
2497
  close,
2649
- ]),
2498
+ ],
2650
2499
  { shouldBreak }
2651
2500
  );
2652
2501
  }
@@ -2663,44 +2512,44 @@ function printNode(path, options, print) {
2663
2512
  ref,
2664
2513
  options
2665
2514
  )
2666
- : concat([ref, unpack, path.call(print, "value")]);
2515
+ : [ref, unpack, path.call(print, "value")];
2667
2516
  }
2668
2517
  case "yield": {
2669
- const printedKeyAndValue = concat([
2670
- node.key ? concat([path.call(print, "key"), " => "]) : "",
2518
+ const printedKeyAndValue = [
2519
+ node.key ? [path.call(print, "key"), " => "] : "",
2671
2520
  path.call(print, "value"),
2672
- ]);
2521
+ ];
2673
2522
 
2674
- return concat([
2523
+ return [
2675
2524
  "yield",
2676
2525
  node.key || node.value ? " " : "",
2677
2526
  node.value && node.value.comments
2678
2527
  ? indent(printedKeyAndValue)
2679
2528
  : printedKeyAndValue,
2680
- ]);
2529
+ ];
2681
2530
  }
2682
2531
  case "yieldfrom":
2683
- return concat([
2532
+ return [
2684
2533
  "yield from ",
2685
2534
  node.value.comments
2686
2535
  ? indent(path.call(print, "value"))
2687
2536
  : path.call(print, "value"),
2688
- ]);
2537
+ ];
2689
2538
  case "unary":
2690
- return concat([node.type, path.call(print, "what")]);
2539
+ return [node.type, path.call(print, "what")];
2691
2540
  case "pre":
2692
- return concat([node.type + node.type, path.call(print, "what")]);
2541
+ return [node.type + node.type, path.call(print, "what")];
2693
2542
  case "post":
2694
- return concat([path.call(print, "what"), node.type + node.type]);
2543
+ return [path.call(print, "what"), node.type + node.type];
2695
2544
  case "cast":
2696
- return concat([
2545
+ return [
2697
2546
  "(",
2698
2547
  node.type,
2699
2548
  ") ",
2700
2549
  node.expr.comments
2701
2550
  ? indent(path.call(print, "expr"))
2702
2551
  : path.call(print, "expr"),
2703
- ]);
2552
+ ];
2704
2553
  case "assignref":
2705
2554
  case "assign": {
2706
2555
  const hasRef = node.kind === "assignref";
@@ -2708,7 +2557,7 @@ function printNode(path, options, print) {
2708
2557
  return printAssignment(
2709
2558
  node.left,
2710
2559
  path.call(print, "left"),
2711
- concat([" ", hasRef ? "=" : node.operator]),
2560
+ [" ", hasRef ? "=" : node.operator],
2712
2561
  node.right,
2713
2562
  path.call(print, "right"),
2714
2563
  hasRef,
@@ -2744,7 +2593,7 @@ function printNode(path, options, print) {
2744
2593
  // $this->lookahead()->type === tt->parenLeft
2745
2594
  // ) {
2746
2595
  if (isInsideParenthesis) {
2747
- return concat(parts);
2596
+ return parts;
2748
2597
  }
2749
2598
 
2750
2599
  // Break between the parens in unaries or in a member expression, i.e.
@@ -2758,9 +2607,7 @@ function printNode(path, options, print) {
2758
2607
  parent.kind === "unary" ||
2759
2608
  (isLookupNode(parent) && parent.kind !== "offsetlookup")
2760
2609
  ) {
2761
- return group(
2762
- concat([indent(concat([softline, concat(parts)])), softline])
2763
- );
2610
+ return group([indent([softline, ...parts]), softline]);
2764
2611
  }
2765
2612
 
2766
2613
  // Avoid indenting sub-expressions in some cases where the first sub-expression is already
@@ -2787,20 +2634,18 @@ function printNode(path, options, print) {
2787
2634
  (shouldInlineLogicalExpression(node) && !samePrecedenceSubExpression) ||
2788
2635
  (!shouldInlineLogicalExpression(node) && shouldIndentIfInlining)
2789
2636
  ) {
2790
- return group(concat(parts));
2637
+ return group(parts);
2791
2638
  }
2792
2639
 
2793
- const rest = concat(parts.slice(1));
2640
+ const rest = parts.slice(1);
2794
2641
 
2795
- return group(
2796
- concat([
2797
- // Don't include the initial expression in the indentation
2798
- // level. The first item is guaranteed to be the first
2799
- // left-most expression.
2800
- parts.length > 0 ? parts[0] : "",
2801
- indent(rest),
2802
- ])
2803
- );
2642
+ return group([
2643
+ // Don't include the initial expression in the indentation
2644
+ // level. The first item is guaranteed to be the first
2645
+ // left-most expression.
2646
+ parts.length > 0 ? parts[0] : "",
2647
+ indent(rest),
2648
+ ]);
2804
2649
  }
2805
2650
  case "retif": {
2806
2651
  const parts = [];
@@ -2820,26 +2665,26 @@ function printNode(path, options, print) {
2820
2665
  node.falseExpr.kind === "bin"
2821
2666
  ? indent(path.call(print, "falseExpr"))
2822
2667
  : path.call(print, "falseExpr");
2823
- const part = concat([
2668
+ const part = [
2824
2669
  node.trueExpr ? line : " ",
2825
2670
  "?",
2826
2671
  node.trueExpr
2827
- ? concat([
2672
+ ? [
2828
2673
  " ",
2829
2674
  node.trueExpr.kind === "bin"
2830
2675
  ? indent(path.call(print, "trueExpr"))
2831
2676
  : path.call(print, "trueExpr"),
2832
2677
  line,
2833
- ])
2678
+ ]
2834
2679
  : "",
2835
2680
  ":",
2836
2681
  node.trueExpr
2837
- ? concat([" ", printedFalseExpr])
2838
- : concat([
2682
+ ? [" ", printedFalseExpr]
2683
+ : [
2839
2684
  shouldInlineRetifFalseExpression(node.falseExpr) ? " " : line,
2840
2685
  printedFalseExpr,
2841
- ]),
2842
- ]);
2686
+ ],
2687
+ ];
2843
2688
 
2844
2689
  parts.push(part);
2845
2690
 
@@ -2865,15 +2710,15 @@ function printNode(path, options, print) {
2865
2710
  const printedTest = path.call(print, "test");
2866
2711
 
2867
2712
  if (!node.trueExpr) {
2868
- const printed = concat([
2713
+ const printed = [
2869
2714
  printedTest,
2870
2715
  pureParent.kind === "bin" ||
2871
2716
  ["print", "echo", "return", "include"].includes(
2872
2717
  firstNonRetifParent.kind
2873
2718
  )
2874
- ? indent(concat(parts))
2875
- : concat(parts),
2876
- ]);
2719
+ ? indent(parts)
2720
+ : parts,
2721
+ ];
2877
2722
 
2878
2723
  // Break between the parens in unaries or in a lookup nodes, i.e.
2879
2724
  //
@@ -2887,19 +2732,17 @@ function printNode(path, options, print) {
2887
2732
  pureParent.kind === "unary" ||
2888
2733
  (isLookupNode(pureParent) && pureParent.kind !== "offsetlookup")
2889
2734
  ) {
2890
- return group(concat([indent(concat([softline, printed])), softline]));
2735
+ return group([indent([softline, printed]), softline]);
2891
2736
  }
2892
2737
 
2893
2738
  return maybeGroup(printed);
2894
2739
  }
2895
2740
 
2896
- return maybeGroup(
2897
- concat([
2898
- node.test.kind === "retif" ? indent(printedTest) : printedTest,
2899
- indent(concat(parts)),
2900
- breakClosingParens ? softline : "",
2901
- ])
2902
- );
2741
+ return maybeGroup([
2742
+ node.test.kind === "retif" ? indent(printedTest) : printedTest,
2743
+ indent(parts),
2744
+ breakClosingParens ? softline : "",
2745
+ ]);
2903
2746
  }
2904
2747
  case "boolean":
2905
2748
  return node.value ? "true" : "false";
@@ -2915,7 +2758,7 @@ function printNode(path, options, print) {
2915
2758
  let linebreak = literalline;
2916
2759
  if (parentParent.type === "heredoc") {
2917
2760
  linebreak = flexible ? hardline : literalline;
2918
- const lines = parentParent.raw.split(/\r?\n/g);
2761
+ const lines = parentParent.raw.split("\n");
2919
2762
  closingTagIndentation = lines[lines.length - 1].search(/\S/);
2920
2763
  if (closingTagIndentation === -1) {
2921
2764
  closingTagIndentation = lines[lines.length - 2].search(/\S/);
@@ -2924,7 +2767,7 @@ function printNode(path, options, print) {
2924
2767
  return join(
2925
2768
  linebreak,
2926
2769
  node.raw
2927
- .split(/\r?\n/g)
2770
+ .split("\n")
2928
2771
  .map((s, i) =>
2929
2772
  i > 0 || node.loc.start.column === 0
2930
2773
  ? s.substring(closingTagIndentation)
@@ -2950,12 +2793,12 @@ function printNode(path, options, print) {
2950
2793
  stringValue = stringValue.substr(0, stringValue.length - 1);
2951
2794
  }
2952
2795
 
2953
- return concat([
2796
+ return [
2954
2797
  node.raw[0] === "b" ? "b" : "",
2955
2798
  quote,
2956
- join(literalline, stringValue.split(/\r?\n/g)),
2799
+ join(literalline, stringValue.split("\n")),
2957
2800
  quote,
2958
- ]);
2801
+ ];
2959
2802
  }
2960
2803
  case "intersectiontype": {
2961
2804
  return printComposedTypes(path, print, "&");
@@ -2966,14 +2809,14 @@ function printNode(path, options, print) {
2966
2809
  case "encapsedpart": {
2967
2810
  const open =
2968
2811
  (node.syntax === "simple" && node.curly) || node.syntax === "complex"
2969
- ? concat([node.curly ? "$" : "", "{"])
2812
+ ? [node.curly ? "$" : "", "{"]
2970
2813
  : "";
2971
2814
  const close =
2972
2815
  (node.syntax === "simple" && node.curly) || node.syntax === "complex"
2973
2816
  ? "}"
2974
2817
  : "";
2975
2818
 
2976
- return concat([open, path.call(print, "expression"), close]);
2819
+ return [open, path.call(print, "expression"), close];
2977
2820
  }
2978
2821
  case "encapsed":
2979
2822
  switch (node.type) {
@@ -2982,16 +2825,16 @@ function printNode(path, options, print) {
2982
2825
  case "heredoc": {
2983
2826
  const flexible = isMinVersion(options.phpVersion, "7.3");
2984
2827
  const linebreak = flexible ? hardline : literalline;
2985
- return concat([
2828
+ return [
2986
2829
  getEncapsedQuotes(node),
2987
2830
  // Respect `indent` for `heredoc` nodes
2988
2831
  node.type === "heredoc" ? linebreak : "",
2989
- concat(path.map(print, "value")),
2832
+ ...path.map(print, "value"),
2990
2833
  getEncapsedQuotes(node, { opening: false }),
2991
2834
  node.type === "heredoc" && docShouldHaveTrailingNewline(path)
2992
2835
  ? hardline
2993
2836
  : "",
2994
- ]);
2837
+ ];
2995
2838
  }
2996
2839
  // istanbul ignore next
2997
2840
  default:
@@ -3000,26 +2843,26 @@ function printNode(path, options, print) {
3000
2843
  case "inline":
3001
2844
  return join(
3002
2845
  literalline,
3003
- node.raw.replace("___PSEUDO_INLINE_PLACEHOLDER___", "").split(/\r?\n/g)
2846
+ node.raw.replace("___PSEUDO_INLINE_PLACEHOLDER___", "").split("\n")
3004
2847
  );
3005
2848
  case "magic":
3006
2849
  return node.value;
3007
2850
  case "nowdoc": {
3008
2851
  const flexible = isMinVersion(options.phpVersion, "7.3");
3009
2852
  const linebreak = flexible ? hardline : literalline;
3010
- return concat([
2853
+ return [
3011
2854
  "<<<'",
3012
2855
  node.label,
3013
2856
  "'",
3014
2857
  linebreak,
3015
- join(linebreak, node.value.split(/\r?\n/g)),
2858
+ join(linebreak, node.value.split("\n")),
3016
2859
  linebreak,
3017
2860
  node.label,
3018
2861
  docShouldHaveTrailingNewline(path) ? hardline : "",
3019
- ]);
2862
+ ];
3020
2863
  }
3021
2864
  case "name":
3022
- return concat([node.resolution === "rn" ? "namespace\\" : "", node.name]);
2865
+ return [node.resolution === "rn" ? "namespace\\" : "", node.name];
3023
2866
  case "literal":
3024
2867
  return path.call(print, "value");
3025
2868
  case "parentreference":
@@ -3046,50 +2889,27 @@ function printNode(path, options, print) {
3046
2889
  const conds =
3047
2890
  armPath.getValue().conds === null
3048
2891
  ? "default"
3049
- : concat(
3050
- armPath.map(
3051
- (condPath, condIdx) =>
3052
- concat(
3053
- [",", line, print(condPath)].slice(condIdx === 0 ? 2 : 0)
3054
- ),
3055
- "conds"
3056
- )
2892
+ : armPath.map(
2893
+ (condPath, condIdx) =>
2894
+ [",", line, print(condPath)].slice(condIdx === 0 ? 2 : 0),
2895
+ "conds"
3057
2896
  );
3058
2897
  const body = armPath.call(print, "body");
3059
- return concat(
3060
- [
3061
- ",",
3062
- hardline,
3063
- group(
3064
- concat([
3065
- group(concat([conds, indent(line)])),
3066
- concat(["=> ", body]),
3067
- ])
3068
- ),
3069
- ].slice(armIdx > 0 ? 0 : 1)
3070
- );
2898
+ return [
2899
+ ",",
2900
+ hardline,
2901
+ group([group([conds, indent(line)]), "=> ", body]),
2902
+ ].slice(armIdx > 0 ? 0 : 1);
3071
2903
  }, "arms");
3072
- return group(
3073
- concat([
3074
- "match (",
3075
- group(
3076
- concat([
3077
- softline,
3078
- indent(concat([path.call(print, "cond")])),
3079
- softline,
3080
- ])
3081
- ),
3082
- ") {",
3083
- group(
3084
- indent(
3085
- concat([...arms, options.trailingCommaPHP ? ifBreak(",") : ""])
3086
- )
3087
- ),
3088
- " ",
3089
- softline,
3090
- "}",
3091
- ])
3092
- );
2904
+ return group([
2905
+ "match (",
2906
+ group([softline, indent(path.call(print, "cond")), softline]),
2907
+ ") {",
2908
+ group(indent([...arms, options.trailingCommaPHP ? ifBreak(",") : ""])),
2909
+ " ",
2910
+ softline,
2911
+ "}",
2912
+ ]);
3093
2913
  }
3094
2914
 
3095
2915
  case "noop":
@@ -3097,27 +2917,25 @@ function printNode(path, options, print) {
3097
2917
  ? comments.printComments(path.getValue().comments, options)
3098
2918
  : "";
3099
2919
  case "namedargument":
3100
- return concat([node.name, ": ", path.call(print, "value")]);
2920
+ return [node.name, ": ", path.call(print, "value")];
3101
2921
 
3102
2922
  case "enumcase":
3103
- return group(
3104
- concat([
3105
- "case ",
3106
- path.call(print, "name"),
3107
- node.value
3108
- ? concat([
3109
- " =",
3110
- printAssignmentRight(
3111
- node.name,
3112
- node.value,
3113
- path.call(print, "value"),
3114
- false,
3115
- options
3116
- ),
3117
- ])
3118
- : "",
3119
- ])
3120
- );
2923
+ return group([
2924
+ "case ",
2925
+ path.call(print, "name"),
2926
+ node.value
2927
+ ? [
2928
+ " =",
2929
+ printAssignmentRight(
2930
+ node.name,
2931
+ node.value,
2932
+ path.call(print, "value"),
2933
+ false,
2934
+ options
2935
+ ),
2936
+ ]
2937
+ : "",
2938
+ ]);
3121
2939
  case "variadicplaceholder":
3122
2940
  return "...";
3123
2941