@prettier/plugin-php 0.25.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -7
- package/src/clean.mjs +11 -0
- package/src/comments.mjs +53 -2
- package/src/needs-parens.mjs +6 -1
- package/src/printer.mjs +186 -34
- package/src/util.mjs +7 -0
- package/standalone.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prettier/plugin-php",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Prettier PHP Plugin",
|
|
5
5
|
"repository": "prettier/prettier-php",
|
|
6
6
|
"author": "Lucas Azzola <@azz>",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"index.d.ts"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"linguist-languages": "^
|
|
30
|
-
"php-parser": "^3.
|
|
29
|
+
"linguist-languages": "^9.4.0",
|
|
30
|
+
"php-parser": "^3.7.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@babel/preset-env": "^7.27.2",
|
|
34
|
-
"@rollup/plugin-alias": "^
|
|
34
|
+
"@rollup/plugin-alias": "^6.0.0",
|
|
35
35
|
"@rollup/plugin-babel": "^7.0.0",
|
|
36
36
|
"@rollup/plugin-commonjs": "^29.0.2",
|
|
37
37
|
"@rollup/plugin-inject": "^5.0.5",
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"@rollup/plugin-replace": "^6.0.3",
|
|
41
41
|
"@rollup/plugin-terser": "^0.4.3",
|
|
42
42
|
"c8": "^10.1.3",
|
|
43
|
-
"cross-env": "^
|
|
43
|
+
"cross-env": "^10.1.0",
|
|
44
44
|
"eslint": "8.57.0",
|
|
45
|
-
"eslint-config-prettier": "
|
|
45
|
+
"eslint-config-prettier": "10.1.8",
|
|
46
46
|
"eslint-plugin-import": "2.32.0",
|
|
47
|
-
"eslint-plugin-jest": "
|
|
47
|
+
"eslint-plugin-jest": "29.15.4",
|
|
48
48
|
"eslint-plugin-prettier": "5.5.5",
|
|
49
49
|
"eslint-plugin-prettier-doc": "^1.1.0",
|
|
50
50
|
"jest": "30.3.0",
|
package/src/clean.mjs
CHANGED
|
@@ -101,6 +101,17 @@ function clean(node, newObj) {
|
|
|
101
101
|
newObj.name.name = normalizeMagicMethodName(newObj.name.name);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
// #[A, B] -> #[A] #[B]: the printer gives an attribute whose arguments
|
|
105
|
+
// break a block of its own (PER-CS 12.3), which is the same declaration.
|
|
106
|
+
if (Array.isArray(node.attrGroups) && node.attrGroups.length > 1) {
|
|
107
|
+
newObj.attrGroups = [
|
|
108
|
+
{
|
|
109
|
+
...newObj.attrGroups[0],
|
|
110
|
+
attrs: newObj.attrGroups.flatMap((attrGroup) => attrGroup.attrs),
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
|
|
104
115
|
if (node.kind === "noop") {
|
|
105
116
|
return null;
|
|
106
117
|
}
|
package/src/comments.mjs
CHANGED
|
@@ -62,6 +62,7 @@ function handleOwnLineComment(comment, text, options) {
|
|
|
62
62
|
options
|
|
63
63
|
) ||
|
|
64
64
|
handleTryComments(enclosingNode, followingNode, comment) ||
|
|
65
|
+
handleClassMemberStatementComments(enclosingNode, followingNode, comment) ||
|
|
65
66
|
handleClassComments(enclosingNode, followingNode, comment) ||
|
|
66
67
|
handleFunctionParameter(
|
|
67
68
|
text,
|
|
@@ -201,6 +202,7 @@ function handleRemainingComment(comment, text, options) {
|
|
|
201
202
|
handleGoto(enclosingNode, comment) ||
|
|
202
203
|
handleHalt(precedingNode, enclosingNode, followingNode, comment) ||
|
|
203
204
|
handleBreakAndContinueStatementComments(enclosingNode, comment) ||
|
|
205
|
+
handleClassMemberStatementComments(enclosingNode, followingNode, comment) ||
|
|
204
206
|
handleInlineComments(
|
|
205
207
|
enclosingNode,
|
|
206
208
|
precedingNode,
|
|
@@ -433,6 +435,32 @@ function handleTraitUseComments(enclosingNode, followingNode, comment) {
|
|
|
433
435
|
return false;
|
|
434
436
|
}
|
|
435
437
|
|
|
438
|
+
function handleClassMemberStatementComments(
|
|
439
|
+
enclosingNode,
|
|
440
|
+
followingNode,
|
|
441
|
+
comment
|
|
442
|
+
) {
|
|
443
|
+
if (
|
|
444
|
+
enclosingNode &&
|
|
445
|
+
enclosingNode.kind === "propertystatement" &&
|
|
446
|
+
enclosingNode.properties?.includes(followingNode)
|
|
447
|
+
) {
|
|
448
|
+
addLeadingComment(enclosingNode, comment);
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (
|
|
453
|
+
enclosingNode &&
|
|
454
|
+
enclosingNode.kind === "classconstant" &&
|
|
455
|
+
enclosingNode.constants?.includes(followingNode)
|
|
456
|
+
) {
|
|
457
|
+
addLeadingComment(enclosingNode, comment);
|
|
458
|
+
return true;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
|
|
436
464
|
function handleClassComments(enclosingNode, followingNode, comment) {
|
|
437
465
|
if (
|
|
438
466
|
enclosingNode &&
|
|
@@ -564,8 +592,8 @@ function handleFunctionParameter(
|
|
|
564
592
|
return false;
|
|
565
593
|
}
|
|
566
594
|
if (
|
|
567
|
-
precedingNode
|
|
568
|
-
followingNode
|
|
595
|
+
precedingNode?.kind === "typereference" &&
|
|
596
|
+
followingNode?.kind === "identifier"
|
|
569
597
|
) {
|
|
570
598
|
addTrailingComment(precedingNode, comment);
|
|
571
599
|
return true;
|
|
@@ -907,6 +935,29 @@ function getCommentChildNodes(node) {
|
|
|
907
935
|
node.what.__parent_new_arguments = [...node.arguments];
|
|
908
936
|
return [node.what];
|
|
909
937
|
}
|
|
938
|
+
|
|
939
|
+
if (node.attrGroups && node.attrGroups.length > 0) {
|
|
940
|
+
if (node.kind === "method" || node.kind === "function") {
|
|
941
|
+
// Keep every child (in source order): dropping `body` makes comments
|
|
942
|
+
// inside the body resolve against the return type, dropping `name`
|
|
943
|
+
// makes a comment after the attribute look like it precedes the body.
|
|
944
|
+
return [
|
|
945
|
+
...node.attrGroups,
|
|
946
|
+
...(node.name && typeof node.name === "object" ? [node.name] : []),
|
|
947
|
+
...node.arguments,
|
|
948
|
+
...(node.type ? [node.type] : []),
|
|
949
|
+
...(node.body ? [node.body] : []),
|
|
950
|
+
];
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
if (node.kind === "classconstant") {
|
|
954
|
+
return [...node.attrGroups, ...node.constants];
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
if (node.kind === "enumcase") {
|
|
958
|
+
return node.attrGroups;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
910
961
|
}
|
|
911
962
|
|
|
912
963
|
function canAttachComment(node) {
|
package/src/needs-parens.mjs
CHANGED
|
@@ -192,7 +192,12 @@ function needsParens(path, options) {
|
|
|
192
192
|
case "bin":
|
|
193
193
|
case "retif":
|
|
194
194
|
if (key === "test" && !parent.trueExpr) {
|
|
195
|
-
|
|
195
|
+
// A full ternary in the test position of a shorthand ternary
|
|
196
|
+
// (`?:`) needs parens: `1 ? 2 : 3 ?: 4` is a syntax error in
|
|
197
|
+
// PHP 8. Shorthand ternaries chain left-associatively, so they
|
|
198
|
+
// don't need parens here.
|
|
199
|
+
// https://github.com/prettier/plugin-php/issues/2115
|
|
200
|
+
return !!node.trueExpr;
|
|
196
201
|
}
|
|
197
202
|
|
|
198
203
|
return true;
|
package/src/printer.mjs
CHANGED
|
@@ -1199,31 +1199,16 @@ function printAttrs(path, options, print, { inline = false } = {}) {
|
|
|
1199
1199
|
if (!path.node.attrGroups) {
|
|
1200
1200
|
return [];
|
|
1201
1201
|
}
|
|
1202
|
-
path.each(() => {
|
|
1203
|
-
const attrGroup = ["#["];
|
|
1202
|
+
path.each((attrGroupPath) => {
|
|
1204
1203
|
if (!inline && allAttrs.length > 0) {
|
|
1205
1204
|
allAttrs.push(hardline);
|
|
1206
1205
|
}
|
|
1207
|
-
attrGroup.push(softline);
|
|
1208
|
-
path.each(() => {
|
|
1209
|
-
const attrNode = path.node;
|
|
1210
|
-
if (attrGroup.length > 2) {
|
|
1211
|
-
attrGroup.push(",", line);
|
|
1212
|
-
}
|
|
1213
|
-
const attrStmt = [attrNode.name];
|
|
1214
|
-
if (attrNode.args.length > 0) {
|
|
1215
|
-
attrStmt.push(printArgumentsList(path, options, print, "args"));
|
|
1216
|
-
}
|
|
1217
|
-
attrGroup.push(group(attrStmt));
|
|
1218
|
-
}, "attrs");
|
|
1219
1206
|
allAttrs.push(
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
inline ? ifBreak(softline, " ") : "",
|
|
1226
|
-
])
|
|
1207
|
+
printAllComments(
|
|
1208
|
+
attrGroupPath,
|
|
1209
|
+
() => printAttrGroup(attrGroupPath, options, print, { inline }),
|
|
1210
|
+
options
|
|
1211
|
+
)
|
|
1227
1212
|
);
|
|
1228
1213
|
}, "attrGroups");
|
|
1229
1214
|
if (allAttrs.length === 0) {
|
|
@@ -1232,6 +1217,40 @@ function printAttrs(path, options, print, { inline = false } = {}) {
|
|
|
1232
1217
|
return [...allAttrs, inline ? "" : hardline];
|
|
1233
1218
|
}
|
|
1234
1219
|
|
|
1220
|
+
// PER-CS 12.3: an attribute whose argument list is split over several lines
|
|
1221
|
+
// must be the only one in its `#[...]` block, and its arguments follow the
|
|
1222
|
+
// multiline function call rules (`#[Name(` ... `)]`). So a block is printed on
|
|
1223
|
+
// one line while it fits; otherwise each attribute gets a block of its own and
|
|
1224
|
+
// only the argument lists break.
|
|
1225
|
+
function printAttrGroup(path, options, print, { inline = false } = {}) {
|
|
1226
|
+
const printedAttrs = path.map(({ node: attrNode }) => {
|
|
1227
|
+
const attrStmt = [attrNode.name];
|
|
1228
|
+
if (attrNode.args.length > 0) {
|
|
1229
|
+
attrStmt.push(printArgumentsList(path, options, print, "args"));
|
|
1230
|
+
}
|
|
1231
|
+
return group(attrStmt);
|
|
1232
|
+
}, "attrs");
|
|
1233
|
+
const separator = inline ? ifBreak(softline, " ") : "";
|
|
1234
|
+
|
|
1235
|
+
if (printedAttrs.length === 1) {
|
|
1236
|
+
return group(["#[", printedAttrs[0], "]", separator]);
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
const printedOneBlock = ["#[", join(", ", printedAttrs), "]", separator];
|
|
1240
|
+
const printedOneBlockEach = group(
|
|
1241
|
+
[
|
|
1242
|
+
join(
|
|
1243
|
+
inline ? line : hardline,
|
|
1244
|
+
printedAttrs.map((attr) => ["#[", attr, "]"])
|
|
1245
|
+
),
|
|
1246
|
+
inline ? line : "",
|
|
1247
|
+
],
|
|
1248
|
+
{ shouldBreak: true }
|
|
1249
|
+
);
|
|
1250
|
+
|
|
1251
|
+
return conditionalGroup([printedOneBlock, printedOneBlockEach]);
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1235
1254
|
function printClass(path, options, print) {
|
|
1236
1255
|
const { node } = path;
|
|
1237
1256
|
const isAnonymousClass = node.kind === "class" && node.isAnonymous;
|
|
@@ -1458,6 +1477,38 @@ function printFunction(path, options, print) {
|
|
|
1458
1477
|
];
|
|
1459
1478
|
}
|
|
1460
1479
|
|
|
1480
|
+
// PHP 8.4 property hooks (`{ get => ...; set(...) { ... } }`) on a property or a
|
|
1481
|
+
// promoted constructor parameter. PER-CS puts the opening brace on the
|
|
1482
|
+
// declaration line and one hook per line, preserving single blank lines.
|
|
1483
|
+
function printPropertyHooks(path, options, print) {
|
|
1484
|
+
const { node } = path;
|
|
1485
|
+
|
|
1486
|
+
if (!node.hooks || node.hooks.length === 0) {
|
|
1487
|
+
return "";
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// Interface / abstract declarations (`{ get; set; }`) stay on the property's line.
|
|
1491
|
+
if (node.hooks.every((hook) => !hook.body)) {
|
|
1492
|
+
return [" { ", join(" ", path.map(print, "hooks")), " }"];
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
const printedHooks = path.map(({ node: hook, isLast }) => {
|
|
1496
|
+
const parts = [print()];
|
|
1497
|
+
|
|
1498
|
+
if (!isLast) {
|
|
1499
|
+
parts.push(hardline);
|
|
1500
|
+
|
|
1501
|
+
if (isNextLineEmpty(options.originalText, locEnd(hook))) {
|
|
1502
|
+
parts.push(hardline);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
return parts;
|
|
1507
|
+
}, "hooks");
|
|
1508
|
+
|
|
1509
|
+
return [" {", indent([hardline, ...printedHooks]), hardline, "}"];
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1461
1512
|
function printBodyControlStructure(
|
|
1462
1513
|
path,
|
|
1463
1514
|
options,
|
|
@@ -1766,14 +1817,13 @@ function printNode(path, options, print) {
|
|
|
1766
1817
|
node.parenthesizedExpression ? ")" : "",
|
|
1767
1818
|
];
|
|
1768
1819
|
case "parameter": {
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
}
|
|
1820
|
+
const visibilities = { 1: "public", 2: "protected", 4: "private" };
|
|
1821
|
+
// promoted constructor property: `public`, and/or the asymmetric set
|
|
1822
|
+
// visibility `private(set)` (PHP 8.4)
|
|
1823
|
+
const promoted = [
|
|
1824
|
+
node.flags ? [visibilities[node.flags], " "] : "",
|
|
1825
|
+
node.flagsSet ? [visibilities[node.flagsSet], "(set) "] : "",
|
|
1826
|
+
];
|
|
1777
1827
|
const name = [
|
|
1778
1828
|
...printAttrs(path, options, print, { inline: true }),
|
|
1779
1829
|
promoted,
|
|
@@ -1785,6 +1835,7 @@ function printNode(path, options, print) {
|
|
|
1785
1835
|
"$",
|
|
1786
1836
|
print("name"),
|
|
1787
1837
|
];
|
|
1838
|
+
const hooks = printPropertyHooks(path, options, print);
|
|
1788
1839
|
|
|
1789
1840
|
if (node.value) {
|
|
1790
1841
|
return group([
|
|
@@ -1802,10 +1853,11 @@ function printNode(path, options, print) {
|
|
|
1802
1853
|
false,
|
|
1803
1854
|
options
|
|
1804
1855
|
),
|
|
1856
|
+
hooks,
|
|
1805
1857
|
]);
|
|
1806
1858
|
}
|
|
1807
1859
|
|
|
1808
|
-
return name;
|
|
1860
|
+
return [name, hooks];
|
|
1809
1861
|
}
|
|
1810
1862
|
case "variadic":
|
|
1811
1863
|
return ["...", print("what")];
|
|
@@ -1827,7 +1879,41 @@ function printNode(path, options, print) {
|
|
|
1827
1879
|
),
|
|
1828
1880
|
]
|
|
1829
1881
|
: "",
|
|
1882
|
+
printPropertyHooks(path, options, print),
|
|
1830
1883
|
]);
|
|
1884
|
+
case "propertyhook": {
|
|
1885
|
+
const declaration = [
|
|
1886
|
+
...printAttrs(path, options, print, { inline: true }),
|
|
1887
|
+
node.isFinal ? "final " : "",
|
|
1888
|
+
node.byref ? "&" : "",
|
|
1889
|
+
node.name,
|
|
1890
|
+
node.parameter ? ["(", print("parameter"), ")"] : "",
|
|
1891
|
+
];
|
|
1892
|
+
|
|
1893
|
+
// `get;` / `set;` in an interface or abstract class
|
|
1894
|
+
if (!node.body) {
|
|
1895
|
+
return [...declaration, ";"];
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
// `get => expr;`
|
|
1899
|
+
if (node.body.kind !== "block") {
|
|
1900
|
+
return group([
|
|
1901
|
+
...declaration,
|
|
1902
|
+
" =>",
|
|
1903
|
+
printAssignmentRight(node, node.body, print("body"), false, options),
|
|
1904
|
+
";",
|
|
1905
|
+
]);
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
// `get { ... }` - like a closure, the brace stays on the hook's line
|
|
1909
|
+
return [
|
|
1910
|
+
...declaration,
|
|
1911
|
+
" {",
|
|
1912
|
+
indent([hasEmptyBody(path) ? "" : hardline, print("body")]),
|
|
1913
|
+
hasEmptyBody(path) ? "" : hardline,
|
|
1914
|
+
"}",
|
|
1915
|
+
];
|
|
1916
|
+
}
|
|
1831
1917
|
case "propertystatement": {
|
|
1832
1918
|
const attrs = [];
|
|
1833
1919
|
path.each(() => {
|
|
@@ -1850,10 +1936,18 @@ function printNode(path, options, print) {
|
|
|
1850
1936
|
|
|
1851
1937
|
return group([
|
|
1852
1938
|
...attrs,
|
|
1939
|
+
node.isAbstract ? "abstract " : "",
|
|
1940
|
+
node.isFinal ? "final " : "",
|
|
1853
1941
|
hasVisibility
|
|
1854
1942
|
? [node.visibility === null ? "var" : node.visibility, ""]
|
|
1855
1943
|
: "",
|
|
1856
|
-
|
|
1944
|
+
// asymmetric visibility: `public private(set)`
|
|
1945
|
+
node.visibilitySet
|
|
1946
|
+
? [hasVisibility ? " " : "", node.visibilitySet, "(set)"]
|
|
1947
|
+
: "",
|
|
1948
|
+
node.isStatic
|
|
1949
|
+
? [hasVisibility || node.visibilitySet ? " " : "", "static"]
|
|
1950
|
+
: "",
|
|
1857
1951
|
firstProperty ? [" ", firstProperty] : "",
|
|
1858
1952
|
indent(
|
|
1859
1953
|
printed.slice(1).map((p) => [",", hasValue ? hardline : line, p])
|
|
@@ -2142,11 +2236,64 @@ function printNode(path, options, print) {
|
|
|
2142
2236
|
|
|
2143
2237
|
return parts;
|
|
2144
2238
|
}
|
|
2145
|
-
case "clone":
|
|
2239
|
+
case "clone": {
|
|
2240
|
+
if (!node.properties) {
|
|
2241
|
+
return [
|
|
2242
|
+
"clone ",
|
|
2243
|
+
node.what.comments ? indent(print("what")) : print("what"),
|
|
2244
|
+
];
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
// PHP 8.5 clone with: `clone($obj, ['prop' => $value])`, laid out like
|
|
2248
|
+
// a call with two arguments (see printArgumentsList). No trailing comma:
|
|
2249
|
+
// php-parser does not accept one after the properties expression.
|
|
2250
|
+
const printedWhat = print("what");
|
|
2251
|
+
const printedProperties = print("properties");
|
|
2252
|
+
const printedArguments = [printedWhat, ",", line, printedProperties];
|
|
2253
|
+
const allArgsBrokenOut = () =>
|
|
2254
|
+
group(["clone(", indent([line, ...printedArguments]), line, ")"], {
|
|
2255
|
+
shouldBreak: true,
|
|
2256
|
+
});
|
|
2257
|
+
|
|
2258
|
+
if (!shouldGroupLastArg([node.what, node.properties])) {
|
|
2259
|
+
return group(
|
|
2260
|
+
["clone(", indent([softline, ...printedArguments]), softline, ")"],
|
|
2261
|
+
{
|
|
2262
|
+
shouldBreak: willBreak(printedWhat) || willBreak(printedProperties),
|
|
2263
|
+
}
|
|
2264
|
+
);
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
const somePrintedArgumentsWillBreak =
|
|
2268
|
+
willBreak(printedWhat) || willBreak(printedProperties);
|
|
2269
|
+
const simpleConcat = [
|
|
2270
|
+
"clone(",
|
|
2271
|
+
printedWhat,
|
|
2272
|
+
", ",
|
|
2273
|
+
printedProperties,
|
|
2274
|
+
")",
|
|
2275
|
+
];
|
|
2276
|
+
|
|
2146
2277
|
return [
|
|
2147
|
-
|
|
2148
|
-
|
|
2278
|
+
somePrintedArgumentsWillBreak ? breakParent : "",
|
|
2279
|
+
conditionalGroup(
|
|
2280
|
+
[
|
|
2281
|
+
somePrintedArgumentsWillBreak
|
|
2282
|
+
? ifBreak(allArgsBrokenOut(), simpleConcat)
|
|
2283
|
+
: simpleConcat,
|
|
2284
|
+
[
|
|
2285
|
+
"clone(",
|
|
2286
|
+
printedWhat,
|
|
2287
|
+
", ",
|
|
2288
|
+
group(printedProperties, { shouldBreak: true }),
|
|
2289
|
+
")",
|
|
2290
|
+
],
|
|
2291
|
+
allArgsBrokenOut(),
|
|
2292
|
+
],
|
|
2293
|
+
{ shouldBreak: willBreak(printedWhat) }
|
|
2294
|
+
),
|
|
2149
2295
|
];
|
|
2296
|
+
}
|
|
2150
2297
|
case "propertylookup":
|
|
2151
2298
|
case "nullsafepropertylookup":
|
|
2152
2299
|
case "staticlookup":
|
|
@@ -2306,6 +2453,10 @@ function printNode(path, options, print) {
|
|
|
2306
2453
|
parent.curly) ||
|
|
2307
2454
|
(parentParent &&
|
|
2308
2455
|
parent.kind === "offsetlookup" &&
|
|
2456
|
+
// Only the base variable of the lookup follows the `${` printed
|
|
2457
|
+
// by the encapsedpart; a variable in the offset position is a
|
|
2458
|
+
// nested variable and keeps its own `$`.
|
|
2459
|
+
parent.what === node &&
|
|
2309
2460
|
parentParent.kind === "encapsedpart" &&
|
|
2310
2461
|
parentParent.syntax === "simple" &&
|
|
2311
2462
|
parentParent.curly)
|
|
@@ -2909,6 +3060,7 @@ function printNode(path, options, print) {
|
|
|
2909
3060
|
|
|
2910
3061
|
case "enumcase":
|
|
2911
3062
|
return group([
|
|
3063
|
+
...printAttrs(path, options, print),
|
|
2912
3064
|
"case ",
|
|
2913
3065
|
print("name"),
|
|
2914
3066
|
node.value
|
package/src/util.mjs
CHANGED
|
@@ -354,6 +354,13 @@ function lineShouldEndWithSemicolon(path) {
|
|
|
354
354
|
if (node.kind === "method" && node.isAbstract) {
|
|
355
355
|
return true;
|
|
356
356
|
}
|
|
357
|
+
// a hooked property ends with its closing brace, not a semicolon
|
|
358
|
+
if (
|
|
359
|
+
node.kind === "propertystatement" &&
|
|
360
|
+
node.properties.some((property) => property.hooks?.length > 0)
|
|
361
|
+
) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
357
364
|
if (node.kind === "method") {
|
|
358
365
|
const { parent } = path;
|
|
359
366
|
if (parent && parent.kind === "interface") {
|