From 9b5ba5f1d4839456819e7e3498ab235a724b3d55 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 31 Aug 2021 11:19:10 +0200 Subject: [PATCH 01/44] opened 3.1-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 497ddb293..210f71ddb 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } } } From 681707b3310d5ade6ed5f642658c9d5b03f036ee Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 31 Aug 2021 11:20:03 +0200 Subject: [PATCH 02/44] requires PHP 7.2 --- .github/workflows/coding-style.yml | 2 +- .github/workflows/tests.yml | 4 ++-- composer.json | 2 +- readme.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 337a0a631..40437ada3 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.1 + php-version: 7.2 coverage: none - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index de8c8e95e..266902db6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1'] + php: ['7.2', '7.3', '7.4', '8.0', '8.1'] fail-fast: false @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.1 + php-version: 7.2 coverage: none - run: composer update --no-progress --prefer-dist --prefer-lowest --prefer-stable diff --git a/composer.json b/composer.json index 210f71ddb..e0d60ba78 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=7.1 <8.2", + "php": ">=7.2 <8.2", "ext-tokenizer": "*", "nette/neon": "^3.3 || ^4.0", "nette/php-generator": "^3.5.4 || ^4.0", diff --git a/readme.md b/readme.md index 642cfc2fd..d68757b83 100644 --- a/readme.md +++ b/readme.md @@ -37,7 +37,7 @@ The recommended way to install is via Composer: composer require nette/di ``` -It requires PHP version 7.1 and supports PHP up to 8.1. +It requires PHP version 7.2 and supports PHP up to 8.1. Usage From 6d0479a1f10ab9db38bc2d009a28ea3cf0fee34a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 13 Sep 2021 12:33:45 +0200 Subject: [PATCH 03/44] uses nette/utils 3.2 --- composer.json | 2 +- src/DI/Resolver.php | 2 +- tests/DI/Resolver.autowireArguments.80.phpt | 2 +- tests/DI/Resolver.autowireArguments.81.phpt | 2 +- tests/DI/Resolver.autowireArguments.errors.phpt | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index e0d60ba78..7a82450d7 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "nette/php-generator": "^3.5.4 || ^4.0", "nette/robot-loader": "^3.2", "nette/schema": "^1.1", - "nette/utils": "^3.1.6" + "nette/utils": "^3.2.5" }, "require-dev": { "nette/tester": "^2.2", diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 8b02facbd..641d1712a 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -628,7 +628,7 @@ private static function autowireArgument(\ReflectionParameter $parameter, callab $desc = Reflection::toString($parameter); $type = Nette\Utils\Type::fromReflection($parameter); - if ($parameter->getType() instanceof \ReflectionIntersectionType) { + if ($type && $type->isIntersection()) { throw new ServiceCreationException(sprintf( 'Parameter %s has intersection type, so its value must be specified.', $desc diff --git a/tests/DI/Resolver.autowireArguments.80.phpt b/tests/DI/Resolver.autowireArguments.80.phpt index 7ebf0b136..4dd145455 100644 --- a/tests/DI/Resolver.autowireArguments.80.phpt +++ b/tests/DI/Resolver.autowireArguments.80.phpt @@ -25,7 +25,7 @@ Assert::exception(function () { [], function () {} ); -}, Nette\InvalidStateException::class, 'Parameter $x in {closure}%a?% has union type and no default value, so its value must be specified.'); +}, Nette\InvalidStateException::class, 'Parameter $x in {closure}() has union type and no default value, so its value must be specified.'); // nullable union Assert::same( diff --git a/tests/DI/Resolver.autowireArguments.81.phpt b/tests/DI/Resolver.autowireArguments.81.phpt index 721cb1383..241f611a3 100644 --- a/tests/DI/Resolver.autowireArguments.81.phpt +++ b/tests/DI/Resolver.autowireArguments.81.phpt @@ -30,7 +30,7 @@ Assert::exception(function () { [], function () {} ); -}, Nette\InvalidStateException::class, 'Parameter $x in {closure}%a?% has intersection type, so its value must be specified.'); +}, Nette\InvalidStateException::class, 'Parameter $x in {closure}() has intersection type, so its value must be specified.'); // object as default Assert::same( diff --git a/tests/DI/Resolver.autowireArguments.errors.phpt b/tests/DI/Resolver.autowireArguments.errors.phpt index 11c748bd3..ba801b0d3 100644 --- a/tests/DI/Resolver.autowireArguments.errors.phpt +++ b/tests/DI/Resolver.autowireArguments.errors.phpt @@ -20,7 +20,7 @@ Assert::exception(function () { [], function () {} ); -}, Nette\DI\ServiceCreationException::class, 'Service of type stdClass required by $x in {closure}%a?% not found. Did you add it to configuration file?'); +}, Nette\DI\ServiceCreationException::class, 'Service of type stdClass required by $x in {closure}() not found. Did you add it to configuration file?'); // not found @@ -30,7 +30,7 @@ Assert::exception(function () { [], function () {} ); -}, Nette\DI\ServiceCreationException::class, "Class 'Foo' required by \$x in {closure}%a?% not found. Check the parameter type and 'use' statements."); +}, Nette\DI\ServiceCreationException::class, "Class 'Foo' required by \$x in {closure}() not found. Check the parameter type and 'use' statements."); // no typehint @@ -40,7 +40,7 @@ Assert::exception(function () { [], function () {} ); -}, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}%a?% has no class type or default value, so its value must be specified.'); +}, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}() has no class type or default value, so its value must be specified.'); // scalar @@ -50,7 +50,7 @@ Assert::exception(function () { [], function () {} ); -}, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}%a?% has no class type or default value, so its value must be specified.'); +}, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}() has no class type or default value, so its value must be specified.'); // bad variadics (this is actually what PHP allows) @@ -60,7 +60,7 @@ Assert::exception(function () { [1, 'args' => []], function () {} ); -}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}%a?%.'); +}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}().'); // bad variadics @@ -70,4 +70,4 @@ Assert::exception(function () { ['args' => [], 1], function () {} ); -}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}%a?%.'); +}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}().'); From e1b51bda2b9e590bdc55faeceff408bb02ba089a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 12 Jan 2021 16:06:00 +0100 Subject: [PATCH 04/44] removed deprecated stuff --- src/DI/Compiler.php | 14 ---- src/DI/Config/DefinitionSchema.php | 20 +++--- src/DI/Config/Helpers.php | 9 +-- src/DI/ContainerBuilder.php | 8 --- src/DI/Definitions/FactoryDefinition.php | 75 --------------------- src/DI/Definitions/ServiceDefinition.php | 52 -------------- src/DI/Extensions/DIExtension.php | 11 --- tests/DI/DIExtension.run.phpt | 32 --------- tests/DI/Definitions.ServiceDefinition.phpt | 23 ------- 9 files changed, 12 insertions(+), 232 deletions(-) delete mode 100644 tests/DI/DIExtension.run.phpt diff --git a/src/DI/Compiler.php b/src/DI/Compiler.php index c4ecfc2dc..35e12ed7d 100644 --- a/src/DI/Compiler.php +++ b/src/DI/Compiler.php @@ -332,18 +332,4 @@ protected function createPhpGenerator(): PhpGenerator { return new PhpGenerator($this->builder); } - - - /** @deprecated use non-static Compiler::loadDefinitionsFromConfig() */ - public static function loadDefinitions(): void - { - throw new Nette\DeprecatedException(__METHOD__ . '() is deprecated, use non-static Compiler::loadDefinitionsFromConfig(array $configList).'); - } - - - /** @deprecated use non-static Compiler::loadDefinitionsFromConfig() */ - public static function loadDefinition(): void - { - throw new Nette\DeprecatedException(__METHOD__ . '() is deprecated, use non-static Compiler::loadDefinitionsFromConfig(array $configList).'); - } } diff --git a/src/DI/Config/DefinitionSchema.php b/src/DI/Config/DefinitionSchema.php index 4249a91f9..62b57f179 100644 --- a/src/DI/Config/DefinitionSchema.php +++ b/src/DI/Config/DefinitionSchema.php @@ -103,16 +103,16 @@ public function normalize($def, Context $context) unset($def['create']); } - if (isset($def['class']) && !isset($def['type'])) { - if ($def['class'] instanceof Statement) { - $key = end($context->path); - trigger_error(sprintf("Service '%s': option 'class' should be changed to 'factory'.", $key), E_USER_DEPRECATED); - $def['factory'] = $def['class']; - unset($def['class']); - } elseif (!isset($def['factory']) && !isset($def['dynamic']) && !isset($def['imported'])) { - $def['factory'] = $def['class']; - unset($def['class']); - } + // back compatibility + if ( + isset($def['class']) + && !isset($def['type']) + && !isset($def['factory']) + && !isset($def['dynamic']) + && !isset($def['imported']) + ) { + $def['factory'] = $def['class']; + unset($def['class']); } foreach (['class' => 'type', 'dynamic' => 'imported'] as $alias => $original) { diff --git a/src/DI/Config/Helpers.php b/src/DI/Config/Helpers.php index 531d88ba6..9124a5236 100644 --- a/src/DI/Config/Helpers.php +++ b/src/DI/Config/Helpers.php @@ -23,19 +23,14 @@ final class Helpers public const PREVENT_MERGING = '_prevent_merging'; - /** - * Merges configurations. Left has higher priority than right one. - * @return array|string - */ + /** @deprecated */ public static function merge($left, $right) { return Nette\Schema\Helpers::merge($left, $right); } - /** - * Return true if array prevents merging and removes this information. - */ + /** @deprecated */ public static function takeParent(&$data): bool { if (is_array($data) && isset($data[self::PREVENT_MERGING])) { diff --git a/src/DI/ContainerBuilder.php b/src/DI/ContainerBuilder.php index ebdb1c4a2..394475fc0 100644 --- a/src/DI/ContainerBuilder.php +++ b/src/DI/ContainerBuilder.php @@ -417,12 +417,4 @@ public function formatPhp(string $statement, array $args): string }); return (new PhpGenerator($this))->formatPhp($statement, $args); } - - - /** @deprecated use resolve() */ - public function prepareClassList(): void - { - trigger_error(__METHOD__ . '() is deprecated, use resolve()', E_USER_DEPRECATED); - $this->resolve(); - } } diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index c4fd315d0..9c942ba7b 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -89,81 +89,6 @@ public function getResultDefinition(): Definition } - /** - * @deprecated use ->getResultDefinition()->setFactory() - * @return static - */ - public function setFactory($factory, array $args = []) - { - trigger_error(sprintf('Service %s: %s() is deprecated, use ->getResultDefinition()->setFactory()', $this->getName(), __METHOD__), E_USER_DEPRECATED); - $this->resultDefinition->setFactory($factory, $args); - return $this; - } - - - /** @deprecated use ->getResultDefinition()->getFactory() */ - public function getFactory(): ?Statement - { - trigger_error(sprintf('Service %s: %s() is deprecated, use ->getResultDefinition()->getFactory()', $this->getName(), __METHOD__), E_USER_DEPRECATED); - return $this->resultDefinition->getFactory(); - } - - - /** - * @deprecated use ->getResultDefinition()->getEntity() - * @return mixed - */ - public function getEntity() - { - trigger_error(sprintf('Service %s: %s() is deprecated, use ->getResultDefinition()->getEntity()', $this->getName(), __METHOD__), E_USER_DEPRECATED); - return $this->resultDefinition->getEntity(); - } - - - /** - * @deprecated use ->getResultDefinition()->setArguments() - * @return static - */ - public function setArguments(array $args = []) - { - trigger_error(sprintf('Service %s: %s() is deprecated, use ->getResultDefinition()->setArguments()', $this->getName(), __METHOD__), E_USER_DEPRECATED); - $this->resultDefinition->setArguments($args); - return $this; - } - - - /** - * @deprecated use ->getResultDefinition()->setSetup() - * @return static - */ - public function setSetup(array $setup) - { - trigger_error(sprintf('Service %s: %s() is deprecated, use ->getResultDefinition()->setSetup()', $this->getName(), __METHOD__), E_USER_DEPRECATED); - $this->resultDefinition->setSetup($setup); - return $this; - } - - - /** @deprecated use ->getResultDefinition()->getSetup() */ - public function getSetup(): array - { - trigger_error(sprintf('Service %s: %s() is deprecated, use ->getResultDefinition()->getSetup()', $this->getName(), __METHOD__), E_USER_DEPRECATED); - return $this->resultDefinition->getSetup(); - } - - - /** - * @deprecated use ->getResultDefinition()->addSetup() - * @return static - */ - public function addSetup($entity, array $args = []) - { - trigger_error(sprintf('Service %s: %s() is deprecated, use ->getResultDefinition()->addSetup()', $this->getName(), __METHOD__), E_USER_DEPRECATED); - $this->resultDefinition->addSetup($entity, $args); - return $this; - } - - /** @return static */ public function setParameters(array $params) { diff --git a/src/DI/Definitions/ServiceDefinition.php b/src/DI/Definitions/ServiceDefinition.php index 924059bd1..2e862fd5c 100644 --- a/src/DI/Definitions/ServiceDefinition.php +++ b/src/DI/Definitions/ServiceDefinition.php @@ -35,21 +35,6 @@ public function __construct() } - /** @deprecated Use setType() */ - public function setClass(?string $type) - { - $this->setType($type); - if (func_num_args() > 1) { - trigger_error(sprintf('Service %s: %s() second parameter $args is deprecated, use setFactory()', $this->getName(), __METHOD__), E_USER_DEPRECATED); - if ($args = func_get_arg(1)) { - $this->setFactory($type, $args); - } - } - - return $this; - } - - /** @return static */ public function setType(?string $type) { @@ -152,43 +137,6 @@ public function addSetup($entity, array $args = []) } - /** @deprecated */ - public function setParameters(array $params) - { - throw new Nette\DeprecatedException(sprintf('Service %s: %s() is deprecated.', $this->getName(), __METHOD__)); - } - - - /** @deprecated */ - public function getParameters(): array - { - trigger_error(sprintf('Service %s: %s() is deprecated.', $this->getName(), __METHOD__), E_USER_DEPRECATED); - return []; - } - - - /** @deprecated use $builder->addImportedDefinition(...) */ - public function setDynamic(): void - { - throw new Nette\DeprecatedException(sprintf('Service %s: %s() is deprecated, use $builder->addImportedDefinition(...)', $this->getName(), __METHOD__)); - } - - - /** @deprecated use $builder->addFactoryDefinition(...) or addAccessorDefinition(...) */ - public function setImplement(): void - { - throw new Nette\DeprecatedException(sprintf('Service %s: %s() is deprecated, use $builder->addFactoryDefinition(...)', $this->getName(), __METHOD__)); - } - - - /** @deprecated use addTag('nette.inject') */ - public function setInject(bool $state = true) - { - trigger_error(sprintf('Service %s: %s() is deprecated, use addTag(Nette\DI\Extensions\InjectExtension::TAG_INJECT)', $this->getName(), __METHOD__), E_USER_DEPRECATED); - return $this->addTag(Nette\DI\Extensions\InjectExtension::TAG_INJECT, $state); - } - - public function resolveType(Nette\DI\Resolver $resolver): void { if (!$this->getEntity()) { diff --git a/src/DI/Extensions/DIExtension.php b/src/DI/Extensions/DIExtension.php index b96f6cf8e..7a0b3c966 100644 --- a/src/DI/Extensions/DIExtension.php +++ b/src/DI/Extensions/DIExtension.php @@ -92,8 +92,6 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class) ) { $this->enableTracyIntegration(); } - - $this->initializeTaggedServices(); } @@ -124,15 +122,6 @@ private function restrictTypes(Nette\PhpGenerator\ClassType $class): void } - private function initializeTaggedServices(): void - { - foreach (array_filter($this->getContainerBuilder()->findByTag('run')) as $name => $on) { - trigger_error("Tag 'run' used in service '$name' definition is deprecated.", E_USER_DEPRECATED); - $this->initialization->addBody('$this->getService(?);', [$name]); - } - } - - private function enableTracyIntegration(): void { Nette\Bridges\DITracy\ContainerPanel::$compilationTime = $this->time; diff --git a/tests/DI/DIExtension.run.phpt b/tests/DI/DIExtension.run.phpt deleted file mode 100644 index 27526245d..000000000 --- a/tests/DI/DIExtension.run.phpt +++ /dev/null @@ -1,32 +0,0 @@ -addExtension('di', new DIExtension); -$loader = new DI\Config\Loader; -$config = $loader->load(Tester\FileMock::create(' -services: - std: {factory: stdClass, tags: [run]} - - {factory: stdClass, tags: [run]} -', 'neon')); - -@eval($compiler->addConfig($config)->setClassName(Container1::class)->compile()); // @ tag is deprecated - -$container = new Container1; -Assert::false($container->isCreated('std')); - -$container->initialize(); -Assert::true($container->isCreated('std')); diff --git a/tests/DI/Definitions.ServiceDefinition.phpt b/tests/DI/Definitions.ServiceDefinition.phpt index 05e98f561..a458f38ff 100644 --- a/tests/DI/Definitions.ServiceDefinition.phpt +++ b/tests/DI/Definitions.ServiceDefinition.phpt @@ -19,11 +19,6 @@ Assert::exception(function () { $def->setType('Foo'); }, Nette\InvalidArgumentException::class, "Service '': Class or interface 'Foo' not found."); -Assert::exception(function () { - $def = new ServiceDefinition; - $def->setImplement('Foo'); -}, Nette\DeprecatedException::class); - test('', function () { $def = new ServiceDefinition; $def->setType(stdClass::class); @@ -35,24 +30,6 @@ test('', function () { Assert::null($def->getEntity()); }); -test('', function () { - $def = new ServiceDefinition; - Assert::error(function () use ($def) { - $def->setClass(stdClass::class, []); - }, E_USER_DEPRECATED); - Assert::same(stdClass::class, $def->getType()); - Assert::null($def->getEntity()); -}); - -test('', function () { - $def = new ServiceDefinition; - Assert::error(function () use ($def) { - $def->setClass(stdClass::class, [1, 2]); - }, E_USER_DEPRECATED); - Assert::same(stdClass::class, $def->getType()); - Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getFactory()); -}); - test('', function () { $def = new ServiceDefinition; $def->setFactory(stdClass::class); From df9cf43f6a7a5c296b670209b7338bec54f65d39 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 12 Jan 2021 16:23:16 +0100 Subject: [PATCH 05/44] some deprecated methods triggers notice --- src/DI/Definitions/Definition.php | 2 ++ src/DI/Definitions/ImportedDefinition.php | 1 + 2 files changed, 3 insertions(+) diff --git a/src/DI/Definitions/Definition.php b/src/DI/Definitions/Definition.php index 7be002f54..1aaa7583d 100644 --- a/src/DI/Definitions/Definition.php +++ b/src/DI/Definitions/Definition.php @@ -198,6 +198,7 @@ public function getClass(): ?string /** @deprecated Use '$def instanceof Nette\DI\Definitions\ImportedDefinition' */ public function isDynamic(): bool { + trigger_error(sprintf('Service %s: %s() is deprecated, use "instanceof ImportedDefinition".', $this->getName(), __METHOD__), E_USER_DEPRECATED); return false; } @@ -205,6 +206,7 @@ public function isDynamic(): bool /** @deprecated Use Nette\DI\Definitions\FactoryDefinition or AccessorDefinition */ public function getImplement(): ?string { + trigger_error(sprintf('Service %s: %s() is deprecated.', $this->getName(), __METHOD__), E_USER_DEPRECATED); return null; } diff --git a/src/DI/Definitions/ImportedDefinition.php b/src/DI/Definitions/ImportedDefinition.php index e03c245b7..2002f6f71 100644 --- a/src/DI/Definitions/ImportedDefinition.php +++ b/src/DI/Definitions/ImportedDefinition.php @@ -48,6 +48,7 @@ public function generateMethod(Nette\PhpGenerator\Method $method, PhpGenerator $ /** @deprecated use '$def instanceof ImportedDefinition' */ public function isDynamic(): bool { + trigger_error(sprintf('Service %s: %s() is deprecated, use "instanceof ImportedDefinition".', $this->getName(), __METHOD__), E_USER_DEPRECATED); return true; } } From e43b9edeba3af2160b8b2893d270fbd9f44deed8 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 31 Dec 2020 20:04:30 +0100 Subject: [PATCH 06/44] PhpExtension & ConstantsExtension are deprecated (have been moved to nette/bootstrap) --- src/DI/Extensions/ConstantsExtension.php | 2 ++ src/DI/Extensions/PhpExtension.php | 2 ++ tests/DI/ConstantsExtension.basic.phpt | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/DI/Extensions/ConstantsExtension.php b/src/DI/Extensions/ConstantsExtension.php index ab94e8766..3d34fb5f3 100644 --- a/src/DI/Extensions/ConstantsExtension.php +++ b/src/DI/Extensions/ConstantsExtension.php @@ -14,11 +14,13 @@ /** * Constant definitions. + * @deprecated use Nette\Bootstrap\Extensions\ConstantsExtension */ final class ConstantsExtension extends Nette\DI\CompilerExtension { public function loadConfiguration() { + trigger_error(self::class . ' is deprecated, use Nette\Bootstrap\Extensions\ConstantsExtension.', E_USER_DEPRECATED); foreach ($this->getConfig() as $name => $value) { $this->initialization->addBody('define(?, ?);', [$name, $value]); } diff --git a/src/DI/Extensions/PhpExtension.php b/src/DI/Extensions/PhpExtension.php index 6a469e32f..117bdfe84 100644 --- a/src/DI/Extensions/PhpExtension.php +++ b/src/DI/Extensions/PhpExtension.php @@ -14,6 +14,7 @@ /** * PHP directives definition. + * @deprecated use Nette\Bootstrap\Extensions\PhpExtension */ final class PhpExtension extends Nette\DI\CompilerExtension { @@ -25,6 +26,7 @@ public function getConfigSchema(): Nette\Schema\Schema public function loadConfiguration() { + trigger_error(self::class . ' is deprecated, use Nette\Bootstrap\Extensions\PhpExtension.', E_USER_DEPRECATED); foreach ($this->getConfig() as $name => $value) { if ($value === null) { continue; diff --git a/tests/DI/ConstantsExtension.basic.phpt b/tests/DI/ConstantsExtension.basic.phpt index 421e49c2c..925c641d8 100644 --- a/tests/DI/ConstantsExtension.basic.phpt +++ b/tests/DI/ConstantsExtension.basic.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/../bootstrap.php'; $compiler = new DI\Compiler; $compiler->addExtension('constants', new Nette\DI\Extensions\ConstantsExtension); -$container = createContainer($compiler, ' +$container = @createContainer($compiler, ' constants: a: hello A: WORLD From 2489ce2a9af8b20aebdd293e3c81cbd84a1487c5 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 15 Dec 2021 16:43:53 +0100 Subject: [PATCH 07/44] NeonAdapter: operator ? throws exception --- src/DI/Config/Adapters/NeonAdapter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DI/Config/Adapters/NeonAdapter.php b/src/DI/Config/Adapters/NeonAdapter.php index 5d15fd471..030977fee 100644 --- a/src/DI/Config/Adapters/NeonAdapter.php +++ b/src/DI/Config/Adapters/NeonAdapter.php @@ -83,7 +83,7 @@ public function process(array $arr): array } else { $tmp = $this->process([$val->value]); if (is_string($tmp[0]) && strpos($tmp[0], '?') !== false) { - trigger_error("Operator ? is deprecated in config files (used in '$this->file')", E_USER_DEPRECATED); + throw new Nette\DI\InvalidConfigurationException("Operator ? is deprecated in config file (used in '$this->file')"); } $val = new Statement($tmp[0], $this->process($val->attributes)); From 7d6951abb422baf7d55354ae0007821bd4f19a65 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 26 Sep 2021 23:08:35 +0200 Subject: [PATCH 08/44] generated factories should have defined return type, otherwise triggers warning --- src/DI/Definitions/AccessorDefinition.php | 6 +++ src/DI/Definitions/FactoryDefinition.php | 6 +++ src/DI/Definitions/LocatorDefinition.php | 8 ++++ src/DI/Helpers.php | 6 +-- .../Compiler.extension.defaultServices.phpt | 8 +--- tests/DI/Compiler.generatedAccessor.phpt | 3 +- tests/DI/Compiler.generatedFactory.phpt | 45 ++++++------------- ...ler.generatedFactory.scalarParameters.phpt | 3 +- tests/DI/ContainerBuilder.accessor.phpt | 6 +-- tests/DI/ContainerBuilder.aliases.phpt | 8 ++-- tests/DI/ContainerBuilder.aliases2.phpt | 4 +- ...ContainerBuilder.autowiring.implement.phpt | 3 +- tests/DI/ContainerBuilder.create.error.phpt | 4 +- .../ContainerBuilder.factory.arguments.phpt | 3 +- tests/DI/ContainerBuilder.factory.phpt | 6 +-- ...ContainerBuilder.factory.resolveClass.phpt | 40 +++-------------- ...DecoratorExtension.factories.accessor.phpt | 5 +-- tests/DI/DecoratorExtension.factories.phpt | 5 +-- .../Definitions.AccessorDefinition.api.phpt | 4 +- ...efinitions.AccessorDefinition.resolve.phpt | 14 +++--- .../DI/Definitions.FactoryDefinition.api.phpt | 4 +- ...Definitions.FactoryDefinition.resolve.phpt | 16 +++---- .../DI/Definitions.LocatorDefinition.api.phpt | 20 ++++----- 23 files changed, 94 insertions(+), 133 deletions(-) diff --git a/src/DI/Definitions/AccessorDefinition.php b/src/DI/Definitions/AccessorDefinition.php index f47c89a21..1cfc3561e 100644 --- a/src/DI/Definitions/AccessorDefinition.php +++ b/src/DI/Definitions/AccessorDefinition.php @@ -58,6 +58,12 @@ public function setImplement(string $interface) )); } + try { + Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::get()"); + } catch (Nette\DI\ServiceCreationException $e) { + trigger_error($e->getMessage(), E_USER_DEPRECATED); + } + return parent::setType($interface); } diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index 9c942ba7b..d8249da4e 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -58,6 +58,12 @@ public function setImplement(string $interface) )); } + try { + Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::create()"); + } catch (Nette\DI\ServiceCreationException $e) { + trigger_error($e->getMessage(), E_USER_DEPRECATED); + } + return parent::setType($interface); } diff --git a/src/DI/Definitions/LocatorDefinition.php b/src/DI/Definitions/LocatorDefinition.php index 416ec1970..0412ff7ab 100644 --- a/src/DI/Definitions/LocatorDefinition.php +++ b/src/DI/Definitions/LocatorDefinition.php @@ -48,6 +48,14 @@ public function setImplement(string $interface) $method->name )); } + + if ($method->getNumberOfParameters() === 0) { + try { + Nette\DI\Helpers::ensureClassType(Nette\Utils\Type::fromReflection($method), "return type of $interface::$method->name()", true); + } catch (Nette\DI\ServiceCreationException $e) { + trigger_error($e->getMessage(), E_USER_DEPRECATED); + } + } } return parent::setType($interface); diff --git a/src/DI/Helpers.php b/src/DI/Helpers.php index 35d0328e9..943519517 100644 --- a/src/DI/Helpers.php +++ b/src/DI/Helpers.php @@ -230,12 +230,12 @@ public static function getReturnTypeAnnotation(\ReflectionFunctionAbstract $func } - public static function ensureClassType(?Type $type, string $hint): string + public static function ensureClassType(?Type $type, string $hint, bool $allowNullable = false): string { if (!$type) { throw new ServiceCreationException(sprintf('%s is not declared.', ucfirst($hint))); - } elseif (!$type->isClass() || $type->isUnion()) { - throw new ServiceCreationException(sprintf("%s is not expected to be nullable/union/intersection/built-in, '%s' given.", ucfirst($hint), $type)); + } elseif (!$type->isClass() || (!$allowNullable && $type->isUnion())) { + throw new ServiceCreationException(sprintf("%s is not expected to be %sunion/intersection/built-in, '%s' given.", ucfirst($hint), $allowNullable ? '' : 'nullable/', $type)); } $class = $type->getSingleName(); diff --git a/tests/DI/Compiler.extension.defaultServices.phpt b/tests/DI/Compiler.extension.defaultServices.phpt index 454c4c4e5..0266b5d53 100644 --- a/tests/DI/Compiler.extension.defaultServices.phpt +++ b/tests/DI/Compiler.extension.defaultServices.phpt @@ -21,8 +21,7 @@ interface IIpsum } interface IIpsumFactory { - /** @return IIpsum */ - public function create(); + public function create(): IIpsum; } interface IFooBar { @@ -46,10 +45,7 @@ class FooBar implements IFooBar class Factory { - /** - * @return Lorem - */ - public static function createLorem() + public static function createLorem(): Lorem { return new Lorem; } diff --git a/tests/DI/Compiler.generatedAccessor.phpt b/tests/DI/Compiler.generatedAccessor.phpt index d6368d004..443770764 100644 --- a/tests/DI/Compiler.generatedAccessor.phpt +++ b/tests/DI/Compiler.generatedAccessor.phpt @@ -19,8 +19,7 @@ class Lorem interface ILoremAccessor { - /** @return Lorem */ - public function get(); + public function get(): Lorem; } diff --git a/tests/DI/Compiler.generatedFactory.phpt b/tests/DI/Compiler.generatedFactory.phpt index bc0161e0a..9cf3550cb 100644 --- a/tests/DI/Compiler.generatedFactory.phpt +++ b/tests/DI/Compiler.generatedFactory.phpt @@ -16,10 +16,7 @@ require __DIR__ . '/../bootstrap.php'; interface ILoremFactory { - /** - * @return Lorem - */ - public function create(); + public function create(): Lorem; } class Lorem @@ -43,11 +40,7 @@ interface IFinderFactory interface IArticleFactory { - /** - * @param string - * @return Article - */ - public function create($title); + public function create($title): Article; } class Article @@ -98,11 +91,7 @@ class Baz interface IFooFactory { - /** - * @param Baz - * @return Foo - */ - public function create(?Baz $baz = null); + public function create(?Baz $baz = null): Foo; } class Dolor @@ -121,8 +110,7 @@ class Dolor interface DolorFactory { - /** @return Dolor */ - public function create(?Bar $bar, $foo); + public function create(?Bar $bar, $foo): Dolor; } @@ -142,8 +130,7 @@ class TestClass interface ITestClassFactory { - /** @return TestClass */ - public function create($bar); + public function create($bar): TestClass; } class TestExtension extends DI\CompilerExtension @@ -168,7 +155,7 @@ class TestExtension extends DI\CompilerExtension $compiler = new DI\Compiler; $compiler->addExtension('test', new TestExtension); -$container = createContainer($compiler, 'files/compiler.generatedFactory.neon'); +@$container = createContainer($compiler, 'files/compiler.generatedFactory.neon'); // missing type triggers warning Assert::type(ILoremFactory::class, $container->getService('lorem')); @@ -284,15 +271,13 @@ class Bad1 interface Bad2 { - public function create(Baz $bar); + public function create(Baz $bar): Bad1; } Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addFactoryDefinition('one') - ->setImplement(Bad2::class) - ->getResultDefinition() - ->setFactory(Bad1::class); + ->setImplement(Bad2::class); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one' (type of Bad2): Type of \$bar in Bad2::create() doesn't match type in Bad1 constructor."); @@ -307,15 +292,13 @@ class Bad3 interface Bad4 { - public function create($baz); + public function create($baz): Bad3; } Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addFactoryDefinition('one') - ->setImplement(Bad4::class) - ->getResultDefinition() - ->setFactory(Bad3::class); + ->setImplement(Bad4::class); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one' (type of Bad4): Unused parameter \$baz when implementing method Bad4::create(), did you mean \$bar?"); @@ -330,15 +313,13 @@ class Bad5 interface Bad6 { - public function create($baz); + public function create($baz): Bad5; } Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addFactoryDefinition('one') - ->setImplement(Bad6::class) - ->getResultDefinition() - ->setFactory(Bad5::class); + ->setImplement(Bad6::class); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one' (type of Bad6): Unused parameter \$baz when implementing method Bad6::create()."); @@ -346,7 +327,7 @@ Assert::exception(function () { interface Bad7 { - public function get(); + public function get(): stdClass; } Assert::exception(function () { diff --git a/tests/DI/Compiler.generatedFactory.scalarParameters.phpt b/tests/DI/Compiler.generatedFactory.scalarParameters.phpt index be92ac892..3cb72ff7f 100644 --- a/tests/DI/Compiler.generatedFactory.scalarParameters.phpt +++ b/tests/DI/Compiler.generatedFactory.scalarParameters.phpt @@ -15,8 +15,7 @@ require __DIR__ . '/../bootstrap.php'; interface IArticleFactory { - /** @return Article */ - public function create(string $title); + public function create(string $title): Article; } class Article diff --git a/tests/DI/ContainerBuilder.accessor.phpt b/tests/DI/ContainerBuilder.accessor.phpt index 940538e26..6333ba56d 100644 --- a/tests/DI/ContainerBuilder.accessor.phpt +++ b/tests/DI/ContainerBuilder.accessor.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/../bootstrap.php'; interface StdClassAccessor { - public function get(); + public function get(): stdClass; } interface AnnotatedAccessor @@ -48,8 +48,8 @@ $builder->addAccessorDefinition('one') ->setImplement(StdClassAccessor::class) ->setReference(stdClass::class); -$builder->addAccessorDefinition('two') - ->setImplement(AnnotatedAccessor::class); +@$builder->addAccessorDefinition('two') + ->setImplement(AnnotatedAccessor::class); // missing type triggers warning $builder->addAccessorDefinition('three') ->setImplement(StdClassAccessor::class) diff --git a/tests/DI/ContainerBuilder.aliases.phpt b/tests/DI/ContainerBuilder.aliases.phpt index 85c7e4e7b..d2bf878b2 100644 --- a/tests/DI/ContainerBuilder.aliases.phpt +++ b/tests/DI/ContainerBuilder.aliases.phpt @@ -19,12 +19,12 @@ class Service interface ServiceFactory { - public function create(); + public function create(): Service; } interface ServiceFactory2 { - public function create(); + public function create(): Service; } $builder = new DI\ContainerBuilder; @@ -39,13 +39,13 @@ $builder->addFactoryDefinition('aliasedFactory') ->setImplement(ServiceFactory::class) ->setAutowired(false) ->getResultDefinition() - ->setFactory('@serviceFactory'); + ->setFactory('@service'); $builder->addFactoryDefinition('aliasedFactoryViaClass') ->setImplement(ServiceFactory::class) ->setAutowired(false) ->getResultDefinition() - ->setFactory('@\ServiceFactory'); + ->setFactory('@\Service'); $builder->addDefinition('aliasedService') ->setFactory('@service'); diff --git a/tests/DI/ContainerBuilder.aliases2.phpt b/tests/DI/ContainerBuilder.aliases2.phpt index 4833db445..b4ed8db61 100644 --- a/tests/DI/ContainerBuilder.aliases2.phpt +++ b/tests/DI/ContainerBuilder.aliases2.phpt @@ -19,12 +19,12 @@ class Service interface ServiceFactory { - public function create(); + public function create(): Service; } interface ServiceFactory2 { - public function create(); + public function create(): Service; } $builder = new DI\ContainerBuilder; diff --git a/tests/DI/ContainerBuilder.autowiring.implement.phpt b/tests/DI/ContainerBuilder.autowiring.implement.phpt index 92c82783f..6c9ac20d9 100644 --- a/tests/DI/ContainerBuilder.autowiring.implement.phpt +++ b/tests/DI/ContainerBuilder.autowiring.implement.phpt @@ -15,8 +15,7 @@ require __DIR__ . '/../bootstrap.php'; interface ITestFactory { - /** @return Test */ - public function create(); + public function create(): Test; } class Foo diff --git a/tests/DI/ContainerBuilder.create.error.phpt b/tests/DI/ContainerBuilder.create.error.phpt index b4d6381da..ad56b1fca 100644 --- a/tests/DI/ContainerBuilder.create.error.phpt +++ b/tests/DI/ContainerBuilder.create.error.phpt @@ -73,8 +73,8 @@ interface Bad4 Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addFactoryDefinition('one') - ->setImplement(Bad4::class); + @$builder->addFactoryDefinition('one') + ->setImplement(Bad4::class); // missing type triggers warning $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one' (type of Bad4): Return type of Bad4::create() is not declared."); diff --git a/tests/DI/ContainerBuilder.factory.arguments.phpt b/tests/DI/ContainerBuilder.factory.arguments.phpt index 9af2779e3..8967dd02b 100644 --- a/tests/DI/ContainerBuilder.factory.arguments.phpt +++ b/tests/DI/ContainerBuilder.factory.arguments.phpt @@ -26,8 +26,7 @@ class Foo interface FooFactory { - /** @return Foo */ - public function create(); + public function create(): Foo; } diff --git a/tests/DI/ContainerBuilder.factory.phpt b/tests/DI/ContainerBuilder.factory.phpt index 501c4a6b0..cb31f1c47 100644 --- a/tests/DI/ContainerBuilder.factory.phpt +++ b/tests/DI/ContainerBuilder.factory.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/../bootstrap.php'; interface StdClassFactory { - public function create(); + public function create(): stdClass; } interface AnnotatedFactory @@ -38,8 +38,8 @@ $builder->addFactoryDefinition('one') ->getResultDefinition() ->setFactory(stdClass::class); -$builder->addFactoryDefinition('two') - ->setImplement(AnnotatedFactory::class); +@$builder->addFactoryDefinition('two') + ->setImplement(AnnotatedFactory::class); // missing type triggers warning $builder->addDefinition('three') ->setType(FactoryReceiver::class); diff --git a/tests/DI/ContainerBuilder.factory.resolveClass.phpt b/tests/DI/ContainerBuilder.factory.resolveClass.phpt index af17c05b5..efaf5101f 100644 --- a/tests/DI/ContainerBuilder.factory.resolveClass.phpt +++ b/tests/DI/ContainerBuilder.factory.resolveClass.phpt @@ -12,15 +12,13 @@ namespace A class Factory { - /** @return Foo */ - public function createFoo() + public function createFoo(): Foo { return new Foo; } - /** @return Bar */ - public function createBar() + public function createBar(): Bar { return new Bar; } @@ -45,26 +43,7 @@ namespace C { class SelfFactory { - /** @return self */ - public static function create() - { - return new self; - } - } - - class ThisFactory - { - /** @return $this */ - public static function create() - { - return new self; - } - } - - class StaticFactory - { - /** @return static */ - public static function create() + public static function create(): self { return new self; } @@ -82,7 +61,7 @@ namespace interface StdClassFactory { - public function create(); + public function create(): stdClass; } @@ -96,7 +75,7 @@ namespace $builder->addFactoryDefinition('two') ->setImplement(StdClassFactory::class) ->getResultDefinition() - ->setFactory('@one'); + ->setFactory('@eight'); $builder->addFactoryDefinition('three') ->setImplement(StdClassFactory::class) @@ -117,10 +96,7 @@ namespace ->setFactory('C\SelfFactory::create'); $builder->addDefinition('eight') - ->setFactory('C\ThisFactory::create'); - - $builder->addDefinition('nine') - ->setFactory('C\StaticFactory::create'); + ->setFactory('stdClass'); $container = createContainer($builder); @@ -128,7 +104,7 @@ namespace Assert::type(StdClassFactory::class, $container->getService('one')); Assert::type(StdClassFactory::class, $container->getService('two')); - Assert::type(StdClassFactory::class, $container->getService('two')->create()); + Assert::type(stdClass::class, $container->getService('two')->create()); Assert::notSame($container->getService('two')->create(), $container->getService('two')->create()); Assert::type(StdClassFactory::class, $container->getService('three')); @@ -139,6 +115,4 @@ namespace Assert::type(B\Bar::class, $container->getByType(B\Bar::class)); Assert::type(C\SelfFactory::class, $container->getByType(C\SelfFactory::class)); - Assert::type(C\ThisFactory::class, $container->getByType(C\ThisFactory::class)); - Assert::type(C\StaticFactory::class, $container->getByType(C\StaticFactory::class)); } diff --git a/tests/DI/DecoratorExtension.factories.accessor.phpt b/tests/DI/DecoratorExtension.factories.accessor.phpt index 35db040c6..9c5ceaeee 100644 --- a/tests/DI/DecoratorExtension.factories.accessor.phpt +++ b/tests/DI/DecoratorExtension.factories.accessor.phpt @@ -14,10 +14,7 @@ require __DIR__ . '/../bootstrap.php'; interface FooAccessor { - /** - * @return Foo - */ - public function get(); + public function get(): Foo; } class Foo diff --git a/tests/DI/DecoratorExtension.factories.phpt b/tests/DI/DecoratorExtension.factories.phpt index 7823aa89f..56c8a2c1a 100644 --- a/tests/DI/DecoratorExtension.factories.phpt +++ b/tests/DI/DecoratorExtension.factories.phpt @@ -14,10 +14,7 @@ require __DIR__ . '/../bootstrap.php'; interface FooFactory { - /** - * @return Foo - */ - public function create(); + public function create(): Foo; } class Foo diff --git a/tests/DI/Definitions.AccessorDefinition.api.phpt b/tests/DI/Definitions.AccessorDefinition.api.phpt index 7b6df72bf..ff3a9fbf1 100644 --- a/tests/DI/Definitions.AccessorDefinition.api.phpt +++ b/tests/DI/Definitions.AccessorDefinition.api.phpt @@ -42,7 +42,7 @@ interface Bad5 interface Good1 { - public function get(); + public function get(): stdClass; } @@ -96,7 +96,7 @@ Assert::exception(function () { Assert::noError(function () { $def = new AccessorDefinition; - $def->setImplement(Good1::class); + @$def->setImplement(Good1::class); // missing type triggers warning Assert::same(Good1::class, $def->getImplement()); Assert::same(Good1::class, $def->getType()); }); diff --git a/tests/DI/Definitions.AccessorDefinition.resolve.phpt b/tests/DI/Definitions.AccessorDefinition.resolve.phpt index c45c63e1c..5c7270a1f 100644 --- a/tests/DI/Definitions.AccessorDefinition.resolve.phpt +++ b/tests/DI/Definitions.AccessorDefinition.resolve.phpt @@ -13,12 +13,12 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -interface Good1 +interface Bad1 { public function get(); } -interface Good2 +interface Good1 { public function get(): stdClass; } @@ -33,11 +33,11 @@ Assert::exception(function () { Assert::exception(function () { $def = new AccessorDefinition; - $def->setImplement(Good1::class); + @$def->setImplement(Bad1::class); // missing type triggers warning $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); $resolver->completeDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Service of type Good1: Return type of Good1::get() is not declared.'); +}, Nette\DI\ServiceCreationException::class, 'Service of type Bad1: Return type of Bad1::get() is not declared.'); Assert::noError(function () { @@ -52,7 +52,7 @@ Assert::noError(function () { Assert::noError(function () { $def = new AccessorDefinition; - $def->setImplement(Good2::class); + $def->setImplement(Good1::class); $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); @@ -61,9 +61,9 @@ Assert::noError(function () { Assert::exception(function () { $def = new AccessorDefinition; - $def->setImplement(Good2::class); + $def->setImplement(Good1::class); $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); $resolver->completeDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Service of type Good2: Service of type stdClass not found. Did you add it to configuration file?'); +}, Nette\DI\ServiceCreationException::class, 'Service of type Good1: Service of type stdClass not found. Did you add it to configuration file?'); diff --git a/tests/DI/Definitions.FactoryDefinition.api.phpt b/tests/DI/Definitions.FactoryDefinition.api.phpt index 4b8e54275..522078a23 100644 --- a/tests/DI/Definitions.FactoryDefinition.api.phpt +++ b/tests/DI/Definitions.FactoryDefinition.api.phpt @@ -36,7 +36,7 @@ interface Bad4 interface Good1 { - public function create(); + public function create(): stdClass; } @@ -84,7 +84,7 @@ Assert::exception(function () { Assert::noError(function () { $def = new FactoryDefinition; - $def->setImplement(Good1::class); + @$def->setImplement(Good1::class); // missing type triggers warning Assert::same(Good1::class, $def->getImplement()); Assert::same(Good1::class, $def->getType()); }); diff --git a/tests/DI/Definitions.FactoryDefinition.resolve.phpt b/tests/DI/Definitions.FactoryDefinition.resolve.phpt index 582023168..ea31b381c 100644 --- a/tests/DI/Definitions.FactoryDefinition.resolve.phpt +++ b/tests/DI/Definitions.FactoryDefinition.resolve.phpt @@ -13,12 +13,12 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -interface Good1 +interface Bad1 { public function create(); } -interface Good2 +interface Good1 { public function create(): stdClass; } @@ -33,10 +33,10 @@ Assert::exception(function () { Assert::exception(function () { $def = new FactoryDefinition; - $def->setImplement(Good1::class); + @$def->setImplement(Bad1::class); // missing type triggers warning $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Service of type Good1: Return type of Good1::create() is not declared.'); +}, Nette\DI\ServiceCreationException::class, 'Service of type Bad1: Return type of Bad1::create() is not declared.'); Assert::noError(function () { @@ -52,7 +52,7 @@ Assert::noError(function () { Assert::noError(function () { $def = new FactoryDefinition; - $def->setImplement(Good2::class); + $def->setImplement(Good1::class); $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); @@ -62,7 +62,7 @@ Assert::noError(function () { Assert::noError(function () { $def = new FactoryDefinition; - $def->setImplement(Good2::class); + $def->setImplement(Good1::class); $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); @@ -72,9 +72,9 @@ Assert::noError(function () { Assert::exception(function () { $def = new FactoryDefinition; - $def->setImplement(Good2::class); + $def->setImplement(Good1::class); $def->getResultDefinition()->setType(DateTime::class); $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Service of type Good2: Factory for stdClass cannot create incompatible DateTime type.'); +}, Nette\DI\ServiceCreationException::class, 'Service of type Good1: Factory for stdClass cannot create incompatible DateTime type.'); diff --git a/tests/DI/Definitions.LocatorDefinition.api.phpt b/tests/DI/Definitions.LocatorDefinition.api.phpt index 84dbac9fa..25068cf2f 100644 --- a/tests/DI/Definitions.LocatorDefinition.api.phpt +++ b/tests/DI/Definitions.LocatorDefinition.api.phpt @@ -20,46 +20,46 @@ interface Bad1 interface Bad2 { - public function create(); + public function create(): stdClass; } interface Bad3 { - public function get(); + public function get(): stdClass; } interface Bad4 { - public function get($name); + public function get($name): stdClass; - public function foo(); + public function foo(): stdClass; } interface Bad5 { - public static function get($name); + public static function get($name): stdClass; } interface Bad6 { - public function get($arg, $arg2); + public function get($arg, $arg2): stdClass; } interface Good1 { - public function get($name); + public function get($name): stdClass; } interface Good2 { - public function create($name); + public function create($name): stdClass; } interface Good3 { - public function createA(); + public function createA(): stdClass; - public function getB(); + public function getB(): stdClass; } From 91ae50a2980219592a3f026f84bf170b74f36afc Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 14 Dec 2021 19:28:50 +0100 Subject: [PATCH 09/44] annotations @return are deprecated --- src/DI/Resolver.php | 6 +++++- tests/DI/Compiler.extensionOverride.phpt | 6 ++---- tests/DI/Compiler.services.autowiring.phpt | 3 +-- tests/DI/Compiler.services.create.phpt | 6 ++---- tests/DI/ContainerBuilder.autowiring.chaining.phpt | 6 ++---- tests/DI/ContainerBuilder.basic.phpt | 3 +-- tests/DI/ContainerBuilder.basic2.phpt | 3 +-- tests/DI/ContainerBuilder.basic3.phpt | 3 +-- tests/DI/ContainerBuilder.basic4.phpt | 9 +++------ tests/DI/ContainerBuilder.byClass.phpt | 6 ++---- tests/DI/ContainerBuilder.create.rich.phpt | 6 ++---- tests/DI/ContainerBuilder.resolveTypes.phpt | 12 ++++++------ 12 files changed, 28 insertions(+), 41 deletions(-) diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 641d1712a..bd1590bfd 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -129,8 +129,12 @@ public function resolveEntityType(Statement $statement): ?string $this->addDependency($reflection); - $type = Nette\Utils\Type::fromReflection($reflection) ?? Helpers::getReturnTypeAnnotation($reflection); + $type = Nette\Utils\Type::fromReflection($reflection) ?? ($annotation = Helpers::getReturnTypeAnnotation($reflection)); if ($type && !in_array((string) $type, ['object', 'mixed'], true)) { + if (isset($annotation)) { + trigger_error('Annotation @return should be replaced with native return type at ' . Callback::toString($entity), E_USER_DEPRECATED); + } + return Helpers::ensureClassType($type, sprintf('return type of %s()', Callback::toString($entity))); } diff --git a/tests/DI/Compiler.extensionOverride.phpt b/tests/DI/Compiler.extensionOverride.phpt index 6a9a38b73..2adb5619f 100644 --- a/tests/DI/Compiler.extensionOverride.phpt +++ b/tests/DI/Compiler.extensionOverride.phpt @@ -15,8 +15,7 @@ require __DIR__ . '/../bootstrap.php'; class Factory { - /** @return Lorem */ - public static function createLorem(...$args) + public static function createLorem(...$args): Lorem { return new Lorem(...$args); } @@ -25,8 +24,7 @@ class Factory class IpsumFactory { - /** @return Ipsum */ - public static function create(...$args) + public static function create(...$args): Ipsum { return new Ipsum(...$args); } diff --git a/tests/DI/Compiler.services.autowiring.phpt b/tests/DI/Compiler.services.autowiring.phpt index 57a5388f0..c49ce65d9 100644 --- a/tests/DI/Compiler.services.autowiring.phpt +++ b/tests/DI/Compiler.services.autowiring.phpt @@ -15,8 +15,7 @@ require __DIR__ . '/../bootstrap.php'; class Factory { - /** @return Model auto-wiring using annotation */ - public static function createModel() + public static function createModel(): Model { return new Model; } diff --git a/tests/DI/Compiler.services.create.phpt b/tests/DI/Compiler.services.create.phpt index 26a77e850..e9140ceea 100644 --- a/tests/DI/Compiler.services.create.phpt +++ b/tests/DI/Compiler.services.create.phpt @@ -15,8 +15,7 @@ require __DIR__ . '/../bootstrap.php'; class Factory { - /** @return Lorem */ - public static function createLorem($arg) + public static function createLorem($arg): Lorem { return new Lorem(__METHOD__ . ' ' . implode(' ', func_get_args())); } @@ -31,8 +30,7 @@ class Lorem } - /** @return Lorem */ - public function foo(...$args) + public function foo(...$args): self { $this->foo = $args; return $this; diff --git a/tests/DI/ContainerBuilder.autowiring.chaining.phpt b/tests/DI/ContainerBuilder.autowiring.chaining.phpt index b4bb276b4..a8783d4ba 100644 --- a/tests/DI/ContainerBuilder.autowiring.chaining.phpt +++ b/tests/DI/ContainerBuilder.autowiring.chaining.phpt @@ -15,8 +15,7 @@ require __DIR__ . '/../bootstrap.php'; class Foo { - /** @return Bar */ - public static function create(Test $test) + public static function create(Test $test): Bar { return new Bar; } @@ -29,8 +28,7 @@ class Foo class Bar { - /** @return Baz */ - public function create(Test $test) + public function create(Test $test): Baz { return new Baz; } diff --git a/tests/DI/ContainerBuilder.basic.phpt b/tests/DI/ContainerBuilder.basic.phpt index 6d761791a..0ec054bab 100644 --- a/tests/DI/ContainerBuilder.basic.phpt +++ b/tests/DI/ContainerBuilder.basic.phpt @@ -19,8 +19,7 @@ class Service public $methods; - /** @return Service */ - public static function create(?DI\Container $container = null) + public static function create(?DI\Container $container = null): self { return new self(array_slice(func_get_args(), 1)); } diff --git a/tests/DI/ContainerBuilder.basic2.phpt b/tests/DI/ContainerBuilder.basic2.phpt index 087f8921b..1bda434e5 100644 --- a/tests/DI/ContainerBuilder.basic2.phpt +++ b/tests/DI/ContainerBuilder.basic2.phpt @@ -20,8 +20,7 @@ class Factory } - /** @return Factory */ - public static function create() + public static function create(): self { return new self; } diff --git a/tests/DI/ContainerBuilder.basic3.phpt b/tests/DI/ContainerBuilder.basic3.phpt index 4bbcd7784..e124ec100 100644 --- a/tests/DI/ContainerBuilder.basic3.phpt +++ b/tests/DI/ContainerBuilder.basic3.phpt @@ -13,8 +13,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -/** @return stdClass */ -function create() +function create(): stdClass { return new stdClass; } diff --git a/tests/DI/ContainerBuilder.basic4.phpt b/tests/DI/ContainerBuilder.basic4.phpt index 6fa263fc5..48663dcb2 100644 --- a/tests/DI/ContainerBuilder.basic4.phpt +++ b/tests/DI/ContainerBuilder.basic4.phpt @@ -9,8 +9,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -/** @return ClassA */ -function func() +function func(): ClassA { return new ClassA; } @@ -18,8 +17,7 @@ function func() class ClassA { - /** @return ClassB */ - public function funcA(stdClass $arg) + public function funcA(stdClass $arg): ClassB { return new ClassB; } @@ -27,8 +25,7 @@ class ClassA class ClassB { - /** @return ClassC */ - public function funcB(stdClass $arg) + public function funcB(stdClass $arg): ClassC { return new ClassC; } diff --git a/tests/DI/ContainerBuilder.byClass.phpt b/tests/DI/ContainerBuilder.byClass.phpt index 1b4c98d4d..b73309432 100644 --- a/tests/DI/ContainerBuilder.byClass.phpt +++ b/tests/DI/ContainerBuilder.byClass.phpt @@ -35,8 +35,7 @@ class AnnotatedFactory public $methods; - /** @return stdClass */ - public function create() + public function create(): stdClass { $this->methods[] = [__FUNCTION__, func_get_args()]; return new stdClass; @@ -57,8 +56,7 @@ class UninstantiableFactory } - /** @return stdClass */ - public function create() + public function create(): stdClass { } } diff --git a/tests/DI/ContainerBuilder.create.rich.phpt b/tests/DI/ContainerBuilder.create.rich.phpt index b26fdb0af..435004119 100644 --- a/tests/DI/ContainerBuilder.create.rich.phpt +++ b/tests/DI/ContainerBuilder.create.rich.phpt @@ -16,8 +16,7 @@ require __DIR__ . '/../bootstrap.php'; class Factory { - /** @return Obj */ - public function create() + public function create(): Obj { return new Obj; } @@ -31,8 +30,7 @@ class Factory class Obj { - /** @return Obj */ - public function foo(...$args) + public function foo(...$args): self { $this->args[] = $args; return $this; diff --git a/tests/DI/ContainerBuilder.resolveTypes.phpt b/tests/DI/ContainerBuilder.resolveTypes.phpt index 602cd36c6..4c11a8387 100644 --- a/tests/DI/ContainerBuilder.resolveTypes.phpt +++ b/tests/DI/ContainerBuilder.resolveTypes.phpt @@ -97,7 +97,7 @@ Assert::noError(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setFactory([Factory::class, 'createClassPhpDoc']); - $container = createContainer($builder); + $container = @createContainer($builder); // @return is deprecated }); Assert::noError(function () { @@ -111,7 +111,7 @@ Assert::noError(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setFactory([Factory::class, 'createNullableClassPhpDoc']); - $container = createContainer($builder); + $container = @createContainer($builder); // @return is deprecated }); Assert::exception(function () { @@ -125,7 +125,7 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setFactory([Factory::class, 'createScalarPhpDoc']); - $container = createContainer($builder); + $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createScalarPhpDoc() is not expected to be nullable/union/intersection/built-in, 'array' given."); Assert::exception(function () { @@ -139,7 +139,7 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setFactory([Factory::class, 'createObjectPhpDoc']); - $container = createContainer($builder); + $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { @@ -160,7 +160,7 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setFactory([Factory::class, 'createMixedPhpDoc']); - $container = createContainer($builder); + $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { @@ -174,6 +174,6 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setFactory([Factory::class, 'createGeneric']); - $container = createContainer($builder); + $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Class 'T' not found. Check the return type of Factory::createGeneric()."); From 9bc2d43f38be6aeff90b11496649fa3ab4af4c94 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 14 Dec 2021 05:44:23 +0100 Subject: [PATCH 10/44] Resolver: non-optional autowired parameters trigger notice that value is required [Closes #271] --- src/DI/Resolver.php | 11 ++++++++++ tests/DI/Resolver.autowireArguments.80.phpt | 7 +++---- .../DI/Resolver.autowireArguments.errors.phpt | 20 +++++++++++++++++++ tests/DI/Resolver.autowireArguments.phpt | 20 ------------------- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index bd1590bfd..36f73cd6c 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -586,12 +586,23 @@ public static function autowireArguments( $useName = true; } else { $res[$num] = null; + trigger_error(sprintf( + 'The parameter %s should have a declared value in the configuration.', + Reflection::toString($param) + ), E_USER_DEPRECATED); } } else { $res[$num] = $param->isDefaultValueAvailable() ? Reflection::getParameterDefaultValue($param) : null; + + if (!$param->isOptional()) { + trigger_error(sprintf( + 'The parameter %s should have a declared value in the configuration.', + Reflection::toString($param) + ), E_USER_DEPRECATED); + } } if (PHP_VERSION_ID < 80000) { diff --git a/tests/DI/Resolver.autowireArguments.80.phpt b/tests/DI/Resolver.autowireArguments.80.phpt index 4dd145455..c6e35bf3c 100644 --- a/tests/DI/Resolver.autowireArguments.80.phpt +++ b/tests/DI/Resolver.autowireArguments.80.phpt @@ -28,14 +28,13 @@ Assert::exception(function () { }, Nette\InvalidStateException::class, 'Parameter $x in {closure}() has union type and no default value, so its value must be specified.'); // nullable union -Assert::same( - [null], +Assert::error(function () { Resolver::autowireArguments( new ReflectionFunction(function (stdClass|Test|null $x) {}), [], function () {} - ), -); + ); +}, E_USER_DEPRECATED, 'The parameter $x in {closure}() should have a declared value in the configuration.'); // optional union Assert::same( diff --git a/tests/DI/Resolver.autowireArguments.errors.phpt b/tests/DI/Resolver.autowireArguments.errors.phpt index ba801b0d3..45805f402 100644 --- a/tests/DI/Resolver.autowireArguments.errors.phpt +++ b/tests/DI/Resolver.autowireArguments.errors.phpt @@ -53,6 +53,26 @@ Assert::exception(function () { }, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}() has no class type or default value, so its value must be specified.'); +// nullable unknown class +Assert::error(function () { + Resolver::autowireArguments( + new ReflectionFunction(function (?stdClass $arg) {}), + [], + function ($type) { return $type === Test::class ? new Test : null; } + ); +}, E_USER_DEPRECATED, 'The parameter $arg in {closure}() should have a declared value in the configuration.'); + + +// nullable scalar +Assert::error(function () { + Resolver::autowireArguments( + new ReflectionFunction(function (?int $arg) {}), + [], + function ($type) { return $type === Test::class ? new Test : null; } + ); +}, E_USER_DEPRECATED, 'The parameter $arg in {closure}() should have a declared value in the configuration.'); + + // bad variadics (this is actually what PHP allows) Assert::exception(function () { Resolver::autowireArguments( diff --git a/tests/DI/Resolver.autowireArguments.phpt b/tests/DI/Resolver.autowireArguments.phpt index 9735a165c..40b1fb93f 100644 --- a/tests/DI/Resolver.autowireArguments.phpt +++ b/tests/DI/Resolver.autowireArguments.phpt @@ -38,26 +38,6 @@ Assert::equal( ) ); -// nullable unknown class -Assert::equal( - [null], - Resolver::autowireArguments( - new ReflectionFunction(function (?stdClass $arg) {}), - [], - function ($type) { return $type === Test::class ? new Test : null; } - ) -); - -// nullable scalar -Assert::equal( - [null], - Resolver::autowireArguments( - new ReflectionFunction(function (?int $arg) {}), - [], - function ($type) { return $type === Test::class ? new Test : null; } - ) -); - // nullable optional class Assert::equal( [new Test], From 2d0a00e78627602f8a071cab11276f499f63c4be Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 27 Sep 2021 01:34:41 +0200 Subject: [PATCH 11/44] DefinitionSchema moved to Nette\DI\Extensions --- src/DI/{Config => Extensions}/DefinitionSchema.php | 3 ++- src/DI/Extensions/ServicesExtension.php | 2 +- tests/DI/DefinitionSchema.normalize.phpt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) rename src/DI/{Config => Extensions}/DefinitionSchema.php (99%) diff --git a/src/DI/Config/DefinitionSchema.php b/src/DI/Extensions/DefinitionSchema.php similarity index 99% rename from src/DI/Config/DefinitionSchema.php rename to src/DI/Extensions/DefinitionSchema.php index 62b57f179..bb38318da 100644 --- a/src/DI/Config/DefinitionSchema.php +++ b/src/DI/Extensions/DefinitionSchema.php @@ -7,9 +7,10 @@ declare(strict_types=1); -namespace Nette\DI\Config; +namespace Nette\DI\Extensions; use Nette; +use Nette\DI\Config\Helpers; use Nette\DI\Definitions; use Nette\DI\Definitions\Statement; use Nette\Schema\Context; diff --git a/src/DI/Extensions/ServicesExtension.php b/src/DI/Extensions/ServicesExtension.php index 02e83f1fd..7cbeb21e2 100644 --- a/src/DI/Extensions/ServicesExtension.php +++ b/src/DI/Extensions/ServicesExtension.php @@ -24,7 +24,7 @@ final class ServicesExtension extends Nette\DI\CompilerExtension public function getConfigSchema(): Nette\Schema\Schema { - return Nette\Schema\Expect::arrayOf(new Nette\DI\Config\DefinitionSchema($this->getContainerBuilder())); + return Nette\Schema\Expect::arrayOf(new DefinitionSchema($this->getContainerBuilder())); } diff --git a/tests/DI/DefinitionSchema.normalize.phpt b/tests/DI/DefinitionSchema.normalize.phpt index 733cca6a2..f759a3c21 100644 --- a/tests/DI/DefinitionSchema.normalize.phpt +++ b/tests/DI/DefinitionSchema.normalize.phpt @@ -6,8 +6,8 @@ declare(strict_types=1); -use Nette\DI\Config\DefinitionSchema; use Nette\DI\Definitions\Statement; +use Nette\DI\Extensions\DefinitionSchema; use Tester\Assert; From 958dd58b5b23979320b4f344856072e24e482caa Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 28 Sep 2021 12:31:27 +0200 Subject: [PATCH 12/44] deprecated option 'parameters' used by generated factories --- src/DI/Definitions/FactoryDefinition.php | 19 ++++++++++++++++++- ...r.generatedFactory.nullableParameters.phpt | 3 ++- ...Compiler.generatedFactory.returnTypes.phpt | 3 ++- ...ler.generatedFactory.scalarParameters.phpt | 3 ++- tests/DI/ContainerBuilder.factory.params.phpt | 4 ++-- .../DI/Definitions.FactoryDefinition.api.phpt | 2 +- 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index d8249da4e..c6292264a 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -95,14 +95,31 @@ public function getResultDefinition(): Definition } - /** @return static */ + /** @deprecated */ public function setParameters(array $params) { + if ($params) { + $old = $new = []; + foreach ($params as $k => $v) { + $tmp = explode(' ', is_int($k) ? $v : $k); + $old[] = '%' . end($tmp) . '%'; + $new[] = '$' . end($tmp); + } + + trigger_error(sprintf( + "Service '%s': Option 'parameters' is deprecated and should be removed. The %s should be replaced with %s in configuration.", + $this->getName(), + implode(', ', $old), + implode(', ', $new) + ), E_USER_DEPRECATED); + } + $this->parameters = $params; return $this; } + /** @deprecated */ public function getParameters(): array { return $this->parameters; diff --git a/tests/DI/Compiler.generatedFactory.nullableParameters.phpt b/tests/DI/Compiler.generatedFactory.nullableParameters.phpt index 43ca87089..929af4eea 100644 --- a/tests/DI/Compiler.generatedFactory.nullableParameters.phpt +++ b/tests/DI/Compiler.generatedFactory.nullableParameters.phpt @@ -40,7 +40,8 @@ class Article } $compiler = new DI\Compiler; -$container = createContainer($compiler, ' +// parameters are deprecated +$container = @createContainer($compiler, ' services: article: diff --git a/tests/DI/Compiler.generatedFactory.returnTypes.phpt b/tests/DI/Compiler.generatedFactory.returnTypes.phpt index 2b05d9257..15a4d097c 100644 --- a/tests/DI/Compiler.generatedFactory.returnTypes.phpt +++ b/tests/DI/Compiler.generatedFactory.returnTypes.phpt @@ -34,7 +34,8 @@ class FooArticle extends Article } $compiler = new DI\Compiler; -$container = createContainer($compiler, ' +// parameters are deprecated +$container = @createContainer($compiler, ' services: article: factory: Article(%title%) diff --git a/tests/DI/Compiler.generatedFactory.scalarParameters.phpt b/tests/DI/Compiler.generatedFactory.scalarParameters.phpt index 3cb72ff7f..68666489d 100644 --- a/tests/DI/Compiler.generatedFactory.scalarParameters.phpt +++ b/tests/DI/Compiler.generatedFactory.scalarParameters.phpt @@ -30,7 +30,8 @@ class Article } $compiler = new DI\Compiler; -$container = createContainer($compiler, ' +// parameters are deprecated +$container = @createContainer($compiler, ' services: article: factory: Article(%title%) diff --git a/tests/DI/ContainerBuilder.factory.params.phpt b/tests/DI/ContainerBuilder.factory.params.phpt index 2fbe0a464..a5e1d25e2 100644 --- a/tests/DI/ContainerBuilder.factory.params.phpt +++ b/tests/DI/ContainerBuilder.factory.params.phpt @@ -26,8 +26,8 @@ $builder->addFactoryDefinition('one') ->setFactory(stdClass::class) ->addSetup('$a', [$builder::literal('$a')]); -$builder->addFactoryDefinition('two') - ->setParameters(['stdClass foo', 'array bar', 'foobar' => null]) +@$builder->addFactoryDefinition('two') + ->setParameters(['stdClass foo', 'array bar', 'foobar' => null]) // parameters is deprecated ->setImplement(StdClassFactory::class) ->getResultDefinition() ->setFactory(stdClass::class) diff --git a/tests/DI/Definitions.FactoryDefinition.api.phpt b/tests/DI/Definitions.FactoryDefinition.api.phpt index 522078a23..526aba439 100644 --- a/tests/DI/Definitions.FactoryDefinition.api.phpt +++ b/tests/DI/Definitions.FactoryDefinition.api.phpt @@ -94,7 +94,7 @@ test('', function () { $def = new FactoryDefinition; $def->setImplement(Good1::class); - $def->setParameters(['a' => 1]); + @$def->setParameters(['a' => 1]); // parameters are deprecated Assert::same(['a' => 1], $def->getParameters()); }); From e59148670ddc61c9de4a319a841c531db91e210a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 19 Jan 2022 11:50:06 +0100 Subject: [PATCH 13/44] option 'create' is used primary internally --- src/DI/Extensions/DefinitionSchema.php | 22 +++++++++++----------- src/DI/Extensions/ServicesExtension.php | 10 +++++----- src/DI/Resolver.php | 2 +- tests/DI/Compiler.loadConfig.include.phpt | 2 +- tests/DI/DefinitionSchema.normalize.phpt | 14 +++++++------- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/DI/Extensions/DefinitionSchema.php b/src/DI/Extensions/DefinitionSchema.php index bb38318da..1198598d5 100644 --- a/src/DI/Extensions/DefinitionSchema.php +++ b/src/DI/Extensions/DefinitionSchema.php @@ -88,7 +88,7 @@ public function normalize($def, Context $context) if (array_keys($def->arguments) === ['tagged']) { $res += $def->arguments; } elseif (array_keys($def->arguments) === [0]) { - $res['factory'] = $def->arguments[0]; + $res['create'] = $def->arguments[0]; } elseif ($def->arguments) { $res['references'] = $def->arguments; } @@ -96,23 +96,23 @@ public function normalize($def, Context $context) return $res; } elseif (!is_array($def) || isset($def[0], $def[1])) { - return ['factory' => $def]; + return ['create' => $def]; } elseif (is_array($def)) { - if (isset($def['create']) && !isset($def['factory'])) { - $def['factory'] = $def['create']; - unset($def['create']); + // back compatibility + if (isset($def['factory']) && !isset($def['create'])) { + $def['create'] = $def['factory']; + unset($def['factory']); } - // back compatibility if ( isset($def['class']) && !isset($def['type']) - && !isset($def['factory']) + && !isset($def['create']) && !isset($def['dynamic']) && !isset($def['imported']) ) { - $def['factory'] = $def['class']; + $def['create'] = $def['class']; unset($def['class']); } @@ -209,7 +209,7 @@ private static function getServiceSchema(): Schema { return Expect::structure([ 'type' => Expect::type('string'), - 'factory' => Expect::type('callable|Nette\DI\Definitions\Statement'), + 'create' => Expect::type('callable|Nette\DI\Definitions\Statement'), 'arguments' => Expect::array(), 'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'), 'inject' => Expect::bool(), @@ -226,7 +226,7 @@ private static function getAccessorSchema(): Schema return Expect::structure([ 'type' => Expect::string(), 'implement' => Expect::string(), - 'factory' => Expect::type('callable|Nette\DI\Definitions\Statement'), + 'create' => Expect::type('callable|Nette\DI\Definitions\Statement'), 'autowired' => Expect::type('bool|string|array'), 'tags' => Expect::array(), ]); @@ -237,7 +237,7 @@ private static function getFactorySchema(): Schema { return Expect::structure([ 'type' => Expect::string(), - 'factory' => Expect::type('callable|Nette\DI\Definitions\Statement'), + 'create' => Expect::type('callable|Nette\DI\Definitions\Statement'), 'implement' => Expect::string(), 'arguments' => Expect::array(), 'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'), diff --git a/src/DI/Extensions/ServicesExtension.php b/src/DI/Extensions/ServicesExtension.php index 7cbeb21e2..89af4b678 100644 --- a/src/DI/Extensions/ServicesExtension.php +++ b/src/DI/Extensions/ServicesExtension.php @@ -80,8 +80,8 @@ private function loadDefinition(?string $name, \stdClass $config): void */ private function updateServiceDefinition(Definitions\ServiceDefinition $definition, \stdClass $config): void { - if ($config->factory) { - $definition->setFactory(Helpers::filterArguments([$config->factory])[0]); + if ($config->create) { + $definition->setFactory(Helpers::filterArguments([$config->create])[0]); $definition->setType(null); } @@ -124,7 +124,7 @@ private function updateAccessorDefinition(Definitions\AccessorDefinition $defini $definition->setImplement($config->implement); } - if ($ref = $config->factory ?? $config->type ?? null) { + if ($ref = $config->create ?? $config->type ?? null) { $definition->setReference($ref); } } @@ -139,8 +139,8 @@ private function updateFactoryDefinition(Definitions\FactoryDefinition $definiti $definition->setAutowired(true); } - if ($config->factory) { - $resultDef->setFactory(Helpers::filterArguments([$config->factory])[0]); + if ($config->create) { + $resultDef->setFactory(Helpers::filterArguments([$config->create])[0]); } if ($config->type) { diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 36f73cd6c..0f3890d25 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -147,7 +147,7 @@ public function resolveEntityType(Statement $statement): ?string if (!class_exists($entity)) { throw new ServiceCreationException(sprintf( interface_exists($entity) - ? "Interface %s can not be used as 'factory', did you mean 'implement'?" + ? "Interface %s can not be used as 'create' or 'factory', did you mean 'implement'?" : "Class '%s' not found.", $entity )); diff --git a/tests/DI/Compiler.loadConfig.include.phpt b/tests/DI/Compiler.loadConfig.include.phpt index 4f3f78b1f..26d00f815 100644 --- a/tests/DI/Compiler.loadConfig.include.phpt +++ b/tests/DI/Compiler.loadConfig.include.phpt @@ -41,7 +41,7 @@ Assert::equal([ 'services' => [ 'a' => (object) [ 'type' => null, - 'factory' => stdClass::class, + 'create' => stdClass::class, 'arguments' => [], 'setup' => [], 'inject' => null, diff --git a/tests/DI/DefinitionSchema.normalize.phpt b/tests/DI/DefinitionSchema.normalize.phpt index f759a3c21..890072f83 100644 --- a/tests/DI/DefinitionSchema.normalize.phpt +++ b/tests/DI/DefinitionSchema.normalize.phpt @@ -26,17 +26,17 @@ Assert::with(DefinitionSchema::class, function () { Assert::same([], $schema->normalize(null, $context)); Assert::same([], $schema->normalize([], $context)); Assert::same([false], $schema->normalize(false, $context)); - Assert::same(['factory' => true], $schema->normalize(true, $context)); - Assert::same(['factory' => 'class'], $schema->normalize('class', $context)); + Assert::same(['create' => true], $schema->normalize(true, $context)); + Assert::same(['create' => 'class'], $schema->normalize('class', $context)); Assert::same(['implement' => Iface::class], $schema->normalize(Iface::class, $context)); - Assert::same(['factory' => ['class', 'method']], $schema->normalize(['class', 'method'], $context)); - Assert::same(['factory' => [Iface::class, 'method']], $schema->normalize([Iface::class, 'method'], $context)); + Assert::same(['create' => ['class', 'method']], $schema->normalize(['class', 'method'], $context)); + Assert::same(['create' => [Iface::class, 'method']], $schema->normalize([Iface::class, 'method'], $context)); $statement = new Statement(['class', 'method']); - Assert::same(['factory' => $statement], $schema->normalize($statement, $context)); + Assert::same(['create' => $statement], $schema->normalize($statement, $context)); $statement = new Statement(Iface::class, ['foo']); - Assert::same(['implement' => Iface::class, 'factory' => 'foo'], $schema->normalize($statement, $context)); + Assert::same(['implement' => Iface::class, 'create' => 'foo'], $schema->normalize($statement, $context)); $statement = new Statement(Iface::class, ['stdClass', 'stdClass']); Assert::same(['implement' => Iface::class, 'references' => ['stdClass', 'stdClass']], $schema->normalize($statement, $context)); @@ -45,7 +45,7 @@ Assert::with(DefinitionSchema::class, function () { Assert::same(['implement' => Iface::class, 'tagged' => 123], $schema->normalize($statement, $context)); // aliases - Assert::same(['factory' => 'val'], $schema->normalize(['class' => 'val'], $context)); + Assert::same(['create' => 'val'], $schema->normalize(['class' => 'val'], $context)); Assert::same(['imported' => 'val'], $schema->normalize(['dynamic' => 'val'], $context)); Assert::exception(function () use ($schema, $context) { From bbd0ddaab53b98e6d450d4d4e9bff8269021388f Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 15 Dec 2021 16:49:09 +0100 Subject: [PATCH 14/44] method setCreator() is used primary internally --- src/DI/Definitions/FactoryDefinition.php | 10 ++-- src/DI/Definitions/ServiceDefinition.php | 44 +++++++------- src/DI/Extensions/InjectExtension.php | 2 +- src/DI/Extensions/ServicesExtension.php | 10 ++-- tests/DI/Compiler.extensionOverride.phpt | 60 +++++++++---------- tests/DI/Compiler.generatedFactory.phpt | 4 +- ...erExtension.loadDefinitionsFromConfig.phpt | 6 +- tests/DI/ContainerBuilder.accessor.phpt | 4 +- tests/DI/ContainerBuilder.aliases.phpt | 16 ++--- tests/DI/ContainerBuilder.aliases2.phpt | 4 +- tests/DI/ContainerBuilder.basic.phpt | 14 ++--- tests/DI/ContainerBuilder.basic2.phpt | 2 +- tests/DI/ContainerBuilder.basic3.phpt | 2 +- tests/DI/ContainerBuilder.byClass.phpt | 12 ++-- tests/DI/ContainerBuilder.create.error.phpt | 26 ++++---- .../ContainerBuilder.create.resolveClass.phpt | 2 +- tests/DI/ContainerBuilder.create.rich.phpt | 4 +- tests/DI/ContainerBuilder.factory.params.phpt | 8 +-- tests/DI/ContainerBuilder.factory.phpt | 4 +- ...ContainerBuilder.factory.resolveClass.phpt | 14 ++--- tests/DI/ContainerBuilder.names.phpt | 6 +- tests/DI/ContainerBuilder.recursive.phpt | 4 +- .../ContainerBuilder.resolveTypes.php80.phpt | 2 +- tests/DI/ContainerBuilder.resolveTypes.phpt | 24 ++++---- tests/DI/ContainerBuilder.selfdependency.phpt | 2 +- tests/DI/Definitions.ServiceDefinition.phpt | 32 +++++----- 26 files changed, 161 insertions(+), 157 deletions(-) diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index c6292264a..d733c80ef 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -167,13 +167,13 @@ public function complete(Nette\DI\Resolver $resolver): void $this->completeParameters($resolver); } - $this->convertArguments($resultDef->getFactory()->arguments); + $this->convertArguments($resultDef->getCreator()->arguments); foreach ($resultDef->getSetup() as $setup) { $this->convertArguments($setup->arguments); } - if ($resultDef->getEntity() instanceof Reference && !$resultDef->getFactory()->arguments) { - $resultDef->setFactory([ // render as $container->createMethod() + if ($resultDef->getEntity() instanceof Reference && !$resultDef->getCreator()->arguments) { + $resultDef->setCreator([ // render as $container->createMethod() new Reference(Nette\DI\ContainerBuilder::THIS_CONTAINER), Nette\DI\Container::getMethodName($resultDef->getEntity()->getValue()), ]); @@ -191,7 +191,7 @@ private function completeParameters(Nette\DI\Resolver $resolver): void $ctorParams = []; if ( - ($class = $resolver->resolveEntityType($this->resultDefinition->getFactory())) + ($class = $resolver->resolveEntityType($this->resultDefinition->getCreator())) && ($ctor = (new \ReflectionClass($class))->getConstructor()) ) { foreach ($ctor->getParameters() as $param) { @@ -213,7 +213,7 @@ private function completeParameters(Nette\DI\Resolver $resolver): void )); } - $this->resultDefinition->getFactory()->arguments[$ctorParam->getPosition()] = new Php\Literal('$' . $ctorParam->name); + $this->resultDefinition->getCreator()->arguments[$ctorParam->getPosition()] = new Php\Literal('$' . $ctorParam->name); } elseif (!$this->resultDefinition->getSetup()) { $hint = Nette\Utils\Helpers::getSuggestion(array_keys($ctorParams), $param->name); diff --git a/src/DI/Definitions/ServiceDefinition.php b/src/DI/Definitions/ServiceDefinition.php index 2e862fd5c..ba208741a 100644 --- a/src/DI/Definitions/ServiceDefinition.php +++ b/src/DI/Definitions/ServiceDefinition.php @@ -23,7 +23,7 @@ final class ServiceDefinition extends Definition { /** @var Statement */ - private $factory; + private $creator; /** @var Statement[] */ private $setup = []; @@ -31,7 +31,7 @@ final class ServiceDefinition extends Definition public function __construct() { - $this->factory = new Statement(null); + $this->creator = new Statement(null); } @@ -43,6 +43,7 @@ public function setType(?string $type) /** + * Alias for setCreator() * @param string|array|Definition|Reference|Statement $factory * @return static */ @@ -52,6 +53,9 @@ public function setFactory($factory, array $args = []) } + /** + * Alias for getCreator() + */ public function getFactory(): Statement { return $this->getCreator(); @@ -59,35 +63,35 @@ public function getFactory(): Statement /** - * @param string|array|Definition|Reference|Statement $factory + * @param string|array|Definition|Reference|Statement $creator * @return static */ - public function setCreator($factory, array $args = []) + public function setCreator($creator, array $args = []) { - $this->factory = $factory instanceof Statement - ? $factory - : new Statement($factory, $args); + $this->creator = $creator instanceof Statement + ? $creator + : new Statement($creator, $args); return $this; } public function getCreator(): Statement { - return $this->factory; + return $this->creator; } /** @return string|array|Definition|Reference|null */ public function getEntity() { - return $this->factory->getEntity(); + return $this->creator->getEntity(); } /** @return static */ public function setArguments(array $args = []) { - $this->factory->arguments = $args; + $this->creator->arguments = $args; return $this; } @@ -95,7 +99,7 @@ public function setArguments(array $args = []) /** @return static */ public function setArgument($key, $value) { - $this->factory->arguments[$key] = $value; + $this->creator->arguments[$key] = $value; return $this; } @@ -144,10 +148,10 @@ public function resolveType(Nette\DI\Resolver $resolver): void throw new ServiceCreationException('Factory and type are missing in definition of service.'); } - $this->setFactory($this->getType(), $this->factory->arguments ?? []); + $this->setCreator($this->getType(), $this->creator->arguments ?? []); } elseif (!$this->getType()) { - $type = $resolver->resolveEntityType($this->factory); + $type = $resolver->resolveEntityType($this->creator); if (!$type) { throw new ServiceCreationException('Unknown service type, specify it or declare return type of factory method.'); } @@ -165,13 +169,13 @@ public function resolveType(Nette\DI\Resolver $resolver): void public function complete(Nette\DI\Resolver $resolver): void { - $entity = $this->factory->getEntity(); - if ($entity instanceof Reference && !$this->factory->arguments && !$this->setup) { + $entity = $this->creator->getEntity(); + if ($entity instanceof Reference && !$this->creator->arguments && !$this->setup) { $ref = $resolver->normalizeReference($entity); - $this->setFactory([new Reference(Nette\DI\ContainerBuilder::THIS_CONTAINER), 'getService'], [$ref->getValue()]); + $this->setCreator([new Reference(Nette\DI\ContainerBuilder::THIS_CONTAINER), 'getService'], [$ref->getValue()]); } - $this->factory = $resolver->completeStatement($this->factory); + $this->creator = $resolver->completeStatement($this->creator); foreach ($this->setup as &$setup) { if ( @@ -188,8 +192,8 @@ public function complete(Nette\DI\Resolver $resolver): void public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void { - $entity = $this->factory->getEntity(); - $code = $generator->formatStatement($this->factory) . ";\n"; + $entity = $this->creator->getEntity(); + $code = $generator->formatStatement($this->creator) . ";\n"; if (!$this->setup) { $method->setBody('return ' . $code); return; @@ -208,7 +212,7 @@ public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGe public function __clone() { parent::__clone(); - $this->factory = unserialize(serialize($this->factory)); + $this->creator = unserialize(serialize($this->creator)); $this->setup = unserialize(serialize($this->setup)); } } diff --git a/src/DI/Extensions/InjectExtension.php b/src/DI/Extensions/InjectExtension.php index 4b8273115..47f4aca63 100644 --- a/src/DI/Extensions/InjectExtension.php +++ b/src/DI/Extensions/InjectExtension.php @@ -46,7 +46,7 @@ public function beforeCompile() private function updateDefinition(Definitions\ServiceDefinition $def): void { - $resolvedType = (new DI\Resolver($this->getContainerBuilder()))->resolveEntityType($def->getFactory()); + $resolvedType = (new DI\Resolver($this->getContainerBuilder()))->resolveEntityType($def->getCreator()); $class = is_subclass_of($resolvedType, $def->getType()) ? $resolvedType : $def->getType(); diff --git a/src/DI/Extensions/ServicesExtension.php b/src/DI/Extensions/ServicesExtension.php index 89af4b678..e6b7cee6d 100644 --- a/src/DI/Extensions/ServicesExtension.php +++ b/src/DI/Extensions/ServicesExtension.php @@ -81,7 +81,7 @@ private function loadDefinition(?string $name, \stdClass $config): void private function updateServiceDefinition(Definitions\ServiceDefinition $definition, \stdClass $config): void { if ($config->create) { - $definition->setFactory(Helpers::filterArguments([$config->create])[0]); + $definition->setCreator(Helpers::filterArguments([$config->create])[0]); $definition->setType(null); } @@ -92,7 +92,7 @@ private function updateServiceDefinition(Definitions\ServiceDefinition $definiti if ($config->arguments) { $arguments = Helpers::filterArguments($config->arguments); if (empty($config->reset['arguments']) && !Nette\Utils\Arrays::isList($arguments)) { - $arguments = array_replace($definition->getFactory()->arguments, $arguments); + $arguments = array_replace($definition->getCreator()->arguments, $arguments); } $definition->setArguments($arguments); @@ -140,17 +140,17 @@ private function updateFactoryDefinition(Definitions\FactoryDefinition $definiti } if ($config->create) { - $resultDef->setFactory(Helpers::filterArguments([$config->create])[0]); + $resultDef->setCreator(Helpers::filterArguments([$config->create])[0]); } if ($config->type) { - $resultDef->setFactory($config->type); + $resultDef->setCreator($config->type); } if ($config->arguments) { $arguments = Helpers::filterArguments($config->arguments); if (empty($config->reset['arguments']) && !Nette\Utils\Arrays::isList($arguments)) { - $arguments = array_replace($resultDef->getFactory()->arguments, $arguments); + $arguments = array_replace($resultDef->getCreator()->arguments, $arguments); } $resultDef->setArguments($arguments); diff --git a/tests/DI/Compiler.extensionOverride.phpt b/tests/DI/Compiler.extensionOverride.phpt index 2adb5619f..24b8f0148 100644 --- a/tests/DI/Compiler.extensionOverride.phpt +++ b/tests/DI/Compiler.extensionOverride.phpt @@ -55,79 +55,79 @@ class FooExtension extends Nette\DI\CompilerExtension $builder = $this->getContainerBuilder(); $builder->addDefinition('one1') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('one2') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('one3') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('one4') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('one5') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('one6') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('one7') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('one8') - ->setFactory(Lorem::class, [1]) + ->setCreator(Lorem::class, [1]) ->addSetup('__construct', [2]); $builder->addDefinition('one9') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('one10') - ->setFactory(Lorem::class, [1]); + ->setCreator(Lorem::class, [1]); $builder->addDefinition('two1') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('two2') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('two3') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('two4') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1, 2]); + ->setCreator('Factory::createLorem', [1, 2]); $builder->addDefinition('two5') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('two6') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1, 2]); + ->setCreator('Factory::createLorem', [1, 2]); $builder->addDefinition('two7') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('two8') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1, 2]); + ->setCreator('Factory::createLorem', [1, 2]); $builder->addDefinition('two9') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1, 2]); + ->setCreator('Factory::createLorem', [1, 2]); $builder->addDefinition('two10') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('two11') ->setType(Lorem::class) - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three1') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three2') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three3') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three4') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three5') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three6') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three7') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three8') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); $builder->addDefinition('three9') - ->setFactory('Factory::createLorem', [1]); + ->setCreator('Factory::createLorem', [1]); } } diff --git a/tests/DI/Compiler.generatedFactory.phpt b/tests/DI/Compiler.generatedFactory.phpt index 9cf3550cb..d3b5dd3ee 100644 --- a/tests/DI/Compiler.generatedFactory.phpt +++ b/tests/DI/Compiler.generatedFactory.phpt @@ -142,7 +142,7 @@ class TestExtension extends DI\CompilerExtension ->setParameters(['Baz baz' => null]) ->setImplement(IFooFactory::class) ->getResultDefinition() - ->setFactory(Foo::class) + ->setCreator(Foo::class) ->setArguments([1 => $builder::literal('$baz')]); $builder->addFactoryDefinition('overridenFactory') @@ -332,7 +332,7 @@ interface Bad7 Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition(stdClass::class)->setFactory(stdClass::class); + $builder->addDefinition(stdClass::class)->setCreator(stdClass::class); $builder->addAccessorDefinition('one') ->setImplement(Bad7::class) ->setClass(stdClass::class) diff --git a/tests/DI/CompilerExtension.loadDefinitionsFromConfig.phpt b/tests/DI/CompilerExtension.loadDefinitionsFromConfig.phpt index 08cd2b8b0..17e1c2d04 100644 --- a/tests/DI/CompilerExtension.loadDefinitionsFromConfig.phpt +++ b/tests/DI/CompilerExtension.loadDefinitionsFromConfig.phpt @@ -27,6 +27,6 @@ $compilerExtension = (new CompilerExtension)->setCompiler($compiler, 'blog'); $compilerExtension->loadDefinitionsFromConfig($config['services']); -Assert::same('@blog.articles', $builder->getDefinition('blog.comments')->getFactory()->arguments[1]); -Assert::equal(new Reference('blog.articles'), $builder->getDefinition('blog.articlesList')->getFactory()->arguments[0]); -Assert::equal(new Reference('blog.comments'), $builder->getDefinition('blog.commentsControl')->getFactory()->arguments[0]->getEntity()); +Assert::same('@blog.articles', $builder->getDefinition('blog.comments')->getCreator()->arguments[1]); +Assert::equal(new Reference('blog.articles'), $builder->getDefinition('blog.articlesList')->getCreator()->arguments[0]); +Assert::equal(new Reference('blog.comments'), $builder->getDefinition('blog.commentsControl')->getCreator()->arguments[0]->getEntity()); diff --git a/tests/DI/ContainerBuilder.accessor.phpt b/tests/DI/ContainerBuilder.accessor.phpt index 6333ba56d..e6b528e09 100644 --- a/tests/DI/ContainerBuilder.accessor.phpt +++ b/tests/DI/ContainerBuilder.accessor.phpt @@ -38,11 +38,11 @@ class AccessorReceiver $builder = new DI\ContainerBuilder; $builder->addDefinition('service') - ->setFactory(stdClass::class); + ->setCreator(stdClass::class); $builder->addDefinition('service2') ->setAutowired(false) - ->setFactory(stdClass::class); + ->setCreator(stdClass::class); $builder->addAccessorDefinition('one') ->setImplement(StdClassAccessor::class) diff --git a/tests/DI/ContainerBuilder.aliases.phpt b/tests/DI/ContainerBuilder.aliases.phpt index d2bf878b2..2ff62dc18 100644 --- a/tests/DI/ContainerBuilder.aliases.phpt +++ b/tests/DI/ContainerBuilder.aliases.phpt @@ -30,38 +30,38 @@ interface ServiceFactory2 $builder = new DI\ContainerBuilder; $builder->addDefinition('aliasForFactory') - ->setFactory('@serviceFactory'); + ->setCreator('@serviceFactory'); $builder->addDefinition('aliasForFactoryViaClass') - ->setFactory('@\ServiceFactory'); + ->setCreator('@\ServiceFactory'); $builder->addFactoryDefinition('aliasedFactory') ->setImplement(ServiceFactory::class) ->setAutowired(false) ->getResultDefinition() - ->setFactory('@service'); + ->setCreator('@service'); $builder->addFactoryDefinition('aliasedFactoryViaClass') ->setImplement(ServiceFactory::class) ->setAutowired(false) ->getResultDefinition() - ->setFactory('@\Service'); + ->setCreator('@\Service'); $builder->addDefinition('aliasedService') - ->setFactory('@service'); + ->setCreator('@service'); $builder->addDefinition('aliasedServiceViaClass') - ->setFactory('@\Service'); + ->setCreator('@\Service'); $builder->addFactoryDefinition('serviceFactory') ->setImplement(ServiceFactory::class) ->getResultDefinition() - ->setFactory('@service'); + ->setCreator('@service'); $builder->addFactoryDefinition('serviceFactoryViaClass') ->setImplement(ServiceFactory2::class) ->getResultDefinition() - ->setFactory('@\Service'); + ->setCreator('@\Service'); $builder->addDefinition('service') ->setType(Service::class); diff --git a/tests/DI/ContainerBuilder.aliases2.phpt b/tests/DI/ContainerBuilder.aliases2.phpt index b4ed8db61..944cbbbe5 100644 --- a/tests/DI/ContainerBuilder.aliases2.phpt +++ b/tests/DI/ContainerBuilder.aliases2.phpt @@ -32,12 +32,12 @@ $builder = new DI\ContainerBuilder; $builder->addFactoryDefinition('serviceFactory') ->setImplement(ServiceFactory::class) ->getResultDefinition() - ->setFactory('@service'); + ->setCreator('@service'); $builder->addFactoryDefinition('serviceFactoryViaClass') ->setImplement(ServiceFactory2::class) ->getResultDefinition() - ->setFactory('@\Service'); + ->setCreator('@\Service'); $builder->addDefinition('service') ->setType(stdClass::class); diff --git a/tests/DI/ContainerBuilder.basic.phpt b/tests/DI/ContainerBuilder.basic.phpt index 0ec054bab..02e380000 100644 --- a/tests/DI/ContainerBuilder.basic.phpt +++ b/tests/DI/ContainerBuilder.basic.phpt @@ -40,31 +40,31 @@ class Service $builder = new DI\ContainerBuilder; $builder->addDefinition('one') - ->setFactory(Service::class, ['@@string']); + ->setCreator(Service::class, ['@@string']); $builder->addDefinition('three') - ->setFactory(Service::class, ['a', 'b']); + ->setCreator(Service::class, ['a', 'b']); $builder->addDefinition('four') - ->setFactory(Service::class, ['a', 'b']) + ->setCreator(Service::class, ['a', 'b']) ->addSetup('methodA', ['a', 'b']) ->addSetup('@four::methodB', [1, 2]) ->addSetup('methodC', ['@self', '@container']) ->addSetup('methodD', ['@one']); $builder->addDefinition('five', null) - ->setFactory('Service::create'); + ->setCreator('Service::create'); $six = $builder->addDefinition('six') - ->setFactory('Service::create', ['@container', 'a', 'b']) + ->setCreator('Service::create', ['@container', 'a', 'b']) ->addSetup(['@six', 'methodA'], ['a', 'b']); $builder->addDefinition('seven') - ->setFactory([$six, 'create'], ['@container', $six]) + ->setCreator([$six, 'create'], ['@container', $six]) ->addSetup([$six, 'methodA']) ->addSetup('$service->methodA(?)', ['a']); $six = $builder->addDefinition('eight') - ->setFactory('Service::create', [new Reference('container'), 'a', 'b']) + ->setCreator('Service::create', [new Reference('container'), 'a', 'b']) ->addSetup([new Reference('self'), 'methodA'], [new Reference('eight'), new Reference('self')]) ->addSetup([new Reference('eight'), 'methodB']) ->addSetup([new Reference('six'), 'methodC']) diff --git a/tests/DI/ContainerBuilder.basic2.phpt b/tests/DI/ContainerBuilder.basic2.phpt index 1bda434e5..a042e2e2f 100644 --- a/tests/DI/ContainerBuilder.basic2.phpt +++ b/tests/DI/ContainerBuilder.basic2.phpt @@ -29,7 +29,7 @@ class Factory $builder = new DI\ContainerBuilder; $builder->addDefinition('one') - ->setFactory('Factory::create'); + ->setCreator('Factory::create'); $container = createContainer($builder); diff --git a/tests/DI/ContainerBuilder.basic3.phpt b/tests/DI/ContainerBuilder.basic3.phpt index e124ec100..ad684c8ef 100644 --- a/tests/DI/ContainerBuilder.basic3.phpt +++ b/tests/DI/ContainerBuilder.basic3.phpt @@ -21,7 +21,7 @@ function create(): stdClass $builder = new DI\ContainerBuilder; $builder->addDefinition('one') - ->setFactory('::create'); + ->setCreator('::create'); $container = createContainer($builder); diff --git a/tests/DI/ContainerBuilder.byClass.phpt b/tests/DI/ContainerBuilder.byClass.phpt index b73309432..744a47218 100644 --- a/tests/DI/ContainerBuilder.byClass.phpt +++ b/tests/DI/ContainerBuilder.byClass.phpt @@ -72,30 +72,30 @@ $builder->addDefinition('annotatedFactory') $builder->addDefinition('two') ->setType(stdClass::class) ->setAutowired(false) - ->setFactory('@factory::create', ['@\Factory']) + ->setCreator('@factory::create', ['@\Factory']) ->addSetup(['@\Factory', 'create'], ['@\Factory']); $builder->addDefinition('three') ->setType(stdClass::class) ->setAutowired(false) - ->setFactory('@\Factory::create', ['@\Factory']); + ->setCreator('@\Factory::create', ['@\Factory']); $builder->addDefinition('four') ->setAutowired(false) - ->setFactory('@\AnnotatedFactory::create'); + ->setCreator('@\AnnotatedFactory::create'); $builder->addDefinition('five') ->setType(stdClass::class) ->setAutowired(false) - ->setFactory('@\IFactory::create'); + ->setCreator('@\IFactory::create'); $builder->addDefinition('uninstantiableFactory') ->setType(UninstantiableFactory::class) - ->setFactory('UninstantiableFactory::getInstance'); + ->setCreator('UninstantiableFactory::getInstance'); $builder->addDefinition('six') ->setAutowired(false) - ->setFactory('@\UninstantiableFactory::create'); + ->setCreator('@\UninstantiableFactory::create'); diff --git a/tests/DI/ContainerBuilder.create.error.phpt b/tests/DI/ContainerBuilder.create.error.phpt index ad56b1fca..5cbbdbe75 100644 --- a/tests/DI/ContainerBuilder.create.error.phpt +++ b/tests/DI/ContainerBuilder.create.error.phpt @@ -17,43 +17,43 @@ require __DIR__ . '/../bootstrap.php'; Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setType('X')->setFactory('Unknown'); + $builder->addDefinition('one')->setType('X')->setCreator('Unknown'); }, Nette\InvalidArgumentException::class, "Service 'one': Class or interface 'X' not found."); Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition(null)->setFactory('Unknown'); + $builder->addDefinition(null)->setCreator('Unknown'); $builder->complete(); }, Nette\DI\ServiceCreationException::class, "Service (Unknown::__construct()): Class 'Unknown' not found."); Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory('@two'); - $builder->addDefinition('two')->setFactory('Unknown'); + $builder->addDefinition('one')->setCreator('@two'); + $builder->addDefinition('two')->setCreator('Unknown'); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'two': Class 'Unknown' not found."); Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory(new Reference('two')); - $builder->addDefinition('two')->setFactory('Unknown'); + $builder->addDefinition('one')->setCreator(new Reference('two')); + $builder->addDefinition('two')->setCreator('Unknown'); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'two': Class 'Unknown' not found."); Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory('stdClass::foo'); + $builder->addDefinition('one')->setCreator('stdClass::foo'); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one': Method stdClass::foo() is not callable."); Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory('Nette\DI\Container::foo'); // has __magic + $builder->addDefinition('one')->setCreator('Nette\DI\Container::foo'); // has __magic $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one': Method Nette\\DI\\Container::foo() is not callable."); @@ -101,7 +101,7 @@ class Bad6 Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory('Bad6::create'); + $builder->addDefinition('one')->setCreator('Bad6::create'); $builder->complete(); }, Nette\DI\ServiceCreationException::class, "Service 'one': Method Bad6::create() is not callable."); @@ -115,7 +115,7 @@ class Bad7 Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory('Bad7::create'); + $builder->addDefinition('one')->setCreator('Bad7::create'); $builder->complete(); }, Nette\DI\ServiceCreationException::class, "Service 'one': Unknown service type, specify it or declare return type of factory method."); @@ -144,14 +144,14 @@ class Good // fail in argument Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory(Good::class, [new Statement('Unknown')]); + $builder->addDefinition('one')->setCreator(Good::class, [new Statement('Unknown')]); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class 'Unknown' not found. (used in Good::__construct())"); // fail in argument Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory(Good::class, [new Statement(Bad8::class)]); + $builder->addDefinition('one')->setCreator(Good::class, [new Statement(Bad8::class)]); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Bad8 has private constructor. (used in Good::__construct())"); @@ -181,7 +181,7 @@ trait Bad10 // trait cannot be instantiated Assert::exception(function () { $builder = new DI\ContainerBuilder; - $builder->addDefinition('one')->setFactory('Bad10::method'); + $builder->addDefinition('one')->setCreator('Bad10::method'); $builder->complete(); }, Nette\InvalidStateException::class, "Service 'one': Method Bad10::method() is not callable."); diff --git a/tests/DI/ContainerBuilder.create.resolveClass.phpt b/tests/DI/ContainerBuilder.create.resolveClass.phpt index 4b6d9efa8..006cb75c7 100644 --- a/tests/DI/ContainerBuilder.create.resolveClass.phpt +++ b/tests/DI/ContainerBuilder.create.resolveClass.phpt @@ -31,7 +31,7 @@ $builder->addDefinition('one') ->setType(Factory::class); $builder->addDefinition('two') - ->setFactory('@one::createBar'); + ->setCreator('@one::createBar'); $container = createContainer($builder); diff --git a/tests/DI/ContainerBuilder.create.rich.phpt b/tests/DI/ContainerBuilder.create.rich.phpt index 435004119..6bb079636 100644 --- a/tests/DI/ContainerBuilder.create.rich.phpt +++ b/tests/DI/ContainerBuilder.create.rich.phpt @@ -40,11 +40,11 @@ class Obj $builder = new DI\ContainerBuilder; $one = $builder->addDefinition('one') - ->setFactory([new Statement(Factory::class), 'create']) + ->setCreator([new Statement(Factory::class), 'create']) ->addSetup([new Statement(Factory::class), 'mark'], ['@self']); $two = $builder->addDefinition('two') - ->setFactory([new Statement([$one, 'foo'], [1]), 'foo'], [2]); + ->setCreator([new Statement([$one, 'foo'], [1]), 'foo'], [2]); $container = createContainer($builder); diff --git a/tests/DI/ContainerBuilder.factory.params.phpt b/tests/DI/ContainerBuilder.factory.params.phpt index a5e1d25e2..4b44ac44c 100644 --- a/tests/DI/ContainerBuilder.factory.params.phpt +++ b/tests/DI/ContainerBuilder.factory.params.phpt @@ -23,25 +23,25 @@ $builder = new DI\ContainerBuilder; $builder->addFactoryDefinition('one') ->setImplement(StdClassFactory::class) ->getResultDefinition() - ->setFactory(stdClass::class) + ->setCreator(stdClass::class) ->addSetup('$a', [$builder::literal('$a')]); @$builder->addFactoryDefinition('two') ->setParameters(['stdClass foo', 'array bar', 'foobar' => null]) // parameters is deprecated ->setImplement(StdClassFactory::class) ->getResultDefinition() - ->setFactory(stdClass::class) + ->setCreator(stdClass::class) ->addSetup('$a', [$builder::literal('$foo')]); $builder->addDefinition('three') ->setType(stdClass::class); $builder->addDefinition('four') - ->setFactory('@one::create', [1 => [1]]) + ->setCreator('@one::create', [1 => [1]]) ->setAutowired(false); $builder->addDefinition('five') - ->setFactory('@two::create', [1 => [1]]) + ->setCreator('@two::create', [1 => [1]]) ->setAutowired(false); diff --git a/tests/DI/ContainerBuilder.factory.phpt b/tests/DI/ContainerBuilder.factory.phpt index cb31f1c47..7c1b277c6 100644 --- a/tests/DI/ContainerBuilder.factory.phpt +++ b/tests/DI/ContainerBuilder.factory.phpt @@ -36,7 +36,7 @@ $builder = new DI\ContainerBuilder; $builder->addFactoryDefinition('one') ->setImplement(StdClassFactory::class) ->getResultDefinition() - ->setFactory(stdClass::class); + ->setCreator(stdClass::class); @$builder->addFactoryDefinition('two') ->setImplement(AnnotatedFactory::class); // missing type triggers warning @@ -45,7 +45,7 @@ $builder->addDefinition('three') ->setType(FactoryReceiver::class); $builder->addDefinition('four') - ->setFactory(FactoryReceiver::class, ['@one']); + ->setCreator(FactoryReceiver::class, ['@one']); $container = createContainer($builder); diff --git a/tests/DI/ContainerBuilder.factory.resolveClass.phpt b/tests/DI/ContainerBuilder.factory.resolveClass.phpt index efaf5101f..8f021c681 100644 --- a/tests/DI/ContainerBuilder.factory.resolveClass.phpt +++ b/tests/DI/ContainerBuilder.factory.resolveClass.phpt @@ -70,33 +70,33 @@ namespace $builder->addFactoryDefinition('one') ->setImplement(StdClassFactory::class) ->getResultDefinition() - ->setFactory(stdClass::class); + ->setCreator(stdClass::class); $builder->addFactoryDefinition('two') ->setImplement(StdClassFactory::class) ->getResultDefinition() - ->setFactory('@eight'); + ->setCreator('@eight'); $builder->addFactoryDefinition('three') ->setImplement(StdClassFactory::class) ->getResultDefinition() - ->setFactory('@one::create') // alias + ->setCreator('@one::create') // alias ->setType(stdClass::class); // type is needed $builder->addDefinition('four') ->setType(A\Factory::class); $builder->addDefinition('five') - ->setFactory('@four::createFoo'); + ->setCreator('@four::createFoo'); $builder->addDefinition('six') - ->setFactory('@four::createBar'); + ->setCreator('@four::createBar'); $builder->addDefinition('seven') - ->setFactory('C\SelfFactory::create'); + ->setCreator('C\SelfFactory::create'); $builder->addDefinition('eight') - ->setFactory('stdClass'); + ->setCreator('stdClass'); $container = createContainer($builder); diff --git a/tests/DI/ContainerBuilder.names.phpt b/tests/DI/ContainerBuilder.names.phpt index 5db877184..c6f134977 100644 --- a/tests/DI/ContainerBuilder.names.phpt +++ b/tests/DI/ContainerBuilder.names.phpt @@ -11,13 +11,13 @@ require __DIR__ . '/../bootstrap.php'; $builder = new DI\ContainerBuilder; $builder->addDefinition('01') - ->setFactory(stdClass::class); + ->setCreator(stdClass::class); $builder->addDefinition(null) - ->setFactory(stdClass::class); + ->setCreator(stdClass::class); $builder->addDefinition(null) - ->setFactory(stdClass::class); + ->setCreator(stdClass::class); $container = createContainer($builder); diff --git a/tests/DI/ContainerBuilder.recursive.phpt b/tests/DI/ContainerBuilder.recursive.phpt index 50ca69c71..86a668d1f 100644 --- a/tests/DI/ContainerBuilder.recursive.phpt +++ b/tests/DI/ContainerBuilder.recursive.phpt @@ -23,9 +23,9 @@ class Service $builder = new DI\ContainerBuilder; $builder->addDefinition('one') - ->setFactory('@two::get'); + ->setCreator('@two::get'); $builder->addDefinition('two') - ->setFactory('@one::get'); + ->setCreator('@one::get'); Assert::exception(function () use ($builder) { $container = createContainer($builder); diff --git a/tests/DI/ContainerBuilder.resolveTypes.php80.phpt b/tests/DI/ContainerBuilder.resolveTypes.php80.phpt index 161e93e38..8f8631215 100644 --- a/tests/DI/ContainerBuilder.resolveTypes.php80.phpt +++ b/tests/DI/ContainerBuilder.resolveTypes.php80.phpt @@ -25,6 +25,6 @@ require __DIR__ . '/../bootstrap.php'; Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createUnion']); + ->setCreator([Factory::class, 'createUnion']); $container = createContainer($builder); }, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createUnion() is not expected to be nullable/union/intersection/built-in, 'stdClass|array' given."); diff --git a/tests/DI/ContainerBuilder.resolveTypes.phpt b/tests/DI/ContainerBuilder.resolveTypes.phpt index 4c11a8387..9072a8446 100644 --- a/tests/DI/ContainerBuilder.resolveTypes.phpt +++ b/tests/DI/ContainerBuilder.resolveTypes.phpt @@ -96,84 +96,84 @@ require __DIR__ . '/../bootstrap.php'; Assert::noError(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createClassPhpDoc']); + ->setCreator([Factory::class, 'createClassPhpDoc']); $container = @createContainer($builder); // @return is deprecated }); Assert::noError(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createClass']); + ->setCreator([Factory::class, 'createClass']); $container = createContainer($builder); }); Assert::noError(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createNullableClassPhpDoc']); + ->setCreator([Factory::class, 'createNullableClassPhpDoc']); $container = @createContainer($builder); // @return is deprecated }); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createNullableClass']); + ->setCreator([Factory::class, 'createNullableClass']); $container = createContainer($builder); }, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createNullableClass() is not expected to be nullable/union/intersection/built-in, '?stdClass' given."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createScalarPhpDoc']); + ->setCreator([Factory::class, 'createScalarPhpDoc']); $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createScalarPhpDoc() is not expected to be nullable/union/intersection/built-in, 'array' given."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createScalar']); + ->setCreator([Factory::class, 'createScalar']); $container = createContainer($builder); }, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createScalar() is not expected to be nullable/union/intersection/built-in, 'array' given."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createObjectPhpDoc']); + ->setCreator([Factory::class, 'createObjectPhpDoc']); $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createObject']); + ->setCreator([Factory::class, 'createObject']); $container = createContainer($builder); }, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createObjectNullable']); + ->setCreator([Factory::class, 'createObjectNullable']); $container = createContainer($builder); }, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createObjectNullable() is not expected to be nullable/union/intersection/built-in, '?object' given."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createMixedPhpDoc']); + ->setCreator([Factory::class, 'createMixedPhpDoc']); $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createMixed']); + ->setCreator([Factory::class, 'createMixed']); $container = createContainer($builder); }, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') - ->setFactory([Factory::class, 'createGeneric']); + ->setCreator([Factory::class, 'createGeneric']); $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Class 'T' not found. Check the return type of Factory::createGeneric()."); diff --git a/tests/DI/ContainerBuilder.selfdependency.phpt b/tests/DI/ContainerBuilder.selfdependency.phpt index 7230c1925..a418c2639 100644 --- a/tests/DI/ContainerBuilder.selfdependency.phpt +++ b/tests/DI/ContainerBuilder.selfdependency.phpt @@ -23,7 +23,7 @@ class Foo $builder = new DI\ContainerBuilder; $builder->addDefinition(null) - ->setFactory(Foo::class); + ->setCreator(Foo::class); Assert::exception(function () use ($builder) { createContainer($builder); diff --git a/tests/DI/Definitions.ServiceDefinition.phpt b/tests/DI/Definitions.ServiceDefinition.phpt index a458f38ff..f53781689 100644 --- a/tests/DI/Definitions.ServiceDefinition.phpt +++ b/tests/DI/Definitions.ServiceDefinition.phpt @@ -32,51 +32,51 @@ test('', function () { test('', function () { $def = new ServiceDefinition; - $def->setFactory(stdClass::class); + $def->setCreator(stdClass::class); Assert::null($def->getType()); - Assert::equal(new Statement(stdClass::class, []), $def->getFactory()); + Assert::equal(new Statement(stdClass::class, []), $def->getCreator()); $def->setArguments([1, 2]); Assert::null($def->getType()); - Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getFactory()); + Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getCreator()); // Demonstrate that setArguments call will always replace arguments. $def->setArguments([1 => 200]); - Assert::equal(new Statement(stdClass::class, [1 => 200]), $def->getFactory()); + Assert::equal(new Statement(stdClass::class, [1 => 200]), $def->getCreator()); }); test('Test with factory being previously set.', function () { $def1 = new ServiceDefinition; - $def1->setFactory(stdClass::class, ['foo', 'bar']); + $def1->setCreator(stdClass::class, ['foo', 'bar']); $def1->setArgument(1, 'new'); - Assert::equal(new Statement(stdClass::class, ['foo', 'new']), $def1->getFactory()); + Assert::equal(new Statement(stdClass::class, ['foo', 'new']), $def1->getCreator()); // Test with factory being set implicitly. $def2 = new ServiceDefinition; $def2->setArgument(1, 'new'); $def2->setArgument(2, 'bar'); - Assert::equal(new Statement(null, [1 => 'new', 2 => 'bar']), $def2->getFactory()); + Assert::equal(new Statement(null, [1 => 'new', 2 => 'bar']), $def2->getCreator()); }); test('', function () { $def = new ServiceDefinition; - $def->setFactory(stdClass::class, [1, 2]); + $def->setCreator(stdClass::class, [1, 2]); Assert::null($def->getType()); - Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getFactory()); + Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getCreator()); }); test('', function () { $def = new ServiceDefinition; - $def->setFactory(new Statement(stdClass::class, [1, 2])); + $def->setCreator(new Statement(stdClass::class, [1, 2])); Assert::null($def->getType()); - Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getFactory()); + Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getCreator()); }); test('', function () { $def = new ServiceDefinition; - $def->setFactory(new Statement(stdClass::class, [1, 2]), [99]); // 99 is ignored + $def->setCreator(new Statement(stdClass::class, [1, 2]), [99]); // 99 is ignored Assert::null($def->getType()); - Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getFactory()); + Assert::equal(new Statement(stdClass::class, [1, 2]), $def->getCreator()); }); test('', function () { @@ -107,12 +107,12 @@ test('', function () { test('deep clone', function () { $def = new ServiceDefinition; - $def->setFactory(new Statement(stdClass::class, [1, 2])); + $def->setCreator(new Statement(stdClass::class, [1, 2])); $def->addSetup(new Statement(stdClass::class, [1, 2])); $dolly = clone $def; - Assert::notSame($dolly->getFactory(), $def->getFactory()); - Assert::equal($dolly->getFactory(), $def->getFactory()); + Assert::notSame($dolly->getCreator(), $def->getCreator()); + Assert::equal($dolly->getCreator(), $def->getCreator()); Assert::notSame($dolly->getSetup(), $def->getSetup()); Assert::equal($dolly->getSetup(), $def->getSetup()); }); From 70198f23c11f2f99f18ededcd620112b5e62b050 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 20 Oct 2021 00:16:55 +0200 Subject: [PATCH 15/44] Three ... dots are deprecated, triggers notices --- src/DI/Config/Adapters/NeonAdapter.php | 6 ++++++ src/DI/Helpers.php | 6 ++---- tests/DI/Compiler.services.autowiring.phpt | 2 +- tests/DI/Helpers.filterArguments.phpt | 9 ++------- tests/DI/NeonAdapter.preprocess.phpt | 11 +++++++++++ 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/DI/Config/Adapters/NeonAdapter.php b/src/DI/Config/Adapters/NeonAdapter.php index 030977fee..00a80db2d 100644 --- a/src/DI/Config/Adapters/NeonAdapter.php +++ b/src/DI/Config/Adapters/NeonAdapter.php @@ -150,6 +150,7 @@ function (&$val): void { } + /** @internal */ public function removeUnderscoreVisitor(Neon\Node $node) { if (!$node instanceof Neon\Node\EntityNode) { @@ -165,6 +166,11 @@ public function removeUnderscoreVisitor(Neon\Node $node) if ($attr->value instanceof Neon\Node\LiteralNode && $attr->value->value === '_') { unset($node->attributes[$i]); $index = true; + + } elseif ($attr->value instanceof Neon\Node\LiteralNode && $attr->value->value === '...') { + trigger_error("Replace ... with _ in configuration file '$this->file'.", E_USER_DEPRECATED); + unset($node->attributes[$i]); + $index = true; } } } diff --git a/src/DI/Helpers.php b/src/DI/Helpers.php index 943519517..4d7f09509 100644 --- a/src/DI/Helpers.php +++ b/src/DI/Helpers.php @@ -137,14 +137,12 @@ public static function escape($value) /** - * Removes ... and process constants recursively. + * Process constants recursively. */ public static function filterArguments(array $args): array { foreach ($args as $k => $v) { - if ($v === '...') { - unset($args[$k]); - } elseif ( + if ( PHP_VERSION_ID >= 80100 && is_string($v) && preg_match('#^([\w\\\\]+)::\w+$#D', $v, $m) diff --git a/tests/DI/Compiler.services.autowiring.phpt b/tests/DI/Compiler.services.autowiring.phpt index c49ce65d9..ec043dcd2 100644 --- a/tests/DI/Compiler.services.autowiring.phpt +++ b/tests/DI/Compiler.services.autowiring.phpt @@ -52,7 +52,7 @@ services: factory: Factory()::createModel setup: # local methods - - test(...) + - test(_) - @model::test() - @self::test() diff --git a/tests/DI/Helpers.filterArguments.phpt b/tests/DI/Helpers.filterArguments.phpt index 35cdf7a39..4976abb79 100644 --- a/tests/DI/Helpers.filterArguments.phpt +++ b/tests/DI/Helpers.filterArguments.phpt @@ -16,11 +16,6 @@ require __DIR__ . '/../bootstrap.php'; Assert::same([], Helpers::filterArguments([])); -Assert::same( - ['a', 'b', 3 => ['c'], [1 => 'd']], - Helpers::filterArguments(['a', 'b', '...', ['c', '...'], ['...', 'd']]) -); - Assert::same( ['a', 'b', Nette\DI\ContainerBuilder::THIS_CONTAINER], Helpers::filterArguments(['a', 'b', 'Nette\DI\ContainerBuilder::THIS_CONTAINER']) @@ -32,6 +27,6 @@ Assert::equal( ); Assert::equal( - [new Statement('class', ['a', 2 => Nette\DI\ContainerBuilder::THIS_CONTAINER])], - Helpers::filterArguments([new Statement('class', ['a', '...', 'Nette\DI\ContainerBuilder::THIS_CONTAINER'])]) + [new Statement('class', ['a', Nette\DI\ContainerBuilder::THIS_CONTAINER])], + Helpers::filterArguments([new Statement('class', ['a', 'Nette\DI\ContainerBuilder::THIS_CONTAINER'])]), ); diff --git a/tests/DI/NeonAdapter.preprocess.phpt b/tests/DI/NeonAdapter.preprocess.phpt index 17d6e8b8a..6db0c564c 100644 --- a/tests/DI/NeonAdapter.preprocess.phpt +++ b/tests/DI/NeonAdapter.preprocess.phpt @@ -70,3 +70,14 @@ Assert::equal( [new Statement('Class', ['arg1', 2 => ['_']])], $data ); + + +// ... deprecated +$data = @$adapter->load(Tester\FileMock::create(' +- Class(arg1, ..., [...]) +', 'neon')); + +Assert::equal( + [new Statement('Class', ['arg1', 2 => ['...']])], + $data +); From f02f9e581aeff827d0e35326cd1e9bb084f54e2c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 15 Dec 2021 00:42:45 +0100 Subject: [PATCH 16/44] NeonAdapter: automatically escapes @ --- src/DI/Config/Adapters/NeonAdapter.php | 21 +++++++++++++++++++++ tests/DI/Compiler.referenceBug.phpt | 2 +- tests/DI/NeonAdapter.preprocess.phpt | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/DI/Config/Adapters/NeonAdapter.php b/src/DI/Config/Adapters/NeonAdapter.php index 00a80db2d..319b3791e 100644 --- a/src/DI/Config/Adapters/NeonAdapter.php +++ b/src/DI/Config/Adapters/NeonAdapter.php @@ -44,6 +44,7 @@ public function load(string $file): array $node = $decoder->parseToNode($input); $traverser = new Neon\Traverser; $node = $traverser->traverse($node, [$this, 'removeUnderscoreVisitor']); + $node = $traverser->traverse($node, [$this, 'convertAtSignVisitor']); return $this->process((array) $node->toValue()); } @@ -174,4 +175,24 @@ public function removeUnderscoreVisitor(Neon\Node $node) } } } + + + /** @internal */ + public function convertAtSignVisitor(Neon\Node $node) + { + if ($node instanceof Neon\Node\StringNode) { + if (substr($node->value, 0, 2) === '@@') { + trigger_error("There is no need to escape @ anymore, replace @@ with @ in: '$node->value' (used in $this->file)", E_USER_DEPRECATED); + } else { + $node->value = preg_replace('#^@#', '$0$0', $node->value); // escape + } + + } elseif ( + $node instanceof Neon\Node\LiteralNode + && is_string($node->value) + && substr($node->value, 0, 2) === '@@' + ) { + trigger_error("There is no need to escape @ anymore, replace @@ with @ and put string in quotes: '$node->value' (used in $this->file)", E_USER_DEPRECATED); + } + } } diff --git a/tests/DI/Compiler.referenceBug.phpt b/tests/DI/Compiler.referenceBug.phpt index 9d1311ded..4351067ae 100644 --- a/tests/DI/Compiler.referenceBug.phpt +++ b/tests/DI/Compiler.referenceBug.phpt @@ -32,7 +32,7 @@ services: - stdClass a: Lorem(x: true) b: Lorem(x: Lorem(x: true)) - c: Lorem(@@test) + c: Lorem("@test") '); diff --git a/tests/DI/NeonAdapter.preprocess.phpt b/tests/DI/NeonAdapter.preprocess.phpt index 6db0c564c..344d26678 100644 --- a/tests/DI/NeonAdapter.preprocess.phpt +++ b/tests/DI/NeonAdapter.preprocess.phpt @@ -81,3 +81,22 @@ Assert::equal( [new Statement('Class', ['arg1', 2 => ['...']])], $data ); + + +// @ escaping +$data = @$adapter->load(Tester\FileMock::create(' +- @@double +- "@@doublequoted" +- @simple +- "@simplequoted" +', 'neon')); + +Assert::equal( + [ + '@@double', + '@@doublequoted', + '@simple', + '@@simplequoted', // escaped + ], + $data +); From 10b9ef54de4bdea0b8e25073e13d044751c6e29e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 15 Dec 2021 19:41:28 +0100 Subject: [PATCH 17/44] Resolver: not() and others expect 1 parameter --- src/DI/Resolver.php | 16 ++++------------ tests/DI/Compiler.functions.phpt | 2 +- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 0f3890d25..6935df01b 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -198,12 +198,8 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo break; case $entity === 'not': - if (count($arguments) > 1) { - throw new ServiceCreationException(sprintf( - 'Function %s() expects at most 1 parameter, %s given.', - $entity, - count($arguments) - )); + if (count($arguments) !== 1) { + throw new ServiceCreationException(sprintf('Function %s() expects 1 parameter, %s given.', $entity, count($arguments))); } $entity = ['', '!']; @@ -213,12 +209,8 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo case $entity === 'int': case $entity === 'float': case $entity === 'string': - if (count($arguments) > 1) { - throw new ServiceCreationException(sprintf( - 'Function %s() expects at most 1 parameter, %s given.', - $entity, - count($arguments) - )); + if (count($arguments) !== 1) { + throw new ServiceCreationException(sprintf('Function %s() expects 1 parameter, %s given.', $entity, count($arguments))); } $arguments = [$arguments[0], $entity]; diff --git a/tests/DI/Compiler.functions.phpt b/tests/DI/Compiler.functions.phpt index b789deded..ae74a814f 100644 --- a/tests/DI/Compiler.functions.phpt +++ b/tests/DI/Compiler.functions.phpt @@ -85,4 +85,4 @@ Assert::exception(function () { services: - Service(bool(123, 10)) '); -}, Nette\InvalidStateException::class, 'Service of type Service: Function bool() expects at most 1 parameter, 2 given. (used in Service::__construct())'); +}, Nette\InvalidStateException::class, 'Service of type Service: Function bool() expects 1 parameter, 2 given. (used in Service::__construct())'); From 8ba7d09c4029f4313979b1f21ec440ad8b7f28d1 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 15 Dec 2021 21:24:34 +0100 Subject: [PATCH 18/44] Loader::save() is deprecated --- src/DI/Config/Loader.php | 5 ++--- tests/DI/PhpAdapter.phpt | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/DI/Config/Loader.php b/src/DI/Config/Loader.php index 1c56f2d47..6273a8c73 100644 --- a/src/DI/Config/Loader.php +++ b/src/DI/Config/Loader.php @@ -74,11 +74,10 @@ public function load(string $file, ?bool $merge = true): array } - /** - * Save configuration to file. - */ + /** @deprecated */ public function save(array $data, string $file): void { + trigger_error(__METHOD__ . "() is deprecated, use adapter's dump() method.", E_USER_DEPRECATED); if (file_put_contents($file, $this->getAdapter($file)->dump($data)) === false) { throw new Nette\IOException(sprintf("Cannot write file '%s'.", $file)); } diff --git a/tests/DI/PhpAdapter.phpt b/tests/DI/PhpAdapter.phpt index 5e46af9b8..682c39939 100644 --- a/tests/DI/PhpAdapter.phpt +++ b/tests/DI/PhpAdapter.phpt @@ -31,7 +31,7 @@ Assert::same([ ], $data); -$config->save($data, TEMP_FILE); +@$config->save($data, TEMP_FILE); // deprecated Assert::match(<<<'EOD' Date: Sun, 12 Sep 2021 23:09:50 +0200 Subject: [PATCH 19/44] opened 4.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7a82450d7..8a3c3d707 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "4.0-dev" } } } From c616e95bb64959e54ff7cb9adbb58766aa43968c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 31 Dec 2020 20:05:06 +0100 Subject: [PATCH 20/44] requires PHP 8.0 --- .github/workflows/coding-style.yml | 2 +- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 6 +++--- composer.json | 2 +- readme.md | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 40437ada3..00abb989e 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.2 + php-version: 8.0 coverage: none - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index b0692d716..f985b0526 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer install --no-progress --prefer-dist diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 266902db6..82b6f1861 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['7.2', '7.3', '7.4', '8.0', '8.1'] + php: ['8.0', '8.1'] fail-fast: false @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.2 + php-version: 8.0 coverage: none - run: composer update --no-progress --prefer-dist --prefer-lowest --prefer-stable @@ -49,7 +49,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer install --no-progress --prefer-dist diff --git a/composer.json b/composer.json index 8a3c3d707..b374c9024 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=7.2 <8.2", + "php": ">=8.0 <8.2", "ext-tokenizer": "*", "nette/neon": "^3.3 || ^4.0", "nette/php-generator": "^3.5.4 || ^4.0", diff --git a/readme.md b/readme.md index d68757b83..f0c9ad926 100644 --- a/readme.md +++ b/readme.md @@ -37,7 +37,7 @@ The recommended way to install is via Composer: composer require nette/di ``` -It requires PHP version 7.2 and supports PHP up to 8.1. +It requires PHP version 8.0 and supports PHP up to 8.1. Usage From e74d64823968b48e538b2d2f607829384f078577 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 16:44:22 +0100 Subject: [PATCH 21/44] composer: updated dependencies --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index b374c9024..009c46b1a 100644 --- a/composer.json +++ b/composer.json @@ -19,14 +19,14 @@ "ext-tokenizer": "*", "nette/neon": "^3.3 || ^4.0", "nette/php-generator": "^3.5.4 || ^4.0", - "nette/robot-loader": "^3.2", - "nette/schema": "^1.1", - "nette/utils": "^3.2.5" + "nette/robot-loader": "^3.3.1 || ^4.0", + "nette/schema": "^1.2.2", + "nette/utils": "^4.0" }, "require-dev": { - "nette/tester": "^2.2", - "tracy/tracy": "^2.3", - "phpstan/phpstan": "^0.12" + "nette/tester": "^2.4", + "tracy/tracy": "^2.8", + "phpstan/phpstan": "^1.0" }, "conflict": { "nette/bootstrap": "<3.0" From 69fb30da30d8d1649e85aa9cd772f5d1f9678247 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 14 Dec 2021 07:19:10 +0100 Subject: [PATCH 22/44] coding style --- src/DI/Autowiring.php | 4 +- src/DI/Compiler.php | 8 +- src/DI/CompilerExtension.php | 2 +- src/DI/Config/Adapters/NeonAdapter.php | 12 +- src/DI/Container.php | 18 ++- src/DI/ContainerBuilder.php | 4 +- src/DI/Definitions/AccessorDefinition.php | 6 +- src/DI/Definitions/Definition.php | 2 +- src/DI/Definitions/FactoryDefinition.php | 14 +-- src/DI/Definitions/ImportedDefinition.php | 2 +- src/DI/Definitions/LocatorDefinition.php | 6 +- src/DI/DependencyChecker.php | 4 +- src/DI/Extensions/DIExtension.php | 2 +- src/DI/Extensions/DecoratorExtension.php | 11 +- src/DI/Extensions/DefinitionSchema.php | 2 +- src/DI/Extensions/ExtensionsExtension.php | 2 +- src/DI/Extensions/InjectExtension.php | 10 +- src/DI/Extensions/SearchExtension.php | 16 ++- src/DI/Helpers.php | 14 +-- src/DI/Resolver.php | 36 +++--- tests/DI/Compiler.config.phpt | 6 +- tests/DI/Compiler.dependencies.phpt | 8 +- .../Compiler.dynamicParameters.validator.phpt | 2 +- tests/DI/Compiler.functions.phpt | 2 +- tests/DI/Container.dynamic.phpt | 8 +- tests/DI/Container.static-dynamic.phpt | 10 +- .../DI/ContainerBuilder.getByType.alias.phpt | 6 +- tests/DI/ContainerBuilder.getByType.phpt | 2 +- tests/DI/ContainerBuilder.metadata.phpt | 8 +- tests/DI/ContainerLoader.basic.phpt | 4 +- tests/DI/DecoratorExtension.basic.phpt | 2 +- ...Definitions.AccessorDefinition.render.phpt | 32 ++--- .../Definitions.FactoryDefinition.render.phpt | 2 +- tests/DI/Definitions.ImportedDefinition.phpt | 12 +- ...tions.LocatorDefinition.render.create.phpt | 46 ++++---- ...initions.LocatorDefinition.render.get.phpt | 46 ++++---- ...itions.LocatorDefinition.render.multi.phpt | 40 +++---- tests/DI/Helpers.escape().phpt | 2 +- tests/DI/Helpers.expand().phpt | 2 +- tests/DI/Helpers.filterArguments.phpt | 4 +- tests/DI/NeonAdapter.basic.phpt | 111 +++++++++--------- tests/DI/NeonAdapter.preprocess.phpt | 30 +++-- tests/DI/PhpAdapter.phpt | 26 ++-- tests/DI/Resolver.autowireArguments.80.phpt | 6 +- .../DI/Resolver.autowireArguments.errors.phpt | 16 +-- tests/DI/Resolver.autowireArguments.phpt | 44 +++---- 46 files changed, 317 insertions(+), 335 deletions(-) diff --git a/src/DI/Autowiring.php b/src/DI/Autowiring.php index 5a5164912..3edc55513 100644 --- a/src/DI/Autowiring.php +++ b/src/DI/Autowiring.php @@ -71,7 +71,7 @@ public function getByType(string $type, bool $throw = false): ?string throw new ServiceCreationException(sprintf( "Multiple services of type $type found: %s%s", implode(', ', $list), - $hint + $hint, )); } } @@ -133,7 +133,7 @@ public function rebuild(): void throw new ServiceCreationException(sprintf( "Incompatible class %s in autowiring definition of service '%s'.", $autowiredType, - $name + $name, )); } } diff --git a/src/DI/Compiler.php b/src/DI/Compiler.php index 35e12ed7d..17388b1f7 100644 --- a/src/DI/Compiler.php +++ b/src/DI/Compiler.php @@ -74,7 +74,7 @@ public function addExtension(?string $name, CompilerExtension $extension) throw new Nette\InvalidArgumentException(sprintf( "Name of extension '%s' has the same name as '%s' in a case-insensitive manner.", $name, - $nm + $nm, )); } } @@ -87,7 +87,7 @@ public function addExtension(?string $name, CompilerExtension $extension) public function getExtensions(?string $type = null): array { return $type - ? array_filter($this->extensions, function ($item) use ($type): bool { return $item instanceof $type; }) + ? array_filter($this->extensions, fn($item): bool => $item instanceof $type) : $this->extensions; } @@ -250,14 +250,14 @@ public function processExtensions(): void if ($extra = array_diff_key($this->extensions, $extensions, $first, [self::Services => 1])) { throw new Nette\DeprecatedException(sprintf( "Extensions '%s' were added while container was being compiled.", - implode("', '", array_keys($extra)) + implode("', '", array_keys($extra)), )); } elseif ($extra = key(array_diff_key($this->configs, $this->extensions))) { $hint = Nette\Utils\Helpers::getSuggestion(array_keys($this->extensions), $extra); throw new InvalidConfigurationException( sprintf("Found section '%s' in configuration, but corresponding extension is missing", $extra) - . ($hint ? ", did you mean '$hint'?" : '.') + . ($hint ? ", did you mean '$hint'?" : '.'), ); } } diff --git a/src/DI/CompilerExtension.php b/src/DI/CompilerExtension.php index 0523448ad..aaf61527d 100644 --- a/src/DI/CompilerExtension.php +++ b/src/DI/CompilerExtension.php @@ -95,7 +95,7 @@ public function validateConfig(array $expected, ?array $config = null, ?string $ throw new Nette\DI\InvalidConfigurationException(sprintf( "Unknown configuration option '%s\u{a0}›\u{a0}%s'", $name, - $hint ? key($extra) : implode("', '{$name}\u{a0}›\u{a0}", array_keys($extra)) + $hint ? key($extra) : implode("', '{$name}\u{a0}›\u{a0}", array_keys($extra)), ) . ($hint ? ", did you mean '{$name}\u{a0}›\u{a0}{$hint}'?" : '.')); } diff --git a/src/DI/Config/Adapters/NeonAdapter.php b/src/DI/Config/Adapters/NeonAdapter.php index 319b3791e..e5b81651d 100644 --- a/src/DI/Config/Adapters/NeonAdapter.php +++ b/src/DI/Config/Adapters/NeonAdapter.php @@ -59,7 +59,7 @@ public function process(array $arr): array throw new Nette\DI\InvalidConfigurationException(sprintf( "Replacing operator is available only for arrays, item '%s' is not array (used in '%s')", $key, - $this->file + $this->file, )); } @@ -76,7 +76,7 @@ public function process(array $arr): array foreach ($this->process($val->attributes) as $st) { $tmp = new Statement( $tmp === null ? $st->getEntity() : [$tmp, ltrim(implode('::', (array) $st->getEntity()), ':')], - $st->arguments + $st->arguments, ); } @@ -109,7 +109,7 @@ function (&$val): void { if ($val instanceof Statement) { $val = self::statementToEntity($val); } - } + }, ); return "# generated by Nette\n\n" . Neon\Neon::encode($data, Neon\Neon::BLOCK); } @@ -125,7 +125,7 @@ function (&$val): void { } elseif ($val instanceof Reference) { $val = '@' . $val->getValue(); } - } + }, ); $entity = $val->getEntity(); @@ -138,7 +138,7 @@ function (&$val): void { [ self::statementToEntity($entity[0]), new Neon\Entity('::' . $entity[1], $val->arguments), - ] + ], ); } elseif ($entity[0] instanceof Reference) { $entity = '@' . $entity[0]->getValue() . '::' . $entity[1]; @@ -161,7 +161,7 @@ public function removeUnderscoreVisitor(Neon\Node $node) $index = false; foreach ($node->attributes as $i => $attr) { if ($index) { - $attr->key = $attr->key ?? new Neon\Node\LiteralNode((string) $i); + $attr->key ??= new Neon\Node\LiteralNode((string) $i); } if ($attr->value instanceof Neon\Node\LiteralNode && $attr->value->value === '_') { diff --git a/src/DI/Container.php b/src/DI/Container.php index 09518b571..e25cbd495 100644 --- a/src/DI/Container.php +++ b/src/DI/Container.php @@ -49,7 +49,7 @@ public function __construct(array $params = []) $this->parameters = $params; $this->methods = array_flip(array_filter( get_class_methods($this), - function ($s) { return preg_match('#^createService.#', $s); } + fn($s) => preg_match('#^createService.#', $s), )); } @@ -79,7 +79,7 @@ public function addService(string $name, $service) $rt = Nette\Utils\Type::fromReflection(new \ReflectionFunction($service)); $type = $rt ? Helpers::ensureClassType($rt, 'return type of closure') : ''; } else { - $type = get_class($service); + $type = $service::class; } if (!isset($this->methods[self::getMethodName($name)])) { @@ -90,7 +90,7 @@ public function addService(string $name, $service) "Service '%s' must be instance of %s, %s.", $name, $expectedType, - $type ? "$type given" : 'add typehint to closure' + $type ? "$type given" : 'add typehint to closure', )); } @@ -222,7 +222,7 @@ public function createService(string $name, array $args = []) if (!is_object($service)) { throw new Nette\UnexpectedValueException(sprintf( "Unable to create service '$name', value returned by %s is not object.", - $cb instanceof \Closure ? 'closure' : "method $method()" + $cb instanceof \Closure ? 'closure' : "method $method()", )); } @@ -258,14 +258,14 @@ public function getByType(string $type, bool $throw = true) if (is_a($methodType, $type, true)) { throw new MissingServiceException(sprintf( "Service of type %s is not autowired or is missing in di\u{a0}›\u{a0}export\u{a0}›\u{a0}types.", - $type + $type, )); } } throw new MissingServiceException(sprintf( 'Service of type %s not found. Did you add it to configuration file?', - $type + $type, )); } @@ -355,11 +355,9 @@ public function callMethod(callable $function, array $args = []) private function autowireArguments(\ReflectionFunctionAbstract $function, array $args = []): array { - return Resolver::autowireArguments($function, $args, function (string $type, bool $single) { - return $single + return Resolver::autowireArguments($function, $args, fn(string $type, bool $single) => $single ? $this->getByType($type) - : array_map([$this, 'getService'], $this->findAutowired($type)); - }); + : array_map([$this, 'getService'], $this->findAutowired($type))); } diff --git a/src/DI/ContainerBuilder.php b/src/DI/ContainerBuilder.php index 394475fc0..506ba3c32 100644 --- a/src/DI/ContainerBuilder.php +++ b/src/DI/ContainerBuilder.php @@ -83,7 +83,7 @@ public function addDefinition(?string $name, ?Definition $definition = null): De throw new Nette\InvalidStateException(sprintf( "Service '%s' has the same name as '%s' in a case-insensitive manner.", $name, - $nm + $nm, )); } } @@ -399,7 +399,7 @@ public function exportMeta(): array public static function literal(string $code, ?array $args = null): Nette\PhpGenerator\PhpLiteral { return new Nette\PhpGenerator\PhpLiteral( - $args === null ? $code : (new Nette\PhpGenerator\Dumper)->format($code, ...$args) + $args === null ? $code : (new Nette\PhpGenerator\Dumper)->format($code, ...$args), ); } diff --git a/src/DI/Definitions/AccessorDefinition.php b/src/DI/Definitions/AccessorDefinition.php index 1cfc3561e..4ac206740 100644 --- a/src/DI/Definitions/AccessorDefinition.php +++ b/src/DI/Definitions/AccessorDefinition.php @@ -32,7 +32,7 @@ public function setImplement(string $interface) throw new Nette\InvalidArgumentException(sprintf( "Service '%s': Interface '%s' not found.", $this->getName(), - $interface + $interface, )); } @@ -48,13 +48,13 @@ public function setImplement(string $interface) throw new Nette\InvalidArgumentException(sprintf( "Service '%s': Interface %s must have just one non-static method get().", $this->getName(), - $interface + $interface, )); } elseif ($method->getNumberOfParameters()) { throw new Nette\InvalidArgumentException(sprintf( "Service '%s': Method %s::get() must have no parameters.", $this->getName(), - $interface + $interface, )); } diff --git a/src/DI/Definitions/Definition.php b/src/DI/Definitions/Definition.php index 1aaa7583d..491faa832 100644 --- a/src/DI/Definitions/Definition.php +++ b/src/DI/Definitions/Definition.php @@ -69,7 +69,7 @@ protected function setType(?string $type) throw new Nette\InvalidArgumentException(sprintf( "Service '%s': Class or interface '%s' not found.", $this->name, - $type + $type, )); } else { $this->type = Nette\DI\Helpers::normalizeClass($type); diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index d733c80ef..70a7ea5ab 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -44,7 +44,7 @@ public function setImplement(string $interface) throw new Nette\InvalidArgumentException(sprintf( "Service '%s': Interface '%s' not found.", $this->getName(), - $interface + $interface, )); } @@ -54,7 +54,7 @@ public function setImplement(string $interface) throw new Nette\InvalidArgumentException(sprintf( "Service '%s': Interface %s must have just one non-static method create().", $this->getName(), - $interface + $interface, )); } @@ -74,7 +74,7 @@ public function getImplement(): ?string } - final public function getResultType(): ?string + public function getResultType(): ?string { return $this->resultDefinition->getType(); } @@ -110,7 +110,7 @@ public function setParameters(array $params) "Service '%s': Option 'parameters' is deprecated and should be removed. The %s should be replaced with %s in configuration.", $this->getName(), implode(', ', $old), - implode(', ', $new) + implode(', ', $new), ), E_USER_DEPRECATED); } @@ -152,7 +152,7 @@ public function resolveType(Nette\DI\Resolver $resolver): void throw new ServiceCreationException(sprintf( 'Factory for %s cannot create incompatible %s type.', $type, - $resultDef->getType() + $resultDef->getType(), )); } } @@ -209,7 +209,7 @@ private function completeParameters(Nette\DI\Resolver $resolver): void "Type of \$%s in %s::create() doesn't match type in %s constructor.", $param->name, $interface, - $class + $class, )); } @@ -220,7 +220,7 @@ private function completeParameters(Nette\DI\Resolver $resolver): void throw new ServiceCreationException(sprintf( 'Unused parameter $%s when implementing method %s::create()', $param->name, - $interface + $interface, ) . ($hint ? ", did you mean \${$hint}?" : '.')); } diff --git a/src/DI/Definitions/ImportedDefinition.php b/src/DI/Definitions/ImportedDefinition.php index 2002f6f71..d05948fcf 100644 --- a/src/DI/Definitions/ImportedDefinition.php +++ b/src/DI/Definitions/ImportedDefinition.php @@ -40,7 +40,7 @@ public function generateMethod(Nette\PhpGenerator\Method $method, PhpGenerator $ $method->setReturnType('void') ->setBody( 'throw new Nette\\DI\\ServiceCreationException(?);', - ["Unable to create imported service '{$this->getName()}', it must be added using addService()"] + ["Unable to create imported service '{$this->getName()}', it must be added using addService()"], ); } diff --git a/src/DI/Definitions/LocatorDefinition.php b/src/DI/Definitions/LocatorDefinition.php index 0412ff7ab..4ead39c3e 100644 --- a/src/DI/Definitions/LocatorDefinition.php +++ b/src/DI/Definitions/LocatorDefinition.php @@ -45,7 +45,7 @@ public function setImplement(string $interface) "Service '%s': Method %s::%s() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static.", $this->getName(), $interface, - $method->name + $method->name, )); } @@ -118,7 +118,7 @@ public function complete(Nette\DI\Resolver $resolver): void "Service '%s': duplicated tag '%s' with value '%s'.", $this->getName(), $this->tagged, - $tag + $tag, ), E_USER_NOTICE); } @@ -154,7 +154,7 @@ public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGe ->setReturnType((string) Nette\Utils\Type::fromReflection($rm)); if (!$name) { - $class->addProperty('mapping', array_map(function ($item) { return $item->getValue(); }, $this->references)) + $class->addProperty('mapping', array_map(fn($item) => $item->getValue(), $this->references)) ->setPrivate(); $methodInner->setBody('if (!isset($this->mapping[$name])) { diff --git a/src/DI/DependencyChecker.php b/src/DI/DependencyChecker.php index 663543d51..fcf890064 100644 --- a/src/DI/DependencyChecker.php +++ b/src/DI/DependencyChecker.php @@ -86,7 +86,7 @@ public static function isExpired( array &$phpFiles, array $classes, array $functions, - string $hash + string $hash, ): bool { try { $currentFiles = @array_map('filemtime', array_combine($tmp = array_keys($files), $tmp)); // @ - files may not exist @@ -177,7 +177,7 @@ private static function hashParameters(\ReflectionFunctionAbstract $method): arr (string) Type::fromReflection($param), $param->isVariadic(), $param->isDefaultValueAvailable() - ? is_object($tmp = Reflection::getParameterDefaultValue($param)) ? ['object' => get_class($tmp)] : ['value' => $tmp] + ? is_object($tmp = Reflection::getParameterDefaultValue($param)) ? ['object' => $tmp::class] : ['value' => $tmp] : null, ]; } diff --git a/src/DI/Extensions/DIExtension.php b/src/DI/Extensions/DIExtension.php index 7a0b3c966..262fffb8f 100644 --- a/src/DI/Extensions/DIExtension.php +++ b/src/DI/Extensions/DIExtension.php @@ -117,7 +117,7 @@ private function restrictTypes(Nette\PhpGenerator\ClassType $class): void $prop = $class->getProperty('wiring'); $prop->setValue(array_intersect_key( $prop->getValue(), - $this->exportedTypes + (is_array($option) ? array_flip($option) : []) + $this->exportedTypes + (is_array($option) ? array_flip($option) : []), )); } diff --git a/src/DI/Extensions/DecoratorExtension.php b/src/DI/Extensions/DecoratorExtension.php index b570c3fc7..6aaa9cc27 100644 --- a/src/DI/Extensions/DecoratorExtension.php +++ b/src/DI/Extensions/DecoratorExtension.php @@ -25,7 +25,7 @@ public function getConfigSchema(): Nette\Schema\Schema 'setup' => Expect::list(), 'tags' => Expect::array(), 'inject' => Expect::bool(), - ]) + ]), ); } @@ -77,9 +77,10 @@ public function addTags(string $type, array $tags): void private function findByType(string $type): array { - return array_filter($this->getContainerBuilder()->getDefinitions(), function (Definitions\Definition $def) use ($type): bool { - return is_a($def->getType(), $type, true) - || ($def instanceof Definitions\FactoryDefinition && is_a($def->getResultType(), $type, true)); - }); + return array_filter( + $this->getContainerBuilder()->getDefinitions(), + fn(Definitions\Definition $def): bool => is_a($def->getType(), $type, true) + || ($def instanceof Definitions\FactoryDefinition && is_a($def->getResultType(), $type, true)), + ); } } diff --git a/src/DI/Extensions/DefinitionSchema.php b/src/DI/Extensions/DefinitionSchema.php index 1198598d5..4dc4812cc 100644 --- a/src/DI/Extensions/DefinitionSchema.php +++ b/src/DI/Extensions/DefinitionSchema.php @@ -123,7 +123,7 @@ public function normalize($def, Context $context) "Options '%s' and '%s' are aliases, use only '%s'.", $alias, $original, - $original + $original, )); } diff --git a/src/DI/Extensions/ExtensionsExtension.php b/src/DI/Extensions/ExtensionsExtension.php index a44456016..556c16c3b 100644 --- a/src/DI/Extensions/ExtensionsExtension.php +++ b/src/DI/Extensions/ExtensionsExtension.php @@ -38,7 +38,7 @@ public function loadConfiguration() if (!is_a($class, Nette\DI\CompilerExtension::class, true)) { throw new Nette\DI\InvalidConfigurationException(sprintf( "Extension '%s' not found or is not Nette\\DI\\CompilerExtension descendant.", - $class + $class, )); } diff --git a/src/DI/Extensions/InjectExtension.php b/src/DI/Extensions/InjectExtension.php index 47f4aca63..33b0943f7 100644 --- a/src/DI/Extensions/InjectExtension.php +++ b/src/DI/Extensions/InjectExtension.php @@ -96,11 +96,9 @@ public static function getInjectMethods(string $class): array } $methods = array_keys($classes); - uksort($classes, function (string $a, string $b) use ($classes, $methods): int { - return $classes[$a] === $classes[$b] + uksort($classes, fn(string $a, string $b): int => $classes[$a] === $classes[$b] ? array_search($a, $methods, true) <=> array_search($b, $methods, true) - : (is_a($classes[$a], $classes[$b], true) ? 1 : -1); - }); + : (is_a($classes[$a], $classes[$b], true) ? 1 : -1)); return array_keys($classes); } @@ -150,11 +148,11 @@ public static function callInjects(DI\Container $container, $service): void throw new Nette\InvalidArgumentException(sprintf('Service must be object, %s given.', gettype($service))); } - foreach (self::getInjectMethods(get_class($service)) as $method) { + foreach (self::getInjectMethods($service::class) as $method) { $container->callMethod([$service, $method]); } - foreach (self::getInjectProperties(get_class($service)) as $property => $type) { + foreach (self::getInjectProperties($service::class) as $property => $type) { $service->$property = $container->getByType($type); } } diff --git a/src/DI/Extensions/SearchExtension.php b/src/DI/Extensions/SearchExtension.php index 34b6daea1..119e3363a 100644 --- a/src/DI/Extensions/SearchExtension.php +++ b/src/DI/Extensions/SearchExtension.php @@ -48,12 +48,10 @@ public function getConfigSchema(): Nette\Schema\Schema 'implements' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]), ]), 'tags' => Expect::array(), - ]) - )->before(function ($val) { - return is_string($val['in'] ?? null) + ]), + )->before(fn($val) => is_string($val['in'] ?? null) ? ['default' => $val] - : $val; - }); + : $val); } @@ -65,7 +63,7 @@ public function loadConfiguration() "Option '%s\u{a0}›\u{a0}%s\u{a0}›\u{a0}in' must be valid directory name, '%s' given.", $this->name, $name, - $batch->in + $batch->in, )); } @@ -97,7 +95,7 @@ public function findClasses(\stdClass $config): array if (!class_exists($class) && !interface_exists($class) && !trait_exists($class)) { throw new Nette\InvalidStateException(sprintf( 'Class %s was found, but it cannot be loaded by autoloading.', - $class + $class, )); } @@ -111,8 +109,8 @@ public function findClasses(\stdClass $config): array ) && (!$acceptRE || preg_match($acceptRE, $rc->name)) && (!$rejectRE || !preg_match($rejectRE, $rc->name)) - && (!$acceptParent || Arrays::some($acceptParent, function ($nm) use ($rc) { return $rc->isSubclassOf($nm); })) - && (!$rejectParent || Arrays::every($rejectParent, function ($nm) use ($rc) { return !$rc->isSubclassOf($nm); })) + && (!$acceptParent || Arrays::some($acceptParent, fn($nm) => $rc->isSubclassOf($nm))) + && (!$rejectParent || Arrays::every($rejectParent, fn($nm) => !$rc->isSubclassOf($nm))) ) { $found[] = $rc->name; } diff --git a/src/DI/Helpers.php b/src/DI/Helpers.php index 4d7f09509..a3452f7c5 100644 --- a/src/DI/Helpers.php +++ b/src/DI/Helpers.php @@ -66,7 +66,7 @@ public static function expand($var, array $params, $recursive = false) } elseif (isset($recursive[$part])) { throw new Nette\InvalidArgumentException(sprintf( 'Circular reference detected for variables: %s.', - implode(', ', array_keys($recursive)) + implode(', ', array_keys($recursive)), )); } else { @@ -100,12 +100,10 @@ public static function expand($var, array $params, $recursive = false) } if ($php) { - $res = array_filter($res, function ($val): bool { return $val !== ''; }); - $res = array_map(function ($val): string { - return $val instanceof DynamicParameter + $res = array_filter($res, fn($val): bool => $val !== ''); + $res = array_map(fn($val): string => $val instanceof DynamicParameter ? "($val)" - : var_export((string) $val, true); - }, $res); + : var_export((string) $val, true), $res); return new DynamicParameter(implode(' . ', $res)); } @@ -183,7 +181,7 @@ public static function prefixServiceName($config, string $namespace) } elseif ($config instanceof Statement) { return new Statement( self::prefixServiceName($config->getEntity(), $namespace), - self::prefixServiceName($config->arguments, $namespace) + self::prefixServiceName($config->arguments, $namespace), ); } elseif (is_array($config)) { foreach ($config as &$val) { @@ -277,7 +275,7 @@ public static function convertType($value, string $type) throw new Nette\InvalidStateException(sprintf( 'Cannot convert %s to %s.', is_scalar($value) ? "'$value'" : gettype($value), - $type + $type, )); } } diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 6935df01b..114cee201 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -61,7 +61,7 @@ public function getContainerBuilder(): ContainerBuilder public function resolveDefinition(Definition $def): void { if ($this->recursive->contains($def)) { - $names = array_map(function ($item) { return $item->getName(); }, iterator_to_array($this->recursive)); + $names = array_map(fn($item) => $item->getName(), iterator_to_array($this->recursive)); throw new ServiceCreationException(sprintf('Circular reference detected for services: %s.', implode(', ', $names))); } @@ -149,7 +149,7 @@ public function resolveEntityType(Statement $statement): ?string interface_exists($entity) ? "Interface %s can not be used as 'create' or 'factory', did you mean 'implement'?" : "Class '%s' not found.", - $entity + $entity, )); } @@ -187,11 +187,9 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo $this->currentServiceAllowed = $currentServiceAllowed; $entity = $this->normalizeEntity($statement); $arguments = $this->convertReferences($statement->arguments); - $getter = function (string $type, bool $single) { - return $single + $getter = fn(string $type, bool $single) => $single ? $this->getByType($type) - : array_values(array_filter($this->builder->findAutowired($type), function ($obj) { return $obj !== $this->currentService; })); - }; + : array_values(array_filter($this->builder->findAutowired($type), fn($obj) => $obj !== $this->currentService)); switch (true) { case is_string($entity) && Strings::contains($entity, '?'): // PHP literal @@ -230,7 +228,7 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo } elseif ($arguments) { throw new ServiceCreationException(sprintf( 'Unable to pass arguments, class %s has no constructor.', - $entity + $entity, )); } @@ -244,7 +242,7 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo if (!preg_match('#^\$?(\\\\?' . PhpHelpers::PHP_IDENT . ')+(\[\])?$#D', $entity[1])) { throw new ServiceCreationException(sprintf( "Expected function, method or property name, '%s' given.", - $entity[1] + $entity[1], )); } @@ -253,7 +251,7 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo if (!Nette\Utils\Arrays::isList($arguments)) { throw new ServiceCreationException(sprintf( 'Unable to pass specified arguments to %s.', - $entity[0] + $entity[0], )); } elseif (!function_exists($entity[1])) { throw new ServiceCreationException(sprintf("Function %s doesn't exist.", $entity[1])); @@ -526,7 +524,7 @@ private function convertReferences(array $arguments): array public static function autowireArguments( \ReflectionFunctionAbstract $method, array $arguments, - callable $getter + callable $getter, ): array { $optCount = 0; $useName = false; @@ -542,7 +540,7 @@ public static function autowireArguments( throw new ServiceCreationException(sprintf( 'Parameter %s must be array, %s given.', Reflection::toString($param), - gettype($arguments[$paramName]) + gettype($arguments[$paramName]), )); } @@ -613,7 +611,7 @@ public static function autowireArguments( if ($arguments) { throw new ServiceCreationException(sprintf( 'Unable to pass specified arguments to %s.', - Reflection::toString($method) + Reflection::toString($method), )); } elseif ($optCount) { $res = array_slice($res, 0, -$optCount); @@ -635,13 +633,13 @@ private static function autowireArgument(\ReflectionParameter $parameter, callab $desc = Reflection::toString($parameter); $type = Nette\Utils\Type::fromReflection($parameter); - if ($type && $type->isIntersection()) { + if ($type?->isIntersection()) { throw new ServiceCreationException(sprintf( 'Parameter %s has intersection type, so its value must be specified.', - $desc + $desc, )); - } elseif ($type && $type->isClass()) { + } elseif ($type?->isClass()) { $class = $type->getSingleName(); try { $res = $getter($class, true); @@ -657,18 +655,18 @@ private static function autowireArgument(\ReflectionParameter $parameter, callab throw new ServiceCreationException(sprintf( 'Service of type %s required by %s not found. Did you add it to configuration file?', $class, - $desc + $desc, )); } else { throw new ServiceCreationException(sprintf( "Class '%s' required by %s not found. Check the parameter type and 'use' statements.", $class, - $desc + $desc, )); } } elseif ( $method instanceof \ReflectionMethod - && $type && $type->getSingleName() === 'array' + && $type?->getSingleName() === 'array' && preg_match('#@param[ \t]+(?|([\w\\\\]+)\[\]|array)[ \t]+\$' . $parameter->name . '#', (string) $method->getDocComment(), $m) && ($itemType = Reflection::expandClassName($m[1], $method->getDeclaringClass())) && (class_exists($itemType) || interface_exists($itemType)) @@ -690,7 +688,7 @@ private static function autowireArgument(\ReflectionParameter $parameter, callab throw new ServiceCreationException(sprintf( 'Parameter %s has %s, so its value must be specified.', $desc, - $type && $type->isUnion() ? 'union type and no default value' : 'no class type or default value' + $type?->isUnion() ? 'union type and no default value' : 'no class type or default value', )); } } diff --git a/tests/DI/Compiler.config.phpt b/tests/DI/Compiler.config.phpt index bcd1a7b03..26f804d62 100644 --- a/tests/DI/Compiler.config.phpt +++ b/tests/DI/Compiler.config.phpt @@ -17,7 +17,7 @@ test('Compiler config', function () { Assert::same( [], - $compiler->getConfig() + $compiler->getConfig(), ); $compiler->addConfig([ @@ -34,7 +34,7 @@ test('Compiler config', function () { ], 'services' => [], ], - $compiler->getConfig() + $compiler->getConfig(), ); }); @@ -55,6 +55,6 @@ parameters: Assert::same( ['php', 'node'], - $compiler->getConfig()['parameters']['languages'] + $compiler->getConfig()['parameters']['languages'], ); }); diff --git a/tests/DI/Compiler.dependencies.phpt b/tests/DI/Compiler.dependencies.phpt index 6fe0e5169..d71c2914b 100644 --- a/tests/DI/Compiler.dependencies.phpt +++ b/tests/DI/Compiler.dependencies.phpt @@ -24,7 +24,7 @@ Assert::same( [], '40cd750bba9870f18aada2478b24840a', ], - $compiler->exportDependencies() + $compiler->exportDependencies(), ); Assert::false(DependencyChecker::isExpired(...$compiler->exportDependencies())); @@ -39,7 +39,7 @@ Assert::same( [], '40cd750bba9870f18aada2478b24840a', ], - $compiler->exportDependencies() + $compiler->exportDependencies(), ); Assert::false(DependencyChecker::isExpired(...$compiler->exportDependencies())); @@ -54,7 +54,7 @@ Assert::same( [], '40cd750bba9870f18aada2478b24840a', ], - $compiler->exportDependencies() + $compiler->exportDependencies(), ); $res = $compiler->exportDependencies(); @@ -77,7 +77,7 @@ if (PHP_VERSION_ID >= 80100) { [], 'ff31f9bba26681aa5b228503003778cc', ], - $compiler->exportDependencies() + $compiler->exportDependencies(), ); Assert::false(DependencyChecker::isExpired(...$compiler->exportDependencies())); diff --git a/tests/DI/Compiler.dynamicParameters.validator.phpt b/tests/DI/Compiler.dynamicParameters.validator.phpt index 0d6cb4eb7..efd4f208b 100644 --- a/tests/DI/Compiler.dynamicParameters.validator.phpt +++ b/tests/DI/Compiler.dynamicParameters.validator.phpt @@ -18,7 +18,7 @@ class FooExtension extends Nette\DI\CompilerExtension Expect::structure([ 'string' => Expect::string()->dynamic(), 'intnull' => Expect::int()->nullable()->dynamic(), - ]) + ]), ); } } diff --git a/tests/DI/Compiler.functions.phpt b/tests/DI/Compiler.functions.phpt index ae74a814f..dfc4aaca1 100644 --- a/tests/DI/Compiler.functions.phpt +++ b/tests/DI/Compiler.functions.phpt @@ -67,7 +67,7 @@ Assert::same( 'int' => [0, 1, 231, 123], 'float' => [0.0, 1.0, 231.0, 123.0], ], - $obj->args + $obj->args, ); Assert::exception(function () use ($container) { diff --git a/tests/DI/Container.dynamic.phpt b/tests/DI/Container.dynamic.phpt index 827c5d475..2f71ed403 100644 --- a/tests/DI/Container.dynamic.phpt +++ b/tests/DI/Container.dynamic.phpt @@ -40,9 +40,7 @@ test('', function () use ($container) { test('closure', function () use ($container) { - @$container->addService('four', function () { // @ triggers service should be defined as "imported" - return new Service; - }); + @$container->addService('four', fn() => new Service); Assert::true($container->hasService('four')); Assert::false($container->isCreated('four')); @@ -55,9 +53,7 @@ test('closure', function () use ($container) { test('closure with typehint', function () use ($container) { - @$container->addService('five', function (): Service { // @ triggers service should be defined as "imported" - return new Service; - }); + @$container->addService('five', fn(): Service => new Service); Assert::same(Service::class, $container->getServiceType('five')); }); diff --git a/tests/DI/Container.static-dynamic.phpt b/tests/DI/Container.static-dynamic.phpt index 7d9e2a40d..1fde5b2c3 100644 --- a/tests/DI/Container.static-dynamic.phpt +++ b/tests/DI/Container.static-dynamic.phpt @@ -46,7 +46,7 @@ test('', function () { test('closure', function () { $container = new MyContainer; - $container->addService('one', function () { return new stdClass; }); + $container->addService('one', fn() => new stdClass); Assert::true($container->hasService('one')); Assert::same('', $container->getServiceType('one')); @@ -58,7 +58,7 @@ test('closure', function () { test('closure & typehint', function () { $container = new MyContainer; - $container->addService('one', function (): stdClass { return new stdClass; }); + $container->addService('one', fn(): stdClass => new stdClass); Assert::same(stdClass::class, $container->getServiceType('one')); Assert::true($container->hasService('one')); @@ -73,7 +73,7 @@ test('closure & matching typehint', function () { { } - $container->addService('typehint', function (): MyClass { return new MyClass; }); + $container->addService('typehint', fn(): MyClass => new MyClass); Assert::same(MyClass::class, $container->getServiceType('typehint')); Assert::true($container->hasService('typehint')); @@ -83,11 +83,11 @@ test('closure & matching typehint', function () { Assert::exception(function () { // closure & wrong typehint $container = new MyContainer; - $container->addService('typehint', function () { return new DateTime; }); + $container->addService('typehint', fn() => new DateTime); }, Nette\InvalidArgumentException::class, "Service 'typehint' must be instance of stdClass, add typehint to closure."); Assert::exception(function () { // closure & wrong typehint $container = new MyContainer; - $container->addService('typehint', function (): DateTime { return new DateTime; }); + $container->addService('typehint', fn(): DateTime => new DateTime); }, Nette\InvalidArgumentException::class, "Service 'typehint' must be instance of stdClass, DateTime given."); diff --git a/tests/DI/ContainerBuilder.getByType.alias.phpt b/tests/DI/ContainerBuilder.getByType.alias.phpt index d3ed77234..a9a5aade0 100644 --- a/tests/DI/ContainerBuilder.getByType.alias.phpt +++ b/tests/DI/ContainerBuilder.getByType.alias.phpt @@ -39,15 +39,15 @@ Assert::exception(function () use ($builder) { Assert::same( ['one' => $builder->getDefinition('one'), 'two' => $builder->getDefinition('two')], - $builder->findByType(Service::class) + $builder->findByType(Service::class), ); Assert::same( ['one' => $builder->getDefinition('one'), 'two' => $builder->getDefinition('two')], - $builder->findByType(Alias::class) + $builder->findByType(Alias::class), ); Assert::same( ['one' => $builder->getDefinition('one'), 'two' => $builder->getDefinition('two')], - $builder->findByType('\service') + $builder->findByType('\service'), ); diff --git a/tests/DI/ContainerBuilder.getByType.phpt b/tests/DI/ContainerBuilder.getByType.phpt index 511b9d46c..89adb773d 100644 --- a/tests/DI/ContainerBuilder.getByType.phpt +++ b/tests/DI/ContainerBuilder.getByType.phpt @@ -73,6 +73,6 @@ Assert::same([ Assert::same( ['two' => $builder->getDefinition('two'), 'three' => $builder->getDefinition('three')], - $builder->findByType(Service2::class) + $builder->findByType(Service2::class), ); Assert::same([], $builder->findByType('unknown')); diff --git a/tests/DI/ContainerBuilder.metadata.phpt b/tests/DI/ContainerBuilder.metadata.phpt index b293ff6c2..30e75cd74 100644 --- a/tests/DI/ContainerBuilder.metadata.phpt +++ b/tests/DI/ContainerBuilder.metadata.phpt @@ -38,12 +38,12 @@ Assert::same( Nette\DI\Container::class => [['container']], stdClass::class => [['lorem']], ], - getPropertyValue($container, 'wiring') + getPropertyValue($container, 'wiring'), ); Assert::same( ['container' => Nette\DI\Container::class], - getPropertyValue($container, 'types') + getPropertyValue($container, 'types'), ); Assert::same( @@ -52,12 +52,12 @@ Assert::same( 'b' => ['lorem' => 'c'], 'd' => ['lorem' => ['e']], ], - getPropertyValue($container, 'tags') + getPropertyValue($container, 'tags'), ); Assert::same( [], - getPropertyValue($container, 'aliases') + getPropertyValue($container, 'aliases'), ); Assert::same(['lorem' => true], $container->findByTag('a')); diff --git a/tests/DI/ContainerLoader.basic.phpt b/tests/DI/ContainerLoader.basic.phpt index 7b1a92aa1..9f75a0b5f 100644 --- a/tests/DI/ContainerLoader.basic.phpt +++ b/tests/DI/ContainerLoader.basic.phpt @@ -19,9 +19,7 @@ $key = [1, 2]; $className = $cache->getClassName($key); Assert::match('Container%[\w]+%', $className); -$container = $cache->load(function () use ($className) { - return "class $className {}"; -}, $key); +$container = $cache->load(fn() => "class $className {}", $key); Assert::type($className, new $container); $container = $cache->load(function () {}, 'key2'); diff --git a/tests/DI/DecoratorExtension.basic.phpt b/tests/DI/DecoratorExtension.basic.phpt index 8747145a9..08667d50e 100644 --- a/tests/DI/DecoratorExtension.basic.phpt +++ b/tests/DI/DecoratorExtension.basic.phpt @@ -78,7 +78,7 @@ $builder = $compiler->getContainerBuilder(); Assert::same( ['a' => true, 'tag' => 2, DI\Extensions\InjectExtension::TAG_INJECT => true, 'Iface' => true], - $builder->getDefinition('one')->getTags() + $builder->getDefinition('one')->getTags(), ); Assert::true($builder->getDefinition('one')->getTag(DI\Extensions\InjectExtension::TAG_INJECT)); diff --git a/tests/DI/Definitions.AccessorDefinition.render.phpt b/tests/DI/Definitions.AccessorDefinition.render.phpt index 758e32613..e0f3e9884 100644 --- a/tests/DI/Definitions.AccessorDefinition.render.phpt +++ b/tests/DI/Definitions.AccessorDefinition.render.phpt @@ -36,26 +36,26 @@ test('', function () { Assert::match( <<<'XX' -public function createServiceAbc(): Good2 -{ - return new class ($this) implements Good2 { - private $container; + public function createServiceAbc(): Good2 + { + return new class ($this) implements Good2 { + private $container; - public function __construct($container) - { - $this->container = $container; - } + public function __construct($container) + { + $this->container = $container; + } - public function get(): stdClass - { - return $this->container->getService('a'); - } - }; -} -XX + public function get(): stdClass + { + return $this->container->getService('a'); + } + }; + } + XX , - $method->__toString() + $method->__toString(), ); }); diff --git a/tests/DI/Definitions.FactoryDefinition.render.phpt b/tests/DI/Definitions.FactoryDefinition.render.phpt index 146da0eeb..b4b10e331 100644 --- a/tests/DI/Definitions.FactoryDefinition.render.phpt +++ b/tests/DI/Definitions.FactoryDefinition.render.phpt @@ -53,6 +53,6 @@ test('', function () { } }; }', - $method->__toString() + $method->__toString(), ); }); diff --git a/tests/DI/Definitions.ImportedDefinition.phpt b/tests/DI/Definitions.ImportedDefinition.phpt index 1ff490e4e..0bc96250a 100644 --- a/tests/DI/Definitions.ImportedDefinition.phpt +++ b/tests/DI/Definitions.ImportedDefinition.phpt @@ -42,12 +42,12 @@ test('', function () { Assert::match( <<<'XX' -public function createServiceAbc(): void -{ - throw new Nette\DI\ServiceCreationException('Unable to create imported service \'abc\', it must be added using addService()'); -} -XX + public function createServiceAbc(): void + { + throw new Nette\DI\ServiceCreationException('Unable to create imported service \'abc\', it must be added using addService()'); + } + XX , - $method->__toString() + $method->__toString(), ); }); diff --git a/tests/DI/Definitions.LocatorDefinition.render.create.phpt b/tests/DI/Definitions.LocatorDefinition.render.create.phpt index 2550d0611..f10b438b5 100644 --- a/tests/DI/Definitions.LocatorDefinition.render.create.phpt +++ b/tests/DI/Definitions.LocatorDefinition.render.create.phpt @@ -37,30 +37,30 @@ test('', function () { Assert::match( <<<'XX' -public function createServiceAbc(): Good -{ - return new class ($this) implements Good { - private $container;%A?% - private $mapping = ['first' => 'a', 'second' => 'a']; - - - public function __construct($container) - { - $this->container = $container; - } - - - public function create($name): stdClass - { - if (!isset($this->mapping[$name])) { - throw new Nette\DI\MissingServiceException("Service '$name' is not defined."); + public function createServiceAbc(): Good + { + return new class ($this) implements Good { + private $container;%A?% + private $mapping = ['first' => 'a', 'second' => 'a']; + + + public function __construct($container) + { + $this->container = $container; + } + + + public function create($name): stdClass + { + if (!isset($this->mapping[$name])) { + throw new Nette\DI\MissingServiceException("Service '$name' is not defined."); + } + return $this->container->createService($this->mapping[$name]); + } + }; } - return $this->container->createService($this->mapping[$name]); - } - }; -} -XX + XX , - $method->__toString() + $method->__toString(), ); }); diff --git a/tests/DI/Definitions.LocatorDefinition.render.get.phpt b/tests/DI/Definitions.LocatorDefinition.render.get.phpt index e12b207f2..1ef788f3e 100644 --- a/tests/DI/Definitions.LocatorDefinition.render.get.phpt +++ b/tests/DI/Definitions.LocatorDefinition.render.get.phpt @@ -37,30 +37,30 @@ test('', function () { Assert::match( <<<'XX' -public function createServiceAbc(): Good -{ - return new class ($this) implements Good { - private $container;%A?% - private $mapping = ['first' => 'a', 'second' => 'a']; - - - public function __construct($container) - { - $this->container = $container; - } - - - public function get($name): stdClass - { - if (!isset($this->mapping[$name])) { - throw new Nette\DI\MissingServiceException("Service '$name' is not defined."); + public function createServiceAbc(): Good + { + return new class ($this) implements Good { + private $container;%A?% + private $mapping = ['first' => 'a', 'second' => 'a']; + + + public function __construct($container) + { + $this->container = $container; + } + + + public function get($name): stdClass + { + if (!isset($this->mapping[$name])) { + throw new Nette\DI\MissingServiceException("Service '$name' is not defined."); + } + return $this->container->getService($this->mapping[$name]); + } + }; } - return $this->container->getService($this->mapping[$name]); - } - }; -} -XX + XX , - $method->__toString() + $method->__toString(), ); }); diff --git a/tests/DI/Definitions.LocatorDefinition.render.multi.phpt b/tests/DI/Definitions.LocatorDefinition.render.multi.phpt index 036048d66..5b24175a5 100644 --- a/tests/DI/Definitions.LocatorDefinition.render.multi.phpt +++ b/tests/DI/Definitions.LocatorDefinition.render.multi.phpt @@ -39,32 +39,32 @@ test('', function () { Assert::match( <<<'XX' -public function createServiceAbc(): Good -{ - return new class ($this) implements Good { - private $container; + public function createServiceAbc(): Good + { + return new class ($this) implements Good { + private $container; - public function __construct($container) - { - $this->container = $container; - } + public function __construct($container) + { + $this->container = $container; + } - public function createFirst(): stdClass - { - return $this->container->createServiceA(); - } + public function createFirst(): stdClass + { + return $this->container->createServiceA(); + } - public function getSecond(): ?stdClass - { - return $this->container->getService('a'); - } - }; -} -XX + public function getSecond(): ?stdClass + { + return $this->container->getService('a'); + } + }; + } + XX , - $method->__toString() + $method->__toString(), ); }); diff --git a/tests/DI/Helpers.escape().phpt b/tests/DI/Helpers.escape().phpt index 522946581..86a92be96 100644 --- a/tests/DI/Helpers.escape().phpt +++ b/tests/DI/Helpers.escape().phpt @@ -19,5 +19,5 @@ Assert::same('@@', Helpers::escape('@')); Assert::same('x@', Helpers::escape('x@')); Assert::same( ['key1' => '%%', 'key2' => '@@', '%%a%%' => 123, '@' => 123], - Helpers::escape(['key1' => '%', 'key2' => '@', '%a%' => 123, '@' => 123]) + Helpers::escape(['key1' => '%', 'key2' => '@', '%a%' => 123, '@' => 123]), ); diff --git a/tests/DI/Helpers.expand().phpt b/tests/DI/Helpers.expand().phpt index a515d5719..90aef87cf 100644 --- a/tests/DI/Helpers.expand().phpt +++ b/tests/DI/Helpers.expand().phpt @@ -30,7 +30,7 @@ Assert::same( Helpers::expand('%keyA%', [ 'keyA' => ['key1' => 123, 'key2' => '%keyB%'], 'keyB' => 'abc', - ], true) + ], true), ); Assert::equal(new PhpLiteral('func()'), Helpers::expand('%key%', ['key' => new PhpLiteral('func()')])); diff --git a/tests/DI/Helpers.filterArguments.phpt b/tests/DI/Helpers.filterArguments.phpt index 4976abb79..44c0320cd 100644 --- a/tests/DI/Helpers.filterArguments.phpt +++ b/tests/DI/Helpers.filterArguments.phpt @@ -18,12 +18,12 @@ Assert::same([], Helpers::filterArguments([])); Assert::same( ['a', 'b', Nette\DI\ContainerBuilder::THIS_CONTAINER], - Helpers::filterArguments(['a', 'b', 'Nette\DI\ContainerBuilder::THIS_CONTAINER']) + Helpers::filterArguments(['a', 'b', 'Nette\DI\ContainerBuilder::THIS_CONTAINER']), ); Assert::equal( ['a', 'b', new Nette\DI\Definitions\Reference('service')], - Helpers::filterArguments(['a', 'b', '@service']) + Helpers::filterArguments(['a', 'b', '@service']), ); Assert::equal( diff --git a/tests/DI/NeonAdapter.basic.phpt b/tests/DI/NeonAdapter.basic.phpt index 18a2d67d2..92a8eb833 100644 --- a/tests/DI/NeonAdapter.basic.phpt +++ b/tests/DI/NeonAdapter.basic.phpt @@ -12,59 +12,58 @@ $adapter = new NeonAdapter; $data = $adapter->load('files/neonAdapter.neon'); Assert::match(<<<'EOD' -# generated by Nette - -parameters: - type: Ipsum - -services: - referencedService: @one - referencedServiceWithSetup: - factory: @one - setup: - - $x(10) - - serviceAsParam: Ipsum(@one) - calledService: @one() - calledServiceWithArgs: @one(1) - calledServiceAsParam: Ipsum(@one()) - calledServiceWithArgsAsParam: Ipsum(@one(1)) - one: - type: %class% - arguments: - - 1 - - two: - factory: %class%(1) - - three: - type: Lorem - factory: Factory::createLorem - arguments: - - 1 - - four: - factory: Factory::createLorem(1) - - five: - factory: Factory::createLorem(1) - - six: Factory::createLorem(1) - seven: @factory - eight: @factory() - nine: - - @three - - foo - - stdClass: stdClass - factory: Lorem - rich1: Lorem(1)::foo() - rich2: - factory: Lorem(Ipsum(@one))::foo(1) - - rich3: Factory::createLorem(1)::foo() - rich4: Factory()::createLorem(1)::foo() - - Lorem(1)::foo() - -EOD -, $adapter->dump($data)); + # generated by Nette + + parameters: + type: Ipsum + + services: + referencedService: @one + referencedServiceWithSetup: + factory: @one + setup: + - $x(10) + + serviceAsParam: Ipsum(@one) + calledService: @one() + calledServiceWithArgs: @one(1) + calledServiceAsParam: Ipsum(@one()) + calledServiceWithArgsAsParam: Ipsum(@one(1)) + one: + type: %class% + arguments: + - 1 + + two: + factory: %class%(1) + + three: + type: Lorem + factory: Factory::createLorem + arguments: + - 1 + + four: + factory: Factory::createLorem(1) + + five: + factory: Factory::createLorem(1) + + six: Factory::createLorem(1) + seven: @factory + eight: @factory() + nine: + - @three + - foo + + stdClass: stdClass + factory: Lorem + rich1: Lorem(1)::foo() + rich2: + factory: Lorem(Ipsum(@one))::foo(1) + + rich3: Factory::createLorem(1)::foo() + rich4: Factory()::createLorem(1)::foo() + - Lorem(1)::foo() + + EOD, $adapter->dump($data)); diff --git a/tests/DI/NeonAdapter.preprocess.phpt b/tests/DI/NeonAdapter.preprocess.phpt index 344d26678..89552d5bc 100644 --- a/tests/DI/NeonAdapter.preprocess.phpt +++ b/tests/DI/NeonAdapter.preprocess.phpt @@ -25,25 +25,24 @@ Assert::equal([ new Statement('ent', [2]), 'inner', ], - [3, 4] + [3, 4], ), new Statement( [ new Statement('ent', [3]), 'inner', ], - [5] + [5], ), ], $data); Assert::match(<<<'EOD' -# generated by Nette + # generated by Nette -- ent(1) -- ent(2)::inner(3, 4) -- ent(3)::inner(5) -EOD -, $adapter->dump($data)); + - ent(1) + - ent(2)::inner(3, 4) + - ent(3)::inner(5) + EOD, $adapter->dump($data)); // references @@ -53,12 +52,11 @@ $data = [ ]; Assert::match(<<<'EOD' -# generated by Nette + # generated by Nette -a: @foo::method(@bar) -b: @foo() -EOD -, $adapter->dump($data)); + a: @foo::method(@bar) + b: @foo() + EOD, $adapter->dump($data)); // _ @@ -68,7 +66,7 @@ $data = $adapter->load(Tester\FileMock::create(' Assert::equal( [new Statement('Class', ['arg1', 2 => ['_']])], - $data + $data, ); @@ -79,7 +77,7 @@ $data = @$adapter->load(Tester\FileMock::create(' Assert::equal( [new Statement('Class', ['arg1', 2 => ['...']])], - $data + $data, ); @@ -98,5 +96,5 @@ Assert::equal( '@simple', '@@simplequoted', // escaped ], - $data + $data, ); diff --git a/tests/DI/PhpAdapter.phpt b/tests/DI/PhpAdapter.phpt index 682c39939..909d4c68d 100644 --- a/tests/DI/PhpAdapter.phpt +++ b/tests/DI/PhpAdapter.phpt @@ -33,18 +33,18 @@ Assert::same([ @$config->save($data, TEMP_FILE); // deprecated Assert::match(<<<'EOD' - 'the example', - 'database' => [ - 'adapter' => 'pdo_mysql', - 'params' => [ - 'host' => 'db.example.com', - 'username' => 'dbuser', - 'password' => '*secret*', - 'dbname' => 'dbname', + 'the example', + 'database' => [ + 'adapter' => 'pdo_mysql', + 'params' => [ + 'host' => 'db.example.com', + 'username' => 'dbuser', + 'password' => '*secret*', + 'dbname' => 'dbname', + ], ], - ], -]; -EOD + ]; + EOD , file_get_contents(TEMP_FILE)); diff --git a/tests/DI/Resolver.autowireArguments.80.phpt b/tests/DI/Resolver.autowireArguments.80.phpt index c6e35bf3c..9fb463c2e 100644 --- a/tests/DI/Resolver.autowireArguments.80.phpt +++ b/tests/DI/Resolver.autowireArguments.80.phpt @@ -23,7 +23,7 @@ Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function (stdClass|Test $x) {}), [], - function () {} + function () {}, ); }, Nette\InvalidStateException::class, 'Parameter $x in {closure}() has union type and no default value, so its value must be specified.'); @@ -32,7 +32,7 @@ Assert::error(function () { Resolver::autowireArguments( new ReflectionFunction(function (stdClass|Test|null $x) {}), [], - function () {} + function () {}, ); }, E_USER_DEPRECATED, 'The parameter $x in {closure}() should have a declared value in the configuration.'); @@ -42,7 +42,7 @@ Assert::same( Resolver::autowireArguments( new ReflectionFunction(function (stdClass|int $x = 1) {}), [], - function () {} + function () {}, ), ); diff --git a/tests/DI/Resolver.autowireArguments.errors.phpt b/tests/DI/Resolver.autowireArguments.errors.phpt index 45805f402..4b6bc3461 100644 --- a/tests/DI/Resolver.autowireArguments.errors.phpt +++ b/tests/DI/Resolver.autowireArguments.errors.phpt @@ -18,7 +18,7 @@ Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function (stdClass $x) {}), [], - function () {} + function () {}, ); }, Nette\DI\ServiceCreationException::class, 'Service of type stdClass required by $x in {closure}() not found. Did you add it to configuration file?'); @@ -28,7 +28,7 @@ Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function (Foo $x) {}), [], - function () {} + function () {}, ); }, Nette\DI\ServiceCreationException::class, "Class 'Foo' required by \$x in {closure}() not found. Check the parameter type and 'use' statements."); @@ -38,7 +38,7 @@ Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function ($x) {}), [], - function () {} + function () {}, ); }, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}() has no class type or default value, so its value must be specified.'); @@ -48,7 +48,7 @@ Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function (int $x) {}), [], - function () {} + function () {}, ); }, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}() has no class type or default value, so its value must be specified.'); @@ -58,7 +58,7 @@ Assert::error(function () { Resolver::autowireArguments( new ReflectionFunction(function (?stdClass $arg) {}), [], - function ($type) { return $type === Test::class ? new Test : null; } + fn($type) => $type === Test::class ? new Test : null, ); }, E_USER_DEPRECATED, 'The parameter $arg in {closure}() should have a declared value in the configuration.'); @@ -68,7 +68,7 @@ Assert::error(function () { Resolver::autowireArguments( new ReflectionFunction(function (?int $arg) {}), [], - function ($type) { return $type === Test::class ? new Test : null; } + fn($type) => $type === Test::class ? new Test : null, ); }, E_USER_DEPRECATED, 'The parameter $arg in {closure}() should have a declared value in the configuration.'); @@ -78,7 +78,7 @@ Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function (...$args) {}), [1, 'args' => []], - function () {} + function () {}, ); }, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}().'); @@ -88,6 +88,6 @@ Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function (...$args) {}), ['args' => [], 1], - function () {} + function () {}, ); }, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}().'); diff --git a/tests/DI/Resolver.autowireArguments.phpt b/tests/DI/Resolver.autowireArguments.phpt index 40b1fb93f..3eb11e334 100644 --- a/tests/DI/Resolver.autowireArguments.phpt +++ b/tests/DI/Resolver.autowireArguments.phpt @@ -24,8 +24,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function (Test $arg) {}), [], - function ($type) { return $type === Test::class ? new Test : null; } - ) + fn($type) => $type === Test::class ? new Test : null, + ), ); // nullable class @@ -34,8 +34,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function (?Test $arg) {}), [], - function ($type) { return $type === Test::class ? new Test : null; } - ) + fn($type) => $type === Test::class ? new Test : null, + ), ); // nullable optional class @@ -44,8 +44,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function (?Test $arg = null) {}), [], - function ($type) { return $type === Test::class ? new Test : null; } - ) + fn($type) => $type === Test::class ? new Test : null, + ), ); // nullable optional scalar @@ -54,8 +54,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function (?int $arg = null) {}), [], - function ($type) { return $type === Test::class ? new Test : null; } - ) + fn($type) => $type === Test::class ? new Test : null, + ), ); // optional arguments + positional @@ -64,8 +64,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function ($a = 1, $b = 2) {}), [1 => 'new'], - function () {} - ) + function () {}, + ), ); // optional arguments + named @@ -74,8 +74,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function ($a = 1, $b = 2) {}), ['b' => 'new'], - function () {} - ) + function () {}, + ), ); // optional arguments + variadics @@ -84,8 +84,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function ($a = 1, ...$args) {}), [1 => 'new1', 2 => 'new2'], - function () {} - ) + function () {}, + ), ); // optional arguments + variadics @@ -94,8 +94,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function ($a = 1, ...$args) {}), ['a' => 'new', 1 => 'new1', 2 => 'new2'], - function () {} - ) + function () {}, + ), ); // variadics as items @@ -104,8 +104,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function (...$args) {}), [1, 2, 3], - function () {} - ) + function () {}, + ), ); // variadics as array @@ -114,8 +114,8 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function (...$args) {}), ['args' => [1, 2, 3]], - function () {} - ) + function () {}, + ), ); // named parameter intentionally overwrites the indexed one (due to overwriting in the configuration) @@ -124,6 +124,6 @@ Assert::equal( Resolver::autowireArguments( new ReflectionFunction(function ($a) {}), [1, 'a' => 2], - function () {} - ) + function () {}, + ), ); From 5d1d12393bb241d038cc28e5474b52ab491a69bf Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 14 Dec 2021 19:34:58 +0100 Subject: [PATCH 23/44] removed support for PHP 7 --- src/Bridges/DITracy/ContainerPanel.php | 2 +- src/DI/Container.php | 3 +- src/DI/DependencyChecker.php | 11 ++-- src/DI/Extensions/InjectExtension.php | 2 +- src/DI/Resolver.php | 40 +++---------- tests/DI/Compiler.arguments.phpt | 12 ---- tests/DI/Container.dynamic.php80.phpt | 22 ------- tests/DI/Container.dynamic.phpt | 7 +++ .../ContainerBuilder.resolveTypes.php80.phpt | 30 ---------- tests/DI/ContainerBuilder.resolveTypes.phpt | 14 +++++ tests/DI/Resolver.autowireArguments.80.phpt | 57 ------------------- .../DI/Resolver.autowireArguments.errors.phpt | 20 +++++++ tests/DI/Resolver.autowireArguments.phpt | 26 ++++++++- 13 files changed, 80 insertions(+), 166 deletions(-) delete mode 100644 tests/DI/Container.dynamic.php80.phpt delete mode 100644 tests/DI/ContainerBuilder.resolveTypes.php80.phpt delete mode 100644 tests/DI/Resolver.autowireArguments.80.phpt diff --git a/src/Bridges/DITracy/ContainerPanel.php b/src/Bridges/DITracy/ContainerPanel.php index a86747e14..2d4982974 100644 --- a/src/Bridges/DITracy/ContainerPanel.php +++ b/src/Bridges/DITracy/ContainerPanel.php @@ -62,7 +62,7 @@ public function getPanel(): string $types = []; foreach ($rc->getMethods() as $method) { if (preg_match('#^createService(.+)#', $method->name, $m) && $method->getReturnType()) { - $types[lcfirst(str_replace('__', '.', $m[1]))] = $method->getReturnType()->getName(); + $types[lcfirst(str_replace('__', '.', $m[1]))] = (string) $method->getReturnType(); } } diff --git a/src/DI/Container.php b/src/DI/Container.php index e25cbd495..961a8aa8f 100644 --- a/src/DI/Container.php +++ b/src/DI/Container.php @@ -159,8 +159,7 @@ public function getServiceType(string $name): string return $this->types[$name]; } elseif (isset($this->methods[$method])) { - $type = (new \ReflectionMethod($this, $method))->getReturnType(); - return $type ? $type->getName() : ''; + return (string) (new \ReflectionMethod($this, $method))->getReturnType(); } else { throw new MissingServiceException(sprintf("Service '%s' not found.", $name)); diff --git a/src/DI/DependencyChecker.php b/src/DI/DependencyChecker.php index fcf890064..566d29d7a 100644 --- a/src/DI/DependencyChecker.php +++ b/src/DI/DependencyChecker.php @@ -11,7 +11,6 @@ use Nette; use Nette\Utils\Reflection; -use Nette\Utils\Type; use ReflectionClass; use ReflectionMethod; @@ -121,8 +120,8 @@ class_uses($name), $name, $prop->name, $prop->getDocComment(), - (string) Type::fromReflection($prop), - PHP_VERSION_ID >= 80000 ? count($prop->getAttributes(Attributes\Inject::class)) : null, + (string) $prop->getType(), + count($prop->getAttributes(Attributes\Inject::class)), ]; } } @@ -134,7 +133,7 @@ class_uses($name), $method->name, $method->getDocComment(), self::hashParameters($method), - (string) Type::fromReflection($method), + (string) $method->getReturnType(), ]; } } @@ -160,7 +159,7 @@ class_uses($name), $uses, $method->getDocComment(), self::hashParameters($method), - (string) Type::fromReflection($method), + (string) $method->getReturnType(), ]; } @@ -174,7 +173,7 @@ private static function hashParameters(\ReflectionFunctionAbstract $method): arr foreach ($method->getParameters() as $param) { $res[] = [ $param->name, - (string) Type::fromReflection($param), + (string) $param->getType(), $param->isVariadic(), $param->isDefaultValueAvailable() ? is_object($tmp = Reflection::getParameterDefaultValue($param)) ? ['object' => $tmp::class] : ['value' => $tmp] diff --git a/src/DI/Extensions/InjectExtension.php b/src/DI/Extensions/InjectExtension.php index 33b0943f7..493902c5f 100644 --- a/src/DI/Extensions/InjectExtension.php +++ b/src/DI/Extensions/InjectExtension.php @@ -112,7 +112,7 @@ public static function getInjectProperties(string $class): array $res = []; foreach ((new \ReflectionClass($class))->getProperties() as $rp) { $name = $rp->getName(); - $hasAttr = PHP_VERSION_ID >= 80000 && $rp->getAttributes(DI\Attributes\Inject::class); + $hasAttr = $rp->getAttributes(DI\Attributes\Inject::class); if ($hasAttr || DI\Helpers::parseAnnotation($rp, 'inject') !== null) { if (!$rp->isPublic() || $rp->isStatic()) { trigger_error(sprintf('Property %s for injection must be public and non-static.', Reflection::toString($rp)), E_USER_WARNING); diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 114cee201..59688acb7 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -526,7 +526,6 @@ public static function autowireArguments( array $arguments, callable $getter, ): array { - $optCount = 0; $useName = false; $num = -1; $res = []; @@ -557,9 +556,6 @@ public static function autowireArguments( $res = array_merge($res, $variadics); } - $optCount = 0; - break; - } elseif (array_key_exists($paramName, $arguments)) { $res[$useName ? $paramName : $num] = $arguments[$paramName]; unset($arguments[$paramName], $arguments[$num]); @@ -571,39 +567,21 @@ public static function autowireArguments( } elseif (($aw = self::autowireArgument($param, $getter)) !== null) { $res[$useName ? $paramName : $num] = $aw; - } elseif (PHP_VERSION_ID >= 80000) { - if ($param->isOptional()) { - $useName = true; - } else { - $res[$num] = null; - trigger_error(sprintf( - 'The parameter %s should have a declared value in the configuration.', - Reflection::toString($param) - ), E_USER_DEPRECATED); - } + } elseif ($param->isOptional()) { + $useName = true; } else { - $res[$num] = $param->isDefaultValueAvailable() - ? Reflection::getParameterDefaultValue($param) - : null; - - if (!$param->isOptional()) { - trigger_error(sprintf( - 'The parameter %s should have a declared value in the configuration.', - Reflection::toString($param) - ), E_USER_DEPRECATED); - } - } + $res[$num] = null; - if (PHP_VERSION_ID < 80000) { - $optCount = $param->isOptional() && $res[$num] === ($param->isDefaultValueAvailable() ? Reflection::getParameterDefaultValue($param) : null) - ? $optCount + 1 - : 0; + trigger_error(sprintf( + 'The parameter %s should have a declared value in the configuration.', + Reflection::toString($param), + ), E_USER_DEPRECATED); } } // extra parameters - while (!$useName && !$optCount && array_key_exists(++$num, $arguments)) { + while (!$useName && array_key_exists(++$num, $arguments)) { $res[$num] = $arguments[$num]; unset($arguments[$num]); } @@ -613,8 +591,6 @@ public static function autowireArguments( 'Unable to pass specified arguments to %s.', Reflection::toString($method), )); - } elseif ($optCount) { - $res = array_slice($res, 0, -$optCount); } return $res; diff --git a/tests/DI/Compiler.arguments.phpt b/tests/DI/Compiler.arguments.phpt index 176710d16..921dd3e39 100644 --- a/tests/DI/Compiler.arguments.phpt +++ b/tests/DI/Compiler.arguments.phpt @@ -41,18 +41,6 @@ class Lorem } -if (PHP_VERSION_ID < 80000) { - Assert::error(function () use (&$container) { - $container = createContainer(new DI\Compiler, ' - services: - dolor: Lorem(::MY_FAILING_CONSTANT_TEST) - '); - }, E_WARNING, "%a?%Couldn't find constant MY_FAILING_CONSTANT_TEST"); - Assert::same([null], $container->getService('dolor')->args[0]); -} - - - define('MY_CONSTANT_TEST', 'one'); $container = createContainer(new DI\Compiler, " diff --git a/tests/DI/Container.dynamic.php80.phpt b/tests/DI/Container.dynamic.php80.phpt deleted file mode 100644 index a4166f118..000000000 --- a/tests/DI/Container.dynamic.php80.phpt +++ /dev/null @@ -1,22 +0,0 @@ -addService('six', function (): stdClass|Closure {}); // @ triggers service should be defined as "imported" - $container->getService('six'); -}, Nette\InvalidStateException::class, "Return type of closure is not expected to be nullable/union/intersection/built-in, 'stdClass|Closure' given."); diff --git a/tests/DI/Container.dynamic.phpt b/tests/DI/Container.dynamic.phpt index 2f71ed403..9b44597e5 100644 --- a/tests/DI/Container.dynamic.phpt +++ b/tests/DI/Container.dynamic.phpt @@ -64,3 +64,10 @@ Assert::exception(function () use ($container) { @$container->addService('six', function () {}); // @ triggers service should be defined as "imported" $container->getService('six'); }, Nette\UnexpectedValueException::class, "Unable to create service 'six', value returned by closure is not object."); + + +// union type +Assert::exception(function () use ($container) { + @$container->addService('six', function (): stdClass|Closure {}); // @ triggers service should be defined as "imported" + $container->getService('six'); +}, Nette\InvalidStateException::class, "Return type of closure is not expected to be nullable/union/intersection/built-in, 'stdClass|Closure' given."); diff --git a/tests/DI/ContainerBuilder.resolveTypes.php80.phpt b/tests/DI/ContainerBuilder.resolveTypes.php80.phpt deleted file mode 100644 index 8f8631215..000000000 --- a/tests/DI/ContainerBuilder.resolveTypes.php80.phpt +++ /dev/null @@ -1,30 +0,0 @@ -addDefinition('a') - ->setCreator([Factory::class, 'createUnion']); - $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createUnion() is not expected to be nullable/union/intersection/built-in, 'stdClass|array' given."); diff --git a/tests/DI/ContainerBuilder.resolveTypes.phpt b/tests/DI/ContainerBuilder.resolveTypes.phpt index 9072a8446..05d2142b9 100644 --- a/tests/DI/ContainerBuilder.resolveTypes.phpt +++ b/tests/DI/ContainerBuilder.resolveTypes.phpt @@ -87,6 +87,12 @@ class Factory { return (object) null; } + + + public function createUnion(): stdClass|array + { + return []; + } } @@ -177,3 +183,11 @@ Assert::exception(function () { $container = @createContainer($builder); // @return is deprecated }, Nette\DI\ServiceCreationException::class, "Service 'a': Class 'T' not found. Check the return type of Factory::createGeneric()."); + +Assert::exception(function () { + $builder = new DI\ContainerBuilder; + $builder->addDefinition('a') + ->setFactory([Factory::class, 'createUnion']); + $container = createContainer($builder); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Return type of Factory::createUnion() is not expected to be nullable/union/intersection/built-in, 'stdClass|array' given."); diff --git a/tests/DI/Resolver.autowireArguments.80.phpt b/tests/DI/Resolver.autowireArguments.80.phpt deleted file mode 100644 index 9fb463c2e..000000000 --- a/tests/DI/Resolver.autowireArguments.80.phpt +++ /dev/null @@ -1,57 +0,0 @@ - 1, 'b' => 2, 'c' => 3], - Resolver::autowireArguments( - new ReflectionFunction(function (...$args) {}), - ['a' => 1, 'b' => 2, 'c' => 3], - function () {} - ) -); diff --git a/tests/DI/Resolver.autowireArguments.errors.phpt b/tests/DI/Resolver.autowireArguments.errors.phpt index 4b6bc3461..c950a41af 100644 --- a/tests/DI/Resolver.autowireArguments.errors.phpt +++ b/tests/DI/Resolver.autowireArguments.errors.phpt @@ -73,6 +73,26 @@ Assert::error(function () { }, E_USER_DEPRECATED, 'The parameter $arg in {closure}() should have a declared value in the configuration.'); +// union +Assert::exception(function () { + Resolver::autowireArguments( + new ReflectionFunction(function (stdClass|Test $x) {}), + [], + function () {}, + ); +}, Nette\InvalidStateException::class, 'Parameter $x in {closure}() has union type and no default value, so its value must be specified.'); + + +// nullable union +Assert::error(function () { + Resolver::autowireArguments( + new ReflectionFunction(function (stdClass|Test|null $x) {}), + [], + function () {}, + ); +}, E_USER_DEPRECATED, 'The parameter $x in {closure}() should have a declared value in the configuration.'); + + // bad variadics (this is actually what PHP allows) Assert::exception(function () { Resolver::autowireArguments( diff --git a/tests/DI/Resolver.autowireArguments.phpt b/tests/DI/Resolver.autowireArguments.phpt index 3eb11e334..ceaea54df 100644 --- a/tests/DI/Resolver.autowireArguments.phpt +++ b/tests/DI/Resolver.autowireArguments.phpt @@ -60,7 +60,7 @@ Assert::equal( // optional arguments + positional Assert::equal( - PHP_VERSION_ID < 80000 ? [1, 'new'] : ['b' => 'new'], + ['b' => 'new'], Resolver::autowireArguments( new ReflectionFunction(function ($a = 1, $b = 2) {}), [1 => 'new'], @@ -70,7 +70,7 @@ Assert::equal( // optional arguments + named Assert::equal( - PHP_VERSION_ID < 80000 ? [1, 'new'] : ['b' => 'new'], + ['b' => 'new'], Resolver::autowireArguments( new ReflectionFunction(function ($a = 1, $b = 2) {}), ['b' => 'new'], @@ -80,7 +80,7 @@ Assert::equal( // optional arguments + variadics Assert::equal( - PHP_VERSION_ID < 80000 ? [1, 'new1', 'new2'] : ['args' => ['new1', 'new2']], + ['args' => ['new1', 'new2']], Resolver::autowireArguments( new ReflectionFunction(function ($a = 1, ...$args) {}), [1 => 'new1', 2 => 'new2'], @@ -127,3 +127,23 @@ Assert::equal( function () {}, ), ); + +// optional union +Assert::same( + [], + Resolver::autowireArguments( + new ReflectionFunction(function (stdClass|int $x = 1) {}), + [], + function () {}, + ), +); + +// named variadics +Assert::equal( + ['a' => 1, 'b' => 2, 'c' => 3], + Resolver::autowireArguments( + new ReflectionFunction(function (...$args) {}), + ['a' => 1, 'b' => 2, 'c' => 3], + function () {}, + ), +); From 78591d383acb122b32f96269d7900e8b6eced2d0 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:11:39 +0100 Subject: [PATCH 24/44] added property typehints --- src/Bridges/DITracy/ContainerPanel.php | 9 ++--- src/DI/Autowiring.php | 9 +++-- src/DI/Compiler.php | 24 ++++---------- src/DI/CompilerExtension.php | 15 +++------ src/DI/Config/Loader.php | 11 +++---- src/DI/Container.php | 13 +++----- src/DI/ContainerBuilder.php | 27 +++++---------- src/DI/ContainerLoader.php | 7 ++-- src/DI/Definitions/AccessorDefinition.php | 3 +- src/DI/Definitions/Definition.php | 15 +++------ src/DI/Definitions/FactoryDefinition.php | 7 ++-- src/DI/Definitions/LocatorDefinition.php | 6 ++-- src/DI/Definitions/Reference.php | 3 +- src/DI/Definitions/ServiceDefinition.php | 5 ++- src/DI/Definitions/Statement.php | 7 ++-- src/DI/DependencyChecker.php | 4 +-- src/DI/Extensions/DIExtension.php | 33 +++++++------------ src/DI/Extensions/DefinitionSchema.php | 3 +- src/DI/Extensions/ParametersExtension.php | 8 ++--- src/DI/Extensions/SearchExtension.php | 7 ++-- src/DI/PhpGenerator.php | 7 ++-- src/DI/Resolver.php | 19 ++++------- tests/DI/Compiler.arguments.phpt | 2 +- .../DI/CompilerExtension.validateConfig.phpt | 2 +- tests/bootstrap.php | 2 +- 25 files changed, 83 insertions(+), 165 deletions(-) diff --git a/src/Bridges/DITracy/ContainerPanel.php b/src/Bridges/DITracy/ContainerPanel.php index 2d4982974..5767f64cd 100644 --- a/src/Bridges/DITracy/ContainerPanel.php +++ b/src/Bridges/DITracy/ContainerPanel.php @@ -21,14 +21,11 @@ class ContainerPanel implements Tracy\IBarPanel { use Nette\SmartObject; - /** @var float|null */ - public static $compilationTime; + public static ?float $compilationTime = null; - /** @var Nette\DI\Container */ - private $container; + private Nette\DI\Container $container; - /** @var float|null */ - private $elapsedTime; + private ?float $elapsedTime; public function __construct(Container $container) diff --git a/src/DI/Autowiring.php b/src/DI/Autowiring.php index 3edc55513..3889fae39 100644 --- a/src/DI/Autowiring.php +++ b/src/DI/Autowiring.php @@ -19,17 +19,16 @@ class Autowiring { use Nette\SmartObject; - /** @var ContainerBuilder */ - private $builder; + private ContainerBuilder $builder; /** @var array[] type => services, used by getByType() */ - private $highPriority = []; + private array $highPriority = []; /** @var array[] type => services, used by findByType() */ - private $lowPriority = []; + private array $lowPriority = []; /** @var string[] of classes excluded from autowiring */ - private $excludedClasses = []; + private array $excludedClasses = []; public function __construct(ContainerBuilder $builder) diff --git a/src/DI/Compiler.php b/src/DI/Compiler.php index 17388b1f7..00a0787fa 100644 --- a/src/DI/Compiler.php +++ b/src/DI/Compiler.php @@ -26,25 +26,15 @@ class Compiler DI = 'di'; /** @var CompilerExtension[] */ - private $extensions = []; - - /** @var ContainerBuilder */ - private $builder; - - /** @var array */ - private $config = []; + private array $extensions = []; + private ContainerBuilder $builder; + private array $config = []; /** @var array [section => array[]] */ - private $configs = []; - - /** @var string */ - private $sources = ''; - - /** @var DependencyChecker */ - private $dependencies; - - /** @var string */ - private $className = 'Container'; + private array $configs = []; + private string $sources = ''; + private DependencyChecker $dependencies; + private string $className = 'Container'; public function __construct(?ContainerBuilder $builder = null) diff --git a/src/DI/CompilerExtension.php b/src/DI/CompilerExtension.php index aaf61527d..d528ef349 100644 --- a/src/DI/CompilerExtension.php +++ b/src/DI/CompilerExtension.php @@ -19,17 +19,10 @@ abstract class CompilerExtension { use Nette\SmartObject; - /** @var Compiler */ - protected $compiler; - - /** @var string */ - protected $name; - - /** @var array|object */ - protected $config = []; - - /** @var Nette\PhpGenerator\Closure */ - protected $initialization; + protected Compiler $compiler; + protected string $name; + protected array|object $config = []; + protected Nette\PhpGenerator\Closure $initialization; /** @return static */ diff --git a/src/DI/Config/Loader.php b/src/DI/Config/Loader.php index 6273a8c73..11a14880e 100644 --- a/src/DI/Config/Loader.php +++ b/src/DI/Config/Loader.php @@ -22,16 +22,13 @@ class Loader private const IncludesKey = 'includes'; - private $adapters = [ + private array $adapters = [ 'php' => Adapters\PhpAdapter::class, 'neon' => Adapters\NeonAdapter::class, ]; - - private $dependencies = []; - - private $loadedFiles = []; - - private $parameters = []; + private array $dependencies = []; + private array $loadedFiles = []; + private array $parameters = []; /** diff --git a/src/DI/Container.php b/src/DI/Container.php index 961a8aa8f..de77937c2 100644 --- a/src/DI/Container.php +++ b/src/DI/Container.php @@ -19,8 +19,7 @@ class Container { use Nette\SmartObject; - /** @var array user parameters */ - public $parameters = []; + public array $parameters = []; /** @var string[] services name => type (complete list of available services) */ protected $types = []; @@ -35,13 +34,11 @@ class Container protected $wiring = []; /** @var object[] service name => instance */ - private $instances = []; + private array $instances = []; - /** @var array circular reference detector */ - private $creating; - - /** @var array */ - private $methods; + /** circular reference detector */ + private array $creating; + private array $methods; public function __construct(array $params = []) diff --git a/src/DI/ContainerBuilder.php b/src/DI/ContainerBuilder.php index 506ba3c32..1e24b7527 100644 --- a/src/DI/ContainerBuilder.php +++ b/src/DI/ContainerBuilder.php @@ -24,26 +24,17 @@ class ContainerBuilder THIS_SERVICE = 'self', THIS_CONTAINER = 'container'; - /** @var array */ - public $parameters = []; + public array $parameters = []; /** @var Definition[] */ - private $definitions = []; - - /** @var array of alias => service */ - private $aliases = []; - - /** @var Autowiring */ - private $autowiring; - - /** @var bool */ - private $needsResolve = true; - - /** @var bool */ - private $resolving = false; - - /** @var array */ - private $dependencies = []; + private array $definitions = []; + + /** alias => service */ + private array $aliases = []; + private Autowiring $autowiring; + private bool $needsResolve = true; + private bool $resolving = false; + private array $dependencies = []; public function __construct() diff --git a/src/DI/ContainerLoader.php b/src/DI/ContainerLoader.php index d8b04cb62..3721dba80 100644 --- a/src/DI/ContainerLoader.php +++ b/src/DI/ContainerLoader.php @@ -19,11 +19,8 @@ class ContainerLoader { use Nette\SmartObject; - /** @var bool */ - private $autoRebuild = false; - - /** @var string */ - private $tempDirectory; + private bool $autoRebuild = false; + private string $tempDirectory; public function __construct(string $tempDirectory, bool $autoRebuild = false) diff --git a/src/DI/Definitions/AccessorDefinition.php b/src/DI/Definitions/AccessorDefinition.php index 4ac206740..44ebd0397 100644 --- a/src/DI/Definitions/AccessorDefinition.php +++ b/src/DI/Definitions/AccessorDefinition.php @@ -21,8 +21,7 @@ final class AccessorDefinition extends Definition { private const MethodGet = 'get'; - /** @var Reference|null */ - private $reference; + private ?Reference $reference = null; /** @return static */ diff --git a/src/DI/Definitions/Definition.php b/src/DI/Definitions/Definition.php index 491faa832..5543ea051 100644 --- a/src/DI/Definitions/Definition.php +++ b/src/DI/Definitions/Definition.php @@ -19,19 +19,14 @@ abstract class Definition { use Nette\SmartObject; - /** @var string|null */ - private $name; - - /** @var string|null class or interface name */ - private $type; - - /** @var array */ - private $tags = []; + private ?string $name = null; + private ?string $type = null; + private array $tags = []; /** @var bool|string[] */ - private $autowired = true; + private bool|array $autowired = true; - /** @var callable|null */ + /** @var ?callable */ private $notifier; diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index 70a7ea5ab..f577b0cdd 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -24,11 +24,8 @@ final class FactoryDefinition extends Definition { private const MethodCreate = 'create'; - /** @var array */ - public $parameters = []; - - /** @var Definition */ - private $resultDefinition; + public array $parameters = []; + private Definition $resultDefinition; public function __construct() diff --git a/src/DI/Definitions/LocatorDefinition.php b/src/DI/Definitions/LocatorDefinition.php index 4ead39c3e..8bf2d15d5 100644 --- a/src/DI/Definitions/LocatorDefinition.php +++ b/src/DI/Definitions/LocatorDefinition.php @@ -18,10 +18,8 @@ final class LocatorDefinition extends Definition { /** @var Reference[] */ - private $references = []; - - /** @var string|null */ - private $tagged; + private array $references = []; + private ?string $tagged = null; /** @return static */ diff --git a/src/DI/Definitions/Reference.php b/src/DI/Definitions/Reference.php index f6de3ade8..0ce79eea5 100644 --- a/src/DI/Definitions/Reference.php +++ b/src/DI/Definitions/Reference.php @@ -21,8 +21,7 @@ final class Reference public const SELF = 'self'; - /** @var string */ - private $value; + private string $value; public static function fromType(string $value): self diff --git a/src/DI/Definitions/ServiceDefinition.php b/src/DI/Definitions/ServiceDefinition.php index ba208741a..ac07797d1 100644 --- a/src/DI/Definitions/ServiceDefinition.php +++ b/src/DI/Definitions/ServiceDefinition.php @@ -22,11 +22,10 @@ */ final class ServiceDefinition extends Definition { - /** @var Statement */ - private $creator; + private Statement $creator; /** @var Statement[] */ - private $setup = []; + private array $setup = []; public function __construct() diff --git a/src/DI/Definitions/Statement.php b/src/DI/Definitions/Statement.php index 47231c01e..ff4d85dcd 100644 --- a/src/DI/Definitions/Statement.php +++ b/src/DI/Definitions/Statement.php @@ -22,11 +22,8 @@ final class Statement implements Nette\Schema\DynamicParameter { use Nette\SmartObject; - /** @var array */ - public $arguments; - - /** @var string|array|Definition|Reference|null */ - private $entity; + public array $arguments; + private string|array|Definition|Reference|null $entity; /** diff --git a/src/DI/DependencyChecker.php b/src/DI/DependencyChecker.php index 566d29d7a..e2ea4eb51 100644 --- a/src/DI/DependencyChecker.php +++ b/src/DI/DependencyChecker.php @@ -24,8 +24,8 @@ class DependencyChecker public const VERSION = 1; - /** @var array of ReflectionClass|\ReflectionFunctionAbstract|string */ - private $dependencies = []; + /** @var array */ + private array $dependencies = []; /** diff --git a/src/DI/Extensions/DIExtension.php b/src/DI/Extensions/DIExtension.php index 262fffb8f..0c1bb1d13 100644 --- a/src/DI/Extensions/DIExtension.php +++ b/src/DI/Extensions/DIExtension.php @@ -18,17 +18,10 @@ */ final class DIExtension extends Nette\DI\CompilerExtension { - /** @var array */ - public $exportedTags = []; - - /** @var array */ - public $exportedTypes = []; - - /** @var bool */ - private $debugMode; - - /** @var float */ - private $time; + public array $exportedTags = []; + public array $exportedTypes = []; + private bool $debugMode; + private float $time; public function __construct(bool $debugMode = false) @@ -37,27 +30,23 @@ public function __construct(bool $debugMode = false) $this->time = microtime(true); $this->config = new class { - /** @var ?bool */ - public $debugger; + public ?bool $debugger = null; /** @var string[] */ - public $excluded = []; + public array $excluded = []; - /** @var ?string */ - public $parentClass; + public ?string $parentClass = null; - /** @var object */ - public $export; + public object $export; }; $this->config->export = new class { - /** @var bool */ - public $parameters = true; + public bool $parameters = true; /** @var string[]|bool|null */ - public $tags = true; + public array|bool|null $tags = true; /** @var string[]|bool|null */ - public $types = true; + public array|bool|null $types = true; }; } diff --git a/src/DI/Extensions/DefinitionSchema.php b/src/DI/Extensions/DefinitionSchema.php index 4dc4812cc..c604943fb 100644 --- a/src/DI/Extensions/DefinitionSchema.php +++ b/src/DI/Extensions/DefinitionSchema.php @@ -25,8 +25,7 @@ class DefinitionSchema implements Schema { use Nette\SmartObject; - /** @var Nette\DI\ContainerBuilder */ - private $builder; + private Nette\DI\ContainerBuilder $builder; public function __construct(Nette\DI\ContainerBuilder $builder) diff --git a/src/DI/Extensions/ParametersExtension.php b/src/DI/Extensions/ParametersExtension.php index b97dfa4ad..98bc34406 100644 --- a/src/DI/Extensions/ParametersExtension.php +++ b/src/DI/Extensions/ParametersExtension.php @@ -19,13 +19,11 @@ final class ParametersExtension extends Nette\DI\CompilerExtension { /** @var string[] */ - public $dynamicParams = []; + public array $dynamicParams = []; /** @var string[][] */ - public $dynamicValidators = []; - - /** @var array */ - private $compilerConfig; + public array $dynamicValidators = []; + private array $compilerConfig; public function __construct(array &$compilerConfig) diff --git a/src/DI/Extensions/SearchExtension.php b/src/DI/Extensions/SearchExtension.php index 119e3363a..c530531b2 100644 --- a/src/DI/Extensions/SearchExtension.php +++ b/src/DI/Extensions/SearchExtension.php @@ -20,11 +20,8 @@ */ final class SearchExtension extends Nette\DI\CompilerExtension { - /** @var array */ - private $classes = []; - - /** @var string */ - private $tempDir; + private array $classes = []; + private string $tempDir; public function __construct(string $tempDir) diff --git a/src/DI/PhpGenerator.php b/src/DI/PhpGenerator.php index c5bad2448..6ae23df5d 100644 --- a/src/DI/PhpGenerator.php +++ b/src/DI/PhpGenerator.php @@ -23,11 +23,8 @@ class PhpGenerator { use Nette\SmartObject; - /** @var ContainerBuilder */ - private $builder; - - /** @var string */ - private $className; + private ContainerBuilder $builder; + private ?string $className = null; public function __construct(ContainerBuilder $builder) diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 59688acb7..c338da9b3 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -29,20 +29,13 @@ class Resolver { use Nette\SmartObject; - /** @var ContainerBuilder */ - private $builder; + private ContainerBuilder $builder; + private ?Definition $currentService = null; + private ?string $currentServiceType = null; + private bool $currentServiceAllowed = false; - /** @var Definition|null */ - private $currentService; - - /** @var string|null */ - private $currentServiceType; - - /** @var bool */ - private $currentServiceAllowed = false; - - /** @var \SplObjectStorage circular reference detector */ - private $recursive; + /** circular reference detector */ + private \SplObjectStorage $recursive; public function __construct(ContainerBuilder $builder) diff --git a/tests/DI/Compiler.arguments.phpt b/tests/DI/Compiler.arguments.phpt index 921dd3e39..120dedfc0 100644 --- a/tests/DI/Compiler.arguments.phpt +++ b/tests/DI/Compiler.arguments.phpt @@ -19,7 +19,7 @@ class Lorem public $args; - public $var = 123; + public int $var = 123; public function __construct() diff --git a/tests/DI/CompilerExtension.validateConfig.phpt b/tests/DI/CompilerExtension.validateConfig.phpt index 1c6f2f35b..298603945 100644 --- a/tests/DI/CompilerExtension.validateConfig.phpt +++ b/tests/DI/CompilerExtension.validateConfig.phpt @@ -14,7 +14,7 @@ require __DIR__ . '/../bootstrap.php'; class MyExtension extends Nette\DI\CompilerExtension { - protected $name = 'my'; + protected string $name = 'my'; } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 9a7a63f32..531d91951 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -45,7 +45,7 @@ function test(string $title, Closure $function): void class Notes { - public static $notes = []; + public static array $notes = []; public static function add($message): void From cde5b0cf4b2beb195e37db6709740da30b81faf5 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 27 Sep 2021 01:27:28 +0200 Subject: [PATCH 25/44] added property typehints to Container --- src/DI/Container.php | 8 ++++---- src/DI/PhpGenerator.php | 3 ++- tests/DI/Container.getServiceType.phpt | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/DI/Container.php b/src/DI/Container.php index de77937c2..72ec4ef31 100644 --- a/src/DI/Container.php +++ b/src/DI/Container.php @@ -22,16 +22,16 @@ class Container public array $parameters = []; /** @var string[] services name => type (complete list of available services) */ - protected $types = []; + protected array $types = []; /** @var string[] alias => service name */ - protected $aliases = []; + protected array $aliases = []; /** @var array[] tag name => service name => tag value */ - protected $tags = []; + protected array $tags = []; /** @var array[] type => level => services */ - protected $wiring = []; + protected array $wiring = []; /** @var object[] service name => instance */ private array $instances = []; diff --git a/src/DI/PhpGenerator.php b/src/DI/PhpGenerator.php index 6ae23df5d..cf71b1985 100644 --- a/src/DI/PhpGenerator.php +++ b/src/DI/PhpGenerator.php @@ -49,7 +49,8 @@ public function generate(string $className): Php\ClassType foreach ($this->builder->exportMeta() as $key => $value) { $class->addProperty($key) ->setProtected() - ->setValue($value); + ->setValue($value) + ->setType(get_debug_type($value)); } $definitions = $this->builder->getDefinitions(); diff --git a/tests/DI/Container.getServiceType.phpt b/tests/DI/Container.getServiceType.phpt index 9790cd102..d1dc352ee 100644 --- a/tests/DI/Container.getServiceType.phpt +++ b/tests/DI/Container.getServiceType.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/../bootstrap.php'; class MyContainer extends Container { - protected $aliases = [ + protected array $aliases = [ 'three' => 'one', ]; From c6ccd4058016ac85e510320188f18fdb874b3110 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 15 Dec 2021 16:58:31 +0100 Subject: [PATCH 26/44] added PHP 8 typehints --- src/DI/Autowiring.php | 1 - src/DI/Compiler.php | 27 +++++++------------- src/DI/CompilerExtension.php | 16 +++--------- src/DI/Config/Loader.php | 7 ++--- src/DI/Container.php | 27 ++++++-------------- src/DI/ContainerBuilder.php | 8 ++---- src/DI/ContainerLoader.php | 8 ++---- src/DI/Definitions/AccessorDefinition.php | 9 ++----- src/DI/Definitions/Definition.php | 29 ++++++--------------- src/DI/Definitions/FactoryDefinition.php | 8 +++--- src/DI/Definitions/ImportedDefinition.php | 3 +-- src/DI/Definitions/LocatorDefinition.php | 9 +++---- src/DI/Definitions/Reference.php | 2 +- src/DI/Definitions/ServiceDefinition.php | 31 ++++++----------------- src/DI/Definitions/Statement.php | 8 ++---- src/DI/DependencyChecker.php | 3 +-- src/DI/Extensions/InjectExtension.php | 7 +---- src/DI/Helpers.php | 18 +++---------- src/DI/Resolver.php | 11 +++----- src/DI/exceptions.php | 2 +- tests/DI/Container.errors.phpt | 4 --- tests/bootstrap.php | 2 +- 22 files changed, 66 insertions(+), 174 deletions(-) diff --git a/src/DI/Autowiring.php b/src/DI/Autowiring.php index 3889fae39..3e88a4df7 100644 --- a/src/DI/Autowiring.php +++ b/src/DI/Autowiring.php @@ -39,7 +39,6 @@ public function __construct(ContainerBuilder $builder) /** * Resolves service name by type. - * @param bool $throw exception if service not found? * @throws MissingServiceException when not found * @throws ServiceCreationException when multiple found */ diff --git a/src/DI/Compiler.php b/src/DI/Compiler.php index 00a0787fa..691c7cec8 100644 --- a/src/DI/Compiler.php +++ b/src/DI/Compiler.php @@ -48,9 +48,8 @@ public function __construct(?ContainerBuilder $builder = null) /** * Add custom configurator extension. - * @return static */ - public function addExtension(?string $name, CompilerExtension $extension) + public function addExtension(?string $name, CompilerExtension $extension): static { if ($name === null) { $name = '_' . count($this->extensions); @@ -88,8 +87,7 @@ public function getContainerBuilder(): ContainerBuilder } - /** @return static */ - public function setClassName(string $className) + public function setClassName(string $className): static { $this->className = $className; return $this; @@ -98,9 +96,8 @@ public function setClassName(string $className) /** * Adds new configuration. - * @return static */ - public function addConfig(array $config) + public function addConfig(array $config): static { foreach ($config as $section => $data) { $this->configs[$section][] = $data; @@ -113,9 +110,8 @@ public function addConfig(array $config) /** * Adds new configuration from file. - * @return static */ - public function loadConfig(string $file, ?Config\Loader $loader = null) + public function loadConfig(string $file, ?Config\Loader $loader = null): static { $sources = $this->sources . "// source: $file\n"; $loader = $loader ?: new Config\Loader; @@ -141,9 +137,8 @@ public function getConfig(): array /** * Sets the names of dynamic parameters. - * @return static */ - public function setDynamicParameterNames(array $names) + public function setDynamicParameterNames(array $names): static { assert($this->extensions[self::Parameters] instanceof Extensions\ParametersExtension); $this->extensions[self::Parameters]->dynamicParams = $names; @@ -154,9 +149,8 @@ public function setDynamicParameterNames(array $names) /** * Adds dependencies to the list. * @param array $deps of ReflectionClass|\ReflectionFunctionAbstract|string - * @return static */ - public function addDependencies(array $deps) + public function addDependencies(array $deps): static { $this->dependencies->add(array_filter($deps)); return $this; @@ -172,8 +166,7 @@ public function exportDependencies(): array } - /** @return static */ - public function addExportedTag(string $tag) + public function addExportedTag(string $tag): static { if (isset($this->extensions[self::DI])) { assert($this->extensions[self::DI] instanceof Extensions\DIExtension); @@ -184,8 +177,7 @@ public function addExportedTag(string $tag) } - /** @return static */ - public function addExportedType(string $type) + public function addExportedType(string $type): static { if (isset($this->extensions[self::DI])) { assert($this->extensions[self::DI] instanceof Extensions\DIExtension); @@ -268,9 +260,8 @@ private function processBeforeCompile(): void /** * Merges and validates configurations against scheme. - * @return array|object */ - private function processSchema(Schema\Schema $schema, array $configs, $name = null) + private function processSchema(Schema\Schema $schema, array $configs, $name = null): array|object { $processor = new Schema\Processor; $processor->onNewContext[] = function (Schema\Context $context) use ($name) { diff --git a/src/DI/CompilerExtension.php b/src/DI/CompilerExtension.php index d528ef349..7e59b9c74 100644 --- a/src/DI/CompilerExtension.php +++ b/src/DI/CompilerExtension.php @@ -25,8 +25,7 @@ abstract class CompilerExtension protected Nette\PhpGenerator\Closure $initialization; - /** @return static */ - public function setCompiler(Compiler $compiler, string $name) + public function setCompiler(Compiler $compiler, string $name): static { $this->initialization = new Nette\PhpGenerator\Closure; $this->compiler = $compiler; @@ -35,16 +34,8 @@ public function setCompiler(Compiler $compiler, string $name) } - /** - * @param array|object $config - * @return static - */ - public function setConfig($config) + public function setConfig(array|object $config): static { - if (!is_array($config) && !is_object($config)) { - throw new Nette\InvalidArgumentException; - } - $this->config = $config; return $this; } @@ -52,9 +43,8 @@ public function setConfig($config) /** * Returns extension configuration. - * @return array|object */ - public function getConfig() + public function getConfig(): array|object { return $this->config; } diff --git a/src/DI/Config/Loader.php b/src/DI/Config/Loader.php index 11a14880e..a9273de1b 100644 --- a/src/DI/Config/Loader.php +++ b/src/DI/Config/Loader.php @@ -103,10 +103,8 @@ public function expandIncludedFile(string $includedFile, string $mainFile): stri /** * Registers adapter for given file extension. - * @param string|Adapter $adapter - * @return static */ - public function addAdapter(string $extension, $adapter) + public function addAdapter(string $extension, string|Adapter $adapter): static { $this->adapters[strtolower($extension)] = $adapter; return $this; @@ -126,8 +124,7 @@ private function getAdapter(string $file): Adapter } - /** @return static */ - public function setParameters(array $params) + public function setParameters(array $params): static { $this->parameters = $params; return $this; diff --git a/src/DI/Container.php b/src/DI/Container.php index 72ec4ef31..29b159bae 100644 --- a/src/DI/Container.php +++ b/src/DI/Container.php @@ -60,16 +60,12 @@ public function getParameters(): array /** * Adds the service to the container. * @param object $service service or its factory - * @return static */ - public function addService(string $name, $service) + public function addService(string $name, object $service): static { $name = $this->aliases[$name] ?? $name; if (isset($this->instances[$name])) { throw new Nette\InvalidStateException(sprintf("Service '%s' already exists.", $name)); - - } elseif (!is_object($service)) { - throw new Nette\InvalidArgumentException(sprintf("Service '%s' must be a object, %s given.", $name, gettype($service))); } if ($service instanceof \Closure) { @@ -114,10 +110,9 @@ public function removeService(string $name): void /** * Gets the service object by name. - * @return object * @throws MissingServiceException */ - public function getService(string $name) + public function getService(string $name): object { if (!isset($this->instances[$name])) { if (isset($this->aliases[$name])) { @@ -133,10 +128,9 @@ public function getService(string $name) /** * Gets the service object by name. - * @return object * @throws MissingServiceException */ - public function getByName(string $name) + public function getByName(string $name): object { return $this->getService($name); } @@ -190,10 +184,9 @@ public function isCreated(string $name): bool /** * Creates new instance of the service. - * @return object * @throws MissingServiceException */ - public function createService(string $name, array $args = []) + public function createService(string $name, array $args = []): object { $name = $this->aliases[$name] ?? $name; $method = self::getMethodName($name); @@ -233,7 +226,7 @@ public function createService(string $name, array $args = []) * @return ?T * @throws MissingServiceException */ - public function getByType(string $type, bool $throw = true) + public function getByType(string $type, bool $throw = true): ?object { $type = Helpers::normalizeClass($type); if (!empty($this->wiring[$type][0])) { @@ -309,10 +302,8 @@ public function findByTag(string $tag): array /** * Creates new instance using autowiring. - * @return object - * @throws Nette\InvalidArgumentException */ - public function createInstance(string $class, array $args = []) + public function createInstance(string $class, array $args = []): object { $rc = new \ReflectionClass($class); if (!$rc->isInstantiable()) { @@ -331,9 +322,8 @@ public function createInstance(string $class, array $args = []) /** * Calls all methods starting with with "inject" using autowiring. - * @param object $service */ - public function callInjects($service): void + public function callInjects(object $service): void { Extensions\InjectExtension::callInjects($this, $service); } @@ -341,9 +331,8 @@ public function callInjects($service): void /** * Calls method using autowiring. - * @return mixed */ - public function callMethod(callable $function, array $args = []) + public function callMethod(callable $function, array $args = []): mixed { return $function(...$this->autowireArguments(Nette\Utils\Callback::toReflection($function), $args)); } diff --git a/src/DI/ContainerBuilder.php b/src/DI/ContainerBuilder.php index 1e24b7527..e212b6a3f 100644 --- a/src/DI/ContainerBuilder.php +++ b/src/DI/ContainerBuilder.php @@ -197,9 +197,8 @@ public function getAliases(): array /** * @param string[] $types - * @return static */ - public function addExcludedClasses(array $types) + public function addExcludedClasses(array $types): static { $this->needsResolve = true; $this->autowiring->addExcludedClasses($types); @@ -209,7 +208,6 @@ public function addExcludedClasses(array $types) /** * Resolves autowired service name by type. - * @param bool $throw exception if service doesn't exist? * @throws MissingServiceException */ public function getByType(string $type, bool $throw = false): ?string @@ -327,11 +325,9 @@ public function complete(): void /** * Adds item to the list of dependencies. - * @param \ReflectionClass|\ReflectionFunctionAbstract|string $dep - * @return static * @internal */ - public function addDependency($dep) + public function addDependency(\ReflectionClass|\ReflectionFunctionAbstract|string $dep): static { $this->dependencies[] = $dep; return $this; diff --git a/src/DI/ContainerLoader.php b/src/DI/ContainerLoader.php index 3721dba80..c0e666aa2 100644 --- a/src/DI/ContainerLoader.php +++ b/src/DI/ContainerLoader.php @@ -32,9 +32,8 @@ public function __construct(string $tempDirectory, bool $autoRebuild = false) /** * @param callable $generator function (Nette\DI\Compiler $compiler): string|null - * @param mixed $key */ - public function load(callable $generator, $key = null): string + public function load(callable $generator, mixed $key = null): string { $class = $this->getClassName($key); if (!class_exists($class, false)) { @@ -45,10 +44,7 @@ public function load(callable $generator, $key = null): string } - /** - * @param mixed $key - */ - public function getClassName($key): string + public function getClassName(mixed $key): string { return 'Container_' . substr(md5(serialize($key)), 0, 10); } diff --git a/src/DI/Definitions/AccessorDefinition.php b/src/DI/Definitions/AccessorDefinition.php index 44ebd0397..aed4a0e71 100644 --- a/src/DI/Definitions/AccessorDefinition.php +++ b/src/DI/Definitions/AccessorDefinition.php @@ -24,8 +24,7 @@ final class AccessorDefinition extends Definition private ?Reference $reference = null; - /** @return static */ - public function setImplement(string $interface) + public function setImplement(string $interface): static { if (!interface_exists($interface)) { throw new Nette\InvalidArgumentException(sprintf( @@ -73,11 +72,7 @@ public function getImplement(): ?string } - /** - * @param string|Reference $reference - * @return static - */ - public function setReference($reference) + public function setReference(string|Reference $reference): static { if ($reference instanceof Reference) { $this->reference = $reference; diff --git a/src/DI/Definitions/Definition.php b/src/DI/Definitions/Definition.php index 5543ea051..31da84f77 100644 --- a/src/DI/Definitions/Definition.php +++ b/src/DI/Definitions/Definition.php @@ -31,10 +31,9 @@ abstract class Definition /** - * @return static * @internal This is managed by ContainerBuilder and should not be called by user */ - final public function setName(string $name) + final public function setName(string $name): static { if ($this->name) { throw new Nette\InvalidStateException('Name already has been set.'); @@ -51,8 +50,7 @@ final public function getName(): ?string } - /** @return static */ - protected function setType(?string $type) + protected function setType(?string $type): static { if ($this->autowired && $this->notifier && $this->type !== $type) { ($this->notifier)(); @@ -80,8 +78,7 @@ final public function getType(): ?string } - /** @return static */ - final public function setTags(array $tags) + final public function setTags(array $tags): static { $this->tags = $tags; return $this; @@ -94,29 +91,20 @@ final public function getTags(): array } - /** - * @param mixed $attr - * @return static - */ - final public function addTag(string $tag, $attr = true) + final public function addTag(string $tag, mixed $attr = true): static { $this->tags[$tag] = $attr; return $this; } - /** @return mixed */ - final public function getTag(string $tag) + final public function getTag(string $tag): mixed { return $this->tags[$tag] ?? null; } - /** - * @param bool|string|string[] $state - * @return static - */ - final public function setAutowired($state = true) + final public function setAutowired(bool|string|array $state = true): static { if ($this->notifier && $this->autowired !== $state) { ($this->notifier)(); @@ -130,14 +118,13 @@ final public function setAutowired($state = true) /** @return bool|string[] */ - final public function getAutowired() + final public function getAutowired(): bool|array { return $this->autowired; } - /** @return static */ - public function setExported(bool $state = true) + public function setExported(bool $state = true): static { return $this->addTag('nette.exported', $state); } diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index f577b0cdd..e094fe9b7 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -34,8 +34,7 @@ public function __construct() } - /** @return static */ - public function setImplement(string $interface) + public function setImplement(string $interface): static { if (!interface_exists($interface)) { throw new Nette\InvalidArgumentException(sprintf( @@ -77,8 +76,7 @@ public function getResultType(): ?string } - /** @return static */ - public function setResultDefinition(Definition $definition) + public function setResultDefinition(Definition $definition): static { $this->resultDefinition = $definition; return $this; @@ -93,7 +91,7 @@ public function getResultDefinition(): Definition /** @deprecated */ - public function setParameters(array $params) + public function setParameters(array $params): static { if ($params) { $old = $new = []; diff --git a/src/DI/Definitions/ImportedDefinition.php b/src/DI/Definitions/ImportedDefinition.php index d05948fcf..d02dc803a 100644 --- a/src/DI/Definitions/ImportedDefinition.php +++ b/src/DI/Definitions/ImportedDefinition.php @@ -18,8 +18,7 @@ */ final class ImportedDefinition extends Definition { - /** @return static */ - public function setType(?string $type) + public function setType(?string $type): static { return parent::setType($type); } diff --git a/src/DI/Definitions/LocatorDefinition.php b/src/DI/Definitions/LocatorDefinition.php index 8bf2d15d5..8e671f79c 100644 --- a/src/DI/Definitions/LocatorDefinition.php +++ b/src/DI/Definitions/LocatorDefinition.php @@ -22,8 +22,7 @@ final class LocatorDefinition extends Definition private ?string $tagged = null; - /** @return static */ - public function setImplement(string $interface) + public function setImplement(string $interface): static { if (!interface_exists($interface)) { throw new Nette\InvalidArgumentException(sprintf("Service '%s': Interface '%s' not found.", $this->getName(), $interface)); @@ -66,8 +65,7 @@ public function getImplement(): ?string } - /** @return static */ - public function setReferences(array $references) + public function setReferences(array $references): static { $this->references = []; foreach ($references as $name => $ref) { @@ -87,8 +85,7 @@ public function getReferences(): array } - /** @return static */ - public function setTagged(?string $tagged) + public function setTagged(?string $tagged): static { $this->tagged = $tagged; return $this; diff --git a/src/DI/Definitions/Reference.php b/src/DI/Definitions/Reference.php index 0ce79eea5..c6423bc1a 100644 --- a/src/DI/Definitions/Reference.php +++ b/src/DI/Definitions/Reference.php @@ -24,7 +24,7 @@ final class Reference private string $value; - public static function fromType(string $value): self + public static function fromType(string $value): static { if (strpos($value, '\\') === false) { $value = '\\' . $value; diff --git a/src/DI/Definitions/ServiceDefinition.php b/src/DI/Definitions/ServiceDefinition.php index ac07797d1..90a25d594 100644 --- a/src/DI/Definitions/ServiceDefinition.php +++ b/src/DI/Definitions/ServiceDefinition.php @@ -34,8 +34,7 @@ public function __construct() } - /** @return static */ - public function setType(?string $type) + public function setType(?string $type): static { return parent::setType($type); } @@ -43,10 +42,8 @@ public function setType(?string $type) /** * Alias for setCreator() - * @param string|array|Definition|Reference|Statement $factory - * @return static */ - public function setFactory($factory, array $args = []) + public function setFactory(string|array|Definition|Reference|Statement $factory, array $args = []): static { return $this->setCreator($factory, $args); } @@ -61,11 +58,7 @@ public function getFactory(): Statement } - /** - * @param string|array|Definition|Reference|Statement $creator - * @return static - */ - public function setCreator($creator, array $args = []) + public function setCreator(string|array|Definition|Reference|Statement $creator, array $args = []): static { $this->creator = $creator instanceof Statement ? $creator @@ -80,23 +73,20 @@ public function getCreator(): Statement } - /** @return string|array|Definition|Reference|null */ - public function getEntity() + public function getEntity(): string|array|Definition|Reference|null { return $this->creator->getEntity(); } - /** @return static */ - public function setArguments(array $args = []) + public function setArguments(array $args = []): static { $this->creator->arguments = $args; return $this; } - /** @return static */ - public function setArgument($key, $value) + public function setArgument($key, $value): static { $this->creator->arguments[$key] = $value; return $this; @@ -105,9 +95,8 @@ public function setArgument($key, $value) /** * @param Statement[] $setup - * @return static */ - public function setSetup(array $setup) + public function setSetup(array $setup): static { foreach ($setup as $v) { if (!$v instanceof Statement) { @@ -127,11 +116,7 @@ public function getSetup(): array } - /** - * @param string|array|Definition|Reference|Statement $entity - * @return static - */ - public function addSetup($entity, array $args = []) + public function addSetup(string|array|Definition|Reference|Statement $entity, array $args = []): static { $this->setup[] = $entity instanceof Statement ? $entity diff --git a/src/DI/Definitions/Statement.php b/src/DI/Definitions/Statement.php index ff4d85dcd..d77b6fe29 100644 --- a/src/DI/Definitions/Statement.php +++ b/src/DI/Definitions/Statement.php @@ -26,10 +26,7 @@ final class Statement implements Nette\Schema\DynamicParameter private string|array|Definition|Reference|null $entity; - /** - * @param string|array|Definition|Reference|null $entity - */ - public function __construct($entity, array $arguments = []) + public function __construct(string|array|Definition|Reference|null $entity, array $arguments = []) { if ( $entity !== null @@ -62,8 +59,7 @@ public function __construct($entity, array $arguments = []) } - /** @return string|array|Definition|Reference|null */ - public function getEntity() + public function getEntity(): string|array|Definition|Reference|null { return $this->entity; } diff --git a/src/DI/DependencyChecker.php b/src/DI/DependencyChecker.php index e2ea4eb51..3a648d259 100644 --- a/src/DI/DependencyChecker.php +++ b/src/DI/DependencyChecker.php @@ -30,9 +30,8 @@ class DependencyChecker /** * Adds dependencies to the list. - * @return static */ - public function add(array $deps) + public function add(array $deps): static { $this->dependencies = array_merge($this->dependencies, $deps); return $this; diff --git a/src/DI/Extensions/InjectExtension.php b/src/DI/Extensions/InjectExtension.php index 493902c5f..7f2e64a87 100644 --- a/src/DI/Extensions/InjectExtension.php +++ b/src/DI/Extensions/InjectExtension.php @@ -140,14 +140,9 @@ public static function getInjectProperties(string $class): array /** * Calls all methods starting with with "inject" using autowiring. - * @param object $service */ - public static function callInjects(DI\Container $container, $service): void + public static function callInjects(DI\Container $container, object $service): void { - if (!is_object($service)) { - throw new Nette\InvalidArgumentException(sprintf('Service must be object, %s given.', gettype($service))); - } - foreach (self::getInjectMethods($service::class) as $method) { $container->callMethod([$service, $method]); } diff --git a/src/DI/Helpers.php b/src/DI/Helpers.php index a3452f7c5..2f2e996fc 100644 --- a/src/DI/Helpers.php +++ b/src/DI/Helpers.php @@ -26,12 +26,9 @@ final class Helpers /** * Expands %placeholders%. - * @param mixed $var - * @param bool|array $recursive - * @return mixed * @throws Nette\InvalidArgumentException */ - public static function expand($var, array $params, $recursive = false) + public static function expand(mixed $var, array $params, bool|array $recursive = false): mixed { if (is_array($var)) { $res = []; @@ -113,10 +110,8 @@ public static function expand($var, array $params, $recursive = false) /** * Escapes '%' and '@' - * @param mixed $value - * @return mixed */ - public static function escape($value) + public static function escape(mixed $value): mixed { if (is_array($value)) { $res = []; @@ -165,10 +160,8 @@ public static function filterArguments(array $args): array /** * Replaces @extension with real extension name in service definition. - * @param mixed $config - * @return mixed */ - public static function prefixServiceName($config, string $namespace) + public static function prefixServiceName(mixed $config, string $namespace): mixed { if (is_string($config)) { if (strncmp($config, '@extension.', 10) === 0) { @@ -195,7 +188,6 @@ public static function prefixServiceName($config, string $namespace) /** * Returns an annotation value. - * @param \ReflectionFunctionAbstract|\ReflectionProperty|\ReflectionClass $ref */ public static function parseAnnotation(\Reflector $ref, string $name): ?string { @@ -253,11 +245,9 @@ public static function normalizeClass(string $type): string /** * Non data-loss type conversion. - * @param mixed $value - * @return mixed * @throws Nette\InvalidStateException */ - public static function convertType($value, string $type) + public static function convertType(mixed $value, string $type): mixed { if (is_scalar($value)) { $norm = ($value === false ? '0' : (string) $value); diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index c338da9b3..b4e62ef7e 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -332,8 +332,8 @@ public function completeArguments(array $arguments): array } - /** @return string|array|Reference literal, Class, Reference, [Class, member], [, globalFunc], [Reference, member], [Statement, member] */ - private function normalizeEntity(Statement $statement) + /** Returns literal, Class, Reference, [Class, member], [, globalFunc], [Reference, member], [Statement, member] */ + private function normalizeEntity(Statement $statement): string|array|Reference { $entity = $statement->getEntity(); if (is_array($entity)) { @@ -422,10 +422,8 @@ public function getByType(string $type): Reference /** * Adds item to the list of dependencies. - * @param \ReflectionClass|\ReflectionFunctionAbstract|string $dep - * @return static */ - public function addDependency($dep) + public function addDependency(\ReflectionClass|\ReflectionFunctionAbstract|string $dep): static { $this->builder->addDependency($dep); return $this; @@ -594,9 +592,8 @@ public static function autowireArguments( * Resolves missing argument using autowiring. * @param (callable(string $type, bool $single): (object|object[]|null)) $getter * @throws ServiceCreationException - * @return mixed */ - private static function autowireArgument(\ReflectionParameter $parameter, callable $getter) + private static function autowireArgument(\ReflectionParameter $parameter, callable $getter): mixed { $method = $parameter->getDeclaringFunction(); $desc = Reflection::toString($parameter); diff --git a/src/DI/exceptions.php b/src/DI/exceptions.php index b441c5ed3..83fcb526d 100644 --- a/src/DI/exceptions.php +++ b/src/DI/exceptions.php @@ -25,7 +25,7 @@ class MissingServiceException extends Nette\InvalidStateException */ class ServiceCreationException extends Nette\InvalidStateException { - public function setMessage(string $message): self + public function setMessage(string $message): static { $this->message = $message; return $this; diff --git a/tests/DI/Container.errors.phpt b/tests/DI/Container.errors.phpt index 58e5d9ee1..244c46786 100644 --- a/tests/DI/Container.errors.phpt +++ b/tests/DI/Container.errors.phpt @@ -20,10 +20,6 @@ Assert::exception(function () use ($container, $service) { $container->addService('', $service); }, Nette\InvalidArgumentException::class, 'Service name must be a non-empty string.'); -Assert::exception(function () use ($container) { - $container->addService('one', null); -}, Nette\InvalidArgumentException::class, "Service 'one' must be a object, NULL given."); - Assert::exception(function () use ($container) { $container->getService('one'); }, Nette\DI\MissingServiceException::class, "Service 'one' not found."); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 531d91951..ae30cb39f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -63,7 +63,7 @@ public static function fetch(): array } -function createContainer($source, $config = null, $params = []): ?Nette\DI\Container +function createContainer($source, $config = null, array $params = []): ?Nette\DI\Container { $class = 'Container' . md5((string) lcg_value()); if ($source instanceof Nette\DI\ContainerBuilder) { From 4c81807aebd9b23ea9debb0639fce892eab3a508 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 11 Mar 2021 21:52:44 +0100 Subject: [PATCH 27/44] removed community health files --- .github/ISSUE_TEMPLATE/Bug_report.md | 19 ------------- .github/ISSUE_TEMPLATE/Feature_request.md | 9 ------ .github/ISSUE_TEMPLATE/Support_question.md | 12 -------- .github/ISSUE_TEMPLATE/Support_us.md | 21 -------------- .github/funding.yml | 2 -- .github/pull_request_template.md | 11 -------- contributing.md | 33 ---------------------- 7 files changed, 107 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/Bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/Feature_request.md delete mode 100644 .github/ISSUE_TEMPLATE/Support_question.md delete mode 100644 .github/ISSUE_TEMPLATE/Support_us.md delete mode 100644 .github/funding.yml delete mode 100644 .github/pull_request_template.md delete mode 100644 contributing.md diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md deleted file mode 100644 index a4cd12634..000000000 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: "🐛 Bug Report" -about: "If something isn't working as expected 🤔" - ---- - -Version: ?.?.? - -### Bug Description -... A clear and concise description of what the bug is. A good bug report shouldn't leave others needing to chase you up for more information. - -### Steps To Reproduce -... If possible a minimal demo of the problem ... - -### Expected Behavior -... A clear and concise description of what you expected to happen. - -### Possible Solution -... Only if you have suggestions on a fix for the bug diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md deleted file mode 100644 index d2e219489..000000000 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: "🚀 Feature Request" -about: "I have a suggestion (and may want to implement it) 🙂" - ---- - -- Is your feature request related to a problem? Please describe. -- Explain your intentions. -- It's up to you to make a strong case to convince the project's developers of the merits of this feature. diff --git a/.github/ISSUE_TEMPLATE/Support_question.md b/.github/ISSUE_TEMPLATE/Support_question.md deleted file mode 100644 index 75c48b6ed..000000000 --- a/.github/ISSUE_TEMPLATE/Support_question.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: "🤗 Support Question" -about: "If you have a question 💬, please check out our forum!" - ---- - ---------------^ Click "Preview" for a nicer view! -We primarily use GitHub as an issue tracker; for usage and support questions, please check out these resources below. Thanks! 😁. - -* Nette Forum: https://forum.nette.org -* Nette Gitter: https://gitter.im/nette/nette -* Slack (czech): https://pehapkari.slack.com/messages/C2R30BLKA diff --git a/.github/ISSUE_TEMPLATE/Support_us.md b/.github/ISSUE_TEMPLATE/Support_us.md deleted file mode 100644 index 92d8a4c3a..000000000 --- a/.github/ISSUE_TEMPLATE/Support_us.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: "❤️ Support us" -about: "If you would like to support our efforts in maintaining this project 🙌" - ---- - ---------------^ Click "Preview" for a nicer view! - -> https://nette.org/donate - -Help support Nette! - -We develop Nette Framework for more than 14 years. In order to make your life more comfortable. Nette cares about the safety of your sites. Nette saves you time. And gives job opportunities. - -Nette earns you money. And is absolutely free. - -To ensure future development and improving the documentation, we need your donation. - -Whether you are chief of IT company which benefits from Nette, or developer who goes for advice on our forum, if you like Nette, [please make a donation now](https://nette.org/donate). - -Thank you! diff --git a/.github/funding.yml b/.github/funding.yml deleted file mode 100644 index 25adc9520..000000000 --- a/.github/funding.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: dg -custom: "https://nette.org/donate" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index f8aa3f408..000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,11 +0,0 @@ -- bug fix / new feature? -- BC break? yes/no -- doc PR: nette/docs#??? - - diff --git a/contributing.md b/contributing.md deleted file mode 100644 index 184152c02..000000000 --- a/contributing.md +++ /dev/null @@ -1,33 +0,0 @@ -How to contribute & use the issue tracker -========================================= - -Nette welcomes your contributions. There are several ways to help out: - -* Create an issue on GitHub, if you have found a bug -* Write test cases for open bug issues -* Write fixes for open bug/feature issues, preferably with test cases included -* Contribute to the [documentation](https://nette.org/en/writing) - -Issues ------- - -Please **do not use the issue tracker to ask questions**. We will be happy to help you -on [Nette forum](https://forum.nette.org) or chat with us on [Gitter](https://gitter.im/nette/nette). - -A good bug report shouldn't leave others needing to chase you up for more -information. Please try to be as detailed as possible in your report. - -**Feature requests** are welcome. But take a moment to find out whether your idea -fits with the scope and aims of the project. It's up to *you* to make a strong -case to convince the project's developers of the merits of this feature. - -Contributing ------------- - -If you'd like to contribute, please take a moment to read [the contributing guide](https://nette.org/en/contributing). - -The best way to propose a feature is to discuss your ideas on [Nette forum](https://forum.nette.org) before implementing them. - -Please do not fix whitespace, format code, or make a purely cosmetic patch. - -Thanks! :heart: From b7c88e2b44040f45fa6ab2e2038df72e824ca8b8 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 10 Mar 2022 04:20:27 +0100 Subject: [PATCH 28/44] used PHP 8 features --- src/DI/Autowiring.php | 2 +- src/DI/CompilerExtension.php | 2 +- src/DI/Config/Adapters/NeonAdapter.php | 4 ++-- src/DI/Definitions/AccessorDefinition.php | 2 +- src/DI/Definitions/LocatorDefinition.php | 2 +- src/DI/Definitions/Reference.php | 6 +++--- src/DI/Definitions/Statement.php | 4 ++-- src/DI/DependencyChecker.php | 2 +- src/DI/Extensions/InjectExtension.php | 2 +- src/DI/Extensions/SearchExtension.php | 2 +- src/DI/PhpGenerator.php | 4 ++-- src/DI/Resolver.php | 8 ++++---- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/DI/Autowiring.php b/src/DI/Autowiring.php index 3e88a4df7..dbc72f60f 100644 --- a/src/DI/Autowiring.php +++ b/src/DI/Autowiring.php @@ -63,7 +63,7 @@ public function getByType(string $type, bool $throw = false): ?string } else { $list = $types[$type]; natsort($list); - $hint = count($list) === 2 && ($tmp = strpos($list[0], '.') xor strpos($list[1], '.')) + $hint = count($list) === 2 && ($tmp = str_contains($list[0], '.') xor str_contains($list[1], '.')) ? '. If you want to overwrite service ' . $list[$tmp ? 0 : 1] . ', give it proper name.' : ''; throw new ServiceCreationException(sprintf( diff --git a/src/DI/CompilerExtension.php b/src/DI/CompilerExtension.php index 7e59b9c74..680570822 100644 --- a/src/DI/CompilerExtension.php +++ b/src/DI/CompilerExtension.php @@ -137,7 +137,7 @@ public function getInitialization(): Nette\PhpGenerator\Closure */ public function prefix(string $id): string { - return substr_replace($id, $this->name . '.', substr($id, 0, 1) === '@' ? 1 : 0, 0); + return substr_replace($id, $this->name . '.', str_starts_with($id, '@') ? 1 : 0, 0); } diff --git a/src/DI/Config/Adapters/NeonAdapter.php b/src/DI/Config/Adapters/NeonAdapter.php index e5b81651d..c335fb930 100644 --- a/src/DI/Config/Adapters/NeonAdapter.php +++ b/src/DI/Config/Adapters/NeonAdapter.php @@ -54,7 +54,7 @@ public function process(array $arr): array { $res = []; foreach ($arr as $key => $val) { - if (is_string($key) && substr($key, -1) === self::PreventMergingSuffix) { + if (is_string($key) && str_ends_with($key, self::PreventMergingSuffix)) { if (!is_array($val) && $val !== null) { throw new Nette\DI\InvalidConfigurationException(sprintf( "Replacing operator is available only for arrays, item '%s' is not array (used in '%s')", @@ -83,7 +83,7 @@ public function process(array $arr): array $val = $tmp; } else { $tmp = $this->process([$val->value]); - if (is_string($tmp[0]) && strpos($tmp[0], '?') !== false) { + if (is_string($tmp[0]) && str_contains($tmp[0], '?')) { throw new Nette\DI\InvalidConfigurationException("Operator ? is deprecated in config file (used in '$this->file')"); } diff --git a/src/DI/Definitions/AccessorDefinition.php b/src/DI/Definitions/AccessorDefinition.php index aed4a0e71..f3e60d569 100644 --- a/src/DI/Definitions/AccessorDefinition.php +++ b/src/DI/Definitions/AccessorDefinition.php @@ -77,7 +77,7 @@ public function setReference(string|Reference $reference): static if ($reference instanceof Reference) { $this->reference = $reference; } else { - $this->reference = substr($reference, 0, 1) === '@' + $this->reference = str_starts_with($reference, '@') ? new Reference(substr($reference, 1)) : Reference::fromType($reference); } diff --git a/src/DI/Definitions/LocatorDefinition.php b/src/DI/Definitions/LocatorDefinition.php index 8e671f79c..b0deb2a9d 100644 --- a/src/DI/Definitions/LocatorDefinition.php +++ b/src/DI/Definitions/LocatorDefinition.php @@ -69,7 +69,7 @@ public function setReferences(array $references): static { $this->references = []; foreach ($references as $name => $ref) { - $this->references[$name] = substr($ref, 0, 1) === '@' + $this->references[$name] = str_starts_with($ref, '@') ? new Reference(substr($ref, 1)) : Reference::fromType($ref); } diff --git a/src/DI/Definitions/Reference.php b/src/DI/Definitions/Reference.php index c6423bc1a..5396d15fd 100644 --- a/src/DI/Definitions/Reference.php +++ b/src/DI/Definitions/Reference.php @@ -26,7 +26,7 @@ final class Reference public static function fromType(string $value): static { - if (strpos($value, '\\') === false) { + if (!str_contains($value, '\\')) { $value = '\\' . $value; } @@ -48,13 +48,13 @@ public function getValue(): string public function isName(): bool { - return strpos($this->value, '\\') === false && $this->value !== self::SELF; + return !str_contains($this->value, '\\') && $this->value !== self::SELF; } public function isType(): bool { - return strpos($this->value, '\\') !== false; + return str_contains($this->value, '\\'); } diff --git a/src/DI/Definitions/Statement.php b/src/DI/Definitions/Statement.php index d77b6fe29..dd7f44bd9 100644 --- a/src/DI/Definitions/Statement.php +++ b/src/DI/Definitions/Statement.php @@ -48,9 +48,9 @@ public function __construct(string|array|Definition|Reference|null $entity, arra $entity = explode('::', $entity, 2); } - if (is_string($entity) && substr($entity, 0, 1) === '@') { // normalize @service to Reference + if (is_string($entity) && str_starts_with($entity, '@')) { // normalize @service to Reference $entity = new Reference(substr($entity, 1)); - } elseif (is_array($entity) && is_string($entity[0]) && substr($entity[0], 0, 1) === '@') { + } elseif (is_array($entity) && is_string($entity[0]) && str_starts_with($entity[0], '@')) { $entity[0] = new Reference(substr($entity[0], 1)); } diff --git a/src/DI/DependencyChecker.php b/src/DI/DependencyChecker.php index 3a648d259..dd32e5f4c 100644 --- a/src/DI/DependencyChecker.php +++ b/src/DI/DependencyChecker.php @@ -140,7 +140,7 @@ class_uses($name), $flip = array_flip($classes); foreach ($functions as $name) { - if (strpos($name, '::')) { + if (str_contains($name, '::')) { $method = new ReflectionMethod($name); $class = $method->getDeclaringClass(); if (isset($flip[$class->name])) { diff --git a/src/DI/Extensions/InjectExtension.php b/src/DI/Extensions/InjectExtension.php index 7f2e64a87..28f4313d8 100644 --- a/src/DI/Extensions/InjectExtension.php +++ b/src/DI/Extensions/InjectExtension.php @@ -90,7 +90,7 @@ public static function getInjectMethods(string $class): array { $classes = []; foreach (get_class_methods($class) as $name) { - if (substr($name, 0, 6) === 'inject') { + if (str_starts_with($name, 'inject')) { $classes[$name] = (new \ReflectionMethod($class, $name))->getDeclaringClass()->name; } } diff --git a/src/DI/Extensions/SearchExtension.php b/src/DI/Extensions/SearchExtension.php index c530531b2..771f82b55 100644 --- a/src/DI/Extensions/SearchExtension.php +++ b/src/DI/Extensions/SearchExtension.php @@ -140,7 +140,7 @@ private static function buildNameRegexp(array $masks): ?string { $res = []; foreach ((array) $masks as $mask) { - $mask = (strpos($mask, '\\') === false ? '**\\' : '') . $mask; + $mask = (str_contains($mask, '\\') ? '' : '**\\') . $mask; $mask = preg_quote($mask, '#'); $mask = str_replace('\*\*\\\\', '(.*\\\\)?', $mask); $mask = str_replace('\\\\\*\*', '(\\\\.*)?', $mask); diff --git a/src/DI/PhpGenerator.php b/src/DI/PhpGenerator.php index cf71b1985..65687c08a 100644 --- a/src/DI/PhpGenerator.php +++ b/src/DI/PhpGenerator.php @@ -128,7 +128,7 @@ public function formatStatement(Statement $statement): string switch (true) { case $entity[1][0] === '$': // property getter, setter or appender $name = substr($entity[1], 1); - if ($append = (substr($name, -2) === '[]')) { + if ($append = (str_ends_with($name, '[]'))) { $name = substr($name, 0, -2); } @@ -141,7 +141,7 @@ public function formatStatement(Statement $statement): string case $entity[0] instanceof Statement: $inner = $this->formatPhp('?', [$entity[0]]); - if (substr($inner, 0, 4) === 'new ') { + if (str_starts_with($inner, 'new ')) { $inner = "($inner)"; } diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index b4e62ef7e..90c5d22e3 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -263,7 +263,7 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo case $entity[0] instanceof Reference: if ($entity[1][0] === '$') { // property getter, setter or appender Validators::assert($arguments, 'list:0..1', "setup arguments for '" . Callback::toString($entity) . "'"); - if (!$arguments && substr($entity[1], -2) === '[]') { + if (!$arguments && str_ends_with($entity[1], '[]')) { throw new ServiceCreationException(sprintf('Missing argument for %s.', $entity[1])); } } elseif ( @@ -291,7 +291,7 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo try { $arguments = $this->completeArguments($arguments); } catch (ServiceCreationException $e) { - if (!strpos($e->getMessage(), ' (used in')) { + if (!str_contains($e->getMessage(), ' (used in')) { $e->setMessage($e->getMessage() . " (used in {$this->entityToString($entity)})"); } @@ -432,7 +432,7 @@ public function addDependency(\ReflectionClass|\ReflectionFunctionAbstract|strin private function completeException(\Throwable $e, Definition $def): ServiceCreationException { - if ($e instanceof ServiceCreationException && Strings::startsWith($e->getMessage(), "Service '")) { + if ($e instanceof ServiceCreationException && str_starts_with($e->getMessage(), "Service '")) { return $e; } @@ -499,7 +499,7 @@ private function convertReferences(array $arguments): array } else { // @service::property $val = new Statement([new Reference($pair[0]), '$' . $pair[1]]); } - } elseif (is_string($val) && substr($val, 0, 2) === '@@') { // escaped text @@ + } elseif (is_string($val) && str_starts_with($val, '@@')) { // escaped text @@ $val = substr($val, 1); } }); From 8b82e51d6b8aa18334e5245da7150d53a665a908 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 24 Sep 2021 14:07:27 +0200 Subject: [PATCH 29/44] deprecated magic properties except for $entity (BC break) --- src/DI/Definitions/ServiceDefinition.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DI/Definitions/ServiceDefinition.php b/src/DI/Definitions/ServiceDefinition.php index 90a25d594..bf799aacc 100644 --- a/src/DI/Definitions/ServiceDefinition.php +++ b/src/DI/Definitions/ServiceDefinition.php @@ -16,9 +16,9 @@ /** * Definition of standard service. * - * @property string|null $class - * @property Statement $factory - * @property Statement[] $setup + * @property-deprecated string|null $class + * @property-deprecated Statement $factory + * @property-deprecated Statement[] $setup */ final class ServiceDefinition extends Definition { From 050a14d1a39c9cf3eae4338531049c884319406b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 28 Sep 2021 12:50:02 +0200 Subject: [PATCH 30/44] removed option 'parameters' used by generated factories (BC break) --- src/DI/Definitions/FactoryDefinition.php | 49 +----------- src/DI/Extensions/DefinitionSchema.php | 7 -- src/DI/Extensions/ServicesExtension.php | 4 - src/DI/PhpGenerator.php | 23 ------ ...r.generatedFactory.nullableParameters.phpt | 75 ------------------- tests/DI/Compiler.generatedFactory.phpt | 1 - ...Compiler.generatedFactory.returnTypes.phpt | 8 +- ...ler.generatedFactory.scalarParameters.phpt | 63 ---------------- tests/DI/ContainerBuilder.factory.params.phpt | 15 ---- .../DI/Definitions.FactoryDefinition.api.phpt | 9 --- tests/DI/files/compiler.generatedFactory.neon | 7 +- 11 files changed, 7 insertions(+), 254 deletions(-) delete mode 100644 tests/DI/Compiler.generatedFactory.nullableParameters.phpt delete mode 100644 tests/DI/Compiler.generatedFactory.scalarParameters.phpt diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index e094fe9b7..dce87d88c 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -13,7 +13,6 @@ use Nette\DI\Helpers; use Nette\DI\ServiceCreationException; use Nette\PhpGenerator as Php; -use Nette\Utils\Reflection; use Nette\Utils\Type; @@ -24,7 +23,6 @@ final class FactoryDefinition extends Definition { private const MethodCreate = 'create'; - public array $parameters = []; private Definition $resultDefinition; @@ -90,37 +88,6 @@ public function getResultDefinition(): Definition } - /** @deprecated */ - public function setParameters(array $params): static - { - if ($params) { - $old = $new = []; - foreach ($params as $k => $v) { - $tmp = explode(' ', is_int($k) ? $v : $k); - $old[] = '%' . end($tmp) . '%'; - $new[] = '$' . end($tmp); - } - - trigger_error(sprintf( - "Service '%s': Option 'parameters' is deprecated and should be removed. The %s should be replaced with %s in configuration.", - $this->getName(), - implode(', ', $old), - implode(', ', $new), - ), E_USER_DEPRECATED); - } - - $this->parameters = $params; - return $this; - } - - - /** @deprecated */ - public function getParameters(): array - { - return $this->parameters; - } - - public function resolveType(Nette\DI\Resolver $resolver): void { $interface = $this->getType(); @@ -158,9 +125,7 @@ public function complete(Nette\DI\Resolver $resolver): void $resultDef = $this->resultDefinition; if ($resultDef instanceof ServiceDefinition) { - if (!$this->parameters) { - $this->completeParameters($resolver); - } + $this->completeParameters($resolver); $this->convertArguments($resultDef->getCreator()->arguments); foreach ($resultDef->getSetup() as $setup) { @@ -195,11 +160,10 @@ private function completeParameters(Nette\DI\Resolver $resolver): void } foreach ($method->getParameters() as $param) { - $methodType = Type::fromReflection($param); if (isset($ctorParams[$param->name])) { $ctorParam = $ctorParams[$param->name]; $ctorType = Type::fromReflection($ctorParam); - if ($ctorType && !$ctorType->allows((string) $methodType)) { + if ($ctorType && !$ctorType->allows((string) Type::fromReflection($param))) { throw new ServiceCreationException(sprintf( "Type of \$%s in %s::create() doesn't match type in %s constructor.", $param->name, @@ -218,13 +182,6 @@ private function completeParameters(Nette\DI\Resolver $resolver): void $interface, ) . ($hint ? ", did you mean \${$hint}?" : '.')); } - - $paramDef = $methodType . ' ' . $param->name; - if ($param->isDefaultValueAvailable()) { - $this->parameters[$paramDef] = Reflection::getParameterDefaultValue($param); - } else { - $this->parameters[] = $paramDef; - } } } @@ -260,7 +217,7 @@ public function generateMethod(Php\Method $method, Nette\DI\PhpGenerator $genera $rm = new \ReflectionMethod($this->getType(), self::MethodCreate); $methodCreate - ->setParameters($generator->convertParameters($this->parameters)) + ->setParameters(array_map([new Php\Factory, 'fromParameterReflection'], $rm->getParameters())) ->setReturnType((string) (Type::fromReflection($rm) ?? $this->getResultType())) ->setBody($body); diff --git a/src/DI/Extensions/DefinitionSchema.php b/src/DI/Extensions/DefinitionSchema.php index c604943fb..9bf29a823 100644 --- a/src/DI/Extensions/DefinitionSchema.php +++ b/src/DI/Extensions/DefinitionSchema.php @@ -179,12 +179,6 @@ private function sniffType($key, array $def): string private function expandParameters(array $config): array { $params = $this->builder->parameters; - if (isset($config['parameters'])) { - foreach ((array) $config['parameters'] as $k => $v) { - $v = explode(' ', is_int($k) ? $v : $k); - $params[end($v)] = $this->builder::literal('$' . end($v)); - } - } return Nette\DI\Helpers::expand($config, $params); } @@ -240,7 +234,6 @@ private static function getFactorySchema(): Schema 'implement' => Expect::string(), 'arguments' => Expect::array(), 'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'), - 'parameters' => Expect::array(), 'references' => Expect::array(), 'tagged' => Expect::string(), 'inject' => Expect::bool(), diff --git a/src/DI/Extensions/ServicesExtension.php b/src/DI/Extensions/ServicesExtension.php index e6b7cee6d..d913d145c 100644 --- a/src/DI/Extensions/ServicesExtension.php +++ b/src/DI/Extensions/ServicesExtension.php @@ -170,10 +170,6 @@ private function updateFactoryDefinition(Definitions\FactoryDefinition $definiti } } - if (isset($config->parameters)) { - $definition->setParameters($config->parameters); - } - if (isset($config->inject)) { $definition->addTag(InjectExtension::TAG_INJECT, $config->inject); } diff --git a/src/DI/PhpGenerator.php b/src/DI/PhpGenerator.php index 65687c08a..edbeefeb8 100644 --- a/src/DI/PhpGenerator.php +++ b/src/DI/PhpGenerator.php @@ -187,29 +187,6 @@ public function formatPhp(string $statement, array $args): string } - /** - * Converts parameters from Definition to PhpGenerator. - * @return Php\Parameter[] - */ - public function convertParameters(array $parameters): array - { - $res = []; - foreach ($parameters as $k => $v) { - $tmp = explode(' ', is_int($k) ? $v : $k); - $param = $res[] = new Php\Parameter(end($tmp)); - if (!is_int($k)) { - $param->setDefaultValue($v); - } - - if (isset($tmp[1])) { - $param->setType($tmp[0]); - } - } - - return $res; - } - - public function getClassName(): ?string { return $this->className; diff --git a/tests/DI/Compiler.generatedFactory.nullableParameters.phpt b/tests/DI/Compiler.generatedFactory.nullableParameters.phpt deleted file mode 100644 index 929af4eea..000000000 --- a/tests/DI/Compiler.generatedFactory.nullableParameters.phpt +++ /dev/null @@ -1,75 +0,0 @@ -title = $title; - $this->foo = $foo; - $this->lorem = $lorem; - } -} - -$compiler = new DI\Compiler; -// parameters are deprecated -$container = @createContainer($compiler, ' -services: - - article: - factory: Article(%title%, %foo%, %lorem%) - implement: IArticleFactory - parameters: [?string title, ?Foo foo, ?int lorem: null] - - article2: - implement: IArticleFactory - arguments: [%title%, %foo%, %lorem%] - parameters: [?string title, ?Foo foo, ?int lorem: null] - - article3: - implement: IArticleFactory -'); - -foreach (['article', 'article2', 'article3'] as $serviceName) { - $service = $container->getService($serviceName); - Assert::type(IArticleFactory::class, $service); - $article = $service->create('lorem-ipsum', $foo = new Foo, 1); - Assert::type(Article::class, $article); - Assert::same('lorem-ipsum', $article->title); - Assert::same($foo, $article->foo); - Assert::same(1, $article->lorem); - - $article = $service->create(null, null); - Assert::type(Article::class, $article); - Assert::null($article->title); - Assert::null($article->foo); - Assert::same($serviceName === 'article3' ? 1 : null, $article->lorem); -} diff --git a/tests/DI/Compiler.generatedFactory.phpt b/tests/DI/Compiler.generatedFactory.phpt index d3b5dd3ee..cf74b71bb 100644 --- a/tests/DI/Compiler.generatedFactory.phpt +++ b/tests/DI/Compiler.generatedFactory.phpt @@ -139,7 +139,6 @@ class TestExtension extends DI\CompilerExtension { $builder = $this->getContainerBuilder(); $builder->addFactoryDefinition('fooFactory2') - ->setParameters(['Baz baz' => null]) ->setImplement(IFooFactory::class) ->getResultDefinition() ->setCreator(Foo::class) diff --git a/tests/DI/Compiler.generatedFactory.returnTypes.phpt b/tests/DI/Compiler.generatedFactory.returnTypes.phpt index 15a4d097c..aa3dc92bf 100644 --- a/tests/DI/Compiler.generatedFactory.returnTypes.phpt +++ b/tests/DI/Compiler.generatedFactory.returnTypes.phpt @@ -34,18 +34,14 @@ class FooArticle extends Article } $compiler = new DI\Compiler; -// parameters are deprecated -$container = @createContainer($compiler, ' +$container = createContainer($compiler, ' services: article: - factory: Article(%title%) + factory: Article implement: IArticleFactory - parameters: [title] article2: implement: IArticleFactory - arguments: [%title%] - parameters: [title] article3: implement: IArticleFactory diff --git a/tests/DI/Compiler.generatedFactory.scalarParameters.phpt b/tests/DI/Compiler.generatedFactory.scalarParameters.phpt deleted file mode 100644 index 68666489d..000000000 --- a/tests/DI/Compiler.generatedFactory.scalarParameters.phpt +++ /dev/null @@ -1,63 +0,0 @@ -title = $title; - } -} - -$compiler = new DI\Compiler; -// parameters are deprecated -$container = @createContainer($compiler, ' -services: - article: - factory: Article(%title%) - implement: IArticleFactory - parameters: [string title] - - article2: - implement: IArticleFactory - arguments: [%title%] - parameters: [string title] - - article3: - implement: IArticleFactory -'); - -Assert::type(IArticleFactory::class, $container->getService('article')); -$article = $container->getService('article')->create('lorem-ipsum'); -Assert::type(Article::class, $article); -Assert::same('lorem-ipsum', $article->title); - -Assert::type(IArticleFactory::class, $container->getService('article2')); -$article = $container->getService('article2')->create('lorem-ipsum'); -Assert::type(Article::class, $article); -Assert::same('lorem-ipsum', $article->title); - -Assert::type(IArticleFactory::class, $container->getService('article3')); -$article = $container->getService('article3')->create('lorem-ipsum'); -Assert::type(Article::class, $article); -Assert::same('lorem-ipsum', $article->title); diff --git a/tests/DI/ContainerBuilder.factory.params.phpt b/tests/DI/ContainerBuilder.factory.params.phpt index 4b44ac44c..fcadb2165 100644 --- a/tests/DI/ContainerBuilder.factory.params.phpt +++ b/tests/DI/ContainerBuilder.factory.params.phpt @@ -26,13 +26,6 @@ $builder->addFactoryDefinition('one') ->setCreator(stdClass::class) ->addSetup('$a', [$builder::literal('$a')]); -@$builder->addFactoryDefinition('two') - ->setParameters(['stdClass foo', 'array bar', 'foobar' => null]) // parameters is deprecated - ->setImplement(StdClassFactory::class) - ->getResultDefinition() - ->setCreator(stdClass::class) - ->addSetup('$a', [$builder::literal('$foo')]); - $builder->addDefinition('three') ->setType(stdClass::class); @@ -40,18 +33,10 @@ $builder->addDefinition('four') ->setCreator('@one::create', [1 => [1]]) ->setAutowired(false); -$builder->addDefinition('five') - ->setCreator('@two::create', [1 => [1]]) - ->setAutowired(false); - $container = createContainer($builder); Assert::type(StdClassFactory::class, $container->getService('one')); -Assert::type(StdClassFactory::class, $container->getService('two')); Assert::type(stdClass::class, $container->getService('four')); Assert::same($container->getService('four')->a, $container->getService('three')); - -Assert::type(stdClass::class, $container->getService('five')); -Assert::same($container->getService('five')->a, $container->getService('three')); diff --git a/tests/DI/Definitions.FactoryDefinition.api.phpt b/tests/DI/Definitions.FactoryDefinition.api.phpt index 526aba439..1860e1531 100644 --- a/tests/DI/Definitions.FactoryDefinition.api.phpt +++ b/tests/DI/Definitions.FactoryDefinition.api.phpt @@ -90,15 +90,6 @@ Assert::noError(function () { }); -test('', function () { - $def = new FactoryDefinition; - $def->setImplement(Good1::class); - - @$def->setParameters(['a' => 1]); // parameters are deprecated - Assert::same(['a' => 1], $def->getParameters()); -}); - - test('', function () { $def = new FactoryDefinition; $def->setImplement(Good1::class); diff --git a/tests/DI/files/compiler.generatedFactory.neon b/tests/DI/files/compiler.generatedFactory.neon index c26a79b9c..ee9ffa756 100644 --- a/tests/DI/files/compiler.generatedFactory.neon +++ b/tests/DI/files/compiler.generatedFactory.neon @@ -8,9 +8,8 @@ services: finder: IFinderFactory article: - create: Article(%title%) + create: Article($title) implement: IArticleFactory - parameters: [title] setup: - method(@self::ABC) - $prop = @self::ABC @@ -18,12 +17,10 @@ services: article2: implement: IArticleFactory arguments: [$title] - parameters: [title] fooFactory1: - create: Foo(_, %baz%) + create: Foo(_, $baz) implement: IFooFactory - parameters: [Baz baz = null] fooFactory3: type: Foo From 6d7ea49e8a9b6be7ed0e257d564f359a744e37b2 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 28 Sep 2021 13:58:39 +0200 Subject: [PATCH 31/44] removed deprecated ConstantsExtension & PhpExtension (BC break) --- src/DI/Extensions/ConstantsExtension.php | 28 ------------ src/DI/Extensions/PhpExtension.php | 54 ------------------------ tests/DI/ConstantsExtension.basic.phpt | 26 ------------ 3 files changed, 108 deletions(-) delete mode 100644 src/DI/Extensions/ConstantsExtension.php delete mode 100644 src/DI/Extensions/PhpExtension.php delete mode 100644 tests/DI/ConstantsExtension.basic.phpt diff --git a/src/DI/Extensions/ConstantsExtension.php b/src/DI/Extensions/ConstantsExtension.php deleted file mode 100644 index 3d34fb5f3..000000000 --- a/src/DI/Extensions/ConstantsExtension.php +++ /dev/null @@ -1,28 +0,0 @@ -getConfig() as $name => $value) { - $this->initialization->addBody('define(?, ?);', [$name, $value]); - } - } -} diff --git a/src/DI/Extensions/PhpExtension.php b/src/DI/Extensions/PhpExtension.php deleted file mode 100644 index 117bdfe84..000000000 --- a/src/DI/Extensions/PhpExtension.php +++ /dev/null @@ -1,54 +0,0 @@ -getConfig() as $name => $value) { - if ($value === null) { - continue; - - } elseif ($name === 'include_path') { - $this->initialization->addBody('set_include_path(?);', [str_replace(';', PATH_SEPARATOR, $value)]); - - } elseif ($name === 'ignore_user_abort') { - $this->initialization->addBody('ignore_user_abort(?);', [$value]); - - } elseif ($name === 'max_execution_time') { - $this->initialization->addBody('set_time_limit(?);', [$value]); - - } elseif ($name === 'date.timezone') { - $this->initialization->addBody('date_default_timezone_set(?);', [$value]); - - } elseif (function_exists('ini_set')) { - $this->initialization->addBody('ini_set(?, ?);', [$name, $value === false ? '0' : (string) $value]); - - } elseif (ini_get($name) !== (string) $value) { - throw new Nette\NotSupportedException('Required function ini_set() is disabled.'); - } - } - } -} diff --git a/tests/DI/ConstantsExtension.basic.phpt b/tests/DI/ConstantsExtension.basic.phpt deleted file mode 100644 index 925c641d8..000000000 --- a/tests/DI/ConstantsExtension.basic.phpt +++ /dev/null @@ -1,26 +0,0 @@ -addExtension('constants', new Nette\DI\Extensions\ConstantsExtension); -$container = @createContainer($compiler, ' -constants: - a: hello - A: WORLD -'); -$container->initialize(); - -Assert::same('hello', a); -Assert::same('WORLD', A); From bbefc9ce7f339b5dd15ababdd1e10536ae883886 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 20 Oct 2021 00:22:51 +0200 Subject: [PATCH 32/44] three ... dots throws exception (BC break) --- src/DI/Config/Adapters/NeonAdapter.php | 2 +- tests/DI/NeonAdapter.preprocess.phpt | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/DI/Config/Adapters/NeonAdapter.php b/src/DI/Config/Adapters/NeonAdapter.php index c335fb930..5af1e6908 100644 --- a/src/DI/Config/Adapters/NeonAdapter.php +++ b/src/DI/Config/Adapters/NeonAdapter.php @@ -169,7 +169,7 @@ public function removeUnderscoreVisitor(Neon\Node $node) $index = true; } elseif ($attr->value instanceof Neon\Node\LiteralNode && $attr->value->value === '...') { - trigger_error("Replace ... with _ in configuration file '$this->file'.", E_USER_DEPRECATED); + throw new Nette\DI\InvalidConfigurationException("Replace ... with _ in configuration file '$this->file'."); unset($node->attributes[$i]); $index = true; } diff --git a/tests/DI/NeonAdapter.preprocess.phpt b/tests/DI/NeonAdapter.preprocess.phpt index 89552d5bc..a39209eff 100644 --- a/tests/DI/NeonAdapter.preprocess.phpt +++ b/tests/DI/NeonAdapter.preprocess.phpt @@ -70,17 +70,6 @@ Assert::equal( ); -// ... deprecated -$data = @$adapter->load(Tester\FileMock::create(' -- Class(arg1, ..., [...]) -', 'neon')); - -Assert::equal( - [new Statement('Class', ['arg1', 2 => ['...']])], - $data, -); - - // @ escaping $data = @$adapter->load(Tester\FileMock::create(' - @@double From 3ebc450b5b3eb5480df45291d8e6f57a58ca49b6 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 26 Sep 2021 23:11:18 +0200 Subject: [PATCH 33/44] exception messages use [Service ...]\n format [WIP] added Definition::getDescriptor(), Helpers::entityToString() --- src/DI/Definitions/AccessorDefinition.php | 14 +-- src/DI/Definitions/Definition.php | 27 ++++- src/DI/Definitions/FactoryDefinition.php | 13 ++- src/DI/Definitions/LocatorDefinition.php | 14 +-- src/DI/Definitions/ServiceDefinition.php | 11 ++ src/DI/Extensions/InjectExtension.php | 20 ++++ src/DI/Extensions/ServicesExtension.php | 9 +- src/DI/Helpers.php | 33 +++++- src/DI/PhpGenerator.php | 2 +- src/DI/Resolver.php | 70 ++++-------- tests/DI/Compiler.configOverride.phpt | 3 +- .../DI/Compiler.extensionOverride.errors.phpt | 3 +- tests/DI/Compiler.functions.phpt | 4 +- tests/DI/Compiler.generatedFactory.phpt | 9 +- .../ContainerBuilder.autowiring.novalue.phpt | 6 +- tests/DI/ContainerBuilder.create.error.phpt | 104 +++++++++++++----- tests/DI/ContainerBuilder.error.phpt | 30 ++++- tests/DI/ContainerBuilder.recursive.phpt | 3 +- tests/DI/ContainerBuilder.resolveTypes.phpt | 27 +++-- tests/DI/ContainerBuilder.selfdependency.phpt | 4 +- .../Definitions.AccessorDefinition.api.phpt | 21 ++-- ...efinitions.AccessorDefinition.resolve.phpt | 9 +- .../DI/Definitions.FactoryDefinition.api.phpt | 18 ++- ...Definitions.FactoryDefinition.resolve.phpt | 9 +- tests/DI/Definitions.ImportedDefinition.phpt | 6 +- .../DI/Definitions.LocatorDefinition.api.phpt | 24 ++-- ...Definitions.LocatorDefinition.resolve.phpt | 3 +- tests/DI/Definitions.ServiceDefinition.phpt | 3 +- tests/DI/InjectExtension.errors.phpt | 9 +- .../DI/Resolver.autowireArguments.errors.phpt | 6 +- 30 files changed, 352 insertions(+), 162 deletions(-) diff --git a/src/DI/Definitions/AccessorDefinition.php b/src/DI/Definitions/AccessorDefinition.php index f3e60d569..85e3bc171 100644 --- a/src/DI/Definitions/AccessorDefinition.php +++ b/src/DI/Definitions/AccessorDefinition.php @@ -28,8 +28,8 @@ public function setImplement(string $interface): static { if (!interface_exists($interface)) { throw new Nette\InvalidArgumentException(sprintf( - "Service '%s': Interface '%s' not found.", - $this->getName(), + "[%s]\nInterface '%s' not found.", + $this->getDescriptor(), $interface, )); } @@ -44,20 +44,20 @@ public function setImplement(string $interface): static || count($rc->getMethods()) > 1 ) { throw new Nette\InvalidArgumentException(sprintf( - "Service '%s': Interface %s must have just one non-static method get().", - $this->getName(), + "[%s]\nInterface %s must have just one non-static method get().", + $this->getDescriptor(), $interface, )); } elseif ($method->getNumberOfParameters()) { throw new Nette\InvalidArgumentException(sprintf( - "Service '%s': Method %s::get() must have no parameters.", - $this->getName(), + "[%s]\nMethod %s::get() must have no parameters.", + $this->getDescriptor(), $interface, )); } try { - Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::get()"); + Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::get()", $this->getDescriptor()); } catch (Nette\DI\ServiceCreationException $e) { trigger_error($e->getMessage(), E_USER_DEPRECATED); } diff --git a/src/DI/Definitions/Definition.php b/src/DI/Definitions/Definition.php index 31da84f77..530698ce8 100644 --- a/src/DI/Definitions/Definition.php +++ b/src/DI/Definitions/Definition.php @@ -50,6 +50,29 @@ final public function getName(): ?string } + final public function isAnonymous(): bool + { + return !$this->name || ctype_digit($this->name); + } + + + public function getDescriptor(): string + { + if (!$this->isAnonymous()) { + return "Service '$this->name'" . ($this->type ? " of type $this->type" : ''); + + } elseif ($this->type) { + return "Service of type $this->type"; + + } elseif ($this->name) { + return "Service '$this->name'"; + + } else { + return 'Service ?'; + } + } + + protected function setType(?string $type): static { if ($this->autowired && $this->notifier && $this->type !== $type) { @@ -60,8 +83,8 @@ protected function setType(?string $type): static $this->type = null; } elseif (!class_exists($type) && !interface_exists($type)) { throw new Nette\InvalidArgumentException(sprintf( - "Service '%s': Class or interface '%s' not found.", - $this->name, + "[%s]\nClass or interface '%s' not found.", + $this->getDescriptor(), $type, )); } else { diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index dce87d88c..5023ca123 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -36,8 +36,8 @@ public function setImplement(string $interface): static { if (!interface_exists($interface)) { throw new Nette\InvalidArgumentException(sprintf( - "Service '%s': Interface '%s' not found.", - $this->getName(), + "[%s]\nInterface '%s' not found.", + $this->getDescriptor(), $interface, )); } @@ -46,14 +46,14 @@ public function setImplement(string $interface): static $method = $rc->getMethods()[0] ?? null; if (!$method || $method->isStatic() || $method->name !== self::MethodCreate || count($rc->getMethods()) > 1) { throw new Nette\InvalidArgumentException(sprintf( - "Service '%s': Interface %s must have just one non-static method create().", - $this->getName(), + "[%s]\nInterface %s must have just one non-static method create().", + $this->getDescriptor(), $interface, )); } try { - Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::create()"); + Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::create()", $this->getDescriptor()); } catch (Nette\DI\ServiceCreationException $e) { trigger_error($e->getMessage(), E_USER_DEPRECATED); } @@ -112,7 +112,8 @@ public function resolveType(Nette\DI\Resolver $resolver): void if ($type && !$type->allows($resultDef->getType())) { throw new ServiceCreationException(sprintf( - 'Factory for %s cannot create incompatible %s type.', + "[%s]\nFactory for %s cannot create incompatible %s type.", + $this->getDescriptor(), $type, $resultDef->getType(), )); diff --git a/src/DI/Definitions/LocatorDefinition.php b/src/DI/Definitions/LocatorDefinition.php index b0deb2a9d..ea8ef4108 100644 --- a/src/DI/Definitions/LocatorDefinition.php +++ b/src/DI/Definitions/LocatorDefinition.php @@ -25,12 +25,12 @@ final class LocatorDefinition extends Definition public function setImplement(string $interface): static { if (!interface_exists($interface)) { - throw new Nette\InvalidArgumentException(sprintf("Service '%s': Interface '%s' not found.", $this->getName(), $interface)); + throw new Nette\InvalidArgumentException(sprintf("[%s]\nInterface '%s' not found.", $this->getDescriptor(), $interface)); } $methods = (new \ReflectionClass($interface))->getMethods(); if (!$methods) { - throw new Nette\InvalidArgumentException(sprintf("Service '%s': Interface %s must have at least one method.", $this->getName(), $interface)); + throw new Nette\InvalidArgumentException(sprintf("[%s]\nInterface %s must have at least one method.", $this->getDescriptor(), $interface)); } foreach ($methods as $method) { @@ -39,8 +39,8 @@ public function setImplement(string $interface): static || (preg_match('#^(get|create)[A-Z]#', $method->name) && $method->getNumberOfParameters() === 0) )) { throw new Nette\InvalidArgumentException(sprintf( - "Service '%s': Method %s::%s() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static.", - $this->getName(), + "[%s]\nMethod %s::%s() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static.", + $this->getDescriptor(), $interface, $method->name, )); @@ -48,7 +48,7 @@ public function setImplement(string $interface): static if ($method->getNumberOfParameters() === 0) { try { - Nette\DI\Helpers::ensureClassType(Nette\Utils\Type::fromReflection($method), "return type of $interface::$method->name()", true); + Nette\DI\Helpers::ensureClassType(Nette\Utils\Type::fromReflection($method), "return type of $interface::$method->name()", $this->getDescriptor(), true); } catch (Nette\DI\ServiceCreationException $e) { trigger_error($e->getMessage(), E_USER_DEPRECATED); } @@ -110,8 +110,8 @@ public function complete(Nette\DI\Resolver $resolver): void foreach ($resolver->getContainerBuilder()->findByTag($this->tagged) as $name => $tag) { if (isset($this->references[$tag])) { trigger_error(sprintf( - "Service '%s': duplicated tag '%s' with value '%s'.", - $this->getName(), + "[%s]\nDuplicated tag '%s' with value '%s'.", + $this->getDescriptor(), $this->tagged, $tag, ), E_USER_NOTICE); diff --git a/src/DI/Definitions/ServiceDefinition.php b/src/DI/Definitions/ServiceDefinition.php index bf799aacc..79b06f7d0 100644 --- a/src/DI/Definitions/ServiceDefinition.php +++ b/src/DI/Definitions/ServiceDefinition.php @@ -34,6 +34,17 @@ public function __construct() } + public function getDescriptor(): string + { + $entity = $this->getEntity(); + if ($entity && $this->isAnonymous()) { + return 'Service ' . (is_string($entity) ? "of type $entity" : Nette\DI\Helpers::entityToString($entity)); + } + + return parent::getDescriptor(); + } + + public function setType(?string $type): static { return parent::setType($type); diff --git a/src/DI/Extensions/InjectExtension.php b/src/DI/Extensions/InjectExtension.php index 28f4313d8..a73030c18 100644 --- a/src/DI/Extensions/InjectExtension.php +++ b/src/DI/Extensions/InjectExtension.php @@ -63,6 +63,7 @@ private function updateDefinition(Definitions\ServiceDefinition $def): void } } + self::checkType($class, $property, $type, $builder, $def); array_unshift($setups, $inject); } @@ -148,7 +149,26 @@ public static function callInjects(DI\Container $container, object $service): vo } foreach (self::getInjectProperties($service::class) as $property => $type) { + self::checkType($service, $property, $type, $container); $service->$property = $container->getByType($type); } } + + + private static function checkType( + object|string $class, + string $name, + ?string $type, + DI\Container|DI\ContainerBuilder|null $container, + Definitions\Definition $def = null, + ): void { + if ($container && !$container->getByType($type, false)) { + throw new Nette\DI\MissingServiceException(sprintf( + "%sService of type %s required by %s not found.\nDid you add it to configuration file?", + $def ? '[' . $def->getDescriptor() . "]\n" : '', + $type, + Reflection::toString(new \ReflectionProperty($class, $name)), + )); + } + } } diff --git a/src/DI/Extensions/ServicesExtension.php b/src/DI/Extensions/ServicesExtension.php index d913d145c..7d0dd0238 100644 --- a/src/DI/Extensions/ServicesExtension.php +++ b/src/DI/Extensions/ServicesExtension.php @@ -55,7 +55,7 @@ private function loadDefinition(?string $name, \stdClass $config): void $this->getContainerBuilder()->removeDefinition($name); return; } elseif (!empty($config->alteration) && !$this->getContainerBuilder()->hasDefinition($name)) { - throw new Nette\DI\InvalidConfigurationException('missing original definition for alteration.'); + throw new Nette\DI\InvalidConfigurationException('Missing original definition for alteration.'); } $def = $this->retrieveDefinition($name, $config); @@ -70,7 +70,12 @@ private function loadDefinition(?string $name, \stdClass $config): void $this->{$methods[$config->defType]}($def, $config); $this->updateDefinition($def, $config); } catch (\Throwable $e) { - throw new Nette\DI\InvalidConfigurationException(($name ? "Service '$name': " : '') . $e->getMessage(), 0, $e); + $message = $e->getMessage(); + if ($name && !str_starts_with($message, '[Service ')) { + $message = "[Service '$name']\n$message"; + } + + throw new Nette\DI\InvalidConfigurationException($message, 0, $e); } } diff --git a/src/DI/Helpers.php b/src/DI/Helpers.php index 2f2e996fc..c86aad863 100644 --- a/src/DI/Helpers.php +++ b/src/DI/Helpers.php @@ -218,17 +218,22 @@ public static function getReturnTypeAnnotation(\ReflectionFunctionAbstract $func } - public static function ensureClassType(?Type $type, string $hint, bool $allowNullable = false): string - { + public static function ensureClassType( + ?Type $type, + string $hint, + string $descriptor = '', + bool $allowNullable = false, + ): string { + $descriptor = $descriptor ? "[$descriptor]\n" : ''; if (!$type) { - throw new ServiceCreationException(sprintf('%s is not declared.', ucfirst($hint))); + throw new ServiceCreationException(sprintf('%s%s is not declared.', $descriptor, ucfirst($hint))); } elseif (!$type->isClass() || (!$allowNullable && $type->isUnion())) { - throw new ServiceCreationException(sprintf("%s is not expected to be %sunion/intersection/built-in, '%s' given.", ucfirst($hint), $allowNullable ? '' : 'nullable/', $type)); + throw new ServiceCreationException(sprintf("%s%s is not expected to be %sunion/intersection/built-in, '%s' given.", $descriptor, ucfirst($hint), $allowNullable ? '' : 'nullable/', $type)); } $class = $type->getSingleName(); if (!class_exists($class) && !interface_exists($class)) { - throw new ServiceCreationException(sprintf("Class '%s' not found.\nCheck the %s.", $class, $hint)); + throw new ServiceCreationException(sprintf("%sClass '%s' not found.\nCheck the %s.", $descriptor, $class, $hint)); } return $class; @@ -268,4 +273,22 @@ public static function convertType(mixed $value, string $type): mixed $type, )); } + + + public static function entityToString(string|array|Reference $entity, bool $inner = false): string + { + if (is_string($entity)) { + return $entity . ($inner ? '()' : ''); + + } elseif ($entity instanceof Reference) { + return '@' . $entity->getValue(); + + } else { + [$a, $b] = $entity; + return self::entityToString($a instanceof Statement ? $a->entity : $a, true) + . '::' + . $b + . (str_contains($b, '$') ? '' : '()'); + } + } } diff --git a/src/DI/PhpGenerator.php b/src/DI/PhpGenerator.php index edbeefeb8..e861ce494 100644 --- a/src/DI/PhpGenerator.php +++ b/src/DI/PhpGenerator.php @@ -102,7 +102,7 @@ public function generateMethod(Definitions\Definition $def): Php\Method return $method; } catch (\Throwable $e) { - throw new ServiceCreationException("Service '$name': " . $e->getMessage(), 0, $e); + throw new ServiceCreationException(sprintf("[%s]\n%s", $def->getDescriptor(), $e->getMessage()), 0, $e); } } diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 90c5d22e3..6d5505a38 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -290,9 +290,21 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo try { $arguments = $this->completeArguments($arguments); + } catch (ServiceCreationException $e) { - if (!str_contains($e->getMessage(), ' (used in')) { - $e->setMessage($e->getMessage() . " (used in {$this->entityToString($entity)})"); + if (!str_contains($e->getMessage(), "\nRelated to")) { + if (is_string($entity)) { + $desc = $entity . '::__construct()'; + } else { + $desc = Helpers::entityToString($entity); + $desc = preg_replace('~@self::~A', '', $desc); + } + + if ($currentServiceAllowed) { + $desc .= ' in setup'; + } + + $e->setMessage($e->getMessage() . "\nRelated to $desc."); } throw $e; @@ -432,25 +444,16 @@ public function addDependency(\ReflectionClass|\ReflectionFunctionAbstract|strin private function completeException(\Throwable $e, Definition $def): ServiceCreationException { - if ($e instanceof ServiceCreationException && str_starts_with($e->getMessage(), "Service '")) { + $message = $e->getMessage(); + if ($e instanceof ServiceCreationException && str_starts_with($message, '[Service ')) { return $e; } - $name = $def->getName(); - $type = $def->getType(); - if ($name && !ctype_digit($name)) { - $message = "Service '$name'" . ($type ? " (type of $type)" : '') . ': '; - } elseif ($type) { - $message = "Service of type $type: "; - } elseif ($def instanceof Definitions\ServiceDefinition && $def->getEntity()) { - $message = 'Service (' . $this->entityToString($def->getEntity()) . '): '; - } else { - $message = ''; + if ($tmp = $def->getType()) { + $message = str_replace(" $tmp::", ' ' . preg_replace('~.*\\\\~', '', $tmp) . '::', $message); } - $message .= $type - ? str_replace("$type::", preg_replace('~.*\\\\~', '', $type) . '::', $e->getMessage()) - : $e->getMessage(); + $message = '[' . $def->getDescriptor() . "]\n" . $message; return $e instanceof ServiceCreationException ? $e->setMessage($message) @@ -458,35 +461,6 @@ private function completeException(\Throwable $e, Definition $def): ServiceCreat } - private function entityToString($entity): string - { - $referenceToText = function (Reference $ref): string { - return $ref->isSelf() && $this->currentService - ? '@' . $this->currentService->getName() - : '@' . $ref->getValue(); - }; - if (is_string($entity)) { - return $entity . '::__construct()'; - } elseif ($entity instanceof Reference) { - $entity = $referenceToText($entity); - } elseif (is_array($entity)) { - if (strpos($entity[1], '$') === false) { - $entity[1] .= '()'; - } - - if ($entity[0] instanceof Reference) { - $entity[0] = $referenceToText($entity[0]); - } elseif (!is_string($entity[0])) { - return $entity[1]; - } - - return implode('::', $entity); - } - - return (string) $entity; - } - - private function convertReferences(array $arguments): array { array_walk_recursive($arguments, function (&$val): void { @@ -612,20 +586,20 @@ private static function autowireArgument(\ReflectionParameter $parameter, callab } catch (MissingServiceException $e) { $res = null; } catch (ServiceCreationException $e) { - throw new ServiceCreationException("{$e->getMessage()} (required by $desc)", 0, $e); + throw new ServiceCreationException(sprintf("%s\nRequired by %s.", $e->getMessage(), $desc), 0, $e); } if ($res !== null || $parameter->allowsNull()) { return $res; } elseif (class_exists($class) || interface_exists($class)) { throw new ServiceCreationException(sprintf( - 'Service of type %s required by %s not found. Did you add it to configuration file?', + "Service of type %s required by %s not found.\nDid you add it to configuration file?", $class, $desc, )); } else { throw new ServiceCreationException(sprintf( - "Class '%s' required by %s not found. Check the parameter type and 'use' statements.", + "Class '%s' required by %s not found.\nCheck the parameter type and 'use' statements.", $class, $desc, )); diff --git a/tests/DI/Compiler.configOverride.phpt b/tests/DI/Compiler.configOverride.phpt index 20669e361..63aa223f2 100644 --- a/tests/DI/Compiler.configOverride.phpt +++ b/tests/DI/Compiler.configOverride.phpt @@ -59,4 +59,5 @@ $compiler->addConfig([ Assert::exception(function () use ($compiler, $class) { $compiler->setClassName($class) ->compile(); -}, DI\InvalidConfigurationException::class, "Service 's3': missing original definition for alteration."); +}, DI\InvalidConfigurationException::class, "[Service 's3'] +Missing original definition for alteration."); diff --git a/tests/DI/Compiler.extensionOverride.errors.phpt b/tests/DI/Compiler.extensionOverride.errors.phpt index a4b942814..945f0e5b5 100644 --- a/tests/DI/Compiler.extensionOverride.errors.phpt +++ b/tests/DI/Compiler.extensionOverride.errors.phpt @@ -21,4 +21,5 @@ services: bad: alteration: yes '); -}, Nette\DI\InvalidConfigurationException::class, "Service 'bad': missing original definition for alteration."); +}, Nette\DI\InvalidConfigurationException::class, "[Service 'bad'] +Missing original definition for alteration."); diff --git a/tests/DI/Compiler.functions.phpt b/tests/DI/Compiler.functions.phpt index dfc4aaca1..58596d7da 100644 --- a/tests/DI/Compiler.functions.phpt +++ b/tests/DI/Compiler.functions.phpt @@ -85,4 +85,6 @@ Assert::exception(function () { services: - Service(bool(123, 10)) '); -}, Nette\InvalidStateException::class, 'Service of type Service: Function bool() expects 1 parameter, 2 given. (used in Service::__construct())'); +}, Nette\InvalidStateException::class, '[Service of type Service] +Function bool() expects 1 parameter, 2 given. +Related to Service::__construct().'); diff --git a/tests/DI/Compiler.generatedFactory.phpt b/tests/DI/Compiler.generatedFactory.phpt index cf74b71bb..ff448c758 100644 --- a/tests/DI/Compiler.generatedFactory.phpt +++ b/tests/DI/Compiler.generatedFactory.phpt @@ -278,7 +278,8 @@ Assert::exception(function () { $builder->addFactoryDefinition('one') ->setImplement(Bad2::class); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of Bad2): Type of \$bar in Bad2::create() doesn't match type in Bad1 constructor."); +}, Nette\InvalidStateException::class, "[Service 'one' of type Bad2] +Type of \$bar in Bad2::create() doesn't match type in Bad1 constructor."); @@ -299,7 +300,8 @@ Assert::exception(function () { $builder->addFactoryDefinition('one') ->setImplement(Bad4::class); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of Bad4): Unused parameter \$baz when implementing method Bad4::create(), did you mean \$bar?"); +}, Nette\InvalidStateException::class, "[Service 'one' of type Bad4] +Unused parameter \$baz when implementing method Bad4::create(), did you mean \$bar?"); @@ -320,7 +322,8 @@ Assert::exception(function () { $builder->addFactoryDefinition('one') ->setImplement(Bad6::class); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of Bad6): Unused parameter \$baz when implementing method Bad6::create()."); +}, Nette\InvalidStateException::class, "[Service 'one' of type Bad6] +Unused parameter \$baz when implementing method Bad6::create()."); diff --git a/tests/DI/ContainerBuilder.autowiring.novalue.phpt b/tests/DI/ContainerBuilder.autowiring.novalue.phpt index 1a9b7cca4..3aee26fda 100644 --- a/tests/DI/ContainerBuilder.autowiring.novalue.phpt +++ b/tests/DI/ContainerBuilder.autowiring.novalue.phpt @@ -24,7 +24,8 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('foo')->setType(Foo::class); $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'foo' (type of Foo): Parameter \$x in Foo::__construct() has no class type or default value, so its value must be specified."); +}, Nette\DI\ServiceCreationException::class, "[Service 'foo' of type Foo] +Parameter \$x in Foo::__construct() has no class type or default value, so its value must be specified."); class Bar @@ -38,7 +39,8 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('foo')->setType(Bar::class); $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'foo' (type of Bar): Parameter \$x in Bar::__construct() has no class type or default value, so its value must be specified."); +}, Nette\DI\ServiceCreationException::class, "[Service 'foo' of type Bar] +Parameter \$x in Bar::__construct() has no class type or default value, so its value must be specified."); class Bar2 diff --git a/tests/DI/ContainerBuilder.create.error.phpt b/tests/DI/ContainerBuilder.create.error.phpt index 5cbbdbe75..b78d406e6 100644 --- a/tests/DI/ContainerBuilder.create.error.phpt +++ b/tests/DI/ContainerBuilder.create.error.phpt @@ -18,14 +18,16 @@ require __DIR__ . '/../bootstrap.php'; Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setType('X')->setCreator('Unknown'); -}, Nette\InvalidArgumentException::class, "Service 'one': Class or interface 'X' not found."); +}, Nette\InvalidArgumentException::class, "[Service 'one'] +Class or interface 'X' not found."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition(null)->setCreator('Unknown'); $builder->complete(); -}, Nette\DI\ServiceCreationException::class, "Service (Unknown::__construct()): Class 'Unknown' not found."); +}, Nette\DI\ServiceCreationException::class, "[Service of type Unknown] +Class 'Unknown' not found."); Assert::exception(function () { @@ -33,7 +35,8 @@ Assert::exception(function () { $builder->addDefinition('one')->setCreator('@two'); $builder->addDefinition('two')->setCreator('Unknown'); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'two': Class 'Unknown' not found."); +}, Nette\InvalidStateException::class, "[Service 'two'] +Class 'Unknown' not found."); Assert::exception(function () { @@ -41,28 +44,32 @@ Assert::exception(function () { $builder->addDefinition('one')->setCreator(new Reference('two')); $builder->addDefinition('two')->setCreator('Unknown'); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'two': Class 'Unknown' not found."); +}, Nette\InvalidStateException::class, "[Service 'two'] +Class 'Unknown' not found."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setCreator('stdClass::foo'); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one': Method stdClass::foo() is not callable."); +}, Nette\InvalidStateException::class, "[Service 'one'] +Method stdClass::foo() is not callable."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setCreator('Nette\DI\Container::foo'); // has __magic $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one': Method Nette\\DI\\Container::foo() is not callable."); +}, Nette\InvalidStateException::class, "[Service 'one'] +Method Nette\\DI\\Container::foo() is not callable."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addFactoryDefinition('one') ->setImplement('Unknown'); -}, Nette\InvalidArgumentException::class, "Service 'one': Interface 'Unknown' not found."); +}, Nette\InvalidArgumentException::class, "[Service 'one'] +Interface 'Unknown' not found."); @@ -76,7 +83,8 @@ Assert::exception(function () { @$builder->addFactoryDefinition('one') ->setImplement(Bad4::class); // missing type triggers warning $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of Bad4): Return type of Bad4::create() is not declared."); +}, Nette\InvalidStateException::class, "[Service 'one' of type Bad4] +Return type of Bad4::create() is not declared."); interface Bad5 @@ -89,7 +97,8 @@ Assert::exception(function () { $builder->addAccessorDefinition('one') ->setImplement(Bad5::class); $builder->complete(); -}, Nette\InvalidArgumentException::class, "Service 'one': Method Bad5::get() must have no parameters."); +}, Nette\InvalidArgumentException::class, "[Service 'one'] +Method Bad5::get() must have no parameters."); class Bad6 @@ -103,7 +112,8 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setCreator('Bad6::create'); $builder->complete(); -}, Nette\DI\ServiceCreationException::class, "Service 'one': Method Bad6::create() is not callable."); +}, Nette\DI\ServiceCreationException::class, "[Service 'one'] +Method Bad6::create() is not callable."); class Bad7 @@ -117,7 +127,8 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setCreator('Bad7::create'); $builder->complete(); -}, Nette\DI\ServiceCreationException::class, "Service 'one': Unknown service type, specify it or declare return type of factory method."); +}, Nette\DI\ServiceCreationException::class, "[Service 'one'] +Unknown service type, specify it or declare return type of factory method."); class Bad8 @@ -131,7 +142,8 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setType(Bad8::class); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of Bad8): Class Bad8 has private constructor."); +}, Nette\InvalidStateException::class, "[Service 'one' of type Bad8] +Class Bad8 has private constructor."); class Good @@ -146,14 +158,18 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setCreator(Good::class, [new Statement('Unknown')]); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class 'Unknown' not found. (used in Good::__construct())"); +}, Nette\InvalidStateException::class, "[Service 'one' of type Good] +Class 'Unknown' not found. +Related to Good::__construct()."); // fail in argument Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setCreator(Good::class, [new Statement(Bad8::class)]); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Bad8 has private constructor. (used in Good::__construct())"); +}, Nette\InvalidStateException::class, "[Service 'one' of type Good] +Class Bad8 has private constructor. +Related to Good::__construct()."); abstract class Bad9 @@ -168,7 +184,8 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setType(Bad9::class); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of Bad9): Class Bad9 is abstract."); +}, Nette\InvalidStateException::class, "[Service 'one' of type Bad9] +Class Bad9 is abstract."); trait Bad10 @@ -183,7 +200,8 @@ Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('one')->setCreator('Bad10::method'); $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one': Method Bad10::method() is not callable."); +}, Nette\InvalidStateException::class, "[Service 'one'] +Method Bad10::method() is not callable."); class ConstructorParam @@ -208,7 +226,9 @@ services: b: stdClass bad: ConstructorParam '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of ConstructorParam): Multiple services of type stdClass found: a, b (required by \$x in ConstructorParam::__construct())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type ConstructorParam] +Multiple services of type stdClass found: a, b +Required by \$x in ConstructorParam::__construct()."); // forced autowiring fail @@ -219,7 +239,9 @@ services: b: stdClass bad: ConstructorParam(@\stdClass) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of ConstructorParam): Multiple services of type stdClass found: a, b (used in ConstructorParam::__construct())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type ConstructorParam] +Multiple services of type stdClass found: a, b +Related to ConstructorParam::__construct()."); // autowiring fail in chain @@ -230,7 +252,9 @@ services: b: stdClass bad: MethodParam()::foo() '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (required by \$x in MethodParam::foo())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type MethodParam] +Multiple services of type stdClass found: a, b +Required by \$x in MethodParam::foo()."); // forced autowiring fail in chain @@ -241,7 +265,9 @@ services: b: stdClass bad: MethodParam()::foo(@\stdClass) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (used in foo())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type MethodParam] +Multiple services of type stdClass found: a, b +Related to MethodParam()::foo()."); // autowiring fail in argument @@ -252,7 +278,10 @@ services: b: stdClass bad: Good(ConstructorParam()) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (required by \$x in ConstructorParam::__construct()) (used in Good::__construct())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type Good] +Multiple services of type stdClass found: a, b +Required by \$x in ConstructorParam::__construct(). +Related to Good::__construct()."); // forced autowiring fail in argument @@ -263,7 +292,9 @@ services: b: stdClass bad: Good(ConstructorParam(@\stdClass)) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in ConstructorParam::__construct())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type Good] +Multiple services of type stdClass found: a, b +Related to ConstructorParam::__construct()."); // autowiring fail in chain in argument @@ -274,7 +305,10 @@ services: b: stdClass bad: Good(MethodParam()::foo()) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (required by \$x in MethodParam::foo()) (used in Good::__construct())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type Good] +Multiple services of type stdClass found: a, b +Required by \$x in MethodParam::foo(). +Related to Good::__construct()."); // forced autowiring fail in chain in argument @@ -285,7 +319,9 @@ services: b: stdClass bad: Good(MethodParam()::foo(@\stdClass)) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in foo())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type Good] +Multiple services of type stdClass found: a, b +Related to MethodParam()::foo()."); // forced autowiring fail in property passing @@ -299,7 +335,9 @@ services: setup: - $a = @\stdClass '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in @bad::\$a)"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type Good] +Multiple services of type stdClass found: a, b +Related to \$a in setup."); // autowiring fail in rich property passing @@ -313,7 +351,9 @@ services: setup: - $a = MethodParam()::foo(@\stdClass) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in foo())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type Good] +Multiple services of type stdClass found: a, b +Related to MethodParam()::foo() in setup."); // autowiring fail in method calling @@ -327,7 +367,9 @@ services: setup: - foo '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (required by \$x in MethodParam::foo())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type MethodParam] +Multiple services of type stdClass found: a, b +Required by \$x in MethodParam::foo()."); // forced autowiring fail in method calling @@ -341,7 +383,9 @@ services: setup: - bar(@\stdClass) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in @bad::bar())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type Good] +Multiple services of type stdClass found: a, b +Related to bar() in setup."); // autowiring fail in rich method calling @@ -355,4 +399,6 @@ services: setup: - bar(MethodParam()::foo(@\stdClass)) '); -}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in foo())"); +}, Nette\DI\ServiceCreationException::class, "[Service 'bad' of type Good] +Multiple services of type stdClass found: a, b +Related to MethodParam()::foo() in setup."); diff --git a/tests/DI/ContainerBuilder.error.phpt b/tests/DI/ContainerBuilder.error.phpt index 3bef4bab2..46e690429 100644 --- a/tests/DI/ContainerBuilder.error.phpt +++ b/tests/DI/ContainerBuilder.error.phpt @@ -7,6 +7,7 @@ declare(strict_types=1); use Nette\DI; +use Nette\DI\Definitions\Statement; use Tester\Assert; @@ -20,7 +21,8 @@ $builder->addDefinition('one') Assert::exception(function () use ($builder) { $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of stdClass): Expected function, method or property name, '1234' given."); +}, Nette\InvalidStateException::class, "[Service 'one' of type stdClass] +Expected function, method or property name, '1234' given."); @@ -43,4 +45,28 @@ $builder->addDefinition('one') Assert::exception(function () use ($builder) { $builder->complete(); -}, Nette\InvalidStateException::class, "Service 'one' (type of stdClass): Missing argument for \$prop[]."); +}, Nette\InvalidStateException::class, "[Service 'one' of type stdClass] +Missing argument for \$prop[]."); + + + +$builder = new DI\ContainerBuilder; +$builder->addDefinition(null) + ->setFactory([new Statement('Unknown'), 'foo']); + +Assert::exception(function () use ($builder) { + $builder->complete(); +}, Nette\DI\ServiceCreationException::class, "[Service Unknown()::foo()] +Class 'Unknown' not found."); + + + +$builder = new DI\ContainerBuilder; +$builder->addDefinition(null) + ->setFactory('stdClass') + ->addSetup([new Statement('Unknown'), 'foo']); + +Assert::exception(function () use ($builder) { + $builder->complete(); +}, Nette\DI\ServiceCreationException::class, "[Service of type stdClass] +Class 'Unknown' not found."); diff --git a/tests/DI/ContainerBuilder.recursive.phpt b/tests/DI/ContainerBuilder.recursive.phpt index 86a668d1f..d7ba6ff54 100644 --- a/tests/DI/ContainerBuilder.recursive.phpt +++ b/tests/DI/ContainerBuilder.recursive.phpt @@ -29,4 +29,5 @@ $builder->addDefinition('two') Assert::exception(function () use ($builder) { $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'two': Circular reference detected for services: one, two."); +}, Nette\DI\ServiceCreationException::class, "[Service 'two'] +Circular reference detected for services: one, two."); diff --git a/tests/DI/ContainerBuilder.resolveTypes.phpt b/tests/DI/ContainerBuilder.resolveTypes.phpt index 05d2142b9..a3504eaf8 100644 --- a/tests/DI/ContainerBuilder.resolveTypes.phpt +++ b/tests/DI/ContainerBuilder.resolveTypes.phpt @@ -125,63 +125,72 @@ Assert::exception(function () { $builder->addDefinition('a') ->setCreator([Factory::class, 'createNullableClass']); $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createNullableClass() is not expected to be nullable/union/intersection/built-in, '?stdClass' given."); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Return type of Factory::createNullableClass() is not expected to be nullable/union/intersection/built-in, '?stdClass' given."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setCreator([Factory::class, 'createScalarPhpDoc']); $container = @createContainer($builder); // @return is deprecated -}, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createScalarPhpDoc() is not expected to be nullable/union/intersection/built-in, 'array' given."); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Return type of Factory::createScalarPhpDoc() is not expected to be nullable/union/intersection/built-in, 'array' given."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setCreator([Factory::class, 'createScalar']); $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createScalar() is not expected to be nullable/union/intersection/built-in, 'array' given."); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Return type of Factory::createScalar() is not expected to be nullable/union/intersection/built-in, 'array' given."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setCreator([Factory::class, 'createObjectPhpDoc']); $container = @createContainer($builder); // @return is deprecated -}, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setCreator([Factory::class, 'createObject']); $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setCreator([Factory::class, 'createObjectNullable']); $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'a': Return type of Factory::createObjectNullable() is not expected to be nullable/union/intersection/built-in, '?object' given."); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Return type of Factory::createObjectNullable() is not expected to be nullable/union/intersection/built-in, '?object' given."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setCreator([Factory::class, 'createMixedPhpDoc']); $container = @createContainer($builder); // @return is deprecated -}, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setCreator([Factory::class, 'createMixed']); $container = createContainer($builder); -}, Nette\DI\ServiceCreationException::class, "Service 'a': Unknown service type, specify it or declare return type of factory method."); +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Unknown service type, specify it or declare return type of factory method."); Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') ->setCreator([Factory::class, 'createGeneric']); $container = @createContainer($builder); // @return is deprecated -}, Nette\DI\ServiceCreationException::class, "Service 'a': Class 'T' not found. +}, Nette\DI\ServiceCreationException::class, "[Service 'a'] +Class 'T' not found. Check the return type of Factory::createGeneric()."); Assert::exception(function () { diff --git a/tests/DI/ContainerBuilder.selfdependency.phpt b/tests/DI/ContainerBuilder.selfdependency.phpt index a418c2639..b23d6e9dc 100644 --- a/tests/DI/ContainerBuilder.selfdependency.phpt +++ b/tests/DI/ContainerBuilder.selfdependency.phpt @@ -27,4 +27,6 @@ $builder->addDefinition(null) Assert::exception(function () use ($builder) { createContainer($builder); -}, Nette\DI\ServiceCreationException::class, 'Service of type Foo: Service of type Foo required by $foo in Foo::__construct() not found. Did you add it to configuration file?'); +}, Nette\DI\ServiceCreationException::class, '[Service of type Foo] +Service of type Foo required by $foo in Foo::__construct() not found. +Did you add it to configuration file?'); diff --git a/tests/DI/Definitions.AccessorDefinition.api.phpt b/tests/DI/Definitions.AccessorDefinition.api.phpt index ff3a9fbf1..47f7d7436 100644 --- a/tests/DI/Definitions.AccessorDefinition.api.phpt +++ b/tests/DI/Definitions.AccessorDefinition.api.phpt @@ -55,43 +55,50 @@ Assert::exception(function () { Assert::exception(function () { $def = new AccessorDefinition; $def->setImplement('Foo'); -}, Nette\InvalidArgumentException::class, "Service '': Interface 'Foo' not found."); +}, Nette\InvalidArgumentException::class, "[Service ?] +Interface 'Foo' not found."); Assert::exception(function () { $def = new AccessorDefinition; $def->setImplement(stdClass::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface 'stdClass' not found."); +}, Nette\InvalidArgumentException::class, "[Service ?] +Interface 'stdClass' not found."); Assert::exception(function () { $def = new AccessorDefinition; $def->setImplement(Bad1::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad1 must have just one non-static method get()."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad1 must have just one non-static method get().'); Assert::exception(function () { $def = new AccessorDefinition; $def->setImplement(Bad2::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad2 must have just one non-static method get()."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad2 must have just one non-static method get().'); Assert::exception(function () { $def = new AccessorDefinition; $def->setImplement(Bad3::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad3 must have just one non-static method get()."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad3 must have just one non-static method get().'); Assert::exception(function () { $def = new AccessorDefinition; $def->setImplement(Bad4::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad4 must have just one non-static method get()."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad4 must have just one non-static method get().'); Assert::exception(function () { $def = new AccessorDefinition; $def->setImplement(Bad5::class); -}, Nette\InvalidArgumentException::class, "Service '': Method Bad5::get() must have no parameters."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Method Bad5::get() must have no parameters.'); Assert::noError(function () { diff --git a/tests/DI/Definitions.AccessorDefinition.resolve.phpt b/tests/DI/Definitions.AccessorDefinition.resolve.phpt index 5c7270a1f..10752fe8c 100644 --- a/tests/DI/Definitions.AccessorDefinition.resolve.phpt +++ b/tests/DI/Definitions.AccessorDefinition.resolve.phpt @@ -28,7 +28,8 @@ Assert::exception(function () { $def = new AccessorDefinition; $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Type of service is unknown.'); +}, Nette\DI\ServiceCreationException::class, '[Service ?] +Type of service is unknown.'); Assert::exception(function () { @@ -37,7 +38,8 @@ Assert::exception(function () { $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); $resolver->completeDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Service of type Bad1: Return type of Bad1::get() is not declared.'); +}, Nette\DI\ServiceCreationException::class, '[Service of type Bad1] +Return type of Bad1::get() is not declared.'); Assert::noError(function () { @@ -66,4 +68,5 @@ Assert::exception(function () { $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); $resolver->completeDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Service of type Good1: Service of type stdClass not found. Did you add it to configuration file?'); +}, Nette\DI\ServiceCreationException::class, '[Service of type Good1] +Service of type stdClass not found. Did you add it to configuration file?'); diff --git a/tests/DI/Definitions.FactoryDefinition.api.phpt b/tests/DI/Definitions.FactoryDefinition.api.phpt index 1860e1531..60af96c8c 100644 --- a/tests/DI/Definitions.FactoryDefinition.api.phpt +++ b/tests/DI/Definitions.FactoryDefinition.api.phpt @@ -49,37 +49,43 @@ Assert::exception(function () { Assert::exception(function () { $def = new FactoryDefinition; $def->setImplement('Foo'); -}, Nette\InvalidArgumentException::class, "Service '': Interface 'Foo' not found."); +}, Nette\InvalidArgumentException::class, "[Service ?] +Interface 'Foo' not found."); Assert::exception(function () { $def = new FactoryDefinition; $def->setImplement(stdClass::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface 'stdClass' not found."); +}, Nette\InvalidArgumentException::class, "[Service ?] +Interface 'stdClass' not found."); Assert::exception(function () { $def = new FactoryDefinition; $def->setImplement(Bad1::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad1 must have just one non-static method create()."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad1 must have just one non-static method create().'); Assert::exception(function () { $def = new FactoryDefinition; $def->setImplement(Bad2::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad2 must have just one non-static method create()."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad2 must have just one non-static method create().'); Assert::exception(function () { $def = new FactoryDefinition; $def->setImplement(Bad3::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad3 must have just one non-static method create()."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad3 must have just one non-static method create().'); Assert::exception(function () { $def = new FactoryDefinition; $def->setImplement(Bad4::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad4 must have just one non-static method create()."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad4 must have just one non-static method create().'); Assert::noError(function () { diff --git a/tests/DI/Definitions.FactoryDefinition.resolve.phpt b/tests/DI/Definitions.FactoryDefinition.resolve.phpt index ea31b381c..a986c39e3 100644 --- a/tests/DI/Definitions.FactoryDefinition.resolve.phpt +++ b/tests/DI/Definitions.FactoryDefinition.resolve.phpt @@ -28,7 +28,8 @@ Assert::exception(function () { $def = new FactoryDefinition; $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Type is missing in definition of service.'); +}, Nette\DI\ServiceCreationException::class, '[Service ?] +Type is missing in definition of service.'); Assert::exception(function () { @@ -36,7 +37,8 @@ Assert::exception(function () { @$def->setImplement(Bad1::class); // missing type triggers warning $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Service of type Bad1: Return type of Bad1::create() is not declared.'); +}, Nette\DI\ServiceCreationException::class, '[Service of type Bad1] +Return type of Bad1::create() is not declared.'); Assert::noError(function () { @@ -77,4 +79,5 @@ Assert::exception(function () { $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Service of type Good1: Factory for stdClass cannot create incompatible DateTime type.'); +}, Nette\DI\ServiceCreationException::class, '[Service of type Good1] +Factory for stdClass cannot create incompatible DateTime type.'); diff --git a/tests/DI/Definitions.ImportedDefinition.phpt b/tests/DI/Definitions.ImportedDefinition.phpt index 0bc96250a..e0600804a 100644 --- a/tests/DI/Definitions.ImportedDefinition.phpt +++ b/tests/DI/Definitions.ImportedDefinition.phpt @@ -16,14 +16,16 @@ require __DIR__ . '/../bootstrap.php'; Assert::exception(function () { $def = new ImportedDefinition; $def->setType('Foo'); -}, Nette\InvalidArgumentException::class, "Service '': Class or interface 'Foo' not found."); +}, Nette\InvalidArgumentException::class, "[Service ?] +Class or interface 'Foo' not found."); Assert::exception(function () { $def = new ImportedDefinition; $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Type of service is unknown.'); +}, Nette\DI\ServiceCreationException::class, '[Service ?] +Type of service is unknown.'); test('', function () { diff --git a/tests/DI/Definitions.LocatorDefinition.api.phpt b/tests/DI/Definitions.LocatorDefinition.api.phpt index 25068cf2f..b1d3d13c8 100644 --- a/tests/DI/Definitions.LocatorDefinition.api.phpt +++ b/tests/DI/Definitions.LocatorDefinition.api.phpt @@ -72,49 +72,57 @@ Assert::exception(function () { Assert::exception(function () { $def = new LocatorDefinition; $def->setImplement('Foo'); -}, Nette\InvalidArgumentException::class, "Service '': Interface 'Foo' not found."); +}, Nette\InvalidArgumentException::class, "[Service ?] +Interface 'Foo' not found."); Assert::exception(function () { $def = new LocatorDefinition; $def->setImplement(stdClass::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface 'stdClass' not found."); +}, Nette\InvalidArgumentException::class, "[Service ?] +Interface 'stdClass' not found."); Assert::exception(function () { $def = new LocatorDefinition; $def->setImplement(Bad1::class); -}, Nette\InvalidArgumentException::class, "Service '': Interface Bad1 must have at least one method."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Interface Bad1 must have at least one method.'); Assert::exception(function () { $def = new LocatorDefinition; $def->setImplement(Bad2::class); -}, Nette\InvalidArgumentException::class, "Service '': Method Bad2::create() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Method Bad2::create() does not meet the requirements: is create($name), get($name), create*() or get*() and is non-static.'); Assert::exception(function () { $def = new LocatorDefinition; $def->setImplement(Bad3::class); -}, Nette\InvalidArgumentException::class, "Service '': Method Bad3::get() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Method Bad3::get() does not meet the requirements: is create($name), get($name), create*() or get*() and is non-static.'); Assert::exception(function () { $def = new LocatorDefinition; $def->setImplement(Bad4::class); -}, Nette\InvalidArgumentException::class, "Service '': Method Bad4::foo() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Method Bad4::foo() does not meet the requirements: is create($name), get($name), create*() or get*() and is non-static.'); Assert::exception(function () { $def = new LocatorDefinition; $def->setImplement(Bad5::class); -}, Nette\InvalidArgumentException::class, "Service '': Method Bad5::get() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Method Bad5::get() does not meet the requirements: is create($name), get($name), create*() or get*() and is non-static.'); Assert::exception(function () { $def = new LocatorDefinition; $def->setImplement(Bad6::class); -}, Nette\InvalidArgumentException::class, "Service '': Method Bad6::get() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static."); +}, Nette\InvalidArgumentException::class, '[Service ?] +Method Bad6::get() does not meet the requirements: is create($name), get($name), create*() or get*() and is non-static.'); Assert::noError(function () { diff --git a/tests/DI/Definitions.LocatorDefinition.resolve.phpt b/tests/DI/Definitions.LocatorDefinition.resolve.phpt index 2a12fbf54..45714e3a8 100644 --- a/tests/DI/Definitions.LocatorDefinition.resolve.phpt +++ b/tests/DI/Definitions.LocatorDefinition.resolve.phpt @@ -33,7 +33,8 @@ Assert::exception(function () { $def = new LocatorDefinition; $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, 'Type of service is unknown.'); +}, Nette\DI\ServiceCreationException::class, '[Service ?] +Type of service is unknown.'); test('', function () { diff --git a/tests/DI/Definitions.ServiceDefinition.phpt b/tests/DI/Definitions.ServiceDefinition.phpt index f53781689..e0d26954c 100644 --- a/tests/DI/Definitions.ServiceDefinition.phpt +++ b/tests/DI/Definitions.ServiceDefinition.phpt @@ -17,7 +17,8 @@ require __DIR__ . '/../bootstrap.php'; Assert::exception(function () { $def = new ServiceDefinition; $def->setType('Foo'); -}, Nette\InvalidArgumentException::class, "Service '': Class or interface 'Foo' not found."); +}, Nette\InvalidArgumentException::class, "[Service ?] +Class or interface 'Foo' not found."); test('', function () { $def = new ServiceDefinition; diff --git a/tests/DI/InjectExtension.errors.phpt b/tests/DI/InjectExtension.errors.phpt index e45b665d3..12bc18457 100644 --- a/tests/DI/InjectExtension.errors.phpt +++ b/tests/DI/InjectExtension.errors.phpt @@ -58,7 +58,9 @@ services: factory: ServiceA inject: yes '); -}, InvalidStateException::class, "Service 'service' (type of ServiceA): Service of type DateTimeImmutable not found. Did you add it to configuration file?"); +}, InvalidStateException::class, "[Service 'service' of type ServiceA] +Service of type DateTimeImmutable required by ServiceA::\$a not found. +Did you add it to configuration file?"); Assert::exception(function () { @@ -72,6 +74,9 @@ services: '); }, InvalidStateException::class, "Class 'Unknown' not found. Check the type of property ServiceB::\$a."); +// }, InvalidStateException::class, "[Service 'service' of type ServiceB] +// Class 'Unknown' required by ServiceB::\$a not found. +// Check the property type and 'use' statements."); Assert::exception(function () { @@ -84,6 +89,8 @@ services: inject: yes '); }, InvalidStateException::class, 'Type of property ServiceC::$a is not declared.'); +//}, InvalidStateException::class, "[Service 'service' of type ServiceC] +//Property ServiceC::\$a has no type."); Assert::error(function () { diff --git a/tests/DI/Resolver.autowireArguments.errors.phpt b/tests/DI/Resolver.autowireArguments.errors.phpt index c950a41af..f38cdd774 100644 --- a/tests/DI/Resolver.autowireArguments.errors.phpt +++ b/tests/DI/Resolver.autowireArguments.errors.phpt @@ -20,7 +20,8 @@ Assert::exception(function () { [], function () {}, ); -}, Nette\DI\ServiceCreationException::class, 'Service of type stdClass required by $x in {closure}() not found. Did you add it to configuration file?'); +}, Nette\DI\ServiceCreationException::class, 'Service of type stdClass required by $x in {closure}() not found. +Did you add it to configuration file?'); // not found @@ -30,7 +31,8 @@ Assert::exception(function () { [], function () {}, ); -}, Nette\DI\ServiceCreationException::class, "Class 'Foo' required by \$x in {closure}() not found. Check the parameter type and 'use' statements."); +}, Nette\DI\ServiceCreationException::class, "Class 'Foo' required by \$x in {closure}() not found. +Check the parameter type and 'use' statements."); // no typehint From 8de37febfea2a6fc8b148620131cf1f285782484 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 14 Dec 2021 19:36:44 +0100 Subject: [PATCH 34/44] generated factories must have defined return type (BC break) --- src/DI/Definitions/AccessorDefinition.php | 16 +++++++--------- src/DI/Definitions/FactoryDefinition.php | 16 +++++----------- src/DI/Definitions/LocatorDefinition.php | 6 +----- tests/DI/Compiler.generatedFactory.phpt | 16 +--------------- tests/DI/ContainerBuilder.accessor.phpt | 12 ------------ tests/DI/ContainerBuilder.create.error.phpt | 7 +++---- tests/DI/ContainerBuilder.factory.phpt | 13 ------------- tests/DI/Definitions.AccessorDefinition.api.phpt | 14 +++++++++++++- .../Definitions.AccessorDefinition.resolve.phpt | 7 ++----- tests/DI/Definitions.FactoryDefinition.api.phpt | 14 +++++++++++++- .../Definitions.FactoryDefinition.resolve.phpt | 6 ++---- tests/DI/Definitions.LocatorDefinition.api.phpt | 16 ++++++++-------- tests/DI/files/compiler.generatedFactory.neon | 2 -- 13 files changed, 55 insertions(+), 90 deletions(-) diff --git a/src/DI/Definitions/AccessorDefinition.php b/src/DI/Definitions/AccessorDefinition.php index 85e3bc171..28dadec4c 100644 --- a/src/DI/Definitions/AccessorDefinition.php +++ b/src/DI/Definitions/AccessorDefinition.php @@ -56,11 +56,7 @@ public function setImplement(string $interface): static )); } - try { - Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::get()", $this->getDescriptor()); - } catch (Nette\DI\ServiceCreationException $e) { - trigger_error($e->getMessage(), E_USER_DEPRECATED); - } + Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::get()", $this->getDescriptor()); return parent::setType($interface); } @@ -100,10 +96,12 @@ public function resolveType(Nette\DI\Resolver $resolver): void public function complete(Nette\DI\Resolver $resolver): void { if (!$this->reference) { - $interface = $this->getType(); - $method = new \ReflectionMethod($interface, self::MethodGet); - $type = Type::fromReflection($method) ?? Helpers::getReturnTypeAnnotation($method); - $this->setReference(Helpers::ensureClassType($type, "return type of $interface::get()")); + if (!$this->getType()) { + throw new Nette\DI\ServiceCreationException('Type is missing in definition of service.'); + } + + $method = new \ReflectionMethod($this->getType(), self::MethodGet); + $this->setReference(Type::fromReflection($method)->getSingleName()); } $this->reference = $resolver->normalizeReference($this->reference); diff --git a/src/DI/Definitions/FactoryDefinition.php b/src/DI/Definitions/FactoryDefinition.php index 5023ca123..d8d911521 100644 --- a/src/DI/Definitions/FactoryDefinition.php +++ b/src/DI/Definitions/FactoryDefinition.php @@ -52,11 +52,7 @@ public function setImplement(string $interface): static )); } - try { - Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::create()", $this->getDescriptor()); - } catch (Nette\DI\ServiceCreationException $e) { - trigger_error($e->getMessage(), E_USER_DEPRECATED); - } + Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::create()", $this->getDescriptor()); return parent::setType($interface); } @@ -90,13 +86,11 @@ public function getResultDefinition(): Definition public function resolveType(Nette\DI\Resolver $resolver): void { - $interface = $this->getType(); - if (!$interface) { + if (!$this->getType()) { throw new ServiceCreationException('Type is missing in definition of service.'); } - $method = new \ReflectionMethod($interface, self::MethodCreate); - $type = Type::fromReflection($method) ?? Helpers::getReturnTypeAnnotation($method); + $type = Type::fromReflection(new \ReflectionMethod($this->getType(), self::MethodCreate)); $resultDef = $this->resultDefinition; try { @@ -106,7 +100,7 @@ public function resolveType(Nette\DI\Resolver $resolver): void throw $e; } - $resultDef->setType(Helpers::ensureClassType($type, "return type of $interface::create()")); + $resultDef->setType($type->getSingleName()); $resolver->resolveDefinition($resultDef); } @@ -219,7 +213,7 @@ public function generateMethod(Php\Method $method, Nette\DI\PhpGenerator $genera $rm = new \ReflectionMethod($this->getType(), self::MethodCreate); $methodCreate ->setParameters(array_map([new Php\Factory, 'fromParameterReflection'], $rm->getParameters())) - ->setReturnType((string) (Type::fromReflection($rm) ?? $this->getResultType())) + ->setReturnType((string) Type::fromReflection($rm)) ->setBody($body); $method->setBody('return new class ($this) ' . $class . ';'); diff --git a/src/DI/Definitions/LocatorDefinition.php b/src/DI/Definitions/LocatorDefinition.php index ea8ef4108..479170478 100644 --- a/src/DI/Definitions/LocatorDefinition.php +++ b/src/DI/Definitions/LocatorDefinition.php @@ -47,11 +47,7 @@ public function setImplement(string $interface): static } if ($method->getNumberOfParameters() === 0) { - try { - Nette\DI\Helpers::ensureClassType(Nette\Utils\Type::fromReflection($method), "return type of $interface::$method->name()", $this->getDescriptor(), true); - } catch (Nette\DI\ServiceCreationException $e) { - trigger_error($e->getMessage(), E_USER_DEPRECATED); - } + Nette\DI\Helpers::ensureClassType(Nette\Utils\Type::fromReflection($method), "return type of $interface::$method->name()", $this->getDescriptor(), true); } } diff --git a/tests/DI/Compiler.generatedFactory.phpt b/tests/DI/Compiler.generatedFactory.phpt index ff448c758..aafb12437 100644 --- a/tests/DI/Compiler.generatedFactory.phpt +++ b/tests/DI/Compiler.generatedFactory.phpt @@ -7,7 +7,6 @@ declare(strict_types=1); use Nette\DI; -use Nette\DI\Config\Adapters as Adapt; use Tester\Assert; @@ -30,14 +29,6 @@ class Lorem } } -interface IFinderFactory -{ - /** - * @return Adapt\NeonAdapter comment - */ - public function create(); -} - interface IArticleFactory { public function create($title): Article; @@ -154,7 +145,7 @@ class TestExtension extends DI\CompilerExtension $compiler = new DI\Compiler; $compiler->addExtension('test', new TestExtension); -@$container = createContainer($compiler, 'files/compiler.generatedFactory.neon'); // missing type triggers warning +$container = createContainer($compiler, 'files/compiler.generatedFactory.neon'); Assert::type(ILoremFactory::class, $container->getService('lorem')); @@ -165,11 +156,6 @@ Assert::same($container->getService('ipsum'), $lorem->ipsum); Assert::type(ILoremFactory::class, $container->getByType(ILoremFactory::class)); -Assert::type(IFinderFactory::class, $container->getService('finder')); -$finder = $container->getService('finder')->create(); -Assert::type(Nette\DI\Config\Adapters\NeonAdapter::class, $finder); - - Assert::type(IArticleFactory::class, $container->getService('article')); $article = $container->getService('article')->create('nemam'); Assert::type(Article::class, $article); diff --git a/tests/DI/ContainerBuilder.accessor.phpt b/tests/DI/ContainerBuilder.accessor.phpt index e6b528e09..73d39bcff 100644 --- a/tests/DI/ContainerBuilder.accessor.phpt +++ b/tests/DI/ContainerBuilder.accessor.phpt @@ -18,12 +18,6 @@ interface StdClassAccessor public function get(): stdClass; } -interface AnnotatedAccessor -{ - /** @return stdClass */ - public function get(); -} - class AccessorReceiver { public $accessor; @@ -48,9 +42,6 @@ $builder->addAccessorDefinition('one') ->setImplement(StdClassAccessor::class) ->setReference(stdClass::class); -@$builder->addAccessorDefinition('two') - ->setImplement(AnnotatedAccessor::class); // missing type triggers warning - $builder->addAccessorDefinition('three') ->setImplement(StdClassAccessor::class) ->setAutowired(false) @@ -65,9 +56,6 @@ $container = createContainer($builder); Assert::type(StdClassAccessor::class, $container->getService('one')); Assert::same($container->getService('one')->get(), $container->getService('service')); -Assert::type(AnnotatedAccessor::class, $container->getService('two')); -Assert::same($container->getService('two')->get(), $container->getService('service')); - Assert::type(StdClassAccessor::class, $container->getService('three')); Assert::same($container->getService('three')->get(), $container->getService('service2')); diff --git a/tests/DI/ContainerBuilder.create.error.phpt b/tests/DI/ContainerBuilder.create.error.phpt index b78d406e6..259e6b684 100644 --- a/tests/DI/ContainerBuilder.create.error.phpt +++ b/tests/DI/ContainerBuilder.create.error.phpt @@ -80,10 +80,9 @@ interface Bad4 Assert::exception(function () { $builder = new DI\ContainerBuilder; - @$builder->addFactoryDefinition('one') - ->setImplement(Bad4::class); // missing type triggers warning - $builder->complete(); -}, Nette\InvalidStateException::class, "[Service 'one' of type Bad4] + $builder->addFactoryDefinition('one') + ->setImplement(Bad4::class); +}, Nette\InvalidStateException::class, "[Service 'one'] Return type of Bad4::create() is not declared."); diff --git a/tests/DI/ContainerBuilder.factory.phpt b/tests/DI/ContainerBuilder.factory.phpt index 7c1b277c6..8f8dda8d8 100644 --- a/tests/DI/ContainerBuilder.factory.phpt +++ b/tests/DI/ContainerBuilder.factory.phpt @@ -18,12 +18,6 @@ interface StdClassFactory public function create(): stdClass; } -interface AnnotatedFactory -{ - /** @return stdClass */ - public function create(); -} - class FactoryReceiver { public function __construct(StdClassFactory $factory) @@ -38,9 +32,6 @@ $builder->addFactoryDefinition('one') ->getResultDefinition() ->setCreator(stdClass::class); -@$builder->addFactoryDefinition('two') - ->setImplement(AnnotatedFactory::class); // missing type triggers warning - $builder->addDefinition('three') ->setType(FactoryReceiver::class); @@ -54,10 +45,6 @@ Assert::type(StdClassFactory::class, $container->getService('one')); Assert::type(stdClass::class, $container->getService('one')->create()); Assert::notSame($container->getService('one')->create(), $container->getService('one')->create()); -Assert::type(AnnotatedFactory::class, $container->getService('two')); -Assert::type(stdClass::class, $container->getService('two')->create()); -Assert::notSame($container->getService('two')->create(), $container->getService('two')->create()); - Assert::type(FactoryReceiver::class, $container->getService('three')); Assert::type(FactoryReceiver::class, $container->getService('four')); diff --git a/tests/DI/Definitions.AccessorDefinition.api.phpt b/tests/DI/Definitions.AccessorDefinition.api.phpt index 47f7d7436..1d0659ee9 100644 --- a/tests/DI/Definitions.AccessorDefinition.api.phpt +++ b/tests/DI/Definitions.AccessorDefinition.api.phpt @@ -40,6 +40,11 @@ interface Bad5 public function get($arg); } +interface Bad6 +{ + public function get(); +} + interface Good1 { public function get(): stdClass; @@ -101,9 +106,16 @@ Assert::exception(function () { Method Bad5::get() must have no parameters.'); +Assert::exception(function () { + $def = new AccessorDefinition; + $def->setImplement(Bad6::class); +}, Nette\DI\ServiceCreationException::class, '[Service ?] +Return type of Bad6::get() is not declared.'); + + Assert::noError(function () { $def = new AccessorDefinition; - @$def->setImplement(Good1::class); // missing type triggers warning + $def->setImplement(Good1::class); Assert::same(Good1::class, $def->getImplement()); Assert::same(Good1::class, $def->getType()); }); diff --git a/tests/DI/Definitions.AccessorDefinition.resolve.phpt b/tests/DI/Definitions.AccessorDefinition.resolve.phpt index 10752fe8c..d03e48290 100644 --- a/tests/DI/Definitions.AccessorDefinition.resolve.phpt +++ b/tests/DI/Definitions.AccessorDefinition.resolve.phpt @@ -34,11 +34,8 @@ Type of service is unknown.'); Assert::exception(function () { $def = new AccessorDefinition; - @$def->setImplement(Bad1::class); // missing type triggers warning - $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); - $resolver->resolveDefinition($def); - $resolver->completeDefinition($def); -}, Nette\DI\ServiceCreationException::class, '[Service of type Bad1] + $def->setImplement(Bad1::class); +}, Nette\DI\ServiceCreationException::class, '[Service ?] Return type of Bad1::get() is not declared.'); diff --git a/tests/DI/Definitions.FactoryDefinition.api.phpt b/tests/DI/Definitions.FactoryDefinition.api.phpt index 60af96c8c..46d936045 100644 --- a/tests/DI/Definitions.FactoryDefinition.api.phpt +++ b/tests/DI/Definitions.FactoryDefinition.api.phpt @@ -34,6 +34,11 @@ interface Bad4 public static function create(); } +interface Bad5 +{ + public function create(); +} + interface Good1 { public function create(): stdClass; @@ -88,9 +93,16 @@ Assert::exception(function () { Interface Bad4 must have just one non-static method create().'); +Assert::exception(function () { + $def = new FactoryDefinition; + $def->setImplement(Bad5::class); +}, Nette\DI\ServiceCreationException::class, '[Service ?] +Return type of Bad5::create() is not declared.'); + + Assert::noError(function () { $def = new FactoryDefinition; - @$def->setImplement(Good1::class); // missing type triggers warning + $def->setImplement(Good1::class); Assert::same(Good1::class, $def->getImplement()); Assert::same(Good1::class, $def->getType()); }); diff --git a/tests/DI/Definitions.FactoryDefinition.resolve.phpt b/tests/DI/Definitions.FactoryDefinition.resolve.phpt index a986c39e3..79410b22a 100644 --- a/tests/DI/Definitions.FactoryDefinition.resolve.phpt +++ b/tests/DI/Definitions.FactoryDefinition.resolve.phpt @@ -34,10 +34,8 @@ Type is missing in definition of service.'); Assert::exception(function () { $def = new FactoryDefinition; - @$def->setImplement(Bad1::class); // missing type triggers warning - $resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder); - $resolver->resolveDefinition($def); -}, Nette\DI\ServiceCreationException::class, '[Service of type Bad1] + $def->setImplement(Bad1::class); +}, Nette\DI\ServiceCreationException::class, '[Service ?] Return type of Bad1::create() is not declared.'); diff --git a/tests/DI/Definitions.LocatorDefinition.api.phpt b/tests/DI/Definitions.LocatorDefinition.api.phpt index b1d3d13c8..488c0a016 100644 --- a/tests/DI/Definitions.LocatorDefinition.api.phpt +++ b/tests/DI/Definitions.LocatorDefinition.api.phpt @@ -20,39 +20,39 @@ interface Bad1 interface Bad2 { - public function create(): stdClass; + public function create(); } interface Bad3 { - public function get(): stdClass; + public function get(); } interface Bad4 { - public function get($name): stdClass; + public function get($name); - public function foo(): stdClass; + public function foo(); } interface Bad5 { - public static function get($name): stdClass; + public static function get($name); } interface Bad6 { - public function get($arg, $arg2): stdClass; + public function get($arg, $arg2); } interface Good1 { - public function get($name): stdClass; + public function get($name); } interface Good2 { - public function create($name): stdClass; + public function create($name); } interface Good3 diff --git a/tests/DI/files/compiler.generatedFactory.neon b/tests/DI/files/compiler.generatedFactory.neon index ee9ffa756..0881fd3c2 100644 --- a/tests/DI/files/compiler.generatedFactory.neon +++ b/tests/DI/files/compiler.generatedFactory.neon @@ -5,8 +5,6 @@ services: lorem: \ILoremFactory(Lorem) - finder: IFinderFactory - article: create: Article($title) implement: IArticleFactory From c179222706fbcb1459d853809d696ba43aa05630 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 27 Sep 2021 00:47:42 +0200 Subject: [PATCH 35/44] annotations @return are no longer supported (BC break) --- src/DI/Helpers.php | 14 ---- src/DI/Resolver.php | 14 +--- tests/DI/ContainerBuilder.resolveTypes.phpt | 82 --------------------- tests/DI/Helpers.getReturnType.phpt | 30 -------- tests/DI/fixtures/Helpers.getReturnType.php | 49 ------------ 5 files changed, 4 insertions(+), 185 deletions(-) delete mode 100644 tests/DI/Helpers.getReturnType.phpt delete mode 100644 tests/DI/fixtures/Helpers.getReturnType.php diff --git a/src/DI/Helpers.php b/src/DI/Helpers.php index c86aad863..688a845ad 100644 --- a/src/DI/Helpers.php +++ b/src/DI/Helpers.php @@ -204,20 +204,6 @@ public static function parseAnnotation(\Reflector $ref, string $name): ?string } - public static function getReturnTypeAnnotation(\ReflectionFunctionAbstract $func): ?Type - { - $type = preg_replace('#[|\s].*#', '', (string) self::parseAnnotation($func, 'return')); - if (!$type || $type === 'object' || $type === 'mixed') { - return null; - } elseif ($func instanceof \ReflectionMethod) { - $type = $type === '$this' ? 'static' : $type; - $type = Reflection::expandClassName($type, $func->getDeclaringClass()); - } - - return Type::fromString($type); - } - - public static function ensureClassType( ?Type $type, string $hint, diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 6d5505a38..a8271c602 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -122,16 +122,10 @@ public function resolveEntityType(Statement $statement): ?string $this->addDependency($reflection); - $type = Nette\Utils\Type::fromReflection($reflection) ?? ($annotation = Helpers::getReturnTypeAnnotation($reflection)); - if ($type && !in_array((string) $type, ['object', 'mixed'], true)) { - if (isset($annotation)) { - trigger_error('Annotation @return should be replaced with native return type at ' . Callback::toString($entity), E_USER_DEPRECATED); - } - - return Helpers::ensureClassType($type, sprintf('return type of %s()', Callback::toString($entity))); - } - - return null; + $type = Nette\Utils\Type::fromReflection($reflection); + return $type && !in_array((string) $type, ['object', 'mixed'], true) + ? Helpers::ensureClassType($type, sprintf('return type of %s()', Callback::toString($entity))) + : null; } elseif ($entity instanceof Reference) { // alias or factory return $this->resolveReferenceType($entity); diff --git a/tests/DI/ContainerBuilder.resolveTypes.phpt b/tests/DI/ContainerBuilder.resolveTypes.phpt index a3504eaf8..bbd710270 100644 --- a/tests/DI/ContainerBuilder.resolveTypes.phpt +++ b/tests/DI/ContainerBuilder.resolveTypes.phpt @@ -8,52 +8,24 @@ use Tester\Assert; class Factory { - /** @return stdClass */ - public function createClassPhpDoc() - { - return []; - } - - public function createClass(): stdClass { return []; } - /** @return stdClass|null */ - public function createNullableClassPhpDoc() - { - return []; - } - - public function createNullableClass(): ?stdClass { return []; } - /** @return array */ - public function createScalarPhpDoc() - { - return []; - } - - public function createScalar(): array { return []; } - /** @return object */ - public function createObjectPhpDoc() - { - return (object) null; - } - - public function createObject(): object { return (object) null; @@ -66,13 +38,6 @@ class Factory } - /** @return mixed */ - public function createMixedPhpDoc() - { - return (object) null; - } - - public function createMixed(): mixed { return (object) null; @@ -99,13 +64,6 @@ class Factory require __DIR__ . '/../bootstrap.php'; -Assert::noError(function () { - $builder = new DI\ContainerBuilder; - $builder->addDefinition('a') - ->setCreator([Factory::class, 'createClassPhpDoc']); - $container = @createContainer($builder); // @return is deprecated -}); - Assert::noError(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') @@ -113,13 +71,6 @@ Assert::noError(function () { $container = createContainer($builder); }); -Assert::noError(function () { - $builder = new DI\ContainerBuilder; - $builder->addDefinition('a') - ->setCreator([Factory::class, 'createNullableClassPhpDoc']); - $container = @createContainer($builder); // @return is deprecated -}); - Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') @@ -128,14 +79,6 @@ Assert::exception(function () { }, Nette\DI\ServiceCreationException::class, "[Service 'a'] Return type of Factory::createNullableClass() is not expected to be nullable/union/intersection/built-in, '?stdClass' given."); -Assert::exception(function () { - $builder = new DI\ContainerBuilder; - $builder->addDefinition('a') - ->setCreator([Factory::class, 'createScalarPhpDoc']); - $container = @createContainer($builder); // @return is deprecated -}, Nette\DI\ServiceCreationException::class, "[Service 'a'] -Return type of Factory::createScalarPhpDoc() is not expected to be nullable/union/intersection/built-in, 'array' given."); - Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') @@ -144,14 +87,6 @@ Assert::exception(function () { }, Nette\DI\ServiceCreationException::class, "[Service 'a'] Return type of Factory::createScalar() is not expected to be nullable/union/intersection/built-in, 'array' given."); -Assert::exception(function () { - $builder = new DI\ContainerBuilder; - $builder->addDefinition('a') - ->setCreator([Factory::class, 'createObjectPhpDoc']); - $container = @createContainer($builder); // @return is deprecated -}, Nette\DI\ServiceCreationException::class, "[Service 'a'] -Unknown service type, specify it or declare return type of factory method."); - Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') @@ -168,14 +103,6 @@ Assert::exception(function () { }, Nette\DI\ServiceCreationException::class, "[Service 'a'] Return type of Factory::createObjectNullable() is not expected to be nullable/union/intersection/built-in, '?object' given."); -Assert::exception(function () { - $builder = new DI\ContainerBuilder; - $builder->addDefinition('a') - ->setCreator([Factory::class, 'createMixedPhpDoc']); - $container = @createContainer($builder); // @return is deprecated -}, Nette\DI\ServiceCreationException::class, "[Service 'a'] -Unknown service type, specify it or declare return type of factory method."); - Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') @@ -184,15 +111,6 @@ Assert::exception(function () { }, Nette\DI\ServiceCreationException::class, "[Service 'a'] Unknown service type, specify it or declare return type of factory method."); -Assert::exception(function () { - $builder = new DI\ContainerBuilder; - $builder->addDefinition('a') - ->setCreator([Factory::class, 'createGeneric']); - $container = @createContainer($builder); // @return is deprecated -}, Nette\DI\ServiceCreationException::class, "[Service 'a'] -Class 'T' not found. -Check the return type of Factory::createGeneric()."); - Assert::exception(function () { $builder = new DI\ContainerBuilder; $builder->addDefinition('a') diff --git a/tests/DI/Helpers.getReturnType.phpt b/tests/DI/Helpers.getReturnType.phpt deleted file mode 100644 index 9a0a47cbf..000000000 --- a/tests/DI/Helpers.getReturnType.phpt +++ /dev/null @@ -1,30 +0,0 @@ - Date: Wed, 6 Oct 2021 22:27:55 +0200 Subject: [PATCH 36/44] annotations @var are no longer supported (BC break) --- src/DI/Extensions/InjectExtension.php | 19 ++-- tests/DI/Container.inject.properties.phpt | 16 +-- tests/DI/InjectExtension.basic.phpt | 12 +- tests/DI/InjectExtension.errors.phpt | 8 +- ...Extension.getInjectProperties().php74.phpt | 40 ------- ...Extension.getInjectProperties().php80.phpt | 36 ------ ...InjectExtension.getInjectProperties().phpt | 105 +++++------------- ...xtension.getInjectProperties().traits.phpt | 4 +- 8 files changed, 55 insertions(+), 185 deletions(-) delete mode 100644 tests/DI/InjectExtension.getInjectProperties().php74.phpt delete mode 100644 tests/DI/InjectExtension.getInjectProperties().php80.phpt diff --git a/src/DI/Extensions/InjectExtension.php b/src/DI/Extensions/InjectExtension.php index a73030c18..dc43574bb 100644 --- a/src/DI/Extensions/InjectExtension.php +++ b/src/DI/Extensions/InjectExtension.php @@ -113,24 +113,19 @@ public static function getInjectProperties(string $class): array $res = []; foreach ((new \ReflectionClass($class))->getProperties() as $rp) { $name = $rp->getName(); - $hasAttr = $rp->getAttributes(DI\Attributes\Inject::class); - if ($hasAttr || DI\Helpers::parseAnnotation($rp, 'inject') !== null) { + if ( + $rp->getAttributes(DI\Attributes\Inject::class) + || DI\Helpers::parseAnnotation($rp, 'inject') !== null + ) { if (!$rp->isPublic() || $rp->isStatic()) { trigger_error(sprintf('Property %s for injection must be public and non-static.', Reflection::toString($rp)), E_USER_WARNING); - continue; - } - if (PHP_VERSION_ID >= 80100 && $rp->isReadOnly()) { + } elseif (PHP_VERSION_ID >= 80100 && $rp->isReadOnly()) { throw new Nette\InvalidStateException(sprintf('Property %s for injection must not be readonly.', Reflection::toString($rp))); - } - $type = Nette\Utils\Type::fromReflection($rp); - if (!$type && !$hasAttr && ($annotation = DI\Helpers::parseAnnotation($rp, 'var'))) { - $annotation = Reflection::expandClassName($annotation, Reflection::getPropertyDeclaringClass($rp)); - $type = Nette\Utils\Type::fromString($annotation); + } else { + $res[$name] = DI\Helpers::ensureClassType(Nette\Utils\Type::fromReflection($rp), 'type of property ' . Reflection::toString($rp)); } - - $res[$rp->getName()] = DI\Helpers::ensureClassType($type, 'type of property ' . Reflection::toString($rp)); } } diff --git a/tests/DI/Container.inject.properties.phpt b/tests/DI/Container.inject.properties.phpt index b633c0f8b..8b0203539 100644 --- a/tests/DI/Container.inject.properties.phpt +++ b/tests/DI/Container.inject.properties.phpt @@ -23,20 +23,17 @@ class Foo implements IFoo class Test1 { - /** @inject @var stdClass */ - public $varA; - - /** @var stdClass @inject */ - public $varB; + /** @inject */ + public stdClass $varA; } class Test2 extends Test1 { - /** @var stdClass @inject */ - public $varC; + /** @inject */ + public stdClass $varC; - /** @var IFoo @inject */ - public $varD; + /** @inject */ + public IFoo $varD; } @@ -52,6 +49,5 @@ $container = createContainer($builder); $test = new Test2; $container->callInjects($test); Assert::type(stdClass::class, $test->varA); -Assert::type(stdClass::class, $test->varB); Assert::type(stdClass::class, $test->varC); Assert::type(Foo::class, $test->varD); diff --git a/tests/DI/InjectExtension.basic.phpt b/tests/DI/InjectExtension.basic.phpt index f1c80294f..bfb9d96b3 100644 --- a/tests/DI/InjectExtension.basic.phpt +++ b/tests/DI/InjectExtension.basic.phpt @@ -31,8 +31,8 @@ class ConcreteDependencyB extends AbstractDependency class ParentClass { - /** @var stdClass @inject */ - public $a; + /** @inject */ + public stdClass $a; public function injectA() @@ -47,11 +47,11 @@ class ParentClass class Service extends ParentClass { - /** @var stdClass @inject */ - public $c; + /** @inject */ + public stdClass $c; - /** @var AbstractDependency @inject */ - public $e; + /** @inject */ + public AbstractDependency $e; public function injectC() diff --git a/tests/DI/InjectExtension.errors.phpt b/tests/DI/InjectExtension.errors.phpt index 12bc18457..18f1ae32b 100644 --- a/tests/DI/InjectExtension.errors.phpt +++ b/tests/DI/InjectExtension.errors.phpt @@ -16,15 +16,15 @@ require __DIR__ . '/../bootstrap.php'; class ServiceA { - /** @var DateTimeImmutable @inject */ - public $a; + /** @inject */ + public DateTimeImmutable $a; } class ServiceB { - /** @var Unknown @inject */ - public $a; + /** @inject */ + public Unknown $a; } diff --git a/tests/DI/InjectExtension.getInjectProperties().php74.phpt b/tests/DI/InjectExtension.getInjectProperties().php74.phpt deleted file mode 100644 index 9a5381d73..000000000 --- a/tests/DI/InjectExtension.getInjectProperties().php74.phpt +++ /dev/null @@ -1,40 +0,0 @@ - A\AInjected::class, - 'varC' => A\AInjected::class, - ], InjectExtension::getInjectProperties(A\AClass::class)); -} diff --git a/tests/DI/InjectExtension.getInjectProperties().php80.phpt b/tests/DI/InjectExtension.getInjectProperties().php80.phpt deleted file mode 100644 index bc72b460f..000000000 --- a/tests/DI/InjectExtension.getInjectProperties().php80.phpt +++ /dev/null @@ -1,36 +0,0 @@ - 'stdClass', -], InjectExtension::getInjectProperties(EClass::class)); diff --git a/tests/DI/InjectExtension.getInjectProperties().phpt b/tests/DI/InjectExtension.getInjectProperties().phpt index 616c6a39a..110af62ba 100644 --- a/tests/DI/InjectExtension.getInjectProperties().phpt +++ b/tests/DI/InjectExtension.getInjectProperties().phpt @@ -6,94 +6,49 @@ declare(strict_types=1); -namespace A -{ - class AClass - { - /** @var AInjected @inject */ - public $varA; +use Nette\DI\Attributes\Inject; +use Nette\DI\Extensions\InjectExtension; +use Tester\Assert; + - /** @var B\BInjected @inject */ - public $varB; +class AClass +{ + /** @inject */ + public AInjected $varA; - /** @var AInjected @inject */ - public $varC; + /** @inject */ + public BInjected $varB; - /** @var AInjected */ - public $varD; - } + public $varD; - class AInjected - { - } + #[Inject] + public stdClass $varF; } -namespace A\B +class BadClass { - use A; - - class BClass extends A\AClass - { - /** @var BInjected @inject */ - public $varF; - } - - class BInjected - { - } + /** @inject */ + public AClass|stdClass $var; } -namespace C +class AInjected { - use A\AInjected; - use A\B; - use C\CInjected as CAlias; +} - class CClass - { - /** @var AInjected @inject */ - public $var1; +class BInjected +{ +} - /** @var B\BInjected @inject */ - public $var2; - /** @var CAlias @inject */ - public $var3; +require __DIR__ . '/../bootstrap.php'; - /** @var CInjected @inject */ - public $var4; - } - class CInjected - { - } -} +Assert::same([ + 'varA' => AInjected::class, + 'varB' => BInjected::class, + 'varF' => stdClass::class, +], InjectExtension::getInjectProperties(AClass::class)); -namespace -{ - use Nette\DI\Extensions\InjectExtension; - use Tester\Assert; - - require __DIR__ . '/../bootstrap.php'; - - - Assert::same([ - 'varA' => A\AInjected::class, - 'varB' => A\B\BInjected::class, - 'varC' => A\AInjected::class, - ], InjectExtension::getInjectProperties(A\AClass::class)); - - Assert::same([ - 'varA' => A\AInjected::class, - 'varB' => A\B\BInjected::class, - 'varC' => A\AInjected::class, - 'varF' => A\B\BInjected::class, - ], InjectExtension::getInjectProperties(A\B\BClass::class)); - - Assert::same([ - 'var1' => A\AInjected::class, - 'var2' => A\B\BInjected::class, - 'var3' => C\CInjected::class, - 'var4' => C\CInjected::class, - ], InjectExtension::getInjectProperties(C\CClass::class)); -} +Assert::exception(function () { + InjectExtension::getInjectProperties(BadClass::class); +}, Nette\InvalidStateException::class, "Type of property BadClass::\$var is not expected to be nullable/union/intersection/built-in, 'AClass|stdClass' given."); diff --git a/tests/DI/InjectExtension.getInjectProperties().traits.phpt b/tests/DI/InjectExtension.getInjectProperties().traits.phpt index 6eecf733b..73a9631b3 100644 --- a/tests/DI/InjectExtension.getInjectProperties().traits.phpt +++ b/tests/DI/InjectExtension.getInjectProperties().traits.phpt @@ -19,8 +19,8 @@ namespace B trait BTrait { - /** @var AInjected @inject */ - public $varA; + /** @inject */ + public AInjected $varA; } } From 986f010dde2ca80f7de094e446ff947eb54c799a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 29 Sep 2021 20:03:06 +0200 Subject: [PATCH 37/44] readme.md: updated code --- readme.md | 85 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/readme.md b/readme.md index f0c9ad926..49dea9d54 100644 --- a/readme.md +++ b/readme.md @@ -50,8 +50,8 @@ We have the object representing email: ```php class Mail { - public $subject; - public $message; + public string $subject; + public string $message; } ``` @@ -60,7 +60,7 @@ An object which can send emails: ```php interface Mailer { - function send(Mail $mail, $to); + function send(Mail $mail, string $to): void; } ``` @@ -69,7 +69,7 @@ A support for logging: ```php interface Logger { - function log($message); + function log(string $message): void; } ``` @@ -78,23 +78,25 @@ And finally, a class that provides sending newsletters: ```php class NewsletterManager { - private $mailer; - private $logger; + private Mailer $mailer; + private Logger $logger; - function __construct(Mailer $mailer, Logger $logger) + public function __construct(Mailer $mailer, Logger $logger) { $this->mailer = $mailer; $this->logger = $logger; } - function distribute(array $recipients) + public function distribute(array $recipients): void { $mail = new Mail; - ... + $mail->subject = '...'; + $mail->message = '...'; + foreach ($recipients as $recipient) { $this->mailer->send($mail, $recipient); } - $this->logger->log(...); + $this->logger->log('...'); } } ``` @@ -106,7 +108,7 @@ Also, we have a ability to implement own `Logger` or `Mailer`, like this: ```php class SendMailMailer implements Mailer { - function send(Mail $mail, $to) + public function send(Mail $mail, string $to): void { mail($to, $mail->subject, $mail->message); } @@ -114,14 +116,14 @@ class SendMailMailer implements Mailer class FileLogger implements Logger { - private $file; + private string $file; - function __construct($file) + public function __construct(string $file) { $this->file = $file; } - function log($message) + public function log(string $message): void { file_put_contents($this->file, $message . "\n", FILE_APPEND); } @@ -135,26 +137,26 @@ Container for our application might look like this: ```php class Container { - private $logger; - private $mailer; + private ?Logger $logger; + private ?Mailer $mailer; - function getLogger() + public function getLogger(): Logger { - if (!$this->logger) { + if (!isset($this->logger)) { $this->logger = new FileLogger('log.txt'); } return $this->logger; } - function getMailer() + public function getMailer(): Mailer { - if (!$this->mailer) { + if (!isset($this->mailer)) { $this->mailer = new SendMailMailer; } return $this->mailer; } - function createNewsletterManager() + public function createNewsletterManager(): NewsletterManager { return new NewsletterManager($this->getMailer(), $this->getLogger()); } @@ -213,7 +215,7 @@ The container will be generated only once and the code is stored in cache (in di During development it is useful to activate auto-refresh mode which automatically regenerate the container when any class or configuration file is changed. Just in the constructor `ContainerLoader` append `true` as the second argument: ```php -$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true); +$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', autoRebuild: true); ``` @@ -244,9 +246,9 @@ Class of the service: ```php class NewsletterManager { - private $anotherService; + private AnotherService $anotherService; - public function setAnotherService(AnotherService $service) + public function setAnotherService(AnotherService $service): void { $this->anotherService = $service; } @@ -254,7 +256,7 @@ class NewsletterManager ... ``` -We can also add the `inject: yes` directive. This directive will enable automatic call of `inject*` methods and passing dependencies to public variables with `@inject` annotations: +We can also add the `inject: yes` directive. This directive will enable automatic call of `inject*` methods and passing dependencies to public variables with #[Inject] attribute: ```neon services: @@ -266,21 +268,23 @@ services: Dependency `Service1` will be passed by calling the `inject*` method, dependency `Service2` will be assigned to the `$service2` variable: ```php +use Nette\DI\Attributes\Inject; + class FooClass { - private $service1; + private Service1 $service1; // 1) inject* method: - public function injectService1(Service1 $service) + public function injectService1(Service1 $service): void { $this->service1 = $service1; } - // 2) Assign to the variable with the @inject annotation: + // 2) Assign to the variable with the #[Inject] attribute: - /** @inject @var Service2 */ - public $service2; + #[Inject] + public Service2 $service2; } ``` @@ -291,17 +295,14 @@ However, this method is not ideal, because the variable must be declared as publ Factories --------- -We can use factories generated from an interface. The interface must declare the returning type in the `@return` annotation of the method. Nette will generate a proper implementation of the interface. +We can use factories generated from an interface. The interface must declare the returning type of the method. Nette will generate a proper implementation of the interface. The interface must have exactly one method named `create`. Our factory interface could be declared in the following way: ```php -interface IBarFactory +interface BarFactory { - /** - * @return Bar - */ - public function create(); + function create(): Bar; } ``` @@ -310,7 +311,7 @@ The `create` method will instantiate an `Bar` with the following definition: ```php class Bar { - private $logger; + private Logger $logger; public function __construct(Logger $logger) { @@ -323,7 +324,7 @@ The factory will be registered in the `config.neon` file: ```neon services: - - IBarFactory + - BarFactory ``` Nette will check if the declared service is an interface. If yes, it will also generate the corresponding implementation of the factory. The definition can be also written in a more verbose form: @@ -331,7 +332,7 @@ Nette will check if the declared service is an interface. If yes, it will also g ```neon services: barFactory: - implement: IBarFactory + implement: BarFactory ``` This full definition allows us to declare additional configuration of the object using the `arguments` and `setup` sections, similarly as for all other services. @@ -341,14 +342,14 @@ In our code, we only have to obtain the factory instance and call the `create` m ```php class Foo { - private $barFactory; + private BarFactory $barFactory; - function __construct(IBarFactory $barFactory) + function __construct(BarFactory $barFactory) { $this->barFactory = $barFactory; } - function bar() + function bar(): void { $bar = $this->barFactory->create(); } From 7f04701e98686565d8c54226b31b608122d189e5 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 14 Dec 2021 01:46:38 +0100 Subject: [PATCH 38/44] Resolver: only optional parameters are autowired with default value (BC break) [WIP] TODO: nullable unknown class --- src/DI/Resolver.php | 10 +--------- tests/DI/Resolver.autowireArguments.errors.phpt | 8 ++++---- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index a8271c602..d5bd52c94 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -607,15 +607,7 @@ private static function autowireArgument(\ReflectionParameter $parameter, callab ) { return $getter($itemType, false); - } elseif ( - ($type && $parameter->allowsNull()) - || $parameter->isOptional() - || $parameter->isDefaultValueAvailable() - ) { - // !optional + defaultAvailable, !optional + !defaultAvailable since 8.1.0 = func($a = null, $b) - // optional + !defaultAvailable, optional + defaultAvailable since 8.0.0 = i.e. Exception::__construct, mysqli::mysqli, ... - // optional + !defaultAvailable = variadics - // in other cases the optional and defaultAvailable are identical + } elseif ($parameter->isOptional()) { return null; } else { diff --git a/tests/DI/Resolver.autowireArguments.errors.phpt b/tests/DI/Resolver.autowireArguments.errors.phpt index f38cdd774..fe219e1eb 100644 --- a/tests/DI/Resolver.autowireArguments.errors.phpt +++ b/tests/DI/Resolver.autowireArguments.errors.phpt @@ -66,13 +66,13 @@ Assert::error(function () { // nullable scalar -Assert::error(function () { +Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function (?int $arg) {}), [], fn($type) => $type === Test::class ? new Test : null, ); -}, E_USER_DEPRECATED, 'The parameter $arg in {closure}() should have a declared value in the configuration.'); +}, Nette\DI\ServiceCreationException::class, 'Parameter $arg in {closure}() has union type and no default value, so its value must be specified.'); // union @@ -86,13 +86,13 @@ Assert::exception(function () { // nullable union -Assert::error(function () { +Assert::exception(function () { Resolver::autowireArguments( new ReflectionFunction(function (stdClass|Test|null $x) {}), [], function () {}, ); -}, E_USER_DEPRECATED, 'The parameter $x in {closure}() should have a declared value in the configuration.'); +}, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}() has union type and no default value, so its value must be specified.'); // bad variadics (this is actually what PHP allows) From 1b2d3716c51f36f1b71780d5b0594cd0a258fa99 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 15 Dec 2021 19:45:29 +0100 Subject: [PATCH 39/44] Resolver: processing of functions like not() moved to PhpGenerator --- src/DI/PhpGenerator.php | 9 +++++++++ src/DI/Resolver.php | 10 ---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/DI/PhpGenerator.php b/src/DI/PhpGenerator.php index e861ce494..ccb4b53e1 100644 --- a/src/DI/PhpGenerator.php +++ b/src/DI/PhpGenerator.php @@ -119,6 +119,15 @@ public function formatStatement(Statement $statement): string case is_string($entity) && Strings::contains($entity, '?'): // PHP literal return $this->formatPhp($entity, $arguments); + case $entity === 'not': + return $this->formatPhp('!(?)', $arguments); + + case $entity === 'bool': + case $entity === 'int': + case $entity === 'float': + case $entity === 'string': + return $this->formatPhp('?::?(?, ?)', [Helpers::class, 'convertType', $arguments[0], $entity]); + case is_string($entity): // create class return $arguments ? $this->formatPhp("new $entity(...?:)", [$arguments]) diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index d5bd52c94..0291e723d 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -183,13 +183,6 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo break; case $entity === 'not': - if (count($arguments) !== 1) { - throw new ServiceCreationException(sprintf('Function %s() expects 1 parameter, %s given.', $entity, count($arguments))); - } - - $entity = ['', '!']; - break; - case $entity === 'bool': case $entity === 'int': case $entity === 'float': @@ -197,9 +190,6 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo if (count($arguments) !== 1) { throw new ServiceCreationException(sprintf('Function %s() expects 1 parameter, %s given.', $entity, count($arguments))); } - - $arguments = [$arguments[0], $entity]; - $entity = [Helpers::class, 'convertType']; break; case is_string($entity): // create class From 3f0b0e694c1d6682752c4fc7f3b1517f35f2734b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=C3=ADk=20Jan?= Date: Wed, 18 May 2022 10:23:33 +0200 Subject: [PATCH 40/44] Allow custom ExtensionExtension usage --- src/DI/Compiler.php | 3 ++- tests/DI/ExtensionsExtension.basic.phpt | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/DI/Compiler.php b/src/DI/Compiler.php index 691c7cec8..1c21307d6 100644 --- a/src/DI/Compiler.php +++ b/src/DI/Compiler.php @@ -199,7 +199,8 @@ public function compile(): string /** @internal */ public function processExtensions(): void { - $first = $this->getExtensions(Extensions\ParametersExtension::class) + $this->getExtensions(Extensions\ExtensionsExtension::class); + $extensionsExtensionName = array_key_exists('extensions', $this->extensions) ? get_class($this->extensions['extensions']) : Nette\DI\Extensions\ExtensionsExtension::class; + $first = $this->getExtensions(Extensions\ParametersExtension::class) + $this->getExtensions($extensionsExtensionName); foreach ($first as $name => $extension) { $config = $this->processSchema($extension->getConfigSchema(), $this->configs[$name] ?? [], $name); $extension->setConfig($this->config[$name] = $config); diff --git a/tests/DI/ExtensionsExtension.basic.phpt b/tests/DI/ExtensionsExtension.basic.phpt index ee5409fb6..e976f4d5d 100644 --- a/tests/DI/ExtensionsExtension.basic.phpt +++ b/tests/DI/ExtensionsExtension.basic.phpt @@ -51,6 +51,15 @@ class FirstExtension extends DI\CompilerExtension } } +class CustomExtensionsExtension extends DI\CompilerExtension +{ + + public function loadConfiguration() + { + $this->compiler->addExtension('first', new FirstExtension()); + } + +} $compiler = new DI\Compiler; $compiler->addExtension('first', new FirstExtension); @@ -67,7 +76,11 @@ foo: key: value '); - Assert::same('hello', $container->parameters['foo']); Assert::same('test', $container->parameters['bar']); Assert::same(['services', 'parameters', 'first', 'extensions', 'foo', 'bar'], $container->parameters['first']); + +$compiler = new DI\Compiler; +$compiler->addExtension('extensions', new CustomExtensionsExtension); +$container = createContainer($compiler); +Assert::same(['services', 'parameters', 'extensions', 'first'], $container->parameters['first']); From fff7b842281961033bece6e5d9c50c32770e73c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=C3=ADk=20Jan?= Date: Wed, 18 May 2022 10:26:36 +0200 Subject: [PATCH 41/44] Fix Github Actions --- tests/DI/ExtensionsExtension.basic.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/DI/ExtensionsExtension.basic.phpt b/tests/DI/ExtensionsExtension.basic.phpt index e976f4d5d..ff388a1c4 100644 --- a/tests/DI/ExtensionsExtension.basic.phpt +++ b/tests/DI/ExtensionsExtension.basic.phpt @@ -84,3 +84,5 @@ $compiler = new DI\Compiler; $compiler->addExtension('extensions', new CustomExtensionsExtension); $container = createContainer($compiler); Assert::same(['services', 'parameters', 'extensions', 'first'], $container->parameters['first']); + + From 3fca0d702dd6d6b61e927e4f641f5972c6a2ebca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=C3=ADk=20Jan?= Date: Wed, 18 May 2022 10:44:22 +0200 Subject: [PATCH 42/44] Fix CS --- src/DI/Compiler.php | 4 ++-- tests/DI/ExtensionsExtension.basic.phpt | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/DI/Compiler.php b/src/DI/Compiler.php index 1c21307d6..e5a364425 100644 --- a/src/DI/Compiler.php +++ b/src/DI/Compiler.php @@ -199,8 +199,8 @@ public function compile(): string /** @internal */ public function processExtensions(): void { - $extensionsExtensionName = array_key_exists('extensions', $this->extensions) ? get_class($this->extensions['extensions']) : Nette\DI\Extensions\ExtensionsExtension::class; - $first = $this->getExtensions(Extensions\ParametersExtension::class) + $this->getExtensions($extensionsExtensionName); + $extensionsExtensionName = array_key_exists('extensions', $this->extensions) ? get_class($this->extensions['extensions']) : Nette\DI\Extensions\ExtensionsExtension::class; + $first = $this->getExtensions(Extensions\ParametersExtension::class) + $this->getExtensions($extensionsExtensionName); foreach ($first as $name => $extension) { $config = $this->processSchema($extension->getConfigSchema(), $this->configs[$name] ?? [], $name); $extension->setConfig($this->config[$name] = $config); diff --git a/tests/DI/ExtensionsExtension.basic.phpt b/tests/DI/ExtensionsExtension.basic.phpt index ff388a1c4..798fd6044 100644 --- a/tests/DI/ExtensionsExtension.basic.phpt +++ b/tests/DI/ExtensionsExtension.basic.phpt @@ -56,7 +56,7 @@ class CustomExtensionsExtension extends DI\CompilerExtension public function loadConfiguration() { - $this->compiler->addExtension('first', new FirstExtension()); + $this->compiler->addExtension('first', new FirstExtension()); } } @@ -84,5 +84,3 @@ $compiler = new DI\Compiler; $compiler->addExtension('extensions', new CustomExtensionsExtension); $container = createContainer($compiler); Assert::same(['services', 'parameters', 'extensions', 'first'], $container->parameters['first']); - - From 4b2154407a3cc61bc80ca0d3795ea70c7c651569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=C3=ADk=20Jan?= Date: Wed, 18 May 2022 10:47:59 +0200 Subject: [PATCH 43/44] Fix CS --- src/DI/Compiler.php | 5 ++++- tests/DI/ExtensionsExtension.basic.phpt | 4 +--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/DI/Compiler.php b/src/DI/Compiler.php index e5a364425..3a70e462a 100644 --- a/src/DI/Compiler.php +++ b/src/DI/Compiler.php @@ -199,7 +199,10 @@ public function compile(): string /** @internal */ public function processExtensions(): void { - $extensionsExtensionName = array_key_exists('extensions', $this->extensions) ? get_class($this->extensions['extensions']) : Nette\DI\Extensions\ExtensionsExtension::class; + $extensionsExtensionName = Nette\DI\Extensions\ExtensionsExtension::class; + if (array_key_exists('extensions', $this->extensions)) { + $extensionsExtensionName = get_class($this->extensions['extensions']); + } $first = $this->getExtensions(Extensions\ParametersExtension::class) + $this->getExtensions($extensionsExtensionName); foreach ($first as $name => $extension) { $config = $this->processSchema($extension->getConfigSchema(), $this->configs[$name] ?? [], $name); diff --git a/tests/DI/ExtensionsExtension.basic.phpt b/tests/DI/ExtensionsExtension.basic.phpt index 798fd6044..16183b0b8 100644 --- a/tests/DI/ExtensionsExtension.basic.phpt +++ b/tests/DI/ExtensionsExtension.basic.phpt @@ -53,12 +53,10 @@ class FirstExtension extends DI\CompilerExtension class CustomExtensionsExtension extends DI\CompilerExtension { - public function loadConfiguration() { - $this->compiler->addExtension('first', new FirstExtension()); + $this->compiler->addExtension('first', new FirstExtension); } - } $compiler = new DI\Compiler; From 4a98fbfff31085aa8918e2ab62c8f405daae41c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=C3=ADk=20Jan?= Date: Wed, 18 May 2022 10:49:02 +0200 Subject: [PATCH 44/44] Fix CS --- src/DI/Compiler.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/DI/Compiler.php b/src/DI/Compiler.php index 3a70e462a..6a24cdf39 100644 --- a/src/DI/Compiler.php +++ b/src/DI/Compiler.php @@ -199,10 +199,10 @@ public function compile(): string /** @internal */ public function processExtensions(): void { - $extensionsExtensionName = Nette\DI\Extensions\ExtensionsExtension::class; - if (array_key_exists('extensions', $this->extensions)) { - $extensionsExtensionName = get_class($this->extensions['extensions']); - } + $extensionsExtensionName = Nette\DI\Extensions\ExtensionsExtension::class; + if (array_key_exists('extensions', $this->extensions)) { + $extensionsExtensionName = get_class($this->extensions['extensions']); + } $first = $this->getExtensions(Extensions\ParametersExtension::class) + $this->getExtensions($extensionsExtensionName); foreach ($first as $name => $extension) { $config = $this->processSchema($extension->getConfigSchema(), $this->configs[$name] ?? [], $name);