From 1b077bcb4757b44bac71f66c595242dd455b88fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=A1=D0=BF=D0=B8?= =?UTF-8?q?=D1=80=D0=BA=D0=BE=D0=B2?= Date: Wed, 14 Jan 2026 12:54:29 +0400 Subject: [PATCH 1/3] configs --- .github/workflows/cs.yml | 48 --------------------------------- .github/workflows/rector-cs.yml | 27 +++++++++++++++++++ .gitignore | 1 + .php-cs-fixer.dist.php | 17 +++++++++++- 4 files changed, 44 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/cs.yml create mode 100644 .github/workflows/rector-cs.yml diff --git a/.github/workflows/cs.yml b/.github/workflows/cs.yml deleted file mode 100644 index 8512828..0000000 --- a/.github/workflows/cs.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: cs fixer - -on: - pull_request_target: - paths-ignore: - - 'docs/**' - - 'README.md' - - 'CHANGELOG.md' - - '.gitignore' - - '.gitattributes' - - 'infection.json.dist' - - 'psalm.xml' - -jobs: - fix: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.head_ref }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - token: ${{ secrets.YIISOFT_GITHUB_TOKEN }} - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: 8.5 - tools: composer:v2 - coverage: none - - - name: Install Composer dependencies - uses: "ramsey/composer-install@v3" - - - name: Run Rector - run: composer rector - - - name: Run PHP CS Fixer - run: composer php-cs-fixer - - - name: Commit changes - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: "Apply PHP CS Fixer and Rector changes (CI)" - file_pattern: '*.php' - disable_globbing: true diff --git a/.github/workflows/rector-cs.yml b/.github/workflows/rector-cs.yml new file mode 100644 index 0000000..6424c2a --- /dev/null +++ b/.github/workflows/rector-cs.yml @@ -0,0 +1,27 @@ +name: Rector + PHP CS Fixer + +on: + pull_request_target: + paths: + - 'src/**' + - 'tests/**' + - '.github/workflows/rector-cs.yml' + - 'composer.json' + - 'rector.php' + - '.php-cs-fixer.dist.php' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + rector: + uses: yiisoft/actions/.github/workflows/rector-cs.yml@master + secrets: + token: ${{ secrets.YIISOFT_GITHUB_TOKEN }} + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + php: '8.1' diff --git a/.gitignore b/.gitignore index 5d6b5cf..4d69d7c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ composer.phar # PHP CS Fixer /.php-cs-fixer.cache +/.php-cs-fixer.php diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 5c4e99a..71110dd 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -14,9 +14,24 @@ ->exclude('Php8_4/'); return (new Config()) + ->setRiskyAllowed(true) ->setParallelConfig(ParallelConfigFactory::detect()) ->setRules([ - '@PER-CS2.0' => true, + '@PER-CS3.0' => true, 'no_unused_imports' => true, + 'ordered_class_elements' => true, + 'class_attributes_separation' => ['elements' => ['method' => 'one']], + 'declare_strict_types' => true, + 'native_function_invocation' => true, + 'native_constant_invocation' => true, + 'fully_qualified_strict_types' => [ + 'import_symbols' => true + ], + 'global_namespace_import' => [ + 'import_classes' => true, + 'import_constants' => true, + 'import_functions' => true, + ], ]) ->setFinder($finder); + From 3a2ce7582920364f8072cf136b8e69fddef8129c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=A1=D0=BF=D0=B8?= =?UTF-8?q?=D1=80=D0=BA=D0=BE=D0=B2?= Date: Wed, 14 Jan 2026 12:55:57 +0400 Subject: [PATCH 2/3] fix CS --- src/ArrayDefinition.php | 118 +++++++++--------- src/Helpers/DefinitionResolver.php | 4 +- src/Helpers/DefinitionValidator.php | 6 +- src/Helpers/ExceptionHelper.php | 4 +- src/Helpers/Normalizer.php | 4 +- src/ParameterDefinition.php | 8 +- .../ServiceWithNonExistingDependency.php | 4 +- tests/Support/Notebook.php | 5 +- tests/Support/Phone.php | 5 +- tests/Unit/DefinitionStorageTest.php | 17 +-- .../Unit/Helpers/DefinitionExtractorTest.php | 2 + tests/Unit/Helpers/DefinitionResolverTest.php | 6 +- .../Unit/Helpers/DefinitionValidatorTest.php | 8 +- 13 files changed, 102 insertions(+), 89 deletions(-) diff --git a/src/ArrayDefinition.php b/src/ArrayDefinition.php index 9361383..1cd6994 100644 --- a/src/ArrayDefinition.php +++ b/src/ArrayDefinition.php @@ -84,35 +84,6 @@ public static function fromPreparedData(string $class, array $constructorArgumen return new self($class, $constructorArguments, $methodsAndProperties); } - /** - * @psalm-param array $config - * - * @psalm-return array - */ - private static function getMethodsAndPropertiesFromConfig(array $config): array - { - $methodsAndProperties = []; - - foreach ($config as $key => $value) { - if ($key === self::CONSTRUCTOR) { - continue; - } - - /** - * @infection-ignore-all Explode limit does not affect the result. - * - * @see \Yiisoft\Definitions\Tests\Unit\Helpers\DefinitionValidatorTest::testIncorrectMethodName() - */ - if (count($methodArray = explode('()', $key, 2)) === 2) { - $methodsAndProperties[$key] = [self::TYPE_METHOD, $methodArray[0], $value]; - } elseif (count($propertyArray = explode('$', $key)) === 2) { - $methodsAndProperties[$key] = [self::TYPE_PROPERTY, $propertyArray[1], $value]; - } - } - - return $methodsAndProperties; - } - /** * @psalm-return class-string */ @@ -173,6 +144,65 @@ public function resolve(ContainerInterface $container): object return $object; } + /** + * Create a new definition that is merged from this definition and another definition. + * + * @param ArrayDefinition $other Definition to merge with. + * + * @return self New definition that is merged from this definition and another definition. + */ + public function merge(self $other): self + { + $new = clone $this; + $new->class = $other->class; + $new->constructorArguments = ArrayDefinitionHelper::mergeArguments($this->constructorArguments, $other->constructorArguments); + + $methodsAndProperties = $this->methodsAndProperties; + foreach ($other->methodsAndProperties as $key => $item) { + if ($item[0] === self::TYPE_PROPERTY) { + $methodsAndProperties[$key] = $item; + } elseif ($item[0] === self::TYPE_METHOD) { + /** @psalm-suppress MixedArgument */ + $arguments = isset($methodsAndProperties[$key]) + ? ArrayDefinitionHelper::mergeArguments($methodsAndProperties[$key][2], $item[2]) + : $item[2]; + $methodsAndProperties[$key] = [$item[0], $item[1], $arguments]; + } + } + $new->methodsAndProperties = $methodsAndProperties; + + return $new; + } + + /** + * @psalm-param array $config + * + * @psalm-return array + */ + private static function getMethodsAndPropertiesFromConfig(array $config): array + { + $methodsAndProperties = []; + + foreach ($config as $key => $value) { + if ($key === self::CONSTRUCTOR) { + continue; + } + + /** + * @infection-ignore-all Explode limit does not affect the result. + * + * @see \Yiisoft\Definitions\Tests\Unit\Helpers\DefinitionValidatorTest::testIncorrectMethodName() + */ + if (count($methodArray = explode('()', $key, 2)) === 2) { + $methodsAndProperties[$key] = [self::TYPE_METHOD, $methodArray[0], $value]; + } elseif (count($propertyArray = explode('$', $key)) === 2) { + $methodsAndProperties[$key] = [self::TYPE_PROPERTY, $propertyArray[1], $value]; + } + } + + return $methodsAndProperties; + } + /** * @param array $dependencies * @@ -267,34 +297,4 @@ private function isIntegerIndexed(array $arguments): bool return $hasIntegerIndex; } - - /** - * Create a new definition that is merged from this definition and another definition. - * - * @param ArrayDefinition $other Definition to merge with. - * - * @return self New definition that is merged from this definition and another definition. - */ - public function merge(self $other): self - { - $new = clone $this; - $new->class = $other->class; - $new->constructorArguments = ArrayDefinitionHelper::mergeArguments($this->constructorArguments, $other->constructorArguments); - - $methodsAndProperties = $this->methodsAndProperties; - foreach ($other->methodsAndProperties as $key => $item) { - if ($item[0] === self::TYPE_PROPERTY) { - $methodsAndProperties[$key] = $item; - } elseif ($item[0] === self::TYPE_METHOD) { - /** @psalm-suppress MixedArgument */ - $arguments = isset($methodsAndProperties[$key]) - ? ArrayDefinitionHelper::mergeArguments($methodsAndProperties[$key][2], $item[2]) - : $item[2]; - $methodsAndProperties[$key] = [$item[0], $item[1], $arguments]; - } - } - $new->methodsAndProperties = $methodsAndProperties; - - return $new; - } } diff --git a/src/Helpers/DefinitionResolver.php b/src/Helpers/DefinitionResolver.php index d56de13..93f8e65 100644 --- a/src/Helpers/DefinitionResolver.php +++ b/src/Helpers/DefinitionResolver.php @@ -78,8 +78,8 @@ public static function ensureResolvable(mixed $value): array|ReferenceInterface| if ($value instanceof DefinitionInterface) { throw new InvalidConfigException( - 'Only references are allowed in constructor arguments, a definition object was provided: ' . - var_export($value, true), + 'Only references are allowed in constructor arguments, a definition object was provided: ' + . var_export($value, true), ); } diff --git a/src/Helpers/DefinitionValidator.php b/src/Helpers/DefinitionValidator.php index 110732e..ea13313 100644 --- a/src/Helpers/DefinitionValidator.php +++ b/src/Helpers/DefinitionValidator.php @@ -20,6 +20,8 @@ use function is_string; use function sprintf; +use const PHP_VERSION_ID; + /** * Definition validator checks if definition is valid. */ @@ -282,8 +284,8 @@ private static function validateConstructor(mixed $value): void foreach ($value as $argument) { if (is_object($argument) && !self::isValidObject($argument)) { throw new InvalidConfigException( - 'Only references are allowed in constructor arguments, a definition object was provided: ' . - var_export($argument, true), + 'Only references are allowed in constructor arguments, a definition object was provided: ' + . var_export($argument, true), ); } } diff --git a/src/Helpers/ExceptionHelper.php b/src/Helpers/ExceptionHelper.php index edc4e0e..41ca1df 100644 --- a/src/Helpers/ExceptionHelper.php +++ b/src/Helpers/ExceptionHelper.php @@ -37,8 +37,8 @@ public static function incorrectArrayDefinitionMethodArguments(string $key, mixe { return new InvalidConfigException( sprintf( - 'Invalid definition: incorrect method "%s" arguments. Expected array, got "%s". ' . - 'Probably you should wrap them into square brackets.', + 'Invalid definition: incorrect method "%s" arguments. Expected array, got "%s". ' + . 'Probably you should wrap them into square brackets.', $key, get_debug_type($value), ), diff --git a/src/Helpers/Normalizer.php b/src/Helpers/Normalizer.php index e6b1379..841b757 100644 --- a/src/Helpers/Normalizer.php +++ b/src/Helpers/Normalizer.php @@ -56,8 +56,8 @@ public static function normalize(mixed $definition, ?string $class = null): Defi if (is_string($definition)) { // Current class if ( - $class === $definition || - ($class === null && class_exists($definition)) + $class === $definition + || ($class === null && class_exists($definition)) ) { /** @psalm-var class-string $definition */ return ArrayDefinition::fromPreparedData($definition); diff --git a/src/ParameterDefinition.php b/src/ParameterDefinition.php index 34fff5a..6246b17 100644 --- a/src/ParameterDefinition.php +++ b/src/ParameterDefinition.php @@ -110,8 +110,8 @@ private function resolveVariadicOrBuiltinOrIntersectionOrNonTyped(): mixed if ($type === null) { throw new NotInstantiableException( sprintf( - 'Can not determine value of the "%s" parameter without type when instantiating "%s". ' . - 'Please specify argument explicitly.', + 'Can not determine value of the "%s" parameter without type when instantiating "%s". ' + . 'Please specify argument explicitly.', $this->parameter->getName(), $this->getCallable(), ), @@ -120,8 +120,8 @@ private function resolveVariadicOrBuiltinOrIntersectionOrNonTyped(): mixed throw new NotInstantiableException( sprintf( - 'Can not determine value of the "%s" parameter of type "%s" when instantiating "%s". ' . - 'Please specify argument explicitly.', + 'Can not determine value of the "%s" parameter of type "%s" when instantiating "%s". ' + . 'Please specify argument explicitly.', $this->parameter->getName(), $type, $this->getCallable(), diff --git a/tests/Support/DefinitionStorage/ServiceWithNonExistingDependency.php b/tests/Support/DefinitionStorage/ServiceWithNonExistingDependency.php index 062efdd..3485720 100644 --- a/tests/Support/DefinitionStorage/ServiceWithNonExistingDependency.php +++ b/tests/Support/DefinitionStorage/ServiceWithNonExistingDependency.php @@ -4,7 +4,9 @@ namespace Yiisoft\Definitions\Tests\Support\DefinitionStorage; +use NonExisting; + final class ServiceWithNonExistingDependency { - public function __construct(\NonExisting $nonExisting) {} + public function __construct(NonExisting $nonExisting) {} } diff --git a/tests/Support/Notebook.php b/tests/Support/Notebook.php index 66cd8d2..1b4cca4 100644 --- a/tests/Support/Notebook.php +++ b/tests/Support/Notebook.php @@ -4,9 +4,12 @@ namespace Yiisoft\Definitions\Tests\Support; +use NotExist1; +use NotExist2; + final class Notebook { public function __construct( - public \NotExist1|\NotExist2 $notExist, + public NotExist1|NotExist2 $notExist, ) {} } diff --git a/tests/Support/Phone.php b/tests/Support/Phone.php index fe3c7dd..85d2804 100644 --- a/tests/Support/Phone.php +++ b/tests/Support/Phone.php @@ -6,15 +6,14 @@ final class Phone { + public bool $dev = false; + public ?string $codeName = null; private ?string $id = null; private array $colors; private array $apps = []; private ?string $author = null; private ?string $country = null; - public bool $dev = false; - public ?string $codeName = null; - public function __construct( private ?string $name = null, private ?string $version = null, diff --git a/tests/Unit/DefinitionStorageTest.php b/tests/Unit/DefinitionStorageTest.php index b69c85a..e9a7dc1 100644 --- a/tests/Unit/DefinitionStorageTest.php +++ b/tests/Unit/DefinitionStorageTest.php @@ -32,6 +32,9 @@ use Yiisoft\Definitions\Tests\Support\UnionCar; use Yiisoft\Definitions\Tests\Support\UnionSelfDependency; use Yiisoft\Test\Support\Container\SimpleContainer; +use NonExisting; +use NotExist1; +use NotExist2; final class DefinitionStorageTest extends TestCase { @@ -90,7 +93,7 @@ public function testServiceWithNonExistingDependency(): void $this->assertSame( [ ServiceWithNonExistingDependency::class, - \NonExisting::class, + NonExisting::class, ], $storage->getBuildStack(), ); @@ -104,7 +107,7 @@ public function testServiceWithNonExistingSubDependency(): void [ ServiceWithNonExistingSubDependency::class, ServiceWithNonExistingDependency::class , - \NonExisting::class, + NonExisting::class, ], $storage->getBuildStack(), ); @@ -137,8 +140,8 @@ public function testNotExistsUnionTypes(): void $this->assertSame( [ Notebook::class, - \NotExist1::class, - \NotExist2::class, + NotExist1::class, + NotExist2::class, ], $storage->getBuildStack(), ); @@ -168,7 +171,7 @@ public function testServiceWithNonExistingUnionTypes(): void [ ServiceWithNonResolvableUnionTypes::class, ServiceWithNonExistingDependency::class, - \NonExisting::class, + NonExisting::class, ServiceWithPrivateConstructor::class, ], $storage->getBuildStack(), @@ -211,8 +214,8 @@ public function testCircular(): void $this->expectException(CircularReferenceException::class); $this->expectExceptionMessage( - 'Circular reference to "' . Chicken::class . '" detected while building: ' . - Chicken::class . ', ' . Egg::class, + 'Circular reference to "' . Chicken::class . '" detected while building: ' + . Chicken::class . ', ' . Egg::class, ); $storage->get(Chicken::class); } diff --git a/tests/Unit/Helpers/DefinitionExtractorTest.php b/tests/Unit/Helpers/DefinitionExtractorTest.php index 53233bd..a94d56b 100644 --- a/tests/Unit/Helpers/DefinitionExtractorTest.php +++ b/tests/Unit/Helpers/DefinitionExtractorTest.php @@ -28,6 +28,8 @@ use Yiisoft\Definitions\Tests\Support\UnionSelfDependency; use Yiisoft\Test\Support\Container\SimpleContainer; +use const PHP_VERSION_ID; + final class DefinitionExtractorTest extends TestCase { public function testResolveConstructor(): void diff --git a/tests/Unit/Helpers/DefinitionResolverTest.php b/tests/Unit/Helpers/DefinitionResolverTest.php index 774c395..2cfe055 100644 --- a/tests/Unit/Helpers/DefinitionResolverTest.php +++ b/tests/Unit/Helpers/DefinitionResolverTest.php @@ -44,9 +44,9 @@ public function testEnsureResolvableDefinition(): void { $this->expectException(InvalidConfigException::class); $this->expectExceptionMessageMatches( - '/^Only references are allowed in constructor arguments, a definition object was provided: (\\\\|)' . - preg_quote(ValueDefinition::class) . - '.*/', + '/^Only references are allowed in constructor arguments, a definition object was provided: (\\\\|)' + . preg_quote(ValueDefinition::class) + . '.*/', ); DefinitionResolver::ensureResolvable(new ValueDefinition(7)); } diff --git a/tests/Unit/Helpers/DefinitionValidatorTest.php b/tests/Unit/Helpers/DefinitionValidatorTest.php index 108e709..bae7e3e 100644 --- a/tests/Unit/Helpers/DefinitionValidatorTest.php +++ b/tests/Unit/Helpers/DefinitionValidatorTest.php @@ -22,6 +22,8 @@ use Yiisoft\Definitions\Tests\Support\UTF8User; use Yiisoft\Definitions\ValueDefinition; +use function sprintf; + final class DefinitionValidatorTest extends TestCase { public function testIntegerKeyOfArray(): void @@ -329,9 +331,9 @@ public function testDefinitionInArguments(): void { $this->expectException(InvalidConfigException::class); $this->expectExceptionMessageMatches( - '/^Only references are allowed in constructor arguments, a definition object was provided: (\\\\|)' . - preg_quote(ValueDefinition::class) . - '.*/', + '/^Only references are allowed in constructor arguments, a definition object was provided: (\\\\|)' + . preg_quote(ValueDefinition::class) + . '.*/', ); DefinitionValidator::validate([ 'class' => GearBox::class, From 63163454c491e89e703593c17af11aea2fc4fa69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=A1=D0=BF=D0=B8?= =?UTF-8?q?=D1=80=D0=BA=D0=BE=D0=B2?= Date: Wed, 14 Jan 2026 12:57:41 +0400 Subject: [PATCH 3/3] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f3f9b7..46d1ccb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 3.4.2 under development -- no changes in this release. +- Enh #112: Explicitly import constants in "use" section (@mspirkov) ## 3.4.1 December 02, 2025