diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b77eca8..0b1cae2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: with: fetch-depth: 2 # required by Scrutinizer - run: composer install --no-progress --no-ansi --no-interaction --dev --prefer-dist - - run: php test/test.php + - run: composer test && composer inspect - if: matrix.coverage == 'xdebug' uses: sudo-bot/action-scrutinizer@latest with: diff --git a/composer.json b/composer.json index 9d9ec8d..b709551 100644 --- a/composer.json +++ b/composer.json @@ -18,10 +18,12 @@ "mindplay/testies": "^1.1.2", "php-di/php-di": "^7.0.5", "pimple/pimple": "^3.5", - "phpunit/php-code-coverage": "^9 || ^10 || ^11" + "phpunit/php-code-coverage": "^9 || ^10 || ^11", + "phpstan/phpstan": "^1.10" }, "scripts": { - "test": "XDEBUG_MODE=coverage php test/test.php" + "test": "XDEBUG_MODE=coverage php test/test.php", + "inspect": "phpstan" }, "autoload": { "psr-4": { diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..d7f8277 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + level: 6 + paths: + - src diff --git a/src/Configuration.php b/src/Configuration.php index 5432277..d78a779 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -2,33 +2,35 @@ namespace mindplay\unbox; +use Psr\Container\ContainerInterface; + /** * This abstract base-class defines the internal state of `Container` and `ContainerFactory` */ abstract class Configuration { /** - * @var mixed[] map where component name => value + * @var array map where component name => value */ protected $values = []; /** - * @var callable[] map where component name => factory function + * @var array map where component name => factory function */ protected $factory = []; /** - * @var array map where component name => mixed list/map of parameter names + * @var array> map where component name => mixed list/map of parameter names */ protected $factory_map = []; /** - * @var callable[][] map where component name => list of configuration functions + * @var array map where component name => list of configuration functions */ protected $config = []; /** - * @var callable[][] map where component name => mixed list/map of parameter names + * @var array>> map where component name => mixed list/map of parameter names */ protected $config_map = []; @@ -51,10 +53,8 @@ public function has(string $name): bool /** * Internally copy configuration state, e.g. from `ContainerFactory` to `Container` - * - * @param Configuration $target */ - protected function copyTo(Configuration $target) + protected function copyTo(Configuration $target): void { $target->values = $this->values; $target->factory = $this->factory; diff --git a/src/Container.php b/src/Container.php index 9e465bf..b8c613b 100644 --- a/src/Container.php +++ b/src/Container.php @@ -12,20 +12,17 @@ class Container extends Configuration implements ContainerInterface, FactoryInterface { /** - * @var bool[] map where component name => TRUE, if the component has been initialized + * @var array map where component name => TRUE, if the component has been initialized */ protected $active = []; /** - * @var int[] map where component name => activation depth + * @var array map where component name => activation depth * * @see get() */ private $activations = []; - /** - * @param Configuration $config - */ public function __construct(Configuration $config) { $config->copyTo($this); @@ -42,9 +39,11 @@ public function __construct(Configuration $config) /** * Resolve the registered component with the given name. * + * @template T of object + * * @param string $name component name - * - * @return mixed component instance/value + * + * @return ($name is class-string ? T : mixed) component instance/value * * @throws NotFoundException */ @@ -153,8 +152,8 @@ public function isActive(string $name): bool * * See also {@see create()} which lets you invoke any constructor. * - * @param callable|object $callback any arbitrary closure or callable, or object implementing __invoke() - * @param mixed|mixed[] $map mixed list/map of parameter values (and/or boxed values) + * @param callable $callback any arbitrary closure or callable + * @param array $map mixed list/map of parameter values (and/or boxed values) * * @return mixed return value from the given callable */ @@ -171,14 +170,14 @@ public function call(callable $callback, array $map = []) * The container will internally resolve and inject any constructor arguments * not explicitly provided in the (optional) second parameter. * - * @param string $class_name fully-qualified class-name - * @param mixed|mixed[] $map mixed list/map of parameter values (and/or boxed values) + * @param string $class_name fully-qualified class-name + * @param array $map mixed list/map of parameter values (and/or boxed values) * * @return mixed new instance of the specified class * * @throws InvalidArgumentException */ - public function create(string $class_name, array $map = []) + public function create(string $class_name, array $map = []): mixed { if (! class_exists($class_name)) { throw new InvalidArgumentException("unable to create component: {$class_name} (autoloading failed)"); @@ -204,15 +203,15 @@ public function create(string $class_name, array $map = []) * * This is the heart of the beast. * - * @param ReflectionParameter[] $params parameter reflections - * @param array $map mixed list/map of parameter values (and/or boxed values) - * @param bool $safe if TRUE, it's considered safe to resolve against parameter names + * @param ReflectionParameter[] $params parameter reflections + * @param array $map mixed list/map of parameter values (and/or boxed values) + * @param bool $safe if TRUE, it's considered safe to resolve against parameter names * - * @return array parameters + * @return array parameters * * @throws ContainerException */ - protected function resolve($params, $map, $safe = true) + protected function resolve($params, $map, $safe = true): array { $args = []; diff --git a/src/ContainerFactory.php b/src/ContainerFactory.php index 01820e6..4ee9cb9 100644 --- a/src/ContainerFactory.php +++ b/src/ContainerFactory.php @@ -275,7 +275,7 @@ public function add(ProviderInterface $provider): void * * @see provides() */ - public function requires(string $requirement, string $description = "") + public function requires(string $requirement, string $description = ""): void { $this->required[$requirement][] = $description; } @@ -291,7 +291,7 @@ public function requires(string $requirement, string $description = "") * * @see requires() */ - public function provides(string $requirement, string $description = "") + public function provides(string $requirement, string $description = ""): void { if (array_key_exists($requirement, $this->provided)) { $message = "The following Requirement has already been fulfilled: {$requirement}"; @@ -338,7 +338,7 @@ public function registerFallback(ContainerInterface $container): void * * @throws ContainerException if any Requirements have not been fulfilled */ - public function createContainer() + public function createContainer(): Container { $messages = []; diff --git a/src/FactoryInterface.php b/src/FactoryInterface.php index eb90667..db29a54 100644 --- a/src/FactoryInterface.php +++ b/src/FactoryInterface.php @@ -14,8 +14,8 @@ interface FactoryInterface * The factory will internally resolve and inject any constructor arguments * not explicitly provided in the (optional) second parameter. * - * @param string $class_name fully-qualified class-name - * @param mixed|mixed[] $map mixed list/map of parameter values (and/or boxed values) + * @param string $class_name fully-qualified class-name + * @param array $map mixed list/map of parameter values (and/or boxed values) * * @return mixed new instance of the specified class */ diff --git a/src/Reflection.php b/src/Reflection.php index 007def0..0e92c9d 100644 --- a/src/Reflection.php +++ b/src/Reflection.php @@ -15,9 +15,9 @@ abstract class Reflection { /** - * Create a Reflection of the function referenced by any type of callable (or object implementing `__invoke()`) + * Create a Reflection of the function referenced by any type of callable * - * @param callable|object $callback + * @param callable $callback * * @return ReflectionFunctionAbstract *