@prettier/plugin-php 0.19.7 → 0.20.1

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
@@ -1,5 +1,4 @@
1
- "use strict";
2
-
1
+ import { util as prettierUtil, doc } from "prettier";
3
2
  const {
4
3
  breakParent,
5
4
  join,
@@ -15,14 +14,22 @@ const {
15
14
  literalline,
16
15
  align,
17
16
  dedentToRoot,
18
- } = require("prettier").doc.builders;
19
- const { willBreak } = require("prettier").doc.utils;
17
+ } = doc.builders;
18
+ const { willBreak } = doc.utils;
20
19
  const { isNextLineEmptyAfterIndex, hasNewline, hasNewlineInRange } =
21
- require("prettier").util;
22
- const comments = require("./comments");
23
- const pathNeedsParens = require("./needs-parens");
24
-
25
- const {
20
+ prettierUtil;
21
+ import {
22
+ printAllComments,
23
+ hasTrailingComment,
24
+ hasLeadingComment,
25
+ printDanglingComments,
26
+ printComments,
27
+ isBlockComment,
28
+ hasLeadingOwnLineComment,
29
+ } from "./comments.js";
30
+ import pathNeedsParens from "./needs-parens.js";
31
+
32
+ import {
26
33
  getLast,
27
34
  getPenultimate,
28
35
  isLastStatement,
@@ -32,8 +39,6 @@ const {
32
39
  maybeStripLeadingSlashFromUse,
33
40
  fileShouldEndWithHardline,
34
41
  hasDanglingComments,
35
- hasLeadingComment,
36
- hasTrailingComment,
37
42
  docShouldHaveTrailingNewline,
38
43
  isLookupNode,
39
44
  isFirstChildrenInlineNode,
@@ -54,7 +59,7 @@ const {
54
59
  getNextNonSpaceNonCommentCharacterIndex,
55
60
  isNextLineEmpty,
56
61
  isPreviousLineEmpty,
57
- } = require("./util");
62
+ } from "./util.js";
58
63
 
59
64
  function isMinVersion(actualVersion, requiredVersion) {
60
65
  return parseFloat(actualVersion) >= parseFloat(requiredVersion);
@@ -80,11 +85,9 @@ function shouldPrintHardlineForOpenBrace(options) {
80
85
  }
81
86
 
82
87
  function genericPrint(path, options, print) {
83
- const node = path.getValue();
88
+ const { node } = path;
84
89
 
85
- if (!node) {
86
- return "";
87
- } else if (typeof node === "string") {
90
+ if (typeof node === "string") {
88
91
  return node;
89
92
  }
90
93
 
@@ -115,7 +118,7 @@ function genericPrint(path, options, print) {
115
118
  }
116
119
 
117
120
  function printPropertyLookup(path, options, print, nullsafe = false) {
118
- return [nullsafe ? "?" : "", "->", path.call(print, "offset")];
121
+ return [nullsafe ? "?" : "", "->", print("offset")];
119
122
  }
120
123
 
121
124
  function printNullsafePropertyLookup(path, options, print) {
@@ -123,19 +126,14 @@ function printNullsafePropertyLookup(path, options, print) {
123
126
  }
124
127
 
125
128
  function printStaticLookup(path, options, print) {
126
- const node = path.getValue();
129
+ const { node } = path;
127
130
  const needCurly = !["variable", "identifier"].includes(node.offset.kind);
128
131
 
129
- return [
130
- "::",
131
- needCurly ? "{" : "",
132
- path.call(print, "offset"),
133
- needCurly ? "}" : "",
134
- ];
132
+ return ["::", needCurly ? "{" : "", print("offset"), needCurly ? "}" : ""];
135
133
  }
136
134
 
137
135
  function printOffsetLookup(path, options, print) {
138
- const node = path.getValue();
136
+ const { node } = path;
139
137
  const shouldInline =
140
138
  (node.offset && node.offset.kind === "number") ||
141
139
  getAncestorNode(path, "encapsed");
@@ -144,7 +142,7 @@ function printOffsetLookup(path, options, print) {
144
142
  "[",
145
143
  node.offset
146
144
  ? group([
147
- indent([shouldInline ? "" : softline, path.call(print, "offset")]),
145
+ indent([shouldInline ? "" : softline, print("offset")]),
148
146
  shouldInline ? "" : softline,
149
147
  ])
150
148
  : "",
@@ -217,7 +215,7 @@ function printMemberChain(path, options, print) {
217
215
  }
218
216
 
219
217
  function traverse(path) {
220
- const node = path.getValue();
218
+ const { node } = path;
221
219
 
222
220
  if (
223
221
  node.kind === "call" &&
@@ -226,7 +224,7 @@ function printMemberChain(path, options, print) {
226
224
  printedNodes.unshift({
227
225
  node,
228
226
  printed: [
229
- comments.printAllComments(
227
+ printAllComments(
230
228
  path,
231
229
  () => printArgumentsList(path, options, print),
232
230
  options
@@ -252,22 +250,18 @@ function printMemberChain(path, options, print) {
252
250
  printedNodes.unshift({
253
251
  node,
254
252
  needsParens: pathNeedsParens(path, options),
255
- printed: comments.printAllComments(
256
- path,
257
- () => printedMemberish,
258
- options
259
- ),
253
+ printed: printAllComments(path, () => printedMemberish, options),
260
254
  });
261
255
  path.call((what) => traverse(what), "what");
262
256
  } else {
263
257
  printedNodes.unshift({
264
258
  node,
265
- printed: path.call(print),
259
+ printed: print(),
266
260
  });
267
261
  }
268
262
  }
269
263
 
270
- const node = path.getValue();
264
+ const { node } = path;
271
265
 
272
266
  printedNodes.unshift({
273
267
  node,
@@ -370,7 +364,7 @@ function printMemberChain(path, options, print) {
370
364
 
371
365
  if (
372
366
  printedNodes[i].node.comments &&
373
- comments.hasTrailingComment(printedNodes[i].node)
367
+ hasTrailingComment(printedNodes[i].node)
374
368
  ) {
375
369
  groups.push(currentGroup);
376
370
  currentGroup = [];
@@ -431,8 +425,7 @@ function printMemberChain(path, options, print) {
431
425
  );
432
426
  }
433
427
 
434
- const isExpressionStatement =
435
- path.getParentNode().kind === "expressionstatement";
428
+ const isExpressionStatement = path.parent.kind === "expressionstatement";
436
429
  const shouldMerge =
437
430
  groups.length >= 2 && !groups[1][0].node.comments && shouldNotWrap(groups);
438
431
 
@@ -484,13 +477,9 @@ function printMemberChain(path, options, print) {
484
477
  const flatGroups = groups.slice(0, cutoff).flat();
485
478
 
486
479
  const hasComment =
487
- flatGroups
488
- .slice(1, -1)
489
- .some((node) => comments.hasLeadingComment(node.node)) ||
490
- flatGroups
491
- .slice(0, -1)
492
- .some((node) => comments.hasTrailingComment(node.node)) ||
493
- (groups[cutoff] && comments.hasLeadingComment(groups[cutoff][0].node));
480
+ flatGroups.slice(1, -1).some((node) => hasLeadingComment(node.node)) ||
481
+ flatGroups.slice(0, -1).some((node) => hasTrailingComment(node.node)) ||
482
+ (groups[cutoff] && hasLeadingComment(groups[cutoff][0].node));
494
483
 
495
484
  const hasEncapsedAncestor = getAncestorNode(path, "encapsed");
496
485
 
@@ -584,12 +573,12 @@ function shouldGroupFirstArg(args) {
584
573
  }
585
574
 
586
575
  function printArgumentsList(path, options, print, argumentsKey = "arguments") {
587
- const args = path.getValue()[argumentsKey];
576
+ const args = path.node[argumentsKey];
588
577
 
589
578
  if (args.length === 0) {
590
579
  return [
591
580
  "(",
592
- comments.printDanglingComments(path, options, /* sameIndent */ true),
581
+ printDanglingComments(path, options, /* sameIndent */ true),
593
582
  ")",
594
583
  ];
595
584
  }
@@ -597,15 +586,13 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
597
586
  let anyArgEmptyLine = false;
598
587
  let hasEmptyLineFollowingFirstArg = false;
599
588
 
600
- const lastArgIndex = args.length - 1;
601
- const printedArguments = path.map((argPath, index) => {
602
- const arg = argPath.getNode();
603
- const parts = [print(argPath)];
589
+ const printedArguments = path.map(({ node: arg, isLast, isFirst }) => {
590
+ const parts = [print()];
604
591
 
605
- if (index === lastArgIndex) {
592
+ if (isLast) {
606
593
  // do nothing
607
594
  } else if (isNextLineEmpty(options.originalText, arg, options)) {
608
- if (index === 0) {
595
+ if (isFirst) {
609
596
  hasEmptyLineFollowingFirstArg = true;
610
597
  }
611
598
 
@@ -618,7 +605,7 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
618
605
  return parts;
619
606
  }, argumentsKey);
620
607
 
621
- const node = path.getValue();
608
+ const { node } = path;
622
609
  const lastArg = getLast(args);
623
610
 
624
611
  const maybeTrailingComma =
@@ -654,12 +641,11 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
654
641
 
655
642
  // We want to print the last argument with a special flag
656
643
  let printedExpanded;
657
- let i = 0;
658
644
 
659
- path.each((argPath) => {
660
- if (shouldGroupFirst && i === 0) {
645
+ path.each(({ isLast, isFirst }) => {
646
+ if (shouldGroupFirst && isFirst) {
661
647
  printedExpanded = [
662
- argPath.call((p) => print(p, { expandFirstArg: true })),
648
+ print([], { expandFirstArg: true }),
663
649
  printedArguments.length > 1 ? "," : "",
664
650
  hasEmptyLineFollowingFirstArg ? hardline : line,
665
651
  hasEmptyLineFollowingFirstArg ? hardline : "",
@@ -667,14 +653,12 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
667
653
  ];
668
654
  }
669
655
 
670
- if (shouldGroupLast && i === args.length - 1) {
656
+ if (shouldGroupLast && isLast) {
671
657
  printedExpanded = [
672
658
  ...printedArguments.slice(0, -1),
673
- argPath.call((p) => print(p, { expandLastArg: true })),
659
+ print([], { expandLastArg: true }),
674
660
  ];
675
661
  }
676
-
677
- i++;
678
662
  }, argumentsKey);
679
663
 
680
664
  const somePrintedArgumentsWillBreak = printedArguments.some(willBreak);
@@ -756,7 +740,7 @@ function printBinaryExpression(
756
740
  isInsideParenthesis
757
741
  ) {
758
742
  let parts = [];
759
- const node = path.getValue();
743
+ const { node } = path;
760
744
 
761
745
  if (node.kind === "bin") {
762
746
  // Put all operators with the same precedence level in the same
@@ -772,9 +756,9 @@ function printBinaryExpression(
772
756
  // Flatten them out by recursively calling this function.
773
757
  parts = parts.concat(
774
758
  path.call(
775
- (left) =>
759
+ () =>
776
760
  printBinaryExpression(
777
- left,
761
+ path,
778
762
  print,
779
763
  options,
780
764
  /* isNested */ true,
@@ -784,18 +768,18 @@ function printBinaryExpression(
784
768
  )
785
769
  );
786
770
  } else {
787
- parts.push(path.call(print, "left"));
771
+ parts.push(print("left"));
788
772
  }
789
773
 
790
774
  const shouldInline = shouldInlineLogicalExpression(node);
791
775
 
792
776
  const right = shouldInline
793
- ? [node.type, " ", path.call(print, "right")]
794
- : [node.type, line, path.call(print, "right")];
777
+ ? [node.type, " ", print("right")]
778
+ : [node.type, line, print("right")];
795
779
 
796
780
  // If there's only a single binary expression, we want to create a group
797
781
  // in order to avoid having a small right part like -1 be on its own line.
798
- const parent = path.getParentNode();
782
+ const { parent } = path;
799
783
  const shouldGroup =
800
784
  !(isInsideParenthesis && ["||", "&&"].includes(node.type)) &&
801
785
  getNodeKindIncludingLogical(parent) !==
@@ -818,18 +802,18 @@ function printBinaryExpression(
818
802
  // the other ones since we don't call the normal print on bin,
819
803
  // only for the left and right parts
820
804
  if (isNested && node.comments) {
821
- parts = comments.printAllComments(path, () => parts, options);
805
+ parts = printAllComments(path, () => parts, options);
822
806
  }
823
807
  } else {
824
808
  // Our stopping case. Simply print the node normally.
825
- parts.push(path.call(print));
809
+ parts.push(print());
826
810
  }
827
811
 
828
812
  return parts;
829
813
  }
830
814
 
831
815
  function printLookupNodes(path, options, print) {
832
- const node = path.getValue();
816
+ const { node } = path;
833
817
 
834
818
  switch (node.kind) {
835
819
  case "propertylookup":
@@ -868,16 +852,13 @@ function printArrayItems(path, options, print) {
868
852
  const printedElements = [];
869
853
  let separatorParts = [];
870
854
 
871
- path.each((childPath) => {
855
+ path.each(({ node }) => {
872
856
  printedElements.push(separatorParts);
873
- printedElements.push(group(print(childPath)));
857
+ printedElements.push(group(print()));
874
858
 
875
859
  separatorParts = [",", line];
876
860
 
877
- if (
878
- childPath.getValue() &&
879
- isNextLineEmpty(options.originalText, childPath.getValue(), options)
880
- ) {
861
+ if (node && isNextLineEmpty(options.originalText, node, options)) {
881
862
  separatorParts.push(softline);
882
863
  }
883
864
  }, "items");
@@ -930,22 +911,26 @@ function wrapPartsIntoGroups(parts, indexes) {
930
911
  }
931
912
 
932
913
  function printLines(path, options, print, childrenAttribute = "children") {
933
- const node = path.getValue();
934
- const parentNode = path.getParentNode();
914
+ const { node, parent: parentNode } = path;
935
915
 
936
916
  let lastInlineIndex = -1;
937
917
 
938
918
  const parts = [];
939
919
  const groupIndexes = [];
940
920
 
941
- path.map((childPath, index) => {
942
- const childNode = childPath.getValue();
921
+ path.map(() => {
922
+ const {
923
+ node: childNode,
924
+ next: nextNode,
925
+ isFirst: isFirstNode,
926
+ isLast: isLastNode,
927
+ index,
928
+ } = path;
929
+
943
930
  const isInlineNode = childNode.kind === "inline";
944
- const printedPath = print(childPath);
945
- const children = node[childrenAttribute];
946
- const nextNode = children[index + 1];
931
+ const printedPath = print();
947
932
  const canPrintBlankLine =
948
- !isLastStatement(childPath) &&
933
+ !isLastStatement(path) &&
949
934
  !isInlineNode &&
950
935
  (nextNode && nextNode.kind === "case"
951
936
  ? !isFirstChildrenInlineNode(path)
@@ -960,8 +945,6 @@ function printLines(path, options, print, childrenAttribute = "children") {
960
945
  : "",
961
946
  ];
962
947
 
963
- const isFirstNode = index === 0;
964
- const isLastNode = children.length - 1 === index;
965
948
  const isBlockNestedNode =
966
949
  node.kind === "block" &&
967
950
  parentNode &&
@@ -986,7 +969,7 @@ function printLines(path, options, print, childrenAttribute = "children") {
986
969
  (isInlineNode ? prevLastInlineIndex : lastInlineIndex) + 1;
987
970
  const end = isLastNode && !isInlineNode ? index + 1 : index;
988
971
  const prevInlineNode =
989
- children[isInlineNode ? prevLastInlineIndex : lastInlineIndex];
972
+ path.siblings[isInlineNode ? prevLastInlineIndex : lastInlineIndex];
990
973
  const alignment = prevInlineNode
991
974
  ? getAlignment(prevInlineNode.raw)
992
975
  : "";
@@ -1024,7 +1007,7 @@ function printLines(path, options, print, childrenAttribute = "children") {
1024
1007
  ? "<?php"
1025
1008
  : "",
1026
1009
  node.kind === "namespace" || !isBlockNestedNode ? hardline : "",
1027
- comments.printComments(childNode.leadingComments, options),
1010
+ printComments(childNode.leadingComments, options),
1028
1011
  hardline,
1029
1012
  "?>",
1030
1013
  ]
@@ -1032,6 +1015,7 @@ function printLines(path, options, print, childrenAttribute = "children") {
1032
1015
  ? ""
1033
1016
  : [beforeCloseTagInlineNode, "?>"];
1034
1017
 
1018
+ //FIXME getNode is used to get ancestors, but it seems this means to get next sibling?
1035
1019
  const nextV = path.getNode(index + 1);
1036
1020
  const skipLastComment = nextV && nextV.children && nextV.children.length;
1037
1021
 
@@ -1040,9 +1024,7 @@ function printLines(path, options, print, childrenAttribute = "children") {
1040
1024
  ? [
1041
1025
  openTag,
1042
1026
  hardline,
1043
- skipLastComment
1044
- ? comments.printComments(childNode.comments, options)
1045
- : "",
1027
+ skipLastComment ? printComments(childNode.comments, options) : "",
1046
1028
  hardline,
1047
1029
  ]
1048
1030
  : isProgramLikeNode(node) && isLastNode
@@ -1069,7 +1051,7 @@ function printLines(path, options, print, childrenAttribute = "children") {
1069
1051
  between && between[2] && between[2].includes("\n")
1070
1052
  ? [hardline, between[2].split("\n").length > 2 ? hardline : ""]
1071
1053
  : " ",
1072
- node.comments ? comments.printComments(node.comments, options) : "",
1054
+ node.comments ? printComments(node.comments, options) : "",
1073
1055
  ];
1074
1056
 
1075
1057
  const shortEcho =
@@ -1116,17 +1098,15 @@ function printLines(path, options, print, childrenAttribute = "children") {
1116
1098
  }
1117
1099
 
1118
1100
  function printStatements(path, options, print, childrenAttribute) {
1119
- return path.map((childPath) => {
1101
+ return path.map(() => {
1120
1102
  const parts = [];
1121
1103
 
1122
- parts.push(print(childPath));
1104
+ parts.push(print());
1123
1105
 
1124
- if (!isLastStatement(childPath)) {
1106
+ if (!isLastStatement(path)) {
1125
1107
  parts.push(hardline);
1126
1108
 
1127
- if (
1128
- isNextLineEmpty(options.originalText, childPath.getValue(), options)
1129
- ) {
1109
+ if (isNextLineEmpty(options.originalText, path.node, options)) {
1130
1110
  parts.push(hardline);
1131
1111
  }
1132
1112
  }
@@ -1143,28 +1123,25 @@ function printClassPart(
1143
1123
  beforePart = " ",
1144
1124
  afterPart = " "
1145
1125
  ) {
1146
- const node = path.getValue();
1147
- const printedBeforePart = hasDanglingComments(node[part])
1126
+ const value = path.node[part];
1127
+ const printedBeforePart = hasDanglingComments(value)
1148
1128
  ? [
1149
1129
  hardline,
1150
- path.call(
1151
- (partPath) => comments.printDanglingComments(partPath, options, true),
1152
- part
1153
- ),
1130
+ path.call(() => printDanglingComments(path, options, true), part),
1154
1131
  hardline,
1155
1132
  ]
1156
1133
  : beforePart;
1157
- const printedPartItems = Array.isArray(node[part])
1134
+ const printedPartItems = Array.isArray(value)
1158
1135
  ? group(
1159
1136
  join(
1160
1137
  ",",
1161
- path.map((itemPartPath) => {
1162
- const printedPart = print(itemPartPath);
1138
+ path.map(({ node }) => {
1139
+ const printedPart = print();
1163
1140
  // Check if any of the implements nodes have comments
1164
- return hasDanglingComments(itemPartPath.getValue())
1141
+ return hasDanglingComments(node)
1165
1142
  ? [
1166
1143
  hardline,
1167
- comments.printDanglingComments(itemPartPath, options, true),
1144
+ printDanglingComments(path, options, true),
1168
1145
  hardline,
1169
1146
  printedPart,
1170
1147
  ]
@@ -1172,7 +1149,7 @@ function printClassPart(
1172
1149
  }, part)
1173
1150
  )
1174
1151
  )
1175
- : [afterPart, path.call(print, part)];
1152
+ : [afterPart, print(part)];
1176
1153
 
1177
1154
  return indent([
1178
1155
  printedBeforePart,
@@ -1183,23 +1160,23 @@ function printClassPart(
1183
1160
 
1184
1161
  function printAttrs(path, options, print, { inline = false } = {}) {
1185
1162
  const allAttrs = [];
1186
- if (!path.getValue().attrGroups) {
1163
+ if (!path.node.attrGroups) {
1187
1164
  return [];
1188
1165
  }
1189
- path.each((agPath) => {
1166
+ path.each(() => {
1190
1167
  const attrGroup = ["#["];
1191
1168
  if (!inline && allAttrs.length > 0) {
1192
1169
  allAttrs.push(hardline);
1193
1170
  }
1194
1171
  attrGroup.push(softline);
1195
- agPath.each((attrPath) => {
1196
- const attrNode = attrPath.getValue();
1172
+ path.each(() => {
1173
+ const attrNode = path.node;
1197
1174
  if (attrGroup.length > 2) {
1198
1175
  attrGroup.push(",", line);
1199
1176
  }
1200
1177
  const attrStmt = [attrNode.name];
1201
1178
  if (attrNode.args.length > 0) {
1202
- attrStmt.push(printArgumentsList(attrPath, options, print, "args"));
1179
+ attrStmt.push(printArgumentsList(path, options, print, "args"));
1203
1180
  }
1204
1181
  attrGroup.push(group(attrStmt));
1205
1182
  }, "attrs");
@@ -1220,7 +1197,7 @@ function printAttrs(path, options, print, { inline = false } = {}) {
1220
1197
  }
1221
1198
 
1222
1199
  function printClass(path, options, print) {
1223
- const node = path.getValue();
1200
+ const { node } = path;
1224
1201
  const isAnonymousClass = node.kind === "class" && node.isAnonymous;
1225
1202
  const attrs = printAttrs(path, options, print, { inline: isAnonymousClass });
1226
1203
  const declaration = isAnonymousClass ? [] : [...attrs];
@@ -1241,11 +1218,11 @@ function printClass(path, options, print) {
1241
1218
  declaration.push(isAnonymousClass ? "" : node.kind);
1242
1219
 
1243
1220
  if (node.name) {
1244
- declaration.push(" ", path.call(print, "name"));
1221
+ declaration.push(" ", print("name"));
1245
1222
  }
1246
1223
 
1247
1224
  if (node.kind === "enum" && node.valueType) {
1248
- declaration.push(": ", path.call(print, "valueType"));
1225
+ declaration.push(": ", print("valueType"));
1249
1226
  }
1250
1227
 
1251
1228
  // Only `class` can have `extends` and `implements`
@@ -1331,7 +1308,7 @@ function printClass(path, options, print) {
1331
1308
  hasEmptyClassBody ? "" : hardline,
1332
1309
  printStatements(path, options, print, "body"),
1333
1310
  ]),
1334
- comments.printDanglingComments(path, options, true),
1311
+ printDanglingComments(path, options, true),
1335
1312
  isAnonymousClass && hasEmptyClassBody ? softline : hardline,
1336
1313
  "}",
1337
1314
  ];
@@ -1340,7 +1317,7 @@ function printClass(path, options, print) {
1340
1317
  }
1341
1318
 
1342
1319
  function printFunction(path, options, print) {
1343
- const node = path.getValue();
1320
+ const { node } = path;
1344
1321
  const declAttrs = printAttrs(path, options, print, {
1345
1322
  inline: node.kind === "closure",
1346
1323
  });
@@ -1369,7 +1346,7 @@ function printFunction(path, options, print) {
1369
1346
  }
1370
1347
 
1371
1348
  if (node.name) {
1372
- declaration.push(path.call(print, "name"));
1349
+ declaration.push(print("name"));
1373
1350
  }
1374
1351
 
1375
1352
  declaration.push(printArgumentsList(path, options, print));
@@ -1385,16 +1362,12 @@ function printFunction(path, options, print) {
1385
1362
  ": ",
1386
1363
  hasDanglingComments(node.type)
1387
1364
  ? [
1388
- path.call(
1389
- (typePath) =>
1390
- comments.printDanglingComments(typePath, options, true),
1391
- "type"
1392
- ),
1365
+ path.call(() => printDanglingComments(path, options, true), "type"),
1393
1366
  " ",
1394
1367
  ]
1395
1368
  : "",
1396
1369
  node.nullable ? "?" : "",
1397
- path.call(print, "type"),
1370
+ print("type"),
1398
1371
  ]);
1399
1372
  }
1400
1373
 
@@ -1407,7 +1380,7 @@ function printFunction(path, options, print) {
1407
1380
  const isClosure = node.kind === "closure";
1408
1381
  const printedBody = [
1409
1382
  "{",
1410
- indent([hasEmptyBody(path) ? "" : hardline, path.call(print, "body")]),
1383
+ indent([hasEmptyBody(path) ? "" : hardline, print("body")]),
1411
1384
  isClosure && hasEmptyBody(path) ? "" : hardline,
1412
1385
  "}",
1413
1386
  ];
@@ -1450,13 +1423,13 @@ function printBodyControlStructure(
1450
1423
  print,
1451
1424
  bodyProperty = "body"
1452
1425
  ) {
1453
- const node = path.getValue();
1426
+ const { node } = path;
1454
1427
 
1455
1428
  if (!node[bodyProperty]) {
1456
1429
  return ";";
1457
1430
  }
1458
1431
 
1459
- const printedBody = path.call(print, bodyProperty);
1432
+ const printedBody = print(bodyProperty);
1460
1433
 
1461
1434
  return [
1462
1435
  node.shortForm ? ":" : " {",
@@ -1529,9 +1502,7 @@ function printAssignmentRight(
1529
1502
  ) {
1530
1503
  const ref = hasRef ? "&" : "";
1531
1504
 
1532
- if (
1533
- comments.hasLeadingOwnLineComment(options.originalText, rightNode, options)
1534
- ) {
1505
+ if (hasLeadingOwnLineComment(options.originalText, rightNode, options)) {
1535
1506
  return indent([hardline, ref, printedRight]);
1536
1507
  }
1537
1508
 
@@ -1567,7 +1538,7 @@ function needsHardlineAfterDanglingComment(node) {
1567
1538
  node.comments.filter((comment) => !comment.leading && !comment.trailing)
1568
1539
  );
1569
1540
 
1570
- return lastDanglingComment && !comments.isBlockComment(lastDanglingComment);
1541
+ return lastDanglingComment && !isBlockComment(lastDanglingComment);
1571
1542
  }
1572
1543
 
1573
1544
  function stringHasNewLines(node) {
@@ -1586,21 +1557,18 @@ function isStringOnItsOwnLine(node, text, options) {
1586
1557
 
1587
1558
  function printComposedTypes(path, print, glue) {
1588
1559
  return group(
1589
- path.map(
1590
- (uPath, i) => (i === 0 ? [path.call(print)] : [glue, path.call(print)]),
1591
- "types"
1592
- )
1560
+ path.map(({ isFirst }) => (isFirst ? [print()] : [glue, print()]), "types")
1593
1561
  );
1594
1562
  }
1595
1563
 
1596
1564
  function printNode(path, options, print) {
1597
- const node = path.getValue();
1565
+ const { node } = path;
1598
1566
 
1599
1567
  switch (node.kind) {
1600
1568
  case "program": {
1601
1569
  return group([
1602
1570
  printLines(path, options, print),
1603
- comments.printDanglingComments(
1571
+ printDanglingComments(
1604
1572
  path,
1605
1573
  options,
1606
1574
  /* sameIndent */ true,
@@ -1609,18 +1577,15 @@ function printNode(path, options, print) {
1609
1577
  ]);
1610
1578
  }
1611
1579
  case "expressionstatement":
1612
- return path.call(print, "expression");
1580
+ return print("expression");
1613
1581
  case "block":
1614
1582
  return [
1615
1583
  printLines(path, options, print),
1616
- comments.printDanglingComments(path, options, true),
1584
+ printDanglingComments(path, options, true),
1617
1585
  ];
1618
1586
  case "declare": {
1619
1587
  const printDeclareArguments = (path) => {
1620
- return join(
1621
- ", ",
1622
- path.map((directive) => print(directive), "directives")
1623
- );
1588
+ return join(", ", path.map(print, "directives"));
1624
1589
  };
1625
1590
 
1626
1591
  if (["block", "short"].includes(node.mode)) {
@@ -1632,7 +1597,7 @@ function printNode(path, options, print) {
1632
1597
  node.children.length > 0
1633
1598
  ? indent([hardline, printLines(path, options, print)])
1634
1599
  : "",
1635
- comments.printDanglingComments(path, options),
1600
+ printDanglingComments(path, options),
1636
1601
  hardline,
1637
1602
  node.mode === "block" ? "}" : "enddeclare;",
1638
1603
  ];
@@ -1648,7 +1613,7 @@ function printNode(path, options, print) {
1648
1613
  ];
1649
1614
  }
1650
1615
  case "declaredirective":
1651
- return [path.call(print, "key"), "=", path.call(print, "value")];
1616
+ return [print("key"), "=", print("value")];
1652
1617
  case "namespace":
1653
1618
  return [
1654
1619
  "namespace ",
@@ -1657,7 +1622,7 @@ function printNode(path, options, print) {
1657
1622
  : "",
1658
1623
  node.withBrackets ? "{" : ";",
1659
1624
  hasDanglingComments(node)
1660
- ? [" ", comments.printDanglingComments(path, options, true)]
1625
+ ? [" ", printDanglingComments(path, options, true)]
1661
1626
  : "",
1662
1627
  node.children.length > 0
1663
1628
  ? node.withBrackets
@@ -1688,10 +1653,7 @@ function printNode(path, options, print) {
1688
1653
  node.name
1689
1654
  ? [maybeStripLeadingSlashFromUse(node.name), "\\{", softline]
1690
1655
  : "",
1691
- join(
1692
- [",", line],
1693
- path.map((item) => print(item), "items")
1694
- ),
1656
+ join([",", line], path.map(print, "items")),
1695
1657
  ]),
1696
1658
  node.name
1697
1659
  ? [
@@ -1706,9 +1668,9 @@ function printNode(path, options, print) {
1706
1668
  node.type ? [node.type, " "] : "",
1707
1669
  maybeStripLeadingSlashFromUse(node.name),
1708
1670
  hasDanglingComments(node)
1709
- ? [" ", comments.printDanglingComments(path, options, true)]
1671
+ ? [" ", printDanglingComments(path, options, true)]
1710
1672
  : "",
1711
- node.alias ? [" as ", path.call(print, "alias")] : "",
1673
+ node.alias ? [" as ", print("alias")] : "",
1712
1674
  ];
1713
1675
  case "class":
1714
1676
  case "enum":
@@ -1717,20 +1679,20 @@ function printNode(path, options, print) {
1717
1679
  return printClass(path, options, print);
1718
1680
  case "traitprecedence":
1719
1681
  return [
1720
- path.call(print, "trait"),
1682
+ print("trait"),
1721
1683
  "::",
1722
- path.call(print, "method"),
1684
+ print("method"),
1723
1685
  " insteadof ",
1724
1686
  join(", ", path.map(print, "instead")),
1725
1687
  ];
1726
1688
  case "traitalias":
1727
1689
  return [
1728
- node.trait ? [path.call(print, "trait"), "::"] : "",
1729
- node.method ? path.call(print, "method") : "",
1690
+ node.trait ? [print("trait"), "::"] : "",
1691
+ node.method ? print("method") : "",
1730
1692
  " as ",
1731
1693
  join(" ", [
1732
1694
  ...(node.visibility ? [node.visibility] : []),
1733
- ...(node.as ? [path.call(print, "as")] : []),
1695
+ ...(node.as ? [print("as")] : []),
1734
1696
  ]),
1735
1697
  ];
1736
1698
  case "traituse":
@@ -1749,11 +1711,7 @@ function printNode(path, options, print) {
1749
1711
  hardline,
1750
1712
  ]
1751
1713
  : hasDanglingComments(node)
1752
- ? [
1753
- line,
1754
- comments.printDanglingComments(path, options, true),
1755
- line,
1756
- ]
1714
+ ? [line, printDanglingComments(path, options, true), line]
1757
1715
  : "",
1758
1716
  "}",
1759
1717
  ]
@@ -1770,11 +1728,9 @@ function printNode(path, options, print) {
1770
1728
  node.isStatic ? "static " : "",
1771
1729
  "fn",
1772
1730
  printArgumentsList(path, options, print),
1773
- node.type
1774
- ? [": ", node.nullable ? "?" : "", path.call(print, "type")]
1775
- : "",
1731
+ node.type ? [": ", node.nullable ? "?" : "", print("type")] : "",
1776
1732
  " => ",
1777
- path.call(print, "body"),
1733
+ print("body"),
1778
1734
  node.parenthesizedExpression ? ")" : "",
1779
1735
  ];
1780
1736
  case "parameter": {
@@ -1791,11 +1747,11 @@ function printNode(path, options, print) {
1791
1747
  promoted,
1792
1748
  node.readonly ? "readonly " : "",
1793
1749
  node.nullable ? "?" : "",
1794
- node.type ? [path.call(print, "type"), " "] : "",
1750
+ node.type ? [print("type"), " "] : "",
1795
1751
  node.byref ? "&" : "",
1796
1752
  node.variadic ? "..." : "",
1797
1753
  "$",
1798
- path.call(print, "name"),
1754
+ print("name"),
1799
1755
  ];
1800
1756
 
1801
1757
  if (node.value) {
@@ -1805,12 +1761,12 @@ function printNode(path, options, print) {
1805
1761
  // no node to attach comments that fall in between the parameter name
1806
1762
  // and value, we store them as dangling comments
1807
1763
  hasDanglingComments(node) ? " " : "",
1808
- comments.printDanglingComments(path, options, true),
1764
+ printDanglingComments(path, options, true),
1809
1765
  " =",
1810
1766
  printAssignmentRight(
1811
1767
  node.name,
1812
1768
  node.value,
1813
- path.call(print, "value"),
1769
+ print("value"),
1814
1770
  false,
1815
1771
  options
1816
1772
  ),
@@ -1820,22 +1776,20 @@ function printNode(path, options, print) {
1820
1776
  return name;
1821
1777
  }
1822
1778
  case "variadic":
1823
- return ["...", path.call(print, "what")];
1779
+ return ["...", print("what")];
1824
1780
  case "property":
1825
1781
  return group([
1826
1782
  node.readonly ? "readonly " : "",
1827
- node.type
1828
- ? [node.nullable ? "?" : "", path.call(print, "type"), " "]
1829
- : "",
1783
+ node.type ? [node.nullable ? "?" : "", print("type"), " "] : "",
1830
1784
  "$",
1831
- path.call(print, "name"),
1785
+ print("name"),
1832
1786
  node.value
1833
1787
  ? [
1834
1788
  " =",
1835
1789
  printAssignmentRight(
1836
1790
  node.name,
1837
1791
  node.value,
1838
- path.call(print, "value"),
1792
+ print("value"),
1839
1793
  false,
1840
1794
  options
1841
1795
  ),
@@ -1844,13 +1798,10 @@ function printNode(path, options, print) {
1844
1798
  ]);
1845
1799
  case "propertystatement": {
1846
1800
  const attrs = [];
1847
- path.map(
1848
- (propPath) => attrs.push(...printAttrs(propPath, options, print)),
1849
- "properties"
1850
- );
1851
- const printed = path.map((childPath) => {
1852
- return print(childPath);
1801
+ path.each(() => {
1802
+ attrs.push(...printAttrs(path, options, print));
1853
1803
  }, "properties");
1804
+ const printed = path.map(print, "properties");
1854
1805
 
1855
1806
  const hasValue = node.properties.some((property) => property.value);
1856
1807
 
@@ -1882,7 +1833,7 @@ function printNode(path, options, print) {
1882
1833
  const body = printBodyControlStructure(path, options, print, "body");
1883
1834
  const opening = group([
1884
1835
  "if (",
1885
- group([indent([softline, path.call(print, "test")]), softline]),
1836
+ group([indent([softline, print("test")]), softline]),
1886
1837
  ")",
1887
1838
  body,
1888
1839
  ]);
@@ -1898,7 +1849,7 @@ function printNode(path, options, print) {
1898
1849
  const commentOnOwnLine =
1899
1850
  (hasTrailingComment(node.body) &&
1900
1851
  node.body.comments.some(
1901
- (comment) => comment.trailing && !comments.isBlockComment(comment)
1852
+ (comment) => comment.trailing && !isBlockComment(comment)
1902
1853
  )) ||
1903
1854
  needsHardlineAfterDanglingComment(node);
1904
1855
  const elseOnSameLine = !commentOnOwnLine;
@@ -1909,7 +1860,7 @@ function printNode(path, options, print) {
1909
1860
  isNextLineEmpty(options.originalText, node.body, options)
1910
1861
  ? hardline
1911
1862
  : "",
1912
- comments.printDanglingComments(path, options, true),
1863
+ printDanglingComments(path, options, true),
1913
1864
  commentOnOwnLine ? hardline : " "
1914
1865
  );
1915
1866
  }
@@ -1918,7 +1869,7 @@ function printNode(path, options, print) {
1918
1869
  "else",
1919
1870
  group(
1920
1871
  node.alternate.kind === "if"
1921
- ? path.call(print, "alternate")
1872
+ ? print("alternate")
1922
1873
  : printBodyControlStructure(path, options, print, "alternate")
1923
1874
  )
1924
1875
  );
@@ -1933,7 +1884,7 @@ function printNode(path, options, print) {
1933
1884
  "do",
1934
1885
  printBodyControlStructure(path, options, print, "body"),
1935
1886
  " while (",
1936
- group([indent([softline, path.call(print, "test")]), softline]),
1887
+ group([indent([softline, print("test")]), softline]),
1937
1888
  ")",
1938
1889
  ];
1939
1890
  case "while":
@@ -1941,7 +1892,7 @@ function printNode(path, options, print) {
1941
1892
  return group([
1942
1893
  node.kind,
1943
1894
  " (",
1944
- group([indent([softline, path.call(print, "test")]), softline]),
1895
+ group([indent([softline, print("test")]), softline]),
1945
1896
  ")",
1946
1897
  printBodyControlStructure(path, options, print, "body"),
1947
1898
  ]);
@@ -1951,7 +1902,7 @@ function printNode(path, options, print) {
1951
1902
  // We want to keep dangling comments above the loop to stay consistent.
1952
1903
  // Any comment positioned between the for statement and the parentheses
1953
1904
  // is going to be printed before the statement.
1954
- const dangling = comments.printDanglingComments(
1905
+ const dangling = printDanglingComments(
1955
1906
  path,
1956
1907
  options,
1957
1908
  /* sameLine */ true
@@ -1990,7 +1941,7 @@ function printNode(path, options, print) {
1990
1941
  // We want to keep dangling comments above the loop to stay consistent.
1991
1942
  // Any comment positioned between the for statement and the parentheses
1992
1943
  // is going to be printed before the statement.
1993
- const dangling = comments.printDanglingComments(
1944
+ const dangling = printDanglingComments(
1994
1945
  path,
1995
1946
  options,
1996
1947
  /* sameLine */ true
@@ -2004,18 +1955,13 @@ function printNode(path, options, print) {
2004
1955
  group([
2005
1956
  indent([
2006
1957
  softline,
2007
- path.call(print, "source"),
1958
+ print("source"),
2008
1959
  line,
2009
1960
  "as ",
2010
1961
  group(
2011
1962
  node.key
2012
- ? indent(
2013
- join(
2014
- [" =>", line],
2015
- [path.call(print, "key"), path.call(print, "value")]
2016
- )
2017
- )
2018
- : path.call(print, "value")
1963
+ ? indent(join([" =>", line], [print("key"), print("value")]))
1964
+ : print("value")
2019
1965
  ),
2020
1966
  ]),
2021
1967
  softline,
@@ -2053,7 +1999,7 @@ function printNode(path, options, print) {
2053
1999
  ? [
2054
2000
  " (",
2055
2001
  join(" | ", path.map(print, "what")),
2056
- node.variable ? [" ", path.call(print, "variable")] : "",
2002
+ node.variable ? [" ", print("variable")] : "",
2057
2003
  ")",
2058
2004
  ]
2059
2005
  : "",
@@ -2065,9 +2011,7 @@ function printNode(path, options, print) {
2065
2011
  node.test
2066
2012
  ? [
2067
2013
  "case ",
2068
- node.test.comments
2069
- ? indent(path.call(print, "test"))
2070
- : path.call(print, "test"),
2014
+ node.test.comments ? indent(print("test")) : print("test"),
2071
2015
  ":",
2072
2016
  ]
2073
2017
  : "default:",
@@ -2075,7 +2019,7 @@ function printNode(path, options, print) {
2075
2019
  ? node.body.children && node.body.children.length
2076
2020
  ? indent([
2077
2021
  isFirstChildrenInlineNode(path) ? "" : hardline,
2078
- path.call(print, "body"),
2022
+ print("body"),
2079
2023
  ])
2080
2024
  : ""
2081
2025
  : "",
@@ -2084,7 +2028,7 @@ function printNode(path, options, print) {
2084
2028
  case "continue":
2085
2029
  if (node.level) {
2086
2030
  if (node.level.kind === "number" && node.level.value !== "1") {
2087
- return [`${node.kind} `, path.call(print, "level")];
2031
+ return [`${node.kind} `, print("level")];
2088
2032
  }
2089
2033
 
2090
2034
  return node.kind;
@@ -2098,7 +2042,7 @@ function printNode(path, options, print) {
2098
2042
  isStringOnItsOwnLine(node.arguments[0], options.originalText, options)
2099
2043
  ) {
2100
2044
  return [
2101
- path.call(print, "what"),
2045
+ print("what"),
2102
2046
  "(",
2103
2047
  join(", ", path.map(print, "arguments")),
2104
2048
  ")",
@@ -2110,10 +2054,7 @@ function printNode(path, options, print) {
2110
2054
  return printMemberChain(path, options, print);
2111
2055
  }
2112
2056
 
2113
- return [
2114
- path.call(print, "what"),
2115
- printArgumentsList(path, options, print),
2116
- ];
2057
+ return [print("what"), printArgumentsList(path, options, print)];
2117
2058
  }
2118
2059
  case "new": {
2119
2060
  const isAnonymousClassNode =
@@ -2128,7 +2069,7 @@ function printNode(path, options, print) {
2128
2069
  return [
2129
2070
  "new ",
2130
2071
  ...path.call(printAttrs, "what"),
2131
- path.call(print, "what"),
2072
+ print("what"),
2132
2073
  "(",
2133
2074
  join(", ", path.map(print, "arguments")),
2134
2075
  ")",
@@ -2143,23 +2084,23 @@ function printNode(path, options, print) {
2143
2084
  parts.push(
2144
2085
  node.what.leadingComments &&
2145
2086
  node.what.leadingComments[0].kind === "commentblock"
2146
- ? [comments.printComments(node.what.leadingComments, options), " "]
2087
+ ? [printComments(node.what.leadingComments, options), " "]
2147
2088
  : "",
2148
2089
  ...path.call(
2149
- (pa) => printAttrs(pa, options, print, { inline: true }),
2090
+ () => printAttrs(path, options, print, { inline: true }),
2150
2091
  "what"
2151
2092
  ),
2152
2093
  "class",
2153
2094
  node.arguments.length > 0
2154
2095
  ? [" ", printArgumentsList(path, options, print)]
2155
2096
  : "",
2156
- group(path.call(print, "what"))
2097
+ group(print("what"))
2157
2098
  );
2158
2099
  } else {
2159
2100
  const isExpression = ["call", "offsetlookup"].includes(node.what.kind);
2160
2101
  const printed = [
2161
2102
  isExpression ? "(" : "",
2162
- path.call(print, "what"),
2103
+ print("what"),
2163
2104
  isExpression ? ")" : "",
2164
2105
  printArgumentsList(path, options, print),
2165
2106
  ];
@@ -2172,19 +2113,17 @@ function printNode(path, options, print) {
2172
2113
  case "clone":
2173
2114
  return [
2174
2115
  "clone ",
2175
- node.what.comments
2176
- ? indent(path.call(print, "what"))
2177
- : path.call(print, "what"),
2116
+ node.what.comments ? indent(print("what")) : print("what"),
2178
2117
  ];
2179
2118
  case "propertylookup":
2180
2119
  case "nullsafepropertylookup":
2181
2120
  case "staticlookup":
2182
2121
  case "offsetlookup": {
2183
- const parent = path.getParentNode();
2122
+ const { parent } = path;
2184
2123
 
2124
+ // TODO: Use `AstPath.findAncestor` when it's stable
2185
2125
  let firstNonMemberParent;
2186
2126
  let i = 0;
2187
-
2188
2127
  do {
2189
2128
  firstNonMemberParent = path.getParentNode(i);
2190
2129
  i++;
@@ -2206,7 +2145,7 @@ function printNode(path, options, print) {
2206
2145
  !isLookupNode(parent));
2207
2146
 
2208
2147
  return [
2209
- path.call(print, "what"),
2148
+ print("what"),
2210
2149
  shouldInline
2211
2150
  ? printLookupNodes(path, options, print)
2212
2151
  : group(indent([softline, printLookupNodes(path, options, print)])),
@@ -2218,9 +2157,9 @@ function printNode(path, options, print) {
2218
2157
  "(",
2219
2158
  node.expression
2220
2159
  ? isStringOnItsOwnLine(node.expression, options.originalText, options)
2221
- ? path.call(print, "expression")
2222
- : [indent([softline, path.call(print, "expression")]), softline]
2223
- : comments.printDanglingComments(path, options),
2160
+ ? print("expression")
2161
+ : [indent([softline, print("expression")]), softline]
2162
+ : printDanglingComments(path, options),
2224
2163
  ")",
2225
2164
  ]);
2226
2165
  case "global":
@@ -2233,32 +2172,24 @@ function printNode(path, options, print) {
2233
2172
  node.require ? "require" : "include",
2234
2173
  node.once ? "_once" : "",
2235
2174
  " ",
2236
- node.target.comments
2237
- ? indent(path.call(print, "target"))
2238
- : path.call(print, "target"),
2175
+ node.target.comments ? indent(print("target")) : print("target"),
2239
2176
  ];
2240
2177
  case "label":
2241
- return [path.call(print, "name"), ":"];
2178
+ return [print("name"), ":"];
2242
2179
  case "goto":
2243
- return ["goto ", path.call(print, "label")];
2180
+ return ["goto ", print("label")];
2244
2181
  case "throw":
2245
2182
  return [
2246
2183
  "throw ",
2247
- node.what.comments
2248
- ? indent(path.call(print, "what"))
2249
- : path.call(print, "what"),
2184
+ node.what.comments ? indent(print("what")) : print("what"),
2250
2185
  ];
2251
2186
  case "silent":
2252
- return ["@", path.call(print, "expr")];
2187
+ return ["@", print("expr")];
2253
2188
  case "halt":
2254
2189
  return [
2255
2190
  hasDanglingComments(node)
2256
2191
  ? [
2257
- comments.printDanglingComments(
2258
- path,
2259
- options,
2260
- /* sameIndent */ true
2261
- ),
2192
+ printDanglingComments(path, options, /* sameIndent */ true),
2262
2193
  hardline,
2263
2194
  ]
2264
2195
  : "",
@@ -2269,14 +2200,12 @@ function printNode(path, options, print) {
2269
2200
  return group([
2270
2201
  "eval(",
2271
2202
  isStringOnItsOwnLine(node.source, options.originalText, options)
2272
- ? path.call(print, "source")
2273
- : [indent([softline, path.call(print, "source")]), softline],
2203
+ ? print("source")
2204
+ : [indent([softline, print("source")]), softline],
2274
2205
  ")",
2275
2206
  ]);
2276
2207
  case "echo": {
2277
- const printedArguments = path.map((childPath) => {
2278
- return print(childPath);
2279
- }, "expressions");
2208
+ const printedArguments = path.map(print, "expressions");
2280
2209
 
2281
2210
  let firstVariable;
2282
2211
 
@@ -2299,8 +2228,8 @@ function printNode(path, options, print) {
2299
2228
  return [
2300
2229
  "print ",
2301
2230
  node.expression.comments
2302
- ? indent(path.call(print, "expression"))
2303
- : path.call(print, "expression"),
2231
+ ? indent(print("expression"))
2232
+ : print("expression"),
2304
2233
  ];
2305
2234
  }
2306
2235
  case "return": {
@@ -2309,7 +2238,7 @@ function printNode(path, options, print) {
2309
2238
  parts.push("return");
2310
2239
 
2311
2240
  if (node.expr) {
2312
- const printedExpr = path.call(print, "expr");
2241
+ const printedExpr = print("expr");
2313
2242
 
2314
2243
  parts.push(" ", node.expr.comments ? indent(printedExpr) : printedExpr);
2315
2244
  }
@@ -2317,7 +2246,7 @@ function printNode(path, options, print) {
2317
2246
  if (hasDanglingComments(node)) {
2318
2247
  parts.push(
2319
2248
  " ",
2320
- comments.printDanglingComments(path, options, /* sameIndent */ true)
2249
+ printDanglingComments(path, options, /* sameIndent */ true)
2321
2250
  );
2322
2251
  }
2323
2252
 
@@ -2332,13 +2261,12 @@ function printNode(path, options, print) {
2332
2261
  case "empty":
2333
2262
  return group([
2334
2263
  "empty(",
2335
- indent([softline, path.call(print, "expression")]),
2264
+ indent([softline, print("expression")]),
2336
2265
  softline,
2337
2266
  ")",
2338
2267
  ]);
2339
2268
  case "variable": {
2340
- const parent = path.getParentNode();
2341
- const parentParent = path.getParentNode(1);
2269
+ const { parent, grandparent: parentParent } = path;
2342
2270
  const ampersand = parent.kind === "assign" ? "" : node.byref ? "&" : "";
2343
2271
  const dollar =
2344
2272
  (parent.kind === "encapsedpart" &&
@@ -2354,18 +2282,12 @@ function printNode(path, options, print) {
2354
2282
  const openCurly = node.curly ? "{" : "";
2355
2283
  const closeCurly = node.curly ? "}" : "";
2356
2284
 
2357
- return [
2358
- ampersand,
2359
- dollar,
2360
- openCurly,
2361
- path.call(print, "name"),
2362
- closeCurly,
2363
- ];
2285
+ return [ampersand, dollar, openCurly, print("name"), closeCurly];
2364
2286
  }
2365
2287
  case "constantstatement":
2366
2288
  case "classconstant": {
2367
2289
  const attrs = printAttrs(path, options, print);
2368
- const printed = path.map((childPath) => print(childPath), "constants");
2290
+ const printed = path.map(print, "constants");
2369
2291
 
2370
2292
  let firstVariable;
2371
2293
 
@@ -2388,17 +2310,15 @@ function printNode(path, options, print) {
2388
2310
  case "constant":
2389
2311
  return printAssignment(
2390
2312
  node.name,
2391
- path.call(print, "name"),
2313
+ print("name"),
2392
2314
  " =",
2393
2315
  node.value,
2394
- path.call(print, "value"),
2316
+ print("value"),
2395
2317
  false,
2396
2318
  options
2397
2319
  );
2398
2320
  case "static": {
2399
- const printed = path.map((childPath) => {
2400
- return print(childPath);
2401
- }, "variables");
2321
+ const printed = path.map(print, "variables");
2402
2322
 
2403
2323
  const hasValue = node.variables.some((item) => item.defaultValue);
2404
2324
 
@@ -2422,10 +2342,10 @@ function printNode(path, options, print) {
2422
2342
  case "staticvariable": {
2423
2343
  return printAssignment(
2424
2344
  node.variable,
2425
- path.call(print, "variable"),
2345
+ print("variable"),
2426
2346
  " =",
2427
2347
  node.defaultValue,
2428
- path.call(print, "defaultValue"),
2348
+ print("defaultValue"),
2429
2349
  false,
2430
2350
  options
2431
2351
  );
@@ -2446,7 +2366,7 @@ function printNode(path, options, print) {
2446
2366
 
2447
2367
  return group([
2448
2368
  open,
2449
- comments.printDanglingComments(path, options),
2369
+ printDanglingComments(path, options),
2450
2370
  softline,
2451
2371
  close,
2452
2372
  ]);
@@ -2494,7 +2414,7 @@ function printNode(path, options, print) {
2494
2414
  ]
2495
2415
  : ""
2496
2416
  ),
2497
- comments.printDanglingComments(path, options, true),
2417
+ printDanglingComments(path, options, true),
2498
2418
  softline,
2499
2419
  close,
2500
2420
  ],
@@ -2507,19 +2427,19 @@ function printNode(path, options, print) {
2507
2427
  return node.key
2508
2428
  ? printAssignment(
2509
2429
  node.key,
2510
- path.call(print, "key"),
2430
+ print("key"),
2511
2431
  " =>",
2512
2432
  node.value,
2513
- path.call(print, "value"),
2433
+ print("value"),
2514
2434
  ref,
2515
2435
  options
2516
2436
  )
2517
- : [ref, unpack, path.call(print, "value")];
2437
+ : [ref, unpack, print("value")];
2518
2438
  }
2519
2439
  case "yield": {
2520
2440
  const printedKeyAndValue = [
2521
- node.key ? [path.call(print, "key"), " => "] : "",
2522
- path.call(print, "value"),
2441
+ node.key ? [print("key"), " => "] : "",
2442
+ print("value"),
2523
2443
  ];
2524
2444
 
2525
2445
  return [
@@ -2533,24 +2453,20 @@ function printNode(path, options, print) {
2533
2453
  case "yieldfrom":
2534
2454
  return [
2535
2455
  "yield from ",
2536
- node.value.comments
2537
- ? indent(path.call(print, "value"))
2538
- : path.call(print, "value"),
2456
+ node.value.comments ? indent(print("value")) : print("value"),
2539
2457
  ];
2540
2458
  case "unary":
2541
- return [node.type, path.call(print, "what")];
2459
+ return [node.type, print("what")];
2542
2460
  case "pre":
2543
- return [node.type + node.type, path.call(print, "what")];
2461
+ return [node.type + node.type, print("what")];
2544
2462
  case "post":
2545
- return [path.call(print, "what"), node.type + node.type];
2463
+ return [print("what"), node.type + node.type];
2546
2464
  case "cast":
2547
2465
  return [
2548
2466
  "(",
2549
2467
  node.type,
2550
2468
  ") ",
2551
- node.expr.comments
2552
- ? indent(path.call(print, "expr"))
2553
- : path.call(print, "expr"),
2469
+ node.expr.comments ? indent(print("expr")) : print("expr"),
2554
2470
  ];
2555
2471
  case "assignref":
2556
2472
  case "assign": {
@@ -2558,17 +2474,16 @@ function printNode(path, options, print) {
2558
2474
 
2559
2475
  return printAssignment(
2560
2476
  node.left,
2561
- path.call(print, "left"),
2477
+ print("left"),
2562
2478
  [" ", hasRef ? "=" : node.operator],
2563
2479
  node.right,
2564
- path.call(print, "right"),
2480
+ print("right"),
2565
2481
  hasRef,
2566
2482
  options
2567
2483
  );
2568
2484
  }
2569
2485
  case "bin": {
2570
- const parent = path.getParentNode();
2571
- const parentParent = path.getParentNode(1);
2486
+ const { parent, grandparent: parentParent } = path;
2572
2487
  const isInsideParenthesis =
2573
2488
  node !== parent.body &&
2574
2489
  (parent.kind === "if" ||
@@ -2651,8 +2566,9 @@ function printNode(path, options, print) {
2651
2566
  }
2652
2567
  case "retif": {
2653
2568
  const parts = [];
2654
- const parent = path.getParentNode();
2569
+ const { parent } = path;
2655
2570
 
2571
+ // TODO: Use `AstPath.findAncestor` when it's stable
2656
2572
  // Find the outermost non-retif parent, and the outermost retif parent.
2657
2573
  let currentParent;
2658
2574
  let i = 0;
@@ -2665,8 +2581,8 @@ function printNode(path, options, print) {
2665
2581
 
2666
2582
  const printedFalseExpr =
2667
2583
  node.falseExpr.kind === "bin"
2668
- ? indent(path.call(print, "falseExpr"))
2669
- : path.call(print, "falseExpr");
2584
+ ? indent(print("falseExpr"))
2585
+ : print("falseExpr");
2670
2586
  const part = [
2671
2587
  node.trueExpr ? line : " ",
2672
2588
  "?",
@@ -2674,8 +2590,8 @@ function printNode(path, options, print) {
2674
2590
  ? [
2675
2591
  " ",
2676
2592
  node.trueExpr.kind === "bin"
2677
- ? indent(path.call(print, "trueExpr"))
2678
- : path.call(print, "trueExpr"),
2593
+ ? indent(print("trueExpr"))
2594
+ : print("trueExpr"),
2679
2595
  line,
2680
2596
  ]
2681
2597
  : "",
@@ -2699,7 +2615,7 @@ function printNode(path, options, print) {
2699
2615
  // ? $b
2700
2616
  // : $c
2701
2617
  // )->call()
2702
- const parentParent = path.getParentNode(1);
2618
+ const parentParent = path.grandparent;
2703
2619
  const pureParent =
2704
2620
  parent.kind === "cast" && parentParent ? parentParent : parent;
2705
2621
  const breakLookupNodes = [
@@ -2709,7 +2625,7 @@ function printNode(path, options, print) {
2709
2625
  ];
2710
2626
  const breakClosingParens = breakLookupNodes.includes(pureParent.kind);
2711
2627
 
2712
- const printedTest = path.call(print, "test");
2628
+ const printedTest = print("test");
2713
2629
 
2714
2630
  if (!node.trueExpr) {
2715
2631
  const printed = [
@@ -2751,10 +2667,10 @@ function printNode(path, options, print) {
2751
2667
  case "number":
2752
2668
  return printNumber(node.value);
2753
2669
  case "string": {
2754
- const parent = path.getParentNode();
2670
+ const { parent } = path;
2755
2671
 
2756
2672
  if (parent.kind === "encapsedpart") {
2757
- const parentParent = path.getParentNode(1);
2673
+ const parentParent = path.grandparent;
2758
2674
  let closingTagIndentation = 0;
2759
2675
  const flexible = isMinVersion(options.phpVersion, "7.3");
2760
2676
  let linebreak = literalline;
@@ -2818,7 +2734,7 @@ function printNode(path, options, print) {
2818
2734
  ? "}"
2819
2735
  : "";
2820
2736
 
2821
- return [open, path.call(print, "expression"), close];
2737
+ return [open, print("expression"), close];
2822
2738
  }
2823
2739
  case "encapsed":
2824
2740
  switch (node.type) {
@@ -2866,7 +2782,7 @@ function printNode(path, options, print) {
2866
2782
  case "name":
2867
2783
  return [node.resolution === "rn" ? "namespace\\" : "", node.name];
2868
2784
  case "literal":
2869
- return path.call(print, "value");
2785
+ return print("value");
2870
2786
  case "parentreference":
2871
2787
  return "parent";
2872
2788
  case "selfreference":
@@ -2878,28 +2794,27 @@ function printNode(path, options, print) {
2878
2794
  case "nullkeyword":
2879
2795
  return "null";
2880
2796
  case "identifier": {
2881
- const parent = path.getParentNode();
2797
+ const { parent } = path;
2882
2798
 
2883
2799
  if (parent.kind === "method") {
2884
2800
  node.name = normalizeMagicMethodName(node.name);
2885
2801
  }
2886
2802
 
2887
- return path.call(print, "name");
2803
+ return print("name");
2888
2804
  }
2889
2805
  case "match": {
2890
- const lastArmIndex = node.arms.length - 1;
2891
- const arms = path.map((armPath, armIdx) => {
2892
- const armNode = armPath.getValue();
2806
+ const arms = path.map(() => {
2807
+ const armNode = path.node;
2893
2808
 
2894
- const maybeLeadingComment = comments.hasLeadingComment(armNode)
2895
- ? [comments.printComments(armNode.leadingComments, options), hardline]
2809
+ const maybeLeadingComment = hasLeadingComment(armNode)
2810
+ ? [printComments(armNode.leadingComments, options), hardline]
2896
2811
  : [];
2897
2812
  const maybeTrailingComma =
2898
- armIdx < lastArmIndex || options.trailingCommaPHP ? "," : "";
2899
- const maybeTrailingComment = comments.hasTrailingComment(armNode)
2813
+ !path.isLast || options.trailingCommaPHP ? "," : "";
2814
+ const maybeTrailingComment = hasTrailingComment(armNode)
2900
2815
  ? [
2901
2816
  " ",
2902
- comments.printComments(
2817
+ printComments(
2903
2818
  armNode.comments.filter((c) => c.trailing),
2904
2819
  options
2905
2820
  ),
@@ -2909,14 +2824,13 @@ function printNode(path, options, print) {
2909
2824
  const conds =
2910
2825
  armNode.conds === null
2911
2826
  ? "default"
2912
- : armPath.map(
2913
- (condPath, condIdx) =>
2914
- [",", line, print(condPath)].slice(condIdx === 0 ? 2 : 0),
2827
+ : path.map(
2828
+ ({ isFirst }) => [",", line, print()].slice(isFirst ? 2 : 0),
2915
2829
  "conds"
2916
2830
  );
2917
- const body = armPath.call(print, "body");
2831
+ const body = print("body");
2918
2832
  const maybeEmptyLineBetweenArms =
2919
- armIdx > 0 &&
2833
+ !path.isFirst &&
2920
2834
  isPreviousLineEmpty(options.originalText, armNode, options)
2921
2835
  ? hardline
2922
2836
  : "";
@@ -2933,11 +2847,11 @@ function printNode(path, options, print) {
2933
2847
  maybeTrailingComma,
2934
2848
  ...maybeTrailingComment,
2935
2849
  ]),
2936
- ].slice(armIdx > 0 ? 0 : 1);
2850
+ ].slice(!path.isFirst ? 0 : 1);
2937
2851
  }, "arms");
2938
2852
  return group([
2939
2853
  "match (",
2940
- group([softline, indent(path.call(print, "cond")), softline]),
2854
+ group([softline, indent(print("cond")), softline]),
2941
2855
  ") {",
2942
2856
  group(indent([...arms])),
2943
2857
  " ",
@@ -2947,23 +2861,21 @@ function printNode(path, options, print) {
2947
2861
  }
2948
2862
 
2949
2863
  case "noop":
2950
- return node.comments
2951
- ? comments.printComments(path.getValue().comments, options)
2952
- : "";
2864
+ return node.comments ? printComments(node.comments, options) : "";
2953
2865
  case "namedargument":
2954
- return [node.name, ": ", path.call(print, "value")];
2866
+ return [node.name, ": ", print("value")];
2955
2867
 
2956
2868
  case "enumcase":
2957
2869
  return group([
2958
2870
  "case ",
2959
- path.call(print, "name"),
2871
+ print("name"),
2960
2872
  node.value
2961
2873
  ? [
2962
2874
  " =",
2963
2875
  printAssignmentRight(
2964
2876
  node.name,
2965
2877
  node.value,
2966
- path.call(print, "value"),
2878
+ print("value"),
2967
2879
  false,
2968
2880
  options
2969
2881
  ),
@@ -2980,4 +2892,4 @@ function printNode(path, options, print) {
2980
2892
  }
2981
2893
  }
2982
2894
 
2983
- module.exports = genericPrint;
2895
+ export default genericPrint;