diff --git a/composer.json b/composer.json
index d34abf3b..b18cd23f 100644
--- a/composer.json
+++ b/composer.json
@@ -16,6 +16,7 @@
}
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.1",
+ "psr/log": "^2.0 || ^3.0"
}
}
diff --git a/composer.lock b/composer.lock
index 7c17f09f..5d70e659 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,59 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "c633a27ea30371ec870c8065ca4ae4cd",
- "packages": [],
+ "content-hash": "9a62d2bdd387b7a6f599b27964325845",
+ "packages": [
+ {
+ "name": "psr/log",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.0"
+ },
+ "time": "2021-07-14T16:46:02+00:00"
+ }
+ ],
"packages-dev": [
{
"name": "amphp/amp",
@@ -680,16 +731,16 @@
},
{
"name": "netresearch/jsonmapper",
- "version": "v4.1.0",
+ "version": "v4.2.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
- "reference": "cfa81ea1d35294d64adb9c68aa4cb9e92400e53f"
+ "reference": "f60565f8c0566a31acf06884cdaa591867ecc956"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/cfa81ea1d35294d64adb9c68aa4cb9e92400e53f",
- "reference": "cfa81ea1d35294d64adb9c68aa4cb9e92400e53f",
+ "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956",
+ "reference": "f60565f8c0566a31acf06884cdaa591867ecc956",
"shasum": ""
},
"require": {
@@ -725,22 +776,22 @@
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
- "source": "https://github.com/cweiske/jsonmapper/tree/v4.1.0"
+ "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0"
},
- "time": "2022-12-08T20:46:14+00:00"
+ "time": "2023-04-09T17:37:40+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v4.15.4",
+ "version": "v4.15.5",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290"
+ "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
- "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e",
+ "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e",
"shasum": ""
},
"require": {
@@ -781,9 +832,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5"
},
- "time": "2023-03-05T19:49:14+00:00"
+ "time": "2023-05-19T20:20:00+00:00"
},
{
"name": "phan/phan",
@@ -1034,22 +1085,22 @@
},
{
"name": "phpstan/extension-installer",
- "version": "1.2.0",
+ "version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/extension-installer.git",
- "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40"
+ "reference": "f45734bfb9984c6c56c4486b71230355f066a58a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
- "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
+ "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a",
+ "reference": "f45734bfb9984c6c56c4486b71230355f066a58a",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0",
"php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.8.0"
+ "phpstan/phpstan": "^1.9.0"
},
"require-dev": {
"composer/composer": "^2.0",
@@ -1072,28 +1123,29 @@
"description": "Composer plugin for automatic installation of PHPStan extensions",
"support": {
"issues": "https://github.com/phpstan/extension-installer/issues",
- "source": "https://github.com/phpstan/extension-installer/tree/1.2.0"
+ "source": "https://github.com/phpstan/extension-installer/tree/1.3.1"
},
- "time": "2022-10-17T12:59:16+00:00"
+ "time": "2023-05-24T08:59:17+00:00"
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.16.1",
+ "version": "1.21.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "e27e92d939e2e3636f0a1f0afaba59692c0bf571"
+ "reference": "6df62b08faef4f899772bc7c3bbabb93d2b7a21c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/e27e92d939e2e3636f0a1f0afaba59692c0bf571",
- "reference": "e27e92d939e2e3636f0a1f0afaba59692c0bf571",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6df62b08faef4f899772bc7c3bbabb93d2b7a21c",
+ "reference": "6df62b08faef4f899772bc7c3bbabb93d2b7a21c",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
+ "nikic/php-parser": "^4.15",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
@@ -1117,22 +1169,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
- "source": "https://github.com/phpstan/phpdoc-parser/tree/1.16.1"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.21.0"
},
- "time": "2023-02-07T18:11:17+00:00"
+ "time": "2023-05-17T13:13:44+00:00"
},
{
"name": "phpstan/phpstan",
- "version": "1.10.8",
+ "version": "1.10.15",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "0166aef76e066f0dd2adc2799bdadfa1635711e9"
+ "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0166aef76e066f0dd2adc2799bdadfa1635711e9",
- "reference": "0166aef76e066f0dd2adc2799bdadfa1635711e9",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/762c4dac4da6f8756eebb80e528c3a47855da9bd",
+ "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd",
"shasum": ""
},
"require": {
@@ -1181,7 +1233,7 @@
"type": "tidelift"
}
],
- "time": "2023-03-24T10:28:16+00:00"
+ "time": "2023-05-09T15:28:01+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@@ -1284,56 +1336,6 @@
},
"time": "2021-11-05T16:47:00+00:00"
},
- {
- "name": "psr/log",
- "version": "3.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/log.git",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
- "shasum": ""
- },
- "require": {
- "php": ">=8.0.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Psr\\Log\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "https://www.php-fig.org/"
- }
- ],
- "description": "Common interface for logging libraries",
- "homepage": "https://github.com/php-fig/log",
- "keywords": [
- "log",
- "psr",
- "psr-3"
- ],
- "support": {
- "source": "https://github.com/php-fig/log/tree/3.0.0"
- },
- "time": "2021-07-14T16:46:02+00:00"
- },
{
"name": "sabre/event",
"version": "5.1.4",
@@ -1402,16 +1404,16 @@
},
{
"name": "sebastian/diff",
- "version": "5.0.1",
+ "version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "aae9a0a43bff37bd5d8d0311426c87bf36153f02"
+ "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/aae9a0a43bff37bd5d8d0311426c87bf36153f02",
- "reference": "aae9a0a43bff37bd5d8d0311426c87bf36153f02",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
+ "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
"shasum": ""
},
"require": {
@@ -1457,7 +1459,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"security": "https://github.com/sebastianbergmann/diff/security/policy",
- "source": "https://github.com/sebastianbergmann/diff/tree/5.0.1"
+ "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3"
},
"funding": [
{
@@ -1465,20 +1467,20 @@
"type": "github"
}
],
- "time": "2023-03-23T05:12:41+00:00"
+ "time": "2023-05-01T07:48:21+00:00"
},
{
"name": "spatie/array-to-xml",
- "version": "3.1.5",
+ "version": "3.1.6",
"source": {
"type": "git",
"url": "https://github.com/spatie/array-to-xml.git",
- "reference": "13f76acef5362d15c71ae1ac6350cc3df5e25e43"
+ "reference": "e210b98957987c755372465be105d32113f339a4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/13f76acef5362d15c71ae1ac6350cc3df5e25e43",
- "reference": "13f76acef5362d15c71ae1ac6350cc3df5e25e43",
+ "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/e210b98957987c755372465be105d32113f339a4",
+ "reference": "e210b98957987c755372465be105d32113f339a4",
"shasum": ""
},
"require": {
@@ -1516,7 +1518,7 @@
"xml"
],
"support": {
- "source": "https://github.com/spatie/array-to-xml/tree/3.1.5"
+ "source": "https://github.com/spatie/array-to-xml/tree/3.1.6"
},
"funding": [
{
@@ -1528,20 +1530,20 @@
"type": "github"
}
],
- "time": "2022-12-24T13:43:51+00:00"
+ "time": "2023-05-11T14:04:07+00:00"
},
{
"name": "symfony/console",
- "version": "v6.2.7",
+ "version": "v6.2.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "cbad09eb8925b6ad4fb721c7a179344dc4a19d45"
+ "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/cbad09eb8925b6ad4fb721c7a179344dc4a19d45",
- "reference": "cbad09eb8925b6ad4fb721c7a179344dc4a19d45",
+ "url": "https://api.github.com/repos/symfony/console/zipball/5aa03db8ef0a5457c316ec580e69562d97734c77",
+ "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77",
"shasum": ""
},
"require": {
@@ -1603,12 +1605,12 @@
"homepage": "https://symfony.com",
"keywords": [
"cli",
- "command line",
+ "command-line",
"console",
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v6.2.7"
+ "source": "https://github.com/symfony/console/tree/v6.2.11"
},
"funding": [
{
@@ -1624,7 +1626,7 @@
"type": "tidelift"
}
],
- "time": "2023-02-25T17:00:03+00:00"
+ "time": "2023-05-26T08:16:21+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -1695,16 +1697,16 @@
},
{
"name": "symfony/filesystem",
- "version": "v6.2.7",
+ "version": "v6.2.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "82b6c62b959f642d000456f08c6d219d749215b3"
+ "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/82b6c62b959f642d000456f08c6d219d749215b3",
- "reference": "82b6c62b959f642d000456f08c6d219d749215b3",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd588debf7d1bc16a2c84b4b3b71145d9946b894",
+ "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894",
"shasum": ""
},
"require": {
@@ -1738,7 +1740,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v6.2.7"
+ "source": "https://github.com/symfony/filesystem/tree/v6.2.10"
},
"funding": [
{
@@ -1754,7 +1756,7 @@
"type": "tidelift"
}
],
- "time": "2023-02-14T08:44:56+00:00"
+ "time": "2023-04-18T13:46:08+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -2256,16 +2258,16 @@
},
{
"name": "symfony/string",
- "version": "v6.2.7",
+ "version": "v6.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "67b8c1eec78296b85dc1c7d9743830160218993d"
+ "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/67b8c1eec78296b85dc1c7d9743830160218993d",
- "reference": "67b8c1eec78296b85dc1c7d9743830160218993d",
+ "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef",
+ "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef",
"shasum": ""
},
"require": {
@@ -2322,7 +2324,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.2.7"
+ "source": "https://github.com/symfony/string/tree/v6.2.8"
},
"funding": [
{
@@ -2338,7 +2340,7 @@
"type": "tidelift"
}
],
- "time": "2023-02-24T10:42:00+00:00"
+ "time": "2023-03-20T16:06:02+00:00"
},
{
"name": "tysonandre/var_representation_polyfill",
@@ -2404,16 +2406,16 @@
},
{
"name": "vimeo/psalm",
- "version": "5.8.0",
+ "version": "5.12.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
- "reference": "9cf4f60a333f779ad3bc704a555920e81d4fdcda"
+ "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vimeo/psalm/zipball/9cf4f60a333f779ad3bc704a555920e81d4fdcda",
- "reference": "9cf4f60a333f779ad3bc704a555920e81d4fdcda",
+ "url": "https://api.github.com/repos/vimeo/psalm/zipball/f90118cdeacd0088e7215e64c0c99ceca819e176",
+ "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176",
"shasum": ""
},
"require": {
@@ -2445,6 +2447,7 @@
"psalm/psalm": "self.version"
},
"require-dev": {
+ "amphp/phpunit-util": "^2.0",
"bamarni/composer-bin-plugin": "^1.4",
"brianium/paratest": "^6.9",
"ext-curl": "*",
@@ -2503,9 +2506,9 @@
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
- "source": "https://github.com/vimeo/psalm/tree/5.8.0"
+ "source": "https://github.com/vimeo/psalm/tree/5.12.0"
},
- "time": "2023-03-09T04:14:35+00:00"
+ "time": "2023-05-22T21:19:03+00:00"
},
{
"name": "webmozart/assert",
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 2fe33c4b..b453d2e1 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -706,17 +706,17 @@
},
{
"name": "netresearch/jsonmapper",
- "version": "v4.1.0",
- "version_normalized": "4.1.0.0",
+ "version": "v4.2.0",
+ "version_normalized": "4.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
- "reference": "cfa81ea1d35294d64adb9c68aa4cb9e92400e53f"
+ "reference": "f60565f8c0566a31acf06884cdaa591867ecc956"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/cfa81ea1d35294d64adb9c68aa4cb9e92400e53f",
- "reference": "cfa81ea1d35294d64adb9c68aa4cb9e92400e53f",
+ "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956",
+ "reference": "f60565f8c0566a31acf06884cdaa591867ecc956",
"shasum": ""
},
"require": {
@@ -730,7 +730,7 @@
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0",
"squizlabs/php_codesniffer": "~3.5"
},
- "time": "2022-12-08T20:46:14+00:00",
+ "time": "2023-04-09T17:37:40+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -754,23 +754,23 @@
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
- "source": "https://github.com/cweiske/jsonmapper/tree/v4.1.0"
+ "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0"
},
"install-path": "../netresearch/jsonmapper"
},
{
"name": "nikic/php-parser",
- "version": "v4.15.4",
- "version_normalized": "4.15.4.0",
+ "version": "v4.15.5",
+ "version_normalized": "4.15.5.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290"
+ "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
- "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e",
+ "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e",
"shasum": ""
},
"require": {
@@ -781,7 +781,7 @@
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
- "time": "2023-03-05T19:49:14+00:00",
+ "time": "2023-05-19T20:20:00+00:00",
"bin": [
"bin/php-parse"
],
@@ -813,7 +813,7 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5"
},
"install-path": "../nikic/php-parser"
},
@@ -1078,30 +1078,30 @@
},
{
"name": "phpstan/extension-installer",
- "version": "1.2.0",
- "version_normalized": "1.2.0.0",
+ "version": "1.3.1",
+ "version_normalized": "1.3.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/extension-installer.git",
- "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40"
+ "reference": "f45734bfb9984c6c56c4486b71230355f066a58a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
- "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
+ "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a",
+ "reference": "f45734bfb9984c6c56c4486b71230355f066a58a",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0",
"php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.8.0"
+ "phpstan/phpstan": "^1.9.0"
},
"require-dev": {
"composer/composer": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2.0",
"phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
},
- "time": "2022-10-17T12:59:16+00:00",
+ "time": "2023-05-24T08:59:17+00:00",
"type": "composer-plugin",
"extra": {
"class": "PHPStan\\ExtensionInstaller\\Plugin"
@@ -1119,29 +1119,30 @@
"description": "Composer plugin for automatic installation of PHPStan extensions",
"support": {
"issues": "https://github.com/phpstan/extension-installer/issues",
- "source": "https://github.com/phpstan/extension-installer/tree/1.2.0"
+ "source": "https://github.com/phpstan/extension-installer/tree/1.3.1"
},
"install-path": "../phpstan/extension-installer"
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.16.1",
- "version_normalized": "1.16.1.0",
+ "version": "1.21.0",
+ "version_normalized": "1.21.0.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "e27e92d939e2e3636f0a1f0afaba59692c0bf571"
+ "reference": "6df62b08faef4f899772bc7c3bbabb93d2b7a21c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/e27e92d939e2e3636f0a1f0afaba59692c0bf571",
- "reference": "e27e92d939e2e3636f0a1f0afaba59692c0bf571",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6df62b08faef4f899772bc7c3bbabb93d2b7a21c",
+ "reference": "6df62b08faef4f899772bc7c3bbabb93d2b7a21c",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
+ "nikic/php-parser": "^4.15",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
@@ -1150,7 +1151,7 @@
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
- "time": "2023-02-07T18:11:17+00:00",
+ "time": "2023-05-17T13:13:44+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -1167,23 +1168,23 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
- "source": "https://github.com/phpstan/phpdoc-parser/tree/1.16.1"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.21.0"
},
"install-path": "../phpstan/phpdoc-parser"
},
{
"name": "phpstan/phpstan",
- "version": "1.10.8",
- "version_normalized": "1.10.8.0",
+ "version": "1.10.15",
+ "version_normalized": "1.10.15.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "0166aef76e066f0dd2adc2799bdadfa1635711e9"
+ "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0166aef76e066f0dd2adc2799bdadfa1635711e9",
- "reference": "0166aef76e066f0dd2adc2799bdadfa1635711e9",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/762c4dac4da6f8756eebb80e528c3a47855da9bd",
+ "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd",
"shasum": ""
},
"require": {
@@ -1192,7 +1193,7 @@
"conflict": {
"phpstan/phpstan-shim": "*"
},
- "time": "2023-03-24T10:28:16+00:00",
+ "time": "2023-05-09T15:28:01+00:00",
"bin": [
"phpstan",
"phpstan.phar"
@@ -1467,17 +1468,17 @@
},
{
"name": "sebastian/diff",
- "version": "5.0.1",
- "version_normalized": "5.0.1.0",
+ "version": "5.0.3",
+ "version_normalized": "5.0.3.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "aae9a0a43bff37bd5d8d0311426c87bf36153f02"
+ "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/aae9a0a43bff37bd5d8d0311426c87bf36153f02",
- "reference": "aae9a0a43bff37bd5d8d0311426c87bf36153f02",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
+ "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
"shasum": ""
},
"require": {
@@ -1487,7 +1488,7 @@
"phpunit/phpunit": "^10.0",
"symfony/process": "^4.2 || ^5"
},
- "time": "2023-03-23T05:12:41+00:00",
+ "time": "2023-05-01T07:48:21+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -1525,7 +1526,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"security": "https://github.com/sebastianbergmann/diff/security/policy",
- "source": "https://github.com/sebastianbergmann/diff/tree/5.0.1"
+ "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3"
},
"funding": [
{
@@ -1537,17 +1538,17 @@
},
{
"name": "spatie/array-to-xml",
- "version": "3.1.5",
- "version_normalized": "3.1.5.0",
+ "version": "3.1.6",
+ "version_normalized": "3.1.6.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/array-to-xml.git",
- "reference": "13f76acef5362d15c71ae1ac6350cc3df5e25e43"
+ "reference": "e210b98957987c755372465be105d32113f339a4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/13f76acef5362d15c71ae1ac6350cc3df5e25e43",
- "reference": "13f76acef5362d15c71ae1ac6350cc3df5e25e43",
+ "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/e210b98957987c755372465be105d32113f339a4",
+ "reference": "e210b98957987c755372465be105d32113f339a4",
"shasum": ""
},
"require": {
@@ -1559,7 +1560,7 @@
"pestphp/pest": "^1.21",
"spatie/pest-plugin-snapshots": "^1.1"
},
- "time": "2022-12-24T13:43:51+00:00",
+ "time": "2023-05-11T14:04:07+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -1587,7 +1588,7 @@
"xml"
],
"support": {
- "source": "https://github.com/spatie/array-to-xml/tree/3.1.5"
+ "source": "https://github.com/spatie/array-to-xml/tree/3.1.6"
},
"funding": [
{
@@ -1603,17 +1604,17 @@
},
{
"name": "symfony/console",
- "version": "v6.2.7",
- "version_normalized": "6.2.7.0",
+ "version": "v6.2.11",
+ "version_normalized": "6.2.11.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "cbad09eb8925b6ad4fb721c7a179344dc4a19d45"
+ "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/cbad09eb8925b6ad4fb721c7a179344dc4a19d45",
- "reference": "cbad09eb8925b6ad4fb721c7a179344dc4a19d45",
+ "url": "https://api.github.com/repos/symfony/console/zipball/5aa03db8ef0a5457c316ec580e69562d97734c77",
+ "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77",
"shasum": ""
},
"require": {
@@ -1648,7 +1649,7 @@
"symfony/lock": "",
"symfony/process": ""
},
- "time": "2023-02-25T17:00:03+00:00",
+ "time": "2023-05-26T08:16:21+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -1677,12 +1678,12 @@
"homepage": "https://symfony.com",
"keywords": [
"cli",
- "command line",
+ "command-line",
"console",
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v6.2.7"
+ "source": "https://github.com/symfony/console/tree/v6.2.11"
},
"funding": [
{
@@ -1772,17 +1773,17 @@
},
{
"name": "symfony/filesystem",
- "version": "v6.2.7",
- "version_normalized": "6.2.7.0",
+ "version": "v6.2.10",
+ "version_normalized": "6.2.10.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "82b6c62b959f642d000456f08c6d219d749215b3"
+ "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/82b6c62b959f642d000456f08c6d219d749215b3",
- "reference": "82b6c62b959f642d000456f08c6d219d749215b3",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd588debf7d1bc16a2c84b4b3b71145d9946b894",
+ "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894",
"shasum": ""
},
"require": {
@@ -1790,7 +1791,7 @@
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
- "time": "2023-02-14T08:44:56+00:00",
+ "time": "2023-04-18T13:46:08+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -1818,7 +1819,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v6.2.7"
+ "source": "https://github.com/symfony/filesystem/tree/v6.2.10"
},
"funding": [
{
@@ -2354,17 +2355,17 @@
},
{
"name": "symfony/string",
- "version": "v6.2.7",
- "version_normalized": "6.2.7.0",
+ "version": "v6.2.8",
+ "version_normalized": "6.2.8.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "67b8c1eec78296b85dc1c7d9743830160218993d"
+ "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/67b8c1eec78296b85dc1c7d9743830160218993d",
- "reference": "67b8c1eec78296b85dc1c7d9743830160218993d",
+ "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef",
+ "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef",
"shasum": ""
},
"require": {
@@ -2384,7 +2385,7 @@
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
- "time": "2023-02-24T10:42:00+00:00",
+ "time": "2023-03-20T16:06:02+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -2423,7 +2424,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.2.7"
+ "source": "https://github.com/symfony/string/tree/v6.2.8"
},
"funding": [
{
@@ -2508,17 +2509,17 @@
},
{
"name": "vimeo/psalm",
- "version": "5.8.0",
- "version_normalized": "5.8.0.0",
+ "version": "5.12.0",
+ "version_normalized": "5.12.0.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
- "reference": "9cf4f60a333f779ad3bc704a555920e81d4fdcda"
+ "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vimeo/psalm/zipball/9cf4f60a333f779ad3bc704a555920e81d4fdcda",
- "reference": "9cf4f60a333f779ad3bc704a555920e81d4fdcda",
+ "url": "https://api.github.com/repos/vimeo/psalm/zipball/f90118cdeacd0088e7215e64c0c99ceca819e176",
+ "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176",
"shasum": ""
},
"require": {
@@ -2550,6 +2551,7 @@
"psalm/psalm": "self.version"
},
"require-dev": {
+ "amphp/phpunit-util": "^2.0",
"bamarni/composer-bin-plugin": "^1.4",
"brianium/paratest": "^6.9",
"ext-curl": "*",
@@ -2568,7 +2570,7 @@
"ext-curl": "In order to send data to shepherd",
"ext-igbinary": "^2.0.5 is required, used to serialize caching data"
},
- "time": "2023-03-09T04:14:35+00:00",
+ "time": "2023-05-22T21:19:03+00:00",
"bin": [
"psalm",
"psalm-language-server",
@@ -2610,7 +2612,7 @@
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
- "source": "https://github.com/vimeo/psalm/tree/5.8.0"
+ "source": "https://github.com/vimeo/psalm/tree/5.12.0"
},
"install-path": "../vimeo/psalm"
},
@@ -2700,7 +2702,6 @@
"phpstan/phpstan",
"phpstan/phpstan-deprecation-rules",
"psr/container",
- "psr/log",
"sabre/event",
"sebastian/diff",
"spatie/array-to-xml",
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 9f147870..2059fa41 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -119,18 +119,18 @@
'dev_requirement' => true,
),
'netresearch/jsonmapper' => array(
- 'pretty_version' => 'v4.1.0',
- 'version' => '4.1.0.0',
- 'reference' => 'cfa81ea1d35294d64adb9c68aa4cb9e92400e53f',
+ 'pretty_version' => 'v4.2.0',
+ 'version' => '4.2.0.0',
+ 'reference' => 'f60565f8c0566a31acf06884cdaa591867ecc956',
'type' => 'library',
'install_path' => __DIR__ . '/../netresearch/jsonmapper',
'aliases' => array(),
'dev_requirement' => true,
),
'nikic/php-parser' => array(
- 'pretty_version' => 'v4.15.4',
- 'version' => '4.15.4.0',
- 'reference' => '6bb5176bc4af8bcb7d926f88718db9b96a2d4290',
+ 'pretty_version' => 'v4.15.5',
+ 'version' => '4.15.5.0',
+ 'reference' => '11e2663a5bc9db5d714eedb4277ee300403b4a9e',
'type' => 'library',
'install_path' => __DIR__ . '/../nikic/php-parser',
'aliases' => array(),
@@ -173,27 +173,27 @@
'dev_requirement' => true,
),
'phpstan/extension-installer' => array(
- 'pretty_version' => '1.2.0',
- 'version' => '1.2.0.0',
- 'reference' => 'f06dbb052ddc394e7896fcd1cfcd533f9f6ace40',
+ 'pretty_version' => '1.3.1',
+ 'version' => '1.3.1.0',
+ 'reference' => 'f45734bfb9984c6c56c4486b71230355f066a58a',
'type' => 'composer-plugin',
'install_path' => __DIR__ . '/../phpstan/extension-installer',
'aliases' => array(),
'dev_requirement' => true,
),
'phpstan/phpdoc-parser' => array(
- 'pretty_version' => '1.16.1',
- 'version' => '1.16.1.0',
- 'reference' => 'e27e92d939e2e3636f0a1f0afaba59692c0bf571',
+ 'pretty_version' => '1.21.0',
+ 'version' => '1.21.0.0',
+ 'reference' => '6df62b08faef4f899772bc7c3bbabb93d2b7a21c',
'type' => 'library',
'install_path' => __DIR__ . '/../phpstan/phpdoc-parser',
'aliases' => array(),
'dev_requirement' => true,
),
'phpstan/phpstan' => array(
- 'pretty_version' => '1.10.8',
- 'version' => '1.10.8.0',
- 'reference' => '0166aef76e066f0dd2adc2799bdadfa1635711e9',
+ 'pretty_version' => '1.10.15',
+ 'version' => '1.10.15.0',
+ 'reference' => '762c4dac4da6f8756eebb80e528c3a47855da9bd',
'type' => 'library',
'install_path' => __DIR__ . '/../phpstan/phpstan',
'aliases' => array(),
@@ -211,7 +211,7 @@
'psalm/psalm' => array(
'dev_requirement' => true,
'provided' => array(
- 0 => '5.8.0',
+ 0 => '5.12.0',
),
),
'psr/container' => array(
@@ -230,7 +230,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../psr/log',
'aliases' => array(),
- 'dev_requirement' => true,
+ 'dev_requirement' => false,
),
'psr/log-implementation' => array(
'dev_requirement' => true,
@@ -248,27 +248,27 @@
'dev_requirement' => true,
),
'sebastian/diff' => array(
- 'pretty_version' => '5.0.1',
- 'version' => '5.0.1.0',
- 'reference' => 'aae9a0a43bff37bd5d8d0311426c87bf36153f02',
+ 'pretty_version' => '5.0.3',
+ 'version' => '5.0.3.0',
+ 'reference' => '912dc2fbe3e3c1e7873313cc801b100b6c68c87b',
'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/diff',
'aliases' => array(),
'dev_requirement' => true,
),
'spatie/array-to-xml' => array(
- 'pretty_version' => '3.1.5',
- 'version' => '3.1.5.0',
- 'reference' => '13f76acef5362d15c71ae1ac6350cc3df5e25e43',
+ 'pretty_version' => '3.1.6',
+ 'version' => '3.1.6.0',
+ 'reference' => 'e210b98957987c755372465be105d32113f339a4',
'type' => 'library',
'install_path' => __DIR__ . '/../spatie/array-to-xml',
'aliases' => array(),
'dev_requirement' => true,
),
'symfony/console' => array(
- 'pretty_version' => 'v6.2.7',
- 'version' => '6.2.7.0',
- 'reference' => 'cbad09eb8925b6ad4fb721c7a179344dc4a19d45',
+ 'pretty_version' => 'v6.2.11',
+ 'version' => '6.2.11.0',
+ 'reference' => '5aa03db8ef0a5457c316ec580e69562d97734c77',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/console',
'aliases' => array(),
@@ -284,9 +284,9 @@
'dev_requirement' => true,
),
'symfony/filesystem' => array(
- 'pretty_version' => 'v6.2.7',
- 'version' => '6.2.7.0',
- 'reference' => '82b6c62b959f642d000456f08c6d219d749215b3',
+ 'pretty_version' => 'v6.2.10',
+ 'version' => '6.2.10.0',
+ 'reference' => 'fd588debf7d1bc16a2c84b4b3b71145d9946b894',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/filesystem',
'aliases' => array(),
@@ -347,9 +347,9 @@
'dev_requirement' => true,
),
'symfony/string' => array(
- 'pretty_version' => 'v6.2.7',
- 'version' => '6.2.7.0',
- 'reference' => '67b8c1eec78296b85dc1c7d9743830160218993d',
+ 'pretty_version' => 'v6.2.8',
+ 'version' => '6.2.8.0',
+ 'reference' => '193e83bbd6617d6b2151c37fff10fa7168ebddef',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/string',
'aliases' => array(),
@@ -365,9 +365,9 @@
'dev_requirement' => true,
),
'vimeo/psalm' => array(
- 'pretty_version' => '5.8.0',
- 'version' => '5.8.0.0',
- 'reference' => '9cf4f60a333f779ad3bc704a555920e81d4fdcda',
+ 'pretty_version' => '5.12.0',
+ 'version' => '5.12.0.0',
+ 'reference' => 'f90118cdeacd0088e7215e64c0c99ceca819e176',
'type' => 'library',
'install_path' => __DIR__ . '/../vimeo/psalm',
'aliases' => array(),
diff --git a/vendor/netresearch/jsonmapper/.github/workflows/test.yml b/vendor/netresearch/jsonmapper/.github/workflows/test.yml
new file mode 100644
index 00000000..76a8d654
--- /dev/null
+++ b/vendor/netresearch/jsonmapper/.github/workflows/test.yml
@@ -0,0 +1,46 @@
+name: JsonMapper tests
+on: [push, workflow_dispatch]
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ php-versions:
+ - '7.1'
+ - '7.2'
+ - '7.3'
+ - '7.4'
+ - '8.0'
+ - '8.1'
+ - '8.2'
+ name: PHP ${{ matrix.php-versions }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-versions }}
+ tools: composer
+ coverage: xdebug
+
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache dependencies
+ uses: actions/cache@v3
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ matrix.php-versions }}-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-${{ matrix.php-versions }}-
+
+ - name: Install dependencies
+ run: composer install --no-interaction --prefer-dist
+
+ - name: Run unit tests
+ run: XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-text
+
+ - name: Check codestyle
+ run: ./vendor/bin/phpcs --standard=PEAR src/
diff --git a/vendor/netresearch/jsonmapper/src/JsonMapper.php b/vendor/netresearch/jsonmapper/src/JsonMapper.php
index fdb984f0..5ae3895b 100644
--- a/vendor/netresearch/jsonmapper/src/JsonMapper.php
+++ b/vendor/netresearch/jsonmapper/src/JsonMapper.php
@@ -75,7 +75,7 @@ class JsonMapper
public $bStrictNullTypes = true;
/**
- * Allow mapping of private and proteted properties.
+ * Allow mapping of private and protected properties.
*
* @var boolean
*/
@@ -131,8 +131,8 @@ class JsonMapper
/**
* Map data all data in $json into the given $object instance.
*
- * @param object|array $json JSON object structure from json_decode()
- * @param object $object Object to map $json data into
+ * @param object|array $json JSON object structure from json_decode()
+ * @param object|class-string $object Object to map $json data into
*
* @return mixed Mapped object is returned.
* @see mapArray()
@@ -145,13 +145,18 @@ class JsonMapper
. ', ' . gettype($json) . ' given.'
);
}
- if (!is_object($object)) {
+ if (!is_object($object) && (!is_string($object) || !class_exists($object))) {
throw new InvalidArgumentException(
- 'JsonMapper::map() requires second argument to be an object'
+ 'JsonMapper::map() requires second argument to '
+ . 'be an object or existing class name'
. ', ' . gettype($object) . ' given.'
);
}
+ if (is_string($object)) {
+ $object = $this->createInstance($object);
+ }
+
$strClassName = get_class($object);
$rc = new ReflectionClass($object);
$strNs = $rc->getNamespaceName();
@@ -177,10 +182,15 @@ class JsonMapper
. ' in object of type ' . $strClassName
);
} else if ($this->undefinedPropertyHandler !== null) {
- call_user_func(
+ $undefinedPropertyKey = call_user_func(
$this->undefinedPropertyHandler,
$object, $key, $jvalue
);
+
+ if (is_string($undefinedPropertyKey)) {
+ list($hasProperty, $accessor, $type, $isNullable)
+ = $this->inspectProperty($rc, $undefinedPropertyKey);
+ }
} else {
$this->log(
'info',
@@ -188,7 +198,10 @@ class JsonMapper
array('property' => $key, 'class' => $strClassName)
);
}
- continue;
+
+ if (!$hasProperty) {
+ continue;
+ }
}
if ($accessor === null) {
@@ -229,7 +242,9 @@ class JsonMapper
} else if ($this->isObjectOfSameType($type, $jvalue)) {
$this->setProperty($object, $accessor, $jvalue);
continue;
- } else if ($this->isSimpleType($type)) {
+ } else if ($this->isSimpleType($type)
+ && !(is_array($jvalue) && $this->hasVariadicArrayType($accessor))
+ ) {
if ($type === 'string' && is_object($jvalue)) {
throw new JsonMapper_Exception(
'JSON property "' . $key . '" in class "'
@@ -268,8 +283,11 @@ class JsonMapper
} else {
$array = $this->createInstance($proptype, false, $jvalue);
}
+ } else if (is_array($jvalue) && $this->hasVariadicArrayType($accessor)) {
+ $array = array();
+ $subtype = $type;
} else {
- if (is_a($type, 'ArrayObject', true)) {
+ if (is_a($type, 'ArrayAccess', true)) {
$array = $this->createInstance($type, false, $jvalue);
}
}
@@ -625,6 +643,8 @@ class JsonMapper
}
if ($accessor instanceof ReflectionProperty) {
$accessor->setValue($object, $value);
+ } else if (is_array($value) && $this->hasVariadicArrayType($accessor)) {
+ $accessor->invoke($object, ...$value);
} else {
//setter method
$accessor->invoke($object, $value);
@@ -647,6 +667,12 @@ class JsonMapper
$class, $useParameter = false, $jvalue = null
) {
if ($useParameter) {
+ if (PHP_VERSION_ID >= 80100
+ && is_subclass_of($class, \BackedEnum::class)
+ ) {
+ return $class::from($jvalue);
+ }
+
return new $class($jvalue);
} else {
$reflectClass = new ReflectionClass($class);
@@ -758,6 +784,32 @@ class JsonMapper
return substr($strType, -2) === '[]';
}
+ /**
+ * Returns true if accessor is a method and has only one parameter
+ * which is variadic.
+ *
+ * @param ReflectionMethod|ReflectionProperty|null $accessor accessor
+ * to set value
+ *
+ * @return bool
+ */
+ protected function hasVariadicArrayType($accessor)
+ {
+ if (!$accessor instanceof ReflectionMethod) {
+ return false;
+ }
+
+ $parameters = $accessor->getParameters();
+
+ if (count($parameters) !== 1) {
+ return false;
+ }
+
+ $parameter = $parameters[0];
+
+ return $parameter->isVariadic();
+ }
+
/**
* Checks if the given type is nullable
*
diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php
index de9aae7e..69f35332 100644
--- a/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php
+++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php
@@ -19,6 +19,8 @@ class Param implements PhpParser\Builder
protected $variadic = false;
+ protected $flags = 0;
+
/** @var Node\AttributeGroup[] */
protected $attributeGroups = [];
@@ -95,6 +97,50 @@ class Param implements PhpParser\Builder
return $this;
}
+ /**
+ * Makes the (promoted) parameter public.
+ *
+ * @return $this The builder instance (for fluid interface)
+ */
+ public function makePublic() {
+ $this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PUBLIC);
+
+ return $this;
+ }
+
+ /**
+ * Makes the (promoted) parameter protected.
+ *
+ * @return $this The builder instance (for fluid interface)
+ */
+ public function makeProtected() {
+ $this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PROTECTED);
+
+ return $this;
+ }
+
+ /**
+ * Makes the (promoted) parameter private.
+ *
+ * @return $this The builder instance (for fluid interface)
+ */
+ public function makePrivate() {
+ $this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PRIVATE);
+
+ return $this;
+ }
+
+ /**
+ * Makes the (promoted) parameter readonly.
+ *
+ * @return $this The builder instance (for fluid interface)
+ */
+ public function makeReadonly() {
+ $this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_READONLY);
+
+ return $this;
+ }
+
/**
* Adds an attribute group.
*
@@ -116,7 +162,7 @@ class Param implements PhpParser\Builder
public function getNode() : Node {
return new Node\Param(
new Node\Expr\Variable($this->name),
- $this->default, $this->type, $this->byRef, $this->variadic, [], 0, $this->attributeGroups
+ $this->default, $this->type, $this->byRef, $this->variadic, [], $this->flags, $this->attributeGroups
);
}
}
diff --git a/vendor/phpstan/extension-installer/README.md b/vendor/phpstan/extension-installer/README.md
index 70afa415..0616f999 100644
--- a/vendor/phpstan/extension-installer/README.md
+++ b/vendor/phpstan/extension-installer/README.md
@@ -72,6 +72,22 @@ Add `phpstan` key in the extension `composer.json`'s `extra` section:
}
```
+## Ignoring a particular extension
+
+You may want to disable auto-installation of a particular extension to handle installation manually. Ignore an extension by adding an `extra.phpstan/extension-installer.ignore` array in `composer.json` that specifies a list of packages to ignore:
+
+```json
+{
+ "extra": {
+ "phpstan/extension-installer": {
+ "ignore": [
+ "phpstan/phpstan-phpunit"
+ ]
+ }
+ }
+}
+```
+
## Limitations
The extension installer depends on Composer script events, therefore you cannot use `--no-scripts` flag.
diff --git a/vendor/phpstan/extension-installer/build-cs/composer.json b/vendor/phpstan/extension-installer/build-cs/composer.json
index e3079710..16a240bc 100644
--- a/vendor/phpstan/extension-installer/build-cs/composer.json
+++ b/vendor/phpstan/extension-installer/build-cs/composer.json
@@ -1,8 +1,9 @@
{
"require-dev": {
- "consistence-community/coding-standard": "^3.10",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "slevomat/coding-standard": "^7.0"
+ "consistence-community/coding-standard": "^3.11.0",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0.0",
+ "slevomat/coding-standard": "^8.8.0",
+ "squizlabs/php_codesniffer": "^3.5.3"
},
"config": {
"allow-plugins": {
diff --git a/vendor/phpstan/extension-installer/build-cs/composer.lock b/vendor/phpstan/extension-installer/build-cs/composer.lock
index 4bcc8de4..db122416 100644
--- a/vendor/phpstan/extension-installer/build-cs/composer.lock
+++ b/vendor/phpstan/extension-installer/build-cs/composer.lock
@@ -4,35 +4,35 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "4485bbedba7bcc71ace5f69dbb9b6c47",
+ "content-hash": "e69c1916405a7e3c8001c1b609a0ee61",
"packages": [],
"packages-dev": [
{
"name": "consistence-community/coding-standard",
- "version": "3.11.1",
+ "version": "3.11.3",
"source": {
"type": "git",
"url": "https://github.com/consistence-community/coding-standard.git",
- "reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df"
+ "reference": "f38e06327d5bf80ff5ff523a2c05e623b5e8d8b1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/consistence-community/coding-standard/zipball/4632fead8c9ee8f50044fcbce9f66c797b34c0df",
- "reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df",
+ "url": "https://api.github.com/repos/consistence-community/coding-standard/zipball/f38e06327d5bf80ff5ff523a2c05e623b5e8d8b1",
+ "reference": "f38e06327d5bf80ff5ff523a2c05e623b5e8d8b1",
"shasum": ""
},
"require": {
- "php": ">=7.4",
- "slevomat/coding-standard": "~7.0",
- "squizlabs/php_codesniffer": "~3.6.0"
+ "php": "~8.0",
+ "slevomat/coding-standard": "~8.0",
+ "squizlabs/php_codesniffer": "~3.7.0"
},
"replace": {
"consistence/coding-standard": "3.10.*"
},
"require-dev": {
- "phing/phing": "2.16.4",
- "php-parallel-lint/php-parallel-lint": "1.3.0",
- "phpunit/phpunit": "9.5.4"
+ "phing/phing": "2.17.0",
+ "php-parallel-lint/php-parallel-lint": "1.3.1",
+ "phpunit/phpunit": "9.5.10"
},
"type": "library",
"autoload": {
@@ -70,41 +70,44 @@
],
"support": {
"issues": "https://github.com/consistence-community/coding-standard/issues",
- "source": "https://github.com/consistence-community/coding-standard/tree/3.11.1"
+ "source": "https://github.com/consistence-community/coding-standard/tree/3.11.3"
},
- "time": "2021-05-03T18:13:22+00:00"
+ "time": "2023-03-27T14:55:41+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
- "version": "v0.7.2",
+ "version": "v1.0.0",
"source": {
"type": "git",
- "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
- "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
+ "url": "https://github.com/PHPCSStandards/composer-installer.git",
+ "reference": "4be43904336affa5c2f70744a348312336afd0da"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
- "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
+ "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da",
+ "reference": "4be43904336affa5c2f70744a348312336afd0da",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
- "php": ">=5.3",
+ "php": ">=5.4",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
+ "ext-json": "*",
+ "ext-zip": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
- "phpcompatibility/php-compatibility": "^9.0"
+ "phpcompatibility/php-compatibility": "^9.0",
+ "yoast/phpunit-polyfills": "^1.0"
},
"type": "composer-plugin",
"extra": {
- "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
+ "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
- "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
+ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -120,7 +123,7 @@
},
{
"name": "Contributors",
- "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
+ "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
@@ -144,23 +147,23 @@
"tests"
],
"support": {
- "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
- "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
+ "issues": "https://github.com/PHPCSStandards/composer-installer/issues",
+ "source": "https://github.com/PHPCSStandards/composer-installer"
},
- "time": "2022-02-04T12:51:07+00:00"
+ "time": "2023-01-05T11:28:13+00:00"
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.5.1",
+ "version": "1.20.4",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "981cc368a216c988e862a75e526b6076987d1b50"
+ "reference": "7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
- "reference": "981cc368a216c988e862a75e526b6076987d1b50",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd",
+ "reference": "7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd",
"shasum": ""
},
"require": {
@@ -170,6 +173,7 @@
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
+ "phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
@@ -189,48 +193,48 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
- "source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.20.4"
},
- "time": "2022-05-05T11:32:40+00:00"
+ "time": "2023-05-02T09:19:37+00:00"
},
{
"name": "slevomat/coding-standard",
- "version": "7.2.1",
+ "version": "8.12.0",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
- "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
+ "reference": "cc04334ed0ce5a251389112fbd2dbe1dbc931ae8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
- "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/cc04334ed0ce5a251389112fbd2dbe1dbc931ae8",
+ "reference": "cc04334ed0ce5a251389112fbd2dbe1dbc931ae8",
"shasum": ""
},
"require": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0",
"php": "^7.2 || ^8.0",
- "phpstan/phpdoc-parser": "^1.5.1",
- "squizlabs/php_codesniffer": "^3.6.2"
+ "phpstan/phpdoc-parser": ">=1.20.0 <1.21.0",
+ "squizlabs/php_codesniffer": "^3.7.1"
},
"require-dev": {
- "phing/phing": "2.17.3",
+ "phing/phing": "2.17.4",
"php-parallel-lint/php-parallel-lint": "1.3.2",
- "phpstan/phpstan": "1.4.10|1.7.1",
- "phpstan/phpstan-deprecation-rules": "1.0.0",
- "phpstan/phpstan-phpunit": "1.0.0|1.1.1",
- "phpstan/phpstan-strict-rules": "1.2.3",
- "phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
+ "phpstan/phpstan": "1.10.15",
+ "phpstan/phpstan-deprecation-rules": "1.1.3",
+ "phpstan/phpstan-phpunit": "1.3.11",
+ "phpstan/phpstan-strict-rules": "1.5.1",
+ "phpunit/phpunit": "7.5.20|8.5.21|9.6.8|10.1.3"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
- "dev-master": "7.x-dev"
+ "dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
- "SlevomatCodingStandard\\": "SlevomatCodingStandard"
+ "SlevomatCodingStandard\\": "SlevomatCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -238,9 +242,13 @@
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
+ "keywords": [
+ "dev",
+ "phpcs"
+ ],
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
- "source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
+ "source": "https://github.com/slevomat/coding-standard/tree/8.12.0"
},
"funding": [
{
@@ -252,20 +260,20 @@
"type": "tidelift"
}
],
- "time": "2022-05-25T10:58:12+00:00"
+ "time": "2023-05-14T20:06:01+00:00"
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.6.2",
+ "version": "3.7.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
+ "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
- "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879",
+ "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879",
"shasum": ""
},
"require": {
@@ -301,14 +309,15 @@
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
- "standards"
+ "standards",
+ "static analysis"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
- "time": "2021-12-12T21:44:58+00:00"
+ "time": "2023-02-22T23:07:41+00:00"
}
],
"aliases": [],
diff --git a/vendor/phpstan/extension-installer/composer.json b/vendor/phpstan/extension-installer/composer.json
index c57fcfe5..f2865a39 100644
--- a/vendor/phpstan/extension-installer/composer.json
+++ b/vendor/phpstan/extension-installer/composer.json
@@ -8,7 +8,7 @@
"require": {
"php": "^7.2 || ^8.0",
"composer-plugin-api": "^2.0",
- "phpstan/phpstan": "^1.8.0"
+ "phpstan/phpstan": "^1.9.0"
},
"require-dev": {
"composer/composer": "^2.0",
diff --git a/vendor/phpstan/extension-installer/src/GeneratedConfig.php b/vendor/phpstan/extension-installer/src/GeneratedConfig.php
index 3c9004ac..a5a02fad 100644
--- a/vendor/phpstan/extension-installer/src/GeneratedConfig.php
+++ b/vendor/phpstan/extension-installer/src/GeneratedConfig.php
@@ -3,21 +3,30 @@
namespace PHPStan\ExtensionInstaller;
/**
- * This is a stub class: it is in place only for scenarios where Composer
- * is run with a `--no-scripts` flag, in which scenarios this stub class
- * is not being replaced.
- *
- * If you are reading this docBlock inside your `vendor/` dir, then this means
- * that phpstan/extension-installer didn't correctly install.
- *
+ * This class is generated by phpstan/extension-installer.
* @internal
*/
final class GeneratedConfig
{
- public const EXTENSIONS = [];
+ public const EXTENSIONS = array (
+ 'phpstan/phpstan-deprecation-rules' =>
+ array (
+ 'install_path' => '/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/vendor/phpstan/phpstan-deprecation-rules',
+ 'relative_install_path' => '../../phpstan-deprecation-rules',
+ 'extra' =>
+ array (
+ 'includes' =>
+ array (
+ 0 => 'rules.neon',
+ ),
+ ),
+ 'version' => '1.1.3',
+ ),
+);
- public const NOT_INSTALLED = [];
+ public const NOT_INSTALLED = array (
+);
private function __construct()
{
diff --git a/vendor/phpstan/extension-installer/src/Plugin.php b/vendor/phpstan/extension-installer/src/Plugin.php
index 4ff82e4b..b8e605bd 100644
--- a/vendor/phpstan/extension-installer/src/Plugin.php
+++ b/vendor/phpstan/extension-installer/src/Plugin.php
@@ -19,6 +19,7 @@ use function is_file;
use function ksort;
use function md5;
use function md5_file;
+use function sort;
use function sprintf;
use function strpos;
use function var_export;
@@ -97,9 +98,18 @@ PHP;
}
$notInstalledPackages = [];
$installedPackages = [];
+ $ignoredPackages = [];
$data = [];
$fs = new Filesystem();
+ $ignore = [];
+
+ $packageExtra = $composer->getPackage()->getExtra();
+
+ if (isset($packageExtra['phpstan/extension-installer']['ignore'])) {
+ $ignore = $packageExtra['phpstan/extension-installer']['ignore'];
+ }
+
foreach ($composer->getRepositoryManager()->getLocalRepository()->getPackages() as $package) {
if (
$package->getType() !== 'phpstan-extension'
@@ -119,7 +129,15 @@ PHP;
continue;
}
+ if (in_array($package->getName(), $ignore, true)) {
+ $ignoredPackages[] = $package->getName();
+ continue;
+ }
+
$installPath = $installationManager->getInstallPath($package);
+ if ($installPath === null) {
+ continue;
+ }
$absoluteInstallPath = $fs->isAbsolutePath($installPath)
? $installPath
@@ -138,6 +156,7 @@ PHP;
ksort($data);
ksort($installedPackages);
ksort($notInstalledPackages);
+ sort($ignoredPackages);
$generatedConfigFileContents = sprintf(self::$generatedFileTemplate, var_export($data, true), var_export($notInstalledPackages, true));
file_put_contents($generatedConfigFilePath, $generatedConfigFileContents);
@@ -154,6 +173,10 @@ PHP;
foreach (array_keys($notInstalledPackages) as $name) {
$io->write(sprintf('> %s: not supported', $name));
}
+
+ foreach ($ignoredPackages as $name) {
+ $io->write(sprintf('> %s: ignored', $name));
+ }
}
}
diff --git a/vendor/phpstan/phpdoc-parser/README.md b/vendor/phpstan/phpdoc-parser/README.md
index 080e25ee..2d2f6c82 100644
--- a/vendor/phpstan/phpdoc-parser/README.md
+++ b/vendor/phpstan/phpdoc-parser/README.md
@@ -1,4 +1,4 @@
-
PHPDoc-Parser for PHPStan
+PHPDoc Parser for PHPStan
@@ -7,11 +7,99 @@
-* [PHPStan](https://phpstan.org)
+This library `phpstan/phpdoc-parser` represents PHPDocs with an AST (Abstract Syntax Tree). It supports parsing and modifying PHPDocs.
-------
+For the complete list of supported PHPDoc features check out PHPStan documentation. PHPStan is the main (but not the only) user of this library.
-Next generation phpDoc parser with support for intersection types and generics.
+* [PHPDoc Basics](https://phpstan.org/writing-php-code/phpdocs-basics) (list of PHPDoc tags)
+* [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) (list of PHPDoc types)
+* [phpdoc-parser API Reference](https://phpstan.github.io/phpdoc-parser/namespace-PHPStan.PhpDocParser.html) with all the AST node types etc.
+
+## Installation
+
+```
+composer require phpstan/phpdoc-parser
+```
+
+## Basic usage
+
+```php
+tokenize('/** @param Lorem $a */'));
+$phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode
+$paramTags = $phpDocNode->getParamTagValues(); // ParamTagValueNode[]
+echo $paramTags[0]->parameterName; // '$a'
+echo $paramTags[0]->type; // IdentifierTypeNode - 'Lorem'
+```
+
+### Format-preserving printer
+
+This component can be used to modify the AST
+and print it again as close as possible to the original.
+
+It's heavily inspired by format-preserving printer component in [nikic/PHP-Parser](https://github.com/nikic/PHP-Parser).
+
+```php
+ true, 'indexes' => true];
+
+$lexer = new Lexer();
+$constExprParser = new ConstExprParser(true, true, $usedAttributes);
+$typeParser = new TypeParser($constExprParser, true, $usedAttributes);
+$phpDocParser = new PhpDocParser($typeParser, $constExprParser, true, true, $usedAttributes);
+
+$tokens = new TokenIterator($lexer->tokenize('/** @param Lorem $a */'));
+$phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode
+
+$cloningTraverser = new NodeTraverser([new CloningVisitor()]);
+
+/** @var PhpDocNode $newPhpDocNode */
+$printer = new Printer();
+[$newPhpDocNode] = $cloningTraverser->traverse([$phpDocNode]);
+
+// change something in $newPhpDocNode
+$newPhpDocNode->getParamTagValues()[0]->type = new IdentifierTypeNode('Ipsum');
+
+$newPhpDoc = $printer->printFormatPreserving($newPhpDocNode, $phpDocNode, $tokens);
+echo $newPhpDoc; // '/** @param Ipsum $a */'
+```
## Code of Conduct
diff --git a/vendor/phpstan/phpdoc-parser/composer.json b/vendor/phpstan/phpdoc-parser/composer.json
index 3b902ae2..30b879b7 100644
--- a/vendor/phpstan/phpdoc-parser/composer.json
+++ b/vendor/phpstan/phpdoc-parser/composer.json
@@ -6,6 +6,7 @@
"php": "^7.2 || ^8.0"
},
"require-dev": {
+ "nikic/php-parser": "^4.15",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
diff --git a/vendor/phpstan/phpdoc-parser/phpstan-baseline.neon b/vendor/phpstan/phpdoc-parser/phpstan-baseline.neon
new file mode 100644
index 00000000..04100fcd
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/phpstan-baseline.neon
@@ -0,0 +1,31 @@
+parameters:
+ ignoreErrors:
+ -
+ message: "#^Method PHPStan\\\\PhpDocParser\\\\Ast\\\\ConstExpr\\\\QuoteAwareConstExprStringNode\\:\\:escapeDoubleQuotedString\\(\\) should return string but returns string\\|null\\.$#"
+ count: 1
+ path: src/Ast/ConstExpr/QuoteAwareConstExprStringNode.php
+
+ -
+ message: "#^Cannot use array destructuring on array\\\\|int\\|string\\>\\|null\\.$#"
+ count: 1
+ path: src/Ast/NodeTraverser.php
+
+ -
+ message: "#^Strict comparison using \\=\\=\\= between 2 and 2 will always evaluate to true\\.$#"
+ count: 2
+ path: src/Ast/NodeTraverser.php
+
+ -
+ message: "#^Variable property access on PHPStan\\\\PhpDocParser\\\\Ast\\\\Node\\.$#"
+ count: 1
+ path: src/Ast/NodeTraverser.php
+
+ -
+ message: "#^Method PHPStan\\\\PhpDocParser\\\\Parser\\\\StringUnescaper\\:\\:parseEscapeSequences\\(\\) should return string but returns string\\|null\\.$#"
+ count: 1
+ path: src/Parser/StringUnescaper.php
+
+ -
+ message: "#^Variable property access on PHPStan\\\\PhpDocParser\\\\Ast\\\\Node\\.$#"
+ count: 2
+ path: src/Printer/Printer.php
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php b/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php
new file mode 100644
index 00000000..32d1a04a
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php
@@ -0,0 +1,34 @@
+quoteType = $quoteType;
+ }
+
+
+ public function __toString(): string
+ {
+ if ($this->quoteType === self::SINGLE_QUOTED) {
+ // from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1007
+ return sprintf("'%s'", addcslashes($this->value, '\'\\'));
+ }
+
+ // from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1010-L1040
+ return sprintf('"%s"', $this->escapeDoubleQuotedString());
+ }
+
+ private function escapeDoubleQuotedString(): string
+ {
+ $quote = '"';
+ $escaped = addcslashes($this->value, "\n\r\t\f\v$" . $quote . '\\');
+
+ // Escape control characters and non-UTF-8 characters.
+ // Regex based on https://stackoverflow.com/a/11709412/385378.
+ $regex = '/(
+ [\x00-\x08\x0E-\x1F] # Control characters
+ | [\xC0-\xC1] # Invalid UTF-8 Bytes
+ | [\xF5-\xFF] # Invalid UTF-8 Bytes
+ | \xE0(?=[\x80-\x9F]) # Overlong encoding of prior code point
+ | \xF0(?=[\x80-\x8F]) # Overlong encoding of prior code point
+ | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
+ | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
+ | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
+ | (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
+ | (? Visitors */
+ private $visitors = [];
+
+ /** @var bool Whether traversal should be stopped */
+ private $stopTraversal;
+
+ /**
+ * @param list $visitors
+ */
+ public function __construct(array $visitors)
+ {
+ $this->visitors = $visitors;
+ }
+
+ /**
+ * Traverses an array of nodes using the registered visitors.
+ *
+ * @param Node[] $nodes Array of nodes
+ *
+ * @return Node[] Traversed array of nodes
+ */
+ public function traverse(array $nodes): array
+ {
+ $this->stopTraversal = false;
+
+ foreach ($this->visitors as $visitor) {
+ $return = $visitor->beforeTraverse($nodes);
+ if ($return === null) {
+ continue;
+ }
+
+ $nodes = $return;
+ }
+
+ $nodes = $this->traverseArray($nodes);
+
+ foreach ($this->visitors as $visitor) {
+ $return = $visitor->afterTraverse($nodes);
+ if ($return === null) {
+ continue;
+ }
+
+ $nodes = $return;
+ }
+
+ return $nodes;
+ }
+
+ /**
+ * Recursively traverse a node.
+ *
+ * @param Node $node Node to traverse.
+ *
+ * @return Node Result of traversal (may be original node or new one)
+ */
+ private function traverseNode(Node $node): Node
+ {
+ $subNodeNames = array_keys(get_object_vars($node));
+ foreach ($subNodeNames as $name) {
+ $subNode =& $node->$name;
+
+ if (is_array($subNode)) {
+ $subNode = $this->traverseArray($subNode);
+ if ($this->stopTraversal) {
+ break;
+ }
+ } elseif ($subNode instanceof Node) {
+ $traverseChildren = true;
+ $breakVisitorIndex = null;
+
+ foreach ($this->visitors as $visitorIndex => $visitor) {
+ $return = $visitor->enterNode($subNode);
+ if ($return === null) {
+ continue;
+ }
+
+ if ($return instanceof Node) {
+ $this->ensureReplacementReasonable($subNode, $return);
+ $subNode = $return;
+ } elseif ($return === self::DONT_TRAVERSE_CHILDREN) {
+ $traverseChildren = false;
+ } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) {
+ $traverseChildren = false;
+ $breakVisitorIndex = $visitorIndex;
+ break;
+ } elseif ($return === self::STOP_TRAVERSAL) {
+ $this->stopTraversal = true;
+ break 2;
+ } else {
+ throw new LogicException(
+ 'enterNode() returned invalid value of type ' . gettype($return)
+ );
+ }
+ }
+
+ if ($traverseChildren) {
+ $subNode = $this->traverseNode($subNode);
+ if ($this->stopTraversal) {
+ break;
+ }
+ }
+
+ foreach ($this->visitors as $visitorIndex => $visitor) {
+ $return = $visitor->leaveNode($subNode);
+
+ if ($return !== null) {
+ if ($return instanceof Node) {
+ $this->ensureReplacementReasonable($subNode, $return);
+ $subNode = $return;
+ } elseif ($return === self::STOP_TRAVERSAL) {
+ $this->stopTraversal = true;
+ break 2;
+ } elseif (is_array($return)) {
+ throw new LogicException(
+ 'leaveNode() may only return an array ' .
+ 'if the parent structure is an array'
+ );
+ } else {
+ throw new LogicException(
+ 'leaveNode() returned invalid value of type ' . gettype($return)
+ );
+ }
+ }
+
+ if ($breakVisitorIndex === $visitorIndex) {
+ break;
+ }
+ }
+ }
+ }
+
+ return $node;
+ }
+
+ /**
+ * Recursively traverse array (usually of nodes).
+ *
+ * @param mixed[] $nodes Array to traverse
+ *
+ * @return mixed[] Result of traversal (may be original array or changed one)
+ */
+ private function traverseArray(array $nodes): array
+ {
+ $doNodes = [];
+
+ foreach ($nodes as $i => &$node) {
+ if ($node instanceof Node) {
+ $traverseChildren = true;
+ $breakVisitorIndex = null;
+
+ foreach ($this->visitors as $visitorIndex => $visitor) {
+ $return = $visitor->enterNode($node);
+ if ($return === null) {
+ continue;
+ }
+
+ if ($return instanceof Node) {
+ $this->ensureReplacementReasonable($node, $return);
+ $node = $return;
+ } elseif (is_array($return)) {
+ $doNodes[] = [$i, $return];
+ continue 2;
+ } elseif ($return === self::REMOVE_NODE) {
+ $doNodes[] = [$i, []];
+ continue 2;
+ } elseif ($return === self::DONT_TRAVERSE_CHILDREN) {
+ $traverseChildren = false;
+ } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) {
+ $traverseChildren = false;
+ $breakVisitorIndex = $visitorIndex;
+ break;
+ } elseif ($return === self::STOP_TRAVERSAL) {
+ $this->stopTraversal = true;
+ break 2;
+ } else {
+ throw new LogicException(
+ 'enterNode() returned invalid value of type ' . gettype($return)
+ );
+ }
+ }
+
+ if ($traverseChildren) {
+ $node = $this->traverseNode($node);
+ if ($this->stopTraversal) {
+ break;
+ }
+ }
+
+ foreach ($this->visitors as $visitorIndex => $visitor) {
+ $return = $visitor->leaveNode($node);
+
+ if ($return !== null) {
+ if ($return instanceof Node) {
+ $this->ensureReplacementReasonable($node, $return);
+ $node = $return;
+ } elseif (is_array($return)) {
+ $doNodes[] = [$i, $return];
+ break;
+ } elseif ($return === self::REMOVE_NODE) {
+ $doNodes[] = [$i, []];
+ break;
+ } elseif ($return === self::STOP_TRAVERSAL) {
+ $this->stopTraversal = true;
+ break 2;
+ } else {
+ throw new LogicException(
+ 'leaveNode() returned invalid value of type ' . gettype($return)
+ );
+ }
+ }
+
+ if ($breakVisitorIndex === $visitorIndex) {
+ break;
+ }
+ }
+ } elseif (is_array($node)) {
+ throw new LogicException('Invalid node structure: Contains nested arrays');
+ }
+ }
+
+ if (count($doNodes) > 0) {
+ while ([$i, $replace] = array_pop($doNodes)) {
+ array_splice($nodes, $i, 1, $replace);
+ }
+ }
+
+ return $nodes;
+ }
+
+ private function ensureReplacementReasonable(Node $old, Node $new): void
+ {
+ if ($old instanceof TypeNode && !$new instanceof TypeNode) {
+ throw new LogicException(sprintf('Trying to replace TypeNode with %s', get_class($new)));
+ }
+
+ if ($old instanceof ConstExprNode && !$new instanceof ConstExprNode) {
+ throw new LogicException(sprintf('Trying to replace ConstExprNode with %s', get_class($new)));
+ }
+
+ if ($old instanceof PhpDocChildNode && !$new instanceof PhpDocChildNode) {
+ throw new LogicException(sprintf('Trying to replace PhpDocChildNode with %s', get_class($new)));
+ }
+
+ if ($old instanceof PhpDocTagValueNode && !$new instanceof PhpDocTagValueNode) {
+ throw new LogicException(sprintf('Trying to replace PhpDocTagValueNode with %s', get_class($new)));
+ }
+ }
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php b/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php
new file mode 100644
index 00000000..bf7d784e
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php
@@ -0,0 +1,87 @@
+ $node stays as-is
+ * * array (of Nodes)
+ * => The return value is merged into the parent array (at the position of the $node)
+ * * NodeTraverser::REMOVE_NODE
+ * => $node is removed from the parent array
+ * * NodeTraverser::DONT_TRAVERSE_CHILDREN
+ * => Children of $node are not traversed. $node stays as-is
+ * * NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN
+ * => Further visitors for the current node are skipped, and its children are not
+ * traversed. $node stays as-is.
+ * * NodeTraverser::STOP_TRAVERSAL
+ * => Traversal is aborted. $node stays as-is
+ * * otherwise
+ * => $node is set to the return value
+ *
+ * @param Node $node Node
+ *
+ * @return Node|Node[]|NodeTraverser::*|null Replacement node (or special return value)
+ */
+ public function enterNode(Node $node);
+
+ /**
+ * Called when leaving a node.
+ *
+ * Return value semantics:
+ * * null
+ * => $node stays as-is
+ * * NodeTraverser::REMOVE_NODE
+ * => $node is removed from the parent array
+ * * NodeTraverser::STOP_TRAVERSAL
+ * => Traversal is aborted. $node stays as-is
+ * * array (of Nodes)
+ * => The return value is merged into the parent array (at the position of the $node)
+ * * otherwise
+ * => $node is set to the return value
+ *
+ * @param Node $node Node
+ *
+ * @return Node|Node[]|NodeTraverser::REMOVE_NODE|NodeTraverser::STOP_TRAVERSAL|null Replacement node (or special return value)
+ */
+ public function leaveNode(Node $node);
+
+ /**
+ * Called once after traversal.
+ *
+ * Return value semantics:
+ * * null: $nodes stays as-is
+ * * otherwise: $nodes is set to the return value
+ *
+ * @param Node[] $nodes Array of nodes
+ *
+ * @return Node[]|null Array of nodes
+ */
+ public function afterTraverse(array $nodes): ?array;
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php b/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php
new file mode 100644
index 00000000..7200f3af
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php
@@ -0,0 +1,20 @@
+setAttribute(Attribute::ORIGINAL_NODE, $originalNode);
+
+ return $node;
+ }
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php
index 17bf04f2..ca7b4f20 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php
@@ -31,10 +31,11 @@ class InvalidTagValueNode implements PhpDocTagValueNode
$exception->getCurrentOffset(),
$exception->getExpectedTokenType(),
$exception->getExpectedTokenValue(),
+ $exception->getCurrentTokenLine(),
];
}
- public function __get(string $name)
+ public function __get(string $name): ?ParserException
{
if ($name !== 'exception') {
trigger_error(sprintf('Undefined property: %s::$%s', self::class, $name), E_USER_WARNING);
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php
index 075cec04..211510be 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php
@@ -30,6 +30,10 @@ class MethodTagValueNode implements PhpDocTagValueNode
/** @var string (may be empty) */
public $description;
+ /**
+ * @param MethodTagValueParameterNode[] $parameters
+ * @param TemplateTagValueNode[] $templateTypes
+ */
public function __construct(bool $isStatic, ?TypeNode $returnType, string $methodName, array $parameters, string $description, array $templateTypes = [])
{
$this->isStatic = $isStatic;
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php
index 41941f80..806783f9 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php
@@ -23,6 +23,7 @@ class ArrayShapeNode implements TypeNode
public $kind;
/**
+ * @param ArrayShapeItemNode[] $items
* @param self::KIND_* $kind
*/
public function __construct(array $items, bool $sealed = true, string $kind = self::KIND_ARRAY)
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php
index 90cb9f08..d2031032 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php
@@ -20,6 +20,14 @@ class ArrayTypeNode implements TypeNode
public function __toString(): string
{
+ if (
+ $this->type instanceof CallableTypeNode
+ || $this->type instanceof ConstTypeNode
+ || $this->type instanceof NullableTypeNode
+ ) {
+ return '(' . $this->type . ')[]';
+ }
+
return $this->type . '[]';
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php
index 83ade94c..e57e5f82 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php
@@ -19,6 +19,9 @@ class CallableTypeNode implements TypeNode
/** @var TypeNode */
public $returnType;
+ /**
+ * @param CallableTypeParameterNode[] $parameters
+ */
public function __construct(IdentifierTypeNode $identifier, array $parameters, TypeNode $returnType)
{
$this->identifier = $identifier;
@@ -29,8 +32,12 @@ class CallableTypeNode implements TypeNode
public function __toString(): string
{
+ $returnType = $this->returnType;
+ if ($returnType instanceof self) {
+ $returnType = "({$returnType})";
+ }
$parameters = implode(', ', $this->parameters);
- return "{$this->identifier}({$parameters}): {$this->returnType}";
+ return "{$this->identifier}({$parameters}): {$returnType}";
}
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php
index 7ab2d7e3..c78d4c7b 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php
@@ -41,8 +41,8 @@ class CallableTypeParameterNode implements Node
$type = "{$this->type} ";
$isReference = $this->isReference ? '&' : '';
$isVariadic = $this->isVariadic ? '...' : '';
- $default = $this->isOptional ? ' = default' : '';
- return trim("{$type}{$isReference}{$isVariadic}{$this->parameterName}") . $default;
+ $isOptional = $this->isOptional ? '=' : '';
+ return trim("{$type}{$isReference}{$isVariadic}{$this->parameterName}") . $isOptional;
}
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php
index 179de55a..44e1d16d 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php
@@ -25,6 +25,10 @@ class GenericTypeNode implements TypeNode
/** @var (self::VARIANCE_*)[] */
public $variances;
+ /**
+ * @param TypeNode[] $genericTypes
+ * @param (self::VARIANCE_*)[] $variances
+ */
public function __construct(IdentifierTypeNode $type, array $genericTypes, array $variances = [])
{
$this->type = $type;
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php
index 7f9aff33..fd761cf7 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php
@@ -3,6 +3,7 @@
namespace PHPStan\PhpDocParser\Ast\Type;
use PHPStan\PhpDocParser\Ast\NodeAttributes;
+use function array_map;
use function implode;
class IntersectionTypeNode implements TypeNode
@@ -13,6 +14,9 @@ class IntersectionTypeNode implements TypeNode
/** @var TypeNode[] */
public $types;
+ /**
+ * @param TypeNode[] $types
+ */
public function __construct(array $types)
{
$this->types = $types;
@@ -21,7 +25,13 @@ class IntersectionTypeNode implements TypeNode
public function __toString(): string
{
- return '(' . implode(' & ', $this->types) . ')';
+ return '(' . implode(' & ', array_map(static function (TypeNode $type): string {
+ if ($type instanceof NullableTypeNode) {
+ return '(' . $type . ')';
+ }
+
+ return (string) $type;
+ }, $this->types)) . ')';
}
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php
new file mode 100644
index 00000000..1ec47cf6
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php
@@ -0,0 +1,38 @@
+exceptionArgs = [
+ $exception->getCurrentTokenValue(),
+ $exception->getCurrentTokenType(),
+ $exception->getCurrentOffset(),
+ $exception->getExpectedTokenType(),
+ $exception->getExpectedTokenValue(),
+ $exception->getCurrentTokenLine(),
+ ];
+ }
+
+ public function getException(): ParserException
+ {
+ return new ParserException(...$this->exceptionArgs);
+ }
+
+ public function __toString(): string
+ {
+ return '*Invalid type*';
+ }
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php
new file mode 100644
index 00000000..2f012406
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php
@@ -0,0 +1,48 @@
+keyName = $keyName;
+ $this->optional = $optional;
+ $this->valueType = $valueType;
+ }
+
+
+ public function __toString(): string
+ {
+ if ($this->keyName !== null) {
+ return sprintf(
+ '%s%s: %s',
+ (string) $this->keyName,
+ $this->optional ? '?' : '',
+ (string) $this->valueType
+ );
+ }
+
+ return (string) $this->valueType;
+ }
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php
new file mode 100644
index 00000000..f418bc30
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php
@@ -0,0 +1,31 @@
+items = $items;
+ }
+
+ public function __toString(): string
+ {
+ $items = $this->items;
+
+ return 'object{' . implode(', ', $items) . '}';
+ }
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php
index 1d5b04ef..39e83dfe 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php
@@ -23,6 +23,14 @@ class OffsetAccessTypeNode implements TypeNode
public function __toString(): string
{
+ if (
+ $this->type instanceof CallableTypeNode
+ || $this->type instanceof ConstTypeNode
+ || $this->type instanceof NullableTypeNode
+ ) {
+ return '(' . $this->type . ')[' . $this->offset . ']';
+ }
+
return $this->type . '[' . $this->offset . ']';
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php
index 08acf56c..c552dab5 100644
--- a/vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php
+++ b/vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php
@@ -3,6 +3,7 @@
namespace PHPStan\PhpDocParser\Ast\Type;
use PHPStan\PhpDocParser\Ast\NodeAttributes;
+use function array_map;
use function implode;
class UnionTypeNode implements TypeNode
@@ -13,6 +14,9 @@ class UnionTypeNode implements TypeNode
/** @var TypeNode[] */
public $types;
+ /**
+ * @param TypeNode[] $types
+ */
public function __construct(array $types)
{
$this->types = $types;
@@ -21,7 +25,13 @@ class UnionTypeNode implements TypeNode
public function __toString(): string
{
- return '(' . implode(' | ', $this->types) . ')';
+ return '(' . implode(' | ', array_map(static function (TypeNode $type): string {
+ if ($type instanceof NullableTypeNode) {
+ return '(' . $type . ')';
+ }
+
+ return (string) $type;
+ }, $this->types)) . ')';
}
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php b/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php
index 1b98839d..ccae6bef 100644
--- a/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php
+++ b/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php
@@ -88,10 +88,14 @@ class Lexer
public const VALUE_OFFSET = 0;
public const TYPE_OFFSET = 1;
+ public const LINE_OFFSET = 2;
/** @var string|null */
private $regexp;
+ /**
+ * @return list
+ */
public function tokenize(string $s): array
{
if ($this->regexp === null) {
@@ -101,11 +105,18 @@ class Lexer
preg_match_all($this->regexp, $s, $matches, PREG_SET_ORDER);
$tokens = [];
+ $line = 1;
foreach ($matches as $match) {
- $tokens[] = [$match[0], (int) $match['MARK']];
+ $type = (int) $match['MARK'];
+ $tokens[] = [$match[0], $type, $line];
+ if ($type !== self::TOKEN_PHPDOC_EOL) {
+ continue;
+ }
+
+ $line++;
}
- $tokens[] = ['', self::TOKEN_END];
+ $tokens[] = ['', self::TOKEN_END, $line];
return $tokens;
}
@@ -149,8 +160,8 @@ class Lexer
self::TOKEN_PHPDOC_TAG => '@(?:[a-z][a-z0-9-\\\\]+:)?[a-z][a-z0-9-\\\\]*+',
self::TOKEN_PHPDOC_EOL => '\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/)\\x20?+)?',
- self::TOKEN_FLOAT => '(?:-?[0-9]++\\.[0-9]*+(?:e-?[0-9]++)?)|(?:-?[0-9]*+\\.[0-9]++(?:e-?[0-9]++)?)|(?:-?[0-9]++e-?[0-9]++)',
- self::TOKEN_INTEGER => '-?(?:(?:0b[0-1]++)|(?:0o[0-7]++)|(?:0x[0-9a-f]++)|(?:[0-9]++))',
+ self::TOKEN_FLOAT => '(?:-?[0-9]++(_[0-9]++)*\\.[0-9]*(_[0-9]++)*+(?:e-?[0-9]++(_[0-9]++)*)?)|(?:-?[0-9]*+(_[0-9]++)*\\.[0-9]++(_[0-9]++)*(?:e-?[0-9]++(_[0-9]++)*)?)|(?:-?[0-9]++(_[0-9]++)*e-?[0-9]++(_[0-9]++)*)',
+ self::TOKEN_INTEGER => '-?(?:(?:0b[0-1]++(_[0-1]++)*)|(?:0o[0-7]++(_[0-7]++)*)|(?:0x[0-9a-f]++(_[0-9a-f]++)*)|(?:[0-9]++(_[0-9]++)*))',
self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\[^\\r\\n]|[^\'\\r\\n\\\\])*+\'',
self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\[^\\r\\n]|[^"\\r\\n\\\\])*+"',
diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php b/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php
index d7876303..b6db8a2c 100644
--- a/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php
+++ b/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php
@@ -4,10 +4,6 @@ namespace PHPStan\PhpDocParser\Parser;
use PHPStan\PhpDocParser\Ast;
use PHPStan\PhpDocParser\Lexer\Lexer;
-use function chr;
-use function hexdec;
-use function octdec;
-use function preg_replace_callback;
use function str_replace;
use function strtolower;
use function substr;
@@ -15,49 +11,93 @@ use function substr;
class ConstExprParser
{
- private const REPLACEMENTS = [
- '\\' => '\\',
- 'n' => "\n",
- 'r' => "\r",
- 't' => "\t",
- 'f' => "\f",
- 'v' => "\v",
- 'e' => "\x1B",
- ];
-
/** @var bool */
private $unescapeStrings;
- public function __construct(bool $unescapeStrings = false)
+ /** @var bool */
+ private $quoteAwareConstExprString;
+
+ /** @var bool */
+ private $useLinesAttributes;
+
+ /** @var bool */
+ private $useIndexAttributes;
+
+ /**
+ * @param array{lines?: bool, indexes?: bool} $usedAttributes
+ */
+ public function __construct(
+ bool $unescapeStrings = false,
+ bool $quoteAwareConstExprString = false,
+ array $usedAttributes = []
+ )
{
$this->unescapeStrings = $unescapeStrings;
+ $this->quoteAwareConstExprString = $quoteAwareConstExprString;
+ $this->useLinesAttributes = $usedAttributes['lines'] ?? false;
+ $this->useIndexAttributes = $usedAttributes['indexes'] ?? false;
}
public function parse(TokenIterator $tokens, bool $trimStrings = false): Ast\ConstExpr\ConstExprNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
if ($tokens->isCurrentTokenType(Lexer::TOKEN_FLOAT)) {
$value = $tokens->currentTokenValue();
$tokens->next();
- return new Ast\ConstExpr\ConstExprFloatNode($value);
+
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstExprFloatNode(str_replace('_', '', $value)),
+ $startLine,
+ $startIndex
+ );
}
if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
$value = $tokens->currentTokenValue();
$tokens->next();
- return new Ast\ConstExpr\ConstExprIntegerNode($value);
+
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $value)),
+ $startLine,
+ $startIndex
+ );
}
if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING, Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
$value = $tokens->currentTokenValue();
+ $type = $tokens->currentTokenType();
if ($trimStrings) {
if ($this->unescapeStrings) {
- $value = self::unescapeString($value);
+ $value = StringUnescaper::unescapeString($value);
} else {
$value = substr($value, 1, -1);
}
}
$tokens->next();
- return new Ast\ConstExpr\ConstExprStringNode($value);
+
+ if ($this->quoteAwareConstExprString) {
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\QuoteAwareConstExprStringNode(
+ $value,
+ $type === Lexer::TOKEN_SINGLE_QUOTED_STRING
+ ? Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED
+ : Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED
+ ),
+ $startLine,
+ $startIndex
+ );
+ }
+
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstExprStringNode($value),
+ $startLine,
+ $startIndex
+ );
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
$identifier = $tokens->currentTokenValue();
@@ -65,14 +105,29 @@ class ConstExprParser
switch (strtolower($identifier)) {
case 'true':
- return new Ast\ConstExpr\ConstExprTrueNode();
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstExprTrueNode(),
+ $startLine,
+ $startIndex
+ );
case 'false':
- return new Ast\ConstExpr\ConstExprFalseNode();
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstExprFalseNode(),
+ $startLine,
+ $startIndex
+ );
case 'null':
- return new Ast\ConstExpr\ConstExprNullNode();
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstExprNullNode(),
+ $startLine,
+ $startIndex
+ );
case 'array':
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
- return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_PARENTHESES);
+ return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_PARENTHESES, $startIndex);
}
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
@@ -106,29 +161,43 @@ class ConstExprParser
break;
}
- return new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName);
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName),
+ $startLine,
+ $startIndex
+ );
}
- return new Ast\ConstExpr\ConstFetchNode('', $identifier);
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstFetchNode('', $identifier),
+ $startLine,
+ $startIndex
+ );
} elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
- return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
+ return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_SQUARE_BRACKET, $startIndex);
}
throw new ParserException(
$tokens->currentTokenValue(),
$tokens->currentTokenType(),
$tokens->currentTokenOffset(),
- Lexer::TOKEN_IDENTIFIER
+ Lexer::TOKEN_IDENTIFIER,
+ null,
+ $tokens->currentTokenLine()
);
}
- private function parseArray(TokenIterator $tokens, int $endToken): Ast\ConstExpr\ConstExprArrayNode
+ private function parseArray(TokenIterator $tokens, int $endToken, int $startIndex): Ast\ConstExpr\ConstExprArrayNode
{
$items = [];
+ $startLine = $tokens->currentTokenLine();
+
if (!$tokens->tryConsumeTokenType($endToken)) {
do {
$items[] = $this->parseArrayItem($tokens);
@@ -136,12 +205,20 @@ class ConstExprParser
$tokens->consumeTokenType($endToken);
}
- return new Ast\ConstExpr\ConstExprArrayNode($items);
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstExprArrayNode($items),
+ $startLine,
+ $startIndex
+ );
}
private function parseArrayItem(TokenIterator $tokens): Ast\ConstExpr\ConstExprArrayItemNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+
$expr = $this->parse($tokens);
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_ARROW)) {
@@ -153,78 +230,40 @@ class ConstExprParser
$value = $expr;
}
- return new Ast\ConstExpr\ConstExprArrayItemNode($key, $value);
- }
-
- private static function unescapeString(string $string): string
- {
- $quote = $string[0];
-
- if ($quote === '\'') {
- return str_replace(
- ['\\\\', '\\\''],
- ['\\', '\''],
- substr($string, 1, -1)
- );
- }
-
- return self::parseEscapeSequences(substr($string, 1, -1), '"');
- }
-
- /**
- * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L90-L130
- */
- private static function parseEscapeSequences(string $str, string $quote): string
- {
- $str = str_replace('\\' . $quote, $quote, $str);
-
- return preg_replace_callback(
- '~\\\\([\\\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\{([0-9a-fA-F]+)\})~',
- static function ($matches) {
- $str = $matches[1];
-
- if (isset(self::REPLACEMENTS[$str])) {
- return self::REPLACEMENTS[$str];
- }
- if ($str[0] === 'x' || $str[0] === 'X') {
- return chr(hexdec(substr($str, 1)));
- }
- if ($str[0] === 'u') {
- return self::codePointToUtf8(hexdec($matches[2]));
- }
-
- return chr(octdec($str));
- },
- $str
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\ConstExpr\ConstExprArrayItemNode($key, $value),
+ $startLine,
+ $startIndex
);
}
/**
- * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L132-L154
+ * @template T of Ast\ConstExpr\ConstExprNode
+ * @param T $node
+ * @return T
*/
- private static function codePointToUtf8(int $num): string
+ private function enrichWithAttributes(TokenIterator $tokens, Ast\ConstExpr\ConstExprNode $node, int $startLine, int $startIndex): Ast\ConstExpr\ConstExprNode
{
- if ($num <= 0x7F) {
- return chr($num);
- }
- if ($num <= 0x7FF) {
- return chr(($num >> 6) + 0xC0)
- . chr(($num & 0x3F) + 0x80);
- }
- if ($num <= 0xFFFF) {
- return chr(($num >> 12) + 0xE0)
- . chr((($num >> 6) & 0x3F) + 0x80)
- . chr(($num & 0x3F) + 0x80);
- }
- if ($num <= 0x1FFFFF) {
- return chr(($num >> 18) + 0xF0)
- . chr((($num >> 12) & 0x3F) + 0x80)
- . chr((($num >> 6) & 0x3F) + 0x80)
- . chr(($num & 0x3F) + 0x80);
+ $endLine = $tokens->currentTokenLine();
+ $endIndex = $tokens->currentTokenIndex();
+ if ($this->useLinesAttributes) {
+ $node->setAttribute(Ast\Attribute::START_LINE, $startLine);
+ $node->setAttribute(Ast\Attribute::END_LINE, $endLine);
}
- // Invalid UTF-8 codepoint escape sequence: Codepoint too large
- return "\xef\xbf\xbd";
+ if ($this->useIndexAttributes) {
+ $tokensArray = $tokens->getTokens();
+ $endIndex--;
+ if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
+ $endIndex--;
+ }
+
+ $node->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
+ $node->setAttribute(Ast\Attribute::END_INDEX, $endIndex);
+ }
+
+ return $node;
}
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php b/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php
index badcdcbb..6ab5cc07 100644
--- a/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php
+++ b/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php
@@ -7,6 +7,7 @@ use PHPStan\PhpDocParser\Lexer\Lexer;
use function assert;
use function json_encode;
use function sprintf;
+use const JSON_INVALID_UTF8_SUBSTITUTE;
use const JSON_UNESCAPED_SLASHES;
use const JSON_UNESCAPED_UNICODE;
@@ -28,12 +29,16 @@ class ParserException extends Exception
/** @var string|null */
private $expectedTokenValue;
+ /** @var int|null */
+ private $currentTokenLine;
+
public function __construct(
string $currentTokenValue,
int $currentTokenType,
int $currentOffset,
int $expectedTokenType,
- ?string $expectedTokenValue = null
+ ?string $expectedTokenValue = null,
+ ?int $currentTokenLine = null
)
{
$this->currentTokenValue = $currentTokenValue;
@@ -41,13 +46,15 @@ class ParserException extends Exception
$this->currentOffset = $currentOffset;
$this->expectedTokenType = $expectedTokenType;
$this->expectedTokenValue = $expectedTokenValue;
+ $this->currentTokenLine = $currentTokenLine;
parent::__construct(sprintf(
- 'Unexpected token %s, expected %s%s at offset %d',
+ 'Unexpected token %s, expected %s%s at offset %d%s',
$this->formatValue($currentTokenValue),
Lexer::TOKEN_LABELS[$expectedTokenType],
$expectedTokenValue !== null ? sprintf(' (%s)', $this->formatValue($expectedTokenValue)) : '',
- $currentOffset
+ $currentOffset,
+ $currentTokenLine === null ? '' : sprintf(' on line %d', $currentTokenLine)
));
}
@@ -82,9 +89,15 @@ class ParserException extends Exception
}
+ public function getCurrentTokenLine(): ?int
+ {
+ return $this->currentTokenLine;
+ }
+
+
private function formatValue(string $value): string
{
- $json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
+ $json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE);
assert($json !== false);
return $json;
diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php b/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php
index d9942b3d..d3eed465 100644
--- a/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php
+++ b/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php
@@ -28,11 +28,32 @@ class PhpDocParser
/** @var bool */
private $requireWhitespaceBeforeDescription;
- public function __construct(TypeParser $typeParser, ConstExprParser $constantExprParser, bool $requireWhitespaceBeforeDescription = false)
+ /** @var bool */
+ private $preserveTypeAliasesWithInvalidTypes;
+
+ /** @var bool */
+ private $useLinesAttributes;
+
+ /** @var bool */
+ private $useIndexAttributes;
+
+ /**
+ * @param array{lines?: bool, indexes?: bool} $usedAttributes
+ */
+ public function __construct(
+ TypeParser $typeParser,
+ ConstExprParser $constantExprParser,
+ bool $requireWhitespaceBeforeDescription = false,
+ bool $preserveTypeAliasesWithInvalidTypes = false,
+ array $usedAttributes = []
+ )
{
$this->typeParser = $typeParser;
$this->constantExprParser = $constantExprParser;
$this->requireWhitespaceBeforeDescription = $requireWhitespaceBeforeDescription;
+ $this->preserveTypeAliasesWithInvalidTypes = $preserveTypeAliasesWithInvalidTypes;
+ $this->useLinesAttributes = $usedAttributes['lines'] ?? false;
+ $this->useIndexAttributes = $usedAttributes['indexes'] ?? false;
}
@@ -54,30 +75,82 @@ class PhpDocParser
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC);
} catch (ParserException $e) {
$name = '';
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
if (count($children) > 0) {
$lastChild = $children[count($children) - 1];
if ($lastChild instanceof Ast\PhpDoc\PhpDocTagNode) {
$name = $lastChild->name;
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
}
}
+
+ $tag = new Ast\PhpDoc\PhpDocTagNode(
+ $name,
+ $this->enrichWithAttributes(
+ $tokens,
+ new Ast\PhpDoc\InvalidTagValueNode($e->getMessage(), $e),
+ $startLine,
+ $startIndex
+ )
+ );
+
$tokens->forwardToTheEnd();
- return new Ast\PhpDoc\PhpDocNode([
- new Ast\PhpDoc\PhpDocTagNode($name, new Ast\PhpDoc\InvalidTagValueNode($e->getMessage(), $e)),
- ]);
+
+ return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode([$this->enrichWithAttributes($tokens, $tag, $startLine, $startIndex)]), 1, 0);
}
- return new Ast\PhpDoc\PhpDocNode(array_values($children));
+ return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode(array_values($children)), 1, 0);
}
private function parseChild(TokenIterator $tokens): Ast\PhpDoc\PhpDocChildNode
{
if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) {
- return $this->parseTag($tokens);
-
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+ return $this->enrichWithAttributes($tokens, $this->parseTag($tokens), $startLine, $startIndex);
}
- return $this->parseText($tokens);
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+ $text = $this->parseText($tokens);
+
+ return $this->enrichWithAttributes($tokens, $text, $startLine, $startIndex);
+ }
+
+ /**
+ * @template T of Ast\Node
+ * @param T $tag
+ * @return T
+ */
+ private function enrichWithAttributes(TokenIterator $tokens, Ast\Node $tag, int $startLine, int $startIndex): Ast\Node
+ {
+ $endLine = $tokens->currentTokenLine();
+ $endIndex = $tokens->currentTokenIndex();
+
+ if ($this->useLinesAttributes) {
+ $tag->setAttribute(Ast\Attribute::START_LINE, $startLine);
+ $tag->setAttribute(Ast\Attribute::END_LINE, $endLine);
+ }
+
+ if ($this->useIndexAttributes) {
+ $tokensArray = $tokens->getTokens();
+ if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_CLOSE_PHPDOC) {
+ $endIndex--;
+ if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
+ $endIndex--;
+ }
+ } elseif ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) {
+ $endIndex--;
+ }
+
+ $tag->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
+ $tag->setAttribute(Ast\Attribute::END_INDEX, $endIndex);
+ }
+
+ return $tag;
}
@@ -120,6 +193,9 @@ class PhpDocParser
public function parseTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\PhpDocTagValueNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+
try {
$tokens->pushSavePoint();
@@ -247,7 +323,7 @@ class PhpDocParser
$tagValue = new Ast\PhpDoc\InvalidTagValueNode($this->parseOptionalDescription($tokens), $e);
}
- return $tagValue;
+ return $this->enrichWithAttributes($tokens, $tagValue, $startLine, $startIndex);
}
@@ -257,9 +333,7 @@ class PhpDocParser
private function parseParamTagValue(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode
{
if (
- $tokens->isCurrentTokenType(Lexer::TOKEN_REFERENCE)
- || $tokens->isCurrentTokenType(Lexer::TOKEN_VARIADIC)
- || $tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)
+ $tokens->isCurrentTokenType(Lexer::TOKEN_REFERENCE, Lexer::TOKEN_VARIADIC, Lexer::TOKEN_VARIABLE)
) {
$type = null;
} else {
@@ -329,6 +403,8 @@ class PhpDocParser
private function parseMethodTagValue(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueNode
{
$isStatic = $tokens->tryConsumeTokenValue('static');
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
$returnTypeOrMethodName = $this->typeParser->parse($tokens);
if ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
@@ -337,7 +413,9 @@ class PhpDocParser
$tokens->next();
} elseif ($returnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode) {
- $returnType = $isStatic ? new Ast\Type\IdentifierTypeNode('static') : null;
+ $returnType = $isStatic
+ ? $this->typeParser->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode('static'), $startLine, $startIndex)
+ : null;
$methodName = $returnTypeOrMethodName->name;
$isStatic = false;
@@ -347,9 +425,12 @@ class PhpDocParser
}
$templateTypes = [];
+
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
do {
- $templateTypes[] = $this->parseTemplateTagValue($tokens, false);
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+ $templateTypes[] = $this->enrichWithAttributes($tokens, $this->parseTemplateTagValue($tokens, false), $startLine, $startIndex);
} while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
}
@@ -370,6 +451,9 @@ class PhpDocParser
private function parseMethodTagValueParameter(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueParameterNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+
switch ($tokens->currentTokenType()) {
case Lexer::TOKEN_IDENTIFIER:
case Lexer::TOKEN_OPEN_PARENTHESES:
@@ -394,7 +478,12 @@ class PhpDocParser
$defaultValue = null;
}
- return new Ast\PhpDoc\MethodTagValueParameterNode($parameterType, $isReference, $isVariadic, $parameterName, $defaultValue);
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\PhpDoc\MethodTagValueParameterNode($parameterType, $isReference, $isVariadic, $parameterName, $defaultValue),
+ $startLine,
+ $startIndex
+ );
}
private function parseTemplateTagValue(TokenIterator $tokens, bool $parseDescription): Ast\PhpDoc\TemplateTagValueNode
@@ -426,10 +515,15 @@ class PhpDocParser
private function parseExtendsTagValue(string $tagName, TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
$baseType = new IdentifierTypeNode($tokens->currentTokenValue());
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
- $type = $this->typeParser->parseGeneric($tokens, $baseType);
+ $type = $this->typeParser->parseGeneric(
+ $tokens,
+ $this->typeParser->enrichWithAttributes($tokens, $baseType, $startLine, $startIndex)
+ );
$description = $this->parseOptionalDescription($tokens);
@@ -453,6 +547,34 @@ class PhpDocParser
// support psalm-type syntax
$tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
+ if ($this->preserveTypeAliasesWithInvalidTypes) {
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+ try {
+ $type = $this->typeParser->parse($tokens);
+ if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
+ if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
+ throw new ParserException(
+ $tokens->currentTokenValue(),
+ $tokens->currentTokenType(),
+ $tokens->currentTokenOffset(),
+ Lexer::TOKEN_PHPDOC_EOL,
+ null,
+ $tokens->currentTokenLine()
+ );
+ }
+ }
+
+ return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type);
+ } catch (ParserException $e) {
+ $this->parseOptionalDescription($tokens);
+ return new Ast\PhpDoc\TypeAliasTagValueNode(
+ $alias,
+ $this->enrichWithAttributes($tokens, new Ast\Type\InvalidTypeNode($e), $startLine, $startIndex)
+ );
+ }
+ }
+
$type = $this->typeParser->parse($tokens);
return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type);
@@ -465,8 +587,16 @@ class PhpDocParser
$tokens->consumeTokenValue(Lexer::TOKEN_IDENTIFIER, 'from');
+ $identifierStartLine = $tokens->currentTokenLine();
+ $identifierStartIndex = $tokens->currentTokenIndex();
$importedFrom = $tokens->currentTokenValue();
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
+ $importedFromType = $this->enrichWithAttributes(
+ $tokens,
+ new IdentifierTypeNode($importedFrom),
+ $identifierStartLine,
+ $identifierStartIndex
+ );
$importedAs = null;
if ($tokens->tryConsumeTokenValue('as')) {
@@ -474,7 +604,7 @@ class PhpDocParser
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
}
- return new Ast\PhpDoc\TypeAliasImportTagValueNode($importedAlias, new IdentifierTypeNode($importedFrom), $importedAs);
+ return new Ast\PhpDoc\TypeAliasImportTagValueNode($importedAlias, $importedFromType, $importedAs);
}
/**
diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php b/vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php
new file mode 100644
index 00000000..70524055
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php
@@ -0,0 +1,96 @@
+ '\\',
+ 'n' => "\n",
+ 'r' => "\r",
+ 't' => "\t",
+ 'f' => "\f",
+ 'v' => "\v",
+ 'e' => "\x1B",
+ ];
+
+ public static function unescapeString(string $string): string
+ {
+ $quote = $string[0];
+
+ if ($quote === '\'') {
+ return str_replace(
+ ['\\\\', '\\\''],
+ ['\\', '\''],
+ substr($string, 1, -1)
+ );
+ }
+
+ return self::parseEscapeSequences(substr($string, 1, -1), '"');
+ }
+
+ /**
+ * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L90-L130
+ */
+ private static function parseEscapeSequences(string $str, string $quote): string
+ {
+ $str = str_replace('\\' . $quote, $quote, $str);
+
+ return preg_replace_callback(
+ '~\\\\([\\\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\{([0-9a-fA-F]+)\})~',
+ static function ($matches) {
+ $str = $matches[1];
+
+ if (isset(self::REPLACEMENTS[$str])) {
+ return self::REPLACEMENTS[$str];
+ }
+ if ($str[0] === 'x' || $str[0] === 'X') {
+ return chr((int) hexdec(substr($str, 1)));
+ }
+ if ($str[0] === 'u') {
+ return self::codePointToUtf8((int) hexdec($matches[2]));
+ }
+
+ return chr((int) octdec($str));
+ },
+ $str
+ );
+ }
+
+ /**
+ * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L132-L154
+ */
+ private static function codePointToUtf8(int $num): string
+ {
+ if ($num <= 0x7F) {
+ return chr($num);
+ }
+ if ($num <= 0x7FF) {
+ return chr(($num >> 6) + 0xC0)
+ . chr(($num & 0x3F) + 0x80);
+ }
+ if ($num <= 0xFFFF) {
+ return chr(($num >> 12) + 0xE0)
+ . chr((($num >> 6) & 0x3F) + 0x80)
+ . chr(($num & 0x3F) + 0x80);
+ }
+ if ($num <= 0x1FFFFF) {
+ return chr(($num >> 18) + 0xF0)
+ . chr((($num >> 12) & 0x3F) + 0x80)
+ . chr((($num >> 6) & 0x3F) + 0x80)
+ . chr(($num & 0x3F) + 0x80);
+ }
+
+ // Invalid UTF-8 codepoint escape sequence: Codepoint too large
+ return "\xef\xbf\xbd";
+ }
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php b/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php
index 569a9321..4348ab79 100644
--- a/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php
+++ b/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php
@@ -2,6 +2,7 @@
namespace PHPStan\PhpDocParser\Parser;
+use LogicException;
use PHPStan\PhpDocParser\Lexer\Lexer;
use function array_pop;
use function assert;
@@ -12,7 +13,7 @@ use function strlen;
class TokenIterator
{
- /** @var mixed[][] */
+ /** @var list */
private $tokens;
/** @var int */
@@ -21,6 +22,9 @@ class TokenIterator
/** @var int[] */
private $savePoints = [];
+ /**
+ * @param list $tokens
+ */
public function __construct(array $tokens, int $index = 0)
{
$this->tokens = $tokens;
@@ -34,6 +38,36 @@ class TokenIterator
}
+ /**
+ * @return list
+ */
+ public function getTokens(): array
+ {
+ return $this->tokens;
+ }
+
+
+ public function getContentBetween(int $startPos, int $endPos): string
+ {
+ if ($startPos < 0 || $endPos > count($this->tokens)) {
+ throw new LogicException();
+ }
+
+ $content = '';
+ for ($i = $startPos; $i < $endPos; $i++) {
+ $content .= $this->tokens[$i][Lexer::VALUE_OFFSET];
+ }
+
+ return $content;
+ }
+
+
+ public function getTokenCount(): int
+ {
+ return count($this->tokens);
+ }
+
+
public function currentTokenValue(): string
{
return $this->tokens[$this->index][Lexer::VALUE_OFFSET];
@@ -57,6 +91,18 @@ class TokenIterator
}
+ public function currentTokenLine(): int
+ {
+ return $this->tokens[$this->index][Lexer::LINE_OFFSET];
+ }
+
+
+ public function currentTokenIndex(): int
+ {
+ return $this->index;
+ }
+
+
public function isCurrentTokenValue(string $tokenValue): bool
{
return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue;
@@ -217,8 +263,69 @@ class TokenIterator
$this->currentTokenType(),
$this->currentTokenOffset(),
$expectedTokenType,
- $expectedTokenValue
+ $expectedTokenValue,
+ $this->currentTokenLine()
);
}
+ /**
+ * Check whether the position is directly preceded by a certain token type.
+ *
+ * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped
+ */
+ public function hasTokenImmediatelyBefore(int $pos, int $expectedTokenType): bool
+ {
+ $tokens = $this->tokens;
+ $pos--;
+ for (; $pos >= 0; $pos--) {
+ $token = $tokens[$pos];
+ $type = $token[Lexer::TYPE_OFFSET];
+ if ($type === $expectedTokenType) {
+ return true;
+ }
+ if (!in_array($type, [
+ Lexer::TOKEN_HORIZONTAL_WS,
+ Lexer::TOKEN_PHPDOC_EOL,
+ ], true)) {
+ break;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check whether the position is directly followed by a certain token type.
+ *
+ * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped
+ */
+ public function hasTokenImmediatelyAfter(int $pos, int $expectedTokenType): bool
+ {
+ $tokens = $this->tokens;
+ $pos++;
+ for ($c = count($tokens); $pos < $c; $pos++) {
+ $token = $tokens[$pos];
+ $type = $token[Lexer::TYPE_OFFSET];
+ if ($type === $expectedTokenType) {
+ return true;
+ }
+ if (!in_array($type, [
+ Lexer::TOKEN_HORIZONTAL_WS,
+ Lexer::TOKEN_PHPDOC_EOL,
+ ], true)) {
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Whether the given position is immediately surrounded by parenthesis.
+ */
+ public function hasParentheses(int $startPos, int $endPos): bool
+ {
+ return $this->hasTokenImmediatelyBefore($startPos, Lexer::TOKEN_OPEN_PARENTHESES)
+ && $this->hasTokenImmediatelyAfter($endPos, Lexer::TOKEN_CLOSE_PARENTHESES);
+ }
+
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php b/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php
index d196eb94..4b429809 100644
--- a/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php
+++ b/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php
@@ -6,6 +6,7 @@ use LogicException;
use PHPStan\PhpDocParser\Ast;
use PHPStan\PhpDocParser\Lexer\Lexer;
use function in_array;
+use function str_replace;
use function strpos;
use function trim;
@@ -15,14 +16,35 @@ class TypeParser
/** @var ConstExprParser|null */
private $constExprParser;
- public function __construct(?ConstExprParser $constExprParser = null)
+ /** @var bool */
+ private $quoteAwareConstExprString;
+
+ /** @var bool */
+ private $useLinesAttributes;
+
+ /** @var bool */
+ private $useIndexAttributes;
+
+ /**
+ * @param array{lines?: bool, indexes?: bool} $usedAttributes
+ */
+ public function __construct(
+ ?ConstExprParser $constExprParser = null,
+ bool $quoteAwareConstExprString = false,
+ array $usedAttributes = []
+ )
{
$this->constExprParser = $constExprParser;
+ $this->quoteAwareConstExprString = $quoteAwareConstExprString;
+ $this->useLinesAttributes = $usedAttributes['lines'] ?? false;
+ $this->useIndexAttributes = $usedAttributes['indexes'] ?? false;
}
/** @phpstan-impure */
public function parse(TokenIterator $tokens): Ast\Type\TypeNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
$type = $this->parseNullable($tokens);
@@ -37,12 +59,45 @@ class TypeParser
}
}
+ return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
+ }
+
+ /**
+ * @internal
+ * @template T of Ast\Node
+ * @param T $type
+ * @return T
+ */
+ public function enrichWithAttributes(TokenIterator $tokens, Ast\Node $type, int $startLine, int $startIndex): Ast\Node
+ {
+ $endLine = $tokens->currentTokenLine();
+ $endIndex = $tokens->currentTokenIndex();
+
+ if ($this->useLinesAttributes) {
+ $type->setAttribute(Ast\Attribute::START_LINE, $startLine);
+ $type->setAttribute(Ast\Attribute::END_LINE, $endLine);
+ }
+
+ if ($this->useIndexAttributes) {
+ $tokensArray = $tokens->getTokens();
+ $endIndex--;
+ if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
+ $endIndex--;
+ }
+
+ $type->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
+ $type->setAttribute(Ast\Attribute::END_INDEX, $endIndex);
+ }
+
return $type;
}
/** @phpstan-impure */
private function subParse(TokenIterator $tokens): Ast\Type\TypeNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+
if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
$type = $this->parseNullable($tokens);
@@ -66,13 +121,16 @@ class TypeParser
}
}
- return $type;
+ return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
}
/** @phpstan-impure */
private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
$type = $this->subParse($tokens);
@@ -81,26 +139,26 @@ class TypeParser
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
- return $this->tryParseArrayOrOffsetAccess($tokens, $type);
+ $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
}
- return $type;
+ return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
}
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
- $type = new Ast\Type\ThisTypeNode();
+ $type = $this->enrichWithAttributes($tokens, new Ast\Type\ThisTypeNode(), $startLine, $startIndex);
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
- return $this->tryParseArrayOrOffsetAccess($tokens, $type);
+ $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
}
- return $type;
+ return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
}
$currentTokenValue = $tokens->currentTokenValue();
$tokens->pushSavePoint(); // because of ConstFetchNode
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
- $type = new Ast\Type\IdentifierTypeNode($currentTokenValue);
+ $type = $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode($currentTokenValue), $startLine, $startIndex);
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
$tokens->dropSavePoint(); // because of ConstFetchNode
@@ -124,15 +182,22 @@ class TypeParser
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
$type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
- } elseif (in_array($type->name, ['array', 'list'], true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
- $type = $this->parseArrayShape($tokens, $type, $type->name);
+ } elseif (in_array($type->name, ['array', 'list', 'object'], true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
+ if ($type->name === 'object') {
+ $type = $this->parseObjectShape($tokens);
+ } else {
+ $type = $this->parseArrayShape($tokens, $type, $type->name);
+ }
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
- $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
+ $type = $this->tryParseArrayOrOffsetAccess(
+ $tokens,
+ $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex)
+ );
}
}
- return $type;
+ return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
} else {
$tokens->rollback(); // because of ConstFetchNode
}
@@ -144,7 +209,9 @@ class TypeParser
$tokens->currentTokenValue(),
$tokens->currentTokenType(),
$tokens->currentTokenOffset(),
- Lexer::TOKEN_IDENTIFIER
+ Lexer::TOKEN_IDENTIFIER,
+ null,
+ $tokens->currentTokenLine()
);
if ($this->constExprParser === null) {
@@ -157,7 +224,7 @@ class TypeParser
throw $exception;
}
- return new Ast\Type\ConstTypeNode($constExpr);
+ return $this->enrichWithAttributes($tokens, new Ast\Type\ConstTypeNode($constExpr), $startLine, $startIndex);
} catch (LogicException $e) {
throw $exception;
}
@@ -336,7 +403,14 @@ class TypeParser
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) {
// trailing comma case
- return new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances);
+ $type = new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances);
+ $startLine = $baseType->getAttribute(Ast\Attribute::START_LINE);
+ $startIndex = $baseType->getAttribute(Ast\Attribute::START_INDEX);
+ if ($startLine !== null && $startIndex !== null) {
+ $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
+ }
+
+ return $type;
}
[$genericTypes[], $variances[]] = $this->parseGenericTypeArgument($tokens);
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
@@ -345,7 +419,14 @@ class TypeParser
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
- return new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances);
+ $type = new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances);
+ $startLine = $baseType->getAttribute(Ast\Attribute::START_LINE);
+ $startIndex = $baseType->getAttribute(Ast\Attribute::START_INDEX);
+ if ($startLine !== null && $startIndex !== null) {
+ $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
+ }
+
+ return $type;
}
@@ -355,9 +436,11 @@ class TypeParser
*/
public function parseGenericTypeArgument(TokenIterator $tokens): array
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) {
return [
- new Ast\Type\IdentifierTypeNode('mixed'),
+ $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode('mixed'), $startLine, $startIndex),
Ast\Type\GenericTypeNode::VARIANCE_BIVARIANT,
];
}
@@ -397,7 +480,10 @@ class TypeParser
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
$tokens->consumeTokenType(Lexer::TOKEN_COLON);
- $returnType = $this->parseCallableReturnType($tokens);
+
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+ $returnType = $this->enrichWithAttributes($tokens, $this->parseCallableReturnType($tokens), $startLine, $startIndex);
return new Ast\Type\CallableTypeNode($identifier, $parameters, $returnType);
}
@@ -406,6 +492,8 @@ class TypeParser
/** @phpstan-impure */
private function parseCallableParameter(TokenIterator $tokens): Ast\Type\CallableTypeParameterNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
$type = $this->parse($tokens);
$isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
$isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
@@ -419,37 +507,141 @@ class TypeParser
}
$isOptional = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
- return new Ast\Type\CallableTypeParameterNode($type, $isReference, $isVariadic, $parameterName, $isOptional);
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\Type\CallableTypeParameterNode($type, $isReference, $isVariadic, $parameterName, $isOptional),
+ $startLine,
+ $startIndex
+ );
}
/** @phpstan-impure */
private function parseCallableReturnType(TokenIterator $tokens): Ast\Type\TypeNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
- $type = $this->parseNullable($tokens);
+ return $this->parseNullable($tokens);
} elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
$type = $this->parse($tokens);
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
+ if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
+ $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
+ }
+ return $type;
+ } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
+ $type = new Ast\Type\ThisTypeNode();
+ if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
+ $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ ));
+ }
+
+ return $type;
} else {
- $type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
- $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
+ $currentTokenValue = $tokens->currentTokenValue();
+ $tokens->pushSavePoint(); // because of ConstFetchNode
+ if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
+ $type = new Ast\Type\IdentifierTypeNode($currentTokenValue);
- if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
- $type = $this->parseGeneric($tokens, $type);
+ if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
+ if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
+ $type = $this->parseGeneric(
+ $tokens,
+ $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ )
+ );
+ if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
+ $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ ));
+ }
- } elseif (in_array($type->name, ['array', 'list'], true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
- $type = $this->parseArrayShape($tokens, $type, $type->name);
+ } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
+ $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ ));
+
+ } elseif (in_array($type->name, ['array', 'list', 'object'], true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
+ if ($type->name === 'object') {
+ $type = $this->parseObjectShape($tokens);
+ } else {
+ $type = $this->parseArrayShape($tokens, $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ ), $type->name);
+ }
+
+ if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
+ $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ ));
+ }
+ }
+
+ return $type;
+ } else {
+ $tokens->rollback(); // because of ConstFetchNode
+ }
+ } else {
+ $tokens->dropSavePoint(); // because of ConstFetchNode
}
}
- if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
- $type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
+ $exception = new ParserException(
+ $tokens->currentTokenValue(),
+ $tokens->currentTokenType(),
+ $tokens->currentTokenOffset(),
+ Lexer::TOKEN_IDENTIFIER,
+ null,
+ $tokens->currentTokenLine()
+ );
+
+ if ($this->constExprParser === null) {
+ throw $exception;
}
- return $type;
+ try {
+ $constExpr = $this->constExprParser->parse($tokens, true);
+ if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) {
+ throw $exception;
+ }
+
+ $type = new Ast\Type\ConstTypeNode($constExpr);
+ if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
+ $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ ));
+ }
+
+ return $type;
+ } catch (LogicException $e) {
+ throw $exception;
+ }
}
@@ -473,6 +665,8 @@ class TypeParser
/** @phpstan-impure */
private function tryParseArrayOrOffsetAccess(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
{
+ $startLine = $type->getAttribute(Ast\Attribute::START_LINE);
+ $startIndex = $type->getAttribute(Ast\Attribute::START_INDEX);
try {
while ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
$tokens->pushSavePoint();
@@ -485,10 +679,28 @@ class TypeParser
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
$tokens->dropSavePoint();
$type = new Ast\Type\OffsetAccessTypeNode($type, $offset);
+
+ if ($startLine !== null && $startIndex !== null) {
+ $type = $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ );
+ }
} else {
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
$tokens->dropSavePoint();
$type = new Ast\Type\ArrayTypeNode($type);
+
+ if ($startLine !== null && $startIndex !== null) {
+ $type = $this->enrichWithAttributes(
+ $tokens,
+ $type,
+ $startLine,
+ $startIndex
+ );
+ }
}
}
@@ -539,6 +751,8 @@ class TypeParser
/** @phpstan-impure */
private function parseArrayShapeItem(TokenIterator $tokens): Ast\Type\ArrayShapeItemNode
{
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
try {
$tokens->pushSavePoint();
$key = $this->parseArrayShapeKey($tokens);
@@ -547,12 +761,22 @@ class TypeParser
$value = $this->parse($tokens);
$tokens->dropSavePoint();
- return new Ast\Type\ArrayShapeItemNode($key, $optional, $value);
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\Type\ArrayShapeItemNode($key, $optional, $value),
+ $startLine,
+ $startIndex
+ );
} catch (ParserException $e) {
$tokens->rollback();
$value = $this->parse($tokens);
- return new Ast\Type\ArrayShapeItemNode(null, false, $value);
+ return $this->enrichWithAttributes(
+ $tokens,
+ new Ast\Type\ArrayShapeItemNode(null, false, $value),
+ $startLine,
+ $startIndex
+ );
}
}
@@ -562,16 +786,28 @@ class TypeParser
*/
private function parseArrayShapeKey(TokenIterator $tokens)
{
+ $startIndex = $tokens->currentTokenIndex();
+ $startLine = $tokens->currentTokenLine();
+
if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
- $key = new Ast\ConstExpr\ConstExprIntegerNode($tokens->currentTokenValue());
+ $key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue()));
$tokens->next();
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
- $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'"));
+ if ($this->quoteAwareConstExprString) {
+ $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED);
+ } else {
+ $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'"));
+ }
$tokens->next();
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
- $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"'));
+ if ($this->quoteAwareConstExprString) {
+ $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED);
+ } else {
+ $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"'));
+ }
+
$tokens->next();
} else {
@@ -579,7 +815,86 @@ class TypeParser
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
}
- return $key;
+ return $this->enrichWithAttributes(
+ $tokens,
+ $key,
+ $startLine,
+ $startIndex
+ );
+ }
+
+ /**
+ * @phpstan-impure
+ */
+ private function parseObjectShape(TokenIterator $tokens): Ast\Type\ObjectShapeNode
+ {
+ $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET);
+
+ $items = [];
+
+ do {
+ $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
+
+ if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) {
+ return new Ast\Type\ObjectShapeNode($items);
+ }
+
+ $items[] = $this->parseObjectShapeItem($tokens);
+
+ $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
+ } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
+
+ $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
+ $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET);
+
+ return new Ast\Type\ObjectShapeNode($items);
+ }
+
+ /** @phpstan-impure */
+ private function parseObjectShapeItem(TokenIterator $tokens): Ast\Type\ObjectShapeItemNode
+ {
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+
+ $key = $this->parseObjectShapeKey($tokens);
+ $optional = $tokens->tryConsumeTokenType(Lexer::TOKEN_NULLABLE);
+ $tokens->consumeTokenType(Lexer::TOKEN_COLON);
+ $value = $this->parse($tokens);
+
+ return $this->enrichWithAttributes($tokens, new Ast\Type\ObjectShapeItemNode($key, $optional, $value), $startLine, $startIndex);
+ }
+
+ /**
+ * @phpstan-impure
+ * @return Ast\ConstExpr\ConstExprStringNode|Ast\Type\IdentifierTypeNode
+ */
+ private function parseObjectShapeKey(TokenIterator $tokens)
+ {
+ $startLine = $tokens->currentTokenLine();
+ $startIndex = $tokens->currentTokenIndex();
+
+ if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
+ if ($this->quoteAwareConstExprString) {
+ $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED);
+ } else {
+ $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'"));
+ }
+ $tokens->next();
+
+ } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
+ if ($this->quoteAwareConstExprString) {
+ $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED);
+ } else {
+ $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"'));
+ }
+ $tokens->next();
+
+ } else {
+ $key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
+ $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
+ }
+
+ return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex);
}
}
diff --git a/vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php b/vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php
new file mode 100644
index 00000000..2684dfc7
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php
@@ -0,0 +1,44 @@
+type = $type;
+ $this->old = $old;
+ $this->new = $new;
+ }
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Printer/Differ.php b/vendor/phpstan/phpdoc-parser/src/Printer/Differ.php
new file mode 100644
index 00000000..ab10be59
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Printer/Differ.php
@@ -0,0 +1,196 @@
+isEqual = $isEqual;
+ }
+
+ /**
+ * Calculate diff (edit script) from $old to $new.
+ *
+ * @param T[] $old Original array
+ * @param T[] $new New array
+ *
+ * @return DiffElem[] Diff (edit script)
+ */
+ public function diff(array $old, array $new): array
+ {
+ [$trace, $x, $y] = $this->calculateTrace($old, $new);
+ return $this->extractDiff($trace, $x, $y, $old, $new);
+ }
+
+ /**
+ * Calculate diff, including "replace" operations.
+ *
+ * If a sequence of remove operations is followed by the same number of add operations, these
+ * will be coalesced into replace operations.
+ *
+ * @param T[] $old Original array
+ * @param T[] $new New array
+ *
+ * @return DiffElem[] Diff (edit script), including replace operations
+ */
+ public function diffWithReplacements(array $old, array $new): array
+ {
+ return $this->coalesceReplacements($this->diff($old, $new));
+ }
+
+ /**
+ * @param T[] $old
+ * @param T[] $new
+ * @return array{array>, int, int}
+ */
+ private function calculateTrace(array $old, array $new): array
+ {
+ $n = count($old);
+ $m = count($new);
+ $max = $n + $m;
+ $v = [1 => 0];
+ $trace = [];
+ for ($d = 0; $d <= $max; $d++) {
+ $trace[] = $v;
+ for ($k = -$d; $k <= $d; $k += 2) {
+ if ($k === -$d || ($k !== $d && $v[$k - 1] < $v[$k + 1])) {
+ $x = $v[$k + 1];
+ } else {
+ $x = $v[$k - 1] + 1;
+ }
+
+ $y = $x - $k;
+ while ($x < $n && $y < $m && ($this->isEqual)($old[$x], $new[$y])) {
+ $x++;
+ $y++;
+ }
+
+ $v[$k] = $x;
+ if ($x >= $n && $y >= $m) {
+ return [$trace, $x, $y];
+ }
+ }
+ }
+ throw new Exception('Should not happen');
+ }
+
+ /**
+ * @param array> $trace
+ * @param T[] $old
+ * @param T[] $new
+ * @return DiffElem[]
+ */
+ private function extractDiff(array $trace, int $x, int $y, array $old, array $new): array
+ {
+ $result = [];
+ for ($d = count($trace) - 1; $d >= 0; $d--) {
+ $v = $trace[$d];
+ $k = $x - $y;
+
+ if ($k === -$d || ($k !== $d && $v[$k - 1] < $v[$k + 1])) {
+ $prevK = $k + 1;
+ } else {
+ $prevK = $k - 1;
+ }
+
+ $prevX = $v[$prevK];
+ $prevY = $prevX - $prevK;
+
+ while ($x > $prevX && $y > $prevY) {
+ $result[] = new DiffElem(DiffElem::TYPE_KEEP, $old[$x - 1], $new[$y - 1]);
+ $x--;
+ $y--;
+ }
+
+ if ($d === 0) {
+ break;
+ }
+
+ while ($x > $prevX) {
+ $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $old[$x - 1], null);
+ $x--;
+ }
+
+ while ($y > $prevY) {
+ $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $new[$y - 1]);
+ $y--;
+ }
+ }
+ return array_reverse($result);
+ }
+
+ /**
+ * Coalesce equal-length sequences of remove+add into a replace operation.
+ *
+ * @param DiffElem[] $diff
+ * @return DiffElem[]
+ */
+ private function coalesceReplacements(array $diff): array
+ {
+ $newDiff = [];
+ $c = count($diff);
+ for ($i = 0; $i < $c; $i++) {
+ $diffType = $diff[$i]->type;
+ if ($diffType !== DiffElem::TYPE_REMOVE) {
+ $newDiff[] = $diff[$i];
+ continue;
+ }
+
+ $j = $i;
+ while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) {
+ $j++;
+ }
+
+ $k = $j;
+ while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) {
+ $k++;
+ }
+
+ if ($j - $i === $k - $j) {
+ $len = $j - $i;
+ for ($n = 0; $n < $len; $n++) {
+ $newDiff[] = new DiffElem(
+ DiffElem::TYPE_REPLACE,
+ $diff[$i + $n]->old,
+ $diff[$j + $n]->new
+ );
+ }
+ } else {
+ for (; $i < $k; $i++) {
+ $newDiff[] = $diff[$i];
+ }
+ }
+ $i = $k - 1;
+ }
+ return $newDiff;
+ }
+
+}
diff --git a/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php b/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php
new file mode 100644
index 00000000..bc07d10c
--- /dev/null
+++ b/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php
@@ -0,0 +1,796 @@
+ */
+ private $differ;
+
+ /**
+ * Map From "{$class}->{$subNode}" to string that should be inserted
+ * between elements of this list subnode
+ *
+ * @var array
+ */
+ private $listInsertionMap = [
+ PhpDocNode::class . '->children' => "\n * ",
+ UnionTypeNode::class . '->types' => '|',
+ IntersectionTypeNode::class . '->types' => '&',
+ ArrayShapeNode::class . '->items' => ', ',
+ ObjectShapeNode::class . '->items' => ', ',
+ CallableTypeNode::class . '->parameters' => ', ',
+ GenericTypeNode::class . '->genericTypes' => ', ',
+ ConstExprArrayNode::class . '->items' => ', ',
+ MethodTagValueNode::class . '->parameters' => ', ',
+ ];
+
+ /**
+ * [$find, $extraLeft, $extraRight]
+ *
+ * @var array
+ */
+ private $emptyListInsertionMap = [
+ CallableTypeNode::class . '->parameters' => ['(', '', ''],
+ ArrayShapeNode::class . '->items' => ['{', '', ''],
+ ObjectShapeNode::class . '->items' => ['{', '', ''],
+ ];
+
+ /** @var array>> */
+ private $parenthesesMap = [
+ CallableTypeNode::class . '->returnType' => [
+ CallableTypeNode::class,
+ UnionTypeNode::class,
+ IntersectionTypeNode::class,
+ ],
+ ArrayTypeNode::class . '->type' => [
+ CallableTypeNode::class,
+ UnionTypeNode::class,
+ IntersectionTypeNode::class,
+ ConstTypeNode::class,
+ NullableTypeNode::class,
+ ],
+ OffsetAccessTypeNode::class . '->type' => [
+ CallableTypeNode::class,
+ UnionTypeNode::class,
+ IntersectionTypeNode::class,
+ ConstTypeNode::class,
+ NullableTypeNode::class,
+ ],
+ ];
+
+ /** @var array>> */
+ private $parenthesesListMap = [
+ IntersectionTypeNode::class . '->types' => [
+ IntersectionTypeNode::class,
+ UnionTypeNode::class,
+ NullableTypeNode::class,
+ ],
+ UnionTypeNode::class . '->types' => [
+ IntersectionTypeNode::class,
+ UnionTypeNode::class,
+ NullableTypeNode::class,
+ ],
+ ];
+
+ public function printFormatPreserving(PhpDocNode $node, PhpDocNode $originalNode, TokenIterator $originalTokens): string
+ {
+ $this->differ = new Differ(static function ($a, $b) {
+ if ($a instanceof Node && $b instanceof Node) {
+ return $a === $b->getAttribute(Attribute::ORIGINAL_NODE);
+ }
+
+ return false;
+ });
+
+ $tokenIndex = 0;
+ $result = $this->printArrayFormatPreserving(
+ $node->children,
+ $originalNode->children,
+ $originalTokens,
+ $tokenIndex,
+ PhpDocNode::class,
+ 'children'
+ );
+ if ($result !== null) {
+ return $result . $originalTokens->getContentBetween($tokenIndex, $originalTokens->getTokenCount());
+ }
+
+ return $this->print($node);
+ }
+
+ public function print(Node $node): string
+ {
+ if ($node instanceof PhpDocNode) {
+ return "/**\n *" . implode("\n *", array_map(
+ function (PhpDocChildNode $child): string {
+ $s = $this->print($child);
+ return $s === '' ? '' : ' ' . $s;
+ },
+ $node->children
+ )) . "\n */";
+ }
+ if ($node instanceof PhpDocTextNode) {
+ return $node->text;
+ }
+ if ($node instanceof PhpDocTagNode) {
+ return trim(sprintf('%s %s', $node->name, $this->print($node->value)));
+ }
+ if ($node instanceof PhpDocTagValueNode) {
+ return $this->printTagValue($node);
+ }
+ if ($node instanceof TypeNode) {
+ return $this->printType($node);
+ }
+ if ($node instanceof ConstExprNode) {
+ return $this->printConstExpr($node);
+ }
+ if ($node instanceof MethodTagValueParameterNode) {
+ $type = $node->type !== null ? $this->print($node->type) . ' ' : '';
+ $isReference = $node->isReference ? '&' : '';
+ $isVariadic = $node->isVariadic ? '...' : '';
+ $default = $node->defaultValue !== null ? ' = ' . $this->print($node->defaultValue) : '';
+ return "{$type}{$isReference}{$isVariadic}{$node->parameterName}{$default}";
+ }
+ if ($node instanceof CallableTypeParameterNode) {
+ $type = $this->print($node->type) . ' ';
+ $isReference = $node->isReference ? '&' : '';
+ $isVariadic = $node->isVariadic ? '...' : '';
+ $isOptional = $node->isOptional ? '=' : '';
+ return trim("{$type}{$isReference}{$isVariadic}{$node->parameterName}") . $isOptional;
+ }
+
+ throw new LogicException(sprintf('Unknown node type %s', get_class($node)));
+ }
+
+ private function printTagValue(PhpDocTagValueNode $node): string
+ {
+ // only nodes that contain another node are handled here
+ // the rest falls back on (string) $node
+
+ if ($node instanceof AssertTagMethodValueNode) {
+ $isNegated = $node->isNegated ? '!' : '';
+ $isEquality = $node->isEquality ? '=' : '';
+ $type = $this->printType($node->type);
+ return trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->method}() {$node->description}");
+ }
+ if ($node instanceof AssertTagPropertyValueNode) {
+ $isNegated = $node->isNegated ? '!' : '';
+ $isEquality = $node->isEquality ? '=' : '';
+ $type = $this->printType($node->type);
+ return trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->property} {$node->description}");
+ }
+ if ($node instanceof AssertTagValueNode) {
+ $isNegated = $node->isNegated ? '!' : '';
+ $isEquality = $node->isEquality ? '=' : '';
+ $type = $this->printType($node->type);
+ return trim("{$isNegated}{$isEquality}{$type} {$node->parameter} {$node->description}");
+ }
+ if ($node instanceof ExtendsTagValueNode || $node instanceof ImplementsTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$type} {$node->description}");
+ }
+ if ($node instanceof MethodTagValueNode) {
+ $static = $node->isStatic ? 'static ' : '';
+ $returnType = $node->returnType !== null ? $this->printType($node->returnType) . ' ' : '';
+ $parameters = implode(', ', array_map(function (MethodTagValueParameterNode $parameter): string {
+ return $this->print($parameter);
+ }, $node->parameters));
+ $description = $node->description !== '' ? " {$node->description}" : '';
+ $templateTypes = count($node->templateTypes) > 0 ? '<' . implode(', ', array_map(function (TemplateTagValueNode $templateTag): string {
+ return $this->print($templateTag);
+ }, $node->templateTypes)) . '>' : '';
+ return "{$static}{$returnType}{$node->methodName}{$templateTypes}({$parameters}){$description}";
+ }
+ if ($node instanceof MixinTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$type} {$node->description}");
+ }
+ if ($node instanceof ParamOutTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$type} {$node->parameterName} {$node->description}");
+ }
+ if ($node instanceof ParamTagValueNode) {
+ $reference = $node->isReference ? '&' : '';
+ $variadic = $node->isVariadic ? '...' : '';
+ $type = $this->printType($node->type);
+ return trim("{$type} {$reference}{$variadic}{$node->parameterName} {$node->description}");
+ }
+ if ($node instanceof PropertyTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$type} {$node->propertyName} {$node->description}");
+ }
+ if ($node instanceof ReturnTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$type} {$node->description}");
+ }
+ if ($node instanceof SelfOutTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim($type . ' ' . $node->description);
+ }
+ if ($node instanceof TemplateTagValueNode) {
+ $bound = $node->bound !== null ? ' of ' . $this->printType($node->bound) : '';
+ $default = $node->default !== null ? ' = ' . $this->printType($node->default) : '';
+ return trim("{$node->name}{$bound}{$default} {$node->description}");
+ }
+ if ($node instanceof ThrowsTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$type} {$node->description}");
+ }
+ if ($node instanceof TypeAliasImportTagValueNode) {
+ return trim(
+ "{$node->importedAlias} from " . $this->printType($node->importedFrom)
+ . ($node->importedAs !== null ? " as {$node->importedAs}" : '')
+ );
+ }
+ if ($node instanceof TypeAliasTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$node->alias} {$type}");
+ }
+ if ($node instanceof UsesTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$type} {$node->description}");
+ }
+ if ($node instanceof VarTagValueNode) {
+ $type = $this->printType($node->type);
+ return trim("{$type} " . trim("{$node->variableName} {$node->description}"));
+ }
+
+ return (string) $node;
+ }
+
+ private function printType(TypeNode $node): string
+ {
+ if ($node instanceof ArrayShapeNode) {
+ $items = array_map(function (ArrayShapeItemNode $item): string {
+ return $this->printType($item);
+ }, $node->items);
+
+ if (! $node->sealed) {
+ $items[] = '...';
+ }
+
+ return $node->kind . '{' . implode(', ', $items) . '}';
+ }
+ if ($node instanceof ArrayShapeItemNode) {
+ if ($node->keyName !== null) {
+ return sprintf(
+ '%s%s: %s',
+ $this->print($node->keyName),
+ $node->optional ? '?' : '',
+ $this->printType($node->valueType)
+ );
+ }
+
+ return $this->printType($node->valueType);
+ }
+ if ($node instanceof ArrayTypeNode) {
+ return $this->printOffsetAccessType($node->type) . '[]';
+ }
+ if ($node instanceof CallableTypeNode) {
+ if ($node->returnType instanceof CallableTypeNode || $node->returnType instanceof UnionTypeNode || $node->returnType instanceof IntersectionTypeNode) {
+ $returnType = $this->wrapInParentheses($node->returnType);
+ } else {
+ $returnType = $this->printType($node->returnType);
+ }
+ $parameters = implode(', ', array_map(function (CallableTypeParameterNode $parameterNode): string {
+ return $this->print($parameterNode);
+ }, $node->parameters));
+ return "{$node->identifier}({$parameters}): {$returnType}";
+ }
+ if ($node instanceof ConditionalTypeForParameterNode) {
+ return sprintf(
+ '(%s %s %s ? %s : %s)',
+ $node->parameterName,
+ $node->negated ? 'is not' : 'is',
+ $this->printType($node->targetType),
+ $this->printType($node->if),
+ $this->printType($node->else)
+ );
+ }
+ if ($node instanceof ConditionalTypeNode) {
+ return sprintf(
+ '(%s %s %s ? %s : %s)',
+ $this->printType($node->subjectType),
+ $node->negated ? 'is not' : 'is',
+ $this->printType($node->targetType),
+ $this->printType($node->if),
+ $this->printType($node->else)
+ );
+ }
+ if ($node instanceof ConstTypeNode) {
+ return $this->printConstExpr($node->constExpr);
+ }
+ if ($node instanceof GenericTypeNode) {
+ $genericTypes = [];
+
+ foreach ($node->genericTypes as $index => $type) {
+ $variance = $node->variances[$index] ?? GenericTypeNode::VARIANCE_INVARIANT;
+ if ($variance === GenericTypeNode::VARIANCE_INVARIANT) {
+ $genericTypes[] = $this->printType($type);
+ } elseif ($variance === GenericTypeNode::VARIANCE_BIVARIANT) {
+ $genericTypes[] = '*';
+ } else {
+ $genericTypes[] = sprintf('%s %s', $variance, $this->print($type));
+ }
+ }
+
+ return $node->type . '<' . implode(', ', $genericTypes) . '>';
+ }
+ if ($node instanceof IdentifierTypeNode) {
+ return $node->name;
+ }
+ if ($node instanceof IntersectionTypeNode || $node instanceof UnionTypeNode) {
+ $items = [];
+ foreach ($node->types as $type) {
+ if (
+ $type instanceof IntersectionTypeNode
+ || $type instanceof UnionTypeNode
+ || $type instanceof NullableTypeNode
+ ) {
+ $items[] = $this->wrapInParentheses($type);
+ continue;
+ }
+
+ $items[] = $this->printType($type);
+ }
+
+ return implode($node instanceof IntersectionTypeNode ? '&' : '|', $items);
+ }
+ if ($node instanceof InvalidTypeNode) {
+ return (string) $node;
+ }
+ if ($node instanceof NullableTypeNode) {
+ if ($node->type instanceof IntersectionTypeNode || $node->type instanceof UnionTypeNode) {
+ return '?(' . $this->printType($node->type) . ')';
+ }
+
+ return '?' . $this->printType($node->type);
+ }
+ if ($node instanceof ObjectShapeNode) {
+ $items = array_map(function (ObjectShapeItemNode $item): string {
+ return $this->printType($item);
+ }, $node->items);
+
+ return 'object{' . implode(', ', $items) . '}';
+ }
+ if ($node instanceof ObjectShapeItemNode) {
+ if ($node->keyName !== null) {
+ return sprintf(
+ '%s%s: %s',
+ $this->print($node->keyName),
+ $node->optional ? '?' : '',
+ $this->printType($node->valueType)
+ );
+ }
+
+ return $this->printType($node->valueType);
+ }
+ if ($node instanceof OffsetAccessTypeNode) {
+ return $this->printOffsetAccessType($node->type) . '[' . $this->printType($node->offset) . ']';
+ }
+ if ($node instanceof ThisTypeNode) {
+ return (string) $node;
+ }
+
+ throw new LogicException(sprintf('Unknown node type %s', get_class($node)));
+ }
+
+ private function wrapInParentheses(TypeNode $node): string
+ {
+ return '(' . $this->printType($node) . ')';
+ }
+
+ private function printOffsetAccessType(TypeNode $type): string
+ {
+ if (
+ $type instanceof CallableTypeNode
+ || $type instanceof UnionTypeNode
+ || $type instanceof IntersectionTypeNode
+ || $type instanceof ConstTypeNode
+ || $type instanceof NullableTypeNode
+ ) {
+ return $this->wrapInParentheses($type);
+ }
+
+ return $this->printType($type);
+ }
+
+ private function printConstExpr(ConstExprNode $node): string
+ {
+ // this is fine - ConstExprNode classes do not contain nodes that need smart printer logic
+ return (string) $node;
+ }
+
+ /**
+ * @param Node[] $nodes
+ * @param Node[] $originalNodes
+ */
+ private function printArrayFormatPreserving(array $nodes, array $originalNodes, TokenIterator $originalTokens, int &$tokenIndex, string $parentNodeClass, string $subNodeName): ?string
+ {
+ $diff = $this->differ->diffWithReplacements($originalNodes, $nodes);
+ $mapKey = $parentNodeClass . '->' . $subNodeName;
+ $insertStr = $this->listInsertionMap[$mapKey] ?? null;
+ $result = '';
+ $beforeFirstKeepOrReplace = true;
+ $delayedAdd = [];
+
+ $insertNewline = false;
+ [$isMultiline, $beforeAsteriskIndent, $afterAsteriskIndent] = $this->isMultiline($tokenIndex, $originalNodes, $originalTokens);
+
+ if ($insertStr === "\n * ") {
+ $insertStr = sprintf("\n%s*%s", $beforeAsteriskIndent, $afterAsteriskIndent);
+ }
+
+ foreach ($diff as $i => $diffElem) {
+ $diffType = $diffElem->type;
+ $newNode = $diffElem->new;
+ $originalNode = $diffElem->old;
+ if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) {
+ $beforeFirstKeepOrReplace = false;
+ if (!$newNode instanceof Node || !$originalNode instanceof Node) {
+ return null;
+ }
+ $itemStartPos = $originalNode->getAttribute(Attribute::START_INDEX);
+ $itemEndPos = $originalNode->getAttribute(Attribute::END_INDEX);
+ if ($itemStartPos < 0 || $itemEndPos < 0 || $itemStartPos < $tokenIndex) {
+ throw new LogicException();
+ }
+
+ $result .= $originalTokens->getContentBetween($tokenIndex, $itemStartPos);
+
+ if (count($delayedAdd) > 0) {
+ foreach ($delayedAdd as $delayedAddNode) {
+ $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey])
+ && in_array(get_class($delayedAddNode), $this->parenthesesListMap[$mapKey], true);
+ if ($parenthesesNeeded) {
+ $result .= '(';
+ }
+ $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens);
+ if ($parenthesesNeeded) {
+ $result .= ')';
+ }
+
+ if ($insertNewline) {
+ $result .= $insertStr . sprintf("\n%s*%s", $beforeAsteriskIndent, $afterAsteriskIndent);
+ } else {
+ $result .= $insertStr;
+ }
+ }
+
+ $delayedAdd = [];
+ }
+
+ $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey])
+ && in_array(get_class($newNode), $this->parenthesesListMap[$mapKey], true);
+ $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($itemStartPos, $itemEndPos);
+ if ($addParentheses) {
+ $result .= '(';
+ }
+
+ $result .= $this->printNodeFormatPreserving($newNode, $originalTokens);
+ if ($addParentheses) {
+ $result .= ')';
+ }
+ $tokenIndex = $itemEndPos + 1;
+
+ } elseif ($diffType === DiffElem::TYPE_ADD) {
+ if ($insertStr === null) {
+ return null;
+ }
+ if (!$newNode instanceof Node) {
+ return null;
+ }
+
+ if ($insertStr === ', ' && $isMultiline) {
+ $insertStr = ',';
+ $insertNewline = true;
+ }
+
+ if ($beforeFirstKeepOrReplace) {
+ // Will be inserted at the next "replace" or "keep" element
+ $delayedAdd[] = $newNode;
+ continue;
+ }
+
+ $itemEndPos = $tokenIndex - 1;
+ if ($insertNewline) {
+ $result .= $insertStr . sprintf("\n%s*%s", $beforeAsteriskIndent, $afterAsteriskIndent);
+ } else {
+ $result .= $insertStr;
+ }
+
+ $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey])
+ && in_array(get_class($newNode), $this->parenthesesListMap[$mapKey], true);
+ if ($parenthesesNeeded) {
+ $result .= '(';
+ }
+
+ $result .= $this->printNodeFormatPreserving($newNode, $originalTokens);
+ if ($parenthesesNeeded) {
+ $result .= ')';
+ }
+
+ $tokenIndex = $itemEndPos + 1;
+
+ } elseif ($diffType === DiffElem::TYPE_REMOVE) {
+ if (!$originalNode instanceof Node) {
+ return null;
+ }
+
+ $itemStartPos = $originalNode->getAttribute(Attribute::START_INDEX);
+ $itemEndPos = $originalNode->getAttribute(Attribute::END_INDEX);
+ if ($itemStartPos < 0 || $itemEndPos < 0) {
+ throw new LogicException();
+ }
+
+ if ($i === 0) {
+ // If we're removing from the start, keep the tokens before the node and drop those after it,
+ // instead of the other way around.
+ $originalTokensArray = $originalTokens->getTokens();
+ for ($j = $tokenIndex; $j < $itemStartPos; $j++) {
+ if ($originalTokensArray[$j][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) {
+ break;
+ }
+ $result .= $originalTokensArray[$j][Lexer::VALUE_OFFSET];
+ }
+ }
+
+ $tokenIndex = $itemEndPos + 1;
+ }
+ }
+
+ if (count($delayedAdd) > 0) {
+ if (!isset($this->emptyListInsertionMap[$mapKey])) {
+ return null;
+ }
+
+ [$findToken, $extraLeft, $extraRight] = $this->emptyListInsertionMap[$mapKey];
+ if ($findToken !== null) {
+ $originalTokensArray = $originalTokens->getTokens();
+ for (; $tokenIndex < count($originalTokensArray); $tokenIndex++) {
+ $result .= $originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET];
+ if ($originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET] !== $findToken) {
+ continue;
+ }
+
+ $tokenIndex++;
+ break;
+ }
+ }
+ $first = true;
+ $result .= $extraLeft;
+ foreach ($delayedAdd as $delayedAddNode) {
+ if (!$first) {
+ $result .= $insertStr;
+ if ($insertNewline) {
+ $result .= sprintf("\n%s*%s", $beforeAsteriskIndent, $afterAsteriskIndent);
+ }
+ }
+
+ $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens);
+ $first = false;
+ }
+ $result .= $extraRight;
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param Node[] $nodes
+ * @return array{bool, string, string}
+ */
+ private function isMultiline(int $initialIndex, array $nodes, TokenIterator $originalTokens): array
+ {
+ $isMultiline = count($nodes) > 1;
+ $pos = $initialIndex;
+ $allText = '';
+ /** @var Node|null $node */
+ foreach ($nodes as $node) {
+ if (!$node instanceof Node) {
+ continue;
+ }
+
+ $endPos = $node->getAttribute(Attribute::END_INDEX) + 1;
+ $text = $originalTokens->getContentBetween($pos, $endPos);
+ $allText .= $text;
+ if (strpos($text, "\n") === false) {
+ // We require that a newline is present between *every* item. If the formatting
+ // is inconsistent, with only some items having newlines, we don't consider it
+ // as multiline
+ $isMultiline = false;
+ }
+ $pos = $endPos;
+ }
+
+ $c = preg_match_all('~\n(?[\\x09\\x20]*)\*(?\\x20*)~', $allText, $matches, PREG_SET_ORDER);
+ if ($c === 0) {
+ return [$isMultiline, '', ''];
+ }
+
+ $before = '';
+ $after = '';
+ foreach ($matches as $match) {
+ if (strlen($match['before']) > strlen($before)) {
+ $before = $match['before'];
+ }
+ if (strlen($match['after']) <= strlen($after)) {
+ continue;
+ }
+
+ $after = $match['after'];
+ }
+
+ return [$isMultiline, $before, $after];
+ }
+
+ private function printNodeFormatPreserving(Node $node, TokenIterator $originalTokens): string
+ {
+ /** @var Node|null $originalNode */
+ $originalNode = $node->getAttribute(Attribute::ORIGINAL_NODE);
+ if ($originalNode === null) {
+ return $this->print($node);
+ }
+
+ $class = get_class($node);
+ if ($class !== get_class($originalNode)) {
+ throw new LogicException();
+ }
+
+ $startPos = $originalNode->getAttribute(Attribute::START_INDEX);
+ $endPos = $originalNode->getAttribute(Attribute::END_INDEX);
+ if ($startPos < 0 || $endPos < 0) {
+ throw new LogicException();
+ }
+
+ $result = '';
+ $pos = $startPos;
+ $subNodeNames = array_keys(get_object_vars($node));
+ foreach ($subNodeNames as $subNodeName) {
+ $subNode = $node->$subNodeName;
+ $origSubNode = $originalNode->$subNodeName;
+
+ if (
+ (!$subNode instanceof Node && $subNode !== null)
+ || (!$origSubNode instanceof Node && $origSubNode !== null)
+ ) {
+ if ($subNode === $origSubNode) {
+ // Unchanged, can reuse old code
+ continue;
+ }
+
+ if (is_array($subNode) && is_array($origSubNode)) {
+ // Array subnode changed, we might be able to reconstruct it
+ $listResult = $this->printArrayFormatPreserving(
+ $subNode,
+ $origSubNode,
+ $originalTokens,
+ $pos,
+ $class,
+ $subNodeName
+ );
+
+ if ($listResult === null) {
+ return $this->print($node);
+ }
+
+ $result .= $listResult;
+ continue;
+ }
+
+ return $this->print($node);
+ }
+
+ if ($origSubNode === null) {
+ if ($subNode === null) {
+ // Both null, nothing to do
+ continue;
+ }
+
+ return $this->print($node);
+ }
+
+ $subStartPos = $origSubNode->getAttribute(Attribute::START_INDEX);
+ $subEndPos = $origSubNode->getAttribute(Attribute::END_INDEX);
+ if ($subStartPos < 0 || $subEndPos < 0) {
+ throw new LogicException();
+ }
+
+ if ($subNode === null) {
+ return $this->print($node);
+ }
+
+ $result .= $originalTokens->getContentBetween($pos, $subStartPos);
+ $mapKey = get_class($node) . '->' . $subNodeName;
+ $parenthesesNeeded = isset($this->parenthesesMap[$mapKey])
+ && in_array(get_class($subNode), $this->parenthesesMap[$mapKey], true);
+ $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($subStartPos, $subEndPos);
+ if ($addParentheses) {
+ $result .= '(';
+ }
+
+ $result .= $this->printNodeFormatPreserving($subNode, $originalTokens);
+ if ($addParentheses) {
+ $result .= ')';
+ }
+
+ $pos = $subEndPos + 1;
+ }
+
+ return $result . $originalTokens->getContentBetween($pos, $endPos + 1);
+ }
+
+}
diff --git a/vendor/phpstan/phpstan/bootstrap.php b/vendor/phpstan/phpstan/bootstrap.php
index 204221a3..1537f3f1 100644
--- a/vendor/phpstan/phpstan/bootstrap.php
+++ b/vendor/phpstan/phpstan/bootstrap.php
@@ -23,7 +23,6 @@ final class PharAutoloader
self::$composerAutoloader = require 'phar://' . __DIR__ . '/phpstan.phar/vendor/autoload.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/async/src/functions_include.php';
- require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise-stream/src/functions_include.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise-timer/src/functions_include.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise/src/functions_include.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/ringcentral/psr7/src/functions_include.php';
diff --git a/vendor/phpstan/phpstan/phpstan.phar b/vendor/phpstan/phpstan/phpstan.phar
index 947d5ab0..3f043c71 100755
Binary files a/vendor/phpstan/phpstan/phpstan.phar and b/vendor/phpstan/phpstan/phpstan.phar differ
diff --git a/vendor/phpstan/phpstan/phpstan.phar.asc b/vendor/phpstan/phpstan/phpstan.phar.asc
index 7d0dcea9..3c34229a 100644
--- a/vendor/phpstan/phpstan/phpstan.phar.asc
+++ b/vendor/phpstan/phpstan/phpstan.phar.asc
@@ -1,16 +1,16 @@
-----BEGIN PGP SIGNATURE-----
-iQIzBAABCgAdFiEEynwsejDI6OEnSoR2UcZzBf/C5cAFAmQdeygACgkQUcZzBf/C
-5cAe5Q//YDKPvVm4HlLT90M/Ov0IJ8brPP6LN0fbMV93TJlXFhh6Ph79YUwxRWve
-FPYr93HDCSOdlg3q3xRNgPcUim5+7U5xf5ze5RWIBR07IDY5+i9Os66CLRALlO4u
-ToXHCO2k0hw26sSskRXmF2IrNIibvPjVjR+ephFGFenWI0S7vq5cYGqOnzwdURyu
-ZNIswHWQsJSGLn4AXfDnushBCy3w5IsSgnENIWD7L9a37A45kek+iHETcX1OLTOd
-AlJOvQ0l2OAE4kMx8tailGYtJo9yLnjtSLw6xQbdw5mf47iapm1U09C52XvYsZg4
-oZNCJ8QFHR1YbbLpdMxPFcMQgbVLGKBwHYcpsi2VdMKdR+7altlF9govkvBLxxm7
-Polq9ya0fS7wAJP0vMESGeP6UJi68DMWH7hxJ7d9tyBieYJHSpm5q5QSYjj4RxM5
-LiTTv9ug8DFIsLJiw1CplE4pxtJ82arXBqggpqO15MRNxwzyJmY7XIHtEZI2dl+d
-BImd5bWl6nCkhKEYPs+6SEt/caXIz/XERap5gO9Q8UBx5jaKPHEKRbuvTgbW1Ods
-fFNDgIsQyg+56LzIxgp2a6IUVeeQSrL4kjeHYQDBMzG0P78ZXjXdUl3kYG3TJHmb
-QNWgYcz3jJJd/F5YSMPpAPT/gpcD4FBnHZ+mlLnGvXvuuGh+MyU=
-=vW1l
+iQIzBAABCgAdFiEEynwsejDI6OEnSoR2UcZzBf/C5cAFAmRaZmcACgkQUcZzBf/C
+5cAn/Q//fbWiR/qaSvlHpk73KH7iDfoHwNvRrHSQODZdMa4PGiEbL+SXsKnRxFDo
+kEJZwgU5qi3WMflt7Ml3dYDlQDgoDerdaiySYFoBcv1NXDWKoF7+Egy1AHxpfNq+
+FMCkZNR2ulSaYUCofM4GkTNap4yVkPCy289ZU6yUmRnJxF+hh/CFfdVPAPbwh/a6
+UqV3R2ENJZSbtA1pzSTBpUPQGQ9qcsqngKyNyxk1hEd9opdMg2eSFvO1e1ZZm/Tk
+Kgh5wCbsbSJuRPGO4vbiybTeO/qXPDlHV6oA5SHnjJ4H24phCsHdyJHHvLQmrUeR
+BKHgnH1y/b5J9cgr9OgEQJK9TMHHd6dii9//Qp+0rUZIDZ4Ym2lDSA/Vn/D9GoV3
+zo4QYzW3TvE3QMdnLcX/ZtaLliPdDYIaYUXOiyaYwLFGVxSWZWOC5IN0G0bLJb39
+Ca/z839nkWdMqg68q/oHC2Nk/v/KZnKg1RlRjYhj53T6nr0JDEiaYMyETSOIFsVX
+AcCQnLLwMndUAibJAyORDnTk+ipg0SecFoPvvhea1BtlTfhSDIlrT4OPKZ5nExzd
+nR/zGbIH8lCvsBc+hq+Kgodtfs5nauwEOwlVUwet26xL1YKOd0jxz+Zp6tgk0wba
+cMf5L9fm85j83DQYr7Ukaaj81kmMujRWDo/dRojKhUlJUrNnjXA=
+=jTtX
-----END PGP SIGNATURE-----
diff --git a/vendor/sebastian/diff/ChangeLog.md b/vendor/sebastian/diff/ChangeLog.md
index ab8640c8..9142e50f 100644
--- a/vendor/sebastian/diff/ChangeLog.md
+++ b/vendor/sebastian/diff/ChangeLog.md
@@ -2,6 +2,18 @@
All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
+## [5.0.3] - 2023-05-01
+
+### Changed
+
+* [#119](https://github.com/sebastianbergmann/diff/pull/119): Improve performance of `TimeEfficientLongestCommonSubsequenceCalculator`
+
+## [5.0.2] - 2023-05-01
+
+### Changed
+
+* [#118](https://github.com/sebastianbergmann/diff/pull/118): Improve performance of `MemoryEfficientLongestCommonSubsequenceCalculator`
+
## [5.0.1] - 2023-03-23
### Fixed
@@ -92,6 +104,8 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt
* This component is no longer supported on PHP 5.6
+[5.0.3]: https://github.com/sebastianbergmann/diff/compare/5.0.2...5.0.3
+[5.0.2]: https://github.com/sebastianbergmann/diff/compare/5.0.1...5.0.2
[5.0.1]: https://github.com/sebastianbergmann/diff/compare/5.0.0...5.0.1
[5.0.0]: https://github.com/sebastianbergmann/diff/compare/4.0.4...5.0.0
[4.0.4]: https://github.com/sebastianbergmann/diff/compare/4.0.3...4.0.4
diff --git a/vendor/sebastian/diff/README.md b/vendor/sebastian/diff/README.md
index 3e84a35b..539dc59e 100644
--- a/vendor/sebastian/diff/README.md
+++ b/vendor/sebastian/diff/README.md
@@ -202,3 +202,5 @@ The code above yields the output below:
)
)
)
+
+Note: If the chunk size is 0 lines, i.e., `getStartRange()` or `getEndRange()` return 0, the number of line returned by `getStart()` or `getEnd()` is one lower than one would expect. It is the line number after which the chunk should be inserted or deleted; in all other cases, it gives the first line number of the replaced range of lines.
diff --git a/vendor/sebastian/diff/SECURITY.md b/vendor/sebastian/diff/SECURITY.md
index 778f018b..d88ff001 100644
--- a/vendor/sebastian/diff/SECURITY.md
+++ b/vendor/sebastian/diff/SECURITY.md
@@ -4,7 +4,7 @@ If you believe you have found a security vulnerability in the library that is de
**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**
-Instead, please send an email to `sebastian@phpunit.de`.
+Instead, please email `sebastian@phpunit.de`.
Please include as much of the information listed below as you can to help us better understand and resolve the issue:
@@ -22,9 +22,9 @@ This information will help us triage your report more quickly.
The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit.
-The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in a HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes.
+The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes.
If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context.
-Vulnerabilities specific to the use outside of a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes.
+Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes.
diff --git a/vendor/sebastian/diff/src/Differ.php b/vendor/sebastian/diff/src/Differ.php
index edf2dcc4..19ccf97c 100644
--- a/vendor/sebastian/diff/src/Differ.php
+++ b/vendor/sebastian/diff/src/Differ.php
@@ -30,14 +30,10 @@ use SebastianBergmann\Diff\Output\DiffOutputBuilderInterface;
final class Differ
{
- public const OLD = 0;
-
- public const ADDED = 1;
-
- public const REMOVED = 2;
-
- public const DIFF_LINE_END_WARNING = 3;
-
+ public const OLD = 0;
+ public const ADDED = 1;
+ public const REMOVED = 2;
+ public const DIFF_LINE_END_WARNING = 3;
public const NO_LINE_END_EOF_WARNING = 4;
private DiffOutputBuilderInterface $outputBuilder;
diff --git a/vendor/sebastian/diff/src/Line.php b/vendor/sebastian/diff/src/Line.php
index ecb2f794..a9106a25 100644
--- a/vendor/sebastian/diff/src/Line.php
+++ b/vendor/sebastian/diff/src/Line.php
@@ -11,10 +11,8 @@ namespace SebastianBergmann\Diff;
final class Line
{
- public const ADDED = 1;
-
- public const REMOVED = 2;
-
+ public const ADDED = 1;
+ public const REMOVED = 2;
public const UNCHANGED = 3;
private int $type;
private string $content;
diff --git a/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php b/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php
index dde08027..a46de07d 100644
--- a/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php
+++ b/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php
@@ -78,7 +78,12 @@ final class MemoryEfficientLongestCommonSubsequenceCalculator implements Longest
if ($from[$i] === $to[$j]) {
$current[$j + 1] = $prev[$j] + 1;
} else {
- $current[$j + 1] = max($current[$j], $prev[$j + 1]);
+ // don't use max() to avoid function call overhead
+ if ($current[$j] > $prev[$j + 1]) {
+ $current[$j + 1] = $current[$j];
+ } else {
+ $current[$j + 1] = $prev[$j + 1];
+ }
}
}
}
diff --git a/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php b/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php
index 51bac1f1..93b76288 100644
--- a/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php
+++ b/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php
@@ -37,12 +37,24 @@ final class TimeEfficientLongestCommonSubsequenceCalculator implements LongestCo
for ($i = 1; $i <= $fromLength; $i++) {
for ($j = 1; $j <= $toLength; $j++) {
- $o = ($j * $width) + $i;
- $matrix[$o] = max(
- $matrix[$o - 1],
- $matrix[$o - $width],
- $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0
- );
+ $o = ($j * $width) + $i;
+
+ // don't use max() to avoid function call overhead
+ $firstOrLast = $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0;
+
+ if ($matrix[$o - 1] > $matrix[$o - $width]) {
+ if ($firstOrLast > $matrix[$o - 1]) {
+ $matrix[$o] = $firstOrLast;
+ } else {
+ $matrix[$o] = $matrix[$o - 1];
+ }
+ } else {
+ if ($firstOrLast > $matrix[$o - $width]) {
+ $matrix[$o] = $firstOrLast;
+ } else {
+ $matrix[$o] = $matrix[$o - $width];
+ }
+ }
}
}
diff --git a/vendor/spatie/array-to-xml/CHANGELOG.md b/vendor/spatie/array-to-xml/CHANGELOG.md
index d43177a4..0a086699 100755
--- a/vendor/spatie/array-to-xml/CHANGELOG.md
+++ b/vendor/spatie/array-to-xml/CHANGELOG.md
@@ -2,6 +2,23 @@
All notable changes to `array-to-xml` will be documented in this file
+## 3.1.5 - 2022-12-24
+
+### What's Changed
+
+- Add Dependabot Automation by @patinthehat in https://github.com/spatie/array-to-xml/pull/196
+- Bump actions/checkout from 2 to 3 by @dependabot in https://github.com/spatie/array-to-xml/pull/197
+- Fix PHP version by @parallels999 in https://github.com/spatie/array-to-xml/pull/198
+- fix deprecated `passing null as string type` by @trin4ik in https://github.com/spatie/array-to-xml/pull/204
+
+### New Contributors
+
+- @dependabot made their first contribution in https://github.com/spatie/array-to-xml/pull/197
+- @parallels999 made their first contribution in https://github.com/spatie/array-to-xml/pull/198
+- @trin4ik made their first contribution in https://github.com/spatie/array-to-xml/pull/204
+
+**Full Changelog**: https://github.com/spatie/array-to-xml/compare/3.1.4...3.1.5
+
## 3.1.4 - 2022-11-24
### What's Changed
diff --git a/vendor/spatie/array-to-xml/README.md b/vendor/spatie/array-to-xml/README.md
index 5d4769a3..ec6a6ad8 100755
--- a/vendor/spatie/array-to-xml/README.md
+++ b/vendor/spatie/array-to-xml/README.md
@@ -1,6 +1,3 @@
-
-[
](https://supportukrainenow.org)
-
# Convert an array to xml
[](https://github.com/spatie/array-to-xml/releases)
diff --git a/vendor/spatie/array-to-xml/src/ArrayToXml.php b/vendor/spatie/array-to-xml/src/ArrayToXml.php
index e08a150d..b84bdc86 100644
--- a/vendor/spatie/array-to-xml/src/ArrayToXml.php
+++ b/vendor/spatie/array-to-xml/src/ArrayToXml.php
@@ -24,7 +24,8 @@ class ArrayToXml
string | null $xmlEncoding = null,
string $xmlVersion = '1.0',
array $domProperties = [],
- bool | null $xmlStandalone = null
+ bool | null $xmlStandalone = null,
+ bool $addXmlDeclaration = true
) {
$this->document = new DOMDocument($xmlVersion, $xmlEncoding ?? '');
@@ -36,6 +37,8 @@ class ArrayToXml
$this->setDomProperties($domProperties);
}
+ $this->addXmlDeclaration = $addXmlDeclaration;
+
$this->replaceSpacesByUnderScoresInKeyNames = $replaceSpacesByUnderScoresInKeyNames;
if (! empty($array) && $this->isArrayAllKeySequential($array)) {
@@ -61,7 +64,8 @@ class ArrayToXml
string $xmlEncoding = null,
string $xmlVersion = '1.0',
array $domProperties = [],
- bool $xmlStandalone = null
+ bool $xmlStandalone = null,
+ bool $addXmlDeclaration = true,
): string {
$converter = new static(
$array,
@@ -70,7 +74,8 @@ class ArrayToXml
$xmlEncoding,
$xmlVersion,
$domProperties,
- $xmlStandalone
+ $xmlStandalone,
+ $addXmlDeclaration
);
return $converter->toXml();
@@ -80,7 +85,7 @@ class ArrayToXml
{
return $this->addXmlDeclaration
? $this->document->saveXML()
- : $this->document->saveXml($this->document->documentElement);
+ : $this->document->saveXML($this->document->documentElement);
}
public function toDom(): DOMDocument
diff --git a/vendor/symfony/console/Command/CompleteCommand.php b/vendor/symfony/console/Command/CompleteCommand.php
index e65b334c..dbf5d7dd 100644
--- a/vendor/symfony/console/Command/CompleteCommand.php
+++ b/vendor/symfony/console/Command/CompleteCommand.php
@@ -173,10 +173,10 @@ final class CompleteCommand extends Command
throw $e;
}
- return self::FAILURE;
+ return 2;
}
- return self::SUCCESS;
+ return 0;
}
private function createCompletionInput(InputInterface $input): CompletionInput
diff --git a/vendor/symfony/console/Command/DumpCompletionCommand.php b/vendor/symfony/console/Command/DumpCompletionCommand.php
index 1ad1c0e7..cac944ec 100644
--- a/vendor/symfony/console/Command/DumpCompletionCommand.php
+++ b/vendor/symfony/console/Command/DumpCompletionCommand.php
@@ -48,14 +48,16 @@ final class DumpCompletionCommand extends Command
$shell = $this->guessShell();
[$rcFile, $completionFile] = match ($shell) {
'fish' => ['~/.config/fish/config.fish', "/etc/fish/completions/$commandName.fish"],
- 'zsh' => ['~/.zshrc', '$fpath[1]/'.$commandName],
+ 'zsh' => ['~/.zshrc', '$fpath[1]/_'.$commandName],
default => ['~/.bashrc', "/etc/bash_completion.d/$commandName"],
};
+ $supportedShells = implode(', ', $this->getSupportedShells());
+
$this
->setHelp(<<%command.name%> command dumps the shell completion script required
-to use shell autocompletion (currently, bash and fish completion is supported).
+to use shell autocompletion (currently, {$supportedShells} completion are supported).
Static installation
------------------->
@@ -94,7 +96,7 @@ EOH
if ($input->getOption('debug')) {
$this->tailDebugLog($commandName, $output);
- return self::SUCCESS;
+ return 0;
}
$shell = $input->getArgument('shell') ?? self::guessShell();
@@ -111,12 +113,12 @@ EOH
$output->writeln(sprintf('Shell not detected, Symfony shell completion only supports "%s").>', implode('", "', $supportedShells)));
}
- return self::INVALID;
+ return 2;
}
$output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, CompleteCommand::COMPLETION_API_VERSION], file_get_contents($completionFile)));
- return self::SUCCESS;
+ return 0;
}
private static function guessShell(): string
@@ -141,8 +143,19 @@ EOH
*/
private function getSupportedShells(): array
{
- return $this->supportedShells ??= array_map(function ($f) {
- return pathinfo($f, \PATHINFO_EXTENSION);
- }, glob(__DIR__.'/../Resources/completion.*'));
+ if (isset($this->supportedShells)) {
+ return $this->supportedShells;
+ }
+
+ $shells = [];
+
+ foreach (new \DirectoryIterator(__DIR__.'/../Resources/') as $file) {
+ if (str_starts_with($file->getBasename(), 'completion.') && $file->isFile()) {
+ $shells[] = $file->getExtension();
+ }
+ }
+ sort($shells);
+
+ return $this->supportedShells = $shells;
}
}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php
index 1659986e..3394c9ad 100644
--- a/vendor/symfony/console/Formatter/OutputFormatterStyle.php
+++ b/vendor/symfony/console/Formatter/OutputFormatterStyle.php
@@ -83,7 +83,8 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
public function apply(string $text): string
{
$this->handlesHrefGracefully ??= 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')
- && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100);
+ && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100)
+ && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);
if (null !== $this->href && $this->handlesHrefGracefully) {
$text = "\033]8;;$this->href\033\\$text\033]8;;\033\\";
diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php
index c345b4af..f26ca577 100644
--- a/vendor/symfony/console/Helper/QuestionHelper.php
+++ b/vendor/symfony/console/Helper/QuestionHelper.php
@@ -123,7 +123,18 @@ class QuestionHelper extends Helper
}
if (false === $ret) {
+ $isBlocked = stream_get_meta_data($inputStream)['blocked'] ?? true;
+
+ if (!$isBlocked) {
+ stream_set_blocking($inputStream, true);
+ }
+
$ret = $this->readInput($inputStream, $question);
+
+ if (!$isBlocked) {
+ stream_set_blocking($inputStream, false);
+ }
+
if (false === $ret) {
throw new MissingInputException('Aborted.');
}
@@ -496,13 +507,11 @@ class QuestionHelper extends Helper
return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r'));
}
- if (!\function_exists('exec')) {
+ if (!\function_exists('shell_exec')) {
return self::$stdinIsInteractive = true;
}
- exec('stty 2> /dev/null', $output, $status);
-
- return self::$stdinIsInteractive = 1 !== $status;
+ return self::$stdinIsInteractive = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null'));
}
/**
diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php
index 893b3192..907c9f50 100644
--- a/vendor/symfony/console/Helper/Table.php
+++ b/vendor/symfony/console/Helper/Table.php
@@ -804,7 +804,7 @@ class Table
$textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
$textLength = Helper::width($textContent);
if ($textLength > 0) {
- $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
+ $contentColumns = mb_str_split($textContent, ceil($textLength / $cell->getColspan()));
foreach ($contentColumns as $position => $content) {
$row[$i + $position] = $content;
}
diff --git a/vendor/symfony/console/Input/InputArgument.php b/vendor/symfony/console/Input/InputArgument.php
index a130c412..0e86e916 100644
--- a/vendor/symfony/console/Input/InputArgument.php
+++ b/vendor/symfony/console/Input/InputArgument.php
@@ -37,7 +37,7 @@ class InputArgument
/**
* @param string $name The argument name
- * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL
+ * @param int|null $mode The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY
* @param string $description A description text
* @param string|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only)
* @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion
diff --git a/vendor/symfony/console/Resources/completion.zsh b/vendor/symfony/console/Resources/completion.zsh
index 97a9e88c..ff76fe5f 100644
--- a/vendor/symfony/console/Resources/completion.zsh
+++ b/vendor/symfony/console/Resources/completion.zsh
@@ -1,3 +1,5 @@
+#compdef {{ COMMAND_NAME }}
+
# This file is part of the Symfony package.
#
# (c) Fabien Potencier
diff --git a/vendor/symfony/console/Terminal.php b/vendor/symfony/console/Terminal.php
index 216c609f..855f4114 100644
--- a/vendor/symfony/console/Terminal.php
+++ b/vendor/symfony/console/Terminal.php
@@ -123,20 +123,19 @@ class Terminal
return self::$stty;
}
- // skip check if exec function is disabled
- if (!\function_exists('exec')) {
+ // skip check if shell_exec function is disabled
+ if (!\function_exists('shell_exec')) {
return false;
}
- exec('stty 2>&1', $output, $exitcode);
-
- return self::$stty = 0 === $exitcode;
+ return self::$stty = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null'));
}
private static function initDimensions()
{
if ('\\' === \DIRECTORY_SEPARATOR) {
- if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) {
+ $ansicon = getenv('ANSICON');
+ if (false !== $ansicon && preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim($ansicon), $matches)) {
// extract [w, H] from "wxh (WxH)"
// or [w, h] from "wxh"
self::$width = (int) $matches[1];
@@ -216,6 +215,8 @@ class Terminal
2 => ['pipe', 'w'],
];
+ $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0;
+
$process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]);
if (!\is_resource($process)) {
return null;
@@ -226,6 +227,10 @@ class Terminal
fclose($pipes[2]);
proc_close($process);
+ if ($cp) {
+ sapi_windows_cp_set($cp);
+ }
+
return $info;
}
}
diff --git a/vendor/symfony/console/composer.json b/vendor/symfony/console/composer.json
index bafe5d16..6cc6166d 100644
--- a/vendor/symfony/console/composer.json
+++ b/vendor/symfony/console/composer.json
@@ -2,7 +2,7 @@
"name": "symfony/console",
"type": "library",
"description": "Eases the creation of beautiful and testable command line interfaces",
- "keywords": ["console", "cli", "command line", "terminal"],
+ "keywords": ["console", "cli", "command-line", "terminal"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
diff --git a/vendor/symfony/filesystem/Filesystem.php b/vendor/symfony/filesystem/Filesystem.php
index c7f3dd29..3b3cf7a1 100644
--- a/vendor/symfony/filesystem/Filesystem.php
+++ b/vendor/symfony/filesystem/Filesystem.php
@@ -161,7 +161,7 @@ class Filesystem
}
} elseif (is_dir($file)) {
if (!$isRecursive) {
- $tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-.'));
+ $tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-_'));
if (file_exists($tmpName)) {
try {
diff --git a/vendor/symfony/string/Inflector/EnglishInflector.php b/vendor/symfony/string/Inflector/EnglishInflector.php
index 4474736a..2871e4e5 100644
--- a/vendor/symfony/string/Inflector/EnglishInflector.php
+++ b/vendor/symfony/string/Inflector/EnglishInflector.php
@@ -55,6 +55,9 @@ final class EnglishInflector implements InflectorInterface
// indices (index), appendices (appendix), prices (price)
['seci', 4, false, true, ['ex', 'ix', 'ice']],
+ // codes (code)
+ ['sedoc', 5, false, true, 'code'],
+
// selfies (selfie)
['seifles', 7, true, true, 'selfie'],
@@ -64,6 +67,9 @@ final class EnglishInflector implements InflectorInterface
// movies (movie)
['seivom', 6, true, true, 'movie'],
+ // names (name)
+ ['seman', 5, true, false, 'name'],
+
// conspectuses (conspectus), prospectuses (prospectus)
['sesutcep', 8, true, true, 'pectus'],
diff --git a/vendor/vimeo/psalm/composer.json b/vendor/vimeo/psalm/composer.json
index ed857f9a..cfca1191 100644
--- a/vendor/vimeo/psalm/composer.json
+++ b/vendor/vimeo/psalm/composer.json
@@ -44,6 +44,7 @@
},
"require-dev": {
"ext-curl": "*",
+ "amphp/phpunit-util": "^2.0",
"bamarni/composer-bin-plugin": "^1.4",
"brianium/paratest": "^6.9",
"mockery/mockery": "^1.5",
diff --git a/vendor/vimeo/psalm/config.xsd b/vendor/vimeo/psalm/config.xsd
index f4302e20..4d4f377f 100644
--- a/vendor/vimeo/psalm/config.xsd
+++ b/vendor/vimeo/psalm/config.xsd
@@ -62,6 +62,7 @@
+
@@ -249,6 +250,7 @@
+
@@ -480,6 +482,7 @@
+
diff --git a/vendor/vimeo/psalm/dictionaries/CallMap.php b/vendor/vimeo/psalm/dictionaries/CallMap.php
index 2e1191c8..bb61ce41 100644
--- a/vendor/vimeo/psalm/dictionaries/CallMap.php
+++ b/vendor/vimeo/psalm/dictionaries/CallMap.php
@@ -418,9 +418,7 @@ return [
'array_uintersect_assoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable', '...rest='=>'array|callable(mixed,mixed):int'],
'array_uintersect_uassoc' => ['array', 'array'=>'array', 'rest'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int', 'key_compare_func'=>'callable(mixed,mixed):int'],
'array_uintersect_uassoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'],
-'array_unique' => ['array', 'array'=>'array', 'flags='=>'0'],
-'array_unique\'1' => ['array', 'array'=>'array', 'flags='=>'1'],
-'array_unique\'2' => ['array', 'array'=>'array', 'flags='=>'2|5'],
+'array_unique' => ['array', 'array'=>'array', 'flags='=>'int'],
'array_unshift' => ['int', '&rw_array'=>'array', '...values='=>'mixed'],
'array_values' => ['list', 'array'=>'array'],
'array_walk' => ['bool', '&rw_array'=>'array', 'callback'=>'callable', 'arg='=>'mixed'],
@@ -612,7 +610,7 @@ return [
'CallbackFilterIterator::next' => ['void'],
'CallbackFilterIterator::rewind' => ['void'],
'CallbackFilterIterator::valid' => ['bool'],
-'ceil' => ['float', 'num'=>'float'],
+'ceil' => ['float', 'num'=>'float|int'],
'chdb::__construct' => ['void', 'pathname'=>'string'],
'chdb::get' => ['string', 'key'=>'string'],
'chdb_create' => ['bool', 'pathname'=>'string', 'data'=>'array'],
@@ -1260,7 +1258,7 @@ return [
'cubrid_unbuffered_query' => ['resource', 'query'=>'string', 'conn_identifier='=>''],
'cubrid_version' => ['string'],
'curl_close' => ['void', 'handle'=>'CurlHandle'],
-'curl_copy_handle' => ['CurlHandle', 'handle'=>'CurlHandle'],
+'curl_copy_handle' => ['CurlHandle|false', 'handle'=>'CurlHandle'],
'curl_errno' => ['int', 'handle'=>'CurlHandle'],
'curl_error' => ['string', 'handle'=>'CurlHandle'],
'curl_escape' => ['string|false', 'handle'=>'CurlHandle', 'string'=>'string'],
@@ -1293,7 +1291,6 @@ return [
'curl_unescape' => ['string|false', 'handle'=>'CurlHandle', 'string'=>'string'],
'curl_version' => ['array', 'version='=>'int'],
'CURLFile::__construct' => ['void', 'filename'=>'string', 'mime_type='=>'?string', 'posted_filename='=>'?string'],
-'CURLFile::__wakeup' => ['void'],
'CURLFile::getFilename' => ['string'],
'CURLFile::getMimeType' => ['string'],
'CURLFile::getPostFilename' => ['string'],
@@ -1321,7 +1318,7 @@ return [
'date_get_last_errors' => ['array{warning_count:int,warnings:array,error_count:int,errors:array}|false'],
'date_interval_create_from_date_string' => ['DateInterval', 'datetime'=>'string'],
'date_interval_format' => ['string', 'object'=>'DateInterval', 'format'=>'string'],
-'date_isodate_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'dayOfWeek='=>'int|mixed'],
+'date_isodate_set' => ['DateTime', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'dayOfWeek='=>'int'],
'date_modify' => ['DateTime|false', 'object'=>'DateTime', 'modifier'=>'string'],
'date_offset_get' => ['int', 'object'=>'DateTimeInterface'],
'date_parse' => ['array', 'datetime'=>'string'],
@@ -1350,7 +1347,7 @@ return [
'datefmt_get_timezone_id' => ['string|false', 'formatter'=>'IntlDateFormatter'],
'datefmt_is_lenient' => ['bool', 'formatter'=>'IntlDateFormatter'],
'datefmt_localtime' => ['array|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
-'datefmt_parse' => ['int|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
+'datefmt_parse' => ['float|int|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
'datefmt_set_calendar' => ['bool', 'formatter'=>'IntlDateFormatter', 'calendar'=>'IntlCalendar|int|null'],
'datefmt_set_lenient' => ['void', 'formatter'=>'IntlDateFormatter', 'lenient'=>'bool'],
'datefmt_set_pattern' => ['bool', 'formatter'=>'IntlDateFormatter', 'pattern'=>'string'],
@@ -1463,20 +1460,20 @@ return [
'db2_tableprivileges' => [''],
'db2_tables' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'?string', 'schema='=>'?string', 'table_name='=>'?string', 'table_type='=>'?string'],
'dba_close' => ['void', 'dba'=>'resource'],
-'dba_delete' => ['bool', 'key'=>'string', 'dba'=>'resource'],
-'dba_exists' => ['bool', 'key'=>'string', 'dba'=>'resource'],
-'dba_fetch' => ['string|false', 'key'=>'string', 'skip'=>'int', 'dba'=>'resource'],
-'dba_fetch\'1' => ['string|false', 'key'=>'string', 'skip'=>'resource'],
+'dba_delete' => ['bool', 'key'=>'array|string', 'dba'=>'resource'],
+'dba_exists' => ['bool', 'key'=>'array|string', 'dba'=>'resource'],
+'dba_fetch' => ['string|false', 'key'=>'array|string', 'skip'=>'int', 'dba'=>'resource'],
+'dba_fetch\'1' => ['string|false', 'key'=>'array|string', 'skip'=>'resource'],
'dba_firstkey' => ['string', 'dba'=>'resource'],
'dba_handlers' => ['array', 'full_info='=>'bool'],
-'dba_insert' => ['bool', 'key'=>'string', 'value'=>'string', 'dba'=>'resource'],
+'dba_insert' => ['bool', 'key'=>'array|string', 'value'=>'string', 'dba'=>'resource'],
'dba_key_split' => ['array|false', 'key'=>'string|false|null'],
'dba_list' => ['array'],
'dba_nextkey' => ['string', 'dba'=>'resource'],
'dba_open' => ['resource', 'path'=>'string', 'mode'=>'string', 'handler='=>'?string', 'permission='=>'int', 'map_size='=>'int', 'flags='=>'?int'],
'dba_optimize' => ['bool', 'dba'=>'resource'],
'dba_popen' => ['resource', 'path'=>'string', 'mode'=>'string', 'handler='=>'?string', 'permission='=>'int', 'map_size='=>'int', 'flags='=>'?int'],
-'dba_replace' => ['bool', 'key'=>'string', 'value'=>'string', 'dba'=>'resource'],
+'dba_replace' => ['bool', 'key'=>'array|string', 'value'=>'string', 'dba'=>'resource'],
'dba_sync' => ['bool', 'dba'=>'resource'],
'dbase_add_record' => ['bool', 'dbase_identifier'=>'resource', 'record'=>'array'],
'dbase_close' => ['bool', 'dbase_identifier'=>'resource'],
@@ -1990,7 +1987,7 @@ return [
'Ds\Vector::sum' => ['int|float'],
'Ds\Vector::toArray' => ['array'],
'Ds\Vector::unshift' => ['void', '...values='=>'mixed'],
-'easter_date' => ['int', 'year='=>'?int'],
+'easter_date' => ['int', 'year='=>'?int', 'mode='=>'int'],
'easter_days' => ['int', 'year='=>'?int', 'mode='=>'int'],
'echo' => ['void', 'arg1'=>'string', '...args='=>'string'],
'eio_busy' => ['resource', 'delay'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'],
@@ -2882,7 +2879,7 @@ return [
'finfo_set_flags' => ['bool', 'finfo'=>'finfo', 'flags'=>'int'],
'floatval' => ['float', 'value'=>'mixed'],
'flock' => ['bool', 'stream'=>'resource', 'operation'=>'int', '&w_would_block='=>'int'],
-'floor' => ['float', 'num'=>'float'],
+'floor' => ['float', 'num'=>'float|int'],
'flush' => ['void'],
'fmod' => ['float', 'num1'=>'float', 'num2'=>'float'],
'fnmatch' => ['bool', 'pattern'=>'string', 'filename'=>'string', 'flags='=>'int'],
@@ -3159,7 +3156,6 @@ return [
'Gender\Gender::get' => ['int', 'name'=>'string', 'country='=>'int'],
'Gender\Gender::isNick' => ['array', 'name0'=>'string', 'name1'=>'string', 'country='=>'int'],
'Gender\Gender::similarNames' => ['array', 'name'=>'string', 'country='=>'int'],
-'Generator::__wakeup' => ['void'],
'Generator::current' => ['mixed'],
'Generator::getReturn' => ['mixed'],
'Generator::key' => ['mixed'],
@@ -3280,8 +3276,8 @@ return [
'get_called_class' => ['class-string'],
'get_cfg_var' => ['string|false', 'option'=>'string'],
'get_class' => ['class-string', 'object='=>'object'],
-'get_class_methods' => ['list', 'object_or_class'=>'object|class-string'],
-'get_class_vars' => ['array', 'class'=>'string'],
+'get_class_methods' => ['list', 'object_or_class'=>'object|class-string'],
+'get_class_vars' => ['array', 'class'=>'string'],
'get_current_user' => ['string'],
'get_debug_type' => ['string', 'value'=>'mixed'],
'get_declared_classes' => ['list'],
@@ -3333,7 +3329,7 @@ return [
'gettimeofday' => ['array'],
'gettimeofday\'1' => ['float', 'as_float='=>'true'],
'gettype' => ['string', 'value'=>'mixed'],
-'glob' => ['list|false', 'pattern'=>'string', 'flags='=>'int'],
+'glob' => ['list|false', 'pattern'=>'non-empty-string', 'flags='=>'int<1, max>'],
'GlobIterator::__construct' => ['void', 'pattern'=>'string', 'flags='=>'int'],
'GlobIterator::count' => ['int'],
'GlobIterator::current' => ['FilesystemIterator|SplFileInfo|string'],
@@ -3555,9 +3551,7 @@ return [
'GmagickPixel::setcolorvalue' => ['GmagickPixel', 'color'=>'int', 'value'=>'float'],
'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int|null'],
'gmmktime' => ['int|false', 'hour'=>'int', 'minute='=>'int|null', 'second='=>'int|null', 'month='=>'int|null', 'day='=>'int|null', 'year='=>'int|null'],
-'GMP::__construct' => ['void'],
'GMP::__serialize' => ['array'],
-'GMP::__toString' => ['numeric-string'],
'GMP::__unserialize' => ['void', 'data'=>'array'],
'gmp_abs' => ['GMP', 'num'=>'GMP|string|int'],
'gmp_add' => ['GMP', 'num1'=>'GMP|string|int', 'num2'=>'GMP|string|int'],
@@ -3742,19 +3736,19 @@ return [
'gzdeflate' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'],
'gzencode' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'],
'gzeof' => ['bool', 'stream'=>'resource'],
-'gzfile' => ['list', 'filename'=>'string', 'use_include_path='=>'int'],
+'gzfile' => ['list|false', 'filename'=>'string', 'use_include_path='=>'int'],
'gzgetc' => ['string|false', 'stream'=>'resource'],
'gzgets' => ['string|false', 'stream'=>'resource', 'length='=>'?int'],
'gzinflate' => ['string|false', 'data'=>'string', 'max_length='=>'int'],
'gzopen' => ['resource|false', 'filename'=>'string', 'mode'=>'string', 'use_include_path='=>'int'],
'gzpassthru' => ['int', 'stream'=>'resource'],
-'gzputs' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
+'gzputs' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
'gzread' => ['string|false', 'stream'=>'resource', 'length'=>'int'],
'gzrewind' => ['bool', 'stream'=>'resource'],
'gzseek' => ['int', 'stream'=>'resource', 'offset'=>'int', 'whence='=>'int'],
'gztell' => ['int|false', 'stream'=>'resource'],
'gzuncompress' => ['string|false', 'data'=>'string', 'max_length='=>'int'],
-'gzwrite' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
+'gzwrite' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
'HaruAnnotation::setBorderStyle' => ['bool', 'width'=>'float', 'dash_on'=>'int', 'dash_off'=>'int'],
'HaruAnnotation::setHighlightMode' => ['bool', 'mode'=>'int'],
'HaruAnnotation::setIcon' => ['bool', 'icon'=>'int'],
@@ -6129,10 +6123,10 @@ return [
'Iterator::rewind' => ['void'],
'Iterator::valid' => ['bool'],
'iterator_apply' => ['0|positive-int', 'iterator'=>'Traversable', 'callback'=>'callable(mixed):bool', 'args='=>'?array'],
-'iterator_count' => ['0|positive-int', 'iterator'=>'Traversable'],
-'iterator_to_array' => ['array', 'iterator'=>'Traversable', 'preserve_keys='=>'bool'],
+'iterator_count' => ['0|positive-int', 'iterator'=>'Traversable|array'],
+'iterator_to_array' => ['array', 'iterator'=>'Traversable|array', 'preserve_keys='=>'bool'],
'IteratorAggregate::getIterator' => ['Traversable'],
-'IteratorIterator::__construct' => ['void', 'it'=>'Traversable'],
+'IteratorIterator::__construct' => ['void', 'iterator'=>'Traversable', 'class='=>'?string'],
'IteratorIterator::current' => ['mixed'],
'IteratorIterator::getInnerIterator' => ['Iterator'],
'IteratorIterator::key' => ['mixed'],
@@ -6164,7 +6158,7 @@ return [
'json_last_error_msg' => ['string'],
'json_validate' => ['bool', 'json'=>'string', 'depth='=>'positive-int', 'flags='=>'int'],
'JsonException::__clone' => ['void'],
-'JsonException::__construct' => ['void'],
+'JsonException::__construct' => ['void', "message="=>"string", 'code='=>'int', 'previous='=>'?Throwable'],
'JsonException::__toString' => ['string'],
'JsonException::__wakeup' => ['void'],
'JsonException::getCode' => ['int'],
@@ -6339,7 +6333,7 @@ return [
'ldap_count_entries' => ['int', 'ldap'=>'LDAP\Connection', 'result'=>'LDAP\Result'],
'ldap_delete' => ['bool', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'controls='=>'?array'],
'ldap_delete_ext' => ['LDAP\Result|false', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'controls='=>'?array'],
-'ldap_dn2ufn' => ['string', 'dn'=>'string'],
+'ldap_dn2ufn' => ['string|false', 'dn'=>'string'],
'ldap_err2str' => ['string', 'errno'=>'int'],
'ldap_errno' => ['int', 'ldap'=>'LDAP\Connection'],
'ldap_error' => ['string', 'ldap'=>'LDAP\Connection'],
@@ -6359,7 +6353,7 @@ return [
'ldap_get_option' => ['bool', 'ldap'=>'LDAP\Connection', 'option'=>'int', '&w_value='=>'array|string|int'],
'ldap_get_values' => ['array|false', 'ldap'=>'LDAP\Connection', 'entry'=>'LDAP\ResultEntry', 'attribute'=>'string'],
'ldap_get_values_len' => ['array|false', 'ldap'=>'LDAP\Connection', 'entry'=>'LDAP\ResultEntry', 'attribute'=>'string'],
-'ldap_list' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
+'ldap_list' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
'ldap_mod_add' => ['bool', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'entry'=>'array', 'controls='=>'?array'],
'ldap_mod_add_ext' => ['LDAP\Result|false', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'entry'=>'array', 'controls='=>'?array'],
'ldap_mod_del' => ['bool', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'entry'=>'array', 'controls='=>'?array'],
@@ -6374,11 +6368,11 @@ return [
'ldap_parse_exop' => ['bool', 'ldap'=>'LDAP\Connection', 'result'=>'LDAP\Result', '&w_response_data='=>'string', '&w_response_oid='=>'string'],
'ldap_parse_reference' => ['bool', 'ldap'=>'LDAP\Connection', 'entry'=>'LDAP\ResultEntry', '&w_referrals'=>'array'],
'ldap_parse_result' => ['bool', 'ldap'=>'LDAP\Connection', 'result'=>'LDAP\Result', '&w_error_code'=>'int', '&w_matched_dn='=>'string', '&w_error_message='=>'string', '&w_referrals='=>'array', '&w_controls='=>'array'],
-'ldap_read' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
+'ldap_read' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
'ldap_rename' => ['bool', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'?array'],
'ldap_rename_ext' => ['LDAP\Result|false', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'?array'],
'ldap_sasl_bind' => ['bool', 'ldap'=>'LDAP\Connection', 'dn='=>'?string', 'password='=>'?string', 'mech='=>'?string', 'realm='=>'?string', 'authc_id='=>'?string', 'authz_id='=>'?string', 'props='=>'?string'],
-'ldap_search' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
+'ldap_search' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
'ldap_set_option' => ['bool', 'ldap'=>'LDAP\Connection|null', 'option'=>'int', 'value'=>'mixed'],
'ldap_set_rebind_proc' => ['bool', 'ldap'=>'LDAP\Connection', 'callback'=>'?callable'],
'ldap_start_tls' => ['bool', 'ldap'=>'LDAP\Connection'],
@@ -6442,14 +6436,14 @@ return [
'libxml_set_external_entity_loader' => ['bool', 'resolver_function'=>'(callable(string,string,array{directory:?string,intSubName:?string,extSubURI:?string,extSubSystem:?string}):(resource|string|null))|null'],
'libxml_set_streams_context' => ['void', 'context'=>'resource'],
'libxml_use_internal_errors' => ['bool', 'use_errors='=>'?bool'],
-'LimitIterator::__construct' => ['void', 'iterator'=>'Iterator', 'offset='=>'int', 'count='=>'int'],
+'LimitIterator::__construct' => ['void', 'iterator'=>'Iterator', 'offset='=>'int', 'limit='=>'int'],
'LimitIterator::current' => ['mixed'],
'LimitIterator::getInnerIterator' => ['Iterator'],
'LimitIterator::getPosition' => ['int'],
'LimitIterator::key' => ['mixed'],
'LimitIterator::next' => ['void'],
'LimitIterator::rewind' => ['void'],
-'LimitIterator::seek' => ['int', 'position'=>'int'],
+'LimitIterator::seek' => ['int', 'offset'=>'int'],
'LimitIterator::valid' => ['bool'],
'lineObj::__construct' => ['void'],
'lineObj::add' => ['int', 'point'=>'pointObj'],
@@ -6848,14 +6842,14 @@ return [
'memory_reset_peak_usage' => ['void'],
'MessageFormatter::__construct' => ['void', 'locale'=>'string', 'pattern'=>'string'],
'MessageFormatter::create' => ['MessageFormatter', 'locale'=>'string', 'pattern'=>'string'],
-'MessageFormatter::format' => ['false|string', 'args'=>'array'],
-'MessageFormatter::formatMessage' => ['false|string', 'locale'=>'string', 'pattern'=>'string', 'args'=>'array'],
+'MessageFormatter::format' => ['false|string', 'values'=>'array'],
+'MessageFormatter::formatMessage' => ['false|string', 'locale'=>'string', 'pattern'=>'string', 'values'=>'array'],
'MessageFormatter::getErrorCode' => ['int'],
'MessageFormatter::getErrorMessage' => ['string'],
'MessageFormatter::getLocale' => ['string'],
'MessageFormatter::getPattern' => ['string'],
-'MessageFormatter::parse' => ['array|false', 'value'=>'string'],
-'MessageFormatter::parseMessage' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'source'=>'string'],
+'MessageFormatter::parse' => ['array|false', 'string'=>'string'],
+'MessageFormatter::parseMessage' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'message'=>'string'],
'MessageFormatter::setPattern' => ['bool', 'pattern'=>'string'],
'metaphone' => ['string', 'string'=>'string', 'max_phonemes='=>'int'],
'method_exists' => ['bool', 'object_or_class'=>'object|class-string|interface-string|enum-string', 'method'=>'string'],
@@ -7065,7 +7059,7 @@ return [
'MongoDB::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'],
'MongoDB::setSlaveOkay' => ['bool', 'ok='=>'bool'],
'MongoDB::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'],
-'MongoDB\BSON\Binary::__construct' => ['void', 'data' => 'string', 'type' => 'int'],
+'MongoDB\BSON\Binary::__construct' => ['void', 'data' => 'string', 'type=' => 'int'],
'MongoDB\BSON\Binary::getData' => ['string'],
'MongoDB\BSON\Binary::getType' => ['int'],
'MongoDB\BSON\Binary::__toString' => ['string'],
@@ -7623,7 +7617,7 @@ return [
'mt_rand\'1' => ['int'],
'mt_srand' => ['void', 'seed='=>'int', 'mode='=>'int'],
'MultipleIterator::__construct' => ['void', 'flags='=>'int'],
-'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'infos='=>'string'],
+'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'info='=>'string|int|null'],
'MultipleIterator::containsIterator' => ['bool', 'iterator'=>'Iterator'],
'MultipleIterator::countIterators' => ['int'],
'MultipleIterator::current' => ['array|false'],
@@ -7811,7 +7805,6 @@ return [
'mysqli::commit' => ['bool', 'flags='=>'int', 'name='=>'?string'],
'mysqli::connect' => ['bool', 'hostname='=>'string|null', 'username='=>'string|null', 'password='=>'string|null', 'database='=>'string|null', 'port='=>'int|null', 'socket='=>'string|null'],
'mysqli::debug' => ['bool', 'options'=>'string'],
-'mysqli::disable_reads_from_master' => ['bool'],
'mysqli::dump_debug_info' => ['bool'],
'mysqli::escape_string' => ['string', 'string'=>'string'],
'mysqli::execute_query' => ['mysqli_result|bool', 'query'=>'non-empty-string', 'params='=>'list|null'],
@@ -7826,23 +7819,19 @@ return [
'mysqli::next_result' => ['bool'],
'mysqli::options' => ['bool', 'option'=>'int', 'value'=>'string|int'],
'mysqli::ping' => ['bool'],
-'mysqli::poll' => ['int|false', '&w_read'=>'array', '&w_write'=>'array', '&w_error'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
+'mysqli::poll' => ['int|false', '&w_read'=>'?array', '&w_error'=>'?array', '&w_reject'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
'mysqli::prepare' => ['mysqli_stmt|false', 'query'=>'string'],
'mysqli::query' => ['bool|mysqli_result', 'query'=>'string', 'result_mode='=>'int'],
-'mysqli::real_connect' => ['bool', 'hostname='=>'string|null', 'username='=>'string|null', 'password='=>'string|null', 'database='=>'string|null', 'port='=>'int|null', 'socket='=>'string|null', 'flags='=>'int'],
+'mysqli::real_connect' => ['bool', 'hostname='=>'?string', 'username='=>'?string', 'password='=>'?string', 'database='=>'?string', 'port='=>'?int', 'socket='=>'?string', 'flags='=>'int'],
'mysqli::real_escape_string' => ['string', 'string'=>'string'],
'mysqli::real_query' => ['bool', 'query'=>'string'],
'mysqli::reap_async_query' => ['mysqli_result|false'],
'mysqli::refresh' => ['bool', 'flags'=>'int'],
'mysqli::release_savepoint' => ['bool', 'name'=>'string'],
'mysqli::rollback' => ['bool', 'flags='=>'int', 'name='=>'?string'],
-'mysqli::rpl_query_type' => ['int', 'query'=>'string'],
'mysqli::savepoint' => ['bool', 'name'=>'string'],
'mysqli::select_db' => ['bool', 'database'=>'string'],
-'mysqli::send_query' => ['bool', 'query'=>'string'],
'mysqli::set_charset' => ['bool', 'charset'=>'string'],
-'mysqli::set_local_infile_default' => ['void'],
-'mysqli::set_local_infile_handler' => ['bool', 'read_func='=>'callable'],
'mysqli::set_opt' => ['bool', 'option'=>'int', 'value'=>'string|int'],
'mysqli::ssl_set' => ['bool', 'key'=>'?string', 'certificate'=>'?string', 'ca_certificate'=>'?string', 'ca_path'=>'?string', 'cipher_algos'=>'?string'],
'mysqli::stat' => ['string|false'],
@@ -7864,8 +7853,6 @@ return [
'mysqli_debug' => ['true', 'options'=>'string'],
'mysqli_disable_reads_from_master' => ['bool', 'link'=>'mysqli'],
'mysqli_disable_rpl_parse' => ['bool', 'link'=>'mysqli'],
-'mysqli_driver::embedded_server_end' => ['void'],
-'mysqli_driver::embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'],
'mysqli_dump_debug_info' => ['bool', 'mysql'=>'mysqli'],
'mysqli_embedded_server_end' => ['void'],
'mysqli_embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'],
@@ -7885,9 +7872,9 @@ return [
'mysqli_fetch_array\'2' => ['list|false|null', 'result'=>'mysqli_result', 'mode='=>'2'],
'mysqli_fetch_assoc' => ['array|false|null', 'result'=>'mysqli_result'],
'mysqli_fetch_column' => ['null|int|float|string|false', 'result'=>'mysqli_result', 'column='=>'int'],
-'mysqli_fetch_field' => ['object|false', 'result'=>'mysqli_result'],
-'mysqli_fetch_field_direct' => ['object|false', 'result'=>'mysqli_result', 'index'=>'int'],
-'mysqli_fetch_fields' => ['stdClass[]', 'result'=>'mysqli_result'],
+'mysqli_fetch_field' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'result'=>'mysqli_result'],
+'mysqli_fetch_field_direct' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'result'=>'mysqli_result', 'index'=>'int'],
+'mysqli_fetch_fields' => ['list