diff --git a/phpstan.neon b/phpstan.neon index 39273cf7d1d0..e1532b47fecc 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -208,9 +208,7 @@ parameters: - '#Parameter \#1 \$typeNode of method Rector\\StaticTypeMapper\\StaticTypeMapper\:\:mapPHPStanPhpDocTypeNodeToPHPStanType\(\) expects PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode, PHPStan\\PhpDocParser\\Ast\\Node given#' - '#Parameter \#1 \$str of function preg_quote expects string, int\|string given#' - - '#Parameter \#2 \$propertyName of method Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\SingleMethodAssignedNodePropertyTypeInferer\:\:resolveAssignedNodeToProperty\(\) expects string, string\|null given#' - '#Parameter \#1 \$sprintfFuncCall of method Rector\\Core\\PhpParser\\NodeTransformer\:\:transformSprintfToArray\(\) expects PhpParser\\Node\\Expr\\FuncCall, PhpParser\\Node given#' - - '#Parameter \#1 \$nodes of method Rector\\CodeQuality\\Rector\\Array_\\CallableThisArrayToAnonymousFunctionRector\:\:hasClassMethodReturn\(\) expects array, array given#' - '#Parameter \#1 \$nodes of method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:find\(\) expects array\|PhpParser\\Node, array\|null given#' - '#PHPDoc tag @return with type iterable is not subtype of native type array#' - '#Method Rector\\SOLID\\Reflection\\ParentConstantReflectionResolver\:\:(.*?)\(\) should return ReflectionClassConstant\|null but returns ReflectionClassConstant\|false#' @@ -231,10 +229,6 @@ parameters: - '#Parameter \#1 \$node of method Rector\\PostRector\\Collector\\NodesToAddCollector\:\:wrapToExpression\(\) expects PhpParser\\Node\\Expr\|PhpParser\\Node\\Stmt, PhpParser\\Node given#' - # generics - - '#Method Rector\\BetterPhpDocParser\\AnnotationReader\\NodeAnnotationReader\:\:createClassReflectionFromNode\(\) return type with generic class ReflectionClass does not specify its types\: T#' - - '#Method Rector\\NodeCollector\\StaticAnalyzer\:\:hasStaticAnnotation\(\) has parameter \$reflectionClass with generic class ReflectionClass but does not specify its types\: T#' - # mixed - '#Property Rector\\Polyfill\\ValueObject\\BinaryToVersionCompareCondition\:\:\$expectedValue has no typehint specified#' # node finder @@ -291,13 +285,20 @@ parameters: count: 1 path: rules/php70/src/EregToPcreTransformer.php - - - message: "#^Cognitive complexity for \"Rector\\\\Php70\\\\EregToPcreTransformer\\:\\:(.*?)\" is (.*?), keep it under 9$#" - path: rules/php70/src/EregToPcreTransformer.php + - "#^Cognitive complexity for \"Rector\\\\Php70\\\\EregToPcreTransformer\\:\\:(.*?)\" is (.*?), keep it under 9$#" - '#Use explicit return value over magic &reference#' - '#Method Rector\\Order\\StmtOrder\:\:createOldToNewKeys\(\) should return array but returns array\|false#' - - '#In method "Rector\\Utils\\ProjectValidator\\Process\\ParallelTaskRunner\:\:evaluateRunningProcesses", caught "Throwable" must be rethrown\. Either catch a more specific exception or add a "throw" clause in the "catch" block to propagate the exception\. More info\: http\://bit\.ly/failloud#' + - '#In method "Rector\\Utils\\ProjectValidator\\Process\\ParallelTaskRunner\:\:(.*?)", caught "Throwable" must be rethrown\. Either catch a more specific exception or add a "throw" clause in the "catch" block to propagate the exception#' # weird + - '#Method (.*?) specified in iterable type Symfony\\Component\\Process\\Process#' + - '#Cannot cast PhpParser\\Node\\Expr\\Error\|PhpParser\\Node\\Identifier to string#' + - '#Class cognitive complexity for "DumpNodesCommand" is 103, keep it under 50#' + - '#Cognitive complexity for "Rector\\Utils\\DocumentationGenerator\\Command\\DumpNodesCommand\:\:execute\(\)" is \d+, keep it under 9#' + + # just for utils + - '#Class "Rector\\Utils\\DoctrineAnnotationParserSyncer\\Rector\\(.*?)" is missing @see annotation with test case class reference#' + + - '#Method Rector\\Utils\\DocumentationGenerator\\Node\\NodeClassProvider\:\:getNodeClasses\(\) should return array but returns array#' diff --git a/utils/doctrine-annotation-parser-syncer/src/ClassSyncerNodeTraverser.php b/utils/doctrine-annotation-parser-syncer/src/ClassSyncerNodeTraverser.php index 026fd664a9c4..d7b14032380e 100644 --- a/utils/doctrine-annotation-parser-syncer/src/ClassSyncerNodeTraverser.php +++ b/utils/doctrine-annotation-parser-syncer/src/ClassSyncerNodeTraverser.php @@ -6,6 +6,7 @@ use PhpParser\Node; use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor; use Rector\PostRector\Application\PostFileProcessor; use Rector\Utils\DoctrineAnnotationParserSyncer\Contract\Rector\ClassSyncerRectorInterface; @@ -22,6 +23,7 @@ final class ClassSyncerNodeTraverser extends NodeTraverser public function __construct(array $classSyncerRectors, PostFileProcessor $postFileProcessor) { foreach ($classSyncerRectors as $classSyncerRector) { + /** @var ClassSyncerRectorInterface&NodeVisitor $classSyncerRector */ $this->addVisitor($classSyncerRector); } diff --git a/utils/doctrine-annotation-parser-syncer/src/Rector/ClassMethod/LogIdentifierAndResolverValueInConstantClassMethodRector.php b/utils/doctrine-annotation-parser-syncer/src/Rector/ClassMethod/LogIdentifierAndResolverValueInConstantClassMethodRector.php index b749565e2155..9f01216c64bb 100644 --- a/utils/doctrine-annotation-parser-syncer/src/Rector/ClassMethod/LogIdentifierAndResolverValueInConstantClassMethodRector.php +++ b/utils/doctrine-annotation-parser-syncer/src/Rector/ClassMethod/LogIdentifierAndResolverValueInConstantClassMethodRector.php @@ -48,7 +48,7 @@ public function refactor(Node $node): ?Node $firstStmt = $node->stmts[0]; unset($node->stmts[0]); $assignExpression = $this->createAssignOriginalIdentifierExpression(); - $node->stmts = array_merge([$firstStmt], [$assignExpression], $node->stmts); + $node->stmts = array_merge([$firstStmt], [$assignExpression], (array) $node->stmts); // 2. record value in each return $this->traverseNodesWithCallable((array) $node->stmts, function (Node $node) { @@ -56,10 +56,15 @@ public function refactor(Node $node): ?Node return null; } + if ($node->expr === null) { + return null; + } + // assign resolved value to temporary variable $resolvedValueVariable = new Variable('resolvedValue'); $assign = new Assign($resolvedValueVariable, $node->expr); $assignExpression = new Expression($assign); + $this->addNodeBeforeNode($assignExpression, $node); // log the value in static call diff --git a/utils/documentation-generator/src/Command/DumpNodesCommand.php b/utils/documentation-generator/src/Command/DumpNodesCommand.php index c9f921d10099..a1c2afaa4647 100644 --- a/utils/documentation-generator/src/Command/DumpNodesCommand.php +++ b/utils/documentation-generator/src/Command/DumpNodesCommand.php @@ -5,6 +5,7 @@ namespace Rector\Utils\DocumentationGenerator\Command; use Nette\Utils\Strings; +use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Const_; use PhpParser\Node\Expr\ArrayDimFetch; @@ -194,6 +195,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $constructorReflection = $nodeClassReflection->getConstructor(); if ($constructorReflection->getNumberOfRequiredParameters() === 0) { + /** @var Node $node */ $node = $nodeClassReflection->newInstance(); // special case if ($node instanceof ArrowFunction) { diff --git a/utils/phpstan-attribute-type-syncer/src/NodeFactory/AttributeAwareClassFactoryFactory.php b/utils/phpstan-attribute-type-syncer/src/NodeFactory/AttributeAwareClassFactoryFactory.php index 76209b51564a..0e1f53b55c11 100644 --- a/utils/phpstan-attribute-type-syncer/src/NodeFactory/AttributeAwareClassFactoryFactory.php +++ b/utils/phpstan-attribute-type-syncer/src/NodeFactory/AttributeAwareClassFactoryFactory.php @@ -149,11 +149,12 @@ private function createClassReference(string $nodeClass): ClassConstFetch private function createIsAFuncCall(string $nodeClass): FuncCall { - return new FuncCall(new Name('is_a'), [ - new Variable(self::NODE), - $this->createClassReference($nodeClass), - new ConstFetch(new Name('true')), - ]); + $variable = new Variable(self::NODE); + $true = new ConstFetch(new Name('true')); + + $args = [new Arg($variable), new Arg($this->createClassReference($nodeClass)), new Arg($true)]; + + return new FuncCall(new Name('is_a'), $args); } private function completeNewArgs(New_ $new, string $phpDocParserNodeClass): void diff --git a/utils/phpstan-extensions/config/phpstan-extensions.neon b/utils/phpstan-extensions/config/phpstan-extensions.neon index d612a80d8bce..704aa8e1707d 100644 --- a/utils/phpstan-extensions/config/phpstan-extensions.neon +++ b/utils/phpstan-extensions/config/phpstan-extensions.neon @@ -42,3 +42,14 @@ services: # $phpDocInfo->getByType($1) => Type|null by $1 - { class: Rector\PHPStanExtensions\ReturnTypeExtension\PhpDocInfoGetByTypeReturnTypeExtension, tags: [phpstan.broker.dynamicMethodReturnTypeExtension] } + + # $builder->getNode() => Type + - + class: Rector\PHPStanExtensions\ReturnTypeExtension\Builder\NamespaceBuilderReturnTypeExtension + tags: [phpstan.broker.dynamicMethodReturnTypeExtension] + - + class: Rector\PHPStanExtensions\ReturnTypeExtension\Builder\ClassMethodBuilderReturnTypeExtension + tags: [phpstan.broker.dynamicMethodReturnTypeExtension] + - + class: Rector\PHPStanExtensions\ReturnTypeExtension\Builder\ClassBuilderReturnTypeExtension + tags: [phpstan.broker.dynamicMethodReturnTypeExtension] diff --git a/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/ClassBuilderReturnTypeExtension.php b/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/ClassBuilderReturnTypeExtension.php new file mode 100644 index 000000000000..c26b9a645f20 --- /dev/null +++ b/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/ClassBuilderReturnTypeExtension.php @@ -0,0 +1,35 @@ +getName() === 'getNode'; + } + + public function getTypeFromMethodCall( + MethodReflection $methodReflection, + MethodCall $methodCall, + Scope $scope + ): Type { + return new FullyQualifiedObjectType(Class_::class); + } +} diff --git a/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/ClassMethodBuilderReturnTypeExtension.php b/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/ClassMethodBuilderReturnTypeExtension.php new file mode 100644 index 000000000000..5d8c1d5be75f --- /dev/null +++ b/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/ClassMethodBuilderReturnTypeExtension.php @@ -0,0 +1,35 @@ +getName() === 'getNode'; + } + + public function getTypeFromMethodCall( + MethodReflection $methodReflection, + MethodCall $methodCall, + Scope $scope + ): Type { + return new FullyQualifiedObjectType(ClassMethod::class); + } +} diff --git a/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/NamespaceBuilderReturnTypeExtension.php b/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/NamespaceBuilderReturnTypeExtension.php new file mode 100644 index 000000000000..ebd2731ec737 --- /dev/null +++ b/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/NamespaceBuilderReturnTypeExtension.php @@ -0,0 +1,35 @@ +getName() === 'getNode'; + } + + public function getTypeFromMethodCall( + MethodReflection $methodReflection, + MethodCall $methodCall, + Scope $scope + ): Type { + return new FullyQualifiedObjectType(Namespace_::class); + } +} diff --git a/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/PropertyBuilderReturnTypeExtension.php b/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/PropertyBuilderReturnTypeExtension.php new file mode 100644 index 000000000000..8d260383335c --- /dev/null +++ b/utils/phpstan-extensions/src/ReturnTypeExtension/Builder/PropertyBuilderReturnTypeExtension.php @@ -0,0 +1,35 @@ +getName() === 'getNode'; + } + + public function getTypeFromMethodCall( + MethodReflection $methodReflection, + MethodCall $methodCall, + Scope $scope + ): Type { + return new FullyQualifiedObjectType(Property::class); + } +} diff --git a/utils/phpstan-extensions/src/ReturnTypeExtension/NameResolverReturnTypeExtension.php b/utils/phpstan-extensions/src/ReturnTypeExtension/NameResolverReturnTypeExtension.php index 3bb8e8014354..2dcc159010ac 100644 --- a/utils/phpstan-extensions/src/ReturnTypeExtension/NameResolverReturnTypeExtension.php +++ b/utils/phpstan-extensions/src/ReturnTypeExtension/NameResolverReturnTypeExtension.php @@ -4,14 +4,14 @@ namespace Rector\PHPStanExtensions\ReturnTypeExtension; -use PhpParser\NodeVisitor\NameResolver; use PHPStan\Reflection\MethodReflection; +use Rector\NodeNameResolver\NodeNameResolver; final class NameResolverReturnTypeExtension extends AbstractResolvedNameReturnTypeExtension { public function getClass(): string { - return NameResolver::class; + return NodeNameResolver::class; } public function isMethodSupported(MethodReflection $methodReflection): bool diff --git a/utils/phpstan-extensions/src/Rule/SeeAnnotationToTestRule.php b/utils/phpstan-extensions/src/Rule/SeeAnnotationToTestRule.php index 66b226776651..be666cdeee21 100644 --- a/utils/phpstan-extensions/src/Rule/SeeAnnotationToTestRule.php +++ b/utils/phpstan-extensions/src/Rule/SeeAnnotationToTestRule.php @@ -93,7 +93,6 @@ private function shouldSkipClassReflection(ClassReflection $classReflection): bo } foreach ($this->requiredSeeTypes as $requiredSeeType) { - dump($requiredSeeType); if ($classReflection->isSubclassOf($requiredSeeType)) { return false; } diff --git a/utils/phpstan-static-type-mapper-checker/src/Finder/PHPStanTypeClassFinder.php b/utils/phpstan-static-type-mapper-checker/src/Finder/PHPStanTypeClassFinder.php index 0aba84a090bd..ae716544bc06 100644 --- a/utils/phpstan-static-type-mapper-checker/src/Finder/PHPStanTypeClassFinder.php +++ b/utils/phpstan-static-type-mapper-checker/src/Finder/PHPStanTypeClassFinder.php @@ -23,6 +23,8 @@ public function find(): array $robotLoader->rebuild(); $classLikesToFilePaths = $robotLoader->getIndexedClasses(); + + /** @var class-string[] $classLikes */ $classLikes = array_keys($classLikesToFilePaths); return $this->filterClassesOnly($classLikes); diff --git a/utils/project-validator/src/CpuCoreCountResolver.php b/utils/project-validator/src/CpuCoreCountResolver.php index 5befb72813c0..bc77f4140e3a 100644 --- a/utils/project-validator/src/CpuCoreCountResolver.php +++ b/utils/project-validator/src/CpuCoreCountResolver.php @@ -19,14 +19,7 @@ final class CpuCoreCountResolver public function resolve(): int { if (defined('PHP_WINDOWS_VERSION_MAJOR')) { - $str = trim(shell_exec('wmic cpu get NumberOfCores 2>&1')); - - $matches = Strings::match($str, '#(\d+)#'); - if (! $matches) { - throw new CouldNotDeterminedCpuCoresException('wmic failed to get number of cpu cores on windows!'); - } - - return (int) $matches[1]; + return $this->resolveForWindows(); } $ret = @shell_exec('nproc'); @@ -47,4 +40,21 @@ public function resolve(): int throw new CouldNotDeterminedCpuCoresException('Failed to detect number of CPUs'); } + + private function resolveForWindows(): int + { + $numberOfCores = shell_exec('wmic cpu get NumberOfCores 2>&1'); + if ($numberOfCores === null) { + throw new CouldNotDeterminedCpuCoresException('wmic failed to get number of cpu cores on windows!'); + } + + $str = trim($numberOfCores); + + $matches = Strings::match($str, '#(\d+)#'); + if (! $matches) { + throw new CouldNotDeterminedCpuCoresException('wmic failed to get number of cpu cores on windows!'); + } + + return (int) $matches[1]; + } } diff --git a/utils/project-validator/src/Process/ParallelTaskRunner.php b/utils/project-validator/src/Process/ParallelTaskRunner.php index 42ead9be0b10..4ae2a6d6aa76 100644 --- a/utils/project-validator/src/Process/ParallelTaskRunner.php +++ b/utils/project-validator/src/Process/ParallelTaskRunner.php @@ -124,6 +124,7 @@ private function startProcess(int $maxProcesses, int $total): void if ($this->canStartAnotherProcess($maxProcesses)) { /** @var string $setName */ $setName = array_key_first($this->remainingTasks); + /** @var SetTask $task */ $task = array_shift($this->remainingTasks); try {