From 86840b7a1704718a71dfa0251baf4d3157beb24e Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 1 Oct 2026 14:51:59 +0200 Subject: [PATCH 1/3] Support PHP 7.4-8.5 with native downgraded source --- .github/workflows/bare_run.yaml | 19 ++++-- .phpunit.result.cache | 1 + composer.json | 4 +- phpunit.xml | 1 - src/Analyzer/NeedsFinalizeAnalyzer.php | 16 ++++- src/Command/CheckCommentedCodeCommand.php | 25 ++++++-- src/Command/CheckConflictsCommand.php | 20 ++++-- src/Command/DuplicatedCodeCommand.php | 23 +++++-- src/Command/FeaturesCommand.php | 34 ++++++++--- src/Command/FinalizeClassesCommand.php | 46 +++++++++++--- src/Command/FindMultiClassesCommand.php | 20 ++++-- .../GenerateSymfonySmokeTestsCommand.php | 34 ++++++++--- src/Command/MeasureCommand.php | 34 ++++++++--- src/Command/NamespaceToPSR4Command.php | 17 ++++-- src/Command/PrivatizeConstantsCommand.php | 41 ++++++++++--- .../SplitSymfonyConfigToPerPackageCommand.php | 21 ++++++- src/Comments/CommentedCodeAnalyzer.php | 5 +- src/DuplicatedCode/CloneDetector.php | 32 +++++++--- src/DuplicatedCode/ValueObject/CodeClone.php | 34 ++++++++--- .../ValueObject/CodeCloneFile.php | 27 ++++++-- src/EntityClassResolver.php | 16 +++-- src/Enum/StaticAccessor.php | 10 ++- src/Enum/SymfonyClass.php | 5 +- src/Finder/FilesFinder.php | 8 +-- src/Finder/MultipleClassInOneFileFinder.php | 13 ++-- src/Finder/PhpFilesFinder.php | 10 +-- src/Git/ConflictResolver.php | 5 +- src/Lines/Analyser.php | 15 +++-- src/Lines/FeatureCounter/Enum/PhpVersion.php | 61 +++++++++++++------ .../FeatureCounter/FeatureCounterAnalyzer.php | 13 +++- .../FeatureCollectorNodeVisitor.php | 11 +++- src/Lines/FeatureCounter/ResultPrinter.php | 20 ++++-- .../FeatureCounter/ValueObject/PhpFeature.php | 30 +++++++-- src/Lines/Finder/MeasureFileFinder.php | 6 +- src/Lines/Finder/ProjectFilesFinder.php | 4 +- .../NodeVisitor/StructureNodeVisitor.php | 11 +++- src/Lines/NumberFormat.php | 15 ++++- .../OutputFormatter/TextOutputFormatter.php | 20 ++++-- src/MockedClassResolver.php | 13 ++-- src/ParentClassResolver.php | 13 ++-- src/PhpParser/CachedPhpParser.php | 11 +++- src/PhpParser/Finder/ClassConstFinder.php | 13 ++-- .../Finder/ClassConstantFetchFinder.php | 20 ++++-- .../AddImportConfigMethodCallNodeVisitor.php | 13 ++-- .../EntityClassNameCollectingNodeVisitor.php | 10 +-- ...ExtractSymfonyExtensionCallNodeVisitor.php | 7 ++- .../FindClassConstFetchNodeVisitor.php | 7 ++- .../FindNonPrivateClassConstNodeVisitor.php | 13 ++-- .../NeedForFinalizeNodeVisitor.php | 12 +++- .../ParentClassNameCollectingNodeVisitor.php | 8 +-- .../Command/DetectUnitTestsCommand.php | 34 ++++++++--- src/Testing/UnitTestFilePathsFinder.php | 20 ++++-- src/Testing/UnitTestFilter.php | 21 +++++-- src/Twig/TwigTemplateConstantExtractor.php | 2 +- src/ValueObject/ClassConstant.php | 19 +++++- .../AbstractClassConstantFetch.php | 18 ++++-- .../EntityClassResolverTest.php | 2 - .../ConflictResolver/ConflictResolverTest.php | 5 +- .../NeedsFinalizeAnalyzerTest.php | 11 ++-- .../ParentClassResolverTest.php | 2 - .../ClassConstFinder/ClassConstFinderTest.php | 7 +-- .../ClassConstantFetchFinderTest.php | 2 - ...ckedClassNameCollectingNodeVisitorTest.php | 8 +-- .../TwigTemplateConstantExtractorTest.php | 2 - .../YamlConfigConstantExtractorTest.php | 2 - 65 files changed, 743 insertions(+), 279 deletions(-) create mode 100644 .phpunit.result.cache diff --git a/.github/workflows/bare_run.yaml b/.github/workflows/bare_run.yaml index 648da5344d..976231f8bf 100644 --- a/.github/workflows/bare_run.yaml +++ b/.github/workflows/bare_run.yaml @@ -1,9 +1,10 @@ name: Bare Run on various PHP versions on: + pull_request: null push: - tags: - - '*' + branches: + - main jobs: bare_run: @@ -12,12 +13,20 @@ jobs: strategy: fail-fast: false matrix: - php_version: ['7.4', '8.0', '8.1'] + php_version: ['7.4', '8.2', '8.5'] steps: + - uses: actions/checkout@v4 + - uses: shivammathur/setup-php@v2 with: - php-version: ${{ matrix.php }} + php-version: ${{ matrix.php_version }} coverage: none - - run: composer require rector/swiss-knife --dev --ansi + - run: composer install --no-dev --ansi + + # verify sources parse on the target PHP version + - run: find bin src -name '*.php' -print0 | xargs -0 -n1 -P4 php -l + + # smoke-test the binary + - run: bin/swiss-knife diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 0000000000..29ccaa2bc7 --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +{"version":1,"defects":[],"times":{"Rector\\SwissKnife\\Tests\\Command\\NamespaceToPSR4CommandTest::testNamespaceRootOptionIsKeptAsString":0.008,"Rector\\SwissKnife\\Tests\\Comments\\CommentedCodeAnalyzerTest::test":0,"Rector\\SwissKnife\\Tests\\DuplicatedCode\\CloneDetectorTest::testDetectsDuplicateAcrossFiles":0.001,"Rector\\SwissKnife\\Tests\\DuplicatedCode\\CloneDetectorTest::testDoesNotReportUniqueCode":0,"Rector\\SwissKnife\\Tests\\EntityClassResolver\\EntityClassResolverTest::test":0.017,"Rector\\SwissKnife\\Tests\\EntityClassResolver\\EntityClassResolverTest::testODMDocument":0.005,"Rector\\SwissKnife\\Tests\\Finder\\FilesFinderTest::testFindAll":0,"Rector\\SwissKnife\\Tests\\Finder\\FilesFinderTest::testExcludeByPath":0,"Rector\\SwissKnife\\Tests\\Finder\\FilesFinderTest::testExcludeByFnMatch":0,"Rector\\SwissKnife\\Tests\\Finder\\PhpFilesFinderTest::testExcludeByFnMatch":0.004,"Rector\\SwissKnife\\Tests\\Finder\\PhpFilesFinderTest::testExcludeByFnMatch2":0.004,"Rector\\SwissKnife\\Tests\\Git\\ConflictResolver\\ConflictResolverTest::test with data set #0":0,"Rector\\SwissKnife\\Tests\\Git\\ConflictResolver\\ConflictResolverTest::test with data set #1":0,"Rector\\SwissKnife\\Tests\\Git\\ConflictResolver\\ConflictResolverTest::test with data set #2":0,"Rector\\SwissKnife\\Tests\\Git\\ConflictResolver\\ConflictResolverTest::test with data set #3":0,"Rector\\SwissKnife\\Tests\\Lines\\AnalyserTest::test":0.008,"Rector\\SwissKnife\\Tests\\Lines\\FeatureCounter\\FeatureCounterAnalyzerTest::test":0.006,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #0":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #1":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #2":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #3":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #4":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #5":0.004,"Rector\\SwissKnife\\Tests\\ParentClassResolver\\ParentClassResolverTest::test":0.006,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstFinder\\ClassConstFinderTest::test with data set #0":0.005,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstFinder\\ClassConstFinderTest::test with data set #1":0.004,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstFinder\\ClassConstFinderTest::test with data set #2":0.004,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstantFetchFinder\\ClassConstantFetchFinderTest::testSkipInterfaceTraitAndEnum":0.005,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstantFetchFinder\\ClassConstantFetchFinderTest::test":0.005,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstantFetchFinder\\ClassConstantFetchFinderTest::testParseError":0.005,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"createMock\"":0.001,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"createStub\"":0.001,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"createStubForIntersectionOfInterfaces\"":0,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"createConfiguredStub\"":0.001,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"unrelated method is not detected\"":0.001,"Rector\\SwissKnife\\Tests\\RobotLoader\\PhpClassLoaderTest::test":0,"Rector\\SwissKnife\\Tests\\RobotLoader\\PhpClassLoaderTest::testExcludedPathIsSkipped":0,"Rector\\SwissKnife\\Tests\\SmokeTestgen\\TestTemplateResolver\\TestTemplateResolverTest::test":0.004,"Rector\\SwissKnife\\Tests\\SmokeTestgen\\Utils\\TestPathResolverTest::test":0,"Rector\\SwissKnife\\Tests\\Testing\\UnitTestFilePathsFinder\\UnitTestFilePathsFinderTest::test":0.001,"Rector\\SwissKnife\\Tests\\Twig\\TwigTemplateConstantExtractor\\TwigTemplateConstantExtractorTest::test":0.004,"Rector\\SwissKnife\\Tests\\YAML\\YamlConfigConstantExtractor\\YamlConfigConstantExtractorTest::test":0.004}} \ No newline at end of file diff --git a/composer.json b/composer.json index 2e24970515..f6ead92c0d 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "bin/swiss-knife" ], "require": { - "php": ">=8.4", + "php": ">=7.4", "ext-tokenizer": "*", "entropy/entropy": "^0.4.23", "nikic/php-parser": "^5.9" @@ -14,7 +14,7 @@ "require-dev": { "phpstan/extension-installer": "^1.4", "phpstan/phpstan": "^2.2", - "phpunit/phpunit": "^12.5", + "phpunit/phpunit": "^9.6", "rector/jack": "^1.1", "rector/rector": "^2.4", "shipmonk/composer-dependency-analyser": "^1.8", diff --git a/phpunit.xml b/phpunit.xml index e89aa98b41..9d1c4cb146 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -4,7 +4,6 @@ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" - cacheDirectory=".phpunit.cache" > diff --git a/src/Analyzer/NeedsFinalizeAnalyzer.php b/src/Analyzer/NeedsFinalizeAnalyzer.php index 991b8f088e..b4bd854d45 100644 --- a/src/Analyzer/NeedsFinalizeAnalyzer.php +++ b/src/Analyzer/NeedsFinalizeAnalyzer.php @@ -10,10 +10,21 @@ use Rector\SwissKnife\PhpParser\NodeTraverserFactory; use Rector\SwissKnife\PhpParser\NodeVisitor\NeedForFinalizeNodeVisitor; -final readonly class NeedsFinalizeAnalyzer +final class NeedsFinalizeAnalyzer { + /** + * @readonly + */ + private CachedPhpParser $cachedPhpParser; + + /** + * @readonly + */ private NodeTraverser $finalizingNodeTraverser; + /** + * @readonly + */ private NeedForFinalizeNodeVisitor $needForFinalizeNodeVisitor; /** @@ -21,8 +32,9 @@ */ public function __construct( array $excludedClasses, - private CachedPhpParser $cachedPhpParser + CachedPhpParser $cachedPhpParser ) { + $this->cachedPhpParser = $cachedPhpParser; Assert::allString($excludedClasses); $this->needForFinalizeNodeVisitor = new NeedForFinalizeNodeVisitor($excludedClasses); diff --git a/src/Command/CheckCommentedCodeCommand.php b/src/Command/CheckCommentedCodeCommand.php index 52bef075ee..2e67c299a5 100644 --- a/src/Command/CheckCommentedCodeCommand.php +++ b/src/Command/CheckCommentedCodeCommand.php @@ -11,14 +11,27 @@ use Rector\SwissKnife\Comments\CommentedCodeAnalyzer; use Rector\SwissKnife\Finder\PhpFilesFinder; -final readonly class CheckCommentedCodeCommand implements CommandInterface +final class CheckCommentedCodeCommand implements CommandInterface { - private const int DEFAULT_LINE_LIMIT = 5; + /** + * @readonly + */ + private CommentedCodeAnalyzer $commentedCodeAnalyzer; + + /** + * @readonly + */ + private OutputPrinter $outputPrinter; - public function __construct( - private CommentedCodeAnalyzer $commentedCodeAnalyzer, - private OutputPrinter $outputPrinter, - ) { + /** + * @var int + */ + private const DEFAULT_LINE_LIMIT = 5; + + public function __construct(CommentedCodeAnalyzer $commentedCodeAnalyzer, OutputPrinter $outputPrinter) + { + $this->commentedCodeAnalyzer = $commentedCodeAnalyzer; + $this->outputPrinter = $outputPrinter; } /** diff --git a/src/Command/CheckConflictsCommand.php b/src/Command/CheckConflictsCommand.php index 8c650f2464..4583243086 100644 --- a/src/Command/CheckConflictsCommand.php +++ b/src/Command/CheckConflictsCommand.php @@ -10,12 +10,22 @@ use Rector\SwissKnife\Finder\FilesFinder; use Rector\SwissKnife\Git\ConflictResolver; -final readonly class CheckConflictsCommand implements CommandInterface +final class CheckConflictsCommand implements CommandInterface { - public function __construct( - private ConflictResolver $conflictResolver, - private OutputPrinter $outputPrinter, - ) { + /** + * @readonly + */ + private ConflictResolver $conflictResolver; + + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + public function __construct(ConflictResolver $conflictResolver, OutputPrinter $outputPrinter) + { + $this->conflictResolver = $conflictResolver; + $this->outputPrinter = $outputPrinter; } /** diff --git a/src/Command/DuplicatedCodeCommand.php b/src/Command/DuplicatedCodeCommand.php index f8cfd0e3d6..c9b3b2169a 100644 --- a/src/Command/DuplicatedCodeCommand.php +++ b/src/Command/DuplicatedCodeCommand.php @@ -10,15 +10,26 @@ use Rector\SwissKnife\DuplicatedCode\CloneDetector; use Rector\SwissKnife\Finder\PhpFilesFinder; -final readonly class DuplicatedCodeCommand implements CommandInterface +final class DuplicatedCodeCommand implements CommandInterface { - private const int DEFAULT_MIN_LINES = 5; + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + /** + * @var int + */ + private const DEFAULT_MIN_LINES = 5; - private const int DEFAULT_MIN_TOKENS = 70; + /** + * @var int + */ + private const DEFAULT_MIN_TOKENS = 70; - public function __construct( - private OutputPrinter $outputPrinter, - ) { + public function __construct(OutputPrinter $outputPrinter) + { + $this->outputPrinter = $outputPrinter; } /** diff --git a/src/Command/FeaturesCommand.php b/src/Command/FeaturesCommand.php index 811f84dda0..962efd9aa4 100644 --- a/src/Command/FeaturesCommand.php +++ b/src/Command/FeaturesCommand.php @@ -13,14 +13,34 @@ use Rector\SwissKnife\Lines\Finder\ProjectFilesFinder; use Rector\SwissKnife\Lines\OutputFormatter\JsonOutputFormatter; -final readonly class FeaturesCommand implements CommandInterface +final class FeaturesCommand implements CommandInterface { - public function __construct( - private OutputPrinter $outputPrinter, - private FeatureCounterAnalyzer $featureCounterAnalyzer, - private ResultPrinter $resultPrinter, - private JsonOutputFormatter $jsonOutputFormatter, - ) { + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + /** + * @readonly + */ + private FeatureCounterAnalyzer $featureCounterAnalyzer; + + /** + * @readonly + */ + private ResultPrinter $resultPrinter; + + /** + * @readonly + */ + private JsonOutputFormatter $jsonOutputFormatter; + + public function __construct(OutputPrinter $outputPrinter, FeatureCounterAnalyzer $featureCounterAnalyzer, ResultPrinter $resultPrinter, JsonOutputFormatter $jsonOutputFormatter) + { + $this->outputPrinter = $outputPrinter; + $this->featureCounterAnalyzer = $featureCounterAnalyzer; + $this->resultPrinter = $resultPrinter; + $this->jsonOutputFormatter = $jsonOutputFormatter; } /** diff --git a/src/Command/FinalizeClassesCommand.php b/src/Command/FinalizeClassesCommand.php index b008ca5dfb..19c8c57036 100644 --- a/src/Command/FinalizeClassesCommand.php +++ b/src/Command/FinalizeClassesCommand.php @@ -18,20 +18,46 @@ use Rector\SwissKnife\ParentClassResolver; use Rector\SwissKnife\PhpParser\CachedPhpParser; -final readonly class FinalizeClassesCommand implements CommandInterface +final class FinalizeClassesCommand implements CommandInterface { + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + /** + * @readonly + */ + private ParentClassResolver $parentClassResolver; + + /** + * @readonly + */ + private EntityClassResolver $entityClassResolver; + + /** + * @readonly + */ + private CachedPhpParser $cachedPhpParser; + + /** + * @readonly + */ + private MockedClassResolver $mockedClassResolver; + /** * @see https://regex101.com/r/Q5Nfbo/1 + * @var string */ - private const string NEWLINE_CLASS_START_REGEX = '#^(readonly )?class\s#m'; - - public function __construct( - private OutputPrinter $outputPrinter, - private ParentClassResolver $parentClassResolver, - private EntityClassResolver $entityClassResolver, - private CachedPhpParser $cachedPhpParser, - private MockedClassResolver $mockedClassResolver, - ) { + private const NEWLINE_CLASS_START_REGEX = '#^(readonly )?class\s#m'; + + public function __construct(OutputPrinter $outputPrinter, ParentClassResolver $parentClassResolver, EntityClassResolver $entityClassResolver, CachedPhpParser $cachedPhpParser, MockedClassResolver $mockedClassResolver) + { + $this->outputPrinter = $outputPrinter; + $this->parentClassResolver = $parentClassResolver; + $this->entityClassResolver = $entityClassResolver; + $this->cachedPhpParser = $cachedPhpParser; + $this->mockedClassResolver = $mockedClassResolver; } /** diff --git a/src/Command/FindMultiClassesCommand.php b/src/Command/FindMultiClassesCommand.php index e7b0cc907c..fd20df6425 100644 --- a/src/Command/FindMultiClassesCommand.php +++ b/src/Command/FindMultiClassesCommand.php @@ -11,12 +11,22 @@ use Rector\SwissKnife\Finder\MultipleClassInOneFileFinder; use Rector\SwissKnife\Finder\PhpFilesFinder; -final readonly class FindMultiClassesCommand implements CommandInterface +final class FindMultiClassesCommand implements CommandInterface { - public function __construct( - private MultipleClassInOneFileFinder $multipleClassInOneFileFinder, - private OutputPrinter $outputPrinter, - ) { + /** + * @readonly + */ + private MultipleClassInOneFileFinder $multipleClassInOneFileFinder; + + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + public function __construct(MultipleClassInOneFileFinder $multipleClassInOneFileFinder, OutputPrinter $outputPrinter) + { + $this->multipleClassInOneFileFinder = $multipleClassInOneFileFinder; + $this->outputPrinter = $outputPrinter; } /** diff --git a/src/Command/GenerateSymfonySmokeTestsCommand.php b/src/Command/GenerateSymfonySmokeTestsCommand.php index 9db622b467..08e509128a 100644 --- a/src/Command/GenerateSymfonySmokeTestsCommand.php +++ b/src/Command/GenerateSymfonySmokeTestsCommand.php @@ -16,14 +16,34 @@ use Rector\SwissKnife\SmokeTestgen\Utils\TestPathResolver; use RuntimeException; -final readonly class GenerateSymfonySmokeTestsCommand implements CommandInterface +final class GenerateSymfonySmokeTestsCommand implements CommandInterface { - public function __construct( - private TestsDirectoryResolver $testsDirectoryResolver, - private TestTemplateResolver $testTemplateResolver, - private TemplateDecorator $templateDecorator, - private OutputPrinter $outputPrinter, - ) { + /** + * @readonly + */ + private TestsDirectoryResolver $testsDirectoryResolver; + + /** + * @readonly + */ + private TestTemplateResolver $testTemplateResolver; + + /** + * @readonly + */ + private TemplateDecorator $templateDecorator; + + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + public function __construct(TestsDirectoryResolver $testsDirectoryResolver, TestTemplateResolver $testTemplateResolver, TemplateDecorator $templateDecorator, OutputPrinter $outputPrinter) + { + $this->testsDirectoryResolver = $testsDirectoryResolver; + $this->testTemplateResolver = $testTemplateResolver; + $this->templateDecorator = $templateDecorator; + $this->outputPrinter = $outputPrinter; } public function getName(): string diff --git a/src/Command/MeasureCommand.php b/src/Command/MeasureCommand.php index f19001092e..2fff35abec 100644 --- a/src/Command/MeasureCommand.php +++ b/src/Command/MeasureCommand.php @@ -13,14 +13,34 @@ use Rector\SwissKnife\Lines\OutputFormatter\JsonOutputFormatter; use Rector\SwissKnife\Lines\OutputFormatter\TextOutputFormatter; -final readonly class MeasureCommand implements CommandInterface +final class MeasureCommand implements CommandInterface { - public function __construct( - private OutputPrinter $outputPrinter, - private Analyser $analyser, - private JsonOutputFormatter $jsonOutputFormatter, - private TextOutputFormatter $textOutputFormatter, - ) { + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + /** + * @readonly + */ + private Analyser $analyser; + + /** + * @readonly + */ + private JsonOutputFormatter $jsonOutputFormatter; + + /** + * @readonly + */ + private TextOutputFormatter $textOutputFormatter; + + public function __construct(OutputPrinter $outputPrinter, Analyser $analyser, JsonOutputFormatter $jsonOutputFormatter, TextOutputFormatter $textOutputFormatter) + { + $this->outputPrinter = $outputPrinter; + $this->analyser = $analyser; + $this->jsonOutputFormatter = $jsonOutputFormatter; + $this->textOutputFormatter = $textOutputFormatter; } /** diff --git a/src/Command/NamespaceToPSR4Command.php b/src/Command/NamespaceToPSR4Command.php index 3825add228..334deeff9b 100644 --- a/src/Command/NamespaceToPSR4Command.php +++ b/src/Command/NamespaceToPSR4Command.php @@ -15,11 +15,16 @@ /** * @see \Rector\SwissKnife\Tests\Command\NamespaceToPSR4CommandTest */ -final readonly class NamespaceToPSR4Command implements CommandInterface +final class NamespaceToPSR4Command implements CommandInterface { - public function __construct( - private OutputPrinter $outputPrinter, - ) { + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + public function __construct(OutputPrinter $outputPrinter) + { + $this->outputPrinter = $outputPrinter; } /** @@ -42,7 +47,7 @@ public function run(string $path, string $namespaceRoot): int $expectedNamespaceLine = 'namespace ' . $expectedNamespace . ';'; // 1. got the correct namespace - if (\str_contains($fileInfo->getContents(), $expectedNamespaceLine)) { + if (strpos($fileInfo->getContents(), $expectedNamespaceLine) !== false) { continue; } @@ -105,7 +110,7 @@ private function findFilesInPath(string $path): array } // filter classes - return str_contains($fileInfo->getContents(), 'class '); + return strpos($fileInfo->getContents(), 'class ') !== false; }); } diff --git a/src/Command/PrivatizeConstantsCommand.php b/src/Command/PrivatizeConstantsCommand.php index 617a4e52e3..d985de608b 100644 --- a/src/Command/PrivatizeConstantsCommand.php +++ b/src/Command/PrivatizeConstantsCommand.php @@ -21,15 +21,40 @@ use Rector\SwissKnife\ValueObject\VisibilityChangeStats; use Rector\SwissKnife\YAML\YamlConfigConstantExtractor; -final readonly class PrivatizeConstantsCommand implements CommandInterface +final class PrivatizeConstantsCommand implements CommandInterface { - public function __construct( - private OutputPrinter $outputPrinter, - private ClassConstantFetchFinder $classConstantFetchFinder, - private ClassConstFinder $classConstFinder, - private TwigTemplateConstantExtractor $twigTemplateConstantExtractor, - private YamlConfigConstantExtractor $yamlConfigConstantExtractor - ) { + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + /** + * @readonly + */ + private ClassConstantFetchFinder $classConstantFetchFinder; + + /** + * @readonly + */ + private ClassConstFinder $classConstFinder; + + /** + * @readonly + */ + private TwigTemplateConstantExtractor $twigTemplateConstantExtractor; + + /** + * @readonly + */ + private YamlConfigConstantExtractor $yamlConfigConstantExtractor; + + public function __construct(OutputPrinter $outputPrinter, ClassConstantFetchFinder $classConstantFetchFinder, ClassConstFinder $classConstFinder, TwigTemplateConstantExtractor $twigTemplateConstantExtractor, YamlConfigConstantExtractor $yamlConfigConstantExtractor) + { + $this->outputPrinter = $outputPrinter; + $this->classConstantFetchFinder = $classConstantFetchFinder; + $this->classConstFinder = $classConstFinder; + $this->twigTemplateConstantExtractor = $twigTemplateConstantExtractor; + $this->yamlConfigConstantExtractor = $yamlConfigConstantExtractor; } public function getName(): string diff --git a/src/Command/SplitSymfonyConfigToPerPackageCommand.php b/src/Command/SplitSymfonyConfigToPerPackageCommand.php index 386c95c973..e6cb2c3392 100644 --- a/src/Command/SplitSymfonyConfigToPerPackageCommand.php +++ b/src/Command/SplitSymfonyConfigToPerPackageCommand.php @@ -21,14 +21,29 @@ use Rector\SwissKnife\PhpParser\NodeVisitor\AddImportConfigMethodCallNodeVisitor; use Rector\SwissKnife\PhpParser\NodeVisitor\ExtractSymfonyExtensionCallNodeVisitor; -final readonly class SplitSymfonyConfigToPerPackageCommand implements CommandInterface +final class SplitSymfonyConfigToPerPackageCommand implements CommandInterface { + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + /** + * @readonly + */ + private SplitConfigClosureFactory $splitConfigClosureFactory; + + /** + * @readonly + */ private Standard $printerStandard; public function __construct( - private OutputPrinter $outputPrinter, - private SplitConfigClosureFactory $splitConfigClosureFactory, + OutputPrinter $outputPrinter, + SplitConfigClosureFactory $splitConfigClosureFactory ) { + $this->outputPrinter = $outputPrinter; + $this->splitConfigClosureFactory = $splitConfigClosureFactory; $this->printerStandard = new Standard(); } diff --git a/src/Comments/CommentedCodeAnalyzer.php b/src/Comments/CommentedCodeAnalyzer.php index a4b0ffa9c9..c6150ee35b 100644 --- a/src/Comments/CommentedCodeAnalyzer.php +++ b/src/Comments/CommentedCodeAnalyzer.php @@ -15,8 +15,9 @@ final class CommentedCodeAnalyzer /** * @see https://regex101.com/r/5OlGjG/1 * @see https://3v4l.org/Y8pSD + * @var string */ - private const string NEWLINE_REGEX = '#\r?\n#'; + private const NEWLINE_REGEX = '#\r?\n#'; /** * @return int[] @@ -30,7 +31,7 @@ public function process(string $filePath, int $commentedLinesCountLimit): array $commentLinesCount = 0; foreach ($fileLines as $key => $fileLine) { - $isCommentLine = str_starts_with(trim((string) $fileLine), '//'); + $isCommentLine = strncmp(trim((string) $fileLine), '//', strlen('//')) === 0; if ($isCommentLine) { ++$commentLinesCount; } else { diff --git a/src/DuplicatedCode/CloneDetector.php b/src/DuplicatedCode/CloneDetector.php index 49476dbae5..a94f87d015 100644 --- a/src/DuplicatedCode/CloneDetector.php +++ b/src/DuplicatedCode/CloneDetector.php @@ -14,12 +14,27 @@ */ final class CloneDetector { + /** + * @readonly + */ + private int $minLines; + + /** + * @readonly + */ + private int $minTokens; + + /** + * @readonly + */ + private bool $fuzzy; + /** * Tokens that carry no structural meaning for clone detection. * * @var array */ - private const array IGNORED_TOKENS = [ + private const IGNORED_TOKENS = [ T_INLINE_HTML => true, T_COMMENT => true, T_DOC_COMMENT => true, @@ -31,8 +46,9 @@ final class CloneDetector /** * Bytes contributed by each kept token to the signature: 1 type byte + 4 CRC32 bytes. + * @var int */ - private const int BYTES_PER_TOKEN = 5; + private const BYTES_PER_TOKEN = 5; /** * First seen location per window hash: hash => [filePath, tokenIndex]. @@ -53,11 +69,11 @@ final class CloneDetector */ private array $clones = []; - public function __construct( - private readonly int $minLines, - private readonly int $minTokens, - private readonly bool $fuzzy - ) { + public function __construct(int $minLines, int $minTokens, bool $fuzzy) + { + $this->minLines = $minLines; + $this->minTokens = $minTokens; + $this->fuzzy = $fuzzy; } /** @@ -97,7 +113,7 @@ private function processFile(string $filePath): void $originToken = 0; for ($i = 0; $i <= $lastWindow; ++$i) { - $hash = substr(md5(substr($signature, $i * self::BYTES_PER_TOKEN, $windowBytes), true), 0, 8); + $hash = substr(md5((string) substr($signature, $i * self::BYTES_PER_TOKEN, $windowBytes), true), 0, 8); if (isset($this->hashes[$hash])) { if (! $found) { diff --git a/src/DuplicatedCode/ValueObject/CodeClone.php b/src/DuplicatedCode/ValueObject/CodeClone.php index c4ad52a6a2..fbe36f0323 100644 --- a/src/DuplicatedCode/ValueObject/CodeClone.php +++ b/src/DuplicatedCode/ValueObject/CodeClone.php @@ -4,13 +4,33 @@ namespace Rector\SwissKnife\DuplicatedCode\ValueObject; -final readonly class CodeClone +final class CodeClone { - public function __construct( - public CodeCloneFile $firstFile, - public CodeCloneFile $secondFile, - public int $lines, - public int $tokens - ) { + /** + * @readonly + */ + public CodeCloneFile $firstFile; + + /** + * @readonly + */ + public CodeCloneFile $secondFile; + + /** + * @readonly + */ + public int $lines; + + /** + * @readonly + */ + public int $tokens; + + public function __construct(CodeCloneFile $firstFile, CodeCloneFile $secondFile, int $lines, int $tokens) + { + $this->firstFile = $firstFile; + $this->secondFile = $secondFile; + $this->lines = $lines; + $this->tokens = $tokens; } } diff --git a/src/DuplicatedCode/ValueObject/CodeCloneFile.php b/src/DuplicatedCode/ValueObject/CodeCloneFile.php index 57e238dd58..f58378c43a 100644 --- a/src/DuplicatedCode/ValueObject/CodeCloneFile.php +++ b/src/DuplicatedCode/ValueObject/CodeCloneFile.php @@ -4,12 +4,27 @@ namespace Rector\SwissKnife\DuplicatedCode\ValueObject; -final readonly class CodeCloneFile +final class CodeCloneFile { - public function __construct( - public string $filePath, - public int $startLine, - public int $endLine - ) { + /** + * @readonly + */ + public string $filePath; + + /** + * @readonly + */ + public int $startLine; + + /** + * @readonly + */ + public int $endLine; + + public function __construct(string $filePath, int $startLine, int $endLine) + { + $this->filePath = $filePath; + $this->startLine = $startLine; + $this->endLine = $endLine; } } diff --git a/src/EntityClassResolver.php b/src/EntityClassResolver.php index b0894478b4..d77b025071 100644 --- a/src/EntityClassResolver.php +++ b/src/EntityClassResolver.php @@ -17,16 +17,22 @@ /** * @see \Rector\SwissKnife\Tests\EntityClassResolver\EntityClassResolverTest */ -final readonly class EntityClassResolver +final class EntityClassResolver { + /** + * @readonly + */ + private CachedPhpParser $cachedPhpParser; + /** * @see https://regex101.com/r/YFbH1x/1 + * @var string */ - private const string YAML_ENTITY_CLASS_NAME_REGEX = '#^(?[\w+\\\\]+)\:\n#m'; + private const YAML_ENTITY_CLASS_NAME_REGEX = '#^(?[\w+\\\\]+)\:\n#m'; - public function __construct( - private CachedPhpParser $cachedPhpParser - ) { + public function __construct(CachedPhpParser $cachedPhpParser) + { + $this->cachedPhpParser = $cachedPhpParser; } /** diff --git a/src/Enum/StaticAccessor.php b/src/Enum/StaticAccessor.php index a16623dd21..5ee622f1fe 100644 --- a/src/Enum/StaticAccessor.php +++ b/src/Enum/StaticAccessor.php @@ -6,7 +6,13 @@ final class StaticAccessor { - public const string STATIC = 'static'; + /** + * @var string + */ + public const STATIC = 'static'; - public const string SELF = 'self'; + /** + * @var string + */ + public const SELF = 'self'; } diff --git a/src/Enum/SymfonyClass.php b/src/Enum/SymfonyClass.php index e01828b9c7..5b47545862 100644 --- a/src/Enum/SymfonyClass.php +++ b/src/Enum/SymfonyClass.php @@ -8,5 +8,8 @@ final class SymfonyClass { - public const string CONTAINER_CONFIGURATOR_CLASS = ContainerConfigurator::class; + /** + * @var string + */ + public const CONTAINER_CONFIGURATOR_CLASS = ContainerConfigurator::class; } diff --git a/src/Finder/FilesFinder.php b/src/Finder/FilesFinder.php index 750bbf2ea5..17720ecb34 100644 --- a/src/Finder/FilesFinder.php +++ b/src/Finder/FilesFinder.php @@ -16,7 +16,7 @@ final class FilesFinder /** * @var string[] */ - private const array SKIPPED_DIRECTORIES = ['node_modules', 'vendor', 'var/cache']; + private const SKIPPED_DIRECTORIES = ['node_modules', 'vendor', 'var/cache']; /** * @param string[] $sources @@ -36,7 +36,7 @@ public static function find(array $sources, array $excludedPaths = []): array // not our code $normalizedRelativePath = '/' . str_replace('\\', '/', $fileInfo->getRelativePathname()); foreach (self::SKIPPED_DIRECTORIES as $skippedDirectory) { - if (str_contains($normalizedRelativePath, '/' . $skippedDirectory . '/')) { + if (strpos($normalizedRelativePath, '/' . $skippedDirectory . '/') !== false) { return false; } } @@ -81,11 +81,11 @@ public static function findYamlFiles(array $paths): array private static function isExcluded(string $realPath, array $excludedPaths): bool { foreach ($excludedPaths as $excludedPath) { - if (str_contains($realPath, $excludedPath)) { + if (strpos($realPath, $excludedPath) !== false) { return true; } - if (str_contains($excludedPath, '*') && fnmatch($excludedPath, $realPath)) { + if (strpos($excludedPath, '*') !== false && fnmatch($excludedPath, $realPath)) { return true; } } diff --git a/src/Finder/MultipleClassInOneFileFinder.php b/src/Finder/MultipleClassInOneFileFinder.php index 9c18d123e6..b82ae4d235 100644 --- a/src/Finder/MultipleClassInOneFileFinder.php +++ b/src/Finder/MultipleClassInOneFileFinder.php @@ -6,11 +6,16 @@ use Rector\SwissKnife\RobotLoader\PhpClassLoader; -final readonly class MultipleClassInOneFileFinder +final class MultipleClassInOneFileFinder { - public function __construct( - private PhpClassLoader $phpClassLoader - ) { + /** + * @readonly + */ + private PhpClassLoader $phpClassLoader; + + public function __construct(PhpClassLoader $phpClassLoader) + { + $this->phpClassLoader = $phpClassLoader; } /** diff --git a/src/Finder/PhpFilesFinder.php b/src/Finder/PhpFilesFinder.php index daeda016da..2594da43c8 100644 --- a/src/Finder/PhpFilesFinder.php +++ b/src/Finder/PhpFilesFinder.php @@ -16,7 +16,7 @@ final class PhpFilesFinder /** * @var string[] */ - private const array SKIPPED_DIRECTORIES = ['vendor', 'var', 'data-fixtures', 'node_modules']; + private const SKIPPED_DIRECTORIES = ['vendor', 'var', 'data-fixtures', 'node_modules']; /** * @param string[] $paths @@ -32,7 +32,7 @@ public static function find(array $paths, array $excludedPaths = []): array $excludedFileNames = []; foreach ($excludedPaths as $excludedPath) { - if (! str_contains($excludedPath, '*')) { + if (strpos($excludedPath, '*') === false) { $excludedFileNames[] = $excludedPath; } } @@ -46,7 +46,7 @@ public static function find(array $paths, array $excludedPaths = []): array $normalizedRelativePath = '/' . str_replace('\\', '/', $fileInfo->getRelativePathname()); foreach (self::SKIPPED_DIRECTORIES as $skippedDirectory) { - if (str_contains($normalizedRelativePath, '/' . $skippedDirectory . '/')) { + if (strpos($normalizedRelativePath, '/' . $skippedDirectory . '/') !== false) { return false; } } @@ -54,11 +54,11 @@ public static function find(array $paths, array $excludedPaths = []): array $realPath = (string) $fileInfo->getRealPath(); foreach ($excludedPaths as $excludedPath) { - if (str_contains($realPath, $excludedPath)) { + if (strpos($realPath, $excludedPath) !== false) { return false; } - if (str_contains($excludedPath, '*') && fnmatch($excludedPath, $realPath)) { + if (strpos($excludedPath, '*') !== false && fnmatch($excludedPath, $realPath)) { return false; } } diff --git a/src/Git/ConflictResolver.php b/src/Git/ConflictResolver.php index a2b265c504..47b9d79a42 100644 --- a/src/Git/ConflictResolver.php +++ b/src/Git/ConflictResolver.php @@ -14,8 +14,9 @@ final class ConflictResolver { /** * @see https://regex101.com/r/L2CThC/1 + * @var string */ - private const string CONFLICT_REGEX = '#^(<<<<<<<|>>>>>>>)#m'; + private const CONFLICT_REGEX = '#^(<<<<<<<|>>>>>>>)#m'; /** * @api @@ -43,7 +44,7 @@ public function extractFromFileInfos(array $filePaths): array } // test fixtures, that should be ignored - if (str_contains((string) realpath($filePath), '/tests/Git/ConflictResolver/Fixture')) { + if (strpos((string) realpath($filePath), '/tests/Git/ConflictResolver/Fixture') !== false) { continue; } diff --git a/src/Lines/Analyser.php b/src/Lines/Analyser.php index 865113471b..e4b1984c64 100644 --- a/src/Lines/Analyser.php +++ b/src/Lines/Analyser.php @@ -14,11 +14,16 @@ /** * @see \Rector\SwissKnife\Tests\Lines\AnalyserTest */ -final readonly class Analyser +final class Analyser { - public function __construct( - private Parser $parser, - ) { + /** + * @readonly + */ + private Parser $parser; + + public function __construct(Parser $parser) + { + $this->parser = $parser; } /** @@ -52,7 +57,7 @@ private function measureFile(Measurements $measurements, string $filePath): void try { // avoid stop on invalid file contents $stmts = $this->parser->parse($fileContents); - } catch (Throwable) { + } catch (Throwable $throwable) { return; } diff --git a/src/Lines/FeatureCounter/Enum/PhpVersion.php b/src/Lines/FeatureCounter/Enum/PhpVersion.php index 877387ae0b..d258235b92 100644 --- a/src/Lines/FeatureCounter/Enum/PhpVersion.php +++ b/src/Lines/FeatureCounter/Enum/PhpVersion.php @@ -6,21 +6,48 @@ final class PhpVersion { - public const string PHP_70 = '7.0'; - - public const string PHP_71 = '7.1'; - - public const string PHP_72 = '7.2'; - - public const string PHP_74 = '7.4'; - - public const string PHP_80 = '8.0'; - - public const string PHP_81 = '8.1'; - - public const string PHP_82 = '8.2'; - - public const string PHP_83 = '8.3'; - - public const string PHP_84 = '8.4'; + /** + * @var string + */ + public const PHP_70 = '7.0'; + + /** + * @var string + */ + public const PHP_71 = '7.1'; + + /** + * @var string + */ + public const PHP_72 = '7.2'; + + /** + * @var string + */ + public const PHP_74 = '7.4'; + + /** + * @var string + */ + public const PHP_80 = '8.0'; + + /** + * @var string + */ + public const PHP_81 = '8.1'; + + /** + * @var string + */ + public const PHP_82 = '8.2'; + + /** + * @var string + */ + public const PHP_83 = '8.3'; + + /** + * @var string + */ + public const PHP_84 = '8.4'; } diff --git a/src/Lines/FeatureCounter/FeatureCounterAnalyzer.php b/src/Lines/FeatureCounter/FeatureCounterAnalyzer.php index c81fc5a1b0..5887d3c651 100644 --- a/src/Lines/FeatureCounter/FeatureCounterAnalyzer.php +++ b/src/Lines/FeatureCounter/FeatureCounterAnalyzer.php @@ -16,13 +16,22 @@ /** * @see \Rector\SwissKnife\Tests\Lines\FeatureCounter\FeatureCounterAnalyzerTest */ -final readonly class FeatureCounterAnalyzer +final class FeatureCounterAnalyzer { + /** + * @readonly + */ + private FeatureCollector $featureCollector; + + /** + * @readonly + */ private Parser $parser; public function __construct( - private FeatureCollector $featureCollector, + FeatureCollector $featureCollector ) { + $this->featureCollector = $featureCollector; $parserFactory = new ParserFactory(); $this->parser = $parserFactory->createForNewestSupportedVersion(); } diff --git a/src/Lines/FeatureCounter/NodeVisitor/FeatureCollectorNodeVisitor.php b/src/Lines/FeatureCounter/NodeVisitor/FeatureCollectorNodeVisitor.php index 669267ac4e..55e2ae8b6b 100644 --- a/src/Lines/FeatureCounter/NodeVisitor/FeatureCollectorNodeVisitor.php +++ b/src/Lines/FeatureCounter/NodeVisitor/FeatureCollectorNodeVisitor.php @@ -10,9 +10,14 @@ final class FeatureCollectorNodeVisitor extends NodeVisitorAbstract { - public function __construct( - private readonly FeatureCollector $featureCollector - ) { + /** + * @readonly + */ + private FeatureCollector $featureCollector; + + public function __construct(FeatureCollector $featureCollector) + { + $this->featureCollector = $featureCollector; } public function enterNode(Node $node): ?Node diff --git a/src/Lines/FeatureCounter/ResultPrinter.php b/src/Lines/FeatureCounter/ResultPrinter.php index 0e8a5bbec4..71407b47ee 100644 --- a/src/Lines/FeatureCounter/ResultPrinter.php +++ b/src/Lines/FeatureCounter/ResultPrinter.php @@ -8,12 +8,22 @@ use Entropy\Console\Output\OutputPrinter; use Rector\SwissKnife\Lines\FeatureCounter\ValueObject\FeatureCollector; -final readonly class ResultPrinter +final class ResultPrinter { - public function __construct( - private OutputPrinter $outputPrinter, - private ConsoleTable $consoleTable, - ) { + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + /** + * @readonly + */ + private ConsoleTable $consoleTable; + + public function __construct(OutputPrinter $outputPrinter, ConsoleTable $consoleTable) + { + $this->outputPrinter = $outputPrinter; + $this->consoleTable = $consoleTable; } public function print(FeatureCollector $featureCollector): void diff --git a/src/Lines/FeatureCounter/ValueObject/PhpFeature.php b/src/Lines/FeatureCounter/ValueObject/PhpFeature.php index 87af8f63eb..04e807c398 100644 --- a/src/Lines/FeatureCounter/ValueObject/PhpFeature.php +++ b/src/Lines/FeatureCounter/ValueObject/PhpFeature.php @@ -8,16 +8,34 @@ final class PhpFeature { + /** + * @var PhpVersion::* + * @readonly + */ + private string $phpVersion; + + /** + * @readonly + */ + private string $name; + + /** + * @var callable + */ + private $nodeTrigger; + + private int $count; + /** * @param PhpVersion::* $phpVersion * @param callable $nodeTrigger */ - public function __construct( - private readonly string $phpVersion, - private readonly string $name, - private $nodeTrigger, - private int $count = 0 - ) { + public function __construct(string $phpVersion, string $name, $nodeTrigger, int $count = 0) + { + $this->phpVersion = $phpVersion; + $this->name = $name; + $this->nodeTrigger = $nodeTrigger; + $this->count = $count; } public function getPhpVersion(): string diff --git a/src/Lines/Finder/MeasureFileFinder.php b/src/Lines/Finder/MeasureFileFinder.php index 729abd065e..50b82377c1 100644 --- a/src/Lines/Finder/MeasureFileFinder.php +++ b/src/Lines/Finder/MeasureFileFinder.php @@ -42,17 +42,17 @@ static function (FileInfo $fileInfo) use ($excludes, $allowVendor): bool { $normalizedRelativePath = '/' . str_replace('\\', '/', $fileInfo->getRelativePathname()); // symfony cache dir - if (str_contains($normalizedRelativePath, '/var/')) { + if (strpos($normalizedRelativePath, '/var/') !== false) { return false; } - if (! $allowVendor && str_contains($normalizedRelativePath, '/vendor/')) { + if (! $allowVendor && strpos($normalizedRelativePath, '/vendor/') !== false) { return false; } $realPath = (string) $fileInfo->getRealPath(); foreach ($excludes as $exclude) { - if (str_contains($realPath, $exclude)) { + if (strpos($realPath, $exclude) !== false) { return false; } } diff --git a/src/Lines/Finder/ProjectFilesFinder.php b/src/Lines/Finder/ProjectFilesFinder.php index 953efcafd7..939b24deb6 100644 --- a/src/Lines/Finder/ProjectFilesFinder.php +++ b/src/Lines/Finder/ProjectFilesFinder.php @@ -12,7 +12,7 @@ final class ProjectFilesFinder /** * @var string[] */ - private const array SKIPPED_DIRECTORIES = ['vendor', 'stubs', 'bin', 'migrations', 'data-fixtures', 'build']; + private const SKIPPED_DIRECTORIES = ['vendor', 'stubs', 'bin', 'migrations', 'data-fixtures', 'build']; /** * @return FileInfo[] @@ -26,7 +26,7 @@ public static function find(string $projectDirectory): array $normalizedRelativePath = '/' . str_replace('\\', '/', $fileInfo->getRelativePathname()); foreach (self::SKIPPED_DIRECTORIES as $skippedDirectory) { - if (str_contains($normalizedRelativePath, '/' . $skippedDirectory . '/')) { + if (strpos($normalizedRelativePath, '/' . $skippedDirectory . '/') !== false) { return false; } } diff --git a/src/Lines/NodeVisitor/StructureNodeVisitor.php b/src/Lines/NodeVisitor/StructureNodeVisitor.php index 7885cdbcce..a34e79e991 100644 --- a/src/Lines/NodeVisitor/StructureNodeVisitor.php +++ b/src/Lines/NodeVisitor/StructureNodeVisitor.php @@ -21,9 +21,14 @@ final class StructureNodeVisitor extends NodeVisitorAbstract { - public function __construct( - private readonly Measurements $measurements - ) { + /** + * @readonly + */ + private Measurements $measurements; + + public function __construct(Measurements $measurements) + { + $this->measurements = $measurements; } public function enterNode(Node $node): ?Node diff --git a/src/Lines/NumberFormat.php b/src/Lines/NumberFormat.php index 81a1fc541d..f2ffe0107c 100644 --- a/src/Lines/NumberFormat.php +++ b/src/Lines/NumberFormat.php @@ -6,17 +6,26 @@ final class NumberFormat { - public static function pretty(int|float $number): string + /** + * @param int|float $number + */ + public static function pretty($number): string { return number_format($number, 0, '.', ' '); } - public static function singleDecimal(float|int $number): float + /** + * @param float|int $number + */ + public static function singleDecimal($number): float { return (float) number_format($number, 1); } - public static function percent(float|int $number): string + /** + * @param float|int $number + */ + public static function percent($number): string { return self::singleDecimal($number) . ' %'; } diff --git a/src/Lines/OutputFormatter/TextOutputFormatter.php b/src/Lines/OutputFormatter/TextOutputFormatter.php index 6010666120..9dfe615829 100644 --- a/src/Lines/OutputFormatter/TextOutputFormatter.php +++ b/src/Lines/OutputFormatter/TextOutputFormatter.php @@ -12,12 +12,22 @@ use Rector\SwissKnife\Lines\Measurements; use Rector\SwissKnife\Lines\NumberFormat; -final readonly class TextOutputFormatter +final class TextOutputFormatter { - public function __construct( - private ViewRenderer $viewRenderer, - private OutputPrinter $outputPrinter, - ) { + /** + * @readonly + */ + private ViewRenderer $viewRenderer; + + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + public function __construct(ViewRenderer $viewRenderer, OutputPrinter $outputPrinter) + { + $this->viewRenderer = $viewRenderer; + $this->outputPrinter = $outputPrinter; } public function printMeasurement(Measurements $measurements, bool $isShort, bool $showLongestFiles): void diff --git a/src/MockedClassResolver.php b/src/MockedClassResolver.php index 26b1fed4e3..1203b3216f 100644 --- a/src/MockedClassResolver.php +++ b/src/MockedClassResolver.php @@ -12,11 +12,16 @@ use Rector\SwissKnife\PhpParser\NodeTraverserFactory; use Rector\SwissKnife\PhpParser\NodeVisitor\MockedClassNameCollectingNodeVisitor; -final readonly class MockedClassResolver +final class MockedClassResolver { - public function __construct( - private CachedPhpParser $cachedPhpParser - ) { + /** + * @readonly + */ + private CachedPhpParser $cachedPhpParser; + + public function __construct(CachedPhpParser $cachedPhpParser) + { + $this->cachedPhpParser = $cachedPhpParser; } /** diff --git a/src/ParentClassResolver.php b/src/ParentClassResolver.php index 70ef7d689d..8be5623ba6 100644 --- a/src/ParentClassResolver.php +++ b/src/ParentClassResolver.php @@ -10,11 +10,16 @@ use Rector\SwissKnife\PhpParser\NodeTraverserFactory; use Rector\SwissKnife\PhpParser\NodeVisitor\ParentClassNameCollectingNodeVisitor; -final readonly class ParentClassResolver +final class ParentClassResolver { - public function __construct( - private CachedPhpParser $cachedPhpParser, - ) { + /** + * @readonly + */ + private CachedPhpParser $cachedPhpParser; + + public function __construct(CachedPhpParser $cachedPhpParser) + { + $this->cachedPhpParser = $cachedPhpParser; } /** diff --git a/src/PhpParser/CachedPhpParser.php b/src/PhpParser/CachedPhpParser.php index d267090c12..0346101d1f 100644 --- a/src/PhpParser/CachedPhpParser.php +++ b/src/PhpParser/CachedPhpParser.php @@ -16,14 +16,19 @@ */ final class CachedPhpParser { + /** + * @readonly + */ + private Parser $phpParser; + /** * @var array */ private array $cachedStmts = []; - public function __construct( - private readonly Parser $phpParser - ) { + public function __construct(Parser $phpParser) + { + $this->phpParser = $phpParser; } /** diff --git a/src/PhpParser/Finder/ClassConstFinder.php b/src/PhpParser/Finder/ClassConstFinder.php index 8b896ffc80..b1f56ab994 100644 --- a/src/PhpParser/Finder/ClassConstFinder.php +++ b/src/PhpParser/Finder/ClassConstFinder.php @@ -12,11 +12,16 @@ /** * @see \Rector\SwissKnife\Tests\PhpParser\Finder\ClassConstFinder\ClassConstFinderTest */ -final readonly class ClassConstFinder +final class ClassConstFinder { - public function __construct( - private CachedPhpParser $cachedPhpParser - ) { + /** + * @readonly + */ + private CachedPhpParser $cachedPhpParser; + + public function __construct(CachedPhpParser $cachedPhpParser) + { + $this->cachedPhpParser = $cachedPhpParser; } /** diff --git a/src/PhpParser/Finder/ClassConstantFetchFinder.php b/src/PhpParser/Finder/ClassConstantFetchFinder.php index b98f64e494..1eb3022c29 100644 --- a/src/PhpParser/Finder/ClassConstantFetchFinder.php +++ b/src/PhpParser/Finder/ClassConstantFetchFinder.php @@ -17,12 +17,22 @@ /** * @see \Rector\SwissKnife\Tests\PhpParser\ClassConstantFetchFinder\ClassConstantFetchFinderTest */ -final readonly class ClassConstantFetchFinder +final class ClassConstantFetchFinder { - public function __construct( - private CachedPhpParser $cachedPhpParser, - private OutputPrinter $outputPrinter, - ) { + /** + * @readonly + */ + private CachedPhpParser $cachedPhpParser; + + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + public function __construct(CachedPhpParser $cachedPhpParser, OutputPrinter $outputPrinter) + { + $this->cachedPhpParser = $cachedPhpParser; + $this->outputPrinter = $outputPrinter; } /** diff --git a/src/PhpParser/NodeVisitor/AddImportConfigMethodCallNodeVisitor.php b/src/PhpParser/NodeVisitor/AddImportConfigMethodCallNodeVisitor.php index 5f3fca705e..9c63e646e0 100644 --- a/src/PhpParser/NodeVisitor/AddImportConfigMethodCallNodeVisitor.php +++ b/src/PhpParser/NodeVisitor/AddImportConfigMethodCallNodeVisitor.php @@ -17,12 +17,17 @@ final class AddImportConfigMethodCallNodeVisitor extends NodeVisitorAbstract { - public function __construct( - private readonly string $outputDirectory - ) { + /** + * @readonly + */ + private string $outputDirectory; + + public function __construct(string $outputDirectory) + { + $this->outputDirectory = $outputDirectory; } - public function enterNode(Node $node): int|null + public function enterNode(Node $node): ?int { if (! $node instanceof Closure) { return null; diff --git a/src/PhpParser/NodeVisitor/EntityClassNameCollectingNodeVisitor.php b/src/PhpParser/NodeVisitor/EntityClassNameCollectingNodeVisitor.php index 030def73db..b1f6440197 100644 --- a/src/PhpParser/NodeVisitor/EntityClassNameCollectingNodeVisitor.php +++ b/src/PhpParser/NodeVisitor/EntityClassNameCollectingNodeVisitor.php @@ -16,12 +16,12 @@ final class EntityClassNameCollectingNodeVisitor extends NodeVisitorAbstract /** * @var string[] */ - private const array ODM_SUFFIXES = ['Document', 'EmbeddedDocument']; + private const ODM_SUFFIXES = ['Document', 'EmbeddedDocument']; /** * @var string[] */ - private const array ORM_SUFFIXES = ['Entity', 'Embeddable']; + private const ORM_SUFFIXES = ['Entity', 'Embeddable']; /** * @var string[] @@ -68,12 +68,12 @@ private function hasDocBlockSuffixes(Class_ $class, array $suffixes): bool $docComment = $class->getDocComment(); if ($docComment instanceof Doc) { // dummy check - if (! str_contains($docComment->getText(), '@')) { + if (strpos($docComment->getText(), '@') === false) { return false; } foreach ($suffixes as $suffix) { - if (str_contains($docComment->getText(), $suffix)) { + if (strpos($docComment->getText(), $suffix) !== false) { return true; } } @@ -92,7 +92,7 @@ private function hasAttributeSuffixes(Class_ $class, array $suffixes): bool foreach ($class->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { foreach ($suffixes as $suffix) { - if (str_ends_with($attr->name->toString(), $suffix)) { + if (substr_compare($attr->name->toString(), $suffix, -strlen($suffix)) === 0) { return true; } } diff --git a/src/PhpParser/NodeVisitor/ExtractSymfonyExtensionCallNodeVisitor.php b/src/PhpParser/NodeVisitor/ExtractSymfonyExtensionCallNodeVisitor.php index 362e1d530d..31f2220e98 100644 --- a/src/PhpParser/NodeVisitor/ExtractSymfonyExtensionCallNodeVisitor.php +++ b/src/PhpParser/NodeVisitor/ExtractSymfonyExtensionCallNodeVisitor.php @@ -12,14 +12,17 @@ final class ExtractSymfonyExtensionCallNodeVisitor extends NodeVisitorAbstract { - private const string EXTENSION_METHOD_NAME = 'extension'; + /** + * @var string + */ + private const EXTENSION_METHOD_NAME = 'extension'; /** * @var MethodCall[] */ private array $extensionMethodCalls = []; - public function enterNode(Node $node): int|null + public function enterNode(Node $node): ?int { if (! $node instanceof Expression) { return null; diff --git a/src/PhpParser/NodeVisitor/FindClassConstFetchNodeVisitor.php b/src/PhpParser/NodeVisitor/FindClassConstFetchNodeVisitor.php index 69a898ae21..a08a304710 100644 --- a/src/PhpParser/NodeVisitor/FindClassConstFetchNodeVisitor.php +++ b/src/PhpParser/NodeVisitor/FindClassConstFetchNodeVisitor.php @@ -34,7 +34,10 @@ final class FindClassConstFetchNodeVisitor extends NodeVisitorAbstract */ private array $classConstantFetches = []; - public function enterNode(Node $node): Node|int|null + /** + * @return Node|int|null + */ + public function enterNode(Node $node) { if ($node instanceof Interface_ || $node instanceof Trait_ || $node instanceof Enum_) { return NodeTraverser::DONT_TRAVERSE_CHILDREN; @@ -148,7 +151,7 @@ private function isVendorClassName(string $className): bool } $reflectionClass = new ReflectionClass($className); - return str_contains((string) $reflectionClass->getFileName(), 'vendor'); + return strpos((string) $reflectionClass->getFileName(), 'vendor') !== false; } private function isCurrentClassConstant(Class_ $currentClass, string $constantName): bool diff --git a/src/PhpParser/NodeVisitor/FindNonPrivateClassConstNodeVisitor.php b/src/PhpParser/NodeVisitor/FindNonPrivateClassConstNodeVisitor.php index 21a2d21e3a..805d336ad7 100644 --- a/src/PhpParser/NodeVisitor/FindNonPrivateClassConstNodeVisitor.php +++ b/src/PhpParser/NodeVisitor/FindNonPrivateClassConstNodeVisitor.php @@ -69,10 +69,15 @@ private function isConstantDefinedInParentClassAlso(Class_ $class, string $const } } - return array_any( - $class->implements, - fn (Name $name): bool => in_array($constantName, $this->getClassConstantNames($name->toString()), true) - ); + $found = false; + foreach ($class->implements as $name) { + if (in_array($constantName, $this->getClassConstantNames($name->toString()), true)) { + $found = true; + break; + } + } + + return $found; } /** diff --git a/src/PhpParser/NodeVisitor/NeedForFinalizeNodeVisitor.php b/src/PhpParser/NodeVisitor/NeedForFinalizeNodeVisitor.php index f95fbf1623..b53b9a79fe 100644 --- a/src/PhpParser/NodeVisitor/NeedForFinalizeNodeVisitor.php +++ b/src/PhpParser/NodeVisitor/NeedForFinalizeNodeVisitor.php @@ -11,14 +11,20 @@ final class NeedForFinalizeNodeVisitor extends NodeVisitorAbstract { + /** + * @var string[] + * @readonly + */ + private array $excludedClasses; + private bool $isNeeded = false; /** * @param string[] $excludedClasses */ - public function __construct( - private readonly array $excludedClasses - ) { + public function __construct(array $excludedClasses) + { + $this->excludedClasses = $excludedClasses; } /** diff --git a/src/PhpParser/NodeVisitor/ParentClassNameCollectingNodeVisitor.php b/src/PhpParser/NodeVisitor/ParentClassNameCollectingNodeVisitor.php index f0124cd290..3b53850847 100644 --- a/src/PhpParser/NodeVisitor/ParentClassNameCollectingNodeVisitor.php +++ b/src/PhpParser/NodeVisitor/ParentClassNameCollectingNodeVisitor.php @@ -42,20 +42,20 @@ public function getParentClassNames(): array // remove native classes $namespacedClassNames = array_filter( $uniqueParentClassNames, - static fn (string $parentClassName): bool => str_contains($parentClassName, '\\') + static fn (string $parentClassName): bool => strpos($parentClassName, '\\') !== false ); // remove obviously vendor names $namespacedClassNames = array_filter($namespacedClassNames, static function (string $className): bool { - if (str_contains($className, 'Symfony\\')) { + if (strpos($className, 'Symfony\\') !== false) { return false; } - if (str_contains($className, 'PHPStan\\')) { + if (strpos($className, 'PHPStan\\') !== false) { return false; } - return ! str_contains($className, 'PhpParser\\'); + return strpos($className, 'PhpParser\\') === false; }); return array_values($namespacedClassNames); diff --git a/src/Testing/Command/DetectUnitTestsCommand.php b/src/Testing/Command/DetectUnitTestsCommand.php index 81b7559ec4..8d8e82df41 100644 --- a/src/Testing/Command/DetectUnitTestsCommand.php +++ b/src/Testing/Command/DetectUnitTestsCommand.php @@ -12,15 +12,33 @@ use Rector\SwissKnife\Testing\Printer\PHPUnitXmlPrinter; use Rector\SwissKnife\Testing\UnitTestFilePathsFinder; -final readonly class DetectUnitTestsCommand implements CommandInterface +final class DetectUnitTestsCommand implements CommandInterface { - private const string OUTPUT_FILENAME = 'phpunit-unit-files.xml'; + /** + * @readonly + */ + private PHPUnitXmlPrinter $phpUnitXmlPrinter; + + /** + * @readonly + */ + private OutputPrinter $outputPrinter; + + /** + * @readonly + */ + private UnitTestFilePathsFinder $unitTestFilePathsFinder; + + /** + * @var string + */ + private const OUTPUT_FILENAME = 'phpunit-unit-files.xml'; - public function __construct( - private PHPUnitXmlPrinter $phpunitXmlPrinter, - private OutputPrinter $outputPrinter, - private UnitTestFilePathsFinder $unitTestFilePathsFinder, - ) { + public function __construct(PHPUnitXmlPrinter $phpunitXmlPrinter, OutputPrinter $outputPrinter, UnitTestFilePathsFinder $unitTestFilePathsFinder) + { + $this->phpUnitXmlPrinter = $phpunitXmlPrinter; + $this->outputPrinter = $outputPrinter; + $this->unitTestFilePathsFinder = $unitTestFilePathsFinder; } /** @@ -38,7 +56,7 @@ public function run(array $sources): int return ExitCode::SUCCESS; } - $filesPHPUnitXmlContents = $this->phpunitXmlPrinter->printFiles($unitTestCasesClassesToFilePaths); + $filesPHPUnitXmlContents = $this->phpUnitXmlPrinter->printFiles($unitTestCasesClassesToFilePaths); FileSystem::write(self::OUTPUT_FILENAME, $filesPHPUnitXmlContents); diff --git a/src/Testing/UnitTestFilePathsFinder.php b/src/Testing/UnitTestFilePathsFinder.php index 409b27d13b..954e110182 100644 --- a/src/Testing/UnitTestFilePathsFinder.php +++ b/src/Testing/UnitTestFilePathsFinder.php @@ -9,12 +9,22 @@ /** * @see \Rector\SwissKnife\Tests\Testing\UnitTestFilePathsFinder\UnitTestFilePathsFinderTest */ -final readonly class UnitTestFilePathsFinder +final class UnitTestFilePathsFinder { - public function __construct( - private TestCaseClassFinder $testCaseClassFinder, - private UnitTestFilter $unitTestFilter, - ) { + /** + * @readonly + */ + private TestCaseClassFinder $testCaseClassFinder; + + /** + * @readonly + */ + private UnitTestFilter $unitTestFilter; + + public function __construct(TestCaseClassFinder $testCaseClassFinder, UnitTestFilter $unitTestFilter) + { + $this->testCaseClassFinder = $testCaseClassFinder; + $this->unitTestFilter = $unitTestFilter; } /** diff --git a/src/Testing/UnitTestFilter.php b/src/Testing/UnitTestFilter.php index c36504c3fd..9acbdc670e 100644 --- a/src/Testing/UnitTestFilter.php +++ b/src/Testing/UnitTestFilter.php @@ -11,7 +11,7 @@ final class UnitTestFilter /** * @var string[]|class-string[] */ - private const array NON_UNIT_TEST_CASE_CLASSES = [ + private const NON_UNIT_TEST_CASE_CLASSES = [ KernelTestCase::class, 'Symfony\Component\Form\Test\TypeTestCase', ]; @@ -22,7 +22,11 @@ final class UnitTestFilter */ public function filter(array $testClassesToFilePaths): array { - return array_filter($testClassesToFilePaths, $this->isUnitTest(...), ARRAY_FILTER_USE_KEY); + return array_filter( + $testClassesToFilePaths, + fn (string $class): bool => $this->isUnitTest($class), + ARRAY_FILTER_USE_KEY + ); } private function isUnitTest(string $class): bool @@ -31,9 +35,14 @@ private function isUnitTest(string $class): bool return false; } - return array_all( - self::NON_UNIT_TEST_CASE_CLASSES, - fn (string $nonUnitTestCaseClass): bool => ! is_a($class, $nonUnitTestCaseClass, true) - ); + $found = true; + foreach (self::NON_UNIT_TEST_CASE_CLASSES as $nonUnitTestCaseClass) { + if (is_a($class, $nonUnitTestCaseClass, true)) { + $found = false; + break; + } + } + + return $found; } } diff --git a/src/Twig/TwigTemplateConstantExtractor.php b/src/Twig/TwigTemplateConstantExtractor.php index 0c00a50800..02d601ab01 100644 --- a/src/Twig/TwigTemplateConstantExtractor.php +++ b/src/Twig/TwigTemplateConstantExtractor.php @@ -47,7 +47,7 @@ private function findClassConstantFetchesInFile(string $filePath): array $constantMatchValue = $constantMatch['constant']; // global constant → skip - if (! str_contains((string) $constantMatchValue, '::')) { + if (strpos((string) $constantMatchValue, '::') === false) { continue; } diff --git a/src/ValueObject/ClassConstant.php b/src/ValueObject/ClassConstant.php index fbcadf9147..6dca27fa45 100644 --- a/src/ValueObject/ClassConstant.php +++ b/src/ValueObject/ClassConstant.php @@ -6,15 +6,28 @@ use Entropy\Validation\Assert; -final readonly class ClassConstant +final class ClassConstant { + /** + * @var class-string + * @readonly + */ + private string $className; + + /** + * @readonly + */ + private string $constantName; + /** * @param class-string $className */ public function __construct( - private string $className, - private string $constantName, + string $className, + string $constantName ) { + $this->className = $className; + $this->constantName = $constantName; Assert::notEmpty($constantName); Assert::notEmpty($className); } diff --git a/src/ValueObject/ClassConstantFetch/AbstractClassConstantFetch.php b/src/ValueObject/ClassConstantFetch/AbstractClassConstantFetch.php index ddeb503498..3712e63358 100644 --- a/src/ValueObject/ClassConstantFetch/AbstractClassConstantFetch.php +++ b/src/ValueObject/ClassConstantFetch/AbstractClassConstantFetch.php @@ -9,10 +9,20 @@ abstract class AbstractClassConstantFetch implements ClassConstantFetchInterface { - public function __construct( - private readonly string $className, - private readonly string $constantName - ) { + /** + * @readonly + */ + private string $className; + + /** + * @readonly + */ + private string $constantName; + + public function __construct(string $className, string $constantName) + { + $this->className = $className; + $this->constantName = $constantName; } public function getClassName(): string diff --git a/tests/EntityClassResolver/EntityClassResolverTest.php b/tests/EntityClassResolver/EntityClassResolverTest.php index c3b2afd244..e482b6bfbf 100644 --- a/tests/EntityClassResolver/EntityClassResolverTest.php +++ b/tests/EntityClassResolver/EntityClassResolverTest.php @@ -4,7 +4,6 @@ namespace Rector\SwissKnife\Tests\EntityClassResolver; -use Override; use Rector\SwissKnife\EntityClassResolver; use Rector\SwissKnife\Tests\AbstractTestCase; use Rector\SwissKnife\Tests\EntityClassResolver\Fixture\Anything\SomeAttributeDocument; @@ -15,7 +14,6 @@ final class EntityClassResolverTest extends AbstractTestCase { private EntityClassResolver $entityClassResolver; - #[Override] protected function setUp(): void { parent::setUp(); diff --git a/tests/Git/ConflictResolver/ConflictResolverTest.php b/tests/Git/ConflictResolver/ConflictResolverTest.php index 6fadf5ad0c..fab7e66b32 100644 --- a/tests/Git/ConflictResolver/ConflictResolverTest.php +++ b/tests/Git/ConflictResolver/ConflictResolverTest.php @@ -5,7 +5,6 @@ namespace Rector\SwissKnife\Tests\Git\ConflictResolver; use Iterator; -use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Rector\SwissKnife\Git\ConflictResolver; @@ -18,7 +17,9 @@ protected function setUp(): void $this->conflictResolver = new ConflictResolver(); } - #[DataProvider('provideData')] + /** + * @dataProvider provideData + */ public function test(string $filePath, int $expectedConflictCount): void { $unresolvedConflictCount = $this->conflictResolver->extractFromFileInfo($filePath); diff --git a/tests/NeedsFinalizeAnalyzer/NeedsFinalizeAnalyzerTest.php b/tests/NeedsFinalizeAnalyzer/NeedsFinalizeAnalyzerTest.php index 03d0f27981..3a6095c046 100644 --- a/tests/NeedsFinalizeAnalyzer/NeedsFinalizeAnalyzerTest.php +++ b/tests/NeedsFinalizeAnalyzer/NeedsFinalizeAnalyzerTest.php @@ -4,8 +4,6 @@ namespace Rector\SwissKnife\Tests\NeedsFinalizeAnalyzer; -use Override; -use PHPUnit\Framework\Attributes\DataProvider; use Rector\SwissKnife\Analyzer\NeedsFinalizeAnalyzer; use Rector\SwissKnife\PhpParser\CachedPhpParser; use Rector\SwissKnife\Tests\AbstractTestCase; @@ -14,18 +12,19 @@ final class NeedsFinalizeAnalyzerTest extends AbstractTestCase { private NeedsFinalizeAnalyzer $needsFinalizeAnalyzer; - #[Override] protected function setUp(): void { parent::setUp(); $this->needsFinalizeAnalyzer = new NeedsFinalizeAnalyzer( - excludedClasses: ['Rector\SwissKnife\Tests\NeedsFinalizeAnalyzer\Fixture\ExcludedClass'], - cachedPhpParser: $this->make(CachedPhpParser::class), + ['Rector\SwissKnife\Tests\NeedsFinalizeAnalyzer\Fixture\ExcludedClass'], + $this->make(CachedPhpParser::class), ); } - #[DataProvider('provideData')] + /** + * @dataProvider provideData + */ public function test(string $filePath, bool $expected): void { $this->assertSame($expected, $this->needsFinalizeAnalyzer->isNeeded($filePath)); diff --git a/tests/ParentClassResolver/ParentClassResolverTest.php b/tests/ParentClassResolver/ParentClassResolverTest.php index 91347734ea..541d7e285a 100644 --- a/tests/ParentClassResolver/ParentClassResolverTest.php +++ b/tests/ParentClassResolver/ParentClassResolverTest.php @@ -4,7 +4,6 @@ namespace Rector\SwissKnife\Tests\ParentClassResolver; -use Override; use Rector\SwissKnife\Finder\PhpFilesFinder; use Rector\SwissKnife\ParentClassResolver; use Rector\SwissKnife\Tests\AbstractTestCase; @@ -16,7 +15,6 @@ final class ParentClassResolverTest extends AbstractTestCase { private ParentClassResolver $parentClassResolver; - #[Override] protected function setUp(): void { parent::setUp(); diff --git a/tests/PhpParser/Finder/ClassConstFinder/ClassConstFinderTest.php b/tests/PhpParser/Finder/ClassConstFinder/ClassConstFinderTest.php index 0a17396df5..ff3f54eb23 100644 --- a/tests/PhpParser/Finder/ClassConstFinder/ClassConstFinderTest.php +++ b/tests/PhpParser/Finder/ClassConstFinder/ClassConstFinderTest.php @@ -5,8 +5,6 @@ namespace Rector\SwissKnife\Tests\PhpParser\Finder\ClassConstFinder; use Iterator; -use Override; -use PHPUnit\Framework\Attributes\DataProvider; use Rector\SwissKnife\PhpParser\Finder\ClassConstFinder; use Rector\SwissKnife\Tests\AbstractTestCase; @@ -14,7 +12,6 @@ final class ClassConstFinderTest extends AbstractTestCase { private ClassConstFinder $classConstFinder; - #[Override] protected function setUp(): void { parent::setUp(); @@ -22,7 +19,9 @@ protected function setUp(): void $this->classConstFinder = $this->make(ClassConstFinder::class); } - #[DataProvider('provideData')] + /** + * @dataProvider provideData + */ public function test(string $filePath, int $expectedClassConstantCount): void { $classConstants = $this->classConstFinder->find($filePath); diff --git a/tests/PhpParser/Finder/ClassConstantFetchFinder/ClassConstantFetchFinderTest.php b/tests/PhpParser/Finder/ClassConstantFetchFinder/ClassConstantFetchFinderTest.php index d50551ced9..15f193fa69 100644 --- a/tests/PhpParser/Finder/ClassConstantFetchFinder/ClassConstantFetchFinderTest.php +++ b/tests/PhpParser/Finder/ClassConstantFetchFinder/ClassConstantFetchFinderTest.php @@ -5,7 +5,6 @@ namespace Rector\SwissKnife\Tests\PhpParser\Finder\ClassConstantFetchFinder; use Entropy\Console\Output\ProgressBar; -use Override; use Rector\SwissKnife\Contract\ClassConstantFetchInterface; use Rector\SwissKnife\Finder\PhpFilesFinder; use Rector\SwissKnife\PhpParser\Finder\ClassConstantFetchFinder; @@ -18,7 +17,6 @@ final class ClassConstantFetchFinderTest extends AbstractTestCase { private ClassConstantFetchFinder $classConstantFetchFinder; - #[Override] protected function setUp(): void { parent::setUp(); diff --git a/tests/PhpParser/NodeVisitor/MockedClassNameCollectingNodeVisitor/MockedClassNameCollectingNodeVisitorTest.php b/tests/PhpParser/NodeVisitor/MockedClassNameCollectingNodeVisitor/MockedClassNameCollectingNodeVisitorTest.php index bd6ba62cc2..3eda1f1b84 100644 --- a/tests/PhpParser/NodeVisitor/MockedClassNameCollectingNodeVisitor/MockedClassNameCollectingNodeVisitorTest.php +++ b/tests/PhpParser/NodeVisitor/MockedClassNameCollectingNodeVisitor/MockedClassNameCollectingNodeVisitorTest.php @@ -7,7 +7,6 @@ use Iterator; use PhpParser\NodeTraverser; use PhpParser\ParserFactory; -use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Rector\SwissKnife\PhpParser\NodeVisitor\MockedClassNameCollectingNodeVisitor; @@ -15,22 +14,19 @@ final class MockedClassNameCollectingNodeVisitorTest extends TestCase { /** * @param string[] $expectedClassNames + * @dataProvider provideData */ - #[DataProvider('provideData')] public function test(string $filePath, array $expectedClassNames): void { $mockedClassNameCollectingNodeVisitor = new MockedClassNameCollectingNodeVisitor(); - $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor($mockedClassNameCollectingNodeVisitor); - $parser = new ParserFactory() + $parser = (new ParserFactory()) ->createForNewestSupportedVersion(); $stmts = $parser->parse((string) file_get_contents($filePath)); $this->assertNotNull($stmts); - $nodeTraverser->traverse($stmts); - $this->assertSame($expectedClassNames, $mockedClassNameCollectingNodeVisitor->getMockedClassNames()); } diff --git a/tests/Twig/TwigTemplateConstantExtractor/TwigTemplateConstantExtractorTest.php b/tests/Twig/TwigTemplateConstantExtractor/TwigTemplateConstantExtractorTest.php index b90d467116..ef5caf36e2 100644 --- a/tests/Twig/TwigTemplateConstantExtractor/TwigTemplateConstantExtractorTest.php +++ b/tests/Twig/TwigTemplateConstantExtractor/TwigTemplateConstantExtractorTest.php @@ -4,7 +4,6 @@ namespace Rector\SwissKnife\Tests\Twig\TwigTemplateConstantExtractor; -use Override; use Rector\SwissKnife\Contract\ClassConstantFetchInterface; use Rector\SwissKnife\Tests\AbstractTestCase; use Rector\SwissKnife\Tests\Twig\TwigTemplateConstantExtractor\Fixture\SomeTemplateUsedConstant; @@ -14,7 +13,6 @@ final class TwigTemplateConstantExtractorTest extends AbstractTestCase { private TwigTemplateConstantExtractor $twigTemplateConstantExtractor; - #[Override] protected function setUp(): void { parent::setUp(); diff --git a/tests/YAML/YamlConfigConstantExtractor/YamlConfigConstantExtractorTest.php b/tests/YAML/YamlConfigConstantExtractor/YamlConfigConstantExtractorTest.php index 50e6b9649e..e12b46691f 100644 --- a/tests/YAML/YamlConfigConstantExtractor/YamlConfigConstantExtractorTest.php +++ b/tests/YAML/YamlConfigConstantExtractor/YamlConfigConstantExtractorTest.php @@ -4,7 +4,6 @@ namespace Rector\SwissKnife\Tests\YAML\YamlConfigConstantExtractor; -use Override; use Rector\SwissKnife\Tests\AbstractTestCase; use Rector\SwissKnife\Tests\YAML\YamlConfigConstantExtractor\Fixture\SomeClassWithConstant; use Rector\SwissKnife\YAML\YamlConfigConstantExtractor; @@ -13,7 +12,6 @@ final class YamlConfigConstantExtractorTest extends AbstractTestCase { private YamlConfigConstantExtractor $yamlConfigConstantExtractor; - #[Override] protected function setUp(): void { parent::setUp(); From 29670643b27e9e4744965092c060ee268eb2b95b Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 1 Oct 2026 14:54:23 +0200 Subject: [PATCH 2/3] Install prod deps only for bare run matrix --- .github/workflows/bare_run.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bare_run.yaml b/.github/workflows/bare_run.yaml index 976231f8bf..e3a1fd9cd0 100644 --- a/.github/workflows/bare_run.yaml +++ b/.github/workflows/bare_run.yaml @@ -23,10 +23,11 @@ jobs: php-version: ${{ matrix.php_version }} coverage: none - - run: composer install --no-dev --ansi - # verify sources parse on the target PHP version - run: find bin src -name '*.php' -print0 | xargs -0 -n1 -P4 php -l + # install prod dependencies only; dev tooling targets 8.x and is irrelevant here + - run: composer install --no-dev --ignore-platform-reqs --ansi + # smoke-test the binary - run: bin/swiss-knife From 6e29731b9ef0de93f937d0dbe84baab769943eba Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 1 Oct 2026 15:04:35 +0200 Subject: [PATCH 3/3] Ignore .phpunit.result.cache --- .gitignore | 1 + .phpunit.result.cache | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 .phpunit.result.cache diff --git a/.gitignore b/.gitignore index f6b653c766..ce18cf5bc6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ composer.lock /vendor .phpunit.cache +.phpunit.result.cache tmp diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index 29ccaa2bc7..0000000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":1,"defects":[],"times":{"Rector\\SwissKnife\\Tests\\Command\\NamespaceToPSR4CommandTest::testNamespaceRootOptionIsKeptAsString":0.008,"Rector\\SwissKnife\\Tests\\Comments\\CommentedCodeAnalyzerTest::test":0,"Rector\\SwissKnife\\Tests\\DuplicatedCode\\CloneDetectorTest::testDetectsDuplicateAcrossFiles":0.001,"Rector\\SwissKnife\\Tests\\DuplicatedCode\\CloneDetectorTest::testDoesNotReportUniqueCode":0,"Rector\\SwissKnife\\Tests\\EntityClassResolver\\EntityClassResolverTest::test":0.017,"Rector\\SwissKnife\\Tests\\EntityClassResolver\\EntityClassResolverTest::testODMDocument":0.005,"Rector\\SwissKnife\\Tests\\Finder\\FilesFinderTest::testFindAll":0,"Rector\\SwissKnife\\Tests\\Finder\\FilesFinderTest::testExcludeByPath":0,"Rector\\SwissKnife\\Tests\\Finder\\FilesFinderTest::testExcludeByFnMatch":0,"Rector\\SwissKnife\\Tests\\Finder\\PhpFilesFinderTest::testExcludeByFnMatch":0.004,"Rector\\SwissKnife\\Tests\\Finder\\PhpFilesFinderTest::testExcludeByFnMatch2":0.004,"Rector\\SwissKnife\\Tests\\Git\\ConflictResolver\\ConflictResolverTest::test with data set #0":0,"Rector\\SwissKnife\\Tests\\Git\\ConflictResolver\\ConflictResolverTest::test with data set #1":0,"Rector\\SwissKnife\\Tests\\Git\\ConflictResolver\\ConflictResolverTest::test with data set #2":0,"Rector\\SwissKnife\\Tests\\Git\\ConflictResolver\\ConflictResolverTest::test with data set #3":0,"Rector\\SwissKnife\\Tests\\Lines\\AnalyserTest::test":0.008,"Rector\\SwissKnife\\Tests\\Lines\\FeatureCounter\\FeatureCounterAnalyzerTest::test":0.006,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #0":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #1":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #2":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #3":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #4":0.004,"Rector\\SwissKnife\\Tests\\NeedsFinalizeAnalyzer\\NeedsFinalizeAnalyzerTest::test with data set #5":0.004,"Rector\\SwissKnife\\Tests\\ParentClassResolver\\ParentClassResolverTest::test":0.006,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstFinder\\ClassConstFinderTest::test with data set #0":0.005,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstFinder\\ClassConstFinderTest::test with data set #1":0.004,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstFinder\\ClassConstFinderTest::test with data set #2":0.004,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstantFetchFinder\\ClassConstantFetchFinderTest::testSkipInterfaceTraitAndEnum":0.005,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstantFetchFinder\\ClassConstantFetchFinderTest::test":0.005,"Rector\\SwissKnife\\Tests\\PhpParser\\Finder\\ClassConstantFetchFinder\\ClassConstantFetchFinderTest::testParseError":0.005,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"createMock\"":0.001,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"createStub\"":0.001,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"createStubForIntersectionOfInterfaces\"":0,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"createConfiguredStub\"":0.001,"Rector\\SwissKnife\\Tests\\PhpParser\\NodeVisitor\\MockedClassNameCollectingNodeVisitor\\MockedClassNameCollectingNodeVisitorTest::test with data set \"unrelated method is not detected\"":0.001,"Rector\\SwissKnife\\Tests\\RobotLoader\\PhpClassLoaderTest::test":0,"Rector\\SwissKnife\\Tests\\RobotLoader\\PhpClassLoaderTest::testExcludedPathIsSkipped":0,"Rector\\SwissKnife\\Tests\\SmokeTestgen\\TestTemplateResolver\\TestTemplateResolverTest::test":0.004,"Rector\\SwissKnife\\Tests\\SmokeTestgen\\Utils\\TestPathResolverTest::test":0,"Rector\\SwissKnife\\Tests\\Testing\\UnitTestFilePathsFinder\\UnitTestFilePathsFinderTest::test":0.001,"Rector\\SwissKnife\\Tests\\Twig\\TwigTemplateConstantExtractor\\TwigTemplateConstantExtractorTest::test":0.004,"Rector\\SwissKnife\\Tests\\YAML\\YamlConfigConstantExtractor\\YamlConfigConstantExtractorTest::test":0.004}} \ No newline at end of file