[CI] Add type-declaration set (#4089)

* [CI] Add type-declaration set

* [rector] [CI] Add type-declaration set

* [cs] [CI] Add type-declaration set

* skip nullable void

* add anonymous parent/interface support

* refactor MultiExceptionCatchRector to use Catch_ over integers

* type fixes

* fix unoin array type override

* remove unused test cases

* drop overcomplicated InlineValidationRulesToArrayDefinitionRector

* skip assign on var

* [rector] skip assign on var

* [cs] skip assign on var

* [rector] [cs] skip assign on var

* skip assign on var

* fixes

* [rector] fixes

* [cs] fixes

Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Tomas Votruba 2020-09-01 19:56:30 +02:00 committed by GitHub
parent 02e703b9b9
commit 7ac228c638
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
312 changed files with 1966 additions and 1225 deletions

View File

@ -32,7 +32,8 @@ jobs:
-
uses: shivammathur/setup-php@v1
with:
php-version: 7.3
# PHP 7.2 is required, so Rector's code is PHP 7.2 compatible even after refactoring
php-version: 7.2
coverage: none
- run: composer install --no-progress --ansi

View File

@ -84,6 +84,9 @@ final class ComposerJsonManipulator
$this->smartFileSystem->dumpFile($composerJsonFile, $this->originalComposerJsonFileContent);
}
/**
* @return mixed[]
*/
private function removeDevKeys(array $json): array
{
foreach (self::KEYS_TO_REMOVE as $keyToRemove) {
@ -94,6 +97,7 @@ final class ComposerJsonManipulator
/**
* Use phpstan/phpstan-src, because the phpstan.phar cannot be packed into rector.phar
* @return mixed[]
*/
private function replacePHPStanWithPHPStanSrc(array $json): array
{
@ -124,6 +128,9 @@ final class ComposerJsonManipulator
return $this->allowDevDependencies($json);
}
/**
* @return mixed[]
*/
private function addDevDependenciesFromPHPStan(array $json, string $phpstanVersion): array
{
// add dev dependencies from PHPStan composer.json
@ -143,6 +150,10 @@ final class ComposerJsonManipulator
return $json;
}
/**
* @param mixed[] $json
* @return mixed[]
*/
private function allowDevDependencies(array $json): array
{
$json['minimum-stability'] = 'dev';
@ -151,6 +162,9 @@ final class ComposerJsonManipulator
return $json;
}
/**
* @return mixed[]
*/
private function readRemoteFileToJson(string $jsonFilePath): array
{
$jsonFileContent = $this->smartFileSystem->readFile($jsonFilePath);

View File

@ -2,14 +2,14 @@
declare(strict_types=1);
use Rector\CodingStyle\Rector\ClassMethod\ReturnArrayClassMethodToYieldRector;
use Rector\PHPUnit\Rector\Class_\AddSeeTestAnnotationRector;
use Rector\PHPUnit\Rector\MethodCall\RemoveExpectAnyFromMockRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(RemoveExpectAnyFromMockRector::class);
$services->set(AddSeeTestAnnotationRector::class);
$services->set(ReturnArrayClassMethodToYieldRector::class);
};

View File

@ -14,14 +14,10 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(ParamTypeDeclarationRector::class);
$services->set(ReturnTypeDeclarationRector::class);
$services->set(PropertyTypeDeclarationRector::class);
$services->set(AddClosureReturnTypeRector::class);
$services->set(AddArrayParamDocTypeRector::class);
$services->set(AddArrayReturnDocTypeRector::class);
};

View File

@ -1,4 +1,4 @@
# All 565 Rectors Overview
# All 564 Rectors Overview
- [Projects](#projects)
---
@ -20,7 +20,7 @@
- [FileSystemRector](#filesystemrector) (1)
- [Generic](#generic) (38)
- [JMS](#jms) (2)
- [Laravel](#laravel) (4)
- [Laravel](#laravel) (3)
- [Legacy](#legacy) (4)
- [MagicDisclosure](#magicdisclosure) (8)
- [MockeryToProphecy](#mockerytoprophecy) (2)
@ -5998,30 +5998,6 @@ Removes JMS\DiExtraBundle\Annotation\Services annotation
## Laravel
### `InlineValidationRulesToArrayDefinitionRector`
- class: [`Rector\Laravel\Rector\ArrayItem\InlineValidationRulesToArrayDefinitionRector`](/../master/rules/laravel/src/Rector/ArrayItem/InlineValidationRulesToArrayDefinitionRector.php)
- [test fixtures](/../master/rules/laravel/tests/Rector/ArrayItem/InlineValidationRulesToArrayDefinitionRector/Fixture)
Transforms inline validation rules to array definition
```diff
use Illuminate\Foundation\Http\FormRequest;
class SomeClass extends FormRequest
{
public function rules(): array
{
return [
- 'someAttribute' => 'required|string|exists:' . SomeModel::class . 'id',
+ 'someAttribute' => ['required', 'string', \Illuminate\Validation\Rule::exists(SomeModel::class, 'id')],
];
}
}
```
<br><br>
### `MinutesToSecondsInCacheRector`
- class: [`Rector\Laravel\Rector\StaticCall\MinutesToSecondsInCacheRector`](/../master/rules/laravel/src/Rector/StaticCall/MinutesToSecondsInCacheRector.php)
@ -14073,7 +14049,7 @@ return function (ContainerConfigurator $containerConfigurator) : void {
$services->set(PropertyAssignToMethodCallRector::class)
->call('configure', [[
PropertyAssignToMethodCallRector::PROPERTY_ASSIGNS_TO_METHODS_CALLS => [
\Rector\SymfonyPhpConfig\inline_value_object(new Rector\Transform\ValueObject\PropertyAssignToMethodCall('SomeClass', 'oldPropertyName', 'oldProperty')), \Rector\SymfonyPhpConfig\inline_value_object(new Rector\Transform\ValueObject\PropertyAssignToMethodCall('SomeClass', 'newMethodName', 'newMethodCall'))]
\Rector\SymfonyPhpConfig\inline_value_object(new Rector\Transform\ValueObject\PropertyAssignToMethodCall('SomeClass', 'oldProperty', 'newMethodCall'))]
]]);
};
```
@ -14576,9 +14552,9 @@ Change @return types and type from static analysis to type declarations if not a
class SomeClass
{
/**
* @return int
*/
- /**
- * @return int
- */
- public function getCount()
+ public function getCount(): int
{

View File

@ -64,7 +64,8 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$parameters->set(Option::EXCLUDE_PATHS, [
'*/Source/*',
'*/Fixture/*', '*/Expected/*',
'*/Fixture/*',
'*/Expected/*',
# generated from /vendor
__DIR__ . '/packages/doctrine-annotation-generated/src/ConstantPreservingDocParser.php',
__DIR__ . '/packages/doctrine-annotation-generated/src/ConstantPreservingAnnotationReader.php',

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->public();
$services->load('Rector\AttributeAwarePhpDoc\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Ast/*']);
->exclude([__DIR__ . '/../src/Ast']);
};

View File

@ -35,7 +35,6 @@ final class AttributeAwareArrayShapeItemNodeFactory implements AttributeNodeAwar
public function create(Node $node, string $docContent): AttributeAwareNodeInterface
{
$node->valueType = $this->attributeAwareNodeFactory->createFromNode($node->valueType, $docContent);
return new AttributeAwareArrayShapeItemNode($node->keyName, $node->optional, $node->valueType, $docContent);
}

View File

@ -36,11 +36,12 @@ final class AttributeAwareGenericTypeNodeFactory implements AttributeNodeAwareFa
{
$node->type = $this->attributeAwareNodeFactory->createFromNode($node->type, $docContent);
foreach ($node->genericTypes as $key => $genericType) {
$node->genericTypes[$key] = $this->attributeAwareNodeFactory->createFromNode($genericType, $docContent);
$genericTypes = [];
foreach ($node->genericTypes as $genericType) {
$genericTypes[] = $this->attributeAwareNodeFactory->createFromNode($genericType, $docContent);
}
return new AttributeAwareGenericTypeNode($node->type, $node->genericTypes);
return new AttributeAwareGenericTypeNode($node->type, $genericTypes);
}
public function setAttributeAwareNodeFactory(AttributeAwareNodeFactory $attributeAwareNodeFactory): void

View File

@ -51,10 +51,7 @@ final class NodeAnnotationReader
$this->constantReferenceIdentifierRestorer = $constantReferenceIdentifierRestorer;
}
/**
* @return object|null
*/
public function readAnnotation(Node $node, string $annotationClass)
public function readAnnotation(Node $node, string $annotationClass): ?object
{
if ($node instanceof Property) {
return $this->readPropertyAnnotation($node, $annotationClass);
@ -71,10 +68,7 @@ final class NodeAnnotationReader
return null;
}
/**
* @return object|null
*/
public function readClassAnnotation(Class_ $class, string $annotationClassName)
public function readClassAnnotation(Class_ $class, string $annotationClassName): ?object
{
$classReflection = $this->createClassReflectionFromNode($class);
@ -90,10 +84,7 @@ final class NodeAnnotationReader
}
}
/**
* @return object|null
*/
public function readPropertyAnnotation(Property $property, string $annotationClassName)
public function readPropertyAnnotation(Property $property, string $annotationClassName): ?object
{
$propertyReflection = $this->createPropertyReflectionFromPropertyNode($property);
if ($propertyReflection === null) {
@ -112,10 +103,7 @@ final class NodeAnnotationReader
}
}
/**
* @return object|null
*/
private function readMethodAnnotation(ClassMethod $classMethod, string $annotationClassName)
private function readMethodAnnotation(ClassMethod $classMethod, string $annotationClassName): ?object
{
/** @var string $className */
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Rector\BetterPhpDocParser\Attributes\Attribute;
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
final class Attribute
{
@ -17,7 +17,7 @@ final class Attribute
* @experiment
* @var string
*/
public const START_END = StartEndValueObject::class;
public const START_END = StartAndEnd::class;
/**
* @var string

View File

@ -21,7 +21,6 @@ use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareParamTagValueNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocTagNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareReturnTagValueNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareVarTagValueNode;
use Rector\BetterPhpDocParser\Annotation\StaticAnnotationNaming;
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\SpacelessPhpDocTagNode;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
@ -147,7 +146,7 @@ final class PhpDocInfo
return count($this->tokens);
}
public function getVarTagValue(): ?AttributeAwareVarTagValueNode
public function getVarTagValue(): ?VarTagValueNode
{
return $this->phpDocNode->getVarTagValues()[0] ?? null;
}
@ -166,7 +165,11 @@ final class PhpDocInfo
return $tag->name === $name;
});
return array_values($tags);
// @todo add dynamic function type resolver to PHPStan, the same type on input is on output
$tags = array_values($tags);
/** @var PhpDocTagNode[]|AttributeAwareNodeInterface[] $tags */
return $tags;
}
public function getParamType(string $name): Type

View File

@ -15,7 +15,7 @@ use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
use Rector\BetterPhpDocParser\Contract\PhpDocNodeFactoryInterface;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocRemover;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
use Rector\Core\Configuration\CurrentNodeProvider;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\StaticTypeMapper\StaticTypeMapper;
@ -129,11 +129,11 @@ final class PhpDocInfoFactory
/** @var AttributeAwareNodeInterface $lastChildNode */
$lastChildNode = array_pop($phpDocChildNodes);
/** @var StartEndValueObject $startEndValueObject */
$startEndValueObject = $lastChildNode->getAttribute(Attribute::START_END);
/** @var StartAndEnd $startAndEnd */
$startAndEnd = $lastChildNode->getAttribute(Attribute::START_END);
if ($startEndValueObject !== null) {
$attributeAwarePhpDocNode->setAttribute(Attribute::LAST_TOKEN_POSITION, $startEndValueObject->getEnd());
if ($startAndEnd !== null) {
$attributeAwarePhpDocNode->setAttribute(Attribute::LAST_TOKEN_POSITION, $startAndEnd->getEnd());
}
}

View File

@ -98,8 +98,8 @@ final class PhpDocTypeChanger
// override existing type
$newPHPStanPhpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType);
$currentReturnTagValueNode = $phpDocInfo->getReturnTagValue();
if ($currentReturnTagValueNode !== null) {
// only change type
$currentReturnTagValueNode->type = $newPHPStanPhpDocType;

View File

@ -21,7 +21,7 @@ final class IndexTagValueNode extends AbstractDoctrineTagValueNode implements Ta
parent::__construct($items, $content);
}
public function getTag(): ?string
public function getTag(): string
{
return $this->tag ?: $this->getShortName();
}

View File

@ -21,7 +21,7 @@ final class UniqueConstraintTagValueNode extends AbstractDoctrineTagValueNode im
parent::__construct($items, $content);
}
public function getTag(): ?string
public function getTag(): string
{
return $this->tag ?: $this->getShortName();
}

View File

@ -35,7 +35,7 @@ final class JoinColumnTagValueNode extends AbstractDoctrineTagValueNode implemen
return $this->items['nullable'];
}
public function getTag(): ?string
public function getTag(): string
{
return $this->tag ?: $this->shortName;
}

View File

@ -103,10 +103,9 @@ final class JoinTablePhpDocNodeFactory extends AbstractPhpDocNodeFactory impleme
}
/**
* @param JoinTable $joinTable
* @return JoinColumnTagValueNode[]
*/
private function createJoinColumnTagValues(string $annotationContent, $joinTable, string $type): array
private function createJoinColumnTagValues(string $annotationContent, JoinTable $joinTable, string $type): array
{
$joinColumnContents = $this->matchJoinColumnContents($annotationContent);

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory;
use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\ParserException;
@ -63,10 +62,10 @@ final class ParamPhpDocNodeFactory
{
try {
$tokenIterator->pushSavePoint();
$tagValue = $this->parseParamTagValue($tokenIterator);
$attributeAwareParamTagValueNode = $this->parseParamTagValue($tokenIterator);
$tokenIterator->dropSavePoint();
return $tagValue;
return $attributeAwareParamTagValueNode;
} catch (ParserException $parserException) {
$tokenIterator->rollback();
$description = $this->privatesCaller->callPrivateMethod(
@ -87,7 +86,7 @@ final class ParamPhpDocNodeFactory
/**
* Override of parent private method to allow reference: https://github.com/rectorphp/rector/pull/1735
*/
private function parseParamTagValue(TokenIterator $tokenIterator): ParamTagValueNode
private function parseParamTagValue(TokenIterator $tokenIterator): AttributeAwareParamTagValueNode
{
$originalTokenIterator = clone $tokenIterator;
$annotationContent = $this->annotationContentResolver->resolveFromTokenIterator($originalTokenIterator);

View File

@ -23,7 +23,7 @@ use Rector\BetterPhpDocParser\Contract\SpecificPhpDocNodeFactoryInterface;
use Rector\BetterPhpDocParser\PhpDocNodeFactory\ParamPhpDocNodeFactory;
use Rector\BetterPhpDocParser\PhpDocNodeFactory\PHPUnitDataProviderDocNodeFactory;
use Rector\BetterPhpDocParser\Printer\MultilineSpaceFormatPreserver;
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
use Rector\Core\Configuration\CurrentNodeProvider;
use Rector\Core\Exception\ShouldNotHappenException;
use Symplify\PackageBuilder\Reflection\PrivatesAccessor;
@ -238,10 +238,10 @@ final class BetterPhpDocParser extends PhpDocParser
$tokenEnd = $this->resolveTokenEnd($tokenIterator);
$startEndValueObject = new StartEndValueObject($tokenStart, $tokenEnd);
$startAndEnd = new StartAndEnd($tokenStart, $tokenEnd);
$attributeAwareNode = $this->attributeAwareNodeFactory->createFromNode($phpDocNode, $docContent);
$attributeAwareNode->setAttribute(Attribute::START_END, $startEndValueObject);
$attributeAwareNode->setAttribute(Attribute::START_END, $startAndEnd);
$possibleMultilineText = $this->multilineSpaceFormatPreserver->resolveCurrentPhpDocNodeText(
$attributeAwareNode

View File

@ -6,7 +6,7 @@ namespace Rector\BetterPhpDocParser\Printer;
use Nette\Utils\Strings;
use PHPStan\PhpDocParser\Ast\Node;
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
final class OriginalSpacingRestorer
{
@ -27,9 +27,9 @@ final class OriginalSpacingRestorer
Node $node,
string $nodeOutput,
array $tokens,
StartEndValueObject $startEndValueObject
StartAndEnd $startAndEnd
): string {
$oldWhitespaces = $this->whitespaceDetector->detectOldWhitespaces($node, $tokens, $startEndValueObject);
$oldWhitespaces = $this->whitespaceDetector->detectOldWhitespaces($node, $tokens, $startAndEnd);
// no original whitespaces, return
if ($oldWhitespaces === []) {

View File

@ -18,7 +18,7 @@ use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocTagNode;
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
use Rector\Core\Exception\ShouldNotHappenException;
/**
@ -47,7 +47,7 @@ final class PhpDocInfoPrinter
private $tokens = [];
/**
* @var StartEndValueObject[]
* @var StartAndEnd[]
*/
private $removedNodePositions = [];
@ -170,45 +170,45 @@ final class PhpDocInfoPrinter
private function printNode(
AttributeAwareNodeInterface $attributeAwareNode,
?StartEndValueObject $startEndValueObject = null,
?StartAndEnd $startAndEnd = null,
int $key = 0,
int $nodeCount = 0
): string {
$output = '';
/** @var StartEndValueObject|null $startEndValueObject */
$startEndValueObject = $attributeAwareNode->getAttribute(Attribute::START_END) ?: $startEndValueObject;
/** @var StartAndEnd|null $startAndEnd */
$startAndEnd = $attributeAwareNode->getAttribute(Attribute::START_END) ?: $startAndEnd;
$attributeAwareNode = $this->multilineSpaceFormatPreserver->fixMultilineDescriptions($attributeAwareNode);
if ($startEndValueObject !== null) {
if ($startAndEnd !== null) {
$isLastToken = ($nodeCount === $key);
$output = $this->addTokensFromTo(
$output,
$this->currentTokenPosition,
$startEndValueObject->getStart(),
$startAndEnd->getStart(),
$isLastToken
);
$this->currentTokenPosition = $startEndValueObject->getEnd();
$this->currentTokenPosition = $startAndEnd->getEnd();
}
if ($attributeAwareNode instanceof PhpDocTagNode) {
if ($startEndValueObject !== null) {
return $this->printPhpDocTagNode($attributeAwareNode, $startEndValueObject, $output);
if ($startAndEnd !== null) {
return $this->printPhpDocTagNode($attributeAwareNode, $startAndEnd, $output);
}
return $output . self::NEWLINE_ASTERISK . $this->printAttributeWithAsterisk($attributeAwareNode);
}
if (! $attributeAwareNode instanceof PhpDocTextNode && ! $attributeAwareNode instanceof GenericTagValueNode && $startEndValueObject) {
if (! $attributeAwareNode instanceof PhpDocTextNode && ! $attributeAwareNode instanceof GenericTagValueNode && $startAndEnd) {
$nodeContent = (string) $attributeAwareNode;
return $this->originalSpacingRestorer->restoreInOutputWithTokensStartAndEndPosition(
$attributeAwareNode,
$nodeContent,
$this->tokens,
$startEndValueObject
$startAndEnd
);
}
@ -257,7 +257,7 @@ final class PhpDocInfoPrinter
*/
private function printPhpDocTagNode(
PhpDocTagNode $phpDocTagNode,
StartEndValueObject $startEndValueObject,
StartAndEnd $startAndEnd,
string $output
): string {
$output .= $phpDocTagNode->name;
@ -267,7 +267,7 @@ final class PhpDocInfoPrinter
throw new ShouldNotHappenException();
}
$nodeOutput = $this->printNode($phpDocTagNodeValue, $startEndValueObject);
$nodeOutput = $this->printNode($phpDocTagNodeValue, $startAndEnd);
$tagSpaceSeparator = $this->resolveTagSpaceSeparator($phpDocTagNode);
// space is handled by $tagSpaceSeparator
@ -301,7 +301,7 @@ final class PhpDocInfoPrinter
}
/**
* @return StartEndValueObject[]
* @return StartAndEnd[]
*/
private function getRemovedNodesPositions(): array
{
@ -316,7 +316,7 @@ final class PhpDocInfoPrinter
);
foreach ($removedNodes as $removedNode) {
/** @var StartEndValueObject $removedPhpDocNodeInfo */
/** @var StartAndEnd $removedPhpDocNodeInfo */
$removedPhpDocNodeInfo = $removedNode->getAttribute(Attribute::START_END);
// change start position to start of the line, so the whole line is removed
@ -325,10 +325,7 @@ final class PhpDocInfoPrinter
--$seekPosition;
}
$this->removedNodePositions[] = new StartEndValueObject(
$seekPosition - 1,
$removedPhpDocNodeInfo->getEnd()
);
$this->removedNodePositions[] = new StartAndEnd($seekPosition - 1, $removedPhpDocNodeInfo->getEnd());
}
return $this->removedNodePositions;

View File

@ -10,7 +10,7 @@ use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Lexer\Lexer;
use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineTagNodeInterface;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\ShortNameAwareTagInterface;
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
final class WhitespaceDetector
{
@ -18,18 +18,18 @@ final class WhitespaceDetector
* @param mixed[] $tokens
* @return string[]
*/
public function detectOldWhitespaces(Node $node, array $tokens, StartEndValueObject $startEndValueObject): array
public function detectOldWhitespaces(Node $node, array $tokens, StartAndEnd $startAndEnd): array
{
$oldWhitespaces = [];
$start = $startEndValueObject->getStart();
$start = $startAndEnd->getStart();
// this is needed, because of 1 token taken from tokens and added annotation name: "ORM" + "\X" → "ORM\X"
// todo, this might be needed to be dynamic, based on taken tokens count (some Collector?)
if ($node instanceof DoctrineTagNodeInterface) {
--$start;
}
for ($i = $start; $i < $startEndValueObject->getEnd(); ++$i) {
for ($i = $start; $i < $startAndEnd->getEnd(); ++$i) {
/** @var string $tokenValue */
$tokenValue = $tokens[$i][0];

View File

@ -4,7 +4,9 @@ declare(strict_types=1);
namespace Rector\BetterPhpDocParser\ValueObject;
final class StartEndValueObject
use Rector\Core\Exception\ShouldNotHappenException;
final class StartAndEnd
{
/**
* @var int
@ -18,6 +20,10 @@ final class StartEndValueObject
public function __construct(int $start, int $end)
{
if ($end < $start) {
throw new ShouldNotHappenException();
}
$this->start = $start;
$this->end = $end;
}

View File

@ -13,6 +13,9 @@ use Rector\BetterPhpDocParser\PhpDocNode\Symfony\SymfonyRouteTagValueNode;
use Rector\BetterPhpDocParser\Utils\ArrayItemStaticHelper;
use Rector\BetterPhpDocParser\ValueObject\TagValueNodeConfiguration;
/**
* @see \Rector\BetterPhpDocParser\Tests\ValueObjectFactory\TagValueNodeConfigurationFactoryTest
*/
final class TagValueNodeConfigurationFactory
{
public function createFromOriginalContent(

View File

@ -16,6 +16,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
/**
* Inspired by https://github.com/symplify/easy-coding-standard/blob/e598ab54686e416788f28fcfe007fd08e0f371d9/packages/changed-files-detector/src/FileHashComputer.php
* @see \Rector\Caching\Tests\Config\FileHashComputerTest
*/
final class FileHashComputer
{

View File

@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->public();
$services->load('Rector\ChangesReporting\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Contract/*', __DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/Contract', __DIR__ . '/../src/ValueObject']);
};

View File

@ -36,7 +36,7 @@ final class RectorChangeCollector
{
return array_filter(
$this->rectorWithFileAndLineChanges,
function (RectorWithFileAndLineChange $rectorWithFileAndLineChange) use ($smartFileInfo) {
function (RectorWithFileAndLineChange $rectorWithFileAndLineChange) use ($smartFileInfo): bool {
return $rectorWithFileAndLineChange->getRealPath() === $smartFileInfo->getRealPath();
}
);

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->public();
$services->load('Rector\DynamicTypeAnalysis\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector/*']);
->exclude([__DIR__ . '/../src/Rector']);
};

View File

@ -9,6 +9,7 @@ use Rector\DynamicTypeAnalysis\ProbeStorage\StaticFileSystemProbeStorage;
/**
* @see https://stackoverflow.com/a/39525458/1348344
* @see \Rector\DynamicTypeAnalysis\Tests\Probe\TypeStaticProbeTest
*/
final class TypeStaticProbe
{

View File

@ -74,7 +74,7 @@ final class PropertyUsageAnalyzer
$isPropertyFetched = (bool) $this->betterNodeFinder->findFirst(
(array) $childClass->stmts,
function (Node $node) use ($propertyName) {
function (Node $node) use ($propertyName): bool {
return $this->isLocalPropertyFetchNamed($node, $propertyName);
}
);

View File

@ -16,5 +16,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autowire();
$services->load('Rector\FileSystemRector\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector/*']);
->exclude([__DIR__ . '/../src/Rector']);
};

View File

@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autoconfigure();
$services->load('Rector\NodeCollector\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/ValueObject']);
};

View File

@ -196,7 +196,7 @@ final class ParsedFunctionLikeNodeCollector
{
$calls = Arrays::flatten($this->methodsCallsByTypeAndMethod);
return array_filter($calls, function (Node $node) {
return array_filter($calls, function (Node $node): bool {
return $node instanceof MethodCall;
});
}

View File

@ -14,6 +14,7 @@ use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Trait_;
@ -58,11 +59,6 @@ final class ParsedNodeCollector
*/
private $constantsByType = [];
/**
* @var array<array<TNodeType>>
*/
private $simpleParsedNodesByType = [];
/**
* @var Interface_[]
*/
@ -73,6 +69,26 @@ final class ParsedNodeCollector
*/
private $traits = [];
/**
* @var StaticCall[]
*/
private $staticCalls = [];
/**
* @var New_[]
*/
private $news = [];
/**
* @var Param[]
*/
private $params = [];
/**
* @var ClassConstFetch[]
*/
private $classConstFetches = [];
/**
* @var NodeNameResolver
*/
@ -83,15 +99,6 @@ final class ParsedNodeCollector
$this->nodeNameResolver = $nodeNameResolver;
}
/**
* @param class-string<TNodeType> $type
* @return array<TNodeType>
*/
public function getNodesByType(string $type): array
{
return $this->simpleParsedNodesByType[$type] ?? [];
}
/**
* @return Interface_[]
*/
@ -160,25 +167,13 @@ final class ParsedNodeCollector
public function collect(Node $node): void
{
$nodeClass = get_class($node);
if ($node instanceof Class_) {
$this->addClass($node);
return;
}
if ($node instanceof Interface_ || $node instanceof Trait_) {
$name = $this->nodeNameResolver->getName($node);
if ($name === null) {
throw new ShouldNotHappenException();
}
if ($node instanceof Interface_) {
$this->interfaces[$name] = $node;
} elseif ($node instanceof Trait_) {
$this->traits[$name] = $node;
}
$this->collectInterfaceOrTrait($node);
return;
}
@ -187,28 +182,42 @@ final class ParsedNodeCollector
return;
}
// simple collect
$this->simpleParsedNodesByType[$nodeClass][] = $node;
if ($node instanceof StaticCall) {
$this->staticCalls[] = $node;
return;
}
if ($node instanceof New_) {
$this->news[] = $node;
return;
}
if ($node instanceof Param) {
$this->params[] = $node;
return;
}
if ($node instanceof ClassConstFetch) {
$this->classConstFetches[] = $node;
}
}
/**
* @return New_[]
*/
public function findNewNodesByClass(string $className): array
public function findNewsByClass(string $className): array
{
$newNodesByClass = [];
$newsByClass = [];
$news = $this->getNodesByType(New_::class);
foreach ($news as $new) {
foreach ($this->news as $new) {
if (! $this->nodeNameResolver->isName($new->class, $className)) {
continue;
}
$newNodesByClass[] = $new;
$newsByClass[] = $new;
}
return $newNodesByClass;
return $newsByClass;
}
public function findClassConstantByClassConstFetch(ClassConstFetch $classConstFetch): ?ClassConst
@ -229,6 +238,38 @@ final class ParsedNodeCollector
return $this->findClassConstant($class, $constantName);
}
/**
* @return ClassConstFetch[]
*/
public function getClassConstFetches(): array
{
return $this->classConstFetches;
}
/**
* @return Param[]
*/
public function getParams(): array
{
return $this->params;
}
/**
* @return New_[]
*/
public function getNews(): array
{
return $this->news;
}
/**
* @return StaticCall[]
*/
public function getStaticCalls(): array
{
return $this->staticCalls;
}
private function addClass(Class_ $class): void
{
if ($this->isClassAnonymous($class)) {
@ -243,6 +284,23 @@ final class ParsedNodeCollector
$this->classes[$className] = $class;
}
/**
* @param Interface_|Trait_ $classLike
*/
private function collectInterfaceOrTrait(ClassLike $classLike): void
{
$name = $this->nodeNameResolver->getName($classLike);
if ($name === null) {
throw new ShouldNotHappenException();
}
if ($classLike instanceof Interface_) {
$this->interfaces[$name] = $classLike;
} elseif ($classLike instanceof Trait_) {
$this->traits[$name] = $classLike;
}
}
private function addClassConstant(ClassConst $classConst): void
{
$className = $classConst->getAttribute(AttributeKey::CLASS_NAME);

View File

@ -45,9 +45,6 @@ final class NodeCollectorNodeVisitor extends NodeVisitorAbstract
$this->parsedClassConstFetchNodeCollector = $parsedClassConstFetchNodeCollector;
}
/**
* @return int|Node|void|null
*/
public function enterNode(Node $node)
{
if ($this->parsedNodeCollector->isCollectableNode($node)) {
@ -57,5 +54,7 @@ final class NodeCollectorNodeVisitor extends NodeVisitorAbstract
$this->parsedFunctionLikeNodeCollector->collect($node);
$this->parsedPropertyFetchNodeCollector->collect($node);
$this->parsedClassConstFetchNodeCollector->collect($node);
return null;
}
}

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autowire();
$services->load('Rector\NodeNameResolver\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Contract/*']);
->exclude([__DIR__ . '/../src/Contract']);
};

View File

@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autoconfigure();
$services->load('Rector\NodeNestingScope\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/ValueObject']);
};

View File

@ -31,7 +31,7 @@ final class ScopeAwareNodeFinder
*/
public function findParentType(Node $node, array $allowedTypes): ?Node
{
$callable = function (Node $node) use ($allowedTypes) {
$callable = function (Node $node) use ($allowedTypes): bool {
foreach ($allowedTypes as $allowedType) {
if (! is_a($node, $allowedType)) {
continue;
@ -58,7 +58,7 @@ final class ScopeAwareNodeFinder
$foundNode = $this->betterNodeFinder->findFirstPrevious($node, function (Node $node) use (
$callable,
$parentNestingBreakTypes
) {
): bool {
if ($callable($node)) {
return true;
}

View File

@ -23,7 +23,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autowire();
$services->load('Rector\NodeTypeResolver\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Contract/*', __DIR__ . '/../src/PHPStan/TypeExtension/*']);
->exclude([__DIR__ . '/../src/Contract', __DIR__ . '/../src/PHPStan/TypeExtension']);
$services->set(TypeAnalyzer::class);

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\NodeTypeResolver;
use PhpParser\Node;
use PhpParser\Node\Stmt;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\CloningVisitor;
use PhpParser\NodeVisitor\NameResolver;
@ -154,8 +155,8 @@ final class NodeScopeAndMetadataDecorator
}
/**
* @param Node[] $nodes
* @return Node[]
* @param Stmt[] $nodes
* @return Stmt[]
*/
public function decorateNodesFromString(array $nodes): array
{

View File

@ -12,6 +12,7 @@ use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\ArrayType;
@ -32,6 +33,8 @@ use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeCorrector\ParentClassesInterfacesAndUsedTraitsCorrector;
use Rector\NodeTypeResolver\TypeAnalyzer\ArrayTypeAnalyzer;
use Rector\PHPStan\Type\FullyQualifiedObjectType;
use Rector\PHPStan\TypeFactoryStaticHelper;
use Rector\PHPStanStaticTypeMapper\Utils\TypeUnwrapper;
use Rector\TypeDeclaration\PHPStan\Type\ObjectTypeSpecifier;
@ -175,7 +178,7 @@ final class NodeTypeResolver
}
if ($node instanceof New_ && $this->classNodeAnalyzer->isAnonymousClass($node->class)) {
return new ObjectWithoutClassType();
return $this->resolveAnonymousClassType($node);
}
$staticType = $nodeScope->getType($node);
@ -364,6 +367,38 @@ final class NodeTypeResolver
return new ArrayType(new MixedType(), new MixedType());
}
private function resolveAnonymousClassType(New_ $new): ObjectWithoutClassType
{
if (! $new->class instanceof Class_) {
return new ObjectWithoutClassType();
}
$types = [];
/** @var Class_ $class */
$class = $new->class;
if ($class->extends !== null) {
$parentClass = (string) $class->extends;
$types[] = new FullyQualifiedObjectType($parentClass);
}
foreach ((array) $class->implements as $implement) {
$parentClass = (string) $implement;
$types[] = new FullyQualifiedObjectType($parentClass);
}
if (count($types) > 1) {
$unionType = TypeFactoryStaticHelper::createUnionObjectType($types);
return new ObjectWithoutClassType($unionType);
}
if (count($types) === 1) {
return new ObjectWithoutClassType($types[0]);
}
return new ObjectWithoutClassType();
}
private function resolveByNodeTypeResolvers(Node $node): ?Type
{
foreach ($this->nodeTypeResolvers as $nodeClass => $nodeTypeResolver) {

View File

@ -15,6 +15,9 @@ use PhpParser\NodeVisitorAbstract;
use Rector\CodingStyle\Naming\ClassNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitor\FunctionMethodAndClassNodeVisitorTest
*/
final class FunctionMethodAndClassNodeVisitor extends NodeVisitorAbstract
{
/**

View File

@ -13,6 +13,7 @@ use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\PHPStan\Type\AliasedObjectType;
use Rector\PHPStan\Type\ShortenedObjectType;
use Rector\TypeDeclaration\TypeNormalizer;
final class TypeComparator
{
@ -21,9 +22,15 @@ final class TypeComparator
*/
private $typeHasher;
public function __construct(TypeHasher $typeHasher)
/**
* @var TypeNormalizer
*/
private $typeNormalizer;
public function __construct(TypeHasher $typeHasher, TypeNormalizer $typeNormalizer)
{
$this->typeHasher = $typeHasher;
$this->typeNormalizer = $typeNormalizer;
}
public function areTypesEquals(Type $firstType, Type $secondType): bool
@ -37,6 +44,9 @@ final class TypeComparator
return true;
}
$firstType = $this->typeNormalizer->normalizeArrayOfUnionToUnionArray($firstType);
$secondType = $this->typeNormalizer->normalizeArrayOfUnionToUnionArray($secondType);
if ($this->typeHasher->areTypesEqual($firstType, $secondType)) {
return true;
}

View File

@ -53,9 +53,7 @@ final class TypeHasher
}
if ($type instanceof UnionType) {
$types = $type->getTypes();
sort($types);
$type = new UnionType($types);
return $this->createUnionTypeHash($type);
}
return $this->phpStanStaticTypeMapper->mapToDocString($type);
@ -65,4 +63,17 @@ final class TypeHasher
{
return $this->createTypeHash($firstType) === $this->createTypeHash($secondType);
}
private function createUnionTypeHash(UnionType $unionType): string
{
$unionedTypesHashes = [];
foreach ($unionType->getTypes() as $unionedType) {
$unionedTypesHashes[] = $this->createTypeHash($unionedType);
}
sort($unionedTypesHashes);
$unionedTypesHashes = array_unique($unionedTypesHashes);
return implode('|', $unionedTypesHashes);
}
}

View File

@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autoconfigure();
$services->load('Rector\PhpAttribute\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Contract/*', __DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/Contract', __DIR__ . '/../src/ValueObject']);
};

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autowire();
$services->load('Rector\PHPStanStaticTypeMapper\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/ValueObject']);
};

View File

@ -25,6 +25,9 @@ use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\TypeDeclaration\TypeNormalizer;
/**
* @see \Rector\PHPStanStaticTypeMapper\Tests\TypeMapper\ArrayTypeMapperTest
*/
final class ArrayTypeMapper implements TypeMapperInterface
{
/**

View File

@ -13,15 +13,22 @@ use PHPStan\Type\VerbosityLevel;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareIdentifierTypeNode;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Contract\PHPStanStaticTypeMapperAwareInterface;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
final class ObjectWithoutClassTypeMapper implements TypeMapperInterface
final class ObjectWithoutClassTypeMapper implements TypeMapperInterface, PHPStanStaticTypeMapperAwareInterface
{
/**
* @var PhpVersionProvider
*/
private $phpVersionProvider;
/**
* @var PHPStanStaticTypeMapper
*/
private $phpStanStaticTypeMapper;
public function __construct(PhpVersionProvider $phpVersionProvider)
{
$this->phpVersionProvider = $phpVersionProvider;
@ -45,6 +52,11 @@ final class ObjectWithoutClassTypeMapper implements TypeMapperInterface
*/
public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node
{
$subtractedType = $type->getSubtractedType();
if ($subtractedType !== null) {
return $this->phpStanStaticTypeMapper->mapToPhpParserNode($subtractedType);
}
if (! $this->phpVersionProvider->isAtLeast(PhpVersionFeature::OBJECT_TYPE)) {
return null;
}
@ -56,4 +68,9 @@ final class ObjectWithoutClassTypeMapper implements TypeMapperInterface
{
return $type->describe(VerbosityLevel::typeOnly());
}
public function setPHPStanStaticTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;
}
}

View File

@ -16,6 +16,9 @@ use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
/**
* @see \Rector\NodeTypeResolver\Tests\StaticTypeMapper\StaticTypeMapperTest
*/
final class StaticTypeMapper implements TypeMapperInterface
{
/**

View File

@ -16,6 +16,7 @@ use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
use PHPStan\Type\VoidType;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareUnionTypeNode;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Php\PhpVersionProvider;
@ -109,6 +110,11 @@ final class UnionTypeMapper implements TypeMapperInterface
return $this->matchTypeForUnionedObjectTypes($type);
}
// void cannot be nullable
if ($nullabledType instanceof VoidType) {
return null;
}
$nullabledTypeNode = $this->phpStanStaticTypeMapper->mapToPhpParserNode($nullabledType);
if ($nullabledTypeNode === null) {
return null;

View File

@ -88,7 +88,7 @@ final class UseNodesToAddCollector implements NodeCollectorInterface
}
/**
* @return FullyQualifiedObjectType[]|AliasedObjectType[]
* @return AliasedObjectType[]|FullyQualifiedObjectType[]
*/
public function getUseImportTypesByNode(Node $node): array
{
@ -156,7 +156,7 @@ final class UseNodesToAddCollector implements NodeCollectorInterface
}
/**
* @return FullyQualifiedObjectType[]|AliasedObjectType[]
* @return AliasedObjectType[]|FullyQualifiedObjectType[]
*/
public function getObjectImportsByFileInfo(SmartFileInfo $smartFileInfo): array
{

View File

@ -37,7 +37,7 @@ final class NodeAddingPostRector extends AbstractPostRector
}
/**
* @return mixed[]|Node
* @return array<int|string, Node>|Node
*/
public function leaveNode(Node $node)
{

View File

@ -59,7 +59,7 @@ final class RectorRecipe
private $nodeTypes = [];
/**
* @var mixed[]
* @var string[]
*/
private $resources = [];
@ -123,6 +123,9 @@ final class RectorRecipe
return $this->name;
}
/**
* @return class-string[]
*/
public function getNodeTypes(): array
{
return $this->nodeTypes;
@ -143,6 +146,9 @@ final class RectorRecipe
return $this->codeAfter;
}
/**
* @return string[]
*/
public function getResources(): array
{
return $this->resources;

View File

@ -22,6 +22,9 @@ final class __Name__Test extends AbstractRectorTestCase
yield [__DIR__ . '/Fixture/fixture.php.inc', '__ExtraFileName__', __DIR__ . '/Source/extra_file.php'];
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [

View File

@ -21,6 +21,9 @@ final class __Name__Test extends AbstractRectorTestCase
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [

View File

@ -21,6 +21,9 @@ final class WhateverRectorTest extends AbstractRectorTestCase
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [

View File

@ -21,6 +21,9 @@ final class WhateverRectorTest extends AbstractRectorTestCase
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [

View File

@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autoconfigure();
$services->load('Rector\Reporting\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/ValueObject']);
};

View File

@ -56,7 +56,7 @@ final class PrintReportCollectorEventSubscriber implements EventSubscriberInterf
}
/**
* @return string[]
* @return array<string, string>
*/
public static function getSubscribedEvents(): array
{

View File

@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autoconfigure();
$services->load('Rector\Set\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/ValueObject']);
};

View File

@ -31,7 +31,7 @@ final class NameScopeFactory
/**
* @param Use_[] $useNodes
* @return string[]
* @return array<string, string>
*/
private function resolveUseNamesByAlias(array $useNodes): array
{
@ -47,7 +47,10 @@ final class NameScopeFactory
throw new ShouldNotHappenException();
}
$useNamesByAlias[$aliasName] = $useName;
// uses must be lowercase, as PHPStan lowercases it
$lowercasedAliasName = strtolower($aliasName);
$useNamesByAlias[$lowercasedAliasName] = $useName;
}
}

View File

@ -14,6 +14,9 @@ use PHPStan\Type\Type;
use Rector\StaticTypeMapper\Contract\PhpDocParser\PhpDocTypeMapperInterface;
use Rector\StaticTypeMapper\PhpDoc\PhpDocTypeMapper;
/**
* @see \Rector\PHPStanStaticTypeMapper\Tests\TypeMapper\ArrayTypeMapperTest
*/
final class ArrayTypeMapper implements PhpDocTypeMapperInterface
{
/**

View File

@ -25,6 +25,7 @@ use Rector\StaticTypeMapper\PHPStan\NameScopeFactory;
/**
* Maps PhpParser <=> PHPStan <=> PHPStan doc <=> string type nodes between all possible formats
* @see \Rector\NodeTypeResolver\Tests\StaticTypeMapper\StaticTypeMapperTest
*/
final class StaticTypeMapper
{

View File

@ -87,7 +87,7 @@ abstract class AbstractNodeVendorLockResolver
}
/**
* @return string[]
* @return class-string[]
*/
protected function getChildrenClassesByClass(Class_ $class): array
{

View File

@ -2,30 +2,14 @@
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use Rector\CodingStyle\Rector\ClassMethod\ReturnArrayClassMethodToYieldRector;
use Rector\CodingStyle\Rector\String_\SplitStringClassConstantToClassConstFetchRector;
use Rector\CodingStyle\ValueObject\MethodToYield;
use Rector\Core\Configuration\Option;
use Rector\DeadCode\Rector\ClassConst\RemoveUnusedClassConstantRector;
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
use Rector\Set\ValueObject\SetList;
use function Rector\SymfonyPhpConfig\inline_value_objects;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(ReturnArrayClassMethodToYieldRector::class)
->call('configure', [[
ReturnArrayClassMethodToYieldRector::METHODS_TO_YIELDS => inline_value_objects([
new MethodToYield(TestCase::class, 'provideData'),
new MethodToYield(TestCase::class, 'provideData*'),
new MethodToYield(TestCase::class, 'dataProvider'),
new MethodToYield(TestCase::class, 'dataProvider*'),
]),
]]);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SETS, [
@ -38,6 +22,8 @@ return static function (ContainerConfigurator $containerConfigurator): void {
SetList::NAMING,
SetList::ORDER,
SetList::DEFLUENT,
SetList::TYPE_DECLARATION,
SetList::PHPUNIT_CODE_QUALITY,
]);
$parameters->set(Option::PATHS, [
@ -72,4 +58,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
// false positives on constants used in rector-ci.php
RemoveUnusedClassConstantRector::class,
]);
# so Rector code is still PHP 7.2 compatible
$parameters->set(Option::PHP_VERSION_FEATURES, '7.2');
};

View File

@ -0,0 +1,431 @@
includes:
- utils/phpstan-extensions/config/phpstan-extensions.neon
- vendor/slam/phpstan-extensions/conf/slam-rules.neon
- vendor/symplify/phpstan-extensions/config/config.neon
- vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon
# see https://github.com/symplify/coding-standard
- vendor/symplify/coding-standard/config/symplify-rules.neon
rules:
# should be fixed in next part of symplify CS release
- Symplify\CodingStandard\Rules\NoClassWithStaticMethodWithoutStaticNameRule
- Symplify\CodingStandard\Rules\SeeAnnotationToTestRule
- Symplify\CodingStandard\Rules\NoReferenceRule
parameters:
level: max
# see https://github.com/symplify/coding-standard
symplify:
# this rule prevents bug in phar like these: https://github.com/rectorphp/rector/pull/3692/files
string_arg_by_method_by_type:
Rector\Core\Rector\AbstractRector:
isObjectType: [1]
max_cognitive_complexity: 9 # default: 8
max_class_cognitive_complexity: 50
parent_classes:
- Rector
required_see_types:
- PHPStan\Rules\Rule
- Rector\Core\Rector\AbstractRector
- Rector\FileSystemRector\Rector\AbstractFileSystemRector
old_to_preffered_classes:
# prevent PHPStorm autocomplete mess
'Symfony\Component\DependencyInjection\Variable': 'PhpParser\Node\Expr\Variable'
'phpDocumentor\Reflection\Types\Expression': 'PhpParser\Node\Stmt\Expression'
'phpDocumentor\Reflection\DocBlock\Tags\Param': 'PhpParser\Node\Param'
'phpDocumentor\Reflection\DocBlock\Tags\Return_': 'PhpParser\Node\Stmt\Return_'
'Closure': 'PhpParser\Node\Expr\Closure'
'PHPUnit\TextUI\Configuration\Variable': 'PhpParser\Node\Expr\Variable'
'PhpCsFixer\FixerDefinition\CodeSample': 'Rector\Core\RectorDefinition\CodeSample'
'SebastianBergmann\Type\MixedType': 'PHPStan\Type\MixedType'
'Hoa\Protocol\Node\Node': 'PhpParser\Node'
# to allow installing with various phsptan versions without reporting old errors here
reportUnmatchedIgnoredErrors: false
checkGenericClassInNonGenericObjectType: false
scanDirectories:
- stubs
bootstrapFiles:
- vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php
paths:
- bin
- src
- rules
- packages
- tests
- compiler/src
- utils
# this cannot be put it, because it wipes PHPStan cache on each run :( - must run in separate
#- config/set
excludes_analyse:
# iterable types
- '#with no value type specified in iterable type array#'
- '#type specified in iterable type (array|iterable)#'
# phsptan bug
- utils/phpstan-extensions/src/Rule/PreventParentMethodVisibilityOverrideRule.php
- utils/phpstan-extensions/src/Rule/KeepRectorNamespaceForRectorRule.php
- packages/rector-generator/templates/*
# generated files
- 'packages/doctrine-annotation-generated/src/ConstantPreservingDocParser.php'
- 'packages/doctrine-annotation-generated/src/ConstantPreservingAnnotationReader.php'
- "*/Expected/*"
# complex printer
- '*tests/Rector/MethodCall/RenameMethodRector/**/SomeClass.php'
# tests files
- '*tests/*/Fixture/*'
- '*tests/*/Source/*'
- '*tests/Source/*'
# part of composer
- '*/tests/Rector/Psr4/MultipleClassFileToPsr4ClassesRector/Expected/Just*ExceptionWithoutNamespace.php'
# tests
- tests/DependencyInjection/config
ignoreErrors:
# @todo remove
# iterable types
- '#with no value type specified in iterable type array#'
- '#type specified in iterable type (array|iterable)#'
# false positive
- '#PHPDoc tag \@param for parameter \$node with type float is incompatible with native type PhpParser\\Node#'
# misuse of interface and class
- '#Parameter \#1 (.*?) expects Symfony\\Component\\DependencyInjection\\ContainerBuilder, Symfony\\Component\\DependencyInjection\\ContainerInterface given#'
- '#Strict comparison using === between string and null will always evaluate to false#'
# false positive - type is set by annotation above
- '#Array \(array<PhpParser\\Node\\Stmt>\) does not accept PhpParser\\Node#'
# irrelevant
- '#Call to function in_array\(\) with arguments string, (.*?) and true will always evaluate to false#'
# known values
- '#Access to an undefined property PhpParser\\Node\\Expr::\$right#'
- '#Access to an undefined property PhpParser\\Node\\Expr\\MethodCall\|PhpParser\\Node\\Stmt\\ClassMethod::\$params#'
- '#Cannot call method getName\(\) on PHPStan\\Reflection\\ClassReflection\|null#'
# false positive, has annotation type above
- '#Method Rector\\CodeQuality\\Rector\\Foreach_\\SimplifyForeachToCoalescingRector\:\:matchReturnOrAssignNode\(\) should return PhpParser\\Node\\Expr\\Assign\|PhpParser\\Node\\Stmt\\Return_\|null but returns PhpParser\\Node\|null#'
- '#Access to an undefined property PhpParser\\Node::\$(\w+)#'
# intentionally incorrect - part of the test
- '#Parameter \#2 \$codeSamples of class Rector\\Core\\RectorDefinition\\RectorDefinition constructor expects array<Rector\\Core\\Contract\\RectorDefinition\\CodeSampleInterface>, array<int, stdClass> given#'
# known values
- '#Cannot access property \$value on PhpParser\\Node\\Expr\\ArrayItem\|null#'
# known values
- '#Strict comparison using === between PhpParser\\Node\\Expr and null will always evaluate to false#'
- '#Access to an undefined property PhpParser\\Node\\Stmt\:\:\$expr#'
- '#Cannot access property \$stmts on PhpParser\\Node\\Stmt\\Else_\|null#'
# node finder
- '#Method Rector\\(.*?) should return array<PhpParser\\Node\\(.*?)> but returns array<PhpParser\\Node\>#'
# part of test
- '#(.*?)(AttributeAwareNodeInterface|AttributeAware(.*?)TagValueNode)(.*?)#'
- '#Parameter \#1 \$children of class PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode constructor expects array<PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode\>, array<int, PHPStan\\PhpDocParser\\Ast\\Node\> given#'
- '#Method Rector\\PHPUnit\\Rector\\MethodCall\\ReplaceAssertArraySubsetRector\:\:matchArray\(\) should return PhpParser\\Node\\Expr\\Array_\|null but returns PhpParser\\Node\\Expr#'
- '#(.*?)PhpParser\\Node\\Expr\\Error\|PhpParser\\Node\\Expr\\Variable given#'
# false positive 0.11.5
- '#Unreachable statement \- code above always terminates#'
- '#Negated boolean expression is always true#'
- '#Strict comparison using \=\=\= between PhpParser\\Node and null will always evaluate to false#'
# known types
- '#Access to an undefined property PhpParser\\Node\\Expr\\Error\|PhpParser\\Node\\Expr\\Variable\:\:\$name#'
- '#Strict comparison using \=\=\= between PhpParser\\Node\\Expr\\ArrayItem and null will always evaluate to false#'
- '#Parameter \#2 \.\.\.\$args of function array_merge expects array, array<int, string\>\|false given#'
- '#Access to an undefined property PhpParser\\Node\\Expr\:\:\$args#'
- '#Parameter \#2 \$name of method Rector\\Core\\Rector\\AbstractRector\:\:isName\(\) expects string, string\|null given#'
# cascade irrelevant
- '#Parameter (.*?) expects array<PhpParser\\Node\\Stmt\>, array<PhpParser\\Node\> given#'
# known value
- '#Cannot cast array<string\>\|bool\|string\|null to string#'
# array is callable
- '#If condition is always true#'
- '#Ternary operator condition is always true#'
- '#Access to an undefined property PhpParser\\Node\\FunctionLike\|PhpParser\\Node\\Stmt\\ClassLike\:\:\$stmts#'
- '#Property Rector\\TypeDeclaration\\TypeInferer\\(.*?)\:\:\$(.*?)TypeInferers \(array<Rector\\TypeDeclaration\\Contract\\TypeInferer\\(.*?)TypeInfererInterface\>\) does not accept array<Rector\\TypeDeclaration\\Contract\\TypeInferer\\PriorityAwareTypeInfererInterface\>#'
# sense-less errors
# 3rd party
-
message: '#Use default null value and nullable compare instead of isset on object#'
path: 'rules/symfony/src/ServiceMapProvider.php'
# PHP 7.4 1_000 support
- '#Property PhpParser\\Node\\Scalar\\DNumber\:\:\$value \(float\) does not accept string#'
- '#Call to function is_string\(\) with float will always evaluate to false#'
- '#Method Rector\\Doctrine\\Rector\\MethodCall\\ChangeSetIdToUuidValueRector\:\:getSetUuidMethodCallOnSameVariable\(\) should return PhpParser\\Node\\Expr\\MethodCall\|null but returns PhpParser\\Node\|null#'
# known value
- '#Method Rector\\StrictCodeQuality\\Rector\\Stmt\\VarInlineAnnotationToAssertRector\:\:findVariableByName\(\) should return PhpParser\\Node\\Expr\\Variable\|null but returns PhpParser\\Node\|null#'
- '#Method Rector\\NodeTypeResolver\\PHPStan\\Type\\TypeFactory\:\:createUnionOrSingleType\(\) should return PHPStan\\Type\\MixedType\|PHPStan\\Type\\UnionType but returns PHPStan\\Type\\Type#'
# test
- '#Class Rector\\DynamicTypeAnalysis\\Tests\\Rector\\ClassMethod\\AddArgumentTypeWithProbeDataRector\\Fixture\\SomeClass not found#'
-
message: '#Class Rector\\Generic\\Tests\\Rector\\StaticCall\\SwapClassMethodArgumentsRector\\Fixture\\SomeClass not found#'
path: rules/generic/tests/Rector/StaticCall/SwapClassMethodArgumentsRector/SwapClassMethodArgumentsRectorTest.php
# internal rule
- '#Class "Rector\\Utils\\(.*?)" is missing @see annotation with test case class reference#'
# mixed
- '#Offset int\|string\|null does not exist on array<PhpParser\\Node\\Stmt>\|null#'
- '#class-string<T of object>\|T of object#'
# known values
- '#Offset 0 does not exist on array<PhpParser\\Node\\Stmt>\|null#'
- '#Parameter \#1 \$left of class PhpParser\\Node\\Expr\\BinaryOp\\Spaceship constructor expects PhpParser\\Node\\Expr, PhpParser\\Node\\Expr\|null given#'
- '#Parameter \#2 \$right of class PhpParser\\Node\\Expr\\BinaryOp\\Spaceship constructor expects PhpParser\\Node\\Expr, PhpParser\\Node\\Expr\|null given#'
# false positive
- '#Comparison operation "<" between 0 and 2 is always true#'
- '#Method Rector\\Symfony\\Rector\\MethodCall\\AbstractToConstructorInjectionRector\:\:getServiceTypeFromMethodCallArgument\(\) should return PHPStan\\Type\\Type but returns PHPStan\\Type\\Type\|null#'
- '#Parameter \#1 \$expected of method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) expects class\-string<object\>, string given#'
- '#Unable to resolve the template type ExpectedType in call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\)#'
# fix Symplify 7.2 later
- '#Method (.*?) returns bool type, so the name should start with is/has/was#'
- '#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#'
# doc is not enough
- '#Result of \|\| is always true#'
# known value
- '#Parameter \#2 \$name of class PhpParser\\Node\\Expr\\MethodCall constructor expects PhpParser\\Node\\Expr\|PhpParser\\Node\\Identifier\|string, string\|null given#'
- '#Parameter \#1 \$eventListenerTag of method Rector\\SymfonyCodeQuality\\Rector\\Class_\\EventListenerToEventSubscriberRector\:\:createEventItem\(\) expects Rector\\Symfony\\ValueObject\\Tag\\EventListenerTag, Rector\\Symfony\\Contract\\Tag\\TagInterface given#'
- '#Method Rector\\BetterPhpDocParser\\PhpDocInfo\\PhpDocInfoFactory\:\:parseTokensToPhpDocNode\(\) should return Rector\\AttributeAwarePhpDoc\\Ast\\PhpDoc\\AttributeAwarePhpDocNode but returns PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode#'
- '#Property PhpParser\\Node\\Stmt\\Expression\:\:\$expr \(PhpParser\\Node\\Expr\) does not accept PhpParser\\Node\\Expr\|null#'
- '#Call to an undefined method PHPStan\\Type\\Type\:\:getClassName\(\)#'
- '#Parameter \#1 \$typeNode of method Rector\\StaticTypeMapper\\StaticTypeMapper\:\:mapPHPStanPhpDocTypeNodeToPHPStanType\(\) expects PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode, PHPStan\\PhpDocParser\\Ast\\Node given#'
- '#Parameter \#1 \$sprintfFuncCall of method Rector\\Core\\PhpParser\\NodeTransformer\:\:transformSprintfToArray\(\) expects PhpParser\\Node\\Expr\\FuncCall, PhpParser\\Node given#'
- '#Parameter \#1 \$nodes of method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:find\(\) expects array<PhpParser\\Node\>\|PhpParser\\Node, array<PhpParser\\Node\\Stmt\>\|null given#'
- '#Method Rector\\SOLID\\Reflection\\ParentConstantReflectionResolver\:\:(.*?)\(\) should return ReflectionClassConstant\|null but returns ReflectionClassConstant\|false#'
- '#Parameter \#1 \$firstStmt of method Rector\\Generic\\Rector\\ClassMethod\\NormalToFluentRector\:\:isBothMethodCallMatch\(\) expects PhpParser\\Node\\Stmt\\Expression, PhpParser\\Node\\Stmt given#'
- '#Method Rector\\Core\\Rector\\AbstractRector\:\:wrapToArg\(\) should return array<PhpParser\\Node\\Arg\> but returns array<PhpParser\\Node\\Arg\|PhpParser\\Node\\Expr\>#'
- '#Method Rector\\FileSystemRector\\Rector\\AbstractFileSystemRector\:\:wrapToArg\(\) should return array<PhpParser\\Node\\Arg\> but returns array<PhpParser\\Node\\Arg\|PhpParser\\Node\\Expr\>#'
- '#Cannot call method (.*?)\(\) on Rector\\BetterPhpDocParser\\PhpDocInfo\\PhpDocInfo\|null#'
- '#Parameter \#(.*?) (.*?) of class PhpParser\\Node\\Expr\\BinaryOp\\(.*?) constructor expects PhpParser\\Node\\Expr, PhpParser\\Node given#'
- '#Access to an undefined property PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode\:\:\$description#'
- '#Method Rector\\Php80\\Rector\\NotIdentical\\StrContainsRector\:\:matchNotIdenticalToFalse\(\) should return PhpParser\\Node\\Expr\\FuncCall\|null but returns PhpParser\\Node\\Expr#'
- '#Parameter \#2 \$name of method Rector\\Core\\Rector\\AbstractRector\:\:isVariableName\(\) expects string, string\|null given#'
# node finder
- '#Method Rector\\Core\\PhpParser\\Node\\Manipulator\\MethodCallManipulator\:\:findAssignToVariableName\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#'
# broken
- '#Cannot call method getParentNode\(\) on Rector\\DeadCode\\ValueObject\\VariableNodeUse\|null#'
- '#Method Rector\\DeadCode\\NodeFinder\\PreviousVariableAssignNodeFinder\:\:find\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#'
- '#Parameter \#2 \$name of method Rector\\NodeNameResolver\\NodeNameResolver\:\:isName\(\) expects string, string\|null given#'
- '#Method Rector\\PHPOffice\\Rector\\MethodCall\\IncreaseColumnIndexRector\:\:findVariableAssignName\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#'
- '#Parameter \#1 \$keyName of method Rector\\AttributeAwarePhpDoc\\Ast\\Type\\AttributeAwareArrayShapeItemNode\:\:createKeyWithSpacePattern\(\) expects PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode\|PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode\|null, PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode\|PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode\|PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode\|null given#'
- '#Method Rector\\Caching\\ChangedFilesDetector\:\:hashFile\(\) should return string but returns string\|false#'
- '#If condition is always false#'
- '#Parameter \#1 \$funcCall of method Rector\\Php80\\MatchAndRefactor\\StrStartsWithMatchAndRefactor\\AbstractMatchAndRefactor\:\:createStrStartsWithValueObjectFromFuncCall\(\) expects PhpParser\\Node\\Expr\\FuncCall, PhpParser\\Node\\Expr given#'
# mostly strings in tests
- '#Class (.*?) should be written with \:\:class notation, string found#'
- '#Method Rector\\Naming\\Naming\\PropertyNaming\:\:resolveShortClassName\(\) should return string but returns string\|null#'
-
message: "#in iterable type Iterator#"
paths:
- *Test.php
- *TestCase.php
-
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
-
message: "#^Parameter \\#1 \\$input of function array_splice expects array, array\\<PhpParser\\\\Node\\\\Stmt\\>\\|null given\\.$#"
count: 1
path: rules/coding-style/src/Rector/ClassMethod/NewlineBeforeNewAssignSetRector.php
-
message: "#^Cognitive complexity for \"Rector\\\\PhpSpecToPHPUnit\\\\Rector\\\\MethodCall\\\\PhpSpecPromisesToPHPUnitAssertRector\\:\\:refactor\\(\\)\" is 13, keep it under 9$#"
count: 1
path: rules/php-spec-to-phpunit/src/Rector/MethodCall/PhpSpecPromisesToPHPUnitAssertRector.php
-
message: "#^Class cognitive complexity for \"EregToPcreTransformer\" is (.*?), keep it under 50$#"
path: rules/php70/src/EregToPcreTransformer.php
-
message: "#Use explicit property fetch names over dynamic#"
path: packages/doctrine-annotation-generated/src/PhpDocNode/ConstantReferenceIdentifierRestorer.php
- "#^Cognitive complexity for \"Rector\\\\Php70\\\\EregToPcreTransformer\\:\\:(.*?)\" is (.*?), keep it under 9$#"
- '#In method "Rector\\Utils\\ProjectValidator\\Process\\ParallelTaskRunner\:\:(.*?)", caught "Throwable" must be rethrown\. Either catch a more specific exception or add a "throw" clause in the "catch" block to propagate the exception#'
# weird
- '#Method (.*?) specified in iterable type Symfony\\Component\\Process\\Process#'
- '#Cannot cast PhpParser\\Node\\Expr\\Error\|PhpParser\\Node\\Identifier to string#'
- '#Class cognitive complexity for "DumpNodesCommand" is \d+, keep it under 50#'
- '#Cognitive complexity for "Rector\\Utils\\DocumentationGenerator\\Command\\DumpNodesCommand\:\:execute\(\)" is \d+, keep it under 9#'
- '#Parameter \#1 \$node of method Rector\\PostRector\\Collector\\NodesToAddCollector\:\:wrapToExpression\(\) expects PhpParser\\Node\\Expr\|PhpParser\\Node\\Stmt, PhpParser\\Node given#'
- '#Access to an undefined property PhpParser\\Node\\Expr\:\:\$class#'
- '#Method Rector\\BetterPhpDocParser\\Tests\\PhpDocParser\\AbstractPhpDocInfoTest\:\:parseFileAndGetFirstNodeOfType\(\) should return PhpParser\\Node but returns PhpParser\\Node\|null#'
- '#Property PhpParser\\Node\\Stmt\\Namespace_\:\:\$stmts \(array<PhpParser\\Node\\Stmt\>\) does not accept array<PhpParser\\Node\>#'
- '#Cognitive complexity for "Rector\\TypeDeclaration\\PHPStan\\Type\\ObjectTypeSpecifier\:\:matchShortenedObjectType\(\)" is 10, keep it under 9#'
- '#Parameter \#1 \$type of method PhpParser\\Builder\\FunctionLike\:\:setReturnType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#'
- '#Cognitive complexity for "Rector\\Core\\PhpParser\\Node\\Value\\ValueResolver\:\:getValue\(\)" is \d+, keep it under 9#'
- '#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#'
- '#Class "Rector\\FileSystemRector\\Rector\\Removing\\RemoveProjectFileRector" 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 \$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#'
- '#Method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findFirstNonAnonymousClass\(\) should return PhpParser\\Node\\Stmt\\Class_\|null but returns PhpParser\\Node\|null#'
# known value
- '#Property PhpParser\\Node\\Stmt\\Foreach_\:\:\$valueVar \(PhpParser\\Node\\Expr\) does not accept PhpParser\\Node\\Expr\|null#'
- '#Access to an undefined property PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode\:\:\$type#'
# local type
-
message: '#Method call "isObjectType\(\)" argument on position 1 cannot use "\:\:class" reference#'
path: 'packages/dynamic-type-analysis/src/Rector/StaticCall/RemoveArgumentTypeProbeRector.php'
# only local use
-
message: '#Class "Rector\\RectorGenerator\\Rector\\Closure\\AddNewServiceToSymfonyPhpConfigRector" is missing @see annotation with test case class reference#'
path: 'packages/rector-generator/src/Rector/Closure/AddNewServiceToSymfonyPhpConfigRector.php'
- '#Class Rector\\Renaming\\Tests\\Rector\\MethodCall\\RenameMethodRector\\Fixture\\SkipSelfMethodRename not found#'
# fixed in symplfiy dev
-
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\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findPreviousAssignToExpr\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#'
- '#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#'
- '#Parameter \#1 \$files of method Symplify\\SmartFileSystem\\Finder\\FinderSanitizer\:\:sanitize\(\) expects \(iterable<SplFileInfo\|string\>&Nette\\Utils\\Finder\)\|Symfony\\Component\\Finder\\Finder, array<string\> given#'
- '#Static property Rector\\Core\\Testing\\PHPUnit\\AbstractGenericRectorTestCase\:\:\$allRectorContainer \(Rector\\Naming\\Tests\\Rector\\Class_\\RenamePropertyToMatchTypeRector\\Source\\ContainerInterface\|Symfony\\Component\\DependencyInjection\\Container\|null\) does not accept Psr\\Container\\ContainerInterface#'
# stubs
- '#Static property Symplify\\PackageBuilder\\Tests\\AbstractKernelTestCase\:\:\$container \(Psr\\Container\\ContainerInterface\) does not accept Rector\\Naming\\Tests\\Rector\\Class_\\RenamePropertyToMatchTypeRector\\Source\\ContainerInterface\|Symfony\\Component\\DependencyInjection\\Container#'
# wtf
-
message: '#Else branch is unreachable because ternary operator condition is always true#'
path: 'rules/psr4/src/Composer/PSR4NamespaceMatcher.php'
# false positive
- '#Parameter \#1 \$arrayItem of method Rector\\NetteKdyby\\NodeResolver\\ListeningMethodsCollector\:\:resolveCustomClassMethodAndEventClass\(\) expects PhpParser\\Node\\Expr\\ArrayItem, PhpParser\\Node given#'
- '#Parameter \#1 \$type of method Rector\\NodeCollector\\NodeCollector\\ParsedNodeCollector<TNodeType of PhpParser\\Node\>\:\:getNodesByType\(\) expects class\-string<TNodeType of PhpParser\\Node\>, string given#'
- '#Class with base "(.*?)" name is already used in "_HumbugBox(.*?)"#'
-
message: '#Class "Rector\\RectorGenerator\\ValueObject\\RectorRecipe" has invalid namespace category "ValueObject"\. Pick one of\: ""#'
path: packages/rector-generator/src/ValueObject/RectorRecipe.php
- '#Parameter \#2 \$currentNode of method Rector\\CodingStyle\\Rector\\Assign\\ManualJsonStringToJsonEncodeArrayRector\:\:matchNextExprAssignConcatToSameVariable\(\) expects PhpParser\\Node\\Expr\\Assign\|PhpParser\\Node\\Expr\\AssignOp\\Concat, PhpParser\\Node given#'
-
message: '#Array (with keys|destruct) is not allowed\. Use value object to pass data instead#'
paths:
# working with cvs file
# 3rd party package
- rules/php70/src/EregToPcreTransformer.php
# output format
- packages/changes-reporting/src/Output/JsonOutputFormatter.php
# template variables
- packages/rector-generator/src/TemplateVariablesFactory.php
# output format to json
- rules/doctrine/src/Collector/UuidMigrationDataCollector.php
# should be replaced by symplify/composer-json-manipulator in the future
- compiler/src/Composer/ComposerJsonManipulator.php
# not sure how to improve
- rules/symfony/src/ValueObject/Tag/EventListenerTag.php
-
message: '#Use explicit return value over magic &reference#'
paths:
# 3rd party code
- rules/php70/src/EregToPcreTransformer.php
- '#Cannot access property \$key on PhpParser\\Node\\Expr\\ArrayItem\|null#'
- '#Class Nette\\DI\\CompilerExtension not found#'
- '#Class Latte\\Macros\\MacroSet not found#'
# symfony/console
-
message: '#Cannot cast array<string\>\|string\|true to string#'
path: 'src/Configuration/Configuration.php'
-
message: '#Use explicit return value over magic &reference#'
path: 'rules/dead-code/src/Rector/BinaryOp/RemoveDuplicatedInstanceOfRector.php'
-
message: '#Class with base "NodeNameResolver" name is already used in "Symplify\\CodingStandard\\PhpParser\\NodeNameResolver", "Rector\\NodeNameResolver\\NodeNameResolver"\. Use unique name to make classes easy to recognize#'
path: 'packages/node-name-resolver/src/NodeNameResolver.php'
-
message: '#Use value object over return of values#'
path: 'rules/phpunit/src/Composer/ComposerAutoloadedDirectoryProvider.php'
-
message: '#Use value object over return of values#'
path: 'rules/php70/src/EregToPcreTransformer.php'
# complex class
- '#Class cognitive complexity for "NodeTypeResolver" is \d+, keep it under 50#'

View File

@ -3,22 +3,12 @@
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Generic\ValueObject\NamespacePrefixWithExcludedClasses;
use Rector\SymfonyPhpConfig\Rector\ArrayItem\ReplaceArrayWithObjectRector;
use Rector\Set\ValueObject\SetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(ReplaceArrayWithObjectRector::class)
->call('configure', [[
ReplaceArrayWithObjectRector::CONSTANT_NAMES_TO_VALUE_OBJECTS => [
'Rector\Generic\Rector\Name\PseudoNamespaceToNamespaceRector::NAMESPACE_PREFIXES_WITH_EXCLUDED_CLASSES' => NamespacePrefixWithExcludedClasses::class,
],
]]);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
$parameters->set(Option::SETS, [SetList::TYPE_DECLARATION]);
$parameters->set(Option::PATHS, [
__DIR__ . '/src',
@ -39,6 +29,8 @@ return static function (ContainerConfigurator $containerConfigurator): void {
'*.php.inc',
]);
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
# so Rector code is still PHP 7.2 compatible
$parameters->set(Option::PHP_VERSION_FEATURES, '7.2');
};

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->public();
$services->load('Rector\Architecture\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector/*']);
->exclude([__DIR__ . '/../src/Rector']);
};

View File

@ -33,7 +33,7 @@ final class DoctrineRepositoryAsServiceTest extends AbstractRectorTestCase
}
/**
* @return mixed[][]
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->public();
$services->load('Rector\Autodiscovery\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector/*', __DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/ValueObject']);
};

View File

@ -61,6 +61,9 @@ final class MoveServicesBySuffixToDirectoryRectorTest extends AbstractFileSystem
];
}
/**
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{
return [

View File

@ -74,7 +74,7 @@ final class MutualRenameTest extends AbstractFileSystemRectorTestCase
}
/**
* @return string[][][]
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{

View File

@ -48,7 +48,7 @@ final class MoveValueObjectsToValueObjectDirectoryRectorTest extends AbstractFil
}
/**
* @return array<string, mixed[]>
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->public();
$services->load('Rector\CodeQuality\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector/*']);
->exclude([__DIR__ . '/../src/Rector']);
};

View File

@ -84,7 +84,7 @@ PHP
&$countInCond,
&$variableName,
$forScope
) {
): ?Variable {
if (! $node instanceof FuncCall) {
return null;
}

View File

@ -136,7 +136,7 @@ PHP
private function findPreviousNodeUsage(Node $node, Expr $expr): ?Node
{
return $this->scopeAwareNodeFinder->findParent($node, function (Node $node) use ($expr) {
return $this->scopeAwareNodeFinder->findParent($node, function (Node $node) use ($expr): bool {
if ($node === $expr) {
return false;
}
@ -162,7 +162,7 @@ PHP
private function findPreviousNodeUsageInForeach(Node $node, Expr $expr): ?Node
{
return $this->betterNodeFinder->findFirstPrevious($node, function (Node $node) use ($expr) {
return $this->betterNodeFinder->findFirstPrevious($node, function (Node $node) use ($expr): bool {
if ($node === $expr) {
return false;
}

View File

@ -106,7 +106,7 @@ PHP
private function isVariableUsedInForeach(Variable $variable, Foreach_ $foreach): bool
{
return (bool) $this->betterNodeFinder->findFirst($foreach->stmts, function (Node $node) use ($variable) {
return (bool) $this->betterNodeFinder->findFirst($foreach->stmts, function (Node $node) use ($variable): bool {
return $this->areNodesEqual($node, $variable);
});
}

View File

@ -68,7 +68,7 @@ PHP
/** @var Assign|Node|null $previousAssignArraysKeysFuncCall */
$previousAssignArraysKeysFuncCall = $this->betterNodeFinder->findFirstPrevious($node, function (Node $node) use (
$arrayVariable
) {
): bool {
// breaking out of scope
if ($node instanceof FunctionLike) {
return true;

View File

@ -10,6 +10,8 @@ use PhpParser\Node\Expr\AssignOp;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\MixedType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Core\PhpParser\Node\AssignAndBinaryMap;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
@ -84,6 +86,10 @@ PHP
}
if ($previousNode instanceof Assign) {
if ($this->isReturnWithVarAnnotation($node)) {
return null;
}
$node->expr = $previousNode->expr;
}
@ -127,6 +133,20 @@ PHP
return $this->isPreviousExpressionVisuallySimilar($previousExpression, $previousNode);
}
private function isReturnWithVarAnnotation(Node $node): bool
{
if (! $node instanceof Return_) {
return false;
}
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if (! $phpDocInfo instanceof PhpDocInfo) {
return false;
}
return ! $phpDocInfo->getVarType() instanceof MixedType;
}
/**
* @param AssignOp|Assign $previousNode
*/

View File

@ -0,0 +1,19 @@
<?php
namespace Rector\CodeQuality\Tests\Rector\Return_\SimplifyUselessVariableRector\Fixture;
class KeepVarDoc
{
public function run()
{
$name = $this->getValue();
/** @var string $name */
return $name;
}
private function getValue()
{
return 'name';
}
}

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->public();
$services->load('Rector\CodingStyle\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector/*', __DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/ValueObject']);
};

View File

@ -30,7 +30,7 @@ final class UseImportsAdder
* @param Stmt[] $stmts
* @param FullyQualifiedObjectType[] $useImportTypes
* @param FullyQualifiedObjectType[] $functionUseImportTypes
* @return Stmt[]
* @return Stmt[] <int|string, \PhpParser\Node\Stmt>
*/
public function addImportsToStmts(array $stmts, array $useImportTypes, array $functionUseImportTypes): array
{

View File

@ -59,6 +59,14 @@ final class ReturnArrayClassMethodToYieldRector extends AbstractRector implement
public function __construct(NodeTransformer $nodeTransformer)
{
$this->nodeTransformer = $nodeTransformer;
// default values
$this->methodsToYields = [
new MethodToYield('PHPUnit\Framework\TestCase', 'provideData'),
new MethodToYield('PHPUnit\Framework\TestCase', 'provideData*'),
new MethodToYield('PHPUnit\Framework\TestCase', 'dataProvider'),
new MethodToYield('PHPUnit\Framework\TestCase', 'dataProvider*'),
];
}
public function getDefinition(): RectorDefinition

View File

@ -24,7 +24,7 @@ use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
* @see \Rector\CodingStyle\Tests\Rector\FuncCall\FunctionCallToConstantRector\FunctionCallToConstantRectorTest
* @see \Rector\CodingStyle\Tests\Rector\FuncCall\VersionCompareFuncCallToConstantRector\VersionCompareFuncCallToConstantRectorTest
*/
final class VersionCompareFuncCallToConstantRector extends AbstractRector
{

View File

@ -71,7 +71,7 @@ PHP
// @see https://regex101.com/r/Vv41Qr/1/
$matches = Strings::matchAll($string->value, '#([\\\\a-zA-Z0-9_\\x80-\\xff]*)::#', PREG_PATTERN_ORDER);
return array_filter($matches[1], function (string $className) {
return array_filter($matches[1], function (string $className): bool {
return class_exists($className);
});
}
@ -81,14 +81,14 @@ PHP
*/
public function getParts(String_ $string, array $classNames): array
{
$classNames = array_map(function (string $className) {
$classNames = array_map(function (string $className): string {
return preg_quote($className);
}, $classNames);
// @see https://regex101.com/r/8nGS0F/1
$parts = Strings::split($string->value, '#(' . implode('|', $classNames) . ')#');
return array_filter($parts, function (string $className) {
return array_filter($parts, function (string $className): bool {
return $className !== '';
});
}

View File

@ -176,7 +176,7 @@ PHP
*/
private function lowercaseArray(array $values): array
{
return array_map(function (string $value) {
return array_map(function (string $value): string {
return strtolower($value);
}, $values);
}

View File

@ -27,6 +27,9 @@ final class ConcatStringAndPlaceholders
return $this->content;
}
/**
* @return mixed[]
*/
public function getPlaceholderNodes(): array
{
return $this->placeholderNodes;

View File

@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Rector\CodingStyle\ValueObject;
use Rector\Core\ValueObject\MethodName;
final class ObjectMagicMethods
{
/**
@ -13,9 +15,9 @@ final class ObjectMagicMethods
'__call',
'__callStatic',
'__clone',
'__construct',
MethodName::CONSTRUCT,
'__debugInfo',
'__destruct',
MethodName::DESCTRUCT,
'__get',
'__invoke',
'__isset',

View File

@ -25,7 +25,7 @@ final class FunctionCallToConstantRectorTest extends AbstractRectorTestCase
}
/**
* @return string[][][]
* @return mixed[]
*/
protected function getRectorsWithConfiguration(): array
{

View File

@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->public();
$services->load('Rector\DeadCode\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector/*', __DIR__ . '/../src/ValueObject/*']);
->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/ValueObject']);
};

View File

@ -68,7 +68,7 @@ final class NextVariableUsageNodeFinder
$this->callableNodeTraverser->traverseNodesWithCallable((array) $scopeNode->stmts, function (Node $currentNode) use (
$expr,
&$nextUsageOfVariable
) {
): ?int {
// used above the assign
if ($currentNode->getStartTokenPos() < $expr->getStartTokenPos()) {
return null;

View File

@ -27,12 +27,12 @@ final class PreviousVariableAssignNodeFinder
$this->nodeNameResolver = $nodeNameResolver;
}
public function find(Assign $assign): ?Assign
public function find(Assign $assign): ?Node
{
$currentAssign = $assign;
$variableName = $this->nodeNameResolver->getName($assign->var);
return $this->betterNodeFinder->findFirstPrevious($assign, function (Node $node) use (
$assign = $this->betterNodeFinder->findFirstPrevious($assign, function (Node $node) use (
$variableName,
$currentAssign
): bool {
@ -47,5 +47,8 @@ final class PreviousVariableAssignNodeFinder
return $this->nodeNameResolver->isName($node->var, $variableName);
});
/** @var Assign|null $assign */
return $assign;
}
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\DeadCode\NodeManipulator;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeNameResolver\NodeNameResolver;
final class MagicMethodDetector
@ -17,7 +18,7 @@ final class MagicMethodDetector
'__callStatic',
'__clone',
'__debugInfo',
'__destruct',
MethodName::DESCTRUCT,
'__get',
'__invoke',
'__isset',

View File

@ -40,7 +40,7 @@ final class VariadicFunctionLikeDetector
$this->callableNodeTraverser->traverseNodesWithCallable(
(array) $functionLike->getStmts(),
function (Node $node) use (&$isVariadic) {
function (Node $node) use (&$isVariadic): ?int {
if (! $node instanceof FuncCall) {
return null;
}

View File

@ -93,8 +93,11 @@ PHP
*/
private function filterItemsWithSameKey(array $arrayItemsByKeys): array
{
return array_filter($arrayItemsByKeys, function (array $arrayItems) {
$arrayItemsByKeys = array_filter($arrayItemsByKeys, function (array $arrayItems): bool {
return count($arrayItems) > 1;
});
/** @var ArrayItem[][] $arrayItemsByKeys */
return $arrayItemsByKeys;
}
}

View File

@ -82,7 +82,9 @@ PHP
*/
private function findVariableUsages(FunctionLike $functionLike, Assign $assign): array
{
return $this->betterNodeFinder->find((array) $functionLike->getStmts(), function (Node $node) use ($assign) {
return $this->betterNodeFinder->find((array) $functionLike->getStmts(), function (Node $node) use (
$assign
): bool {
if (! $node instanceof Variable) {
return false;
}

View File

@ -152,7 +152,7 @@ PHP
$this->traverseNodesWithCallable($node, function (Node $node) use (
$modifiedVariableNames,
&$containsVariableNames
) {
): ?int {
if (! $node instanceof Variable) {
return null;
}
@ -170,12 +170,12 @@ PHP
}
/**
* @param If_[][] $ifWithOnlyReturnsByHash
* @return If_[][]
* @param array<string, If_[]> $ifWithOnlyReturnsByHash
* @return array<string, If_[]>
*/
private function filterOutSingleItemStmts(array $ifWithOnlyReturnsByHash): array
{
return array_filter($ifWithOnlyReturnsByHash, function (array $stmts) {
return array_filter($ifWithOnlyReturnsByHash, function (array $stmts): bool {
return count($stmts) >= 2;
});
}

View File

@ -137,7 +137,7 @@ PHP
/**
* @param StaticCall|FuncCall|MethodCall $node
* @return Expr[]|Node[]
* @return Node[]
*/
private function resolveDefaultValuesFromCall(Node $node): array
{

View File

@ -4,9 +4,6 @@ declare(strict_types=1);
namespace Rector\DeadCode\UnusedNodeResolver;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
@ -92,24 +89,22 @@ final class UnusedClassResolver
{
$classNames = [];
/** @var Param[] $paramNodes */
$paramNodes = $this->parsedNodeCollector->getNodesByType(Param::class);
foreach ($paramNodes as $paramNode) {
if ($paramNode->type === null) {
foreach ($this->parsedNodeCollector->getParams() as $param) {
if ($param->type === null) {
continue;
}
if ($paramNode->type instanceof NullableType) {
$paramNode = $paramNode->type;
if ($param->type instanceof NullableType) {
$param = $param->type;
}
if ($paramNode->type instanceof Identifier) {
if ($param->type instanceof Identifier) {
continue;
}
if ($paramNode->type instanceof Name) {
if ($param->type instanceof Name) {
/** @var string $paramTypeName */
$paramTypeName = $this->nodeNameResolver->getName($paramNode->type);
$paramTypeName = $this->nodeNameResolver->getName($param->type);
$classNames[] = $paramTypeName;
} else {
throw new NotImplementedException();
@ -126,15 +121,13 @@ final class UnusedClassResolver
{
$classNames = [];
/** @var New_[] $newNodes */
$newNodes = $this->parsedNodeCollector->getNodesByType(New_::class);
foreach ($newNodes as $newNode) {
$newNodeClassName = $this->nodeNameResolver->getName($newNode->class);
if (! is_string($newNodeClassName)) {
foreach ($this->parsedNodeCollector->getNews() as $newNode) {
$newClassName = $this->nodeNameResolver->getName($newNode->class);
if (! is_string($newClassName)) {
continue;
}
$classNames[] = $newNodeClassName;
$classNames[] = $newClassName;
}
return $classNames;
@ -147,9 +140,7 @@ final class UnusedClassResolver
{
$classNames = [];
/** @var StaticCall[] $staticCallNodes */
$staticCallNodes = $this->parsedNodeCollector->getNodesByType(StaticCall::class);
foreach ($staticCallNodes as $staticCallNode) {
foreach ($this->parsedNodeCollector->getStaticCalls() as $staticCallNode) {
$staticClassName = $this->nodeNameResolver->getName($staticCallNode->class);
if (! is_string($staticClassName)) {
continue;
@ -165,8 +156,7 @@ final class UnusedClassResolver
*/
private function getClassConstantFetchNames(): array
{
/** @var ClassConstFetch[] $classConstFetches */
$classConstFetches = $this->parsedNodeCollector->getNodesByType(ClassConstFetch::class);
$classConstFetches = $this->parsedNodeCollector->getClassConstFetches();
$classNames = [];
foreach ($classConstFetches as $classConstFetch) {

Some files were not shown because too many files have changed in this diff Show More