From cb5a28dc67266b97e74fee7fbbb15ed169a51d6a Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Sat, 2 Sep 2023 22:05:42 +0200 Subject: [PATCH] Introduce QA settings These settings support: * PHPStan * PHPCS * Psalm Fixes: * WebHook generation --- composer.json | 1 + composer.lock | 459 ++++++++++-------- example/openapi-client-miele.yaml | 6 + example/openapi-client-one.yaml | 6 + example/openapi-client-subsplit.yaml | 6 + example/templates/composer.json | 10 + example/templates/etc/qa/phpstan.neon | 1 + src/Configuration.php | 2 + src/Configuration/QA.php | 17 + src/Configuration/QA/Tool.php | 17 + src/Gatherer/WebHook.php | 5 +- src/Gatherer/WebHookHydrator.php | 2 +- src/Generator.php | 14 +- src/Generator/Client.php | 69 ++- .../Client/PHPStan/ClientCallReturnTypes.php | 306 ++++++++++++ .../PHPStan/ClientCallReturnTypesTest.php | 118 +++++ src/Generator/ClientInterface.php | 41 +- src/Generator/Helper/Operation.php | 18 +- src/Generator/Helper/ReflectionTypes.php | 29 +- src/Generator/Helper/Types.php | 14 +- src/Generator/Operation.php | 86 ++-- src/Generator/Operator.php | 8 +- src/Generator/Schema/CastUnionToType.php | 8 +- src/Generator/WebHook.php | 6 +- src/Generator/WebHooks.php | 2 +- src/phpstan-assertType-mock.php | 9 + tests/app-templates/Makefile | 64 +++ tests/app-templates/composer.json | 76 +++ tests/app/Makefile | 64 +++ tests/app/composer.json | 57 +++ tests/app/etc/openapi-client-generator.state | 80 +-- tests/app/etc/phpstan-extension.neon | 5 + tests/app/src/Client.php | 3 +- tests/app/src/ClientInterface.php | 5 +- .../src/Internal/Operation/Pets/Create.php | 10 +- .../Internal/Operation/Pets/ListListing.php | 12 +- .../app/src/Internal/Operation/Pets/List_.php | 12 +- .../Internal/Operation/Pets/List_/Gatos.php | 6 +- .../Operation/Pets/List_/GatosListing.php | 6 +- .../app/src/Internal/Operation/Pets/Names.php | 4 +- .../Internal/Operation/Pets/NamesListing.php | 4 +- .../src/Internal/Operation/ShowPetById.php | 12 +- .../app/src/Internal/Operator/Pets/Create.php | 6 +- .../Internal/Operator/Pets/ListListing.php | 4 +- .../app/src/Internal/Operator/Pets/List_.php | 4 +- .../Internal/Operator/Pets/List_/Gatos.php | 4 +- .../Operator/Pets/List_/GatosListing.php | 4 +- .../app/src/Internal/Operator/Pets/Names.php | 4 +- .../Internal/Operator/Pets/NamesListing.php | 4 +- .../app/src/Internal/Operator/ShowPetById.php | 4 +- tests/app/src/Internal/Router/Get.php | 2 +- tests/app/src/Internal/Router/Get/Pets.php | 4 +- .../app/src/Internal/Router/Get/PetsList.php | 2 +- tests/app/src/Internal/Router/Get/Three.php | 2 +- tests/app/src/Internal/Router/Get/Two.php | 2 +- tests/app/src/Internal/Router/List/Pets.php | 4 +- .../app/src/Internal/Router/List/PetsList.php | 2 +- tests/app/src/Internal/Router/List/Three.php | 2 +- tests/app/src/Internal/Router/List/Two.php | 2 +- tests/app/src/Internal/Router/Post/Pets.php | 4 +- tests/app/src/Internal/Router/Post/Two.php | 4 +- tests/app/src/Operation/Pets.php | 12 +- tests/app/src/Operation/PetsList.php | 4 +- tests/app/src/Operations.php | 2 +- tests/app/src/OperationsInterface.php | 2 +- .../app/src/PHPStan/ClientCallReturnTypes.php | 61 +++ .../app/tests/Types/ClientCallReturnTypes.php | 27 ++ tests/openapi-client-petstore.yaml | 11 + tests/unit/Gatherer/OperationTest.php | 107 ---- tests/unit/Generator/Helper/TypesTest.php | 8 - 70 files changed, 1419 insertions(+), 559 deletions(-) create mode 100644 src/Configuration/QA.php create mode 100644 src/Configuration/QA/Tool.php create mode 100644 src/Generator/Client/PHPStan/ClientCallReturnTypes.php create mode 100644 src/Generator/Client/PHPStan/ClientCallReturnTypesTest.php create mode 100644 src/phpstan-assertType-mock.php create mode 100644 tests/app-templates/Makefile create mode 100644 tests/app-templates/composer.json create mode 100644 tests/app/Makefile create mode 100644 tests/app/composer.json create mode 100644 tests/app/etc/phpstan-extension.neon create mode 100644 tests/app/src/PHPStan/ClientCallReturnTypes.php create mode 100644 tests/app/tests/Types/ClientCallReturnTypes.php delete mode 100644 tests/unit/Gatherer/OperationTest.php diff --git a/composer.json b/composer.json index 61aaf56..f35db3f 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "php": "^8.2", "api-clients/contracts": "^0.1", "api-clients/github": "^0.2@dev", + "api-clients/openapi-client-utils": "dev-main", "ckr/arraymerger": "^3.0", "codeinc/http-reason-phrase-lookup": "^1.0", "delight-im/random": "^1.0", diff --git a/composer.lock b/composer.lock index 5feeeef..a5ed1b4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "73ab1c69fd4ff4f9394fa62ecfa4c15c", + "content-hash": "7aaac3c8e01680bf30983bab9575e7bb", "packages": [ { "name": "amphp/amp", @@ -218,12 +218,12 @@ "source": { "type": "git", "url": "https://github.com/php-api-clients/github.git", - "reference": "b2a6f4beedbdfcb5c1ee4c418cb75cccbee5e609" + "reference": "334aa3eeb80e23c36f6e997df14e4377b56216b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-api-clients/github/zipball/b2a6f4beedbdfcb5c1ee4c418cb75cccbee5e609", - "reference": "b2a6f4beedbdfcb5c1ee4c418cb75cccbee5e609", + "url": "https://api.github.com/repos/php-api-clients/github/zipball/334aa3eeb80e23c36f6e997df14e4377b56216b1", + "reference": "334aa3eeb80e23c36f6e997df14e4377b56216b1", "shasum": "" }, "require": { @@ -261,7 +261,58 @@ "issues": "https://github.com/php-api-clients/github/issues", "source": "https://github.com/php-api-clients/github/tree/v0.2.x" }, - "time": "2023-07-30T16:16:07+00:00" + "time": "2023-08-31T16:35:59+00:00" + }, + { + "name": "api-clients/openapi-client-utils", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/php-api-clients/openapi-client-utils.git", + "reference": "ff61fcf268b3ca092d4a988963a2b02f2118a88d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-api-clients/openapi-client-utils/zipball/ff61fcf268b3ca092d4a988963a2b02f2118a88d", + "reference": "ff61fcf268b3ca092d4a988963a2b02f2118a88d", + "shasum": "" + }, + "require": { + "api-clients/contracts": "^0.1", + "php": "^8.2" + }, + "require-dev": { + "wyrihaximus/async-test-utilities": "^7.1" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "ApiClients\\Tools\\OpenApiClient\\Utils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + } + ], + "description": "Common utils for generated OpenAPI clients", + "support": { + "issues": "https://github.com/php-api-clients/openapi-client-utils/issues", + "source": "https://github.com/php-api-clients/openapi-client-utils/tree/main" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + } + ], + "time": "2023-09-05T06:06:58+00:00" }, { "name": "azjezz/psl", @@ -703,16 +754,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.3.6", + "version": "1.3.7", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "90d087e988ff194065333d16bc5cf649872d9cdb" + "reference": "76e46335014860eec1aa5a724799a00a2e47cc85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/90d087e988ff194065333d16bc5cf649872d9cdb", - "reference": "90d087e988ff194065333d16bc5cf649872d9cdb", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/76e46335014860eec1aa5a724799a00a2e47cc85", + "reference": "76e46335014860eec1aa5a724799a00a2e47cc85", "shasum": "" }, "require": { @@ -759,7 +810,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.3.6" + "source": "https://github.com/composer/ca-bundle/tree/1.3.7" }, "funding": [ { @@ -775,7 +826,7 @@ "type": "tidelift" } ], - "time": "2023-06-06T12:02:59+00:00" + "time": "2023-08-30T09:31:38+00:00" }, { "name": "composer/class-map-generator", @@ -852,16 +903,16 @@ }, { "name": "composer/composer", - "version": "2.5.8", + "version": "2.6.2", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "4c516146167d1392c8b9b269bb7c24115d262164" + "reference": "623e5e1de055e65bc6c3c61b8348dc4662d75e2b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/4c516146167d1392c8b9b269bb7c24115d262164", - "reference": "4c516146167d1392c8b9b269bb7c24115d262164", + "url": "https://api.github.com/repos/composer/composer/zipball/623e5e1de055e65bc6c3c61b8348dc4662d75e2b", + "reference": "623e5e1de055e65bc6c3c61b8348dc4662d75e2b", "shasum": "" }, "require": { @@ -869,23 +920,23 @@ "composer/class-map-generator": "^1.0", "composer/metadata-minifier": "^1.0", "composer/pcre": "^2.1 || ^3.1", - "composer/semver": "^3.0", + "composer/semver": "^3.2.5", "composer/spdx-licenses": "^1.5.7", "composer/xdebug-handler": "^2.0.2 || ^3.0.3", "justinrainbow/json-schema": "^5.2.11", "php": "^7.2.5 || ^8.0", "psr/log": "^1.0 || ^2.0 || ^3.0", - "react/promise": "^2.8", + "react/promise": "^2.8 || ^3", "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.2", "seld/signal-handler": "^2.0", - "symfony/console": "^5.4.11 || ^6.0.11", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", + "symfony/console": "^5.4.11 || ^6.0.11 || ^7", + "symfony/filesystem": "^5.4 || ^6.0 || ^7", + "symfony/finder": "^5.4 || ^6.0 || ^7", "symfony/polyfill-php73": "^1.24", "symfony/polyfill-php80": "^1.24", "symfony/polyfill-php81": "^1.24", - "symfony/process": "^5.4 || ^6.0" + "symfony/process": "^5.4 || ^6.0 || ^7" }, "require-dev": { "phpstan/phpstan": "^1.9.3", @@ -893,7 +944,7 @@ "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1", "phpstan/phpstan-symfony": "^1.2.10", - "symfony/phpunit-bridge": "^6.0" + "symfony/phpunit-bridge": "^6.0 || ^7" }, "suggest": { "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", @@ -906,7 +957,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "2.6-dev" }, "phpstan": { "includes": [ @@ -916,7 +967,7 @@ }, "autoload": { "psr-4": { - "Composer\\": "src/Composer" + "Composer\\": "src/Composer/" } }, "notification-url": "https://packagist.org/downloads/", @@ -945,7 +996,8 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", - "source": "https://github.com/composer/composer/tree/2.5.8" + "security": "https://github.com/composer/composer/security/policy", + "source": "https://github.com/composer/composer/tree/2.6.2" }, "funding": [ { @@ -961,7 +1013,7 @@ "type": "tidelift" } ], - "time": "2023-06-09T15:13:21+00:00" + "time": "2023-09-03T12:09:15+00:00" }, { "name": "composer/metadata-minifier", @@ -1105,16 +1157,16 @@ }, { "name": "composer/semver", - "version": "3.3.2", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", "shasum": "" }, "require": { @@ -1164,9 +1216,9 @@ "versioning" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" + "source": "https://github.com/composer/semver/tree/3.4.0" }, "funding": [ { @@ -1182,7 +1234,7 @@ "type": "tidelift" } ], - "time": "2022-04-01T19:23:25+00:00" + "time": "2023-08-31T09:50:34+00:00" }, { "name": "composer/spdx-licenses", @@ -1946,16 +1998,16 @@ }, { "name": "ergebnis/composer-normalize", - "version": "2.34.0", + "version": "2.36.0", "source": { "type": "git", "url": "https://github.com/ergebnis/composer-normalize.git", - "reference": "39beb6b5f1e2d923c27fe30c48c3b88582081228" + "reference": "a8ac2c507de9166652cd76f4c336e9c7c0dd1456" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/39beb6b5f1e2d923c27fe30c48c3b88582081228", - "reference": "39beb6b5f1e2d923c27fe30c48c3b88582081228", + "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/a8ac2c507de9166652cd76f4c336e9c7c0dd1456", + "reference": "a8ac2c507de9166652cd76f4c336e9c7c0dd1456", "shasum": "" }, "require": { @@ -1969,17 +2021,17 @@ "php": "~8.1.0 || ~8.2.0" }, "require-dev": { - "composer/composer": "^2.5.8", + "composer/composer": "^2.6.2", "ergebnis/license": "^2.1.0", - "ergebnis/php-cs-fixer-config": "^5.12.0", + "ergebnis/php-cs-fixer-config": "^5.14.1", "ergebnis/phpunit-slow-test-detector": "^2.3.0", "fakerphp/faker": "^1.23.0", "infection/infection": "~0.27.0", - "phpunit/phpunit": "^10.2.6", + "phpunit/phpunit": "^10.3.2", "psalm/plugin-phpunit": "~0.18.4", - "rector/rector": "~0.17.7", + "rector/rector": "~0.18.1", "symfony/filesystem": "^6.0.13", - "vimeo/psalm": "^5.13.1" + "vimeo/psalm": "^5.15.0" }, "type": "composer-plugin", "extra": { @@ -2018,7 +2070,7 @@ "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/composer-normalize" }, - "time": "2023-07-28T06:34:54+00:00" + "time": "2023-09-04T10:00:36+00:00" }, { "name": "ergebnis/json", @@ -2340,38 +2392,39 @@ }, { "name": "ergebnis/phpstan-rules", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/ergebnis/phpstan-rules.git", - "reference": "99360283faf07a6d553f384183f3551a054c5aeb" + "reference": "119e229c48688946450ccca9f1c57c9ca4fb6f02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/99360283faf07a6d553f384183f3551a054c5aeb", - "reference": "99360283faf07a6d553f384183f3551a054c5aeb", + "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/119e229c48688946450ccca9f1c57c9ca4fb6f02", + "reference": "119e229c48688946450ccca9f1c57c9ca4fb6f02", "shasum": "" }, "require": { "ext-mbstring": "*", "nikic/php-parser": "^4.2.3", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0", - "phpstan/phpstan": "^1.7.15" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0", + "phpstan/phpstan": "^1.10.21" }, "require-dev": { - "doctrine/orm": "^2.14.3", - "ergebnis/composer-normalize": "^2.30.2", + "doctrine/orm": "^2.16.1", + "ergebnis/composer-normalize": "^2.35.0", "ergebnis/license": "^2.1.0", - "ergebnis/php-cs-fixer-config": "^5.5.2", - "infection/infection": "~0.26.19", - "nette/di": "^3.1.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", + "ergebnis/php-cs-fixer-config": "^5.13.0", + "ergebnis/phpunit-slow-test-detector": "^2.3.0", + "infection/infection": "~0.27.0", + "nette/di": "^3.1.3", + "phpstan/phpstan-deprecation-rules": "^1.1.4", "phpstan/phpstan-strict-rules": "^1.1.0", - "phpunit/phpunit": "^9.6.7", + "phpunit/phpunit": "^10.3.2", "psalm/plugin-phpunit": "~0.18.4", "psr/container": "^1.1.2", - "rector/rector": "~0.15.25", - "vimeo/psalm": "^5.9.0" + "rector/rector": "~0.17.13", + "vimeo/psalm": "^5.14.1" }, "type": "phpstan-extension", "extra": { @@ -2407,32 +2460,32 @@ "issues": "https://github.com/ergebnis/phpstan-rules/issues", "source": "https://github.com/ergebnis/phpstan-rules" }, - "time": "2023-05-01T17:59:46+00:00" + "time": "2023-08-17T10:28:37+00:00" }, { "name": "evenement/evenement", - "version": "v3.0.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/igorw/evenement.git", - "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7" + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/igorw/evenement/zipball/531bfb9d15f8aa57454f5f0285b18bec903b8fb7", - "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", "shasum": "" }, "require": { "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9 || ^6" }, "type": "library", "autoload": { - "psr-0": { - "Evenement": "src" + "psr-4": { + "Evenement\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2452,9 +2505,9 @@ ], "support": { "issues": "https://github.com/igorw/evenement/issues", - "source": "https://github.com/igorw/evenement/tree/master" + "source": "https://github.com/igorw/evenement/tree/v3.0.2" }, - "time": "2017-07-23T21:35:13+00:00" + "time": "2023-08-08T05:53:35+00:00" }, { "name": "eventsauce/object-hydrator", @@ -2811,22 +2864,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.7.0", + "version": "7.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -2917,7 +2970,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.7.0" + "source": "https://github.com/guzzle/guzzle/tree/7.8.0" }, "funding": [ { @@ -2933,7 +2986,7 @@ "type": "tidelift" } ], - "time": "2023-05-21T14:04:53+00:00" + "time": "2023-08-27T10:20:53+00:00" }, { "name": "guzzlehttp/promises", @@ -3020,16 +3073,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77" + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77", - "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", "shasum": "" }, "require": { @@ -3116,7 +3169,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.0" + "source": "https://github.com/guzzle/psr7/tree/2.6.1" }, "funding": [ { @@ -3132,7 +3185,7 @@ "type": "tidelift" } ], - "time": "2023-08-03T15:06:02+00:00" + "time": "2023-08-27T10:13:57+00:00" }, { "name": "icanhazstring/composer-unused", @@ -5431,16 +5484,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.7.2", + "version": "1.7.3", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d" + "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b2fe4d22a5426f38e014855322200b97b5362c0d", - "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", + "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", "shasum": "" }, "require": { @@ -5483,9 +5536,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.2" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.3" }, - "time": "2023-05-30T18:13:47+00:00" + "time": "2023-08-12T11:01:26+00:00" }, { "name": "phpspec/prophecy", @@ -5656,16 +5709,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.28", + "version": "1.10.33", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e4545b55904ebef470423d3ddddb74fa7325497a" + "reference": "03b1cf9f814ba0863c4e9affea49a4d1ed9a2ed1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e4545b55904ebef470423d3ddddb74fa7325497a", - "reference": "e4545b55904ebef470423d3ddddb74fa7325497a", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/03b1cf9f814ba0863c4e9affea49a4d1ed9a2ed1", + "reference": "03b1cf9f814ba0863c4e9affea49a4d1ed9a2ed1", "shasum": "" }, "require": { @@ -5714,7 +5767,7 @@ "type": "tidelift" } ], - "time": "2023-08-08T12:33:42+00:00" + "time": "2023-09-04T12:20:53+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -5817,16 +5870,16 @@ }, { "name": "phpstan/phpstan-phpunit", - "version": "1.3.13", + "version": "1.3.14", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5" + "reference": "614acc10c522e319639bf38b0698a4a566665f04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d8bdab0218c5eb0964338d24a8511b65e9c94fa5", - "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/614acc10c522e319639bf38b0698a4a566665f04", + "reference": "614acc10c522e319639bf38b0698a4a566665f04", "shasum": "" }, "require": { @@ -5839,7 +5892,7 @@ "require-dev": { "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.5.1", "phpunit/phpunit": "^9.5" }, "type": "phpstan-extension", @@ -5863,9 +5916,9 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.13" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.14" }, - "time": "2023-05-26T11:05:59+00:00" + "time": "2023-08-25T09:46:39+00:00" }, { "name": "phpstan/phpstan-strict-rules", @@ -6237,16 +6290,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.10", + "version": "9.6.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" + "reference": "810500e92855eba8a7a5319ae913be2da6f957b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", - "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/810500e92855eba8a7a5319ae913be2da6f957b0", + "reference": "810500e92855eba8a7a5319ae913be2da6f957b0", "shasum": "" }, "require": { @@ -6320,7 +6373,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.11" }, "funding": [ { @@ -6336,7 +6389,7 @@ "type": "tidelift" } ], - "time": "2023-07-10T04:04:23+00:00" + "time": "2023-08-19T07:10:56+00:00" }, { "name": "pointybeard/reverse-regex", @@ -7393,16 +7446,16 @@ }, { "name": "react/socket", - "version": "v1.13.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "cff482bbad5848ecbe8b57da57e4e213b03619aa" + "reference": "21591111d3ea62e31f2254280ca0656bc2b1bda6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/cff482bbad5848ecbe8b57da57e4e213b03619aa", - "reference": "cff482bbad5848ecbe8b57da57e4e213b03619aa", + "url": "https://api.github.com/repos/reactphp/socket/zipball/21591111d3ea62e31f2254280ca0656bc2b1bda6", + "reference": "21591111d3ea62e31f2254280ca0656bc2b1bda6", "shasum": "" }, "require": { @@ -7417,7 +7470,7 @@ "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", "react/async": "^4 || ^3 || ^2", "react/promise-stream": "^1.4", - "react/promise-timer": "^1.9" + "react/promise-timer": "^1.10" }, "type": "library", "autoload": { @@ -7461,7 +7514,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.13.0" + "source": "https://github.com/reactphp/socket/tree/v1.14.0" }, "funding": [ { @@ -7469,7 +7522,7 @@ "type": "open_collective" } ], - "time": "2023-06-07T10:28:34+00:00" + "time": "2023-08-25T13:48:09+00:00" }, { "name": "react/stream", @@ -7998,22 +8051,22 @@ }, { "name": "roave/better-reflection", - "version": "6.12.0", + "version": "6.13.0", "source": { "type": "git", "url": "https://github.com/Roave/BetterReflection.git", - "reference": "77c68f64032b73840305038ae3d1f6f209542937" + "reference": "89087a62547d5509b3a0329d8b67218448c7d1d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/BetterReflection/zipball/77c68f64032b73840305038ae3d1f6f209542937", - "reference": "77c68f64032b73840305038ae3d1f6f209542937", + "url": "https://api.github.com/repos/Roave/BetterReflection/zipball/89087a62547d5509b3a0329d8b67218448c7d1d7", + "reference": "89087a62547d5509b3a0329d8b67218448c7d1d7", "shasum": "" }, "require": { "ext-json": "*", "jetbrains/phpstorm-stubs": "2023.2", - "nikic/php-parser": "^4.16.0", + "nikic/php-parser": "^4.17.1", "php": "~8.1.0 || ~8.2.0", "roave/signature": "^1.7" }, @@ -8022,11 +8075,11 @@ }, "require-dev": { "doctrine/coding-standard": "^12.0.0", - "phpstan/phpstan": "^1.10.27", - "phpstan/phpstan-phpunit": "^1.3.13", - "phpunit/phpunit": "^10.3.1", + "phpstan/phpstan": "^1.10.32", + "phpstan/phpstan-phpunit": "^1.3.14", + "phpunit/phpunit": "^10.3.2", "roave/infection-static-analysis-plugin": "^1.32.0", - "vimeo/psalm": "5.14.1" + "vimeo/psalm": "5.15.0" }, "suggest": { "composer/composer": "Required to use the ComposerSourceLocator" @@ -8066,9 +8119,9 @@ "description": "Better Reflection - an improved code reflection API", "support": { "issues": "https://github.com/Roave/BetterReflection/issues", - "source": "https://github.com/Roave/BetterReflection/tree/6.12.0" + "source": "https://github.com/Roave/BetterReflection/tree/6.13.0" }, - "time": "2023-08-07T13:53:57+00:00" + "time": "2023-08-29T19:55:40+00:00" }, { "name": "roave/infection-static-analysis-plugin", @@ -9362,16 +9415,16 @@ }, { "name": "seld/signal-handler", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/Seldaek/signal-handler.git", - "reference": "f69d119511dc0360440cdbdaa71829c149b7be75" + "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/f69d119511dc0360440cdbdaa71829c149b7be75", - "reference": "f69d119511dc0360440cdbdaa71829c149b7be75", + "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98", + "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98", "shasum": "" }, "require": { @@ -9417,9 +9470,9 @@ ], "support": { "issues": "https://github.com/Seldaek/signal-handler/issues", - "source": "https://github.com/Seldaek/signal-handler/tree/2.0.1" + "source": "https://github.com/Seldaek/signal-handler/tree/2.0.2" }, - "time": "2022-07-20T18:31:45+00:00" + "time": "2023-09-03T09:24:00+00:00" }, { "name": "slevomat/coding-standard", @@ -9683,16 +9736,16 @@ }, { "name": "symfony/console", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898" + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/aa5d64ad3f63f2e48964fc81ee45cb318a723898", - "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898", + "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", "shasum": "" }, "require": { @@ -9753,7 +9806,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.2" + "source": "https://github.com/symfony/console/tree/v6.3.4" }, "funding": [ { @@ -9769,20 +9822,20 @@ "type": "tidelift" } ], - "time": "2023-07-19T20:17:28+00:00" + "time": "2023-08-16T10:10:12+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "474cfbc46aba85a1ca11a27db684480d0db64ba7" + "reference": "68a5a9570806a087982f383f6109c5e925892a49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/474cfbc46aba85a1ca11a27db684480d0db64ba7", - "reference": "474cfbc46aba85a1ca11a27db684480d0db64ba7", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/68a5a9570806a087982f383f6109c5e925892a49", + "reference": "68a5a9570806a087982f383f6109c5e925892a49", "shasum": "" }, "require": { @@ -9834,7 +9887,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.3.2" + "source": "https://github.com/symfony/dependency-injection/tree/v6.3.4" }, "funding": [ { @@ -9850,7 +9903,7 @@ "type": "tidelift" } ], - "time": "2023-07-19T20:17:28+00:00" + "time": "2023-08-16T17:55:17+00:00" }, { "name": "symfony/deprecation-contracts", @@ -10130,16 +10183,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + "reference": "875e90aeea2777b6f135677f618529449334a612" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", "shasum": "" }, "require": { @@ -10151,7 +10204,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -10191,7 +10244,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" }, "funding": [ { @@ -10207,20 +10260,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { @@ -10232,7 +10285,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -10275,7 +10328,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" }, "funding": [ { @@ -10291,7 +10344,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -10378,16 +10431,16 @@ }, { "name": "symfony/polyfill-php73", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" + "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5", + "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5", "shasum": "" }, "require": { @@ -10396,7 +10449,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -10437,7 +10490,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.28.0" }, "funding": [ { @@ -10453,20 +10506,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "shasum": "" }, "require": { @@ -10475,7 +10528,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -10520,7 +10573,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" }, "funding": [ { @@ -10536,20 +10589,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", "shasum": "" }, "require": { @@ -10558,7 +10611,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -10599,7 +10652,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" }, "funding": [ { @@ -10615,20 +10668,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/process", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d" + "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d", - "reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d", + "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", + "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", "shasum": "" }, "require": { @@ -10660,7 +10713,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.3.2" + "source": "https://github.com/symfony/process/tree/v6.3.4" }, "funding": [ { @@ -10676,7 +10729,7 @@ "type": "tidelift" } ], - "time": "2023-07-12T16:00:22+00:00" + "time": "2023-08-07T10:39:22+00:00" }, { "name": "symfony/property-access", @@ -10840,16 +10893,16 @@ }, { "name": "symfony/serializer", - "version": "v6.3.3", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "33deb86d212893042d7758d452aa39d19ca0efe3" + "reference": "96d28a58d5a128bf77c54534b380eb7c92c8f846" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/33deb86d212893042d7758d452aa39d19ca0efe3", - "reference": "33deb86d212893042d7758d452aa39d19ca0efe3", + "url": "https://api.github.com/repos/symfony/serializer/zipball/96d28a58d5a128bf77c54534b380eb7c92c8f846", + "reference": "96d28a58d5a128bf77c54534b380eb7c92c8f846", "shasum": "" }, "require": { @@ -10914,7 +10967,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.3.3" + "source": "https://github.com/symfony/serializer/tree/v6.3.4" }, "funding": [ { @@ -10930,7 +10983,7 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-08-24T14:35:28+00:00" }, { "name": "symfony/service-contracts", @@ -11164,16 +11217,16 @@ }, { "name": "symfony/var-exporter", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "3400949782c0cb5b3e73aa64cfd71dde000beccc" + "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/3400949782c0cb5b3e73aa64cfd71dde000beccc", - "reference": "3400949782c0cb5b3e73aa64cfd71dde000beccc", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df1f8aac5751871b83d30bf3e2c355770f8f0691", + "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691", "shasum": "" }, "require": { @@ -11218,7 +11271,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.3.2" + "source": "https://github.com/symfony/var-exporter/tree/v6.3.4" }, "funding": [ { @@ -11234,7 +11287,7 @@ "type": "tidelift" } ], - "time": "2023-07-26T17:39:03+00:00" + "time": "2023-08-16T18:14:47+00:00" }, { "name": "symfony/yaml", @@ -11682,16 +11735,16 @@ }, { "name": "vimeo/psalm", - "version": "5.14.1", + "version": "5.15.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "b9d355e0829c397b9b3b47d0c0ed042a8a70284d" + "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/b9d355e0829c397b9b3b47d0c0ed042a8a70284d", - "reference": "b9d355e0829c397b9b3b47d0c0ed042a8a70284d", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/5c774aca4746caf3d239d9c8cadb9f882ca29352", + "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352", "shasum": "" }, "require": { @@ -11719,6 +11772,9 @@ "symfony/console": "^4.1.6 || ^5.0 || ^6.0", "symfony/filesystem": "^5.4 || ^6.0" }, + "conflict": { + "nikic/php-parser": "4.17.0" + }, "provide": { "psalm/psalm": "self.version" }, @@ -11782,9 +11838,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.14.1" + "source": "https://github.com/vimeo/psalm/tree/5.15.0" }, - "time": "2023-08-01T05:16:55+00:00" + "time": "2023-08-20T23:07:30+00:00" }, { "name": "webmozart/assert", @@ -12351,6 +12407,7 @@ "minimum-stability": "stable", "stability-flags": { "api-clients/github": 20, + "api-clients/openapi-client-utils": 20, "wyrihaximus/subsplit-tools": 20 }, "prefer-stable": false, diff --git a/example/openapi-client-miele.yaml b/example/openapi-client-miele.yaml index 9ef30f8..2257f5f 100644 --- a/example/openapi-client-miele.yaml +++ b/example/openapi-client-miele.yaml @@ -32,3 +32,9 @@ voter: - ApiClients\Tools\OpenApiClientGenerator\Voter\ListOperation\PageAndPerPageInQuery streamOperation: - ApiClients\Tools\OpenApiClientGenerator\Voter\StreamOperation\DownloadInOperationId +qa: + phpcs: + enabled: true + phpstan: + enabled: true + configFilePath: etc/phpstan-extension.neon diff --git a/example/openapi-client-one.yaml b/example/openapi-client-one.yaml index c0b8914..aba1efc 100644 --- a/example/openapi-client-one.yaml +++ b/example/openapi-client-one.yaml @@ -32,3 +32,9 @@ voter: - ApiClients\Tools\OpenApiClientGenerator\Voter\ListOperation\PageAndPerPageInQuery streamOperation: - ApiClients\Tools\OpenApiClientGenerator\Voter\StreamOperation\DownloadInOperationId +qa: + phpcs: + enabled: true + phpstan: + enabled: true + configFilePath: etc/phpstan-extension.neon diff --git a/example/openapi-client-subsplit.yaml b/example/openapi-client-subsplit.yaml index 90628ed..74c6564 100644 --- a/example/openapi-client-subsplit.yaml +++ b/example/openapi-client-subsplit.yaml @@ -47,3 +47,9 @@ subSplit: sectionPackage: name: github-{{ section }} repository: git@github.com:php-api-clients/github-{{ section }}.git +qa: + phpcs: + enabled: true + phpstan: + enabled: true + configFilePath: etc/phpstan-extension.neon diff --git a/example/templates/composer.json b/example/templates/composer.json index b1703eb..e11cd01 100644 --- a/example/templates/composer.json +++ b/example/templates/composer.json @@ -16,6 +16,7 @@ {% endfor %} {% endif %} "api-clients/contracts": "^0.1", + "api-clients/openapi-client-utils": "dev-main", "devizzent/cebe-php-openapi": "^1", "eventsauce/object-hydrator": "^1.1", "league/openapi-psr7-validator": "^0.21", @@ -48,6 +49,15 @@ "api-clients/{{ suggest.name }}": "{{ suggest.reason }}"{% if not loop.last %},{% endif %} {% endfor %} }, +{% endif %} +{% if qa.phpstan.enabled is constant('true') and qa.phpstan.configFilePath is not constant('null') %} + "extra": { + "phpstan": { + "includes": [ + "{{ qa.phpstan.configFilePath }}" + ] + } + }, {% endif %} "config": { "sort-packages": true, diff --git a/example/templates/etc/qa/phpstan.neon b/example/templates/etc/qa/phpstan.neon index 9939fb4..485c1a7 100644 --- a/example/templates/etc/qa/phpstan.neon +++ b/example/templates/etc/qa/phpstan.neon @@ -1,2 +1,3 @@ includes: - ../../vendor/wyrihaximus/async-test-utilities/rules.neon + - ../phpstan-extension.neon diff --git a/src/Configuration.php b/src/Configuration.php index 545592a..a993bb2 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -7,6 +7,7 @@ use ApiClients\Tools\OpenApiClientGenerator\Configuration\Destination; use ApiClients\Tools\OpenApiClientGenerator\Configuration\EntryPoints; use ApiClients\Tools\OpenApiClientGenerator\Configuration\Namespace_; +use ApiClients\Tools\OpenApiClientGenerator\Configuration\QA; use ApiClients\Tools\OpenApiClientGenerator\Configuration\Schemas; use ApiClients\Tools\OpenApiClientGenerator\Configuration\State; use ApiClients\Tools\OpenApiClientGenerator\Configuration\SubSplit; @@ -32,6 +33,7 @@ public function __construct( public SubSplit|null $subSplit, public Schemas|null $schemas, public Voter|null $voter, + public QA|null $qa, ) { } } diff --git a/src/Configuration/QA.php b/src/Configuration/QA.php new file mode 100644 index 0000000..2a693ac --- /dev/null +++ b/src/Configuration/QA.php @@ -0,0 +1,17 @@ +post?->requestBody === null || ! property_exists($webhook->post->requestBody, 'content')) { -// var_export(json_decode(json_encode($webhook->getSerializableData()))); + if ($webhook->post?->requestBody === null && ! property_exists($webhook->post->requestBody, 'content')) { throw new RuntimeException('Missing request body content to deal with'); } @@ -45,7 +44,7 @@ public static function gather( ), $header->schema, $schemaRegistry, - ), ExampleData::determiteType($headerSpec->example)); + ), ExampleData::determiteType($header->example)); } return new \ApiClients\Tools\OpenApiClientGenerator\Representation\WebHook( diff --git a/src/Gatherer/WebHookHydrator.php b/src/Gatherer/WebHookHydrator.php index 4ec76b5..413a651 100644 --- a/src/Gatherer/WebHookHydrator.php +++ b/src/Gatherer/WebHookHydrator.php @@ -26,7 +26,7 @@ public static function gather( return Hydrator::gather( $baseNamespace, - 'Internal\\WebHook\\' . Utils::className($event), + 'WebHook\\' . Utils::className($event), '🪝', ...$schemaClasses, ); diff --git a/src/Generator.php b/src/Generator.php index 957867a..3168bde 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -61,6 +61,7 @@ use function str_replace; use function strlen; use function strpos; +use function substr; use function trim; use function usleep; use function WyriHaximus\Twig\render; @@ -195,7 +196,7 @@ public function generate(string $namespace, string $namespaceTest, string $confi $codePrinter = new Standard(); foreach ($this->all($configurationLocation) as $file) { - $fileName = $configurationLocation . $this->configuration->destination->root . DIRECTORY_SEPARATOR . $file->pathPrefix . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $file->fqcn) . '.php'; + $fileName = $configurationLocation . $this->configuration->destination->root . DIRECTORY_SEPARATOR . $file->pathPrefix . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $file->fqcn) . (strpos($file->fqcn, '.') !== false ? '' : '.php'); if ($file->contents instanceof Node\Stmt\Namespace_) { array_unshift($file->contents->stmts, ...(static function (array $uses): iterable { foreach ($uses as $use => $alias) { @@ -246,7 +247,10 @@ public function generate(string $namespace, string $namespaceTest, string $confi } } - include_once $fileName; + if (! (strpos($fileName, DIRECTORY_SEPARATOR . 'Types' . DIRECTORY_SEPARATOR) !== false) && substr($fileName, -4) === '.php') { + include_once $fileName; + } + $existingFiles = array_filter( $existingFiles, static fn (string $file): bool => $file !== $fileName, @@ -510,6 +514,7 @@ private function oneClient( yield from Client::generate( $this->configuration, $this->configuration->destination->source . DIRECTORY_SEPARATOR, + $this->configuration->destination->test . DIRECTORY_SEPARATOR, $client, $routers, ); @@ -600,6 +605,7 @@ private function oneClient( 'operations' => $operations, 'webHooks' => $webHooks, ]; + $vars['qa'] = $configuration->qa; return $vars; })( @@ -793,6 +799,7 @@ private function subSplitClient( yield from Client::generate( $this->configuration, $this->configuration->subSplit->subSplitsDestination . DIRECTORY_SEPARATOR . $this->splitPathPrefix($this->configuration->subSplit->rootPackage, '') . $this->configuration->destination->source, + $this->configuration->subSplit->subSplitsDestination . DIRECTORY_SEPARATOR . $this->splitPathPrefix($this->configuration->subSplit->rootPackage, '') . $this->configuration->destination->test, $client, $routers, ); @@ -926,6 +933,7 @@ private function subSplitClient( } })($this->configuration->subSplit->sectionPackage->name, ...$splits), ], + 'qa' => $this->configuration->qa, ], ); $this->statusOutput->markStepDone('generating_templates_files_root_package'); @@ -950,6 +958,7 @@ private function subSplitClient( 'version' => $this->configuration->subSplit->targetVersion, ], ], + 'qa' => $this->configuration->qa, ], ); $this->statusOutput->markStepDone('generating_templates_files_common_package'); @@ -981,6 +990,7 @@ private function subSplitClient( 'version' => $this->configuration->subSplit->targetVersion, ], ], + 'qa' => $this->configuration->qa, ], ); $this->statusOutput->advanceStep('generating_templates_files_subsplit_package'); diff --git a/src/Generator/Client.php b/src/Generator/Client.php index 9f70412..b9b8741 100644 --- a/src/Generator/Client.php +++ b/src/Generator/Client.php @@ -9,6 +9,8 @@ use ApiClients\Tools\OpenApiClientGenerator\Configuration; use ApiClients\Tools\OpenApiClientGenerator\File; use ApiClients\Tools\OpenApiClientGenerator\Generator\Client\Methods\ChunkCount; +use ApiClients\Tools\OpenApiClientGenerator\Generator\Client\PHPStan\ClientCallReturnTypes; +use ApiClients\Tools\OpenApiClientGenerator\Generator\Client\PHPStan\ClientCallReturnTypesTest; use ApiClients\Tools\OpenApiClientGenerator\Generator\Client\Routers; use ApiClients\Tools\OpenApiClientGenerator\Generator\Client\Routers\RouterClass; use ApiClients\Tools\OpenApiClientGenerator\Generator\Helper\Operation; @@ -37,19 +39,22 @@ use function array_shift; use function array_unique; use function count; +use function dirname; use function explode; use function implode; +use function PHPStan\Testing\assertType; use function strlen; use function strpos; use function trim; use function ucfirst; +use const DIRECTORY_SEPARATOR; use const PHP_EOL; final class Client { /** @return iterable */ - public static function generate(Configuration $configuration, string $pathPrefix, Representation\Client $client, Routers $routers): iterable + public static function generate(Configuration $configuration, string $pathPrefix, string $pathPrefixTests, Representation\Client $client, Routers $routers): iterable { $operations = []; foreach ($client->paths as $path) { @@ -515,28 +520,28 @@ public static function generate(Configuration $configuration, string $pathPrefix $class->addStmt( $factory->method('call')->makePublic()->setDocComment( new Doc(implode(PHP_EOL, [ - '// phpcs:disable', + ...($configuration->qa?->phpcs ? ['// phpcs:disable'] : []), '/**', - ' * @return ' . (static function (array $operations): string { - $count = count($operations); - $lastItem = $count - 1; - $left = ''; - $right = ''; - for ($i = 0; $i < $count; $i++) { - $returnType = Operation::getDocBlockResultTypeFromOperation($operations[$i]); - if ($i !== $lastItem) { - $left .= '($call is Operation\\' . $operations[$i]->classNameSanitized->relative . '::OPERATION_MATCH ? ' . $returnType . ' : '; - } else { - $left .= $returnType; - } - - $right .= ')'; - } - - return $left . $right; - })($operations), + // ' * @return ' . (static function (array $operations): string { + // $count = count($operations); + // $lastItem = $count - 1; + // $left = ''; + // $right = ''; + // for ($i = 0; $i < $count; $i++) { + // $returnType = Operation::getDocBlockResultTypeFromOperation($operations[$i]); + // if ($i !== $lastItem) { + // $left .= '($call is "' . $operations[$i]->matchMethod . ' ' . $operations[$i]->path . '" ? ' . $returnType . ' : '; + // } else { + // $left .= $returnType; + // } + // + // $right .= ')'; + // } + // + // return $left . $right; + // })($operations), ' */', - '// phpcs:enable', + ...($configuration->qa?->phpcs ? ['// phpcs:enable'] : []), ])), )->addParam((new Param('call'))->setType('string'))->addParam((new Param('params'))->setType('array')->setDefault([]))->setReturnType( new UnionType( @@ -661,6 +666,28 @@ public static function generate(Configuration $configuration, string $pathPrefix } yield from \ApiClients\Tools\OpenApiClientGenerator\Generator\Routers::generate($configuration, $pathPrefix, $routers); + + if (! $configuration->qa?->phpstan) { + return; + } + + require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'phpstan-assertType-mock.php'; + assertType('bool', true); + + yield from ClientCallReturnTypes::generate($configuration, $pathPrefix, $client); + yield from ClientCallReturnTypesTest::generate($configuration, $pathPrefixTests, $client); + + if ($configuration->qa->phpstan->configFilePath === null) { + return; + } + + yield new File($pathPrefix, '../' . $configuration->qa->phpstan->configFilePath, implode(PHP_EOL, [ + 'services:', + ' - class: ' . $configuration->namespace->source . '\PHPStan\ClientCallReturnTypes', + ' tags:', + ' - phpstan.broker.dynamicMethodReturnTypeExtension', + '', + ])); } /** diff --git a/src/Generator/Client/PHPStan/ClientCallReturnTypes.php b/src/Generator/Client/PHPStan/ClientCallReturnTypes.php new file mode 100644 index 0000000..3c85132 --- /dev/null +++ b/src/Generator/Client/PHPStan/ClientCallReturnTypes.php @@ -0,0 +1,306 @@ + */ + public static function generate(Configuration $configuration, string $pathPrefix, Representation\Client $client): iterable + { + /** @var array $operations */ + $operations = []; + foreach ($client->paths as $path) { + $operations = [...$operations, ...$path->operations]; + } + + $stmts = []; + foreach ($operations as $operation) { + $stmts[] = new Node\Stmt\If_( + new Expr\BinaryOp\Identical( + new Expr\Variable( + new Node\Name( + 'call', + ), + ), + new Node\Scalar\String_($operation->matchMethod . ' ' . $operation->path), + ), + [ + 'stmts' => [ + new Node\Stmt\Return_( + new Expr\MethodCall( + new Expr\PropertyFetch( + new Expr\Variable( + new Node\Name( + 'this', + ), + ), + new Node\Name( + 'typeResolver', + ), + ), + new Node\Name( + 'resolve', + ), + [ + new Arg( + new Node\Scalar\String_( + Operation::getDocBlockResultTypeFromOperation($operation), + ), + ), + ], + ), + ), + ], + ], + ); + } + + $factory = new BuilderFactory(); + $stmt = $factory->namespace(new Node\Name(trim($configuration->namespace->source . '\PHPStan', '\\'))); + $class = $factory->class('ClientCallReturnTypes')->makeFinal()->makeReadonly()->implement( + new Node\Name('\\' . DynamicMethodReturnTypeExtension::class), + )->addStmt( + $factory->property('printer')->makePrivate()->setType('\\' . Standard::class), + )->addStmt( + $factory->method('__construct')->makePublic()->addParam( + $factory->param('typeResolver')->makePrivate()->setType('\\' . TypeStringResolver::class), + )->addStmt( + new Node\Stmt\Expression( + new Expr\Assign( + new Expr\PropertyFetch( + new Expr\Variable( + new Node\Name( + 'this', + ), + ), + new Node\Name( + 'printer', + ), + ), + new Expr\New_( + new Node\Name( + '\\' . Standard::class, + ), + ), + ), + ), + ), + )->addStmt( + $factory->method('getClass')->makePublic()->setReturnType('string')->addStmt( + new Node\Stmt\Return_( + new Expr\ClassConstFetch( + new Node\Name('\\' . $configuration->namespace->source . '\Client'), + new Node\Name('class'), + ), + ), + ), + )->addStmt( + $factory->method('isMethodSupported')->makePublic()->setReturnType('bool')->addParam( + new Node\Param( + new Expr\Variable( + new Node\Name( + 'methodReflection', + ), + ), + null, + new Node\Name( + '\\' . MethodReflection::class, + ), + ), + )->addStmt( + new Node\Stmt\Return_( + new Expr\BinaryOp\Identical( + new Expr\MethodCall( + new Expr\Variable( + new Node\Name( + 'methodReflection', + ), + ), + new Node\Name( + 'getName', + ), + ), + new Node\Scalar\String_('call'), + ), + ), + ), + )->addStmt( + $factory->method('getTypeFromMethodCall')->makePublic()->setReturnType( + new Node\UnionType([ + new Node\Name('null'), + new Node\Name('\\' . Type::class), + ]), + )->addParam( + new Node\Param( + new Expr\Variable( + new Node\Name( + 'methodReflection', + ), + ), + null, + new Node\Name( + '\\' . MethodReflection::class, + ), + ), + )->addParam( + new Node\Param( + new Expr\Variable( + new Node\Name( + 'methodCall', + ), + ), + null, + new Node\Name( + '\\' . MethodCall::class, + ), + ), + )->addParam( + new Node\Param( + new Expr\Variable( + new Node\Name( + 'scope', + ), + ), + null, + new Node\Name( + '\\' . Scope::class, + ), + ), + )->addStmt( + new Node\Stmt\Expression( + new Expr\Assign( + new Expr\Variable( + new Node\Name( + 'args', + ), + ), + new Expr\MethodCall( + new Expr\Variable( + new Node\Name( + 'methodCall', + ), + ), + new Node\Name( + 'getArgs', + ), + ), + ), + ), + )->addStmt( + new Node\Stmt\If_( + new Expr\BinaryOp\Identical( + new Expr\FuncCall( + new Node\Name( + 'count', + ), + [ + new Arg( + new Expr\Variable( + new Node\Name( + 'args', + ), + ), + ), + ], + ), + new Node\Scalar\LNumber(0), + ), + [ + 'stmts' => [ + new Node\Stmt\Return_( + new Expr\ConstFetch( + new Node\Name('null'), + ), + ), + ], + ], + ), + )->addStmt( + new Node\Stmt\Expression( + new Expr\Assign( + new Expr\Variable( + new Node\Name( + 'call', + ), + ), + new Expr\FuncCall( + new Node\Name( + 'substr', + ), + [ + new Arg( + new MethodCall( + new Expr\PropertyFetch( + new Expr\Variable( + new Node\Name( + 'this', + ), + ), + new Node\Name( + 'printer', + ), + ), + new Node\Name( + 'prettyPrintExpr', + ), + [ + new Arg( + new Expr\PropertyFetch( + new Expr\ArrayDimFetch( + new Expr\Variable( + new Node\Name( + 'args', + ), + ), + new Node\Scalar\LNumber(0), + ), + new Node\Name( + 'value', + ), + ), + ), + ], + ), + ), + new Arg( + new Node\Scalar\LNumber(1), + ), + new Arg( + new Node\Scalar\LNumber(-1), + ), + ], + ), + ), + ), + )->addStmts($stmts)->addStmt( + new Node\Stmt\Return_( + new Expr\ConstFetch( + new Node\Name('null'), + ), + ), + ), + ); + + yield new File($pathPrefix, 'PHPStan\ClientCallReturnTypes', $stmt->addStmt($class)->getNode()); + } +} diff --git a/src/Generator/Client/PHPStan/ClientCallReturnTypesTest.php b/src/Generator/Client/PHPStan/ClientCallReturnTypesTest.php new file mode 100644 index 0000000..47cedef --- /dev/null +++ b/src/Generator/Client/PHPStan/ClientCallReturnTypesTest.php @@ -0,0 +1,118 @@ + */ + public static function generate(Configuration $configuration, string $pathPrefix, Representation\Client $client): iterable + { + $operations = []; + foreach ($client->paths as $path) { + $operations = [...$operations, ...$path->operations]; + } + + $factory = new BuilderFactory(); + $stmt = $factory->namespace(new Node\Name(trim($configuration->namespace->test . '\\Types', '\\'))); + + $stmt->addStmt( + new Node\Stmt\Expression( + new Expr\Assign( + new Expr\Variable( + new Node\Name( + 'client', + ), + ), + new Expr\New_( + new Node\Name( + '\\' . $configuration->namespace->source . '\\Client', + ), + [ + new Arg( + new Expr\New_( + new Node\Stmt\Class_( + null, + [ + 'implements' => [ + new Node\Name('\\' . AuthenticationInterface::class), + ], + 'stmts' => [ + $factory->method('authHeader')->setReturnType( + new Node\Name('string'), + )->addStmt( + new Node\Stmt\Return_( + new Node\Scalar\String_('Saturn V'), + ), + )->getNode(), + ], + ], + ), + ), + ), + new Arg( + new Expr\New_( + new Node\Name( + '\\' . Browser::class, + ), + ), + ), + ], + ), + ), + ), + ); + + foreach ($operations as $operation) { + $stmt->addStmt( + new Node\Stmt\Expression( + new Expr\FuncCall( + new Node\Name( + '\PHPStan\Testing\assertType', + ), + [ + new Arg( + new Node\Scalar\String_( + Operation::getDocBlockResultTypeFromOperation($operation), + ), + ), + new Arg( + new Expr\MethodCall( + new Expr\Variable( + new Node\Name( + 'client', + ), + ), + new Node\Name( + 'call', + ), + [ + new Arg( + new Node\Scalar\String_($operation->matchMethod . ' ' . $operation->path), + ), + ], + ), + ), + ], + ), + ), + ); + } + + yield new File($pathPrefix, 'Types\ClientCallReturnTypes', $stmt->getNode()); + } +} diff --git a/src/Generator/ClientInterface.php b/src/Generator/ClientInterface.php index 5f0db3b..4b7db9d 100644 --- a/src/Generator/ClientInterface.php +++ b/src/Generator/ClientInterface.php @@ -17,7 +17,6 @@ use function array_map; use function array_unique; -use function count; use function explode; use function implode; use function trim; @@ -42,28 +41,28 @@ public static function generate(Configuration $configuration, string $pathPrefix $class->addStmt( $factory->method('call')->makePublic()->setDocComment( new Doc(implode(PHP_EOL, [ - '// phpcs:disable', + ...($configuration->qa?->phpcs ? ['// phpcs:disable'] : []), '/**', - ' * @return ' . (static function (array $operations): string { - $count = count($operations); - $lastItem = $count - 1; - $left = ''; - $right = ''; - for ($i = 0; $i < $count; $i++) { - $returnType = \ApiClients\Tools\OpenApiClientGenerator\Generator\Helper\Operation::getDocBlockResultTypeFromOperation($operations[$i]); - if ($i !== $lastItem) { - $left .= '($call is Operation\\' . $operations[$i]->classNameSanitized->relative . '::OPERATION_MATCH ? ' . $returnType . ' : '; - } else { - $left .= $returnType; - } - - $right .= ')'; - } - - return $left . $right; - })($operations), + // ' * @return ' . (static function (array $operations): string { + // $count = count($operations); + // $lastItem = $count - 1; + // $left = ''; + // $right = ''; + // for ($i = 0; $i < $count; $i++) { + // $returnType = \ApiClients\Tools\OpenApiClientGenerator\Generator\Helper\Operation::getDocBlockResultTypeFromOperation($operations[$i]); + // if ($i !== $lastItem) { + // $left .= '($call is "' . $operations[$i]->matchMethod . ' ' . $operations[$i]->path . '" ? ' . $returnType . ' : '; + // } else { + // $left .= $returnType; + // } + // + // $right .= ')'; + // } + // + // return $left . $right; + // })($operations), ' */', - '// phpcs:enable', + ...($configuration->qa?->phpcs ? ['// phpcs:enabled'] : []), ])), )->addParam((new Param('call'))->setType('string'))->addParam((new Param('params'))->setType('array')->setDefault([]))->setReturnType( new UnionType( diff --git a/src/Generator/Helper/Operation.php b/src/Generator/Helper/Operation.php index cd0de2c..38d273b 100644 --- a/src/Generator/Helper/Operation.php +++ b/src/Generator/Helper/Operation.php @@ -156,6 +156,22 @@ public static function getDocBlockResultTypeFromOperation(Representation\Operati private static function convertObservableIntoIterable(string $string): string { - return str_replace(['\\' . Observable::class, '(', ' ', ')'], ['iterable', '', '', ''], $string); + return str_replace( + [ + '\\' . Observable::class . '<', + '\\' . Observable::class, + '(', + ' ', + ')', + ], + [ + 'iterablegetTypes()), + })(...[ + ...Types::filterDuplicatesAndIncompatibleRawTypes(...array_map( + static fn (ReflectionType $type): string => (string) $type, + $reflection->getTypes(), + )), + ]), ], ); diff --git a/src/Generator/Helper/Types.php b/src/Generator/Helper/Types.php index 9c2f557..4fc58ea 100644 --- a/src/Generator/Helper/Types.php +++ b/src/Generator/Helper/Types.php @@ -34,10 +34,6 @@ public static function normalizeRaw(string ...$types): array { return array_map( static function (string $type): string { - if (substr($type, 0, 6) === 'array{') { - return 'array'; - } - if (in_array($type, self::SCALARS) || substr($type, 0, 1) === '\\') { return $type; } @@ -61,9 +57,17 @@ public static function normalizeNodeName(string ...$types): array public static function filterDuplicatesAndIncompatibleRawTypes(string ...$types): iterable { $keepVoid = true; - $keepArray = true; + $keepArray = false; $duplicates = []; + foreach ($types as $type) { + if ($type !== 'array') { + continue; + } + + $keepArray = true; + } + foreach ($types as $type) { if ($type !== 'void') { $keepVoid = false; diff --git a/src/Generator/Operation.php b/src/Generator/Operation.php index dfc8fb1..b3502c9 100644 --- a/src/Generator/Operation.php +++ b/src/Generator/Operation.php @@ -4,6 +4,8 @@ namespace ApiClients\Tools\OpenApiClientGenerator\Generator; +use ApiClients\Tools\OpenApiClient\Utils\Response\Header; +use ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody; use ApiClients\Tools\OpenApiClientGenerator\Configuration; use ApiClients\Tools\OpenApiClientGenerator\File; use ApiClients\Tools\OpenApiClientGenerator\Generator\Helper\OperationArray; @@ -82,30 +84,6 @@ public static function generate(string $pathPrefix, \ApiClients\Tools\OpenApiCli ], Class_::MODIFIER_PUBLIC, ), - )->addStmt( - new Node\Stmt\ClassConst( - [ - new Node\Const_( - 'METHOD', - new Node\Scalar\String_( - $operation->method, - ), - ), - ], - Class_::MODIFIER_PRIVATE, - ), - )->addStmt( - new Node\Stmt\ClassConst( - [ - new Node\Const_( - 'PATH', - new Node\Scalar\String_( - $operation->path, // Deal with the query - ), - ), - ], - Class_::MODIFIER_PRIVATE, - ), ); if (count($operation->requestBody) > 0) { $class->addStmt( @@ -176,24 +154,19 @@ public static function generate(string $pathPrefix, \ApiClients\Tools\OpenApiCli } $requestParameters = [ - new Node\Arg(new Node\Expr\ClassConstFetch( - new Node\Name('self'), - 'METHOD', - )), + new Node\Arg(new Node\Scalar\String_($operation->method)), new Node\Arg(new Node\Expr\FuncCall( new Node\Name('\str_replace'), [ new Node\Arg(new Node\Expr\Array_(array_map(static fn (string $key): Node\Expr\ArrayItem => new Node\Expr\ArrayItem(new Node\Scalar\String_($key)), array_keys($requestReplaces)))), new Node\Arg(new Node\Expr\Array_(array_map(static fn (Node\Expr\PropertyFetch $pf): Node\Expr\ArrayItem => new Node\Expr\ArrayItem($pf), array_values($requestReplaces)))), new Node\Arg(count($query) > 0 ? new Node\Expr\BinaryOp\Concat( - new Node\Expr\ClassConstFetch( - new Node\Name('self'), - 'PATH', + new Node\Scalar\String_( + $operation->path, // Deal with the query ), new Node\Scalar\String_(rtrim('?' . implode('&', $query), '?')), - ) : new Node\Expr\ClassConstFetch( - new Node\Name('self'), - 'PATH', + ) : new Node\Scalar\String_( + $operation->path, // Deal with the query )), ], )), @@ -324,7 +297,7 @@ public static function generate(string $pathPrefix, \ApiClients\Tools\OpenApiCli new Node\Stmt\Return_(new Node\Expr\MethodCall( new Node\Expr\PropertyFetch( new Node\Expr\Variable('this'), - 'hydrators', + 'hydrator', ), 'hydrateObject', [ @@ -717,27 +690,44 @@ public static function generate(string $pathPrefix, \ApiClients\Tools\OpenApiCli $returnType[] = '\\' . Observable::class . ''; $returnTypeRaw[] = '\\' . Observable::class; } else { - $arrayItems = []; - $arrayItems['code: int'] = new Node\Expr\ArrayItem( - new Node\Scalar\LNumber($empty->code), - new Node\Scalar\String_('code'), - ); + $arrayItems = []; foreach ($empty->headers as $header) { $arrayItems[strtolower($header->name) . ': string'] = new Node\Expr\ArrayItem( - new Node\Expr\MethodCall( - new Node\Expr\Variable('response'), - 'getHeaderLine', + new Node\Expr\New_( + new Node\Name('\\' . Header::class), [ - new Arg(new Node\Scalar\String_($header->name)), + new Arg( + new Node\Scalar\String_(strtolower($header->name)), + ), + new Arg( + new Node\Expr\MethodCall( + new Node\Expr\Variable('response'), + 'getHeaderLine', + [ + new Arg(new Node\Scalar\String_($header->name)), + ], + ), + ), ], ), - new Node\Scalar\String_(strtolower($header->name)), ); } - $returnType[] = 'array{' . implode(',', array_keys($arrayItems)) . '}'; - $returnTypeRaw[] = 'array'; - $empties[] = new Node\Stmt\Return_(new Node\Expr\Array_(array_values($arrayItems))); +// 'array{' . implode(',', array_keys($arrayItems)) . '}'; + $returnType[] = $returnTypeRaw[] = '\\' . WithoutBody::class; + $empties[] = new Node\Stmt\Return_( + new Node\Expr\New_( + new Node\Name('\\' . WithoutBody::class), + [ + new Arg( + new Node\Scalar\LNumber($empty->code), + ), + new Arg( + new Node\Expr\Array_(array_values($arrayItems)), + ), + ], + ), + ); } $emptyCase = new Node\Stmt\Case_( diff --git a/src/Generator/Operator.php b/src/Generator/Operator.php index 54e6768..47f5630 100644 --- a/src/Generator/Operator.php +++ b/src/Generator/Operator.php @@ -225,16 +225,10 @@ private static function callOperation(string $returnType, Operation $operation): 'returnType' => (static function (Representation\Operation $operation): Node\UnionType|Node\Name { /** @phpstan-ignore-next-line */ $returnType = (new ReflectionClass($operation->className->fullyQualified->source))->getMethod('createResponse')->getReturnType(); - if ($returnType === null) { + if ($returnType === null || (string) $returnType === 'void') { return new Node\Name('void'); } - if ((string) $returnType === 'void') { - return new Node\Name( - (string) $returnType, - ); - } - return new Node\UnionType( array_map( static fn (string $object): Node\Name => new Node\Name((strpos($object, '\\') > 0 ? '\\' : '') . $object), diff --git a/src/Generator/Schema/CastUnionToType.php b/src/Generator/Schema/CastUnionToType.php index b944595..b418a76 100644 --- a/src/Generator/Schema/CastUnionToType.php +++ b/src/Generator/Schema/CastUnionToType.php @@ -19,6 +19,7 @@ use function array_shift; use function count; use function implode; +use function sort; final class CastUnionToType { @@ -111,9 +112,14 @@ public static function generate(string $pathPrefix, ClassString $classString, Sc '|', [ ...(static function (Property ...$properties): iterable { + $names = []; foreach ($properties as $property) { - yield $property->sourceName; + $names[] = $property->sourceName; } + + sort($names); + + return $names; })(...$schema->properties), ], ), diff --git a/src/Generator/WebHook.php b/src/Generator/WebHook.php index f36ef30..d86f0c8 100644 --- a/src/Generator/WebHook.php +++ b/src/Generator/WebHook.php @@ -42,7 +42,7 @@ public static function generate( $className = Utils::className($event); $factory = new BuilderFactory(); - $stmt = $factory->namespace(ltrim($namespace . 'WebHook', '\\')); + $stmt = $factory->namespace(ltrim($namespace . 'Internal\WebHook', '\\')); $class = $factory->class(ltrim($className, '\\'))->makeFinal()->implement('\\' . WebHookInterface::class)->setDocComment(new Doc(implode(PHP_EOL, [ '/**', @@ -50,12 +50,12 @@ public static function generate( ' */', ]))); $class->addStmt($factory->property('requestSchemaValidator')->setType('\\' . SchemaValidator::class)->makeReadonly()->makePrivate()); - $class->addStmt($factory->property('hydrator')->setType('Internal\\Hydrator\\WebHook' . $className)->makeReadonly()->makePrivate()); + $class->addStmt($factory->property('hydrator')->setType('Internal\\Hydrator\\WebHook\\' . $className)->makeReadonly()->makePrivate()); $constructor = $factory->method('__construct')->makePublic()->addParam( (new Param('requestSchemaValidator'))->setType('\\' . SchemaValidator::class), )->addParam( - (new Param('hydrator'))->setType('Internal\\Hydrator\\WebHook' . $className), + (new Param('hydrator'))->setType('Internal\\Hydrator\\WebHook\\' . $className), )->addStmt( new Node\Expr\Assign( new Node\Expr\PropertyFetch( diff --git a/src/Generator/WebHooks.php b/src/Generator/WebHooks.php index a080259..8b4dd41 100644 --- a/src/Generator/WebHooks.php +++ b/src/Generator/WebHooks.php @@ -225,7 +225,7 @@ public static function generate(string $pathPrefix, string $namespace, array $we ); foreach ($webHooks as $event => $hooks) { - $eventClassname = 'WebHook' . Utils::className($event); + $eventClassname = 'Internal\WebHook\\' . Utils::className($event); $eventSanitized = lcfirst((new Convert($event))->toPascal()); $class->addStmt($factory->property($eventSanitized)->setType('?' . $eventClassname)->setDefault(null)->makePrivate()); diff --git a/src/phpstan-assertType-mock.php b/src/phpstan-assertType-mock.php new file mode 100644 index 0000000..2cb4e49 --- /dev/null +++ b/src/phpstan-assertType-mock.php @@ -0,0 +1,9 @@ + 0 %} +"suggest": { +{% for suggest in suggests %} +"api-clients/{{ suggest.name }}": "{{ suggest.reason }}"{% if not loop.last %},{% endif %} +{% endfor %} +}, +{% endif %} +{% if qa.phpstan.enabled is constant('true') and qa.phpstan.configFilePath is not constant('null') %} + "extra": { + "phpstan": { + "includes": [ + "{{ qa.phpstan.configFilePath }}" + ] + } + }, +{% endif %} + "config": { + "sort-packages": true, + "platform": { + "php": "8.2.13" + }, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "composer/package-versions-deprecated": true, + "ergebnis/composer-normalize": true, + "icanhazstring/composer-unused": true, + "wyrihaximus/composer-update-bin-autoload-path": true, + "infection/extension-installer": true + } + } +} diff --git a/tests/app/Makefile b/tests/app/Makefile new file mode 100644 index 0000000..9d7ac0f --- /dev/null +++ b/tests/app/Makefile @@ -0,0 +1,64 @@ +# set all to phony +SHELL=bash + +.PHONY: * + +DOCKER_CGROUP:=$(shell cat /proc/1/cgroup | grep docker | wc -l) +COMPOSER_CACHE_DIR:=$(shell composer config --global cache-dir -q || echo ${HOME}/.composer/cache) + +ifneq ("$(wildcard /.dockerenv)","") + IN_DOCKER:=TRUE +else ifneq ("$(DOCKER_CGROUP)","0") + IN_DOCKER:=TRUE +else + IN_DOCKER:=FALSE +endif + +ifeq ("$(IN_DOCKER)","TRUE") + DOCKER_RUN:= +else + PHP_VERSION:=$(shell docker run --rm -v "`pwd`:`pwd`" jess/jq jq -r -c '.config.platform.php' "`pwd`/composer.json" | php -r "echo str_replace('|', '.', explode('.', implode('|', explode('.', stream_get_contents(STDIN), 2)), 2)[0]);") + DOCKER_RUN:=docker run --rm -it \ + -v "`pwd`:`pwd`" \ + -v "${COMPOSER_CACHE_DIR}:/home/app/.composer/cache" \ + -w "`pwd`" \ + "ghcr.io/wyrihaximusnet/php:${PHP_VERSION}-nts-alpine-slim-dev" +endif + +all: ## Runs everything ### + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | grep -v "###" | awk 'BEGIN {FS = ":.*?## "}; {printf "%s\n", $$1}' | xargs --open-tty $(MAKE) + +syntax-php: ## Lint PHP syntax + $(DOCKER_RUN) vendor/bin/parallel-lint --exclude vendor . + +cs-fix: ## Fix any automatically fixable code style issues + $(DOCKER_RUN) vendor/bin/phpcbf --parallel=$(shell nproc) --standard=./etc/qa/phpcs.xml || $(DOCKER_RUN) vendor/bin/phpcbf --parallel=$(shell nproc) --standard=./etc/qa/phpcs.xml + +cs: ## Check the code for code style issues + $(DOCKER_RUN) vendor/bin/phpcs --parallel=$(shell nproc) --standard=./etc/qa/phpcs.xml + +stan: ## Run static analysis (PHPStan) + $(DOCKER_RUN) vendor/bin/phpstan analyse src tests --level max --ansi -c ./etc/qa/phpstan.neon + +psalm: ## Run static analysis (Psalm) + $(DOCKER_RUN) vendor/bin/psalm --threads=$(shell nproc) --shepherd --stats --config=./etc/qa/psalm.xml + +unit-testing: ## Run tests + $(DOCKER_RUN) vendor/bin/phpunit --colors=always -c ./etc/qa/phpunit.xml + $(DOCKER_RUN) test -n "$(COVERALLS_REPO_TOKEN)" && test -n "$(COVERALLS_RUN_LOCALLY)" && test -f ./var/tests-unit-clover-coverage.xml && vendor/bin/php-coveralls -v --coverage_clover ./build/logs/clover.xml --json_path ./var/tests-unit-clover-coverage-upload.json || true + +mutation-testing: ## Run mutation testing + $(DOCKER_RUN) vendor/bin/infection --ansi --min-msi=100 --min-covered-msi=100 --threads=$(shell nproc) --ignore-msi-with-no-mutations || (cat ./var/infection.log && false) + +backward-compatibility-check: ## Check code for backwards incompatible changes + $(DOCKER_RUN) vendor/bin/roave-backward-compatibility-check || true + +shell: ## Provides Shell access in the expected environment ### + $(DOCKER_RUN) ash + +task-list-ci: ## CI: Generate a JSON array of jobs to run, matches the commands run when running `make (|all)` ### + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | grep -v "###" | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%s\n", $$1}' | jq --raw-input --slurp -c 'split("\n")| .[0:-1]' + +help: ## Show this help ### + @printf "\033[33mUsage:\033[0m\n make [target]\n\n\033[33mTargets:\033[0m\n" + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[32m%-32s\033[0m %s\n", $$1, $$2}' | tr -d '#' diff --git a/tests/app/composer.json b/tests/app/composer.json new file mode 100644 index 0000000..d88d0c9 --- /dev/null +++ b/tests/app/composer.json @@ -0,0 +1,57 @@ +{ + "name": "api-clients/petsore", + "description": "Non-Blocking first PetStore client", + "license": "MIT", + "authors": [ + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + } + ], + "require": { + "php": "^8.2", + "api-clients/contracts": "^0.1", + "api-clients/openapi-client-utils": "dev-main", + "devizzent/cebe-php-openapi": "^1", + "eventsauce/object-hydrator": "^1.1", + "league/openapi-psr7-validator": "^0.21", + "psr/http-message": "^1.0", + "react/http": "^1.8", + "react/async": "^4.0", + "wyrihaximus/react-awaitable-observable": "^1.0" + }, + "require-dev": { + "wyrihaximus/async-test-utilities": "^7" + }, + "autoload": { + "psr-4": { + "ApiClients\\Client\\PetStore\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "ApiClients\\Client\\PetStore\\": "src/" + } + }, + "extra": { + "phpstan": { + "includes": [ + "etc/phpstan-extension.neon" + ] + } + }, + "config": { + "sort-packages": true, + "platform": { + "php": "8.2.13" + }, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "composer/package-versions-deprecated": true, + "ergebnis/composer-normalize": true, + "icanhazstring/composer-unused": true, + "wyrihaximus/composer-update-bin-autoload-path": true, + "infection/extension-installer": true + } + } +} diff --git a/tests/app/etc/openapi-client-generator.state b/tests/app/etc/openapi-client-generator.state index 33b2811..4228851 100644 --- a/tests/app/etc/openapi-client-generator.state +++ b/tests/app/etc/openapi-client-generator.state @@ -4,11 +4,11 @@ "files": [ { "name": ".\/tests\/app\/src\/\/Internal\/Operation\/Pets\/List_.php", - "hash": "c520c2f0ff0936c2ba29a39e435b5f28" + "hash": "3335d838b36c19fa3df3a5611de1327b" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operator\/Pets\/List_.php", - "hash": "db5a45157ecec422ce19330c0498fe13" + "hash": "4ebf25c09b352c6bf1cb90ba82dc4cd6" }, { "name": ".\/tests\/app\/tests\/\/Internal\/Operation\/Pets\/List_Test.php", @@ -16,11 +16,11 @@ }, { "name": ".\/tests\/app\/src\/\/Internal\/Operation\/Pets\/ListListing.php", - "hash": "17f17aa7bf998e158be5bbdea09a1663" + "hash": "0d9967a302ca7fb3d6caac3c64053973" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operator\/Pets\/ListListing.php", - "hash": "2c63dfcc725dd37b98b07d9652333ca0" + "hash": "c11b29843d4a000f2707d1c8fadcffef" }, { "name": ".\/tests\/app\/tests\/\/Internal\/Operation\/Pets\/ListListingTest.php", @@ -28,11 +28,11 @@ }, { "name": ".\/tests\/app\/src\/\/Internal\/Operation\/Pets\/Create.php", - "hash": "9c62dcb98ecfd7e7c1c24800e233af0a" + "hash": "7c8734f0d61928c3f40976535c41da3f" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operator\/Pets\/Create.php", - "hash": "bd65b8b37923a642d6924766b01e212e" + "hash": "7558d10cb6b365376dbd1bd4772644bc" }, { "name": ".\/tests\/app\/tests\/\/Internal\/Operation\/Pets\/CreateTest.php", @@ -40,11 +40,11 @@ }, { "name": ".\/tests\/app\/src\/\/Internal\/Operation\/Pets\/List_\/Gatos.php", - "hash": "8d589bf7297e74b697e9e62c056466b9" + "hash": "5f881cdd1eb2f8375929f7abfbd33c7d" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operator\/Pets\/List_\/Gatos.php", - "hash": "8ff4102b1deed87c589211b7e9c3d2f4" + "hash": "9a0e8b8f7719fccb70e7cc4e0832d268" }, { "name": ".\/tests\/app\/tests\/\/Internal\/Operation\/Pets\/List_\/GatosTest.php", @@ -52,11 +52,11 @@ }, { "name": ".\/tests\/app\/src\/\/Internal\/Operation\/Pets\/List_\/GatosListing.php", - "hash": "fdea8c007fe7072c4bc4ae8c79fe609e" + "hash": "eafb9b140f372014143fd7d1b3e271f7" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operator\/Pets\/List_\/GatosListing.php", - "hash": "11a4db25d23f28b147cefa3436042ed8" + "hash": "ebd439f04cc01b4059112f4f08f6cd6c" }, { "name": ".\/tests\/app\/tests\/\/Internal\/Operation\/Pets\/List_\/GatosListingTest.php", @@ -64,11 +64,11 @@ }, { "name": ".\/tests\/app\/src\/\/Internal\/Operation\/Pets\/Names.php", - "hash": "bcdcc705445a5803e16b9bc6553701dd" + "hash": "b84ca3b1cab00b4be051ad86b73cbdd1" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operator\/Pets\/Names.php", - "hash": "00fad21c38012a792a3e550b401c9891" + "hash": "1337e618e38f0a989814088eb4f9d09a" }, { "name": ".\/tests\/app\/tests\/\/Internal\/Operation\/Pets\/NamesTest.php", @@ -76,11 +76,11 @@ }, { "name": ".\/tests\/app\/src\/\/Internal\/Operation\/Pets\/NamesListing.php", - "hash": "d6e405d66fa8b664f91b551974a0280c" + "hash": "c0b8d49169aae176984d12a0030ecd13" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operator\/Pets\/NamesListing.php", - "hash": "b1f0b2b5896403341c1163eb5a3d09d5" + "hash": "d9969b99380a63a7708871e4d87a040d" }, { "name": ".\/tests\/app\/tests\/\/Internal\/Operation\/Pets\/NamesListingTest.php", @@ -88,11 +88,11 @@ }, { "name": ".\/tests\/app\/src\/\/Internal\/Operation\/ShowPetById.php", - "hash": "efb0c281bf9e0b91e88afa00a0bb4628" + "hash": "99cae2c0f875cde1a0f93475618a9c76" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operator\/ShowPetById.php", - "hash": "e0f9587266693670ee7a500927287376" + "hash": "abfb82c3aeca91bf33f6058ffdbe3eca" }, { "name": ".\/tests\/app\/tests\/\/Internal\/Operation\/ShowPetByIdTest.php", @@ -200,71 +200,83 @@ }, { "name": ".\/tests\/app\/src\/\/ClientInterface.php", - "hash": "12883d3abf5ccbfdba4be51d0cd092ea" + "hash": "9b32fe8d0561625aaca2585bfbb27529" }, { "name": ".\/tests\/app\/src\/\/Client.php", - "hash": "dec525ce049b33285761d36347cbc0ee" + "hash": "3d378f18ff2470116a67981cf84dc721" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/Get\/Pets.php", - "hash": "d9b54a60718206d153f01f8741aebec6" + "hash": "c23546b09a87ba3a455be95bc5c2ce36" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/Get\/PetsList.php", - "hash": "2de1a4d9f16004193fbbd3395c919180" + "hash": "409c03c5e43887620f5f47c9177643c0" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/Get.php", - "hash": "5da596f090eb4bf6dba76eae7cf53096" + "hash": "68edf375bba9f6578afb8274e2b97de7" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/List\/Pets.php", - "hash": "651f29a1308fc8e21c6219bbce675888" + "hash": "b32884ea78f685b86aa1f5c464fc0aaf" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/List\/PetsList.php", - "hash": "abcaf1114e4fa5b795ef3417adfbcc39" + "hash": "153e3322116d7b671682061f90f29487" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/Post\/Pets.php", - "hash": "5271ec8b587344911a6019a31b0d5fe6" + "hash": "8ef945a4100cffc65825a02375b3f04f" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/Get\/Two.php", - "hash": "c1d27734336ca9da314357976f84b3c1" + "hash": "7b7d4b9a968f14f380a92ae6313ce8f4" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/Get\/Three.php", - "hash": "d1cf00580ddd63cb456f6daa199941ff" + "hash": "cfd9ac40faf59d186ef864c659a058dc" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/List\/Two.php", - "hash": "0ad946fda00f4e5b2fa03281ba5cf07b" + "hash": "38ce5494202d78c11ec1d99a3cd50121" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/List\/Three.php", - "hash": "bd635f15168763ab4de5e1eb161ed3cf" + "hash": "ea20389356bf4f898364bb2d942559cb" }, { "name": ".\/tests\/app\/src\/\/Internal\/Router\/Post\/Two.php", - "hash": "278185160910ced7d1a477d51e558302" + "hash": "bb74e1a2fe9780b2919d28071ff187cb" }, { "name": ".\/tests\/app\/src\/\/Internal\/Routers.php", "hash": "27ae653029f6d54ef26c6b156366e3a3" }, + { + "name": ".\/tests\/app\/src\/\/PHPStan\/ClientCallReturnTypes.php", + "hash": "7df241311848c7ffaa377eb789cebb58" + }, + { + "name": ".\/tests\/app\/tests\/\/Types\/ClientCallReturnTypes.php", + "hash": "f614aa6d327b69a2edd47d21ffbe163d" + }, + { + "name": ".\/tests\/app\/src\/\/..\/etc\/phpstan-extension.neon", + "hash": "3d7b9f10231d14a80329ca810f476b3d" + }, { "name": ".\/tests\/app\/src\/\/OperationsInterface.php", - "hash": "2186a89312e99b2ad5884dc51675a9d8" + "hash": "54d7fd0cc8f652ba8c5ca0f490e462a5" }, { "name": ".\/tests\/app\/src\/\/Operation\/Pets.php", - "hash": "1d1bb80363ad7f54a6f312950dfde25c" + "hash": "928ce9f3f462bf874afa055342d8f165" }, { "name": ".\/tests\/app\/src\/\/Operation\/PetsList.php", - "hash": "b000993bf5e1c2f8a705f8ae07f2f508" + "hash": "cbe84bf2d290017ccd0946101d58a7da" }, { "name": ".\/tests\/app\/src\/\/Internal\/Operators.php", @@ -272,7 +284,7 @@ }, { "name": ".\/tests\/app\/src\/\/Operations.php", - "hash": "5c1d8df5d9b95ffe1400781c8a32e362" + "hash": "91f162958d7ac8ac63feaccbb534eb45" }, { "name": ".\/tests\/app\/src\/\/Internal\/Hydrator\/Operation\/Pets.php", @@ -300,7 +312,7 @@ "files": [ { "name": "composer.json", - "hash": "" + "hash": "b5d01de7c1f443ef8e07eb69633cea43" }, { "name": "composer.lock", diff --git a/tests/app/etc/phpstan-extension.neon b/tests/app/etc/phpstan-extension.neon new file mode 100644 index 0000000..2045a81 --- /dev/null +++ b/tests/app/etc/phpstan-extension.neon @@ -0,0 +1,5 @@ +services: + - class: ApiClients\Client\PetStore\PHPStan\ClientCallReturnTypes + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + diff --git a/tests/app/src/Client.php b/tests/app/src/Client.php index a410444d..d29c9cb 100644 --- a/tests/app/src/Client.php +++ b/tests/app/src/Client.php @@ -26,10 +26,9 @@ public function __construct(\ApiClients\Contracts\HTTP\Headers\AuthenticationInt } // phpcs:disable /** - * @return ($call is Operation\Pets\List_::OPERATION_MATCH ? iterable : ($call is Operation\Pets\ListListing::OPERATION_MATCH ? iterable : ($call is Operation\Pets\Create::OPERATION_MATCH ? array{code:int} : ($call is Operation\Pets\List_\Gatos::OPERATION_MATCH ? iterable : ($call is Operation\Pets\List_\GatosListing::OPERATION_MATCH ? iterable : ($call is Operation\Pets\Names::OPERATION_MATCH ? iterable : ($call is Operation\Pets\NamesListing::OPERATION_MATCH ? iterable : Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish)))))))) */ // phpcs:enable - public function call(string $call, array $params = array()) : iterable|\ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish + public function call(string $call, array $params = array()) : iterable|\ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody|\ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish { [$method, $path] = explode(' ', $call); $pathChunks = explode('/', $path); diff --git a/tests/app/src/ClientInterface.php b/tests/app/src/ClientInterface.php index c1ab5cf..3772630 100644 --- a/tests/app/src/ClientInterface.php +++ b/tests/app/src/ClientInterface.php @@ -14,9 +14,8 @@ interface ClientInterface { // phpcs:disable /** - * @return ($call is Operation\Pets\List_::OPERATION_MATCH ? iterable : ($call is Operation\Pets\ListListing::OPERATION_MATCH ? iterable : ($call is Operation\Pets\Create::OPERATION_MATCH ? array{code:int} : ($call is Operation\Pets\List_\Gatos::OPERATION_MATCH ? iterable : ($call is Operation\Pets\List_\GatosListing::OPERATION_MATCH ? iterable : ($call is Operation\Pets\Names::OPERATION_MATCH ? iterable : ($call is Operation\Pets\NamesListing::OPERATION_MATCH ? iterable : Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish)))))))) */ - // phpcs:enable - public function call(string $call, array $params = array()) : iterable|\ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish; + // phpcs:enabled + public function call(string $call, array $params = array()) : iterable|\ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody|\ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish; public function operations() : OperationsInterface; } diff --git a/tests/app/src/Internal/Operation/Pets/Create.php b/tests/app/src/Internal/Operation/Pets/Create.php index 652bd84..5c024e1 100644 --- a/tests/app/src/Internal/Operation/Pets/Create.php +++ b/tests/app/src/Internal/Operation/Pets/Create.php @@ -14,8 +14,6 @@ final class Create { public const OPERATION_ID = 'pets/create'; public const OPERATION_MATCH = 'POST /pets'; - private const METHOD = 'POST'; - private const PATH = '/pets'; private readonly \League\OpenAPIValidation\Schema\SchemaValidator $requestSchemaValidator; private readonly \League\OpenAPIValidation\Schema\SchemaValidator $responseSchemaValidator; private readonly Internal\Hydrator\Operation\Pets $hydrator; @@ -28,12 +26,12 @@ public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $re public function createRequest(array $data) : \Psr\Http\Message\RequestInterface { $this->requestSchemaValidator->validate($data, \cebe\openapi\Reader::readFromJson(Schema\Pets\Create\Request\ApplicationJson::SCHEMA_JSON, \cebe\openapi\spec\Schema::class)); - return new \RingCentral\Psr7\Request(self::METHOD, \str_replace(array(), array(), self::PATH), array('Content-Type' => 'application/json'), json_encode($data)); + return new \RingCentral\Psr7\Request('POST', \str_replace(array(), array(), '/pets'), array('Content-Type' => 'application/json'), json_encode($data)); } /** - * @return array{code: int} + * @return \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody */ - public function createResponse(\Psr\Http\Message\ResponseInterface $response) : array + public function createResponse(\Psr\Http\Message\ResponseInterface $response) : \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody { $code = $response->getStatusCode(); [$contentType] = explode(';', $response->getHeaderLine('Content-Type')); @@ -55,7 +53,7 @@ public function createResponse(\Psr\Http\Message\ResponseInterface $response) : * Null response **/ case 201: - return array('code' => 201); + return new \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody(201, array()); } throw new \RuntimeException('Unable to find matching response code and content type'); } diff --git a/tests/app/src/Internal/Operation/Pets/ListListing.php b/tests/app/src/Internal/Operation/Pets/ListListing.php index 35044e5..8edb254 100644 --- a/tests/app/src/Internal/Operation/Pets/ListListing.php +++ b/tests/app/src/Internal/Operation/Pets/ListListing.php @@ -14,8 +14,6 @@ final class ListListing { public const OPERATION_ID = 'pets/list'; public const OPERATION_MATCH = 'LIST /pets'; - private const METHOD = 'GET'; - private const PATH = '/pets'; /**The number of results per page (max 100). **/ private int $perPage; /**Page number of the results to fetch. **/ @@ -31,7 +29,7 @@ public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $re } public function createRequest() : \Psr\Http\Message\RequestInterface { - return new \RingCentral\Psr7\Request(self::METHOD, \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), self::PATH . '?per_page={per_page}&page={page}')); + return new \RingCentral\Psr7\Request('GET', \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), '/pets' . '?per_page={per_page}&page={page}')); } /** * @return \Rx\Observable @@ -52,28 +50,28 @@ public function createResponse(\Psr\Http\Message\ResponseInterface $response) : $error = new \RuntimeException(); try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Cat::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Cat::class, $body); + return $this->hydrator->hydrateObject(Schema\Cat::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaaa; } items_application_json_two_hundred_aaaaa: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Dog::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Dog::class, $body); + return $this->hydrator->hydrateObject(Schema\Dog::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaab; } items_application_json_two_hundred_aaaab: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Bird::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Bird::class, $body); + return $this->hydrator->hydrateObject(Schema\Bird::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaac; } items_application_json_two_hundred_aaaac: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Fish::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Fish::class, $body); + return $this->hydrator->hydrateObject(Schema\Fish::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaad; } diff --git a/tests/app/src/Internal/Operation/Pets/List_.php b/tests/app/src/Internal/Operation/Pets/List_.php index f30d0c3..f5b9375 100644 --- a/tests/app/src/Internal/Operation/Pets/List_.php +++ b/tests/app/src/Internal/Operation/Pets/List_.php @@ -14,8 +14,6 @@ final class List_ { public const OPERATION_ID = 'pets/list'; public const OPERATION_MATCH = 'GET /pets'; - private const METHOD = 'GET'; - private const PATH = '/pets'; /**The number of results per page (max 100). **/ private int $perPage; /**Page number of the results to fetch. **/ @@ -31,7 +29,7 @@ public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $re } public function createRequest() : \Psr\Http\Message\RequestInterface { - return new \RingCentral\Psr7\Request(self::METHOD, \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), self::PATH . '?per_page={per_page}&page={page}')); + return new \RingCentral\Psr7\Request('GET', \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), '/pets' . '?per_page={per_page}&page={page}')); } /** * @return \Rx\Observable @@ -52,28 +50,28 @@ public function createResponse(\Psr\Http\Message\ResponseInterface $response) : $error = new \RuntimeException(); try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Cat::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Cat::class, $body); + return $this->hydrator->hydrateObject(Schema\Cat::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaaa; } items_application_json_two_hundred_aaaaa: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Dog::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Dog::class, $body); + return $this->hydrator->hydrateObject(Schema\Dog::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaab; } items_application_json_two_hundred_aaaab: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Bird::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Bird::class, $body); + return $this->hydrator->hydrateObject(Schema\Bird::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaac; } items_application_json_two_hundred_aaaac: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Fish::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Fish::class, $body); + return $this->hydrator->hydrateObject(Schema\Fish::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaad; } diff --git a/tests/app/src/Internal/Operation/Pets/List_/Gatos.php b/tests/app/src/Internal/Operation/Pets/List_/Gatos.php index bc2d0a1..db912ff 100644 --- a/tests/app/src/Internal/Operation/Pets/List_/Gatos.php +++ b/tests/app/src/Internal/Operation/Pets/List_/Gatos.php @@ -14,8 +14,6 @@ final class Gatos { public const OPERATION_ID = 'pets/list/gatos'; public const OPERATION_MATCH = 'GET /pets/gatos'; - private const METHOD = 'GET'; - private const PATH = '/pets/gatos'; /**The number of results per page (max 100). **/ private int $perPage; /**Page number of the results to fetch. **/ @@ -31,7 +29,7 @@ public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $re } public function createRequest() : \Psr\Http\Message\RequestInterface { - return new \RingCentral\Psr7\Request(self::METHOD, \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), self::PATH . '?per_page={per_page}&page={page}')); + return new \RingCentral\Psr7\Request('GET', \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), '/pets/gatos' . '?per_page={per_page}&page={page}')); } /** * @return \Rx\Observable @@ -52,7 +50,7 @@ public function createResponse(\Psr\Http\Message\ResponseInterface $response) : $error = new \RuntimeException(); try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Cat::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Cat::class, $body); + return $this->hydrator->hydrateObject(Schema\Cat::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaaa; } diff --git a/tests/app/src/Internal/Operation/Pets/List_/GatosListing.php b/tests/app/src/Internal/Operation/Pets/List_/GatosListing.php index 6e8587f..ac47a15 100644 --- a/tests/app/src/Internal/Operation/Pets/List_/GatosListing.php +++ b/tests/app/src/Internal/Operation/Pets/List_/GatosListing.php @@ -14,8 +14,6 @@ final class GatosListing { public const OPERATION_ID = 'pets/list/gatos'; public const OPERATION_MATCH = 'LIST /pets/gatos'; - private const METHOD = 'GET'; - private const PATH = '/pets/gatos'; /**The number of results per page (max 100). **/ private int $perPage; /**Page number of the results to fetch. **/ @@ -31,7 +29,7 @@ public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $re } public function createRequest() : \Psr\Http\Message\RequestInterface { - return new \RingCentral\Psr7\Request(self::METHOD, \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), self::PATH . '?per_page={per_page}&page={page}')); + return new \RingCentral\Psr7\Request('GET', \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), '/pets/gatos' . '?per_page={per_page}&page={page}')); } /** * @return \Rx\Observable @@ -52,7 +50,7 @@ public function createResponse(\Psr\Http\Message\ResponseInterface $response) : $error = new \RuntimeException(); try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Cat::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Cat::class, $body); + return $this->hydrator->hydrateObject(Schema\Cat::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaaa; } diff --git a/tests/app/src/Internal/Operation/Pets/Names.php b/tests/app/src/Internal/Operation/Pets/Names.php index 06f8f8b..16c0716 100644 --- a/tests/app/src/Internal/Operation/Pets/Names.php +++ b/tests/app/src/Internal/Operation/Pets/Names.php @@ -14,8 +14,6 @@ final class Names { public const OPERATION_ID = 'pets/names'; public const OPERATION_MATCH = 'GET /pets/names'; - private const METHOD = 'GET'; - private const PATH = '/pets/names'; /**The number of results per page (max 100). **/ private int $perPage; /**Page number of the results to fetch. **/ @@ -31,7 +29,7 @@ public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $re } public function createRequest() : \Psr\Http\Message\RequestInterface { - return new \RingCentral\Psr7\Request(self::METHOD, \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), self::PATH . '?per_page={per_page}&page={page}')); + return new \RingCentral\Psr7\Request('GET', \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), '/pets/names' . '?per_page={per_page}&page={page}')); } /** * @return \Rx\Observable diff --git a/tests/app/src/Internal/Operation/Pets/NamesListing.php b/tests/app/src/Internal/Operation/Pets/NamesListing.php index a432289..f95d2fa 100644 --- a/tests/app/src/Internal/Operation/Pets/NamesListing.php +++ b/tests/app/src/Internal/Operation/Pets/NamesListing.php @@ -14,8 +14,6 @@ final class NamesListing { public const OPERATION_ID = 'pets/names'; public const OPERATION_MATCH = 'LIST /pets/names'; - private const METHOD = 'GET'; - private const PATH = '/pets/names'; /**The number of results per page (max 100). **/ private int $perPage; /**Page number of the results to fetch. **/ @@ -31,7 +29,7 @@ public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $re } public function createRequest() : \Psr\Http\Message\RequestInterface { - return new \RingCentral\Psr7\Request(self::METHOD, \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), self::PATH . '?per_page={per_page}&page={page}')); + return new \RingCentral\Psr7\Request('GET', \str_replace(array('{per_page}', '{page}'), array($this->perPage, $this->page), '/pets/names' . '?per_page={per_page}&page={page}')); } /** * @return \Rx\Observable diff --git a/tests/app/src/Internal/Operation/ShowPetById.php b/tests/app/src/Internal/Operation/ShowPetById.php index 26984ea..00ceb0c 100644 --- a/tests/app/src/Internal/Operation/ShowPetById.php +++ b/tests/app/src/Internal/Operation/ShowPetById.php @@ -14,8 +14,6 @@ final class ShowPetById { public const OPERATION_ID = 'showPetById'; public const OPERATION_MATCH = 'GET /pets/{petId}'; - private const METHOD = 'GET'; - private const PATH = '/pets/{petId}'; private readonly \League\OpenAPIValidation\Schema\SchemaValidator $responseSchemaValidator; private readonly Internal\Hydrator\Operation\Pets\PetId $hydrator; public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $responseSchemaValidator, Internal\Hydrator\Operation\Pets\PetId $hydrator) @@ -25,7 +23,7 @@ public function __construct(\League\OpenAPIValidation\Schema\SchemaValidator $re } public function createRequest() : \Psr\Http\Message\RequestInterface { - return new \RingCentral\Psr7\Request(self::METHOD, \str_replace(array(), array(), self::PATH)); + return new \RingCentral\Psr7\Request('GET', \str_replace(array(), array(), '/pets/{petId}')); } /** * @return Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish @@ -45,28 +43,28 @@ public function createResponse(\Psr\Http\Message\ResponseInterface $response) : $error = new \RuntimeException(); try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Cat::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Cat::class, $body); + return $this->hydrator->hydrateObject(Schema\Cat::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaaa; } items_application_json_two_hundred_aaaaa: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Dog::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Dog::class, $body); + return $this->hydrator->hydrateObject(Schema\Dog::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaab; } items_application_json_two_hundred_aaaab: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Bird::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Bird::class, $body); + return $this->hydrator->hydrateObject(Schema\Bird::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaac; } items_application_json_two_hundred_aaaac: try { $this->responseSchemaValidator->validate($body, \cebe\openapi\Reader::readFromJson(Schema\Fish::SCHEMA_JSON, '\\cebe\\openapi\\spec\\Schema')); - return $this->hydrators->hydrateObject(Schema\Fish::class, $body); + return $this->hydrator->hydrateObject(Schema\Fish::class, $body); } catch (\Throwable $error) { goto items_application_json_two_hundred_aaaad; } diff --git a/tests/app/src/Internal/Operator/Pets/Create.php b/tests/app/src/Internal/Operator/Pets/Create.php index b71d649..f151119 100644 --- a/tests/app/src/Internal/Operator/Pets/Create.php +++ b/tests/app/src/Internal/Operator/Pets/Create.php @@ -18,13 +18,13 @@ public function __construct(private \React\Http\Browser $browser, private \ApiCl { } /** - * @return array{code:int} + * @return \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody */ - public function call(array $params) : array + public function call(array $params) : \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody { $operation = new \ApiClients\Client\PetStore\Internal\Operation\Pets\Create($this->requestSchemaValidator, $this->responseSchemaValidator, $this->hydrator); $request = $operation->createRequest($params); - $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : array { + $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody { return $operation->createResponse($response); })); if ($result instanceof \Rx\Observable) { diff --git a/tests/app/src/Internal/Operator/Pets/ListListing.php b/tests/app/src/Internal/Operator/Pets/ListListing.php index dcb7171..26cfa31 100644 --- a/tests/app/src/Internal/Operator/Pets/ListListing.php +++ b/tests/app/src/Internal/Operator/Pets/ListListing.php @@ -18,13 +18,13 @@ public function __construct(private \React\Http\Browser $browser, private \ApiCl { } /** - * @return iterable + * @return iterable */ public function call(int $perPage = 30, int $page = 1) : iterable { $operation = new \ApiClients\Client\PetStore\Internal\Operation\Pets\ListListing($this->responseSchemaValidator, $this->hydrator, $perPage, $page); $request = $operation->createRequest(); - $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable|array { + $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable { return $operation->createResponse($response); })); if ($result instanceof \Rx\Observable) { diff --git a/tests/app/src/Internal/Operator/Pets/List_.php b/tests/app/src/Internal/Operator/Pets/List_.php index 8eb07d4..9e4cb2c 100644 --- a/tests/app/src/Internal/Operator/Pets/List_.php +++ b/tests/app/src/Internal/Operator/Pets/List_.php @@ -18,13 +18,13 @@ public function __construct(private \React\Http\Browser $browser, private \ApiCl { } /** - * @return iterable + * @return iterable */ public function call(int $perPage = 30, int $page = 1) : iterable { $operation = new \ApiClients\Client\PetStore\Internal\Operation\Pets\List_($this->responseSchemaValidator, $this->hydrator, $perPage, $page); $request = $operation->createRequest(); - $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable|array { + $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable { return $operation->createResponse($response); })); if ($result instanceof \Rx\Observable) { diff --git a/tests/app/src/Internal/Operator/Pets/List_/Gatos.php b/tests/app/src/Internal/Operator/Pets/List_/Gatos.php index 92b9f9f..a29a055 100644 --- a/tests/app/src/Internal/Operator/Pets/List_/Gatos.php +++ b/tests/app/src/Internal/Operator/Pets/List_/Gatos.php @@ -18,13 +18,13 @@ public function __construct(private \React\Http\Browser $browser, private \ApiCl { } /** - * @return iterable + * @return iterable */ public function call(int $perPage = 30, int $page = 1) : iterable { $operation = new \ApiClients\Client\PetStore\Internal\Operation\Pets\List_\Gatos($this->responseSchemaValidator, $this->hydrator, $perPage, $page); $request = $operation->createRequest(); - $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable|array { + $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable { return $operation->createResponse($response); })); if ($result instanceof \Rx\Observable) { diff --git a/tests/app/src/Internal/Operator/Pets/List_/GatosListing.php b/tests/app/src/Internal/Operator/Pets/List_/GatosListing.php index 2a612ec..de81575 100644 --- a/tests/app/src/Internal/Operator/Pets/List_/GatosListing.php +++ b/tests/app/src/Internal/Operator/Pets/List_/GatosListing.php @@ -18,13 +18,13 @@ public function __construct(private \React\Http\Browser $browser, private \ApiCl { } /** - * @return iterable + * @return iterable */ public function call(int $perPage = 30, int $page = 1) : iterable { $operation = new \ApiClients\Client\PetStore\Internal\Operation\Pets\List_\GatosListing($this->responseSchemaValidator, $this->hydrator, $perPage, $page); $request = $operation->createRequest(); - $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable|array { + $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable { return $operation->createResponse($response); })); if ($result instanceof \Rx\Observable) { diff --git a/tests/app/src/Internal/Operator/Pets/Names.php b/tests/app/src/Internal/Operator/Pets/Names.php index 1b0f3d8..45ca604 100644 --- a/tests/app/src/Internal/Operator/Pets/Names.php +++ b/tests/app/src/Internal/Operator/Pets/Names.php @@ -18,13 +18,13 @@ public function __construct(private \React\Http\Browser $browser, private \ApiCl { } /** - * @return iterable + * @return iterable */ public function call(int $perPage = 30, int $page = 1) : iterable { $operation = new \ApiClients\Client\PetStore\Internal\Operation\Pets\Names($this->responseSchemaValidator, $this->hydrator, $perPage, $page); $request = $operation->createRequest(); - $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable|array { + $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable { return $operation->createResponse($response); })); if ($result instanceof \Rx\Observable) { diff --git a/tests/app/src/Internal/Operator/Pets/NamesListing.php b/tests/app/src/Internal/Operator/Pets/NamesListing.php index e73e5c9..5c4f3d7 100644 --- a/tests/app/src/Internal/Operator/Pets/NamesListing.php +++ b/tests/app/src/Internal/Operator/Pets/NamesListing.php @@ -18,13 +18,13 @@ public function __construct(private \React\Http\Browser $browser, private \ApiCl { } /** - * @return iterable + * @return iterable */ public function call(int $perPage = 30, int $page = 1) : iterable { $operation = new \ApiClients\Client\PetStore\Internal\Operation\Pets\NamesListing($this->responseSchemaValidator, $this->hydrator, $perPage, $page); $request = $operation->createRequest(); - $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable|array { + $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \Rx\Observable { return $operation->createResponse($response); })); if ($result instanceof \Rx\Observable) { diff --git a/tests/app/src/Internal/Operator/ShowPetById.php b/tests/app/src/Internal/Operator/ShowPetById.php index 30052f2..944d30e 100644 --- a/tests/app/src/Internal/Operator/ShowPetById.php +++ b/tests/app/src/Internal/Operator/ShowPetById.php @@ -20,11 +20,11 @@ public function __construct(private \React\Http\Browser $browser, private \ApiCl /** * @return Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish */ - public function call() : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish|array + public function call() : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish { $operation = new \ApiClients\Client\PetStore\Internal\Operation\ShowPetById($this->responseSchemaValidator, $this->hydrator); $request = $operation->createRequest(); - $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish|array { + $result = \React\Async\await($this->browser->request($request->getMethod(), (string) $request->getUri(), $request->withHeader('Authorization', $this->authentication->authHeader())->getHeaders(), (string) $request->getBody())->then(function (\Psr\Http\Message\ResponseInterface $response) use($operation) : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish { return $operation->createResponse($response); })); if ($result instanceof \Rx\Observable) { diff --git a/tests/app/src/Internal/Router/Get.php b/tests/app/src/Internal/Router/Get.php index b01da83..9d166fa 100644 --- a/tests/app/src/Internal/Router/Get.php +++ b/tests/app/src/Internal/Router/Get.php @@ -18,7 +18,7 @@ public function __construct(private \League\OpenAPIValidation\Schema\SchemaValid /** * @return Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish */ - public function showPetById(array $params) : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish|array + public function showPetById(array $params) : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish { $operator = new Internal\Operator\ShowPetById($this->browser, $this->authentication, $this->responseSchemaValidator, $this->hydrators->getObjectMapperOperation🌀Pets🌀PetId()); return $operator->call(); diff --git a/tests/app/src/Internal/Router/Get/Pets.php b/tests/app/src/Internal/Router/Get/Pets.php index 8c2696c..dbd4a54 100644 --- a/tests/app/src/Internal/Router/Get/Pets.php +++ b/tests/app/src/Internal/Router/Get/Pets.php @@ -16,7 +16,7 @@ public function __construct(private \League\OpenAPIValidation\Schema\SchemaValid { } /** - * @return iterable + * @return iterable */ public function list(array $params) : iterable { @@ -35,7 +35,7 @@ public function list(array $params) : iterable return $operator->call($arguments['per_page'], $arguments['page']); } /** - * @return iterable + * @return iterable */ public function names(array $params) : iterable { diff --git a/tests/app/src/Internal/Router/Get/PetsList.php b/tests/app/src/Internal/Router/Get/PetsList.php index dee15c5..b3ef8fd 100644 --- a/tests/app/src/Internal/Router/Get/PetsList.php +++ b/tests/app/src/Internal/Router/Get/PetsList.php @@ -16,7 +16,7 @@ public function __construct(private \League\OpenAPIValidation\Schema\SchemaValid { } /** - * @return iterable + * @return iterable */ public function gatos(array $params) : iterable { diff --git a/tests/app/src/Internal/Router/Get/Three.php b/tests/app/src/Internal/Router/Get/Three.php index 996dc5e..6ddedcc 100644 --- a/tests/app/src/Internal/Router/Get/Three.php +++ b/tests/app/src/Internal/Router/Get/Three.php @@ -16,7 +16,7 @@ public function __construct(private \ApiClients\Client\PetStore\Internal\Routers { } /** - * @return iterable|iterable|Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish + * @return iterable|iterable|Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish */ public function call(string $call, array $params, array $pathChunks) : iterable|\ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish { diff --git a/tests/app/src/Internal/Router/Get/Two.php b/tests/app/src/Internal/Router/Get/Two.php index 0c7b4df..678d83b 100644 --- a/tests/app/src/Internal/Router/Get/Two.php +++ b/tests/app/src/Internal/Router/Get/Two.php @@ -16,7 +16,7 @@ public function __construct(private \ApiClients\Client\PetStore\Internal\Routers { } /** - * @return iterable + * @return iterable */ public function call(string $call, array $params, array $pathChunks) : iterable { diff --git a/tests/app/src/Internal/Router/List/Pets.php b/tests/app/src/Internal/Router/List/Pets.php index 637d522..f469cdb 100644 --- a/tests/app/src/Internal/Router/List/Pets.php +++ b/tests/app/src/Internal/Router/List/Pets.php @@ -16,7 +16,7 @@ public function __construct(private \League\OpenAPIValidation\Schema\SchemaValid { } /** - * @return iterable + * @return iterable */ public function listListing(array $params) : iterable { @@ -40,7 +40,7 @@ public function listListing(array $params) : iterable } while (count($items) > 0); } /** - * @return iterable + * @return iterable */ public function namesListing(array $params) : iterable { diff --git a/tests/app/src/Internal/Router/List/PetsList.php b/tests/app/src/Internal/Router/List/PetsList.php index d4fffe0..d2bcff0 100644 --- a/tests/app/src/Internal/Router/List/PetsList.php +++ b/tests/app/src/Internal/Router/List/PetsList.php @@ -16,7 +16,7 @@ public function __construct(private \League\OpenAPIValidation\Schema\SchemaValid { } /** - * @return iterable + * @return iterable */ public function gatosListing(array $params) : iterable { diff --git a/tests/app/src/Internal/Router/List/Three.php b/tests/app/src/Internal/Router/List/Three.php index be30fac..ef917a3 100644 --- a/tests/app/src/Internal/Router/List/Three.php +++ b/tests/app/src/Internal/Router/List/Three.php @@ -16,7 +16,7 @@ public function __construct(private \ApiClients\Client\PetStore\Internal\Routers { } /** - * @return iterable|iterable + * @return iterable|iterable */ public function call(string $call, array $params, array $pathChunks) : iterable { diff --git a/tests/app/src/Internal/Router/List/Two.php b/tests/app/src/Internal/Router/List/Two.php index 4028c96..fc01877 100644 --- a/tests/app/src/Internal/Router/List/Two.php +++ b/tests/app/src/Internal/Router/List/Two.php @@ -16,7 +16,7 @@ public function __construct(private \ApiClients\Client\PetStore\Internal\Routers { } /** - * @return iterable + * @return iterable */ public function call(string $call, array $params, array $pathChunks) : iterable { diff --git a/tests/app/src/Internal/Router/Post/Pets.php b/tests/app/src/Internal/Router/Post/Pets.php index 57e85b2..9489a61 100644 --- a/tests/app/src/Internal/Router/Post/Pets.php +++ b/tests/app/src/Internal/Router/Post/Pets.php @@ -16,9 +16,9 @@ public function __construct(private \League\OpenAPIValidation\Schema\SchemaValid { } /** - * @return array{code:int} + * @return \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody */ - public function create(array $params) : array + public function create(array $params) : \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody { $operator = new Internal\Operator\Pets\Create($this->browser, $this->authentication, $this->requestSchemaValidator, $this->responseSchemaValidator, $this->hydrators->getObjectMapperOperation🌀Pets()); return $operator->call($params); diff --git a/tests/app/src/Internal/Router/Post/Two.php b/tests/app/src/Internal/Router/Post/Two.php index 82488f6..0b8d8fc 100644 --- a/tests/app/src/Internal/Router/Post/Two.php +++ b/tests/app/src/Internal/Router/Post/Two.php @@ -16,9 +16,9 @@ public function __construct(private \ApiClients\Client\PetStore\Internal\Routers { } /** - * @return array{code:int} + * @return \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody */ - public function call(string $call, array $params, array $pathChunks) : array + public function call(string $call, array $params, array $pathChunks) : \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody { if ($pathChunks[0] == '') { if ($pathChunks[1] == 'pets') { diff --git a/tests/app/src/Operation/Pets.php b/tests/app/src/Operation/Pets.php index 2ceff96..c7e16ea 100644 --- a/tests/app/src/Operation/Pets.php +++ b/tests/app/src/Operation/Pets.php @@ -16,35 +16,35 @@ public function __construct(private Internal\Operators $operators) { } /** - * @return iterable + * @return iterable */ public function list(int $perPage, int $page) : iterable { return $this->operators->pets👷List_()->call($perPage, $page); } /** - * @return iterable + * @return iterable */ public function listListing(int $perPage, int $page) : iterable { return $this->operators->pets👷ListListing()->call($perPage, $page); } /** - * @return array{code:int} + * @return \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody */ - public function create(array $params) : array + public function create(array $params) : \ApiClients\Tools\OpenApiClient\Utils\Response\WithoutBody { return $this->operators->pets👷Create()->call($params); } /** - * @return iterable + * @return iterable */ public function names(int $perPage, int $page) : iterable { return $this->operators->pets👷Names()->call($perPage, $page); } /** - * @return iterable + * @return iterable */ public function namesListing(int $perPage, int $page) : iterable { diff --git a/tests/app/src/Operation/PetsList.php b/tests/app/src/Operation/PetsList.php index ad46b3d..b56af45 100644 --- a/tests/app/src/Operation/PetsList.php +++ b/tests/app/src/Operation/PetsList.php @@ -16,14 +16,14 @@ public function __construct(private Internal\Operators $operators) { } /** - * @return iterable + * @return iterable */ public function gatos(int $perPage, int $page) : iterable { return $this->operators->pets👷List_👷Gatos()->call($perPage, $page); } /** - * @return iterable + * @return iterable */ public function gatosListing(int $perPage, int $page) : iterable { diff --git a/tests/app/src/Operations.php b/tests/app/src/Operations.php index 66bb391..8f0f820 100644 --- a/tests/app/src/Operations.php +++ b/tests/app/src/Operations.php @@ -26,7 +26,7 @@ public function petsList() : Operation\PetsList /** * @return Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish */ - public function showPetById() : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish|array + public function showPetById() : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish { return $this->operators->showPetById()->call(); } diff --git a/tests/app/src/OperationsInterface.php b/tests/app/src/OperationsInterface.php index a0516d4..1edc617 100644 --- a/tests/app/src/OperationsInterface.php +++ b/tests/app/src/OperationsInterface.php @@ -17,5 +17,5 @@ public function petsList() : Operation\PetsList; /** * @return Schema\Cat|Schema\Dog|Schema\Bird|Schema\Fish */ - public function showPetById() : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish|array; + public function showPetById() : \ApiClients\Client\PetStore\Schema\Cat|\ApiClients\Client\PetStore\Schema\Dog|\ApiClients\Client\PetStore\Schema\Bird|\ApiClients\Client\PetStore\Schema\Fish; } diff --git a/tests/app/src/PHPStan/ClientCallReturnTypes.php b/tests/app/src/PHPStan/ClientCallReturnTypes.php new file mode 100644 index 0000000..85d62e2 --- /dev/null +++ b/tests/app/src/PHPStan/ClientCallReturnTypes.php @@ -0,0 +1,61 @@ +printer = new \PhpParser\PrettyPrinter\Standard(); + } + public function getClass() : string + { + return \ApiClients\Client\PetStore\Client::class; + } + public function isMethodSupported(\PHPStan\Reflection\MethodReflection $methodReflection) : bool + { + return $methodReflection->getName() === 'call'; + } + public function getTypeFromMethodCall(\PHPStan\Reflection\MethodReflection $methodReflection, \PhpParser\Node\Expr\MethodCall $methodCall, \PHPStan\Analyser\Scope $scope) : null|\PHPStan\Type\Type + { + $args = $methodCall->getArgs(); + if (count($args) === 0) { + return null; + } + $call = substr($this->printer->prettyPrintExpr($args[0]->value), 1, -1); + if ($call === 'GET /pets') { + return $this->typeResolver->resolve('iterable'); + } + if ($call === 'LIST /pets') { + return $this->typeResolver->resolve('iterable'); + } + if ($call === 'POST /pets') { + return $this->typeResolver->resolve('\\ApiClients\\Tools\\OpenApiClient\\Utils\\Response\\WithoutBody'); + } + if ($call === 'GET /pets/gatos') { + return $this->typeResolver->resolve('iterable'); + } + if ($call === 'LIST /pets/gatos') { + return $this->typeResolver->resolve('iterable'); + } + if ($call === 'GET /pets/names') { + return $this->typeResolver->resolve('iterable'); + } + if ($call === 'LIST /pets/names') { + return $this->typeResolver->resolve('iterable'); + } + if ($call === 'GET /pets/{petId}') { + return $this->typeResolver->resolve('Schema\\Cat|Schema\\Dog|Schema\\Bird|Schema\\Fish'); + } + return null; + } +} diff --git a/tests/app/tests/Types/ClientCallReturnTypes.php b/tests/app/tests/Types/ClientCallReturnTypes.php new file mode 100644 index 0000000..de23e7f --- /dev/null +++ b/tests/app/tests/Types/ClientCallReturnTypes.php @@ -0,0 +1,27 @@ +', $client->call('GET /pets')); +\PHPStan\Testing\assertType('iterable', $client->call('LIST /pets')); +\PHPStan\Testing\assertType('\\ApiClients\\Tools\\OpenApiClient\\Utils\\Response\\WithoutBody', $client->call('POST /pets')); +\PHPStan\Testing\assertType('iterable', $client->call('GET /pets/gatos')); +\PHPStan\Testing\assertType('iterable', $client->call('LIST /pets/gatos')); +\PHPStan\Testing\assertType('iterable', $client->call('GET /pets/names')); +\PHPStan\Testing\assertType('iterable', $client->call('LIST /pets/names')); +\PHPStan\Testing\assertType('Schema\\Cat|Schema\\Dog|Schema\\Bird|Schema\\Fish', $client->call('GET /pets/{petId}')); diff --git a/tests/openapi-client-petstore.yaml b/tests/openapi-client-petstore.yaml index 3fba789..2aded8e 100644 --- a/tests/openapi-client-petstore.yaml +++ b/tests/openapi-client-petstore.yaml @@ -15,6 +15,11 @@ destination: root: app source: src test: tests +templates: + dir: app-templates + variables: + fullName: PetStore + packageName: petsore schemas: allowDuplication: true useAliasesForDuplication: true @@ -26,3 +31,9 @@ voter: - ApiClients\Tools\OpenApiClientGenerator\Voter\ListOperation\PageAndPerPageInQuery streamOperation: - ApiClients\Tools\OpenApiClientGenerator\Voter\StreamOperation\DownloadInOperationId +qa: + phpcs: + enabled: true + phpstan: + enabled: true + configFilePath: etc/phpstan-extension.neon diff --git a/tests/unit/Gatherer/OperationTest.php b/tests/unit/Gatherer/OperationTest.php deleted file mode 100644 index 4b4c400..0000000 --- a/tests/unit/Gatherer/OperationTest.php +++ /dev/null @@ -1,107 +0,0 @@ -, array{docBlock: array, raw: array}> */ - public function types(): iterable - { - yield [ - ['array{code: int}'], - [ - 'docBlock' => ['array{code: int}'], - 'raw' => ['array'], - ], - ]; - - foreach (self::SCALARS as $scalar) { - yield [ - [$scalar], - [ - 'docBlock' => [$scalar], - 'raw' => [$scalar], - ], - ]; - } - - yield [ - ['SimpleUser'], - [ - 'docBlock' => ['Schema\SimpleUser'], - 'raw' => ['Schema\SimpleUser'], - ], - ]; - - yield [ - ['\SimpleUser'], - [ - 'docBlock' => ['\SimpleUser'], - 'raw' => ['\SimpleUser'], - ], - ]; - } - - /** - * @param array $input - * @param array{docBlock: array} $output - * - * @test - * @dataProvider types - */ - public function normalizeDocBlock(array $input, array $output): void - { - self::assertEquals( - Generator\Helper\Types::normalizeDocBlock(...$input), - $output['docBlock'], - ); - } - - /** - * @param array $input - * @param array{raw: array} $output - * - * @test - * @dataProvider types - */ - public function normalizeRaw(array $input, array $output): void - { - self::assertEquals( - Generator\Helper\Types::normalizeRaw(...$input), - $output['raw'], - ); - } - - /** - * @param array $input - * @param array{raw: array} $output - * - * @test - * @dataProvider types - */ - public function normalizeNodeName(array $input, array $output): void - { - self::assertEquals( - array_map( - static fn (Node\Name $type): string => $type->toString(), - Generator\Helper\Types::normalizeNodeName(...$input), - ), - $output['raw'], - ); - } -} diff --git a/tests/unit/Generator/Helper/TypesTest.php b/tests/unit/Generator/Helper/TypesTest.php index d4092b7..979f367 100644 --- a/tests/unit/Generator/Helper/TypesTest.php +++ b/tests/unit/Generator/Helper/TypesTest.php @@ -22,14 +22,6 @@ final class TypesTest extends TestCase /** @return iterable, array{docBlock: array, raw: array}> */ public function types(): iterable { - yield [ - ['array{code: int}'], - [ - 'docBlock' => ['array{code: int}'], - 'raw' => ['array'], - ], - ]; - foreach (self::SCALARS as $scalar) { yield [ [$scalar],