diff --git a/composer.json b/composer.json index 5b411cce9a..6af062fc7a 100644 --- a/composer.json +++ b/composer.json @@ -16,9 +16,9 @@ "clue/ndjson-react": "^1.3", "composer/pcre": "^3.4", "composer/xdebug-handler": "^3.0.5", - "entropy/entropy": "^0.4", + "entropy/entropy": "^0.4.6", "fidry/cpu-core-counter": "^1.3", - "friendsofphp/php-cs-fixer": "^3.95.5", + "friendsofphp/php-cs-fixer": "^3.95.10", "nette/utils": "^4.1", "react/child-process": "^0.6.7", "react/event-loop": "^1.6", @@ -37,7 +37,7 @@ "rector/jack": "^1.0", "rector/rector": "^2.4", "rector/type-perfect": "^2.1", - "symplify/phpstan-rules": "^14.11", + "symplify/phpstan-rules": "^14.12", "symplify/vendor-patches": "^11.5", "tomasvotruba/class-leak": "^2.1.7", "tomasvotruba/type-coverage": "^2.2", diff --git a/packages/coding-standard/src/Fixer/LineLength/LineLengthFixer.php b/packages/coding-standard/src/Fixer/LineLength/LineLengthFixer.php index b5423090b1..bdc211effb 100644 --- a/packages/coding-standard/src/Fixer/LineLength/LineLengthFixer.php +++ b/packages/coding-standard/src/Fixer/LineLength/LineLengthFixer.php @@ -26,6 +26,18 @@ /** * @see \Symplify\CodingStandard\Tests\Fixer\LineLength\LineLengthFixer\LineLengthFixerTest * @see \Symplify\CodingStandard\Tests\Fixer\LineLength\LineLengthFixer\ConfiguredLineLengthFixerTest + * + * @implements ConfigurableFixerInterface< + * array{ + * self::LINE_LENGTH?: int, + * self::BREAK_LONG_LINES?: bool, + * self::INLINE_SHORT_LINES?: bool + * }, array{ + * self::LINE_LENGTH: int, + * self::BREAK_LONG_LINES: bool, + * self::INLINE_SHORT_LINES: bool + * } + * > */ final class LineLengthFixer extends AbstractSymplifyFixer implements ConfigurableFixerInterface { diff --git a/phpstan.neon b/phpstan.neon index d36605a346..42dfedff55 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,15 +1,6 @@ parameters: level: 8 - # reportUnmatchedIgnoredErrors: false - - # requires exact closure types - checkMissingCallableSignature: true - - # symplify - see https://github.com/symplify/phpstan-rules#usage - symplify: - pathStrings: true - paths: - packages - src @@ -23,6 +14,10 @@ parameters: - '*/Source/*' - '*/Fixture/*' + # see https://github.com/symplify/phpstan-rules#usage + symplify: + pathStrings: true + # see https://github.com/tomasVotruba/unused-public unused_public: methods: true @@ -32,23 +27,20 @@ parameters: # see https://github.com/TomasVotruba/type-coverage type_coverage: return: 99 - param: 94.4 + param: 99 property: 99 bootstrapFiles: - tests/bootstrap.php - treatPhpDocTypesAsCertain: true + errorFormat: symplify + treatPhpDocTypesAsCertain: false ignoreErrors: - # set above - - - path: src/Parallel/Application/ParallelFileProcessor.php - message: '#Cannot call method (.*?)\(\) on Symplify\\EasyCodingStandard\\Parallel\\ValueObject\\ProcessPool\|null#' - + # @todo revisit: split return into typed file_diffs/coding_standard_errors buckets - '#Method Symplify\\EasyCodingStandard\\Application\\SingleFileProcessor\:\:processFilePath\(\) should return array\{file_diffs\?\: array, coding_standard_errors\?\: array\} but returns array<(.*?), array>#' - # false positive on custom config tets + # on purpose to override a config - message: '#Missing call to parent\:\:setUp\(\) method#' paths: @@ -57,43 +49,16 @@ parameters: - tests/Skipper/SkipCriteriaResolver/SkippedPathsResolver/SkippedPathsResolverTest.php - src/Testing/PHPUnit/AbstractCheckerTestCase.php - # testing instance of on purpose - - - message: '#Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf#' - path: tests/* - - # overly detailed - - '#PHPDoc tag @var with type string\|false is not subtype of native type non\-empty\-string\|false#' - - # array validation on purpose - - '#Call to static method Webmozart\\Assert\\Assert\:\:allString\(\) with (non-empty-array|list|array) will always evaluate to true#' - - '#Call to static method Webmozart\\Assert\\Assert\:\:allIsArray\(\) with array, array> will always evaluate to true#' - - # hack to autoload contants + # intentional: hack to autoload contants - '#Call to new PHP_CodeSniffer\\Util\\Tokens\(\) on a separate line has no effect#' - # php version condition - - - identifier: smaller.alwaysFalse - path: src/Configuration/ConfigInitializer.php - - # false positive - - - identifier: offsetAssign.dimType - path: src/Console/Output/JsonOutputFormatter.php - # coding-standard: runtime-defined PHP_CodeSniffer/php-cs-fixer token constants - '#Constant T_OPEN_CURLY_BRACKET|T_START_NOWDOC not found#' - # coding-standard: php-cs-fixer interface generics intentionally left unspecified - - '#Class (.*?) implements generic interface PhpCsFixer\\Fixer\\ConfigurableFixerInterface but does not specify its types\: TFixerInputConfig, TFixerComputedConfig#' - # coding-standard: intentional cross-version condition - message: '#Comparison operation ">\=" between int<\d+, \d+> and (.*?) is always true#' path: packages/coding-standard/src/TokenAnalyzer/DocblockRelatedParamNamesResolver.php - - # coding-standard: intentional null removal - - message: '#Parameter \#1 \$array \(array\) to function array_filter does not contain falsy values, the array will always stay the same#' - path: packages/coding-standard/src/TokenRunner/Traverser/TokenReverser.php + identifier: smaller.alwaysFalse + path: src/Configuration/ConfigInitializer.php diff --git a/src/Console/Output/JsonOutputFormatter.php b/src/Console/Output/JsonOutputFormatter.php index e5eeaf4dda..24f3df9a84 100644 --- a/src/Console/Output/JsonOutputFormatter.php +++ b/src/Console/Output/JsonOutputFormatter.php @@ -76,7 +76,7 @@ public function createJsonContent(ErrorAndDiffResult $errorAndDiffResult, bool $ } /** - * @return array{totals: array{errors: int, diffs: int}, files: string[]} + * @return array{totals: array{errors: int, diffs: int}, files: array>>>} */ private function createBaseErrorsJson(ErrorAndDiffResult $errorAndDiffResult): array { diff --git a/src/Parallel/Application/ParallelFileProcessor.php b/src/Parallel/Application/ParallelFileProcessor.php index 627fd104d3..6e6f76b8c2 100644 --- a/src/Parallel/Application/ParallelFileProcessor.php +++ b/src/Parallel/Application/ParallelFileProcessor.php @@ -34,14 +34,12 @@ * * https://github.com/phpstan/phpstan-src/commit/b84acd2e3eadf66189a64fdbc6dd18ff76323f67#diff-7f625777f1ce5384046df08abffd6c911cfbb1cfc8fcb2bdeaf78f337689e3e2R150 */ -final class ParallelFileProcessor +final readonly class ParallelFileProcessor { private const int SYSTEM_ERROR_LIMIT = 50; - private ProcessPool|null $processPool = null; - public function __construct( - private readonly WorkerCommandLineFactory $workerCommandLineFactory, + private WorkerCommandLineFactory $workerCommandLineFactory, ) { } @@ -70,24 +68,32 @@ public function check( $systemErrors = []; $tcpServer = new TcpServer('127.0.0.1:0', $streamSelectLoop); - $this->processPool = new ProcessPool($tcpServer); + $processPool = new ProcessPool($tcpServer); - $tcpServer->on(ReactEvent::CONNECTION, function (ConnectionInterface $connection) use (&$jobs): void { + $tcpServer->on(ReactEvent::CONNECTION, function (ConnectionInterface $connection) use ( + &$jobs, + $processPool + ): void { $inDecoder = new Decoder($connection, true, 512, 0, 4 * 1024 * 1024); $outEncoder = new Encoder($connection); - $inDecoder->on(ReactEvent::DATA, function (array $data) use (&$jobs, $inDecoder, $outEncoder): void { + $inDecoder->on(ReactEvent::DATA, function (array $data) use ( + &$jobs, + $inDecoder, + $outEncoder, + $processPool + ): void { $action = $data[ReactCommand::ACTION]; if ($action !== Action::HELLO) { return; } $processIdentifier = $data[Option::PARALLEL_IDENTIFIER]; - $parallelProcess = $this->processPool->getProcess($processIdentifier); + $parallelProcess = $processPool->getProcess($processIdentifier); $parallelProcess->bindConnection($inDecoder, $outEncoder); if ($jobs === []) { - $this->processPool->quitProcess($processIdentifier); + $processPool->quitProcess($processIdentifier); return; } @@ -112,13 +118,14 @@ public function check( $handleErrorCallable = function (Throwable $throwable) use ( &$systemErrors, &$systemErrorsCount, - &$reachedSystemErrorsCountLimit + &$reachedSystemErrorsCountLimit, + $processPool ): void { $systemErrors[] = new SystemError($throwable->getLine(), $throwable->getMessage(), $throwable->getFile()); ++$systemErrorsCount; $reachedSystemErrorsCountLimit = true; - $this->processPool->quitAll(); + $processPool->quitAll(); }; $timeoutInSeconds = SimpleParameterProvider::getIntParameter(Option::PARALLEL_TIMEOUT_IN_SECONDS); @@ -161,7 +168,8 @@ function (array $json) use ( $postFileCallback, &$systemErrorsCount, &$reachedInternalErrorsCountLimit, - $processIdentifier + $processIdentifier, + $processPool ): void { // decode arrays to objects foreach ($json[Bridge::SYSTEM_ERRORS] as $jsonError) { @@ -186,11 +194,11 @@ function (array $json) use ( $systemErrorsCount += $json[Bridge::SYSTEM_ERRORS_COUNT]; if ($systemErrorsCount >= self::SYSTEM_ERROR_LIMIT) { $reachedInternalErrorsCountLimit = true; - $this->processPool->quitAll(); + $processPool->quitAll(); } if ($jobs === []) { - $this->processPool->quitProcess($processIdentifier); + $processPool->quitProcess($processIdentifier); return; } @@ -205,8 +213,8 @@ function (array $json) use ( $handleErrorCallable, // 3. callable on exit - function ($exitCode, string $stdErr) use (&$systemErrors, $processIdentifier): void { - $this->processPool->tryQuitProcess($processIdentifier); + function ($exitCode, string $stdErr) use (&$systemErrors, $processIdentifier, $processPool): void { + $processPool->tryQuitProcess($processIdentifier); if ($exitCode === ExitCode::SUCCESS) { return; } @@ -219,7 +227,7 @@ function ($exitCode, string $stdErr) use (&$systemErrors, $processIdentifier): v } ); - $this->processPool->attachProcess($processIdentifier, $parallelProcess); + $processPool->attachProcess($processIdentifier, $parallelProcess); } $streamSelectLoop->run(); diff --git a/src/Skipper/FileSystem/FnMatchPathNormalizer.php b/src/Skipper/FileSystem/FnMatchPathNormalizer.php index 70029d8225..03398f9f82 100644 --- a/src/Skipper/FileSystem/FnMatchPathNormalizer.php +++ b/src/Skipper/FileSystem/FnMatchPathNormalizer.php @@ -16,7 +16,6 @@ public function normalizeForFnmatch(string $path): string } if (\str_contains($path, '..')) { - /** @var string|false $realPath */ $realPath = realpath($path); if ($realPath === false) { return ''; diff --git a/src/Skipper/RealpathMatcher.php b/src/Skipper/RealpathMatcher.php index d3674b96e0..d99d1ebc5c 100644 --- a/src/Skipper/RealpathMatcher.php +++ b/src/Skipper/RealpathMatcher.php @@ -8,13 +8,12 @@ final class RealpathMatcher { public function match(string $matchingPath, string $filePath): bool { - /** @var string|false $realPathMatchingPath */ + /** @var non-empty-string|false $realPathMatchingPath */ $realPathMatchingPath = realpath($matchingPath); if ($realPathMatchingPath === false) { return false; } - /** @var string|false $realpathFilePath */ $realpathFilePath = realpath($filePath); if ($realpathFilePath === false) { return false; diff --git a/tests/SniffRunner/File/FileFactoryTest.php b/tests/SniffRunner/File/FileFactoryTest.php index 2b26316d3b..ded13f22f4 100644 --- a/tests/SniffRunner/File/FileFactoryTest.php +++ b/tests/SniffRunner/File/FileFactoryTest.php @@ -4,7 +4,6 @@ namespace Symplify\EasyCodingStandard\Tests\SniffRunner\File; -use PHP_CodeSniffer\Files\File as PhpCodeSnifferFile; use PHP_CodeSniffer\Fixer; use Symplify\EasyCodingStandard\SniffRunner\File\FileFactory; use Symplify\EasyCodingStandard\SniffRunner\ValueObject\File; @@ -20,7 +19,6 @@ public function test(): void $file = $fileFactory->createFromFile($filePath); $this->assertInstanceOf(File::class, $file); - $this->assertInstanceOf(PhpCodeSnifferFile::class, $file); $this->assertInstanceOf(Fixer::class, $file->fixer); $this->assertSame($filePath, $file->getFilename()); }