diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml index 0f39e6904ce..00cc84e3733 100644 --- a/.github/workflows/code_analysis.yaml +++ b/.github/workflows/code_analysis.yaml @@ -23,7 +23,7 @@ jobs: - name: Validate Fixtures run: | - bin/rector validate-fixtures --ansi + bin/rector validate-fixture-content --ansi bin/rector validate-fixture-suffix --ansi - diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md index d0ce724cde9..de98d35aa22 100644 --- a/docs/rector_rules_overview.md +++ b/docs/rector_rules_overview.md @@ -5174,7 +5174,7 @@ Nextras/Form upgrade of addDatePicker method call to DateControl assign { $form = new Form(); - $form->addDatePicker('key', 'Label'); -+ $keyDateControl = $form['key'] = new \Nextras\FormComponents\Controls\DateControl('Label'); ++ $form['key'] = new \Nextras\FormComponents\Controls\DateControl('Label'); } } ``` diff --git a/ecs.php b/ecs.php index 8a571820927..b8491995be4 100644 --- a/ecs.php +++ b/ecs.php @@ -6,6 +6,7 @@ use PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\MethodDeclarationSniff; use PhpCsFixer\Fixer\Import\GlobalNamespaceImportFixer; use PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer; use PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer; +use PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer; use PhpCsFixer\Fixer\Phpdoc\PhpdocTypesFixer; use PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer; use PhpCsFixer\Fixer\Strict\StrictComparisonFixer; @@ -43,6 +44,11 @@ return static function (ContainerConfigurator $containerConfigurator): void { $services->set(LineLengthFixer::class); + $services->set(NoSuperfluousPhpdocTagsFixer::class) + ->call('configure', [[ + 'allow_mixed' => true, + ]]); + $parameters = $containerConfigurator->parameters(); $parameters->set(Option::PATHS, [ diff --git a/packages/attribute-aware-php-doc/src/Ast/PhpDoc/AttributeAwareParamTagValueNode.php b/packages/attribute-aware-php-doc/src/Ast/PhpDoc/AttributeAwareParamTagValueNode.php index 68d0daac88b..50d36a2413e 100644 --- a/packages/attribute-aware-php-doc/src/Ast/PhpDoc/AttributeAwareParamTagValueNode.php +++ b/packages/attribute-aware-php-doc/src/Ast/PhpDoc/AttributeAwareParamTagValueNode.php @@ -40,9 +40,16 @@ final class AttributeAwareParamTagValueNode extends ParamTagValueNode implements $variadic = $this->isVariadic ? '...' : ''; $reference = $this->isReference ? '&' : ''; - return trim( - sprintf('%s %s%s%s %s', $this->type, $variadic, $reference, $this->parameterName, $this->description) + $content = sprintf( + '%s %s%s%s %s', + $this->type, + $variadic, + $reference, + $this->parameterName, + $this->description ); + + return trim($content); } public function isReference(): bool diff --git a/packages/better-php-doc-parser/src/Attributes/Attribute/AttributeTrait.php b/packages/better-php-doc-parser/src/Attributes/Attribute/AttributeTrait.php index ecc5211b3e8..fd1b771737e 100644 --- a/packages/better-php-doc-parser/src/Attributes/Attribute/AttributeTrait.php +++ b/packages/better-php-doc-parser/src/Attributes/Attribute/AttributeTrait.php @@ -11,11 +11,17 @@ trait AttributeTrait */ private $attributes = []; + /** + * @return mixed|null + */ public function getAttribute(string $name) { return $this->attributes[$name] ?? null; } + /** + * @param mixed $value + */ public function setAttribute(string $name, $value): void { $this->attributes[$name] = $value; diff --git a/packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfo.php b/packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfo.php index 3d632a1a6d7..9bf5b746139 100644 --- a/packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfo.php +++ b/packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfo.php @@ -15,9 +15,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; -use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareParamTagValueNode; use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode; @@ -29,14 +27,13 @@ use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\SpacelessPhpDocTagNode; use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface; use Rector\BetterPhpDocParser\Contract\PhpDocNode\ShortNameAwareTagInterface; use Rector\BetterPhpDocParser\Contract\PhpDocNode\TypeAwareTagValueNodeInterface; +use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; use Rector\Core\Exception\NotImplementedException; use Rector\Core\Exception\ShouldNotHappenException; -use Rector\NodeTypeResolver\PHPStan\TypeComparator; use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface; use Rector\PHPStan\Type\FullyQualifiedObjectType; use Rector\PHPStan\Type\ShortenedObjectType; use Rector\StaticTypeMapper\StaticTypeMapper; -use Rector\TypeDeclaration\PhpDocParser\ParamPhpDocNodeFactory; /** * @see \Rector\BetterPhpDocParser\Tests\PhpDocInfo\PhpDocInfo\PhpDocInfoTest @@ -73,21 +70,16 @@ final class PhpDocInfo */ private $node; - /** - * @var TypeComparator - */ - private $typeComparator; - - /** - * @var ParamPhpDocNodeFactory - */ - private $paramPhpDocNodeFactory; - /** * @var bool */ private $isSingleLine = false; + /** + * @var PhpDocTypeChanger + */ + private $phpDocTypeChanger; + /** * @param mixed[] $tokens */ @@ -97,8 +89,7 @@ final class PhpDocInfo string $originalContent, StaticTypeMapper $staticTypeMapper, Node $node, - TypeComparator $typeComparator, - ParamPhpDocNodeFactory $paramPhpDocNodeFactory + PhpDocTypeChanger $phpDocTypeChanger ) { $this->phpDocNode = $attributeAwarePhpDocNode; $this->tokens = $tokens; @@ -106,8 +97,7 @@ final class PhpDocInfo $this->originalContent = $originalContent; $this->staticTypeMapper = $staticTypeMapper; $this->node = $node; - $this->typeComparator = $typeComparator; - $this->paramPhpDocNodeFactory = $paramPhpDocNodeFactory; + $this->phpDocTypeChanger = $phpDocTypeChanger; } public function getOriginalContent(): string @@ -190,6 +180,19 @@ final class PhpDocInfo return $paramTypes; } + public function getParamTagValueNodeByName(string $parameterName): ?ParamTagValueNode + { + foreach ($this->phpDocNode->getParamTagValues() as $paramTagValue) { + if ($paramTagValue->parameterName !== '$' . $parameterName) { + continue; + } + + return $paramTagValue; + } + + return null; + } + public function getVarType(): Type { return $this->getTypeOrMixed($this->getVarTagValue()); @@ -334,49 +337,12 @@ final class PhpDocInfo public function changeVarType(Type $newType): void { - // make sure the tags are not identical, e.g imported class vs FQN class - if ($this->typeComparator->areTypesEquals($this->getVarType(), $newType)) { - return; - } - - // prevent existing type override by mixed - if (! $this->getVarType() instanceof MixedType && $newType instanceof ConstantArrayType && $newType->getItemType() instanceof NeverType) { - return; - } - - // override existing type - $newPHPStanPhpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType); - - $currentVarTagValueNode = $this->getVarTagValue(); - if ($currentVarTagValueNode !== null) { - // only change type - $currentVarTagValueNode->type = $newPHPStanPhpDocType; - } else { - // add completely new one - $attributeAwareVarTagValueNode = new AttributeAwareVarTagValueNode($newPHPStanPhpDocType, '', ''); - $this->addTagValueNode($attributeAwareVarTagValueNode); - } + $this->phpDocTypeChanger->changeVarType($this, $newType); } public function changeReturnType(Type $newType): void { - // make sure the tags are not identical, e.g imported class vs FQN class - if ($this->typeComparator->areTypesEquals($this->getReturnType(), $newType)) { - return; - } - - // override existing type - $newPHPStanPhpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType); - - $currentReturnTagValueNode = $this->getReturnTagValue(); - if ($currentReturnTagValueNode !== null) { - // only change type - $currentReturnTagValueNode->type = $newPHPStanPhpDocType; - } else { - // add completely new one - $attributeAwareReturnTagValueNode = new AttributeAwareReturnTagValueNode($newPHPStanPhpDocType, ''); - $this->addTagValueNode($attributeAwareReturnTagValueNode); - } + $this->phpDocTypeChanger->changeReturnType($this, $newType); } public function addBareTag(string $tag): void @@ -406,33 +372,26 @@ final class PhpDocInfo public function changeParamType(Type $type, Param $param, string $paramName): void { - $paramTagValueNode = $this->getParamTagValueByName($paramName); - - $phpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($type); - - // override existing type - if ($paramTagValueNode !== null) { - $paramTagValueNode->type = $phpDocType; - return; - } - - $paramTagValueNode = $this->paramPhpDocNodeFactory->create($type, $param); - $this->addTagValueNode($paramTagValueNode); + $this->phpDocTypeChanger->changeParamType($this, $type, $param, $paramName); } /** - * @return string[] + * @return class-string[] */ public function getThrowsClassNames(): array { $throwsClasses = []; foreach ($this->getThrowsTypes() as $throwsType) { if ($throwsType instanceof ShortenedObjectType) { - $throwsClasses[] = $throwsType->getFullyQualifiedName(); + /** @var class-string $className */ + $className = $throwsType->getFullyQualifiedName(); + $throwsClasses[] = $className; } if ($throwsType instanceof FullyQualifiedObjectType) { - $throwsClasses[] = $throwsType->getClassName(); + /** @var class-string $className */ + $className = $throwsType->getClassName(); + $throwsClasses[] = $className; } } @@ -449,7 +408,14 @@ final class PhpDocInfo return $this->isSingleLine; } - private function getParamTagValueByName(string $name): ?AttributeAwareParamTagValueNode + public function getReturnTagValue(): ?AttributeAwareReturnTagValueNode + { + /** @var AttributeAwareReturnTagValueNode[] $returnTagValueNodes */ + $returnTagValueNodes = $this->phpDocNode->getReturnTagValues(); + return $returnTagValueNodes[0] ?? null; + } + + public function getParamTagValueByName(string $name): ?AttributeAwareParamTagValueNode { /** @var AttributeAwareParamTagValueNode $paramTagValue */ foreach ($this->phpDocNode->getParamTagValues() as $paramTagValue) { @@ -461,7 +427,7 @@ final class PhpDocInfo return null; } - private function getTypeOrMixed(?PhpDocTagValueNode $phpDocTagValueNode) + private function getTypeOrMixed(?PhpDocTagValueNode $phpDocTagValueNode): Type { if ($phpDocTagValueNode === null) { return new MixedType(); @@ -470,11 +436,6 @@ final class PhpDocInfo return $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType($phpDocTagValueNode, $this->node); } - private function getReturnTagValue(): ?AttributeAwareReturnTagValueNode - { - return $this->phpDocNode->getReturnTagValues()[0] ?? null; - } - private function ensureTypeIsTagValueNode(string $type, string $location): void { if (is_a($type, PhpDocTagValueNode::class, true)) { diff --git a/packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfoFactory.php b/packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfoFactory.php index 7bc23f98375..15f69595326 100644 --- a/packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfoFactory.php +++ b/packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfoFactory.php @@ -13,12 +13,11 @@ use Rector\BetterPhpDocParser\Attributes\Ast\AttributeAwareNodeFactory; use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute; use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface; use Rector\BetterPhpDocParser\Contract\PhpDocNodeFactoryInterface; +use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject; use Rector\Core\Configuration\CurrentNodeProvider; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\NodeTypeResolver\PHPStan\TypeComparator; use Rector\StaticTypeMapper\StaticTypeMapper; -use Rector\TypeDeclaration\PhpDocParser\ParamPhpDocNodeFactory; final class PhpDocInfoFactory { @@ -42,37 +41,30 @@ final class PhpDocInfoFactory */ private $staticTypeMapper; - /** - * @var TypeComparator - */ - private $typeComparator; - /** * @var AttributeAwareNodeFactory */ private $attributeAwareNodeFactory; /** - * @var ParamPhpDocNodeFactory + * @var PhpDocTypeChanger */ - private $paramPhpDocNodeFactory; + private $phpDocTypeChanger; public function __construct( AttributeAwareNodeFactory $attributeAwareNodeFactory, CurrentNodeProvider $currentNodeProvider, Lexer $lexer, - ParamPhpDocNodeFactory $paramPhpDocNodeFactory, PhpDocParser $phpDocParser, StaticTypeMapper $staticTypeMapper, - TypeComparator $typeComparator + PhpDocTypeChanger $phpDocTypeChanger ) { $this->phpDocParser = $phpDocParser; $this->lexer = $lexer; $this->currentNodeProvider = $currentNodeProvider; $this->staticTypeMapper = $staticTypeMapper; - $this->typeComparator = $typeComparator; $this->attributeAwareNodeFactory = $attributeAwareNodeFactory; - $this->paramPhpDocNodeFactory = $paramPhpDocNodeFactory; + $this->phpDocTypeChanger = $phpDocTypeChanger; } public function createFromNode(Node $node): ?PhpDocInfo @@ -155,8 +147,7 @@ final class PhpDocInfoFactory $content, $this->staticTypeMapper, $node, - $this->typeComparator, - $this->paramPhpDocNodeFactory + $this->phpDocTypeChanger ); $node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo); diff --git a/packages/better-php-doc-parser/src/PhpDocManipulator/PhpDocTypeChanger.php b/packages/better-php-doc-parser/src/PhpDocManipulator/PhpDocTypeChanger.php new file mode 100644 index 00000000000..1a5049a2e42 --- /dev/null +++ b/packages/better-php-doc-parser/src/PhpDocManipulator/PhpDocTypeChanger.php @@ -0,0 +1,109 @@ +typeComparator = $typeComparator; + $this->staticTypeMapper = $staticTypeMapper; + $this->paramPhpDocNodeFactory = $paramPhpDocNodeFactory; + } + + public function changeVarType(PhpDocInfo $phpDocInfo, Type $newType): void + { + // make sure the tags are not identical, e.g imported class vs FQN class + if ($this->typeComparator->areTypesEquals($phpDocInfo->getVarType(), $newType)) { + return; + } + + // prevent existing type override by mixed + if (! $phpDocInfo->getVarType() instanceof MixedType && $newType instanceof ConstantArrayType && $newType->getItemType() instanceof NeverType) { + return; + } + + // override existing type + $newPHPStanPhpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType); + + $currentVarTagValueNode = $phpDocInfo->getVarTagValue(); + if ($currentVarTagValueNode !== null) { + // only change type + $currentVarTagValueNode->type = $newPHPStanPhpDocType; + } else { + // add completely new one + $attributeAwareVarTagValueNode = new AttributeAwareVarTagValueNode($newPHPStanPhpDocType, '', ''); + $phpDocInfo->addTagValueNode($attributeAwareVarTagValueNode); + } + } + + public function changeReturnType(PhpDocInfo $phpDocInfo, Type $newType): void + { + // make sure the tags are not identical, e.g imported class vs FQN class + if ($this->typeComparator->areTypesEquals($phpDocInfo->getReturnType(), $newType)) { + return; + } + + // override existing type + $newPHPStanPhpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType); + + $currentReturnTagValueNode = $phpDocInfo->getReturnTagValue(); + if ($currentReturnTagValueNode !== null) { + // only change type + $currentReturnTagValueNode->type = $newPHPStanPhpDocType; + } else { + // add completely new one + $attributeAwareReturnTagValueNode = new AttributeAwareReturnTagValueNode($newPHPStanPhpDocType, ''); + $phpDocInfo->addTagValueNode($attributeAwareReturnTagValueNode); + } + } + + public function changeParamType(PhpDocInfo $phpDocInfo, Type $type, Param $param, string $paramName): void + { + $paramTagValueNode = $phpDocInfo->getParamTagValueByName($paramName); + + $phpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($type); + + // override existing type + if ($paramTagValueNode !== null) { + $paramTagValueNode->type = $phpDocType; + return; + } + + $paramTagValueNode = $this->paramPhpDocNodeFactory->create($type, $param); + + $phpDocInfo->addTagValueNode($paramTagValueNode); + } +} diff --git a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php index dab9a091609..cb62a0194db 100644 --- a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php +++ b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php @@ -180,7 +180,7 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD return implode(', ', $itemsAsStrings); } - private function correctArraySingleItemPrint($value, string $arrayItemAsString): string + private function correctArraySingleItemPrint(array $value, string $arrayItemAsString): string { if (count($value) !== 1) { return $arrayItemAsString; diff --git a/packages/better-php-doc-parser/src/PhpDocNode/PrintTagValueNodeTrait.php b/packages/better-php-doc-parser/src/PhpDocNode/PrintTagValueNodeTrait.php index 6b3b8c94bdd..526110fa92c 100644 --- a/packages/better-php-doc-parser/src/PhpDocNode/PrintTagValueNodeTrait.php +++ b/packages/better-php-doc-parser/src/PhpDocNode/PrintTagValueNodeTrait.php @@ -61,7 +61,10 @@ trait PrintTagValueNodeTrait return $items; } - private function shouldSkipFromExplicitKey($contentItem, $key): bool + /** + * @param mixed $contentItem + */ + private function shouldSkipFromExplicitKey($contentItem, string $key): bool { if (is_array($contentItem)) { return true; diff --git a/packages/better-php-doc-parser/src/Printer/EmptyPhpDocDetector.php b/packages/better-php-doc-parser/src/Printer/EmptyPhpDocDetector.php new file mode 100644 index 00000000000..476de7538a1 --- /dev/null +++ b/packages/better-php-doc-parser/src/Printer/EmptyPhpDocDetector.php @@ -0,0 +1,30 @@ +children) === 0) { + return true; + } + + foreach ($phpDocNode->children as $phpDocChildNode) { + if ($phpDocChildNode instanceof PhpDocTextNode) { + if ($phpDocChildNode->text !== '') { + return false; + } + } else { + return false; + } + } + + return true; + } +} diff --git a/packages/better-php-doc-parser/src/Printer/PhpDocInfoPrinter.php b/packages/better-php-doc-parser/src/Printer/PhpDocInfoPrinter.php index 669d45890fd..aaa851c978c 100644 --- a/packages/better-php-doc-parser/src/Printer/PhpDocInfoPrinter.php +++ b/packages/better-php-doc-parser/src/Printer/PhpDocInfoPrinter.php @@ -6,9 +6,12 @@ namespace Rector\BetterPhpDocParser\Printer; use Nette\Utils\Strings; use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode; +use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode; use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode; +use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; +use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode; +use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; use PHPStan\PhpDocParser\Lexer\Lexer; use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode; use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocTagNode; @@ -73,14 +76,21 @@ final class PhpDocInfoPrinter */ private $spacePatternFactory; + /** + * @var EmptyPhpDocDetector + */ + private $emptyPhpDocDetector; + public function __construct( MultilineSpaceFormatPreserver $multilineSpaceFormatPreserver, OriginalSpacingRestorer $originalSpacingRestorer, - SpacePatternFactory $spacePatternFactory + SpacePatternFactory $spacePatternFactory, + EmptyPhpDocDetector $emptyPhpDocDetector ) { $this->originalSpacingRestorer = $originalSpacingRestorer; $this->multilineSpaceFormatPreserver = $multilineSpaceFormatPreserver; $this->spacePatternFactory = $spacePatternFactory; + $this->emptyPhpDocDetector = $emptyPhpDocDetector; } /** @@ -123,7 +133,7 @@ final class PhpDocInfoPrinter private function printPhpDocNode(AttributeAwarePhpDocNode $attributeAwarePhpDocNode): string { // no nodes were, so empty doc - if ($this->isPhpDocNodeEmpty($attributeAwarePhpDocNode)) { + if ($this->emptyPhpDocDetector->isPhpDocNodeEmpty($attributeAwarePhpDocNode)) { return ''; } @@ -158,25 +168,6 @@ final class PhpDocInfoPrinter return Strings::replace($phpDocString, '#([^*])\*[ \t]+$#sm', '$1*'); } - private function isPhpDocNodeEmpty(PhpDocNode $phpDocNode): bool - { - if (count($phpDocNode->children) === 0) { - return true; - } - - foreach ($phpDocNode->children as $phpDocChildNode) { - if ($phpDocChildNode instanceof PhpDocTextNode) { - if ($phpDocChildNode->text !== '') { - return false; - } - } else { - return false; - } - } - - return true; - } - private function printNode( AttributeAwareNodeInterface $attributeAwareNode, ?StartEndValueObject $startEndValueObject = null, @@ -277,7 +268,6 @@ final class PhpDocInfoPrinter } $nodeOutput = $this->printNode($phpDocTagNodeValue, $startEndValueObject); - $tagSpaceSeparator = $this->resolveTagSpaceSeparator($phpDocTagNode); // space is handled by $tagSpaceSeparator @@ -372,8 +362,15 @@ final class PhpDocInfoPrinter $spacePattern = $this->spacePatternFactory->createSpacePattern($phpDocTagNode); $matches = Strings::match($originalContent, $spacePattern); + if (isset($matches['space'])) { + return $matches['space']; + } - return $matches['space'] ?? ''; + if ($this->isCommonTag($phpDocTagNode)) { + return ' '; + } + + return ''; } private function hasDescription(AttributeAwarePhpDocTagNode $attributeAwarePhpDocTagNode): bool @@ -399,4 +396,21 @@ final class PhpDocInfoPrinter return implode($implodeChar, $content); } + + private function isCommonTag(PhpDocTagNode $phpDocTagNode): bool + { + if ($phpDocTagNode->value instanceof ParamTagValueNode) { + return true; + } + + if ($phpDocTagNode->value instanceof VarTagValueNode) { + return true; + } + + if ($phpDocTagNode->value instanceof ReturnTagValueNode) { + return true; + } + + return $phpDocTagNode->value instanceof ThrowsTagValueNode; + } } diff --git a/packages/caching/src/ChangedFilesDetector.php b/packages/caching/src/ChangedFilesDetector.php index eb2b44d076c..c9a5661b266 100644 --- a/packages/caching/src/ChangedFilesDetector.php +++ b/packages/caching/src/ChangedFilesDetector.php @@ -118,6 +118,9 @@ final class ChangedFilesDetector return hash_file('sha1', $smartFileInfo->getRealPath()); } + /** + * @param mixed $value + */ private function saveItemWithValue(string $key, $value): void { $cacheItem = $this->tagAwareAdapter->getItem($key); diff --git a/packages/doctrine-annotation-generated/src/DataCollector/ResolvedConstantStaticCollector.php b/packages/doctrine-annotation-generated/src/DataCollector/ResolvedConstantStaticCollector.php index 2f7f594dc22..1e6a8cf1068 100644 --- a/packages/doctrine-annotation-generated/src/DataCollector/ResolvedConstantStaticCollector.php +++ b/packages/doctrine-annotation-generated/src/DataCollector/ResolvedConstantStaticCollector.php @@ -11,6 +11,9 @@ final class ResolvedConstantStaticCollector */ private static $valuesByIdentifier = []; + /** + * @param mixed $value + */ public static function collect(string $identifier, $value): void { // skip PHP values diff --git a/packages/doctrine-annotation-generated/src/PhpDocNode/ConstantReferenceIdentifierRestorer.php b/packages/doctrine-annotation-generated/src/PhpDocNode/ConstantReferenceIdentifierRestorer.php index e7aaf6af9e8..b51f9ba4d14 100644 --- a/packages/doctrine-annotation-generated/src/PhpDocNode/ConstantReferenceIdentifierRestorer.php +++ b/packages/doctrine-annotation-generated/src/PhpDocNode/ConstantReferenceIdentifierRestorer.php @@ -75,6 +75,7 @@ final class ConstantReferenceIdentifierRestorer } /** + * @param mixed $value * @return mixed|null */ private function matchIdentifierBasedOnResolverValue(array $identifierToResolvedValues, $value) diff --git a/packages/dynamic-type-analysis/src/Probe/TypeStaticProbe.php b/packages/dynamic-type-analysis/src/Probe/TypeStaticProbe.php index 7572ac711dd..3e35cf8303e 100644 --- a/packages/dynamic-type-analysis/src/Probe/TypeStaticProbe.php +++ b/packages/dynamic-type-analysis/src/Probe/TypeStaticProbe.php @@ -22,6 +22,9 @@ final class TypeStaticProbe */ private static $probeStorage; + /** + * @param mixed $value + */ public static function recordArgumentType($value, string $method, int $argumentPosition): void { $probeItem = self::createProbeItem($value, $method, $argumentPosition); @@ -29,6 +32,9 @@ final class TypeStaticProbe self::recordProbeItem($probeItem); } + /** + * @param mixed $value + */ public static function createProbeItem($value, string $method, int $argumentPosition): string { $type = self::resolveValueTypeToString($value); @@ -37,6 +43,9 @@ final class TypeStaticProbe return implode(';', $data) . PHP_EOL; } + /** + * @param object|mixed[]|mixed $value + */ public static function resolveValueTypeToString($value): string { if (is_object($value)) { diff --git a/packages/dynamic-type-analysis/tests/Probe/TypeStaticProbeTest.php b/packages/dynamic-type-analysis/tests/Probe/TypeStaticProbeTest.php index 6fc5133c84e..75e88d37215 100644 --- a/packages/dynamic-type-analysis/tests/Probe/TypeStaticProbeTest.php +++ b/packages/dynamic-type-analysis/tests/Probe/TypeStaticProbeTest.php @@ -13,6 +13,7 @@ final class TypeStaticProbeTest extends TestCase { /** * @dataProvider provideData() + * @param mixed $value */ public function test($value, string $methodName, int $argumentPosition, string $expectedProbeItem): void { @@ -26,6 +27,7 @@ final class TypeStaticProbeTest extends TestCase } /** + * @param mixed $value * @dataProvider provideDataResolveValueTypeToString() */ public function testResolveValueTypeToString($value, string $expectedValueTypeString): void diff --git a/packages/node-type-resolver/src/NodeTypeResolver.php b/packages/node-type-resolver/src/NodeTypeResolver.php index ce4738e59f0..e59e31b3314 100644 --- a/packages/node-type-resolver/src/NodeTypeResolver.php +++ b/packages/node-type-resolver/src/NodeTypeResolver.php @@ -258,6 +258,9 @@ final class NodeTypeResolver } } + /** + * @param ObjectType|string|mixed $requiredType + */ private function ensureRequiredTypeIsStringOrObjectType($requiredType, string $location): void { if (is_string($requiredType)) { diff --git a/packages/node-type-resolver/src/PhpDoc/PhpDocTypeRenamer.php b/packages/node-type-resolver/src/PhpDoc/PhpDocTypeRenamer.php index c51771adff9..af3a3d131d7 100644 --- a/packages/node-type-resolver/src/PhpDoc/PhpDocTypeRenamer.php +++ b/packages/node-type-resolver/src/PhpDoc/PhpDocTypeRenamer.php @@ -65,11 +65,14 @@ final class PhpDocTypeRenamer }); } + /** + * @param string[] $excludedClasses + */ private function shouldSkip( PhpDocParserNode $phpDocParserNode, Node $phpParserNode, string $namespacePrefix, - $excludedClasses + array $excludedClasses ): bool { if (! $phpDocParserNode instanceof IdentifierTypeNode) { return true; diff --git a/packages/polyfill/src/ConditionEvaluator.php b/packages/polyfill/src/ConditionEvaluator.php index 2bc2ded4fad..aa8c5339f1c 100644 --- a/packages/polyfill/src/ConditionEvaluator.php +++ b/packages/polyfill/src/ConditionEvaluator.php @@ -31,6 +31,9 @@ final class ConditionEvaluator return null; } + /** + * @return bool|int + */ private function evaluateVersionCompareCondition(VersionCompareCondition $versionCompareCondition) { $compareSign = $versionCompareCondition->getCompareSign(); diff --git a/packages/polyfill/src/ConditionResolver.php b/packages/polyfill/src/ConditionResolver.php index 264243c6b6f..35a6de90063 100644 --- a/packages/polyfill/src/ConditionResolver.php +++ b/packages/polyfill/src/ConditionResolver.php @@ -61,11 +61,7 @@ final class ConditionResolver if ($this->isVersionCompareFuncCall($expr->left)) { /** @var FuncCall $funcCall */ $funcCall = $expr->left; - - $versionCompareCondition = $this->resolveVersionCompareConditionForFuncCall($funcCall); - $expectedValue = $this->valueResolver->getValue($expr->right); - - return new BinaryToVersionCompareCondition($versionCompareCondition, $binaryClass, $expectedValue); + return $this->resolveFuncCall($funcCall, $expr->right, $binaryClass); } if ($this->isVersionCompareFuncCall($expr->right)) { @@ -73,6 +69,10 @@ final class ConditionResolver $funcCall = $expr->right; $versionCompareCondition = $this->resolveVersionCompareConditionForFuncCall($funcCall); + if ($versionCompareCondition === null) { + return null; + } + $expectedValue = $this->valueResolver->getValue($expr->left); return new BinaryToVersionCompareCondition($versionCompareCondition, $binaryClass, $expectedValue); @@ -90,7 +90,7 @@ final class ConditionResolver return $this->nodeNameResolver->isName($node, 'version_compare'); } - private function resolveVersionCompareConditionForFuncCall(FuncCall $funcCall) + private function resolveVersionCompareConditionForFuncCall(FuncCall $funcCall): ?VersionCompareCondition { $firstVersion = $this->resolveArgumentValue($funcCall, 0); if ($firstVersion === null) { @@ -121,4 +121,19 @@ final class ConditionResolver return $version; } + + private function resolveFuncCall( + FuncCall $funcCall, + Expr $expr, + string $binaryClass + ): ?BinaryToVersionCompareCondition { + $versionCompareCondition = $this->resolveVersionCompareConditionForFuncCall($funcCall); + if ($versionCompareCondition === null) { + return null; + } + + $expectedValue = $this->valueResolver->getValue($expr); + + return new BinaryToVersionCompareCondition($versionCompareCondition, $binaryClass, $expectedValue); + } } diff --git a/packages/polyfill/src/ValueObject/BinaryToVersionCompareCondition.php b/packages/polyfill/src/ValueObject/BinaryToVersionCompareCondition.php index aaa6b2fef97..0acb8b12982 100644 --- a/packages/polyfill/src/ValueObject/BinaryToVersionCompareCondition.php +++ b/packages/polyfill/src/ValueObject/BinaryToVersionCompareCondition.php @@ -8,6 +8,9 @@ use Rector\Polyfill\Contract\ConditionInterface; final class BinaryToVersionCompareCondition implements ConditionInterface { + /** + * @var mixed + */ private $expectedValue; /** @@ -20,6 +23,9 @@ final class BinaryToVersionCompareCondition implements ConditionInterface */ private $versionCompareCondition; + /** + * @param mixed $expectedValue + */ public function __construct( VersionCompareCondition $versionCompareCondition, string $binaryClass, @@ -40,6 +46,9 @@ final class BinaryToVersionCompareCondition implements ConditionInterface return $this->binaryClass; } + /** + * @return mixed + */ public function getExpectedValue() { return $this->expectedValue; diff --git a/packages/post-rector/src/Collector/NodesToReplaceCollector.php b/packages/post-rector/src/Collector/NodesToReplaceCollector.php index 150b22f87ca..cbad732a3b4 100644 --- a/packages/post-rector/src/Collector/NodesToReplaceCollector.php +++ b/packages/post-rector/src/Collector/NodesToReplaceCollector.php @@ -24,7 +24,10 @@ final class NodesToReplaceCollector implements NodeCollectorInterface return count($this->nodesToReplace) > 0; } - public function getNodes() + /** + * @return Node[][] + */ + public function getNodes(): array { return $this->nodesToReplace; } diff --git a/packages/rector-generator/src/Guard/OverrideGuard.php b/packages/rector-generator/src/Guard/OverrideGuard.php index 40ee7b2d671..698f6d93c3a 100644 --- a/packages/rector-generator/src/Guard/OverrideGuard.php +++ b/packages/rector-generator/src/Guard/OverrideGuard.php @@ -34,7 +34,7 @@ final class OverrideGuard array $templateFileInfos, array $templateVariables, Configuration $configuration - ) { + ): bool { foreach ($templateFileInfos as $templateFileInfo) { if (! $this->doesFileInfoAlreadyExist($templateVariables, $configuration, $templateFileInfo)) { continue; diff --git a/phpstan.neon b/phpstan.neon index d6929ac6943..f92144edee3 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -83,14 +83,6 @@ parameters: ignoreErrors: # false positive - - - message: '#Class with base \"[a-zA-Z0-9\\_]+\" name is already used in#' - paths: - - src/Console/Application.php - - src/PhpParser/Parser/Parser.php - - # false positive -# - '#Call to function method_exists\(\) with string and (.*?) will always evaluate to false#' - '#PHPDoc tag \@param for parameter \$node with type float is incompatible with native type PhpParser\\Node#' # misuse of interface and class @@ -187,9 +179,6 @@ parameters: - '#Method Rector\\NodeTypeResolver\\PHPStan\\Type\\TypeFactory\:\:createUnionOrSingleType\(\) should return PHPStan\\Type\\MixedType\|PHPStan\\Type\\UnionType but returns PHPStan\\Type\\Type#' - #phpstan seems to be missing the entire docblock, though it's there - - '#.*keepLivingCodeFromExpr.*#' - # test - '#Class Rector\\DynamicTypeAnalysis\\Tests\\Rector\\ClassMethod\\AddArgumentTypeWithProbeDataRector\\Fixture\\SomeClass not found#' @@ -201,14 +190,8 @@ parameters: - '#Class "Rector\\Utils\\(.*?)" is missing @see annotation with test case class reference#' # mixed - - '#in iterable type Iterator#' - - '#with no typehint specified#' - - '#return type has no value type specified in iterable type array#' - - '#has no return typehint#' - '#Offset int\|string\|null does not exist on array\|null#' - '#class-string\|T of object#' - - '#with no value type specified in iterable type array#' - - '#type specified in iterable type (array|iterable)#' # known values - '#Offset 0 does not exist on array\|null#' @@ -228,7 +211,6 @@ parameters: - '#Method (.*?) returns bool type, so the name should start with is/has/was#' # known value - - "#^Parameter \\#1 \\$variable of class Rector\\\\Php70\\\\ValueObject\\\\VariableAssignPair constructor expects PhpParser\\\\Node\\\\Expr\\\\ArrayDimFetch\\|PhpParser\\\\Node\\\\Expr\\\\PropertyFetch\\|PhpParser\\\\Node\\\\Expr\\\\StaticPropertyFetch\\|PhpParser\\\\Node\\\\Expr\\\\Variable, PhpParser\\\\Node\\\\Expr given\\.$#" - '#Cannot cast \(array\)\|string\|true to string#' - '#In method "Rector\\BetterPhpDocParser\\AnnotationReader\\NodeAnnotationReader\:\:createPropertyReflectionFromPropertyNode", 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#' @@ -265,8 +247,6 @@ parameters: - '#Parameter \#2 \$name of method Rector\\Core\\Rector\\AbstractRector\:\:isVariableName\(\) expects string, string\|null given#' - # mixed - - '#Property Rector\\Polyfill\\ValueObject\\BinaryToVersionCompareCondition\:\:\$expectedValue has no typehint specified#' # node finder - '#Method Rector\\Core\\PhpParser\\Node\\Manipulator\\MethodCallManipulator\:\:findAssignToVariableName\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#' @@ -293,16 +273,21 @@ parameters: count: 1 path: packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfo.php + - + message: "#in iterable type Iterator#" + paths: + - *Test.php + - *TestCase.php + + # iterable types + - '#with no value type specified in iterable type array#' + - '#type specified in iterable type (array|iterable)#' + - message: "#^Cognitive complexity for \"Rector\\\\BetterPhpDocParser\\\\Printer\\\\WhitespaceDetector\\:\\:detectOldWhitespaces\\(\\)\" is 18, keep it under 9$#" count: 1 path: packages/better-php-doc-parser/src/Printer/WhitespaceDetector.php - # copy-pasted magic from symfony - - - message: '#Use default null value and nullable compare instead of isset/empty on object#' - path: 'rules/symfony/src/ServiceMapProvider.php' - - message: "#^Parameter \\#1 \\$input of function array_splice expects array, array\\\\|null given\\.$#" count: 1 @@ -349,12 +334,9 @@ parameters: - '#Cognitive complexity for "Rector\\NetteKdyby\\ContributeEventClassResolver\:\:resolveGetterMethodByEventClassAndParam\(\)" is \d+, keep it under 9#' - '#Parameter \#1 \$type of class PhpParser\\Node\\NullableType constructor expects PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#' - '#Parameter \#1 \$object of function get_class expects object, PhpParser\\Node\|null given#' - - '#Cognitive complexity for "Rector\\Core\\Application\\RectorApplication\:\:runOnFileInfos\(\)" is 10, keep it under 9#' - '#Class "Rector\\FileSystemRector\\Rector\\Removing\\RemoveProjectFileRector" is missing @see annotation with test case class reference#' - - '#Class "Rector\\Php73\\Rector\\FuncCall\\SetCookieRector" is missing @see annotation with test case class reference#' - '#Parameter \#1 \$type of method PhpParser\\Builder\\Param\:\:setType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#' - '#Parameter \#1 \$node of method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findFirstAncestorInstanceOf\(\) expects PhpParser\\Node, PhpParser\\Node\\Expr\\Variable\|null given#' - - '#Parameter \#1 \$assignAndRootExpr of method Rector\\MagicDisclosure\\NodeFactory\\NonFluentMethodCallFactory\:\:createFromAssignObjectAndMethodCalls\(\) expects Rector\\Core\\ValueObject\\AssignAndRootExpr, Rector\\Core\\ValueObject\\AssignAndRootExpr\|null given#' - '#Parameter \#1 \$expr of method Rector\\MagicDisclosure\\Matcher\\ClassNameTypeMatcher\:\:doesExprMatchNames\(\) expects PhpParser\\Node\\Expr, PhpParser\\Node\\Expr\|null given#' - '#Parameter \#1 \$objectType of method Rector\\Naming\\Naming\\PropertyNaming\:\:fqnToVariableName\(\) expects PHPStan\\Type\\ObjectType\|string, PHPStan\\Type\\Type given#' - '#Method Rector\\Core\\PhpParser\\Node\\NodeFactory\:\:createConcat\(\) should return PhpParser\\Node\\Expr\\BinaryOp\\Concat\|null but returns PhpParser\\Node\\Expr#' @@ -382,9 +364,11 @@ parameters: message: '#Separate function "Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ref\(\)" in method call to standalone row to improve readability#' path: 'packages/rector-generator/config/config.php' - - '#Method Rector\\Nette\\NodeResolver\\FormVariableInputNameTypeResolver\:\:findPreviousAssignToVariable\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#' - - '#Method Rector\\Nette\\NodeResolver\\FormVariableInputNameTypeResolver\:\:resolveFromGetComponentMethodCall\(\) should return array but returns array#' - '#Method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findPreviousAssignToExpr\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#' - - '#Method Rector\\Nette\\FormControlTypeResolver\\GetComponentMethodCallFormControlTypeResolver\:\:resolve\(\) should return array but returns array#' - - '#Class with base "LexerFactory" name is already used in "PHPStan\\Parser\\LexerFactory", "Rector\\Core\\PhpParser\\Parser\\LexerFactory"\. Use unique name to make classes easy to recognize#' - '#Parameter \#1 \$shortControlString of method Rector\\NetteCodeQuality\\Rector\\Assign\\MakeGetComponentAssignAnnotatedRector\:\:resolveTypeFromShortControlNameAndVariable\(\) expects PhpParser\\Node\\Scalar\\String_, PhpParser\\Node\\Expr\|null given#' + - '#Parameter \#1 \$variable of class Rector\\Php70\\ValueObject\\VariableAssignPair constructor expects PhpParser\\Node\\Expr\\ArrayDimFetch\|PhpParser\\Node\\Expr\\PropertyFetch\|PhpParser\\Node\\Expr\\StaticPropertyFetch\|PhpParser\\Node\\Expr\\Variable, PhpParser\\Node\\Expr given#' + + # is nested expr + - '#Access to an undefined property PhpParser\\Node\\Expr\:\:\$expr#' + - '#Cognitive complexity for "Rector\\DeadCode\\NodeManipulator\\LivingCodeManipulator\:\:keepLivingCodeFromExpr\(\)" is \d+, keep it under 9#' + - '#Class with base "LexerFactory" name is already used in "PHPStan\\Parser\\LexerFactory", "Rector\\Core\\PhpParser\\Parser\\LexerFactory"\. Use unique name to make classes easy to recognize#' diff --git a/rector.php b/rector.php index 264c4649b57..22ffa3965a6 100644 --- a/rector.php +++ b/rector.php @@ -3,58 +3,38 @@ declare(strict_types=1); use Rector\Core\Configuration\Option; -use Rector\Injection\Rector\StaticCall\StaticCallToAnotherServiceConstructorInjectionRector; -use Rector\Injection\ValueObject\StaticCallToMethodCall; use Rector\Set\ValueObject\SetList; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; -use function Symfony\Component\DependencyInjection\Loader\Configurator\ref; return static function (ContainerConfigurator $containerConfigurator): void { $containerConfigurator->import(__DIR__ . '/create-rector.php', null, 'not_found'); - $services = $containerConfigurator->services(); - - // @todo improve this - $services->set('value_object', StaticCallToMethodCall::class) - ->args(['Nette\Utils\FileSystem', 'write', 'Symplify\SmartFileSystem\SmartFileSystem', 'dumpFile']) - ->autowire(false); - - $services->set(StaticCallToAnotherServiceConstructorInjectionRector::class) - ->arg('$staticCallsToMethodCalls', [ref('value_object')]); - $parameters = $containerConfigurator->parameters(); # Rector\Naming\Rector\ClassMethod\RenameVariableToMatchNewTypeRector: null - # Rector\Autodiscovery\Rector\FileSystem\MoveInterfacesToContractNamespaceDirectoryRector: null # bleeding edge feature # is_cache_enabled: true $parameters->set(Option::AUTO_IMPORT_NAMES, true); $parameters->set(Option::SETS, [SetList::NAMING]); - $parameters->set( - Option::PATHS, - [ - __DIR__ . '/src', - __DIR__ . '/tests', - __DIR__ . '/rules', - __DIR__ . '/utils', - __DIR__ . '/packages', - __DIR__ . '/bin/rector', - ] - ); + $parameters->set(Option::PATHS, [ + __DIR__ . '/src', + __DIR__ . '/tests', + __DIR__ . '/rules', + __DIR__ . '/utils', + __DIR__ . '/packages', + __DIR__ . '/bin/rector', + ]); - $parameters->set( - Option::EXCLUDE_PATHS, - [ - '/Source/', - '/*Source/', - '/Fixture/', - '/Expected/', - __DIR__ . '/packages/doctrine-annotation-generated/src/*', - '*.php.inc', - ] - ); + $parameters->set(Option::EXCLUDE_PATHS, [ + '/Source/', + '/*Source/', + '/Fixture/', + '/Expected/', + __DIR__ . '/packages/doctrine-annotation-generated/src/*', + '*.php.inc', + ]); # so Rector code is still PHP 7.2 compatible $parameters->set(Option::PHP_VERSION_FEATURES, '7.2'); diff --git a/rules/autodiscovery/src/Analyzer/ClassAnalyzer.php b/rules/autodiscovery/src/Analyzer/ClassAnalyzer.php index e49c40994a6..a4dc9958e98 100644 --- a/rules/autodiscovery/src/Analyzer/ClassAnalyzer.php +++ b/rules/autodiscovery/src/Analyzer/ClassAnalyzer.php @@ -104,7 +104,7 @@ final class ClassAnalyzer return false; } - private function hasAllPropertiesWithSerialize(Class_ $class) + private function hasAllPropertiesWithSerialize(Class_ $class): bool { foreach ($class->stmts as $stmt) { if (! $stmt instanceof Property) { diff --git a/rules/code-quality/src/Rector/Assign/SplitListAssignToSeparateLineRector.php b/rules/code-quality/src/Rector/Assign/SplitListAssignToSeparateLineRector.php index cebea76292a..42cf2a6a594 100644 --- a/rules/code-quality/src/Rector/Assign/SplitListAssignToSeparateLineRector.php +++ b/rules/code-quality/src/Rector/Assign/SplitListAssignToSeparateLineRector.php @@ -81,22 +81,22 @@ PHP return $node; } - private function shouldSkip($node): bool + private function shouldSkip(Assign $assign): bool { - if (! $node->var instanceof Array_ && ! $node->var instanceof List_) { + if (! $assign->var instanceof Array_ && ! $assign->var instanceof List_) { return true; } - if (! $node->expr instanceof Array_) { + if (! $assign->expr instanceof Array_) { return true; } - if (count($node->var->items) !== count($node->expr->items)) { + if (count($assign->var->items) !== count($assign->expr->items)) { return true; } // is value swap - return $this->isValueSwap($node->var, $node->expr); + return $this->isValueSwap($assign->var, $assign->expr); } /** diff --git a/rules/code-quality/src/Rector/FuncCall/AddPregQuoteDelimiterRector.php b/rules/code-quality/src/Rector/FuncCall/AddPregQuoteDelimiterRector.php index 7c1a0e29122..be36d442edb 100644 --- a/rules/code-quality/src/Rector/FuncCall/AddPregQuoteDelimiterRector.php +++ b/rules/code-quality/src/Rector/FuncCall/AddPregQuoteDelimiterRector.php @@ -74,16 +74,18 @@ PHP return $node; } - private function determineDelimiter(FuncCall $funcCall) + private function determineDelimiter(FuncCall $funcCall): ?string { $concat = $this->getUppermostConcat($funcCall); if ($concat === null) { return null; } + $leftMostConcatNode = $concat->left; while ($leftMostConcatNode instanceof Concat) { $leftMostConcatNode = $leftMostConcatNode->left; } + $rightMostConcatNode = $concat->right; while ($rightMostConcatNode instanceof Concat) { $rightMostConcatNode = $rightMostConcatNode->right; @@ -92,10 +94,12 @@ PHP if (! $leftMostConcatNode instanceof String_) { return null; } + $possibleLeftDelimiter = Strings::substring($leftMostConcatNode->value, 0, 1); if (! $rightMostConcatNode instanceof String_) { return null; } + $possibleRightDelimiter = Strings::substring(rtrim($rightMostConcatNode->value, self::ALL_MODIFIERS), -1, 1); if ($possibleLeftDelimiter === $possibleRightDelimiter) { return $possibleLeftDelimiter; diff --git a/rules/coding-style/src/Rector/MethodCall/PreferThisOrSelfMethodCallRector.php b/rules/coding-style/src/Rector/MethodCall/PreferThisOrSelfMethodCallRector.php index c5a1c5ea6ee..51759d91818 100644 --- a/rules/coding-style/src/Rector/MethodCall/PreferThisOrSelfMethodCallRector.php +++ b/rules/coding-style/src/Rector/MethodCall/PreferThisOrSelfMethodCallRector.php @@ -102,7 +102,7 @@ PHP return $node; } - private function ensurePreferenceIsValid($preference): void + private function ensurePreferenceIsValid(string $preference): void { $allowedPreferences = [self::PREFER_THIS, self::PREFER_SELF]; if (in_array($preference, $allowedPreferences, true)) { diff --git a/rules/coding-style/src/Rector/Throw_/AnnotateThrowablesRector.php b/rules/coding-style/src/Rector/Throw_/AnnotateThrowablesRector.php index 62ccb433568..676260b6933 100644 --- a/rules/coding-style/src/Rector/Throw_/AnnotateThrowablesRector.php +++ b/rules/coding-style/src/Rector/Throw_/AnnotateThrowablesRector.php @@ -221,6 +221,9 @@ PHP return new AttributeAwarePhpDocTagNode('@throws', $throwsTagValueNode); } + /** + * @return array + */ private function identifyThrownThrowablesInStaticCall(StaticCall $staticCall): array { $thrownClass = $staticCall->class; @@ -242,13 +245,14 @@ PHP return []; } - return $methodCall->getAttribute('parentNode') instanceof Throw_ - ? $this->extractMethodReturns($fullyQualified, $methodName) + $parent = $methodCall->getAttribute(AttributeKey::PARENT_NODE); + + return $parent instanceof Throw_ ? $this->extractMethodReturns($fullyQualified, $methodName) : $this->extractMethodThrows($fullyQualified, $methodName); } /** - * @return string[] + * @return class-string[] */ private function extractAlreadyAnnotatedThrowables(Node $node): array { @@ -288,6 +292,9 @@ PHP return count($this->throwablesToAnnotate); } + /** + * @return array + */ private function extractMethodReturns(FullyQualified $fullyQualified, Identifier $identifier): array { $method = $identifier->name; @@ -300,6 +307,9 @@ PHP return $this->classMethodReflectionHelper->extractTagsFromMethodDockblock($class, $method, '@return'); } + /** + * @return array + */ private function extractMethodThrows(FullyQualified $fullyQualified, Identifier $identifier): array { $method = $identifier->name; diff --git a/rules/coding-style/src/Rector/Use_/RemoveUnusedAliasRector.php b/rules/coding-style/src/Rector/Use_/RemoveUnusedAliasRector.php index 2bb95d7f53f..fa11889d297 100644 --- a/rules/coding-style/src/Rector/Use_/RemoveUnusedAliasRector.php +++ b/rules/coding-style/src/Rector/Use_/RemoveUnusedAliasRector.php @@ -205,10 +205,13 @@ PHP $useUse->alias = null; } - private function renameTraitUse(string $lastName, TraitUse $traitUse, $usedName): void + /** + * @param Name|Identifier $usedNameNode + */ + private function renameTraitUse(string $lastName, TraitUse $traitUse, Node $usedNameNode): void { foreach ($traitUse->traits as $key => $traitName) { - if (! $this->areNamesEqual($traitName, $usedName)) { + if (! $this->areNamesEqual($traitName, $usedNameNode)) { continue; } @@ -216,48 +219,63 @@ PHP } } - private function renameClass(string $lastName, Class_ $class, $usedName): void + /** + * @param Name|Identifier $usedNameNode + */ + private function renameClass(string $lastName, Class_ $class, Node $usedNameNode): void { - if ($class->name !== null && $this->areNamesEqual($class->name, $usedName)) { + if ($class->name !== null && $this->areNamesEqual($class->name, $usedNameNode)) { $class->name = new Identifier($lastName); } - if ($class->extends !== null && $this->areNamesEqual($class->extends, $usedName)) { + if ($class->extends !== null && $this->areNamesEqual($class->extends, $usedNameNode)) { $class->extends = new Name($lastName); } foreach ($class->implements as $key => $implementNode) { - if ($this->areNamesEqual($implementNode, $usedName)) { + if ($this->areNamesEqual($implementNode, $usedNameNode)) { $class->implements[$key] = new Name($lastName); } } } - private function renameParam(string $lastName, $parentNode, $usedName): void + /** + * @param Name|Identifier $usedNameNode + */ + private function renameParam(string $lastName, Node $parentNode, Node $usedNameNode): void { - if ($parentNode->type !== null && $this->areNamesEqual($parentNode->type, $usedName)) { + if ($parentNode->type !== null && $this->areNamesEqual($parentNode->type, $usedNameNode)) { $parentNode->type = new Name($lastName); } } - private function renameNew(string $lastName, $parentNode, $usedName): void + /** + * @param Name|Identifier $usedNameNode + */ + private function renameNew(string $lastName, Node $parentNode, Node $usedNameNode): void { - if ($this->areNamesEqual($parentNode->class, $usedName)) { + if ($this->areNamesEqual($parentNode->class, $usedNameNode)) { $parentNode->class = new Name($lastName); } } - private function renameClassMethod(string $lastName, ClassMethod $classMethod, $usedName): void + /** + * @param Name|Identifier $usedNameNode + */ + private function renameClassMethod(string $lastName, ClassMethod $classMethod, Node $usedNameNode): void { - if ($classMethod->returnType !== null && $this->areNamesEqual($classMethod->returnType, $usedName)) { + if ($classMethod->returnType !== null && $this->areNamesEqual($classMethod->returnType, $usedNameNode)) { $classMethod->returnType = new Name($lastName); } } - private function renameInterface(string $lastName, Interface_ $interface, $usedName): void + /** + * @param Name|Identifier $usedNameNode + */ + private function renameInterface(string $lastName, Interface_ $interface, Node $usedNameNode): void { foreach ($interface->extends as $key => $extendInterfaceName) { - if ($this->areNamesEqual($extendInterfaceName, $usedName)) { + if ($this->areNamesEqual($extendInterfaceName, $usedNameNode)) { $interface->extends[$key] = new Name($lastName); } } diff --git a/rules/dead-code/src/NodeManipulator/CountManipulator.php b/rules/dead-code/src/NodeManipulator/CountManipulator.php index a6fd16eca0f..5a17da087c3 100644 --- a/rules/dead-code/src/NodeManipulator/CountManipulator.php +++ b/rules/dead-code/src/NodeManipulator/CountManipulator.php @@ -67,7 +67,7 @@ final class CountManipulator return $this->isCountWithExpression($greater->left, $expr); } - private function processGreaterOrEqual(GreaterOrEqual $greaterOrEqual, Expr $expr) + private function processGreaterOrEqual(GreaterOrEqual $greaterOrEqual, Expr $expr): bool { if (! $this->isNumber($greaterOrEqual->right, 1)) { return false; diff --git a/rules/dead-code/src/NodeManipulator/LivingCodeManipulator.php b/rules/dead-code/src/NodeManipulator/LivingCodeManipulator.php index b0961ed984f..73854a79eed 100644 --- a/rules/dead-code/src/NodeManipulator/LivingCodeManipulator.php +++ b/rules/dead-code/src/NodeManipulator/LivingCodeManipulator.php @@ -28,8 +28,6 @@ use PhpParser\Node\Expr\StaticPropertyFetch; use PhpParser\Node\Expr\UnaryMinus; use PhpParser\Node\Expr\UnaryPlus; use PhpParser\Node\Expr\Variable; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; use PhpParser\Node\Scalar; final class LivingCodeManipulator @@ -40,13 +38,11 @@ final class LivingCodeManipulator */ public function keepLivingCodeFromExpr($expr): array { - if (! $expr instanceof Node || - $expr instanceof Closure || - $expr instanceof Name || - $expr instanceof Identifier || - $expr instanceof Scalar || - $expr instanceof ConstFetch - ) { + if (! $expr instanceof Expr) { + return []; + } + + if ($expr instanceof Closure || $expr instanceof Scalar || $expr instanceof ConstFetch) { return []; } @@ -72,8 +68,7 @@ final class LivingCodeManipulator ); } - if ($expr instanceof ClassConstFetch || - $expr instanceof StaticPropertyFetch) { + if ($expr instanceof ClassConstFetch || $expr instanceof StaticPropertyFetch) { return array_merge( $this->keepLivingCodeFromExpr($expr->class), $this->keepLivingCodeFromExpr($expr->name) @@ -81,10 +76,9 @@ final class LivingCodeManipulator } if ($this->isBinaryOpWithoutChange($expr)) { - return array_merge( - $this->keepLivingCodeFromExpr($expr->left), - $this->keepLivingCodeFromExpr($expr->right) - ); + /** @var BinaryOp $binaryOp */ + $binaryOp = $expr; + return $this->processBinary($binaryOp); } if ($expr instanceof Instanceof_) { @@ -95,15 +89,13 @@ final class LivingCodeManipulator } if ($expr instanceof Isset_) { - return array_merge(...array_map(function (Expr $expr): array { - return $this->keepLivingCodeFromExpr($expr); - }, $expr->vars)); + return $this->processIsset($expr); } return [$expr]; } - private function isNestedExpr($expr): bool + private function isNestedExpr(Expr $expr): bool { return $expr instanceof Cast || $expr instanceof Empty_ || @@ -114,15 +106,33 @@ final class LivingCodeManipulator $expr instanceof Clone_; } - private function isBinaryOpWithoutChange($expr): bool + private function isBinaryOpWithoutChange(Expr $expr): bool { - return $expr instanceof BinaryOp - && ! ( - $expr instanceof LogicalAnd || - $expr instanceof BooleanAnd || - $expr instanceof LogicalOr || - $expr instanceof BooleanOr || - $expr instanceof Coalesce - ); + if (! $expr instanceof BinaryOp) { + return false; + } + + return ! ( + $expr instanceof LogicalAnd || + $expr instanceof BooleanAnd || + $expr instanceof LogicalOr || + $expr instanceof BooleanOr || + $expr instanceof Coalesce + ); + } + + private function processIsset(Isset_ $isset): array + { + return array_merge(...array_map(function (Expr $expr): array { + return $this->keepLivingCodeFromExpr($expr); + }, $isset->vars)); + } + + private function processBinary(BinaryOp $binaryOp): array + { + return array_merge( + $this->keepLivingCodeFromExpr($binaryOp->left), + $this->keepLivingCodeFromExpr($binaryOp->right) + ); } } diff --git a/rules/dead-code/src/Rector/Array_/RemoveDuplicatedArrayKeyRector.php b/rules/dead-code/src/Rector/Array_/RemoveDuplicatedArrayKeyRector.php index 61d364b2217..b7d7d44fc15 100644 --- a/rules/dead-code/src/Rector/Array_/RemoveDuplicatedArrayKeyRector.php +++ b/rules/dead-code/src/Rector/Array_/RemoveDuplicatedArrayKeyRector.php @@ -64,7 +64,10 @@ PHP return $node; } - private function getArrayItemsWithDuplicatedKey(Array_ $array) + /** + * @return ArrayItem[][] + */ + private function getArrayItemsWithDuplicatedKey(Array_ $array): array { $arrayItemsByKeys = []; diff --git a/rules/decouple/tests/Rector/DecoupleClassMethodToOwnClassRector/DecoupleClassMethodToOwnClassRectorTest.php b/rules/decouple/tests/Rector/DecoupleClassMethodToOwnClassRector/DecoupleClassMethodToOwnClassRectorTest.php index 70c629b7e04..87ca8c92c92 100644 --- a/rules/decouple/tests/Rector/DecoupleClassMethodToOwnClassRector/DecoupleClassMethodToOwnClassRectorTest.php +++ b/rules/decouple/tests/Rector/DecoupleClassMethodToOwnClassRector/DecoupleClassMethodToOwnClassRectorTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Rector\Decouple\Tests\Rector\DecoupleClassMethodToOwnClassRector; +use Iterator; use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase; use Rector\Decouple\Rector\DecoupleClassMethodToOwnClassRector; use Rector\Decouple\Tests\Rector\DecoupleClassMethodToOwnClassRector\Source\AbstractFather; @@ -22,7 +23,7 @@ final class DecoupleClassMethodToOwnClassRectorTest extends AbstractRectorTestCa $this->assertFileEquals($expectedContentFilePath, $expectedFilePath); } - public function provideData() + public function provideData(): Iterator { yield [ new SmartFileInfo(__DIR__ . '/Fixture/basic.php.inc'), diff --git a/rules/laravel/src/Rector/FuncCall/HelperFunctionToConstructorInjectionRector.php b/rules/laravel/src/Rector/FuncCall/HelperFunctionToConstructorInjectionRector.php index 7c4b611f58f..7e3b2b4113c 100644 --- a/rules/laravel/src/Rector/FuncCall/HelperFunctionToConstructorInjectionRector.php +++ b/rules/laravel/src/Rector/FuncCall/HelperFunctionToConstructorInjectionRector.php @@ -169,7 +169,7 @@ PHP FuncCall $funcCall, ArrayFunctionToMethodCall $arrayFunctionToMethodCall, PropertyFetch $propertyFetch - ) { + ): ?MethodCall { if ($arrayFunctionToMethodCall->getArrayMethod() && $this->isArrayType($funcCall->args[0]->value)) { return new MethodCall($propertyFetch, $arrayFunctionToMethodCall->getArrayMethod(), $funcCall->args); } diff --git a/rules/magic-disclosure/src/Rector/MethodCall/DefluentMethodCallRector.php b/rules/magic-disclosure/src/Rector/MethodCall/DefluentMethodCallRector.php index 9e9b5771e3a..c45ac7e0e38 100644 --- a/rules/magic-disclosure/src/Rector/MethodCall/DefluentMethodCallRector.php +++ b/rules/magic-disclosure/src/Rector/MethodCall/DefluentMethodCallRector.php @@ -111,6 +111,9 @@ PHP $chainMethodCalls = $this->chainMethodCallNodeAnalyzer->collectAllMethodCallsInChain($methodCall); $assignAndRootExpr = $this->chainMethodCallRootExtractor->extractFromMethodCalls($chainMethodCalls); + if ($assignAndRootExpr === null) { + return null; + } if ($this->shouldSkip($assignAndRootExpr, $chainMethodCalls)) { return null; @@ -151,7 +154,10 @@ PHP return $node; } - private function isHandledByReturn($node): bool + /** + * @param MethodCall|Return_ $node + */ + private function isHandledByReturn(Node $node): bool { if ($node instanceof MethodCall) { $parentNode = $node->getAttribute(AttributeKey::PARENT_NODE); @@ -167,12 +173,8 @@ PHP /** * @param MethodCall[] $chainMethodCalls */ - private function shouldSkip(?AssignAndRootExpr $assignAndRootExpr, array $chainMethodCalls): bool + private function shouldSkip(AssignAndRootExpr $assignAndRootExpr, array $chainMethodCalls): bool { - if ($assignAndRootExpr === null) { - return true; - } - if (! $this->chainMethodCallNodeAnalyzer->isCalleeSingleType($assignAndRootExpr, $chainMethodCalls)) { return true; } @@ -183,7 +185,10 @@ PHP ); } - private function removeCurrentNode($node): void + /** + * @param MethodCall|Return_ $node + */ + private function removeCurrentNode(Node $node): void { $parentNode = $node->getAttribute(AttributeKey::PARENT_NODE); if ($parentNode instanceof Assign) { diff --git a/rules/naming/src/Naming/ExpectedNameResolver.php b/rules/naming/src/Naming/ExpectedNameResolver.php index 7081ea1fb3e..5fe164fcf67 100644 --- a/rules/naming/src/Naming/ExpectedNameResolver.php +++ b/rules/naming/src/Naming/ExpectedNameResolver.php @@ -15,6 +15,7 @@ use PhpParser\Node\Expr\Variable; use PhpParser\Node\Name; use PhpParser\Node\Param; use PhpParser\Node\Stmt\Property; +use PHPStan\Type\ArrayType; use PHPStan\Type\MixedType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\NodeNameResolver\NodeNameResolver; @@ -176,6 +177,11 @@ final class ExpectedNameResolver } $returnedType = $this->nodeTypeResolver->getStaticType($expr); + + if ($returnedType instanceof ArrayType) { + return null; + } + if ($returnedType instanceof MixedType) { return null; } diff --git a/rules/naming/src/Rector/Assign/RenameVariableToMatchGetMethodNameRector.php b/rules/naming/src/Rector/Assign/RenameVariableToMatchGetMethodNameRector.php index db355d4f96c..096752b95c7 100644 --- a/rules/naming/src/Rector/Assign/RenameVariableToMatchGetMethodNameRector.php +++ b/rules/naming/src/Rector/Assign/RenameVariableToMatchGetMethodNameRector.php @@ -142,7 +142,7 @@ PHP } $expectedName = $this->expectedNameResolver->resolveForCall($variableAndCallAssign->getCall()); - if ($expectedName === null || $this->isName($node, $expectedName)) { + if ($expectedName === null || $this->isName($node->var, $expectedName)) { return null; } diff --git a/rules/naming/src/Rector/Class_/RenamePropertyToMatchTypeRector.php b/rules/naming/src/Rector/Class_/RenamePropertyToMatchTypeRector.php index 99ca57546a7..fba648ce550 100644 --- a/rules/naming/src/Rector/Class_/RenamePropertyToMatchTypeRector.php +++ b/rules/naming/src/Rector/Class_/RenamePropertyToMatchTypeRector.php @@ -17,12 +17,14 @@ use PhpParser\Node\Stmt\Interface_; use PhpParser\Node\Stmt\Property; use PhpParser\Node\VarLikeIdentifier; use PhpParser\NodeTraverser; +use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\Core\Rector\AbstractRector; use Rector\Core\RectorDefinition\CodeSample; use Rector\Core\RectorDefinition\RectorDefinition; use Rector\Naming\Guard\BreakingVariableRenameGuard; use Rector\Naming\Naming\ConflictingNameResolver; use Rector\Naming\Naming\ExpectedNameResolver; +use Rector\NodeTypeResolver\Node\AttributeKey; /** * @see \Rector\Naming\Tests\Rector\Class_\RenamePropertyToMatchTypeRector\RenamePropertyToMatchTypeRectorTest @@ -233,7 +235,29 @@ PHP // 2. rename param in the rest of the method $this->renameVariableInClassMethod($classMethod, $oldName, $expectedName); + // 3. rename @param variable in docblock too + $this->renameParameterNameInDocBlock($classMethod, $oldName, $expectedName); + $this->hasChange = true; } } + + private function renameParameterNameInDocBlock( + ClassMethod $classMethod, + string $oldName, + string $expectedName + ): void { + /** @var PhpDocInfo|null $phpDocInfo */ + $phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO); + if ($phpDocInfo === null) { + return; + } + + $paramTagValueNode = $phpDocInfo->getParamTagValueNodeByName($oldName); + if ($paramTagValueNode === null) { + return; + } + + $paramTagValueNode->parameterName = '$' . $expectedName; + } } diff --git a/rules/naming/src/VariableRenamer.php b/rules/naming/src/VariableRenamer.php index cf0fee8bf1a..8bc7b5ab1a2 100644 --- a/rules/naming/src/VariableRenamer.php +++ b/rules/naming/src/VariableRenamer.php @@ -74,7 +74,7 @@ final class VariableRenamer ); } - private function renameVariableIfMatchesName(Variable $variable, string $oldName, string $expectedName) + private function renameVariableIfMatchesName(Variable $variable, string $oldName, string $expectedName): ?Variable { if (! $this->nodeNameResolver->isName($variable, $oldName)) { return null; diff --git a/rules/naming/tests/Rector/Class_/RenamePropertyToMatchTypeRector/Fixture/update_doc_name.php.inc b/rules/naming/tests/Rector/Class_/RenamePropertyToMatchTypeRector/Fixture/update_doc_name.php.inc new file mode 100644 index 00000000000..ac26a3a7b8a --- /dev/null +++ b/rules/naming/tests/Rector/Class_/RenamePropertyToMatchTypeRector/Fixture/update_doc_name.php.inc @@ -0,0 +1,35 @@ + +----- + diff --git a/rules/nette-code-quality/src/Contract/MethodNamesByInputNamesResolverAwareInterface.php b/rules/nette-code-quality/src/Contract/MethodNamesByInputNamesResolverAwareInterface.php index 1d42c4abdee..e90af98baa5 100644 --- a/rules/nette-code-quality/src/Contract/MethodNamesByInputNamesResolverAwareInterface.php +++ b/rules/nette-code-quality/src/Contract/MethodNamesByInputNamesResolverAwareInterface.php @@ -8,5 +8,5 @@ use Rector\NetteCodeQuality\NodeResolver\MethodNamesByInputNamesResolver; interface MethodNamesByInputNamesResolverAwareInterface { - public function setResolver(MethodNamesByInputNamesResolver $methodNamesByInputNamesResolver); + public function setResolver(MethodNamesByInputNamesResolver $methodNamesByInputNamesResolver): void; } diff --git a/rules/nette-code-quality/src/Rector/Assign/MakeGetComponentAssignAnnotatedRector.php b/rules/nette-code-quality/src/Rector/Assign/MakeGetComponentAssignAnnotatedRector.php index 091146b311e..c80e829aba9 100644 --- a/rules/nette-code-quality/src/Rector/Assign/MakeGetComponentAssignAnnotatedRector.php +++ b/rules/nette-code-quality/src/Rector/Assign/MakeGetComponentAssignAnnotatedRector.php @@ -199,8 +199,11 @@ PHP return is_a($varStaticType->getClassName(), 'Nette\Application\UI\Control', true); } - private function resolveTypeFromShortControlNameAndVariable(String_ $shortControlString, Scope $scope, Expr $expr) - { + private function resolveTypeFromShortControlNameAndVariable( + String_ $shortControlString, + Scope $scope, + Expr $expr + ): Type { $componentName = $this->getValue($shortControlString); $methodName = sprintf('createComponent%s', ucfirst($componentName)); diff --git a/rules/nette/src/Rector/MethodCall/AddDatePickerToDateControlRector.php b/rules/nette/src/Rector/MethodCall/AddDatePickerToDateControlRector.php index 85fd84855ad..1d11fc72e9c 100644 --- a/rules/nette/src/Rector/MethodCall/AddDatePickerToDateControlRector.php +++ b/rules/nette/src/Rector/MethodCall/AddDatePickerToDateControlRector.php @@ -50,7 +50,7 @@ class SomeClass public function run() { $form = new Form(); - $keyDateControl = $form['key'] = new \Nextras\FormComponents\Controls\DateControl('Label'); + $form['key'] = new \Nextras\FormComponents\Controls\DateControl('Label'); } } PHP @@ -84,7 +84,6 @@ PHP } $controlName = $this->resolveControlName($node->var); - $node->var = new Variable($controlName); // this fixes printing indent @@ -112,35 +111,46 @@ PHP return $controlName->value . 'DateControl'; } - private function createDateTimeControlNew($node): New_ + private function createDateTimeControlNew(MethodCall $methodCall): New_ { $fullyQualified = new FullyQualified('Nextras\FormComponents\Controls\DateControl'); $new = new New_($fullyQualified); - if (isset($node->args[1])) { - $new->args[] = $node->args[1]; + if (isset($methodCall->args[1])) { + $new->args[] = $methodCall->args[1]; } + return $new; } - private function createAssign(MethodCall $methodCall): ?Assign + private function createAssign(MethodCall $methodCall): ?Node { $key = $methodCall->args[0]->value; if (! $key instanceof String_) { return null; } - $arrayDimFetch = new ArrayDimFetch($methodCall->var, $key); $new = $this->createDateTimeControlNew($methodCall); - $formAssign = new Assign($arrayDimFetch, $new); $parent = $methodCall->getAttribute(AttributeKey::PARENT_NODE); if ($parent instanceof Assign) { - return $formAssign; + return $new; } - $controlName = $this->resolveControlName($methodCall); + $arrayDimFetch = new ArrayDimFetch($methodCall->var, $key); + $new = $this->createDateTimeControlNew($methodCall); - return new Assign(new Variable($controlName), $formAssign); + $formAssign = new Assign($arrayDimFetch, $new); + + if ($parent !== null) { + $methodCalls = $this->betterNodeFinder->findInstanceOf($parent, MethodCall::class); + + if (count($methodCalls) > 1) { + $controlName = $this->resolveControlName($methodCall); + return new Assign(new Variable($controlName), $formAssign); + } + } + + return $formAssign; } } diff --git a/rules/nette/tests/Rector/MethodCall/AddDatePickerToDateControlRector/Fixture/assigned_value.php.inc b/rules/nette/tests/Rector/MethodCall/AddDatePickerToDateControlRector/Fixture/assigned_value.php.inc index b77ab9a7aa0..f80c9632836 100644 --- a/rules/nette/tests/Rector/MethodCall/AddDatePickerToDateControlRector/Fixture/assigned_value.php.inc +++ b/rules/nette/tests/Rector/MethodCall/AddDatePickerToDateControlRector/Fixture/assigned_value.php.inc @@ -26,7 +26,7 @@ class AssignedValue public function run() { $form = new Form(); - $datePicker = $form['key'] = new \Nextras\FormComponents\Controls\DateControl('Label'); + $datePicker = new \Nextras\FormComponents\Controls\DateControl('Label'); } } diff --git a/rules/nette/tests/Rector/MethodCall/AddDatePickerToDateControlRector/Fixture/fixture.php.inc b/rules/nette/tests/Rector/MethodCall/AddDatePickerToDateControlRector/Fixture/fixture.php.inc index 4e9fcf9270a..54742dce3ba 100644 --- a/rules/nette/tests/Rector/MethodCall/AddDatePickerToDateControlRector/Fixture/fixture.php.inc +++ b/rules/nette/tests/Rector/MethodCall/AddDatePickerToDateControlRector/Fixture/fixture.php.inc @@ -26,7 +26,7 @@ class SomeClass public function run() { $form = new Form(); - $keyDateControl = $form['key'] = new \Nextras\FormComponents\Controls\DateControl('Label'); + $form['key'] = new \Nextras\FormComponents\Controls\DateControl('Label'); } } diff --git a/rules/php70/src/EregToPcreTransformer.php b/rules/php70/src/EregToPcreTransformer.php index 14742235ed8..1f60f962017 100644 --- a/rules/php70/src/EregToPcreTransformer.php +++ b/rules/php70/src/EregToPcreTransformer.php @@ -181,7 +181,7 @@ final class EregToPcreTransformer return [implode('|', $r), $i]; } - private function processBracket(string $content, int $i, int $l, array &$r, int $rr) + private function processBracket(string $content, int $i, int $l, array &$r, int $rr): int { // special case if ($i + 1 < $l && $content[$i + 1] === ')') { diff --git a/rules/php70/src/Rector/FuncCall/NonVariableToVariableOnFunctionCallRector.php b/rules/php70/src/Rector/FuncCall/NonVariableToVariableOnFunctionCallRector.php index 1ee9ee8d922..659035f8df1 100644 --- a/rules/php70/src/Rector/FuncCall/NonVariableToVariableOnFunctionCallRector.php +++ b/rules/php70/src/Rector/FuncCall/NonVariableToVariableOnFunctionCallRector.php @@ -79,7 +79,6 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector } $arguments = $this->getNonVariableArguments($node); - if ($arguments === []) { return null; } diff --git a/rules/php73/src/Rector/FuncCall/SetCookieRector.php b/rules/php73/src/Rector/FuncCall/SetCookieRector.php index d69f195d009..5074e3b8bc8 100644 --- a/rules/php73/src/Rector/FuncCall/SetCookieRector.php +++ b/rules/php73/src/Rector/FuncCall/SetCookieRector.php @@ -19,8 +19,8 @@ use Rector\Core\ValueObject\PhpVersionFeature; /** * Convert legacy setcookie arguments to new array options * - * @see \Rector\Php73\Tests\Rector\FuncCall\SetcookieRector\SetcookieRectorTest - + * @see \Rector\Php73\Tests\Rector\FuncCall\SetcookieRector\SetCookieRectorTest + * * @see https://www.php.net/setcookie * @see https://wiki.php.net/rfc/same-site-cookie */ diff --git a/rules/php80/src/Rector/FuncCall/TokenGetAllToObjectRector.php b/rules/php80/src/Rector/FuncCall/TokenGetAllToObjectRector.php index 0f9075d926c..a210211452e 100644 --- a/rules/php80/src/Rector/FuncCall/TokenGetAllToObjectRector.php +++ b/rules/php80/src/Rector/FuncCall/TokenGetAllToObjectRector.php @@ -156,9 +156,10 @@ PHP } /** + * @param ClassMethod|Function_ $functionLike * @return Foreach_[] */ - private function findForeachesOverTokenVariable($functionLike, Expr $assignedExpr): array + private function findForeachesOverTokenVariable(FunctionLike $functionLike, Expr $assignedExpr): array { return $this->betterNodeFinder->find((array) $functionLike->stmts, function (Node $node) use ( $assignedExpr diff --git a/rules/psr4/src/Collector/RenamedClassesCollector.php b/rules/psr4/src/Collector/RenamedClassesCollector.php index c064ad83f8a..08483781275 100644 --- a/rules/psr4/src/Collector/RenamedClassesCollector.php +++ b/rules/psr4/src/Collector/RenamedClassesCollector.php @@ -9,7 +9,7 @@ use Rector\Core\Configuration\ChangeConfiguration; final class RenamedClassesCollector { /** - * @var string[] + * @var array */ private $oldToNewClass = []; @@ -29,7 +29,7 @@ final class RenamedClassesCollector } /** - * @return string[] + * @return array */ public function getOldToNewClasses(): array { diff --git a/rules/renaming/src/NodeManipulator/ClassRenamer.php b/rules/renaming/src/NodeManipulator/ClassRenamer.php index 4f9b44400b1..7f046e9d486 100644 --- a/rules/renaming/src/NodeManipulator/ClassRenamer.php +++ b/rules/renaming/src/NodeManipulator/ClassRenamer.php @@ -78,6 +78,9 @@ final class ClassRenamer $this->betterNodeFinder = $betterNodeFinder; } + /** + * @param array $oldToNewClasses + */ public function renameNode(Node $node, array $oldToNewClasses): ?Node { $this->refactorPhpDoc($node, $oldToNewClasses); @@ -101,7 +104,7 @@ final class ClassRenamer * Replace types in @var/@param/@return/@throws, * Doctrine @ORM entity targetClass, Serialize, Assert etc. */ - private function refactorPhpDoc(Node $node, $oldToNewClasses): void + private function refactorPhpDoc(Node $node, array $oldToNewClasses): void { if (! $this->docBlockManipulator->hasNodeTypeTags($node)) { return; diff --git a/rules/renaming/src/Rector/Class_/RenameClassRector.php b/rules/renaming/src/Rector/Class_/RenameClassRector.php index 71a2f5a60cd..75d5863f965 100644 --- a/rules/renaming/src/Rector/Class_/RenameClassRector.php +++ b/rules/renaming/src/Rector/Class_/RenameClassRector.php @@ -33,7 +33,7 @@ final class RenameClassRector extends AbstractRector private $classRenamer; /** - * @param string[] $oldToNewClasses + * @param array $oldToNewClasses */ public function __construct( ChangeConfiguration $changeConfiguration, diff --git a/rules/renaming/src/Rector/MethodCall/RenameMethodRector.php b/rules/renaming/src/Rector/MethodCall/RenameMethodRector.php index 2b830c9eae3..b73a41cdf91 100644 --- a/rules/renaming/src/Rector/MethodCall/RenameMethodRector.php +++ b/rules/renaming/src/Rector/MethodCall/RenameMethodRector.php @@ -147,8 +147,9 @@ PHP /** * @param MethodCall|StaticCall|ClassMethod $node + * @param string|string[] $newMethod */ - private function skipClassMethod($node, $newMethod, string $type): bool + private function skipClassMethod(Node $node, $newMethod, string $type): bool { if (! $node instanceof ClassMethod) { return false; diff --git a/rules/restoration/src/Rector/Class_/RemoveUselessJustForSakeInterfaceRector.php b/rules/restoration/src/Rector/Class_/RemoveUselessJustForSakeInterfaceRector.php index 13ae67a99b0..ee84b3103b7 100644 --- a/rules/restoration/src/Rector/Class_/RemoveUselessJustForSakeInterfaceRector.php +++ b/rules/restoration/src/Rector/Class_/RemoveUselessJustForSakeInterfaceRector.php @@ -9,6 +9,7 @@ use PhpParser\Node; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Interface_; +use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\Rector\AbstractRector; use Rector\Core\RectorDefinition\CodeSample; use Rector\Core\RectorDefinition\RectorDefinition; @@ -176,10 +177,15 @@ CODE_SAMPLE $this->renamedClassesCollector->addClassRename($implementedInterfaceName, $className); } - private function resolveClassFileLocation(string $implementedInterfaceName) + private function resolveClassFileLocation(string $implementedInterfaceName): string { $reflectionClass = new ReflectionClass($implementedInterfaceName); - return $reflectionClass->getFileName(); + $fileName = $reflectionClass->getFileName(); + if (! $fileName) { + throw new ShouldNotHappenException(); + } + + return $fileName; } private function removeOrReplaceImlementedInterface(string $implementedInterfaceName, Class_ $class, int $key): void diff --git a/rules/restoration/src/Rector/Property/MakeTypedPropertyNullableIfCheckedRector.php b/rules/restoration/src/Rector/Property/MakeTypedPropertyNullableIfCheckedRector.php index ecdb072ea76..fa81426c12c 100644 --- a/rules/restoration/src/Rector/Property/MakeTypedPropertyNullableIfCheckedRector.php +++ b/rules/restoration/src/Rector/Property/MakeTypedPropertyNullableIfCheckedRector.php @@ -95,17 +95,17 @@ PHP return $node; } - private function shouldSkipProperty($node): bool + private function shouldSkipProperty(Property $property): bool { - if (count($node->props) !== 1) { + if (count($property->props) !== 1) { return true; } - if ($node->type === null) { + if ($property->type === null) { return true; } - return $node->type instanceof NullableType; + return $property->type instanceof NullableType; } private function isPropertyNullChecked(PropertyProperty $onlyPropertyProperty): bool @@ -171,7 +171,7 @@ PHP return $isIdenticalOrNotIdenticalToNull; } - private function isBooleanNot(Class_ $class, PropertyProperty $onlyPropertyProperty) + private function isBooleanNot(Class_ $class, PropertyProperty $onlyPropertyProperty): bool { $isBooleanNot = false; diff --git a/rules/symfony-php-config/src/Printer/ReturnClosurePrinter.php b/rules/symfony-php-config/src/Printer/ReturnClosurePrinter.php index 3a2e13d3a45..82e91ecb95f 100644 --- a/rules/symfony-php-config/src/Printer/ReturnClosurePrinter.php +++ b/rules/symfony-php-config/src/Printer/ReturnClosurePrinter.php @@ -144,6 +144,9 @@ final class ReturnClosurePrinter return Strings::replace($content, '#\)->#', $nextCallIndentReplacement); } + /** + * @param mixed[]|mixed $value + */ private function shouldSkipObjectConfiguration($value): bool { if (! is_array($value)) { diff --git a/rules/symfony/src/ServiceMapProvider.php b/rules/symfony/src/ServiceMapProvider.php index 472b82c81b1..9b626a3b352 100644 --- a/rules/symfony/src/ServiceMapProvider.php +++ b/rules/symfony/src/ServiceMapProvider.php @@ -195,6 +195,9 @@ final class ServiceMapProvider return $data; } + /** + * @param string|int $key + */ private function convertedNestedArrayOrXml(array $value, array $data, $key): array { foreach ($value as $subKey => $subValue) { diff --git a/rules/type-declaration/src/PhpDocParser/NonInformativeReturnTagRemover.php b/rules/type-declaration/src/PhpDocParser/NonInformativeReturnTagRemover.php index c1d33c0fcb0..d9597fd7c9a 100644 --- a/rules/type-declaration/src/PhpDocParser/NonInformativeReturnTagRemover.php +++ b/rules/type-declaration/src/PhpDocParser/NonInformativeReturnTagRemover.php @@ -189,8 +189,11 @@ final class NonInformativeReturnTagRemover return null; } - private function removeShortObjectType(Type $returnType, $returnTagValueNode, ?PhpDocInfo $phpDocInfo): void - { + private function removeShortObjectType( + Type $returnType, + ReturnTagValueNode $returnTagValueNode, + ?PhpDocInfo $phpDocInfo + ): void { if (! $returnType instanceof ShortenedObjectType) { return; } diff --git a/rules/type-declaration/src/Rector/ClassMethod/AddParamTypeDeclarationRector.php b/rules/type-declaration/src/Rector/ClassMethod/AddParamTypeDeclarationRector.php index 1524a85a7c4..d94b2f252e8 100644 --- a/rules/type-declaration/src/Rector/ClassMethod/AddParamTypeDeclarationRector.php +++ b/rules/type-declaration/src/Rector/ClassMethod/AddParamTypeDeclarationRector.php @@ -142,7 +142,7 @@ PHP private function refactorClassMethodWithTypehintByParameterPosition( ClassMethod $classMethod, - $typehintByParameterPosition + array $typehintByParameterPosition ): void { foreach ($typehintByParameterPosition as $parameterPosition => $type) { if (! isset($classMethod->params[$parameterPosition])) { diff --git a/rules/type-declaration/src/Rector/FunctionLike/ReturnTypeDeclarationRector.php b/rules/type-declaration/src/Rector/FunctionLike/ReturnTypeDeclarationRector.php index 87240e1466a..f14620d5192 100644 --- a/rules/type-declaration/src/Rector/FunctionLike/ReturnTypeDeclarationRector.php +++ b/rules/type-declaration/src/Rector/FunctionLike/ReturnTypeDeclarationRector.php @@ -281,7 +281,7 @@ PHP $this->notifyNodeFileInfo($currentClassMethod); } - private function isVoidDueToThrow(Node $node, $inferredReturnNode): bool + private function isVoidDueToThrow(Node $node, Node $inferredReturnNode): bool { if (! $inferredReturnNode instanceof Identifier) { return false; diff --git a/src/Configuration/ChangeConfiguration.php b/src/Configuration/ChangeConfiguration.php index f6137b7419d..bfe9d5dacf4 100644 --- a/src/Configuration/ChangeConfiguration.php +++ b/src/Configuration/ChangeConfiguration.php @@ -7,12 +7,12 @@ namespace Rector\Core\Configuration; final class ChangeConfiguration { /** - * @var string[] + * @var array */ private $oldToNewClasses = []; /** - * @param string[] $oldToNewClasses + * @param array $oldToNewClasses */ public function setOldToNewClasses(array $oldToNewClasses): void { @@ -20,7 +20,7 @@ final class ChangeConfiguration } /** - * @return string[] + * @return array */ public function getOldToNewClasses(): array { diff --git a/src/DependencyInjection/Collector/RectorServiceArgumentCollector.php b/src/DependencyInjection/Collector/RectorServiceArgumentCollector.php index 02e9a6e593d..a901acfe545 100644 --- a/src/DependencyInjection/Collector/RectorServiceArgumentCollector.php +++ b/src/DependencyInjection/Collector/RectorServiceArgumentCollector.php @@ -46,6 +46,9 @@ final class RectorServiceArgumentCollector } } + /** + * @param mixed $argumentValue + */ private function addArgumentValue(string $serviceClassName, string $argumentName, $argumentValue): void { if (! isset($this->cachedRectorServiceKeyArguments[$serviceClassName][$argumentName])) { diff --git a/src/PhpParser/Node/Manipulator/BinaryOpManipulator.php b/src/PhpParser/Node/Manipulator/BinaryOpManipulator.php index 804ca9b5924..786c7fbad75 100644 --- a/src/PhpParser/Node/Manipulator/BinaryOpManipulator.php +++ b/src/PhpParser/Node/Manipulator/BinaryOpManipulator.php @@ -96,6 +96,9 @@ final class BinaryOpManipulator return new $inversedNodeClass($binaryOp->left, $binaryOp->right); } + /** + * @param string|callable $firstCondition + */ private function validateCondition($firstCondition): void { if (is_callable($firstCondition)) { diff --git a/src/PhpParser/Node/Manipulator/ClassInsertManipulator.php b/src/PhpParser/Node/Manipulator/ClassInsertManipulator.php index 7fada87f5b6..f5493eed29e 100644 --- a/src/PhpParser/Node/Manipulator/ClassInsertManipulator.php +++ b/src/PhpParser/Node/Manipulator/ClassInsertManipulator.php @@ -126,7 +126,7 @@ final class ClassInsertManipulator return false; } - private function hasClassConstant(Class_ $class, string $constantName) + private function hasClassConstant(Class_ $class, string $constantName): bool { foreach ($class->getConstants() as $classConst) { if ($this->nodeNameResolver->isName($classConst, $constantName)) { diff --git a/src/PhpParser/Node/Manipulator/IdentifierManipulator.php b/src/PhpParser/Node/Manipulator/IdentifierManipulator.php index 4183bb10aa9..ecb1d0500a4 100644 --- a/src/PhpParser/Node/Manipulator/IdentifierManipulator.php +++ b/src/PhpParser/Node/Manipulator/IdentifierManipulator.php @@ -86,7 +86,7 @@ final class IdentifierManipulator )); } - private function resolveOldMethodName(Node $node) + private function resolveOldMethodName(Node $node): ?string { if ($node instanceof StaticCall || $node instanceof MethodCall) { return $this->nodeNameResolver->getName($node->name); diff --git a/src/PhpParser/Node/NodeFactory.php b/src/PhpParser/Node/NodeFactory.php index c071fc8ba43..6b384604204 100644 --- a/src/PhpParser/Node/NodeFactory.php +++ b/src/PhpParser/Node/NodeFactory.php @@ -156,7 +156,7 @@ final class NodeFactory } /** - * Creates "($arg)" + * @param mixed $argument */ public function createArg($argument): Arg { @@ -314,11 +314,17 @@ final class NodeFactory return $property; } + /** + * @param mixed $value + */ public function createPrivateClassConst(string $name, $value): ClassConst { return $this->createClassConstant($name, $value, Class_::MODIFIER_PRIVATE); } + /** + * @param mixed $value + */ public function createPublicClassConst(string $name, $value): ClassConst { return $this->createClassConstant($name, $value, Class_::MODIFIER_PUBLIC); @@ -366,6 +372,7 @@ final class NodeFactory } /** + * @param mixed $item * @param string|int|null $key */ private function createArrayItem($item, $key = null): ArrayItem @@ -452,6 +459,9 @@ final class NodeFactory $phpDocInfo->changeVarType($type); } + /** + * @param mixed $value + */ private function createClassConstant(string $name, $value, int $modifier): ClassConst { $value = BuilderHelpers::normalizeValue($value); diff --git a/src/PhpParser/Node/Value/ValueResolver.php b/src/PhpParser/Node/Value/ValueResolver.php index 2766f1e7c54..5390c5426ba 100644 --- a/src/PhpParser/Node/Value/ValueResolver.php +++ b/src/PhpParser/Node/Value/ValueResolver.php @@ -56,6 +56,9 @@ final class ValueResolver $this->nodeTypeResolver = $nodeTypeResolver; } + /** + * @param mixed $value + */ public function isValue(Expr $expr, $value): bool { return $this->getValue($expr) === $value; @@ -188,7 +191,7 @@ final class ValueResolver return $fileInfo->getPathname(); } - private function resolveClassConstFetch(ClassConstFetch $classConstFetch) + private function resolveClassConstFetch(ClassConstFetch $classConstFetch): string { $class = $this->nodeNameResolver->getName($classConstFetch->class); $constant = $this->nodeNameResolver->getName($classConstFetch->name); @@ -219,10 +222,10 @@ final class ValueResolver return $this->constExprEvaluator->evaluateDirectly($classConstNode->consts[0]->value); } - private function processConcat($expr, bool $resolvedClassReference): string + private function processConcat(Concat $concat, bool $resolvedClassReference): string { - return $this->getValue($expr->left, $resolvedClassReference) . $this->getValue( - $expr->right, + return $this->getValue($concat->left, $resolvedClassReference) . $this->getValue( + $concat->right, $resolvedClassReference ); } diff --git a/src/Rector/AbstractRector/NodeFactoryTrait.php b/src/Rector/AbstractRector/NodeFactoryTrait.php index 205a7379d95..4c869574d93 100644 --- a/src/Rector/AbstractRector/NodeFactoryTrait.php +++ b/src/Rector/AbstractRector/NodeFactoryTrait.php @@ -84,6 +84,9 @@ trait NodeFactoryTrait return new ConstFetch(new Name('true')); } + /** + * @param mixed $argument + */ protected function createArg($argument): Arg { return $this->nodeFactory->createArg($argument); diff --git a/src/Rector/AbstractRector/ValueResolverTrait.php b/src/Rector/AbstractRector/ValueResolverTrait.php index 7de7648a69d..3afc21c990b 100644 --- a/src/Rector/AbstractRector/ValueResolverTrait.php +++ b/src/Rector/AbstractRector/ValueResolverTrait.php @@ -26,17 +26,26 @@ trait ValueResolverTrait $this->valueResolver = $valueResolver; } + /** + * @return mixed|mixed[] + */ protected function getValue(Expr $expr, bool $resolvedClassReference = false) { return $this->valueResolver->getValue($expr, $resolvedClassReference); } + /** + * @param mixed $expectedValue + */ protected function isValue(Expr $expr, $expectedValue): bool { return $this->getValue($expr) === $expectedValue; } - protected function isValues(Expr $expr, $expectedValues): bool + /** + * @param mixed[] $expectedValues + */ + protected function isValues(Expr $expr, array $expectedValues): bool { foreach ($expectedValues as $expectedValue) { if ($this->isValue($expr, $expectedValue)) { diff --git a/src/Rector/Argument/ArgumentAdderRector.php b/src/Rector/Argument/ArgumentAdderRector.php index c8cbac7ca50..e5a7fe20582 100644 --- a/src/Rector/Argument/ArgumentAdderRector.php +++ b/src/Rector/Argument/ArgumentAdderRector.php @@ -200,6 +200,9 @@ PHP return ! $this->isInCorrectScope($node, $parameterConfiguration); } + /** + * @param mixed $defaultValue + */ private function addClassMethodParam( ClassMethod $classMethod, string $name, @@ -215,7 +218,7 @@ PHP $classMethod->params[$position] = $param; } - private function processStaticCall(StaticCall $staticCall, int $position, $name): void + private function processStaticCall(StaticCall $staticCall, int $position, string $name): void { if (! $staticCall->class instanceof Name) { return; diff --git a/src/Rector/Argument/ArgumentDefaultValueReplacerRector.php b/src/Rector/Argument/ArgumentDefaultValueReplacerRector.php index 25f51b77365..afe3b27ad9a 100644 --- a/src/Rector/Argument/ArgumentDefaultValueReplacerRector.php +++ b/src/Rector/Argument/ArgumentDefaultValueReplacerRector.php @@ -150,6 +150,9 @@ PHP } } + /** + * @param mixed $value + */ private function normalizeValueToArgument($value): Arg { // class constants → turn string to composite @@ -193,7 +196,7 @@ PHP * @param Arg[] $argumentNodes * @param mixed[] $before */ - private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, int $position, array $before) + private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, int $position, array $before): array { $argumentValues = []; diff --git a/src/Reflection/ClassMethodReflectionHelper.php b/src/Reflection/ClassMethodReflectionHelper.php index d366a6312ba..e16891fc553 100644 --- a/src/Reflection/ClassMethodReflectionHelper.php +++ b/src/Reflection/ClassMethodReflectionHelper.php @@ -27,6 +27,9 @@ final class ClassMethodReflectionHelper $this->phpDocTagsFinder = $phpDocTagsFinder; } + /** + * @return array + */ public function extractTagsFromMethodDockblock(string $class, string $method, string $tag): array { $reflectedMethod = $this->classMethodReflectionFactory->createReflectionMethodIfExists($class, $method); @@ -45,7 +48,9 @@ final class ClassMethodReflectionHelper $classes = []; foreach ($extractedTags as $returnTag) { - $classes[] = Reflection::expandClassName($returnTag, $reflectedMethod->getDeclaringClass()); + /** @var class-string $className */ + $className = Reflection::expandClassName($returnTag, $reflectedMethod->getDeclaringClass()); + $classes[] = $className; } return $classes; diff --git a/src/Testing/Contract/RunnableInterface.php b/src/Testing/Contract/RunnableInterface.php index c1a68e9aec8..fcb58568b05 100644 --- a/src/Testing/Contract/RunnableInterface.php +++ b/src/Testing/Contract/RunnableInterface.php @@ -6,5 +6,8 @@ namespace Rector\Core\Testing\Contract; interface RunnableInterface { + /** + * @return mixed + */ public function run(); } diff --git a/src/Testing/PHPUnit/AbstractGenericRectorTestCase.php b/src/Testing/PHPUnit/AbstractGenericRectorTestCase.php index 6fc02330cb5..f0833e78f9a 100644 --- a/src/Testing/PHPUnit/AbstractGenericRectorTestCase.php +++ b/src/Testing/PHPUnit/AbstractGenericRectorTestCase.php @@ -98,6 +98,9 @@ abstract class AbstractGenericRectorTestCase extends AbstractKernelTestCase return StaticFixtureFinder::yieldDirectory($directory, $suffix); } + /** + * @param mixed $value + */ protected function setParameter(string $name, $value): void { $parameterProvider = self::$container->get(ParameterProvider::class); diff --git a/tests/Configuration/ComposerJsonParserTest.php b/tests/Configuration/ComposerJsonParserTest.php index a59daa9b8e6..b81e64ba963 100644 --- a/tests/Configuration/ComposerJsonParserTest.php +++ b/tests/Configuration/ComposerJsonParserTest.php @@ -14,7 +14,7 @@ final class ComposerJsonParserTest extends AbstractKernelTestCase /** * @dataProvider dataProvider */ - public function test($expectedVersion, string $version): void + public function test(string $expectedVersion, string $version): void { $actualPhpVersion = $this->getComposerJsonPhpVersion($version); diff --git a/tests/PhpParser/Node/Value/ValueResolverTest.php b/tests/PhpParser/Node/Value/ValueResolverTest.php index ba726a0fd98..0eb1a1d0077 100644 --- a/tests/PhpParser/Node/Value/ValueResolverTest.php +++ b/tests/PhpParser/Node/Value/ValueResolverTest.php @@ -28,6 +28,7 @@ final class ValueResolverTest extends AbstractKernelTestCase } /** + * @param mixed $expected * @dataProvider dataProvider */ public function test($expected, Expr $expr): void diff --git a/utils/phpstan-extensions/src/Rule/RequireStringArgumentInMethodCallRule.php b/utils/phpstan-extensions/src/Rule/RequireStringArgumentInMethodCallRule.php index 2f392b6f6c3..a35b7b21b2a 100644 --- a/utils/phpstan-extensions/src/Rule/RequireStringArgumentInMethodCallRule.php +++ b/utils/phpstan-extensions/src/Rule/RequireStringArgumentInMethodCallRule.php @@ -78,7 +78,7 @@ final class RequireStringArgumentInMethodCallRule implements Rule } /** - * @param array $positionsByMethods + * @param array> $positionsByMethods */ private function matchPositions( MethodCall $methodCall, @@ -86,7 +86,7 @@ final class RequireStringArgumentInMethodCallRule implements Rule string $desiredType, array $positionsByMethods, string $methodName - ) { + ): ?array { if (! $this->isNodeVarType($methodCall, $scope, $desiredType)) { return null; } diff --git a/utils/project-validator/src/Command/ValidateFixturesCommand.php b/utils/project-validator/src/Command/ValidateFixtureContentCommand.php similarity index 98% rename from utils/project-validator/src/Command/ValidateFixturesCommand.php rename to utils/project-validator/src/Command/ValidateFixtureContentCommand.php index 03a7a32626c..7284484342e 100644 --- a/utils/project-validator/src/Command/ValidateFixturesCommand.php +++ b/utils/project-validator/src/Command/ValidateFixtureContentCommand.php @@ -16,7 +16,7 @@ use Symplify\PackageBuilder\Console\ShellCode; use Symplify\SmartFileSystem\Finder\FinderSanitizer; use Symplify\SmartFileSystem\SmartFileInfo; -final class ValidateFixturesCommand extends Command +final class ValidateFixtureContentCommand extends Command { /** * @var FinderSanitizer