From 436bfd47e6024250912ffd8eed1abb24524d401a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Sun, 27 Aug 2023 16:34:16 +0200 Subject: [PATCH 01/13] qa: introduce plugin manager static analysis file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- test/StaticAnalysis/PluginManager.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 test/StaticAnalysis/PluginManager.php diff --git a/test/StaticAnalysis/PluginManager.php b/test/StaticAnalysis/PluginManager.php new file mode 100644 index 00000000..578094a7 --- /dev/null +++ b/test/StaticAnalysis/PluginManager.php @@ -0,0 +1,26 @@ + + */ +final class PluginManager extends AbstractSingleInstancePluginManager +{ + /** + * @var class-string + */ + protected string $instanceOf = stdClass::class; + + public function getWhateverPlugin(array|null $options = null): stdClass + { + if ($options === null) { + return $this->get('foo'); + } + + return $this->build('foo', $options); + } +} From 3b3616bec19b2cb1f1b5634985e076cce9485ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Sun, 27 Aug 2023 19:55:49 +0200 Subject: [PATCH 02/13] qa: add `validate` as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- test/StaticAnalysis/PluginManager.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/StaticAnalysis/PluginManager.php b/test/StaticAnalysis/PluginManager.php index 578094a7..1da5b2fa 100644 --- a/test/StaticAnalysis/PluginManager.php +++ b/test/StaticAnalysis/PluginManager.php @@ -1,5 +1,7 @@ - */ + /** @var class-string */ protected string $instanceOf = stdClass::class; public function getWhateverPlugin(array|null $options = null): stdClass @@ -23,4 +23,10 @@ public function getWhateverPlugin(array|null $options = null): stdClass return $this->build('foo', $options); } + + public function functionValidateWhateverPlugin(object $object): stdClass + { + $this->validate($object); + return $object; + } } From bd79d547aca72fe9818b04eb575dc75bed780ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:34:51 +0200 Subject: [PATCH 03/13] qa: remove test testing invalid usage which is covered by psalm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- test/AbstractPluginManagerTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/AbstractPluginManagerTest.php b/test/AbstractPluginManagerTest.php index 469d8b45..8a21518a 100644 --- a/test/AbstractPluginManagerTest.php +++ b/test/AbstractPluginManagerTest.php @@ -220,13 +220,6 @@ public function testPluginManagersMayOptOutOfSupportingAutoInvokableServices(): $pluginManager->get(InvokableObject::class); } - public function testSetServiceShouldRaiseExceptionForInvalidPlugin(): void - { - $pluginManager = new SimplePluginManager(new ServiceManager()); - $this->expectException(InvalidServiceException::class); - $pluginManager->setService(stdClass::class, new stdClass()); - } - public function testPassingServiceInstanceViaConfigureShouldRaiseExceptionForInvalidPlugin(): void { $pluginManager = new SimplePluginManager(new ServiceManager()); From ead9df3a3175d6219d8970538d56c6050b3e60cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:39:30 +0200 Subject: [PATCH 04/13] qa: add some more static analysis checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- test/StaticAnalysis/MixedPluginManager.php | 32 +++++++++++++++++++ ...er.php => SingleInstancePluginManager.php} | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/StaticAnalysis/MixedPluginManager.php rename test/StaticAnalysis/{PluginManager.php => SingleInstancePluginManager.php} (89%) diff --git a/test/StaticAnalysis/MixedPluginManager.php b/test/StaticAnalysis/MixedPluginManager.php new file mode 100644 index 00000000..ab81355e --- /dev/null +++ b/test/StaticAnalysis/MixedPluginManager.php @@ -0,0 +1,32 @@ + + */ +final class MixedPluginManager extends AbstractPluginManager +{ + public function getWhateverPlugin(array|null $options = null): mixed + { + if ($options === null) { + return $this->get('foo'); + } + + return $this->build('foo', $options); + } + + public function functionValidateWhateverPlugin(mixed $plugin): mixed + { + $this->validate($plugin); + return $plugin; + } + + public function validate(mixed $instance): void + { + } +} diff --git a/test/StaticAnalysis/PluginManager.php b/test/StaticAnalysis/SingleInstancePluginManager.php similarity index 89% rename from test/StaticAnalysis/PluginManager.php rename to test/StaticAnalysis/SingleInstancePluginManager.php index 1da5b2fa..8adafe05 100644 --- a/test/StaticAnalysis/PluginManager.php +++ b/test/StaticAnalysis/SingleInstancePluginManager.php @@ -10,7 +10,7 @@ /** * @template-extends AbstractSingleInstancePluginManager */ -final class PluginManager extends AbstractSingleInstancePluginManager +final class SingleInstancePluginManager extends AbstractSingleInstancePluginManager { /** @var class-string */ protected string $instanceOf = stdClass::class; From 961d9be19a6759d81ce438fcce0e2890fdb7cce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:39:43 +0200 Subject: [PATCH 05/13] bugfix: add missing `template-extends` to `SimplePluginManager` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- test/TestAsset/SimplePluginManager.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/TestAsset/SimplePluginManager.php b/test/TestAsset/SimplePluginManager.php index 2e6fd6b9..0962f9ef 100644 --- a/test/TestAsset/SimplePluginManager.php +++ b/test/TestAsset/SimplePluginManager.php @@ -6,7 +6,11 @@ use Laminas\ServiceManager\AbstractSingleInstancePluginManager; +/** + * @template-extends AbstractSingleInstancePluginManager + */ final class SimplePluginManager extends AbstractSingleInstancePluginManager { + /** @var class-string */ protected string $instanceOf = InvokableObject::class; } From 193a41078dfddaf233e2c6172d9221d197625622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:39:59 +0200 Subject: [PATCH 06/13] qa: bump psalm to unreleased version to cover latest changes in upstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 44771f20..38a24619 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,6 @@ "homepage": "https://laminas.dev", "support": { "issues": "https://github.com/laminas/laminas-servicemanager/issues", - "forum": "https://discourse.laminas.dev", "chat": "https://laminas.dev/chat", "forum": "https://discourse.laminas.dev" }, @@ -53,7 +52,7 @@ "phpunit/phpunit": "^10.4", "psalm/plugin-phpunit": "^0.18.4", "symfony/console": "^6.0", - "vimeo/psalm": "^5.10" + "vimeo/psalm": "5.x-dev as 5.16" }, "provide": { "psr/container-implementation": "^1.0 || ^2.0" From a84f4f2179caff462680c0da2850c0d01d3ccf1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Wed, 30 Aug 2023 00:53:53 +0200 Subject: [PATCH 07/13] qa: remove `lctrs/psalm-psr-container-plugin` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To enable proper static analysis without side-effects, we are removing the container plugin here to verify provided psalm-types from `ServiceLocatorInterface` and `PluginManagerInterface` Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- psalm.xml.dist | 3 ++- .../AheadOfTimeFactoryCreatorCommandFactory.php | 5 +++-- src/Command/ConfigDumperCommandFactory.php | 6 +++++- src/Command/FactoryCreatorCommandFactory.php | 6 +++++- .../AheadOfTimeFactoryCompilerFactory.php | 6 +++++- src/Tool/FactoryCreatorFactory.php | 6 +++++- test/CommonServiceLocatorBehaviorsTrait.php | 2 -- test/ServiceManagerTest.php | 2 +- test/StaticAnalysis/ConcreteStdClassPlugin.php | 11 +++++++++++ test/StaticAnalysis/SingleInstancePluginManager.php | 10 ++++++++++ 10 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 test/StaticAnalysis/ConcreteStdClassPlugin.php diff --git a/psalm.xml.dist b/psalm.xml.dist index a17d69e3..859a4f6c 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -20,6 +20,7 @@ + @@ -92,6 +93,6 @@ - + diff --git a/src/Command/AheadOfTimeFactoryCreatorCommandFactory.php b/src/Command/AheadOfTimeFactoryCreatorCommandFactory.php index 84fa91b4..4725379a 100644 --- a/src/Command/AheadOfTimeFactoryCreatorCommandFactory.php +++ b/src/Command/AheadOfTimeFactoryCreatorCommandFactory.php @@ -8,6 +8,7 @@ use Laminas\ServiceManager\Tool\AheadOfTimeFactoryCompiler\AheadOfTimeFactoryCompilerInterface; use Psr\Container\ContainerInterface; +use function assert; use function is_array; use function is_iterable; use function is_string; @@ -18,7 +19,8 @@ final class AheadOfTimeFactoryCreatorCommandFactory public function __invoke(ContainerInterface $container): AheadOfTimeFactoryCreatorCommand { $aheadOfTimeFactoryCompiler = $container->get(AheadOfTimeFactoryCompilerInterface::class); - $config = $container->has('config') ? $container->get('config') : []; + assert($aheadOfTimeFactoryCompiler instanceof AheadOfTimeFactoryCompilerInterface); + $config = $container->has('config') ? $container->get('config') : []; if (! is_iterable($config)) { return new AheadOfTimeFactoryCreatorCommand([], '', $aheadOfTimeFactoryCompiler); } @@ -27,7 +29,6 @@ public function __invoke(ContainerInterface $container): AheadOfTimeFactoryCreat $config = iterator_to_array($config); } - /** @psalm-suppress MixedAssignment Even tho we do verify the type right after assigning it, psalm has problems with that*/ $factoryTargetPath = $config[ConfigProvider::CONFIGURATION_KEY_FACTORY_TARGET_PATH] ?? ''; if (! is_string($factoryTargetPath)) { $factoryTargetPath = ''; diff --git a/src/Command/ConfigDumperCommandFactory.php b/src/Command/ConfigDumperCommandFactory.php index 58406818..7ad9f48e 100644 --- a/src/Command/ConfigDumperCommandFactory.php +++ b/src/Command/ConfigDumperCommandFactory.php @@ -7,6 +7,8 @@ use Laminas\ServiceManager\Tool\ConfigDumperInterface; use Psr\Container\ContainerInterface; +use function assert; + /** * @internal Factories are not meant to be used in any upstream projects. */ @@ -14,6 +16,8 @@ final class ConfigDumperCommandFactory { public function __invoke(ContainerInterface $container): ConfigDumperCommand { - return new ConfigDumperCommand($container->get(ConfigDumperInterface::class)); + $dumper = $container->get(ConfigDumperInterface::class); + assert($dumper instanceof ConfigDumperInterface); + return new ConfigDumperCommand($dumper); } } diff --git a/src/Command/FactoryCreatorCommandFactory.php b/src/Command/FactoryCreatorCommandFactory.php index 44554840..3aa63c42 100644 --- a/src/Command/FactoryCreatorCommandFactory.php +++ b/src/Command/FactoryCreatorCommandFactory.php @@ -7,6 +7,8 @@ use Laminas\ServiceManager\Tool\FactoryCreatorInterface; use Psr\Container\ContainerInterface; +use function assert; + /** * @internal Factories are not meant to be used in any upstream projects. */ @@ -14,6 +16,8 @@ final class FactoryCreatorCommandFactory { public function __invoke(ContainerInterface $container): FactoryCreatorCommand { - return new FactoryCreatorCommand($container->get(FactoryCreatorInterface::class)); + $creator = $container->get(FactoryCreatorInterface::class); + assert($creator instanceof FactoryCreatorInterface); + return new FactoryCreatorCommand($creator); } } diff --git a/src/Tool/AheadOfTimeFactoryCompiler/AheadOfTimeFactoryCompilerFactory.php b/src/Tool/AheadOfTimeFactoryCompiler/AheadOfTimeFactoryCompilerFactory.php index 2e997707..c531338a 100644 --- a/src/Tool/AheadOfTimeFactoryCompiler/AheadOfTimeFactoryCompilerFactory.php +++ b/src/Tool/AheadOfTimeFactoryCompiler/AheadOfTimeFactoryCompilerFactory.php @@ -7,10 +7,14 @@ use Laminas\ServiceManager\Tool\FactoryCreatorInterface; use Psr\Container\ContainerInterface; +use function assert; + final class AheadOfTimeFactoryCompilerFactory { public function __invoke(ContainerInterface $container): AheadOfTimeFactoryCompilerInterface { - return new AheadOfTimeFactoryCompiler($container->get(FactoryCreatorInterface::class)); + $creator = $container->get(FactoryCreatorInterface::class); + assert($creator instanceof FactoryCreatorInterface); + return new AheadOfTimeFactoryCompiler($creator); } } diff --git a/src/Tool/FactoryCreatorFactory.php b/src/Tool/FactoryCreatorFactory.php index cb487ca3..f03f9aca 100644 --- a/src/Tool/FactoryCreatorFactory.php +++ b/src/Tool/FactoryCreatorFactory.php @@ -7,6 +7,8 @@ use Laminas\ServiceManager\Tool\ConstructorParameterResolver\ConstructorParameterResolverInterface; use Psr\Container\ContainerInterface; +use function assert; + /** * @internal */ @@ -14,6 +16,8 @@ final class FactoryCreatorFactory { public function __invoke(ContainerInterface $container): FactoryCreatorInterface { - return new FactoryCreator($container, $container->get(ConstructorParameterResolverInterface::class)); + $resolver = $container->get(ConstructorParameterResolverInterface::class); + assert($resolver instanceof ConstructorParameterResolverInterface); + return new FactoryCreator($container, $resolver); } } diff --git a/test/CommonServiceLocatorBehaviorsTrait.php b/test/CommonServiceLocatorBehaviorsTrait.php index 1c4174f9..1aaabfd9 100644 --- a/test/CommonServiceLocatorBehaviorsTrait.php +++ b/test/CommonServiceLocatorBehaviorsTrait.php @@ -897,12 +897,10 @@ public function testConsistencyOverInternalStates( $target = 'build'; } - /** @psalm-suppress MixedAssignment Yes indeed, service managers can return mixed. */ $object[$target][] = $obj; } // compares the first to the first also, but ok - /** @psalm-suppress MixedAssignment Yes indeed, service managers can return mixed. */ foreach ($object['get'] as $sharedObj) { self::assertSame($object['get'][0], $sharedObj); } diff --git a/test/ServiceManagerTest.php b/test/ServiceManagerTest.php index fde3a57a..16843e9c 100644 --- a/test/ServiceManagerTest.php +++ b/test/ServiceManagerTest.php @@ -108,7 +108,7 @@ static function (ContainerInterface $container, string $name, callable $callback ]); $instance = $serviceManager->get(stdClass::class); - + self::assertInstanceOf(stdClass::class, $instance); self::assertTrue(isset($instance->option), 'Delegator-injected option was not found'); self::assertEquals( $config['option'], diff --git a/test/StaticAnalysis/ConcreteStdClassPlugin.php b/test/StaticAnalysis/ConcreteStdClassPlugin.php new file mode 100644 index 00000000..d2e5c351 --- /dev/null +++ b/test/StaticAnalysis/ConcreteStdClassPlugin.php @@ -0,0 +1,11 @@ +validate($object); return $object; } + + public function getConcretePlugin(): ConcreteStdClassPlugin + { + return $this->get(ConcreteStdClassPlugin::class); + } + + public function buildConcretePlugin(): ConcreteStdClassPlugin + { + return $this->build(ConcreteStdClassPlugin::class); + } } From 2e8dd41ffc83bb69260749a084ebbfb7a9182dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Tue, 5 Sep 2023 20:28:19 +0200 Subject: [PATCH 08/13] qa: remove `MixedAssignment` suppressions as these are now suppressed by `psalm.xml` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to the way, psalm moves forward, this issue will be removed - most probably with v6. The reasoning behind this is, that `mixed` is not bad per-se, depending on how it is used. If a codebase accepts `mixed` in a method (even tho that might be revealing method complexity), that is a absolutely okay and thus, passing `mixed` and esp. assigning `mixed` is absolutely fine in case the following code is accepting mixed and/or the value is narrowed down at some point. Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- src/AbstractPluginManager.php | 1 - src/ServiceManager.php | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/AbstractPluginManager.php b/src/AbstractPluginManager.php index b576c5a7..e284c280 100644 --- a/src/AbstractPluginManager.php +++ b/src/AbstractPluginManager.php @@ -198,7 +198,6 @@ public function get(string $id): mixed $this->plugins->setFactory($id, Factory\InvokableFactory::class); } - /** @psalm-suppress MixedAssignment Yes indeed, service managers can return mixed. */ $instance = $this->plugins->get($id); $this->validate($instance); return $instance; diff --git a/src/ServiceManager.php b/src/ServiceManager.php index 26051496..2e94c7ae 100644 --- a/src/ServiceManager.php +++ b/src/ServiceManager.php @@ -211,7 +211,6 @@ public function get(string $id): mixed // We achieve better performance if we can let all alias // considerations out. if (! $this->aliases) { - /** @psalm-suppress MixedAssignment Yes indeed, service managers can return mixed. */ $service = $this->doCreate($id); // Cache the service for later, if it is supposed to be shared. @@ -240,7 +239,6 @@ public function get(string $id): mixed // At this point, we have to create the object. // We use the resolved name for that. - /** @psalm-suppress MixedAssignment Yes indeed, service managers can return mixed. */ $service = $this->doCreate($resolvedName); // Cache the object for later, if it is supposed to be shared. @@ -622,10 +620,8 @@ private function doCreate(string $resolvedName, ?array $options = null): mixed if (! isset($this->delegators[$resolvedName])) { // Let's create the service by fetching the factory $factory = $this->getFactory($resolvedName); - /** @psalm-suppress MixedAssignment Yes indeed, service managers can return mixed. */ $service = $factory($this->creationContext, $resolvedName, $options); } else { - /** @psalm-suppress MixedAssignment Yes indeed, service managers can return mixed. */ $service = $this->createDelegatorFromName($resolvedName, $options); } } catch (ContainerExceptionInterface $exception) { From 0c3694c758c78bc01472a095dce98f5fb887c2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Tue, 5 Sep 2023 20:30:09 +0200 Subject: [PATCH 09/13] qa: add missing type-narrowing for `AbstractSingleInstancePluginManager#build` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `AbstractSingleInstancePluginManager` has to always return an object as thats what it is used for. Therefore, type-narrowing here is absolutely fine and still fits liskov substitution principle. Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- src/AbstractSingleInstancePluginManager.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/AbstractSingleInstancePluginManager.php b/src/AbstractSingleInstancePluginManager.php index 929a694b..c0a998af 100644 --- a/src/AbstractSingleInstancePluginManager.php +++ b/src/AbstractSingleInstancePluginManager.php @@ -34,6 +34,14 @@ public function get(string $id): object return parent::get($id); } + /** + * {@inheritDoc} + */ + public function build(string $name, ?array $options = null): object + { + return parent::build($name, $options); + } + /** * {@inheritDoc} */ From 3b4d68b6a43304d854b4dfb51d17b559350e18eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Sun, 10 Sep 2023 14:38:53 +0200 Subject: [PATCH 10/13] qa: add some more static analysis files regarding plugin managers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- test/StaticAnalysis/CallablePluginManager.php | 51 ++++++++++++++++ .../StaticAnalysis/ConcreteCallablePlugin.php | 13 +++++ test/StaticAnalysis/UnionPluginManager.php | 58 +++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 test/StaticAnalysis/CallablePluginManager.php create mode 100644 test/StaticAnalysis/ConcreteCallablePlugin.php create mode 100644 test/StaticAnalysis/UnionPluginManager.php diff --git a/test/StaticAnalysis/CallablePluginManager.php b/test/StaticAnalysis/CallablePluginManager.php new file mode 100644 index 00000000..fdddacd1 --- /dev/null +++ b/test/StaticAnalysis/CallablePluginManager.php @@ -0,0 +1,51 @@ + + */ +final class CallablePluginManager extends AbstractPluginManager +{ + public function getWhateverPlugin(array|null $options = null): callable + { + if ($options === null) { + return $this->get('foo'); + } + + return $this->build('foo', $options); + } + + public function validateWhateverPlugin(mixed $plugin): callable + { + $this->validate($plugin); + return $plugin; + } + + public function getConcretePlugin(): ConcreteCallablePlugin + { + return self::get(ConcreteCallablePlugin::class); + } + + public function buildConcretePlugin(): ConcreteCallablePlugin + { + return self::build(ConcreteCallablePlugin::class); + } + + /** + * {@inheritDoc} + */ + public function validate(mixed $instance): void + { + if (! is_callable($instance)) { + throw new InvalidArgumentException('Provided instance is not callable.'); + } + } +} diff --git a/test/StaticAnalysis/ConcreteCallablePlugin.php b/test/StaticAnalysis/ConcreteCallablePlugin.php new file mode 100644 index 00000000..e14de0c8 --- /dev/null +++ b/test/StaticAnalysis/ConcreteCallablePlugin.php @@ -0,0 +1,13 @@ + + */ +final class UnionPluginManager extends AbstractPluginManager +{ + /** + * @return callable|CallableObjectType + */ + public function getWhateverPlugin(array|null $options = null): callable|object + { + if ($options === null) { + return $this->get('foo'); + } + + return $this->build('foo', $options); + } + + public function validateWhateverPlugin(mixed $plugin): callable|object + { + $this->validate($plugin); + return $plugin; + } + + public function getConcretePlugin(): ConcreteCallablePlugin + { + return self::get(ConcreteCallablePlugin::class); + } + + public function buildConcretePlugin(): ConcreteCallablePlugin + { + return self::build(ConcreteCallablePlugin::class); + } + + /** + * {@inheritDoc} + */ + public function validate(mixed $instance): void + { + if (! is_callable($instance)) { + throw new InvalidArgumentException('Provided instance is not callable.'); + } + } +} From 9fa71916ecc633996995a828d5520a0d6f2014d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Tue, 10 Oct 2023 21:24:07 +0200 Subject: [PATCH 11/13] qa: update psalm to latest stable version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- composer.json | 2 +- composer.lock | 335 +++++++++--------- psalm-baseline.xml | 186 ++++------ .../AheadOfTimeFactoryCreatorCommand.php | 9 +- src/ServiceManager.php | 4 +- src/Tool/ConfigDumper.php | 5 +- 6 files changed, 268 insertions(+), 273 deletions(-) diff --git a/composer.json b/composer.json index 38a24619..a723d0f4 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "phpunit/phpunit": "^10.4", "psalm/plugin-phpunit": "^0.18.4", "symfony/console": "^6.0", - "vimeo/psalm": "5.x-dev as 5.16" + "vimeo/psalm": "^5.22" }, "provide": { "psr/container-implementation": "^1.0 || ^2.0" diff --git a/composer.lock b/composer.lock index 4ddbdcbb..b4d5f4c9 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": "d241bbfd820f8a36cabd6da1c031e520", + "content-hash": "84fac30ea170d4ad039fb66654643de1", "packages": [ { "name": "brick/varexporter", @@ -116,16 +116,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.17.1", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { @@ -166,9 +166,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" }, - "time": "2023-08-13T19:53:39+00:00" + "time": "2023-12-10T21:03:43+00:00" }, { "name": "psr/container", @@ -524,16 +524,16 @@ }, { "name": "composer/pcre", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9", "shasum": "" }, "require": { @@ -575,7 +575,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.0" + "source": "https://github.com/composer/pcre/tree/3.1.1" }, "funding": [ { @@ -591,7 +591,7 @@ "type": "tidelift" } ], - "time": "2022-11-17T09:50:14+00:00" + "time": "2023-10-11T07:11:09+00:00" }, { "name": "composer/semver", @@ -930,27 +930,27 @@ }, { "name": "doctrine/lexer", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "84a527db05647743d50373e0ec53a152f2cde568" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568", - "reference": "84a527db05647743d50373e0ec53a152f2cde568", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.5", + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "^5.21" }, "type": "library", "autoload": { @@ -987,7 +987,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.0" + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, "funding": [ { @@ -1003,7 +1003,7 @@ "type": "tidelift" } ], - "time": "2022-12-15T16:57:16+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -1108,16 +1108,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "0.5.1", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623" + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/b58e5a3933e541dc286cc91fc4f3898bbc6f1623", - "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", "shasum": "" }, "require": { @@ -1125,13 +1125,13 @@ }, "require-dev": { "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", "phpstan/phpstan": "^1.9.2", "phpstan/phpstan-deprecation-rules": "^1.0.0", "phpstan/phpstan-phpunit": "^1.2.2", "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^9.5.26 || ^8.5.31", - "theofidry/php-cs-fixer-config": "^1.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", "webmozarts/strict-phpunit": "^7.5" }, "type": "library", @@ -1157,7 +1157,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/0.5.1" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.1.0" }, "funding": [ { @@ -1165,7 +1165,7 @@ "type": "github" } ], - "time": "2022-12-24T12:35:10+00:00" + "time": "2024-02-07T09:43:46+00:00" }, { "name": "friendsofphp/proxy-manager-lts", @@ -1693,16 +1693,16 @@ }, { "name": "netresearch/jsonmapper", - "version": "v4.2.0", + "version": "v4.4.1", "source": { "type": "git", "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/132c75c7dd83e45353ebb9c6c9f591952995bbf0", + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0", "shasum": "" }, "require": { @@ -1713,7 +1713,7 @@ "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", "squizlabs/php_codesniffer": "~3.5" }, "type": "library", @@ -1738,9 +1738,9 @@ "support": { "email": "cweiske@cweiske.de", "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" + "source": "https://github.com/cweiske/jsonmapper/tree/v4.4.1" }, - "time": "2023-04-09T17:37:40+00:00" + "time": "2024-01-31T06:18:54+00:00" }, { "name": "phar-io/manifest", @@ -3189,16 +3189,16 @@ }, { "name": "sebastian/diff", - "version": "5.0.3", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { @@ -3206,12 +3206,12 @@ }, "require-dev": { "phpunit/phpunit": "^10.0", - "symfony/process": "^4.2 || ^5" + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -3244,7 +3244,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { @@ -3252,7 +3252,7 @@ "type": "github" } ], - "time": "2023-05-01T07:48:21+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { "name": "sebastian/environment", @@ -3802,16 +3802,16 @@ }, { "name": "seld/jsonlint", - "version": "1.10.0", + "version": "1.10.2", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "594fd6462aad8ecee0b45ca5045acea4776667f1" + "reference": "9bb7db07b5d66d90f6ebf542f09fc67d800e5259" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/594fd6462aad8ecee0b45ca5045acea4776667f1", - "reference": "594fd6462aad8ecee0b45ca5045acea4776667f1", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9bb7db07b5d66d90f6ebf542f09fc67d800e5259", + "reference": "9bb7db07b5d66d90f6ebf542f09fc67d800e5259", "shasum": "" }, "require": { @@ -3838,7 +3838,7 @@ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "homepage": "https://seld.be" } ], "description": "JSON Linter", @@ -3850,7 +3850,7 @@ ], "support": { "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.10.0" + "source": "https://github.com/Seldaek/jsonlint/tree/1.10.2" }, "funding": [ { @@ -3862,7 +3862,7 @@ "type": "tidelift" } ], - "time": "2023-05-11T13:16:46+00:00" + "time": "2024-02-07T12:57:50+00:00" }, { "name": "slevomat/coding-standard", @@ -3927,16 +3927,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.2.0", + "version": "3.2.3", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7" + "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f9ab39c808500c347d5a8b6b13310bd5221e39e7", - "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/c95fd4db94ec199f798d4b5b4a81757bd20d88ab", + "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab", "shasum": "" }, "require": { @@ -3974,7 +3974,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.2.0" + "source": "https://github.com/spatie/array-to-xml/tree/3.2.3" }, "funding": [ { @@ -3986,20 +3986,20 @@ "type": "github" } ], - "time": "2023-07-19T18:30:26+00:00" + "time": "2024-02-07T10:39:02+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.7.2", + "version": "3.9.0", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/d63cee4890a8afaf86a22e51ad4d97c91dd4579b", + "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b", "shasum": "" }, "require": { @@ -4009,11 +4009,11 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "bin": [ - "bin/phpcs", - "bin/phpcbf" + "bin/phpcbf", + "bin/phpcs" ], "type": "library", "extra": { @@ -4028,22 +4028,45 @@ "authors": [ { "name": "Greg Sherwood", - "role": "lead" + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", "standards", "static analysis" ], "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, - "time": "2023-02-22T23:07:41+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "time": "2024-02-16T15:06:51+00:00" }, { "name": "symfony/console", @@ -4137,7 +4160,7 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -4184,7 +4207,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" }, "funding": [ { @@ -4204,16 +4227,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.3.2", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" + "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ae9d3a6f3003a6caf56acd7466d8d52378d44fef", + "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef", "shasum": "" }, "require": { @@ -4230,13 +4253,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0" + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4264,7 +4287,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.3" }, "funding": [ { @@ -4280,11 +4303,11 @@ "type": "tidelift" } ], - "time": "2023-07-06T06:56:43+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", @@ -4340,7 +4363,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" }, "funding": [ { @@ -4360,16 +4383,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.3.1", + "version": "v6.4.3", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" + "reference": "7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb", + "reference": "7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb", "shasum": "" }, "require": { @@ -4403,7 +4426,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.3.1" + "source": "https://github.com/symfony/filesystem/tree/v6.4.3" }, "funding": [ { @@ -4419,27 +4442,27 @@ "type": "tidelift" } ], - "time": "2023-06-01T08:30:39+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/finder", - "version": "v6.3.3", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e" + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9915db259f67d21eefee768c1abcf1cc61b1fc9e", - "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e", + "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { - "symfony/filesystem": "^6.0" + "symfony/filesystem": "^6.0|^7.0" }, "type": "library", "autoload": { @@ -4467,7 +4490,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.3.3" + "source": "https://github.com/symfony/finder/tree/v6.4.0" }, "funding": [ { @@ -4483,20 +4506,20 @@ "type": "tidelift" } ], - "time": "2023-07-31T08:31:44+00:00" + "time": "2023-10-31T17:30:12+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.3.0", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd" + "reference": "22301f0e7fdeaacc14318928612dee79be99860e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a10f19f5198d589d5c33333cffe98dc9820332dd", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22301f0e7fdeaacc14318928612dee79be99860e", + "reference": "22301f0e7fdeaacc14318928612dee79be99860e", "shasum": "" }, "require": { @@ -4534,7 +4557,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.3.0" + "source": "https://github.com/symfony/options-resolver/tree/v6.4.0" }, "funding": [ { @@ -4550,20 +4573,20 @@ "type": "tidelift" } ], - "time": "2023-05-12T14:21:09+00:00" + "time": "2023-08-08T10:16:24+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "shasum": "" }, "require": { @@ -4577,9 +4600,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4616,7 +4636,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" }, "funding": [ { @@ -4632,7 +4652,7 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -4801,16 +4821,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "shasum": "" }, "require": { @@ -4824,9 +4844,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4864,7 +4881,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" }, "funding": [ { @@ -4880,20 +4897,20 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", "shasum": "" }, "require": { @@ -4901,9 +4918,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4947,7 +4961,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" }, "funding": [ { @@ -4963,20 +4977,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/process", - "version": "v6.3.4", + "version": "v6.4.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" + "reference": "710e27879e9be3395de2b98da3f52a946039f297" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", + "url": "https://api.github.com/repos/symfony/process/zipball/710e27879e9be3395de2b98da3f52a946039f297", + "reference": "710e27879e9be3395de2b98da3f52a946039f297", "shasum": "" }, "require": { @@ -5008,7 +5022,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.3.4" + "source": "https://github.com/symfony/process/tree/v6.4.4" }, "funding": [ { @@ -5024,25 +5038,25 @@ "type": "tidelift" } ], - "time": "2023-08-07T10:39:22+00:00" + "time": "2024-02-20T12:31:00+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.3.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -5090,7 +5104,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -5106,7 +5120,7 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/string", @@ -5246,16 +5260,16 @@ }, { "name": "vimeo/psalm", - "version": "5.15.0", + "version": "5.22.2", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352" + "reference": "d768d914152dbbf3486c36398802f74e80cfde48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/5c774aca4746caf3d239d9c8cadb9f882ca29352", - "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/d768d914152dbbf3486c36398802f74e80cfde48", + "reference": "d768d914152dbbf3486c36398802f74e80cfde48", "shasum": "" }, "require": { @@ -5274,14 +5288,14 @@ "ext-tokenizer": "*", "felixfbecker/advanced-json-rpc": "^3.1", "felixfbecker/language-server-protocol": "^1.5.2", - "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", "nikic/php-parser": "^4.16", "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "sebastian/diff": "^4.0 || ^5.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", - "symfony/console": "^4.1.6 || ^5.0 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0" + "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" }, "conflict": { "nikic/php-parser": "4.17.0" @@ -5303,7 +5317,7 @@ "psalm/plugin-phpunit": "^0.18", "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0" + "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { "ext-curl": "In order to send data to shepherd", @@ -5316,7 +5330,7 @@ "psalm-refactor", "psalter" ], - "type": "library", + "type": "project", "extra": { "branch-alias": { "dev-master": "5.x-dev", @@ -5348,10 +5362,11 @@ "static analysis" ], "support": { + "docs": "https://psalm.dev/docs", "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.15.0" + "source": "https://github.com/vimeo/psalm" }, - "time": "2023-08-20T23:07:30+00:00" + "time": "2024-02-22T23:39:07+00:00" }, { "name": "webimpress/coding-standard", diff --git a/psalm-baseline.xml b/psalm-baseline.xml index bb99df15..0164d512 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,78 +1,66 @@ - + - new $requestedName(...$arguments) + - $serviceDependencies - $serviceDependencies + + - $config[self::class] + - - $config - $dependencies - - $requestedName + - new $requestedName(...$parameters) + - mapLazyService + - self::deDuplicateDetectedCycles($detectedCycles) + - $cycle + - new $requestedName($options) - new $requestedName() + + - Module + - - - validate - - - $wrappedInstance + - - $wrappedInstance - services[$service]]]> - $service + - function () use ($name, $options) { + - $abstractFactory + @@ -85,20 +73,11 @@ - $service + services[$service]]]> - - $abstractFactories - $abstractFactory - - aliases]]> - factories]]> - shared]]> - sharedByDefault]]> - @@ -106,16 +85,16 @@ - $service - $target + + - DelegatorsConfiguration + - $expected + getServiceNotFoundException()]]> getServiceNotFoundException()]]> @@ -124,91 +103,76 @@ - $key + - $className + - $config[ConfigAbstractFactory::class][$className] - $config[ConfigAbstractFactory::class][$className] + + - - $key - $value - - $key + - - $instance - - array + - $instance + - ignoreUnresolvedArguments + - $callback - $className - $container - $container - $instance - $instance - $name - $requestedName + + + + + + + + - static function ($container, $name, $callback) { + - - $first - $instance - $nonSharedObj1 - $nonSharedObj2 - $obj - $second - - $callback() + - $instance + - $container - $options - $requestedName + + + - array_filter(spl_autoload_functions(), $filter) + - AutoloaderInterface[] + - $autoload + - assertIsArray - assertIsArray + + @@ -216,49 +180,55 @@ - $className - $initializer + + - $initializer($wrappedInstance, $proxy) + - $wrappedInstance + - - $inc - $inc - $instance1 - $instance1 - $instance2 - $instance2 - $service - $serviceFromAlias - $serviceFromServiceNameAfterUsingAlias - - array + - $inc + - sampleFactory + + + + + + + + + + + - ServiceManagerConfiguration + + + + + + + + + + + - - $test - - include $file + diff --git a/src/Command/AheadOfTimeFactoryCreatorCommand.php b/src/Command/AheadOfTimeFactoryCreatorCommand.php index a26daa38..7ddaa5cd 100644 --- a/src/Command/AheadOfTimeFactoryCreatorCommand.php +++ b/src/Command/AheadOfTimeFactoryCreatorCommand.php @@ -106,7 +106,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int preg_replace('/\W/', '', $factory->containerConfigurationKey) ); - /** @var class-string $factoryClassName */ $factoryClassName = sprintf('%sFactory', $factory->fullyQualifiedClassName); if (class_exists($factoryClassName)) { $output->writeln(sprintf( @@ -134,6 +133,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $containerConfigurations[$factory->containerConfigurationKey] = ['factories' => []]; } + /** + * Psalm has to understand that the `factoryClassName` variable contains a class-string to a factory which + * will be available once persisted to the filesystem and loaded via composer autoloading. + * + * @psalm-suppress UnnecessaryVarAnnotation Sadly, we do have to do this as psalm is not able to infer + * concatenated arrays. + * @var class-string $factoryClassName + */ $containerConfigurations[$factory->containerConfigurationKey]['factories'] += [ $factory->fullyQualifiedClassName => $factoryClassName, ]; diff --git a/src/ServiceManager.php b/src/ServiceManager.php index 2e94c7ae..1d0b2b63 100644 --- a/src/ServiceManager.php +++ b/src/ServiceManager.php @@ -324,10 +324,10 @@ public function configure(array $config): static $this->shared = $config['shared'] + $this->shared; } - if (! empty($config['aliases'])) { + if (isset($config['aliases']) && $config['aliases'] !== []) { $this->aliases = $config['aliases'] + $this->aliases; $this->mapAliasesToTargets(); - } elseif (! $this->configured && ! empty($this->aliases)) { + } elseif (! $this->configured && $this->aliases !== []) { $this->mapAliasesToTargets(); } diff --git a/src/Tool/ConfigDumper.php b/src/Tool/ConfigDumper.php index 7461e35f..87e6c428 100644 --- a/src/Tool/ConfigDumper.php +++ b/src/Tool/ConfigDumper.php @@ -176,7 +176,7 @@ private function prepareConfig(iterable $config, int $indentLevel = 1): string $entries[] = sprintf( '%s%s%s,', $indent, - $key ? sprintf('%s => ', $key) : '', + $key !== null ? sprintf('%s => ', $key) : '', $this->createConfigValue($value, $indentLevel) ); } @@ -190,6 +190,9 @@ private function prepareConfig(iterable $config, int $indentLevel = 1): string ); } + /** + * @return non-empty-string|null + */ private function createConfigKey(string|int|null $key): string|null { if (is_string($key) && class_exists($key)) { From b79a3d46dcea11cf09eacba595e09b052784d5db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Sat, 2 Mar 2024 23:34:04 +0100 Subject: [PATCH 12/13] qa: ignore `SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.NoAssignment` for inline var annotation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- src/Command/AheadOfTimeFactoryCreatorCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Command/AheadOfTimeFactoryCreatorCommand.php b/src/Command/AheadOfTimeFactoryCreatorCommand.php index 7ddaa5cd..9ba1ccb5 100644 --- a/src/Command/AheadOfTimeFactoryCreatorCommand.php +++ b/src/Command/AheadOfTimeFactoryCreatorCommand.php @@ -133,6 +133,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $containerConfigurations[$factory->containerConfigurationKey] = ['factories' => []]; } + // phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.NoAssignment /** * Psalm has to understand that the `factoryClassName` variable contains a class-string to a factory which * will be available once persisted to the filesystem and loaded via composer autoloading. From ee7ab4efeb2b46f56bbe2777417ac84ad71f3f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Sat, 2 Mar 2024 23:36:43 +0100 Subject: [PATCH 13/13] qa: remove redundant method implementations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These methods were initially introduced to fix psalm issues. These were fixed in one of the more recent versions and thus these methods are redundant as of now. Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- src/AbstractSingleInstancePluginManager.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/AbstractSingleInstancePluginManager.php b/src/AbstractSingleInstancePluginManager.php index c0a998af..e56ce5eb 100644 --- a/src/AbstractSingleInstancePluginManager.php +++ b/src/AbstractSingleInstancePluginManager.php @@ -26,22 +26,6 @@ abstract class AbstractSingleInstancePluginManager extends AbstractPluginManager */ protected string $instanceOf; - /** - * {@inheritDoc} - */ - public function get(string $id): object - { - return parent::get($id); - } - - /** - * {@inheritDoc} - */ - public function build(string $name, ?array $options = null): object - { - return parent::build($name, $options); - } - /** * {@inheritDoc} */