From 4a11f6387a784ca8aeb984a80841eb70b2324a4d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 8 Apr 2026 20:29:04 +0700 Subject: [PATCH 1/4] Bump to Rector ^2.4.1 and replace deprecated file to getFile() on rector rule --- composer.json | 2 +- rector.dist.php | 2 -- src/Exception/RectorErrorException.php | 4 +--- src/Rector/AbstractRector.php | 2 +- ...UpdateRectorCodeSamplesFromFixturesRector.php | 6 +++--- ...NoinspectionDocblockToFileFirstStmtRector.php | 6 +++--- src/Rector/File/SortFileFunctionStmtRector.php | 16 ++++++++-------- src/Support/ComposerScripts.php | 6 +++--- tests/Rector/AbstractRectorTestCase.php | 7 +++---- tests/Support/HelpersTest.php | 4 ++-- 10 files changed, 25 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index da8d1e8..b929f32 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "require": { "php": ">=7.4", "illuminate/support": "^8.83 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0", - "rector/rector": "^2.3", + "rector/rector": "^2.4.1", "symfony/polyfill-php80": "^1.33", "symfony/polyfill-php81": "^1.33", "webmozart/assert": "^1.12 || ^2.0" diff --git a/rector.dist.php b/rector.dist.php index 2a333da..6b4ecf7 100644 --- a/rector.dist.php +++ b/rector.dist.php @@ -48,7 +48,6 @@ use Rector\Set\ValueObject\SetList; use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector; use Rector\Transform\Rector\String_\StringToClassConstantRector; -use Rector\TypeDeclaration\Rector\StmtsAwareInterface\SafeDeclareStrictTypesRector; use Rector\ValueObject\PhpVersion; return RectorConfig::configure() @@ -120,7 +119,6 @@ EnumCaseToPascalCaseRector::class, GeneratorPropertyFetchToMethodCallRector::class, JsonThrowOnErrorRector::class, - SafeDeclareStrictTypesRector::class, SortAssociativeArrayByKeyRector::class, StaticArrowFunctionRector::class, StaticClosureRector::class, diff --git a/src/Exception/RectorErrorException.php b/src/Exception/RectorErrorException.php index c661d96..b09e50d 100644 --- a/src/Exception/RectorErrorException.php +++ b/src/Exception/RectorErrorException.php @@ -21,8 +21,6 @@ /** * @see \PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException - * - * @property \Rector\ValueObject\Application\File $file */ final class RectorErrorException extends Error implements ThrowableContract { @@ -35,7 +33,7 @@ public function __construct(AbstractRector $rector, string $message, array $attr \sprintf( '[%s:%s%s] %s', (new \ReflectionObject($rector))->getShortName(), - (string) Str::of((fn (): string => $this->file->getFilePath())->bindTo($rector, $rector)()) + (string) \str((fn (): string => $this->getFile()->getFilePath())->bindTo($rector, $rector)()) // @phpstan-ignore method.nonObject // ->chopStart(getcwd().\DIRECTORY_SEPARATOR) // ->replaceStart(getcwd().\DIRECTORY_SEPARATOR, '') ->whenStartsWith( diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index b504eb6..cf71112 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -41,7 +41,7 @@ final public function getRuleDefinition(): RuleDefinition protected function description(): string { - return (string) Str::of(static::class) + return (string) \str(static::class) ->afterLast('\\') ->beforeLast('Rector') ->headline() diff --git a/src/Rector/Array_/UpdateRectorCodeSamplesFromFixturesRector.php b/src/Rector/Array_/UpdateRectorCodeSamplesFromFixturesRector.php index 220439a..e65d934 100644 --- a/src/Rector/Array_/UpdateRectorCodeSamplesFromFixturesRector.php +++ b/src/Rector/Array_/UpdateRectorCodeSamplesFromFixturesRector.php @@ -276,7 +276,7 @@ private function parseConfigFile(ClassReflection $classReflection): string // ['/tests/', '/config/configured_rule.php'], // $classReflection->getNativeReflection()->getFileName() // ); - return (string) Str::of($classReflection->getNativeReflection()->getName()) + return (string) \str($classReflection->getNativeReflection()->getName()) ->replace(['Guanguans\\RectorRules\\', '\\'], ['tests/', '/']) ->append('/config/configured_rule.php'); } @@ -292,7 +292,7 @@ private function parseFixtureFiles(ClassReflection $classReflection): array // $classReflection->getNativeReflection()->getFileName() // )); return glob( - (string) Str::of($classReflection->getNativeReflection()->getName()) + (string) \str($classReflection->getNativeReflection()->getName()) ->replace(['Guanguans\\RectorRules\\', '\\'], ['tests/', '/']) ->append('/Fixture/fixture.php.inc') ); @@ -300,7 +300,7 @@ private function parseFixtureFiles(ClassReflection $classReflection): array private function sanitizeCode(string $code): string { - return (string) Str::of($code) + return (string) \str($code) ->trim() ->whenStartsWith($start = ' $code->replaceFirst($start, '')) ->whenEndsWith($finish = '?>', static fn (Stringable $code) => $code->replaceLast($finish, '')) diff --git a/src/Rector/File/AddNoinspectionDocblockToFileFirstStmtRector.php b/src/Rector/File/AddNoinspectionDocblockToFileFirstStmtRector.php index 9df3bb8..345dd75 100644 --- a/src/Rector/File/AddNoinspectionDocblockToFileFirstStmtRector.php +++ b/src/Rector/File/AddNoinspectionDocblockToFileFirstStmtRector.php @@ -157,8 +157,8 @@ private function getInspections(): array /** @var array> $inspectionsMap */ static $inspectionsMap = []; - $inspectionsMap[$this->file->getFilePath()] ??= collect($this->inspectionsMap) - ->filter(fn (array $_, string $path) => Str::is($path, $this->file->getFilePath())) + $inspectionsMap[$this->getFile()->getFilePath()] ??= collect($this->inspectionsMap) + ->filter(fn (array $_, string $path) => Str::is($path, $this->getFile()->getFilePath())) // ->flatten() ->collapse() ->unique() @@ -167,6 +167,6 @@ private function getInspections(): array // ->dd() ->all(); - return $inspectionsMap[$this->file->getFilePath()]; + return $inspectionsMap[$this->getFile()->getFilePath()]; } } diff --git a/src/Rector/File/SortFileFunctionStmtRector.php b/src/Rector/File/SortFileFunctionStmtRector.php index 135866b..37ed1a2 100644 --- a/src/Rector/File/SortFileFunctionStmtRector.php +++ b/src/Rector/File/SortFileFunctionStmtRector.php @@ -57,23 +57,23 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - $rootNode = collect($node->stmts)->first( + $stmt = collect($node->stmts)->first( static fn (Stmt $stmtNode): bool => $stmtNode instanceof Namespace_, $node ); - \assert($rootNode instanceof FileNode || $rootNode instanceof Namespace_); + \assert($stmt instanceof FileNode || $stmt instanceof Namespace_); if ( - collect($rootNode->stmts)->containsStrict( + collect($stmt->stmts)->containsStrict( static fn (Stmt $stmtNode): bool => $stmtNode instanceof ClassLike ) - || !collect($rootNode->stmts)->containsStrict( + || !collect($stmt->stmts)->containsStrict( static fn (Stmt $stmtNode): bool => $stmtNode instanceof Function_ || $stmtNode instanceof If_ ) - || !collect($rootNode->stmts)->containsStrict( + || !collect($stmt->stmts)->containsStrict( fn (Stmt $stmtNode): ?string => $this->parseFuncName($stmtNode) ) - || collect($rootNode->stmts) + || collect($stmt->stmts) ->map(fn (Stmt $stmtNode): ?string => $this->parseFuncName($stmtNode)) ->filter() ->pipe(static fn (Collection $funcNames): bool => $funcNames->all() === $funcNames->sort()->all()) @@ -82,7 +82,7 @@ public function refactor(Node $node): ?Node } /** @var list $sortedStmts */ - $sortedStmts = collect($rootNode->stmts) + $sortedStmts = collect($stmt->stmts) ->sort( fn (Stmt $a, Stmt $b): int => ($aName = $this->parseFuncName($a)) && ($bName = $this->parseFuncName($b)) ? $aName <=> $bName @@ -107,7 +107,7 @@ static function (Collection $stmtNodes, Stmt $stmtNode): Collection { // return null; // } - $rootNode->stmts = $sortedStmts; + $stmt->stmts = $sortedStmts; return $node; } diff --git a/src/Support/ComposerScripts.php b/src/Support/ComposerScripts.php index e456b62..3f502a8 100644 --- a/src/Support/ComposerScripts.php +++ b/src/Support/ComposerScripts.php @@ -96,15 +96,15 @@ public static function listFiles(Event $event): int require_once $event->getComposer()->getConfig()->get('vendor-dir').'/rector/rector/vendor/autoload.php'; classes( - static fn (string $class, string $file): bool => Str::of($class)->startsWith('Rector\\') - && Str::of($class)->afterLast('\\')->contains([ + static fn (string $class, string $file): bool => \str($class)->startsWith('Rector\\') + && \str($class)->afterLast('\\')->contains([ 'Better', // 'Factory', // 'Resolver', // 'er', // 'Renamer', ]) - && !Str::of($file)->contains([ + && !\str($file)->contains([ '/rector-doctrine/', '/rector-downgrade-php/', '/rector-phpunit/', diff --git a/tests/Rector/AbstractRectorTestCase.php b/tests/Rector/AbstractRectorTestCase.php index 22ab8fa..f1b941f 100644 --- a/tests/Rector/AbstractRectorTestCase.php +++ b/tests/Rector/AbstractRectorTestCase.php @@ -60,7 +60,7 @@ final public function testRectorTestCaseClassName(): void { self::assertSame( static::class, - (string) Str::of(static::rectorClass()) + (string) \str(static::rectorClass()) ->replace('RectorRules', 'RectorRulesTests') ->append('\\', static::rectorReflectionClass()->getShortName(), 'Test') ); @@ -82,7 +82,6 @@ final public function testRuleDefinition(): void * @noinspection PhpLanguageLevelInspection * @noinspection PhpUndefinedNamespaceInspection */ - #[\PHPUnit\Framework\Attributes\DataProvider('provideCases')] final public function test(string $filePath): void { $this->doTestFile($filePath); @@ -93,7 +92,7 @@ final public static function provideCases(): iterable yield from self::yieldFilesFromDirectory(static::directory().'/Fixture/'); foreach ((array) glob(static::directory().'/Fixture\d*/', \GLOB_ONLYDIR) as $directory) { - if ((int) (\PHP_MAJOR_VERSION.\PHP_MINOR_VERSION) >= (int) (string) Str::of($directory)->basename()->substr(7)) { + if ((int) (\PHP_MAJOR_VERSION.\PHP_MINOR_VERSION) >= (int) (string) \str($directory)->basename()->substr(7)) { yield from self::yieldFilesFromDirectory($directory); } } @@ -146,7 +145,7 @@ protected static function rectorReflectionClass(): \ReflectionClass */ protected static function rectorClass(): string { - return (string) Str::of((new \ReflectionClass(static::class))->getNamespaceName())->replace( + return (string) \str((new \ReflectionClass(static::class))->getNamespaceName())->replace( 'RectorRulesTests', 'RectorRules' ); diff --git a/tests/Support/HelpersTest.php b/tests/Support/HelpersTest.php index b3a6274..c32d915 100644 --- a/tests/Support/HelpersTest.php +++ b/tests/Support/HelpersTest.php @@ -31,13 +31,13 @@ use function Guanguans\RectorRules\Support\is_subclass_of_any; it('will throw `ReflectionException` when call classes function', function (): void { - classes(fn (string $class): bool => Str::of($class)->startsWith('Illuminate\Support')); + classes(fn (string $class): bool => \str($class)->startsWith('Illuminate\Support')); }) ->group(__DIR__, __FILE__) ->throws(ReflectionException::class); it('can get classes', function (): void { - expect(classes(fn (string $class): bool => Str::of($class)->startsWith(Str::class))) + expect(classes(fn (string $class): bool => \str($class)->startsWith(Str::class))) ->toBeInstanceOf(Collection::class); })->group(__DIR__, __FILE__); From cd7c8908910f2ab0e26d295789bb487b0331e9bf Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 8 Apr 2026 20:32:22 +0700 Subject: [PATCH 2/4] Str::of() unrelated replace --- src/Exception/RectorErrorException.php | 2 +- src/Rector/AbstractRector.php | 2 +- .../Array_/UpdateRectorCodeSamplesFromFixturesRector.php | 6 +++--- src/Support/ComposerScripts.php | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Exception/RectorErrorException.php b/src/Exception/RectorErrorException.php index b09e50d..cd7e023 100644 --- a/src/Exception/RectorErrorException.php +++ b/src/Exception/RectorErrorException.php @@ -33,7 +33,7 @@ public function __construct(AbstractRector $rector, string $message, array $attr \sprintf( '[%s:%s%s] %s', (new \ReflectionObject($rector))->getShortName(), - (string) \str((fn (): string => $this->getFile()->getFilePath())->bindTo($rector, $rector)()) // @phpstan-ignore method.nonObject + (string) Str::of((fn (): string => $this->getFile()->getFilePath())->bindTo($rector, $rector)()) // @phpstan-ignore method.nonObject // ->chopStart(getcwd().\DIRECTORY_SEPARATOR) // ->replaceStart(getcwd().\DIRECTORY_SEPARATOR, '') ->whenStartsWith( diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index cf71112..b504eb6 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -41,7 +41,7 @@ final public function getRuleDefinition(): RuleDefinition protected function description(): string { - return (string) \str(static::class) + return (string) Str::of(static::class) ->afterLast('\\') ->beforeLast('Rector') ->headline() diff --git a/src/Rector/Array_/UpdateRectorCodeSamplesFromFixturesRector.php b/src/Rector/Array_/UpdateRectorCodeSamplesFromFixturesRector.php index e65d934..220439a 100644 --- a/src/Rector/Array_/UpdateRectorCodeSamplesFromFixturesRector.php +++ b/src/Rector/Array_/UpdateRectorCodeSamplesFromFixturesRector.php @@ -276,7 +276,7 @@ private function parseConfigFile(ClassReflection $classReflection): string // ['/tests/', '/config/configured_rule.php'], // $classReflection->getNativeReflection()->getFileName() // ); - return (string) \str($classReflection->getNativeReflection()->getName()) + return (string) Str::of($classReflection->getNativeReflection()->getName()) ->replace(['Guanguans\\RectorRules\\', '\\'], ['tests/', '/']) ->append('/config/configured_rule.php'); } @@ -292,7 +292,7 @@ private function parseFixtureFiles(ClassReflection $classReflection): array // $classReflection->getNativeReflection()->getFileName() // )); return glob( - (string) \str($classReflection->getNativeReflection()->getName()) + (string) Str::of($classReflection->getNativeReflection()->getName()) ->replace(['Guanguans\\RectorRules\\', '\\'], ['tests/', '/']) ->append('/Fixture/fixture.php.inc') ); @@ -300,7 +300,7 @@ private function parseFixtureFiles(ClassReflection $classReflection): array private function sanitizeCode(string $code): string { - return (string) \str($code) + return (string) Str::of($code) ->trim() ->whenStartsWith($start = ' $code->replaceFirst($start, '')) ->whenEndsWith($finish = '?>', static fn (Stringable $code) => $code->replaceLast($finish, '')) diff --git a/src/Support/ComposerScripts.php b/src/Support/ComposerScripts.php index 3f502a8..e456b62 100644 --- a/src/Support/ComposerScripts.php +++ b/src/Support/ComposerScripts.php @@ -96,15 +96,15 @@ public static function listFiles(Event $event): int require_once $event->getComposer()->getConfig()->get('vendor-dir').'/rector/rector/vendor/autoload.php'; classes( - static fn (string $class, string $file): bool => \str($class)->startsWith('Rector\\') - && \str($class)->afterLast('\\')->contains([ + static fn (string $class, string $file): bool => Str::of($class)->startsWith('Rector\\') + && Str::of($class)->afterLast('\\')->contains([ 'Better', // 'Factory', // 'Resolver', // 'er', // 'Renamer', ]) - && !\str($file)->contains([ + && !Str::of($file)->contains([ '/rector-doctrine/', '/rector-downgrade-php/', '/rector-phpunit/', From 6ebdd0305d556a453e342f2315bc5b9d60ab3793 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 8 Apr 2026 20:33:08 +0700 Subject: [PATCH 3/4] Str::of() unrelated replace --- tests/Rector/AbstractRectorTestCase.php | 6 +++--- tests/Support/HelpersTest.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Rector/AbstractRectorTestCase.php b/tests/Rector/AbstractRectorTestCase.php index f1b941f..59810dd 100644 --- a/tests/Rector/AbstractRectorTestCase.php +++ b/tests/Rector/AbstractRectorTestCase.php @@ -60,7 +60,7 @@ final public function testRectorTestCaseClassName(): void { self::assertSame( static::class, - (string) \str(static::rectorClass()) + (string) Str::of(static::rectorClass()) ->replace('RectorRules', 'RectorRulesTests') ->append('\\', static::rectorReflectionClass()->getShortName(), 'Test') ); @@ -92,7 +92,7 @@ final public static function provideCases(): iterable yield from self::yieldFilesFromDirectory(static::directory().'/Fixture/'); foreach ((array) glob(static::directory().'/Fixture\d*/', \GLOB_ONLYDIR) as $directory) { - if ((int) (\PHP_MAJOR_VERSION.\PHP_MINOR_VERSION) >= (int) (string) \str($directory)->basename()->substr(7)) { + if ((int) (\PHP_MAJOR_VERSION.\PHP_MINOR_VERSION) >= (int) (string) Str::of($directory)->basename()->substr(7)) { yield from self::yieldFilesFromDirectory($directory); } } @@ -145,7 +145,7 @@ protected static function rectorReflectionClass(): \ReflectionClass */ protected static function rectorClass(): string { - return (string) \str((new \ReflectionClass(static::class))->getNamespaceName())->replace( + return (string) Str::of((new \ReflectionClass(static::class))->getNamespaceName())->replace( 'RectorRulesTests', 'RectorRules' ); diff --git a/tests/Support/HelpersTest.php b/tests/Support/HelpersTest.php index c32d915..b3a6274 100644 --- a/tests/Support/HelpersTest.php +++ b/tests/Support/HelpersTest.php @@ -31,13 +31,13 @@ use function Guanguans\RectorRules\Support\is_subclass_of_any; it('will throw `ReflectionException` when call classes function', function (): void { - classes(fn (string $class): bool => \str($class)->startsWith('Illuminate\Support')); + classes(fn (string $class): bool => Str::of($class)->startsWith('Illuminate\Support')); }) ->group(__DIR__, __FILE__) ->throws(ReflectionException::class); it('can get classes', function (): void { - expect(classes(fn (string $class): bool => \str($class)->startsWith(Str::class))) + expect(classes(fn (string $class): bool => Str::of($class)->startsWith(Str::class))) ->toBeInstanceOf(Collection::class); })->group(__DIR__, __FILE__); From ddee9f83e5283fe4be5578a0d7459210735b4ded Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 8 Apr 2026 20:36:58 +0700 Subject: [PATCH 4/4] attribute unrelated replace --- tests/Rector/AbstractRectorTestCase.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Rector/AbstractRectorTestCase.php b/tests/Rector/AbstractRectorTestCase.php index 59810dd..22ab8fa 100644 --- a/tests/Rector/AbstractRectorTestCase.php +++ b/tests/Rector/AbstractRectorTestCase.php @@ -82,6 +82,7 @@ final public function testRuleDefinition(): void * @noinspection PhpLanguageLevelInspection * @noinspection PhpUndefinedNamespaceInspection */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideCases')] final public function test(string $filePath): void { $this->doTestFile($filePath);