diff --git a/.gitattributes b/.gitattributes index 669f2d3e..e07b2296 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,3 +10,4 @@ /phpcs.xml export-ignore /phpunit.xml.dist export-ignore /test/ export-ignore +/phpstan.neon.dist export-ignore diff --git a/.gitignore b/.gitignore index 245087af..fa4db2fa 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /vendor/ /zf-mkdoc-theme.tgz /zf-mkdoc-theme/ +/phpstan.neon \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 37c8192d..35e9c983 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ env: global: - COMPOSER_ARGS="--no-interaction" - COVERAGE_DEPS="php-coveralls/php-coveralls" + - STATIC_ANALYSIS_DEPS="phpstan/phpstan" matrix: include: @@ -22,6 +23,7 @@ matrix: - CS_CHECK=true - BENCHMARKS=true - TEST_COVERAGE=true + - STATIC_ANALYSIS=true - php: 7.1 env: - DEPS=latest @@ -43,12 +45,14 @@ install: - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi + - if [[ $STATIC_ANALYSIS == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $STATIC_ANALYSIS_DEPS ; fi - stty cols 120 && composer show script: - if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi - if [[ $BENCHMARKS == 'true' ]]; then vendor/bin/phpbench run --revs=2 --iterations=2 --report=aggregate ; fi - if [[ $CS_CHECK == 'true' ]]; then composer cs-check ; fi + - if [[ $STATIC_ANALYSIS == 'true' ]]; then ./vendor/bin/phpstan analyse --no-progress . ; fi after_script: - if [[ $TEST_COVERAGE == 'true' ]]; then vendor/bin/php-coveralls -v ; fi diff --git a/composer.lock b/composer.lock index eb75628a..94d96ec4 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": "47e70e08f053951ac74c562e3143801a", + "content-hash": "f280e96d0b05401d973f1fdd15dc0c90", "packages": [ { "name": "psr/container", @@ -594,27 +594,27 @@ }, { "name": "ocramius/package-versions", - "version": "1.1.3", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/Ocramius/PackageVersions.git", - "reference": "72b226d2957e9e6a9ed09aeaa29cabd840d1a3b7" + "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/72b226d2957e9e6a9ed09aeaa29cabd840d1a3b7", - "reference": "72b226d2957e9e6a9ed09aeaa29cabd840d1a3b7", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4489d5002c49d55576fa0ba786f42dbb009be46f", + "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0", - "php": "~7.0" + "composer-plugin-api": "^1.0.0", + "php": "^7.1.0" }, "require-dev": { - "composer/composer": "^1.3", + "composer/composer": "^1.6.3", "ext-zip": "*", - "humbug/humbug": "dev-master", - "phpunit/phpunit": "^5.7.5" + "infection/infection": "^0.7.1", + "phpunit/phpunit": "^7.0.0" }, "type": "composer-plugin", "extra": { @@ -639,7 +639,7 @@ } ], "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "time": "2017-09-06T15:24:43+00:00" + "time": "2018-02-05T13:05:30+00:00" }, { "name": "ocramius/proxy-manager", @@ -1577,16 +1577,16 @@ }, { "name": "psr/log", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", "shasum": "" }, "require": { @@ -1620,7 +1620,7 @@ "psr", "psr-3" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2018-11-20T15:27:04+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -2310,44 +2310,45 @@ }, { "name": "symfony/console", - "version": "v3.3.13", + "version": "v3.4.20", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "63cd7960a0a522c3537f6326706d7f3b8de65805" + "reference": "8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/63cd7960a0a522c3537f6326706d7f3b8de65805", - "reference": "63cd7960a0a522c3537f6326706d7f3b8de65805", + "url": "https://api.github.com/repos/symfony/console/zipball/8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb", + "reference": "8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0", + "symfony/debug": "~2.8|~3.0|~4.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~3.3", - "symfony/dependency-injection": "~3.3", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/filesystem": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" }, "suggest": { - "psr/log": "For using the console logger", + "psr/log-implementation": "For using the console logger", "symfony/event-dispatcher": "", - "symfony/filesystem": "", + "symfony/lock": "", "symfony/process": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -2374,20 +2375,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-11-16T15:24:32+00:00" + "time": "2018-11-26T12:48:07+00:00" }, { "name": "symfony/debug", - "version": "v3.3.13", + "version": "v3.4.20", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "74557880e2846b5c84029faa96b834da37e29810" + "reference": "a2233f555ddf55e5600f386fba7781cea1cb82d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/74557880e2846b5c84029faa96b834da37e29810", - "reference": "74557880e2846b5c84029faa96b834da37e29810", + "url": "https://api.github.com/repos/symfony/debug/zipball/a2233f555ddf55e5600f386fba7781cea1cb82d3", + "reference": "a2233f555ddf55e5600f386fba7781cea1cb82d3", "shasum": "" }, "require": { @@ -2398,12 +2399,12 @@ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -2430,7 +2431,7 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-11-10T16:38:39+00:00" + "time": "2018-11-27T12:43:10+00:00" }, { "name": "symfony/filesystem", @@ -2483,16 +2484,16 @@ }, { "name": "symfony/finder", - "version": "v3.3.13", + "version": "v3.4.20", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "138af5ec075d4b1d1bd19de08c38a34bb2d7d880" + "reference": "6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/138af5ec075d4b1d1bd19de08c38a34bb2d7d880", - "reference": "138af5ec075d4b1d1bd19de08c38a34bb2d7d880", + "url": "https://api.github.com/repos/symfony/finder/zipball/6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442", + "reference": "6cf2be5cbd0e87aa35c01f80ae0bf40b6798e442", "shasum": "" }, "require": { @@ -2501,7 +2502,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -2528,7 +2529,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-11-05T15:47:03+00:00" + "time": "2018-11-11T19:48:54+00:00" }, { "name": "symfony/options-resolver", @@ -2586,16 +2587,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.6.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", - "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", "shasum": "" }, "require": { @@ -2607,7 +2608,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.9-dev" } }, "autoload": { @@ -2641,7 +2642,7 @@ "portable", "shim" ], - "time": "2017-10-11T12:05:26+00:00" + "time": "2018-09-21T13:07:52+00:00" }, { "name": "symfony/process", diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 00000000..d055445e --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,28 @@ +parameters: + level: max + + fileExtensions: + - php + + excludes_analyse: + - %currentWorkingDirectory%/benchmarks/* + - %currentWorkingDirectory%/bin/* + - %currentWorkingDirectory%/docs/* + - %currentWorkingDirectory%/test/* + - %currentWorkingDirectory%/vendor/* + + ignoreErrors: + - '#PHPDoc tag @throws with type Psr\\Container\\ContainerExceptionInterface is not subtype of Throwable#' +# AbstractPluginManager::__construct() accepts more types: + - + message: '#Result of && is always false#' + path: %currentWorkingDirectory%/src/AbstractPluginManager.php + - + message: '#Else branch is unreachable because ternary operator condition is always true#' + path: %currentWorkingDirectory%/src/AbstractPluginManager.php + - + message: '#Default value of the parameter \#1 \$resource \(mixed\) of method Zend\\ServiceManager\\Tool\\FactoryCreatorCommand::help\(\) is incompatible with type resource#' + path: %currentWorkingDirectory%/src/Tool/FactoryCreatorCommand.php + - + message: '#Default value of the parameter \#1 \$resource \(mixed\) of method Zend\\ServiceManager\\Tool\\ConfigDumperCommand::help\(\) is incompatible with type resource#' + path: %currentWorkingDirectory%/src/Tool/ConfigDumperCommand.php diff --git a/src/AbstractFactory/ConfigAbstractFactory.php b/src/AbstractFactory/ConfigAbstractFactory.php index eef3c935..8368f475 100644 --- a/src/AbstractFactory/ConfigAbstractFactory.php +++ b/src/AbstractFactory/ConfigAbstractFactory.php @@ -26,10 +26,16 @@ final class ConfigAbstractFactory implements AbstractFactoryInterface */ public function canCreate(\Psr\Container\ContainerInterface $container, $requestedName) { - if (! $container->has('config') || ! array_key_exists(self::class, $container->get('config'))) { + if (! $container->has('config')) { return false; } + $config = $container->get('config'); + + if (! isset($config[self::class])) { + return false; + } + $dependencies = $config[self::class]; return is_array($dependencies) && array_key_exists($requestedName, $dependencies); @@ -50,7 +56,7 @@ public function __invoke(\Psr\Container\ContainerInterface $container, $requeste throw new ServiceNotCreatedException('Config must be an array or an instance of ArrayObject'); } - if (! array_key_exists(self::class, $config)) { + if (! isset($config[self::class])) { throw new ServiceNotCreatedException('Cannot find a `' . self::class . '` key in the config array'); } diff --git a/src/AbstractFactory/ReflectionBasedAbstractFactory.php b/src/AbstractFactory/ReflectionBasedAbstractFactory.php index 98ff9f26..36b0e258 100644 --- a/src/AbstractFactory/ReflectionBasedAbstractFactory.php +++ b/src/AbstractFactory/ReflectionBasedAbstractFactory.php @@ -114,7 +114,9 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o { $reflectionClass = new ReflectionClass($requestedName); - if (null === ($constructor = $reflectionClass->getConstructor())) { + $constructor = $reflectionClass->getConstructor(); + + if (null === $constructor) { return new $requestedName(); } @@ -213,7 +215,9 @@ private function resolveParameter(ReflectionParameter $parameter, ContainerInter return []; } - if (! $parameter->getClass()) { + $parameterClass = $parameter->getClass(); + + if (! $parameterClass) { if (! $parameter->isDefaultValueAvailable()) { throw new ServiceNotFoundException(sprintf( 'Unable to create service "%s"; unable to resolve parameter "%s" ' @@ -226,7 +230,7 @@ private function resolveParameter(ReflectionParameter $parameter, ContainerInter return $parameter->getDefaultValue(); } - $type = $parameter->getClass()->getName(); + $type = $parameterClass->getName(); $type = $this->aliases[$type] ?? $type; if ($container->has($type)) { diff --git a/src/AbstractFactoryInterface.php b/src/AbstractFactoryInterface.php index e45c226b..054bea35 100644 --- a/src/AbstractFactoryInterface.php +++ b/src/AbstractFactoryInterface.php @@ -40,8 +40,8 @@ interface AbstractFactoryInterface extends Factory\AbstractFactoryInterface * Determine if we can create a service with name * * @param ServiceLocatorInterface $serviceLocator - * @param $name - * @param $requestedName + * @param string $name + * @param string $requestedName * @return bool */ public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName); @@ -50,8 +50,8 @@ public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator * Create service with name * * @param ServiceLocatorInterface $serviceLocator - * @param $name - * @param $requestedName + * @param string $name + * @param string $requestedName * @return mixed */ public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName); diff --git a/src/Exception/CyclicAliasException.php b/src/Exception/CyclicAliasException.php index b6b95c2d..c45e247e 100644 --- a/src/Exception/CyclicAliasException.php +++ b/src/Exception/CyclicAliasException.php @@ -46,6 +46,7 @@ public static function fromCyclicAlias($alias, array $aliases) */ public static function fromAliasesMap(array $aliases) { + /** @var bool[][] $detectedCycles */ $detectedCycles = array_filter(array_map( function ($alias) use ($aliases) { return self::getCycleFor($aliases, $alias); @@ -73,7 +74,7 @@ function ($alias) use ($aliases) { * * @param string[] $aliases * @param string $alias - * @return array|null + * @return bool[]|null */ private static function getCycleFor(array $aliases, $alias) { @@ -108,7 +109,7 @@ private static function printReferencesMap(array $aliases) } /** - * @param string[][] $detectedCycles + * @param bool[][] $detectedCycles * @return string */ private static function printCycles(array $detectedCycles) @@ -117,7 +118,7 @@ private static function printCycles(array $detectedCycles) } /** - * @param string[] $detectedCycle + * @param bool[] $detectedCycle * @return string */ private static function printCycle(array $detectedCycle) diff --git a/src/Exception/ExceptionInterface.php b/src/Exception/ExceptionInterface.php index 278bb06d..6076220a 100644 --- a/src/Exception/ExceptionInterface.php +++ b/src/Exception/ExceptionInterface.php @@ -8,10 +8,11 @@ namespace Zend\ServiceManager\Exception; use Psr\Container\ContainerExceptionInterface; +use Throwable; /** * Base exception for all Zend\ServiceManager exceptions. */ -interface ExceptionInterface extends ContainerExceptionInterface +interface ExceptionInterface extends ContainerExceptionInterface, Throwable { } diff --git a/src/Factory/DelegatorFactoryInterface.php b/src/Factory/DelegatorFactoryInterface.php index 02e69c21..473d5000 100644 --- a/src/Factory/DelegatorFactoryInterface.php +++ b/src/Factory/DelegatorFactoryInterface.php @@ -7,6 +7,7 @@ namespace Zend\ServiceManager\Factory; +use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Zend\ServiceManager\Exception\ServiceNotCreatedException; use Zend\ServiceManager\Exception\ServiceNotFoundException; @@ -32,7 +33,7 @@ interface DelegatorFactoryInterface * @throws ServiceNotFoundException if unable to resolve the service. * @throws ServiceNotCreatedException if an exception is raised when * creating a service. - * @throws ContainerException if any other error occurs + * @throws ContainerExceptionInterface if any other error occurs */ public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null); } diff --git a/src/Factory/FactoryInterface.php b/src/Factory/FactoryInterface.php index 33084447..4ad20f6d 100644 --- a/src/Factory/FactoryInterface.php +++ b/src/Factory/FactoryInterface.php @@ -7,6 +7,7 @@ namespace Zend\ServiceManager\Factory; +use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Zend\ServiceManager\Exception\ServiceNotCreatedException; use Zend\ServiceManager\Exception\ServiceNotFoundException; @@ -31,7 +32,7 @@ interface FactoryInterface * @throws ServiceNotFoundException if unable to resolve the service. * @throws ServiceNotCreatedException if an exception is raised when * creating a service. - * @throws ContainerException if any other error occurs + * @throws ContainerExceptionInterface if any other error occurs */ public function __invoke(ContainerInterface $container, $requestedName, array $options = null); } diff --git a/src/InitializerInterface.php b/src/InitializerInterface.php index 23c5ac20..2f5f3646 100644 --- a/src/InitializerInterface.php +++ b/src/InitializerInterface.php @@ -32,7 +32,7 @@ interface InitializerInterface extends Initializer\InitializerInterface /** * Initialize * - * @param $instance + * @param mixed $instance * @param ServiceLocatorInterface $serviceLocator * @return mixed */ diff --git a/src/PluginManagerInterface.php b/src/PluginManagerInterface.php index 7392195e..77407e0f 100644 --- a/src/PluginManagerInterface.php +++ b/src/PluginManagerInterface.php @@ -19,11 +19,10 @@ interface PluginManagerInterface extends ServiceLocatorInterface /** * Validate an instance * - * @param object $instance + * @param object|array $instance * @return void * @throws InvalidServiceException If created instance does not respect the * constraint on type imposed by the plugin manager - * @throws ContainerException if any other error occurs */ public function validate($instance); } diff --git a/src/ServiceManager.php b/src/ServiceManager.php index e4d0c48f..a507993f 100644 --- a/src/ServiceManager.php +++ b/src/ServiceManager.php @@ -69,7 +69,7 @@ class ServiceManager implements ServiceLocatorInterface /** * Whether or not changes may be made to this instance. * - * @param bool + * @var bool */ protected $allowOverride = false; @@ -645,7 +645,7 @@ private function createDelegatorFromName($name, array $options = null) }; } - return $creationCallback($this->creationContext, $name, $creationCallback, $options); + return $creationCallback(); } /** @@ -926,7 +926,7 @@ private function mapAliasesToTargets() /** * Instantiate abstract factories in order to avoid checks during service construction. * - * @param string|Factory\AbstractFactoryInterface $abstractFactories + * @param string|Factory\AbstractFactoryInterface $abstractFactory * @return void */ private function resolveAbstractFactoryInstance($abstractFactory) diff --git a/src/Tool/ConfigDumper.php b/src/Tool/ConfigDumper.php index e4cb5a63..1b358a09 100644 --- a/src/Tool/ConfigDumper.php +++ b/src/Tool/ConfigDumper.php @@ -43,7 +43,7 @@ class ConfigDumper EOC; /** - * @var ContainerInterface + * @var ContainerInterface|null */ private $container; @@ -74,11 +74,12 @@ public function createDependencyConfig(array $config, $className, $ignoreUnresol } // class has no constructor, treat it as an invokable - if (! $reflectionClass->getConstructor()) { + $constructor = $reflectionClass->getConstructor(); + if (! $constructor) { return $this->createInvokable($config, $className); } - $constructorArguments = $reflectionClass->getConstructor()->getParameters(); + $constructorArguments = $constructor->getParameters(); $constructorArguments = array_filter( $constructorArguments, function (ReflectionParameter $argument) { @@ -121,7 +122,7 @@ function (ReflectionParameter $argument) { } /** - * @param $className + * @param string $className * @throws InvalidArgumentException if class name is not a string or does * not exist. */ diff --git a/src/Tool/ConfigDumperCommand.php b/src/Tool/ConfigDumperCommand.php index 60f44847..70523ded 100644 --- a/src/Tool/ConfigDumperCommand.php +++ b/src/Tool/ConfigDumperCommand.php @@ -139,7 +139,7 @@ private function parseArgs(array $args) $arg1 = array_shift($args); } - if (! $args) { + if (empty($args)) { return $this->createErrorArgument('Missing class name'); } diff --git a/src/Tool/FactoryCreator.php b/src/Tool/FactoryCreator.php index f3f19ec7..1b6bb00c 100644 --- a/src/Tool/FactoryCreator.php +++ b/src/Tool/FactoryCreator.php @@ -69,7 +69,7 @@ public function createFactory($className) } /** - * @param $className + * @param string $className * @return string */ private function getClassName($className) @@ -86,11 +86,12 @@ private function getConstructorParameters($className) { $reflectionClass = new ReflectionClass($className); - if (! $reflectionClass || ! $reflectionClass->getConstructor()) { + $reflectionConstructor = $reflectionClass->getConstructor(); + if (! $reflectionConstructor) { return []; } - $constructorParameters = $reflectionClass->getConstructor()->getParameters(); + $constructorParameters = $reflectionConstructor->getParameters(); if (empty($constructorParameters)) { return []; @@ -120,7 +121,9 @@ function (ReflectionParameter $argument) { } return array_map(function (ReflectionParameter $parameter) { - return $parameter->getClass()->getName(); + /** @var ReflectionClass $class */ + $class = $parameter->getClass(); + return $class->getName(); }, $constructorParameters); }