@prettier/plugin-php 0.23.0 → 0.24.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/README.md +27 -11
- package/package.json +1 -1
- package/src/needs-parens.mjs +2 -7
- package/src/options.mjs +112 -18
- package/src/parser.mjs +4 -6
- package/src/printer.mjs +18 -17
- package/src/util.mjs +0 -5
- package/standalone.js +1 -1
package/README.md
CHANGED
|
@@ -176,17 +176,33 @@ await prettier.format(YOUR_CODE, {
|
|
|
176
176
|
|
|
177
177
|
Prettier for PHP supports the following options. We recommend that all users set the `phpVersion` option.
|
|
178
178
|
|
|
179
|
-
| Name | Default
|
|
180
|
-
| ------------------ |
|
|
181
|
-
| `phpVersion` | `"
|
|
182
|
-
| `printWidth` | `80`
|
|
183
|
-
| `tabWidth` | `4`
|
|
184
|
-
| `useTabs` | `false`
|
|
185
|
-
| `singleQuote` | `false`
|
|
186
|
-
| `trailingCommaPHP` | `true`
|
|
187
|
-
| `braceStyle` | `"per-cs"`
|
|
188
|
-
| `requirePragma` | `false`
|
|
189
|
-
| `insertPragma` | `false`
|
|
179
|
+
| Name | Default | Description |
|
|
180
|
+
| ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
181
|
+
| `phpVersion` | `"auto"` \* | Allows specifying the PHP version you're using. (See Notes Below) |
|
|
182
|
+
| `printWidth` | `80` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#print-width)) |
|
|
183
|
+
| `tabWidth` | `4` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#tab-width)), The default is `4` based on the `PSR-2` coding standard. |
|
|
184
|
+
| `useTabs` | `false` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#tabs)) |
|
|
185
|
+
| `singleQuote` | `false` | If set to `"true"`, strings that use double quotes but do not rely on the features they add, will be reformatted. Example: `"foo" -> 'foo'`, `"foo $bar" -> "foo $bar"`. |
|
|
186
|
+
| `trailingCommaPHP` | `true` | If set to `true`, trailing commas will be added wherever possible. <br> If set to `false`, no trailing commas are printed. |
|
|
187
|
+
| `braceStyle` | `"per-cs"` | If set to `"per-cs"`, prettier will move open brace for code blocks (classes, functions and methods) onto new line. <br> If set to `"1tbs"`, prettier will move open brace for code blocks (classes, functions and methods) onto same line. |
|
|
188
|
+
| `requirePragma` | `false` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#require-pragma)) |
|
|
189
|
+
| `insertPragma` | `false` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#insert-pragma)) |
|
|
190
|
+
|
|
191
|
+
### \* `phpVersion` Configuration Notes :
|
|
192
|
+
|
|
193
|
+
The default setting `auto`, attempts to auto-detect your supported php versions from a `composer.json` with in the
|
|
194
|
+
current directory or any parent directory, the plugin will use a minimum supported php version from
|
|
195
|
+
`{"require":{"php":"..."}}` to set the phpVersion. If not found or not able to be parsed, it will default to latest
|
|
196
|
+
supported PHP version.
|
|
197
|
+
|
|
198
|
+
You set the `phpVersion` to `composer` and this will only use the `composer.json` file to determine the php
|
|
199
|
+
version, prettier will crash if the PHP cannot be determined.
|
|
200
|
+
|
|
201
|
+
You can also set the `phpVersion` to a specific version, such as `7.4`, `8.0`, `8.1`, `8.2`, or `8.3`.
|
|
202
|
+
|
|
203
|
+
**Please Note:** If the phpVersion is not set correctly for your environment, this plugin will produce code that could
|
|
204
|
+
be incompatible with your PHP runtime. For example, if you are using PHP 7.4, but the plugin is set to PHP 8.3, it will
|
|
205
|
+
produce code that uses features not available in PHP 7.4.
|
|
190
206
|
|
|
191
207
|
## Ignoring code
|
|
192
208
|
|
package/package.json
CHANGED
package/src/needs-parens.mjs
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getPrecedence,
|
|
3
|
-
shouldFlatten,
|
|
4
|
-
isBitwiseOperator,
|
|
5
|
-
isMinVersion,
|
|
6
|
-
} from "./util.mjs";
|
|
1
|
+
import { getPrecedence, shouldFlatten, isBitwiseOperator } from "./util.mjs";
|
|
7
2
|
|
|
8
3
|
function needsParens(path, options) {
|
|
9
4
|
const { parent } = path;
|
|
@@ -135,7 +130,7 @@ function needsParens(path, options) {
|
|
|
135
130
|
case "new": {
|
|
136
131
|
const requiresParens =
|
|
137
132
|
node.kind === "clone" ||
|
|
138
|
-
(node.kind === "new" &&
|
|
133
|
+
(node.kind === "new" && options.phpVersion < 8.4);
|
|
139
134
|
switch (parent.kind) {
|
|
140
135
|
case "propertylookup":
|
|
141
136
|
case "nullsafepropertylookup":
|
package/src/options.mjs
CHANGED
|
@@ -1,30 +1,124 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
1
4
|
const CATEGORY_PHP = "PHP";
|
|
2
5
|
|
|
6
|
+
// prettier-ignore
|
|
7
|
+
const SUPPORTED_PHP_VERSIONS = [
|
|
8
|
+
5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6,
|
|
9
|
+
7.0, 7.1, 7.2, 7.3, 7.4,
|
|
10
|
+
8.0, 8.1, 8.2, 8.3, 8.4,
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
export const LATEST_SUPPORTED_PHP_VERSION = Math.max(...SUPPORTED_PHP_VERSIONS);
|
|
14
|
+
|
|
15
|
+
let getComposerError = "";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Detect the minimum PHP version from the composer.json file
|
|
19
|
+
* @return {number|null} The PHP version to use in the composer.json file, null when not found
|
|
20
|
+
*/
|
|
21
|
+
function getComposerPhpVersion() {
|
|
22
|
+
// Try to find composer.json
|
|
23
|
+
const currentDir = process.cwd();
|
|
24
|
+
let composerPath = null;
|
|
25
|
+
|
|
26
|
+
const directComposerPath = path.join(currentDir, "composer.json");
|
|
27
|
+
if (fs.existsSync(directComposerPath)) {
|
|
28
|
+
composerPath = directComposerPath;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!composerPath) {
|
|
32
|
+
let searchDir = path.dirname(currentDir);
|
|
33
|
+
while (searchDir !== path.parse(searchDir).root) {
|
|
34
|
+
const potentialComposerPath = path.join(searchDir, "composer.json");
|
|
35
|
+
if (fs.existsSync(potentialComposerPath)) {
|
|
36
|
+
composerPath = potentialComposerPath;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
searchDir = path.dirname(searchDir);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (composerPath) {
|
|
44
|
+
try {
|
|
45
|
+
const fileContent = fs.readFileSync(composerPath, "utf8");
|
|
46
|
+
const composerJson = JSON.parse(fileContent);
|
|
47
|
+
|
|
48
|
+
if (composerJson.require && composerJson.require.php) {
|
|
49
|
+
// Check for a wildcard pattern like "7.*"
|
|
50
|
+
const wildcardMatch = composerJson.require.php.match(
|
|
51
|
+
/^(?:[^0-9]*)?([0-9]+)\.\*/
|
|
52
|
+
);
|
|
53
|
+
if (wildcardMatch) {
|
|
54
|
+
return parseFloat(`${wildcardMatch[1]}.0`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Extract version from composer semver format
|
|
58
|
+
const versionMatch = composerJson.require.php.match(
|
|
59
|
+
/^(?:[^0-9]*)?([0-9]+)\.([0-9]+)/
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (versionMatch) {
|
|
63
|
+
return parseFloat(`${versionMatch[1]}.${versionMatch[2]}`);
|
|
64
|
+
} else {
|
|
65
|
+
getComposerError = `Could not decode PHP version (${composerJson.require.php}})`;
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch (e) {
|
|
70
|
+
getComposerError = `Error reading composer.json: ${e.message}`;
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
getComposerError = "Could not find composer.json";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { getComposerPhpVersion };
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Resolve the PHP version to a number based on the provided options.
|
|
83
|
+
*
|
|
84
|
+
*/
|
|
85
|
+
export function resolvePhpVersion(options) {
|
|
86
|
+
if (!options) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (options.phpVersion === "auto") {
|
|
90
|
+
options.phpVersion =
|
|
91
|
+
getComposerPhpVersion() ?? LATEST_SUPPORTED_PHP_VERSION;
|
|
92
|
+
} else if (options.phpVersion === "composer") {
|
|
93
|
+
const v = getComposerPhpVersion();
|
|
94
|
+
if (v === null) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Could not determine PHP version from composer; ${getComposerError}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
options.phpVersion = v;
|
|
100
|
+
} else {
|
|
101
|
+
options.phpVersion = parseFloat(options.phpVersion);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
3
105
|
export default {
|
|
4
106
|
phpVersion: {
|
|
5
107
|
since: "0.13.0",
|
|
6
108
|
category: CATEGORY_PHP,
|
|
7
109
|
type: "choice",
|
|
8
|
-
default: "
|
|
110
|
+
default: "auto",
|
|
9
111
|
description: "Minimum target PHP version.",
|
|
10
112
|
choices: [
|
|
11
|
-
{ value:
|
|
12
|
-
{
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
{ value: "7.2" },
|
|
21
|
-
{ value: "7.3" },
|
|
22
|
-
{ value: "7.4" },
|
|
23
|
-
{ value: "8.0" },
|
|
24
|
-
{ value: "8.1" },
|
|
25
|
-
{ value: "8.2" },
|
|
26
|
-
{ value: "8.3" },
|
|
27
|
-
{ value: "8.4" },
|
|
113
|
+
...SUPPORTED_PHP_VERSIONS.map((v) => ({ value: v.toFixed(1) })),
|
|
114
|
+
{
|
|
115
|
+
value: "composer",
|
|
116
|
+
description: "Use the PHP version defined in composer.json",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
value: "auto",
|
|
120
|
+
description: `Try composer.json, else latest PHP Version (${LATEST_SUPPORTED_PHP_VERSION})`,
|
|
121
|
+
},
|
|
28
122
|
],
|
|
29
123
|
},
|
|
30
124
|
trailingCommaPHP: {
|
package/src/parser.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import engine from "php-parser";
|
|
2
|
-
import
|
|
2
|
+
import { LATEST_SUPPORTED_PHP_VERSION } from "./options.mjs";
|
|
3
|
+
import { resolvePhpVersion } from "./options.mjs";
|
|
3
4
|
|
|
4
5
|
function parse(text, opts) {
|
|
5
6
|
const inMarkdown = opts && opts.parentParser === "markdown";
|
|
@@ -7,19 +8,16 @@ function parse(text, opts) {
|
|
|
7
8
|
if (!text && inMarkdown) {
|
|
8
9
|
return "";
|
|
9
10
|
}
|
|
11
|
+
resolvePhpVersion(opts);
|
|
10
12
|
|
|
11
13
|
// Todo https://github.com/glayzzle/php-parser/issues/170
|
|
12
14
|
text = text.replace(/\?>\n<\?/g, "?>\n___PSEUDO_INLINE_PLACEHOLDER___<?");
|
|
13
15
|
|
|
14
|
-
const latestSupportedPhpVersion = Math.max(
|
|
15
|
-
...options.phpVersion.choices.map((c) => parseFloat(c.value))
|
|
16
|
-
);
|
|
17
|
-
|
|
18
16
|
// initialize a new parser instance
|
|
19
17
|
const parser = new engine({
|
|
20
18
|
parser: {
|
|
21
19
|
extractDoc: true,
|
|
22
|
-
version: `${
|
|
20
|
+
version: `${LATEST_SUPPORTED_PHP_VERSION}`,
|
|
23
21
|
},
|
|
24
22
|
ast: {
|
|
25
23
|
withPositions: true,
|
package/src/printer.mjs
CHANGED
|
@@ -37,7 +37,6 @@ import {
|
|
|
37
37
|
isReferenceLikeNode,
|
|
38
38
|
normalizeMagicMethodName,
|
|
39
39
|
isSimpleCallArgument,
|
|
40
|
-
isMinVersion,
|
|
41
40
|
} from "./util.mjs";
|
|
42
41
|
|
|
43
42
|
const {
|
|
@@ -66,12 +65,19 @@ const {
|
|
|
66
65
|
isPreviousLineEmpty,
|
|
67
66
|
} = prettierUtil;
|
|
68
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Determine if we should print a trailing comma based on the config & php version
|
|
70
|
+
*
|
|
71
|
+
* @param options {object} Prettier Options
|
|
72
|
+
* @param requiredVersion {number}
|
|
73
|
+
* @returns {boolean}
|
|
74
|
+
*/
|
|
69
75
|
function shouldPrintComma(options, requiredVersion) {
|
|
70
76
|
if (!options.trailingCommaPHP) {
|
|
71
77
|
return false;
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
return
|
|
80
|
+
return options.phpVersion >= requiredVersion;
|
|
75
81
|
}
|
|
76
82
|
|
|
77
83
|
function shouldPrintHardlineForOpenBrace(options) {
|
|
@@ -612,9 +618,9 @@ function printArgumentsList(path, options, print, argumentsKey = "arguments") {
|
|
|
612
618
|
const lastArg = getLast(args);
|
|
613
619
|
|
|
614
620
|
const maybeTrailingComma =
|
|
615
|
-
(shouldPrintComma(options,
|
|
621
|
+
(shouldPrintComma(options, 7.3) &&
|
|
616
622
|
["call", "new", "unset", "isset"].includes(node.kind)) ||
|
|
617
|
-
(shouldPrintComma(options,
|
|
623
|
+
(shouldPrintComma(options, 8.0) &&
|
|
618
624
|
["function", "closure", "method", "arrowfunc", "attribute"].includes(
|
|
619
625
|
node.kind
|
|
620
626
|
))
|
|
@@ -1186,7 +1192,7 @@ function printAttrs(path, options, print, { inline = false } = {}) {
|
|
|
1186
1192
|
allAttrs.push(
|
|
1187
1193
|
group([
|
|
1188
1194
|
indent(attrGroup),
|
|
1189
|
-
ifBreak(shouldPrintComma(options,
|
|
1195
|
+
ifBreak(shouldPrintComma(options, 8.0) ? "," : ""),
|
|
1190
1196
|
softline,
|
|
1191
1197
|
"]",
|
|
1192
1198
|
inline ? ifBreak(softline, " ") : "",
|
|
@@ -1658,11 +1664,7 @@ function printNode(path, options, print) {
|
|
|
1658
1664
|
join([",", line], path.map(print, "items")),
|
|
1659
1665
|
]),
|
|
1660
1666
|
node.name
|
|
1661
|
-
? [
|
|
1662
|
-
ifBreak(shouldPrintComma(options, "7.2") ? "," : ""),
|
|
1663
|
-
softline,
|
|
1664
|
-
"}",
|
|
1665
|
-
]
|
|
1667
|
+
? [ifBreak(shouldPrintComma(options, 7.2) ? "," : ""), softline, "}"]
|
|
1666
1668
|
: "",
|
|
1667
1669
|
]);
|
|
1668
1670
|
case "useitem":
|
|
@@ -2356,9 +2358,8 @@ function printNode(path, options, print) {
|
|
|
2356
2358
|
case "list":
|
|
2357
2359
|
case "array": {
|
|
2358
2360
|
const useShortForm =
|
|
2359
|
-
(node.kind === "array" &&
|
|
2360
|
-
(node.kind === "list" &&
|
|
2361
|
-
(node.shortForm || isMinVersion(options.phpVersion, "7.1")));
|
|
2361
|
+
(node.kind === "array" && options.phpVersion >= 5.4) ||
|
|
2362
|
+
(node.kind === "list" && (node.shortForm || options.phpVersion >= 7.1));
|
|
2362
2363
|
const open = useShortForm ? "[" : [node.kind, "("];
|
|
2363
2364
|
const close = useShortForm ? "]" : ")";
|
|
2364
2365
|
|
|
@@ -2408,7 +2409,7 @@ function printNode(path, options, print) {
|
|
|
2408
2409
|
indent([softline, printArrayItems(path, options, print)]),
|
|
2409
2410
|
needsForcedTrailingComma ? "," : "",
|
|
2410
2411
|
ifBreak(
|
|
2411
|
-
!needsForcedTrailingComma && shouldPrintComma(options,
|
|
2412
|
+
!needsForcedTrailingComma && shouldPrintComma(options, 5.0)
|
|
2412
2413
|
? [
|
|
2413
2414
|
lastElem && shouldPrintHardlineBeforeTrailingComma(lastElem)
|
|
2414
2415
|
? hardline
|
|
@@ -2675,7 +2676,7 @@ function printNode(path, options, print) {
|
|
|
2675
2676
|
if (parent.kind === "encapsedpart") {
|
|
2676
2677
|
const parentParent = path.grandparent;
|
|
2677
2678
|
let closingTagIndentation = 0;
|
|
2678
|
-
const flexible =
|
|
2679
|
+
const flexible = options.phpVersion >= 7.3;
|
|
2679
2680
|
let linebreak = literalline;
|
|
2680
2681
|
if (parentParent.type === "heredoc") {
|
|
2681
2682
|
linebreak = flexible ? hardline : literalline;
|
|
@@ -2744,7 +2745,7 @@ function printNode(path, options, print) {
|
|
|
2744
2745
|
case "string":
|
|
2745
2746
|
case "shell":
|
|
2746
2747
|
case "heredoc": {
|
|
2747
|
-
const flexible =
|
|
2748
|
+
const flexible = options.phpVersion >= 7.3;
|
|
2748
2749
|
const linebreak = flexible ? hardline : literalline;
|
|
2749
2750
|
return [
|
|
2750
2751
|
getEncapsedQuotes(node),
|
|
@@ -2769,7 +2770,7 @@ function printNode(path, options, print) {
|
|
|
2769
2770
|
case "magic":
|
|
2770
2771
|
return node.value;
|
|
2771
2772
|
case "nowdoc": {
|
|
2772
|
-
const flexible =
|
|
2773
|
+
const flexible = options.phpVersion >= 7.3;
|
|
2773
2774
|
const linebreak = flexible ? hardline : literalline;
|
|
2774
2775
|
return [
|
|
2775
2776
|
"<<<'",
|
package/src/util.mjs
CHANGED
|
@@ -709,10 +709,6 @@ function memoize(fn) {
|
|
|
709
709
|
};
|
|
710
710
|
}
|
|
711
711
|
|
|
712
|
-
function isMinVersion(actualVersion, requiredVersion) {
|
|
713
|
-
return parseFloat(actualVersion) >= parseFloat(requiredVersion);
|
|
714
|
-
}
|
|
715
|
-
|
|
716
712
|
export {
|
|
717
713
|
printNumber,
|
|
718
714
|
getPrecedence,
|
|
@@ -744,5 +740,4 @@ export {
|
|
|
744
740
|
normalizeMagicMethodName,
|
|
745
741
|
isSimpleCallArgument,
|
|
746
742
|
memoize,
|
|
747
|
-
isMinVersion,
|
|
748
743
|
};
|