From 6b07d515f229d866caaa624c4eb370a1ca52df14 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Sat, 18 May 2024 14:12:38 +0200 Subject: [PATCH] Update ComponentModel\Container stub for component-model 3.1.0 That version changes the return type to array when `$deep` argument is `false` (default): https://github.com/nette/component-model/commit/7f613eed7f5e57b6bde2d0be1bfdbb7e161620b3 It also deprecates the arguments but we cannot add deprecated annotation to those. https://github.com/nette/component-model/commit/4e0946a788b4ac42ea903b761c693ec7dd083a69 --- extension.neon | 6 +- src/Stubs/Nette/StubFilesExtensionLoader.php | 47 ++++++++++++++ stubs/ComponentModel/Container.stub | 2 +- stubs/ComponentModel/Container_3_1.stub | 21 +++++++ ...ontainerDynamicReturnTypeExtensionTest.php | 61 +++++++++++++++++++ .../Nette/data/componentModelContainer.php | 17 ++++++ .../Nette/data/componentModelContainer31.php | 17 ++++++ 7 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 src/Stubs/Nette/StubFilesExtensionLoader.php create mode 100644 stubs/ComponentModel/Container_3_1.stub create mode 100644 tests/Type/Nette/ComponentModelContainerDynamicReturnTypeExtensionTest.php create mode 100644 tests/Type/Nette/data/componentModelContainer.php create mode 100644 tests/Type/Nette/data/componentModelContainer31.php diff --git a/extension.neon b/extension.neon index 6a34985..8bea503 100644 --- a/extension.neon +++ b/extension.neon @@ -11,7 +11,6 @@ parameters: - stubs/Application/UI/Presenter.stub - stubs/Caching/Cache.stub - stubs/ComponentModel/Component.stub - - stubs/ComponentModel/Container.stub - stubs/ComponentModel/IComponent.stub - stubs/ComponentModel/IContainer.stub - stubs/Database/ResultSet.stub @@ -127,3 +126,8 @@ services: class: PHPStan\Type\Nette\StringsReplaceCallbackClosureTypeExtension tags: - phpstan.staticMethodParameterClosureTypeExtension + + - + class: PHPStan\Stubs\Nette\StubFilesExtensionLoader + tags: + - phpstan.stubFilesExtension diff --git a/src/Stubs/Nette/StubFilesExtensionLoader.php b/src/Stubs/Nette/StubFilesExtensionLoader.php new file mode 100644 index 0000000..342ffb0 --- /dev/null +++ b/src/Stubs/Nette/StubFilesExtensionLoader.php @@ -0,0 +1,47 @@ +=')) { + $files[] = $path . '/ComponentModel/Container_3_1.stub'; + } else { + $files[] = $path . '/ComponentModel/Container.stub'; + } + + return $files; + } + + private static function getInstalledVersion(string $package): ?string + { + if (!class_exists(InstalledVersions::class)) { + return null; + } + + try { + $installedVersion = InstalledVersions::getVersion($package); + } catch (OutOfBoundsException $e) { + return null; + } + + return $installedVersion; + } + +} diff --git a/stubs/ComponentModel/Container.stub b/stubs/ComponentModel/Container.stub index 2c0ba4b..384b2b6 100644 --- a/stubs/ComponentModel/Container.stub +++ b/stubs/ComponentModel/Container.stub @@ -10,7 +10,7 @@ class Container extends Component implements IContainer * @phpstan-param null|class-string $filterType * @phpstan-return ($filterType is null ? \Iterator : \Iterator) */ - public function getComponents(bool $deep = false, string $filterType = null): \Iterator + public function getComponents(bool $deep = false, ?string $filterType = null): \Iterator { // nothing } diff --git a/stubs/ComponentModel/Container_3_1.stub b/stubs/ComponentModel/Container_3_1.stub new file mode 100644 index 0000000..18d16eb --- /dev/null +++ b/stubs/ComponentModel/Container_3_1.stub @@ -0,0 +1,21 @@ + $filterType + * @phpstan-return ( + * $deep is false + * ? ($filterType is null ? array : array) + * : ($filterType is null ? \Iterator : \Iterator) + * ) + */ + public function getComponents(bool $deep = false, ?string $filterType = null): iterable + { + // nothing + } +} diff --git a/tests/Type/Nette/ComponentModelContainerDynamicReturnTypeExtensionTest.php b/tests/Type/Nette/ComponentModelContainerDynamicReturnTypeExtensionTest.php new file mode 100644 index 0000000..c73f3e8 --- /dev/null +++ b/tests/Type/Nette/ComponentModelContainerDynamicReturnTypeExtensionTest.php @@ -0,0 +1,61 @@ + + */ + public function dataFileAsserts(): iterable + { + $componentModelVersion = self::getInstalledVersion('nette/component-model'); + + $suffix = $componentModelVersion !== null && version_compare($componentModelVersion, '3.1.0', '>=') ? '31' : ''; + + yield from self::gatherAssertTypes(__DIR__ . '/data/componentModelContainer' . $suffix . '.php'); + } + + /** + * @dataProvider dataFileAsserts + * @param mixed ...$args + */ + public function testFileAsserts( + string $assertType, + string $file, + ...$args + ): void + { + $this->assertFileAsserts($assertType, $file, ...$args); + } + + public static function getAdditionalConfigFiles(): array + { + return [ + __DIR__ . '/phpstan.neon', + ]; + } + + private static function getInstalledVersion(string $package): ?string + { + if (!class_exists(InstalledVersions::class)) { + return null; + } + + try { + $installedVersion = InstalledVersions::getVersion($package); + } catch (OutOfBoundsException $e) { + return null; + } + + return $installedVersion; + } + +} diff --git a/tests/Type/Nette/data/componentModelContainer.php b/tests/Type/Nette/data/componentModelContainer.php new file mode 100644 index 0000000..f082254 --- /dev/null +++ b/tests/Type/Nette/data/componentModelContainer.php @@ -0,0 +1,17 @@ +', $someForm->getComponents(false)); +assertType('Iterator', $someForm->getComponents(false, Container::class)); +assertType('Iterator', $someForm->getComponents(true)); +assertType('Iterator', $someForm->getComponents(true, Container::class)); diff --git a/tests/Type/Nette/data/componentModelContainer31.php b/tests/Type/Nette/data/componentModelContainer31.php new file mode 100644 index 0000000..a2240d1 --- /dev/null +++ b/tests/Type/Nette/data/componentModelContainer31.php @@ -0,0 +1,17 @@ +', $someForm->getComponents(false)); +assertType('array', $someForm->getComponents(false, Container::class)); +assertType('Iterator', $someForm->getComponents(true)); +assertType('Iterator', $someForm->getComponents(true, Container::class));