mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-18 22:08:00 +01:00
commit
85117cae1e
2
.github/workflows/code_analysis.yaml
vendored
2
.github/workflows/code_analysis.yaml
vendored
@ -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
|
||||
|
||||
-
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
6
ecs.php
6
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, [
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocManipulator;
|
||||
|
||||
use PhpParser\Node\Param;
|
||||
use PHPStan\Type\Constant\ConstantArrayType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\NeverType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareReturnTagValueNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareVarTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\NodeTypeResolver\PHPStan\TypeComparator;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
use Rector\TypeDeclaration\PhpDocParser\ParamPhpDocNodeFactory;
|
||||
|
||||
final class PhpDocTypeChanger
|
||||
{
|
||||
/**
|
||||
* @var TypeComparator
|
||||
*/
|
||||
private $typeComparator;
|
||||
|
||||
/**
|
||||
* @var StaticTypeMapper
|
||||
*/
|
||||
private $staticTypeMapper;
|
||||
|
||||
/**
|
||||
* @var ParamPhpDocNodeFactory
|
||||
*/
|
||||
private $paramPhpDocNodeFactory;
|
||||
|
||||
public function __construct(
|
||||
TypeComparator $typeComparator,
|
||||
StaticTypeMapper $staticTypeMapper,
|
||||
ParamPhpDocNodeFactory $paramPhpDocNodeFactory
|
||||
) {
|
||||
$this->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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\Printer;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
|
||||
|
||||
final class EmptyPhpDocDetector
|
||||
{
|
||||
public 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -11,6 +11,9 @@ final class ResolvedConstantStaticCollector
|
||||
*/
|
||||
private static $valuesByIdentifier = [];
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function collect(string $identifier, $value): void
|
||||
{
|
||||
// skip PHP values
|
||||
|
@ -75,6 +75,7 @@ final class ConstantReferenceIdentifierRestorer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @return mixed|null
|
||||
*/
|
||||
private function matchIdentifierBasedOnResolverValue(array $identifierToResolvedValues, $value)
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -258,6 +258,9 @@ final class NodeTypeResolver
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectType|string|mixed $requiredType
|
||||
*/
|
||||
private function ensureRequiredTypeIsStringOrObjectType($requiredType, string $location): void
|
||||
{
|
||||
if (is_string($requiredType)) {
|
||||
|
@ -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;
|
||||
|
@ -31,6 +31,9 @@ final class ConditionEvaluator
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
*/
|
||||
private function evaluateVersionCompareCondition(VersionCompareCondition $versionCompareCondition)
|
||||
{
|
||||
$compareSign = $versionCompareCondition->getCompareSign();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
48
phpstan.neon
48
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<PhpParser\\Node\\Stmt>\|null#'
|
||||
- '#class-string<T of object>\|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<PhpParser\\Node\\Stmt>\|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\>\)\|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\\<PhpParser\\\\Node\\\\Stmt\\>\\|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<string, string\> but returns array<int\|string, string\>#'
|
||||
- '#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<string, string\> but returns array<int\|string, string\>#'
|
||||
- '#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#'
|
||||
|
52
rector.php
52
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');
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -221,6 +221,9 @@ PHP
|
||||
return new AttributeAwarePhpDocTagNode('@throws', $throwsTagValueNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string>
|
||||
*/
|
||||
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<class-string>
|
||||
*/
|
||||
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<class-string>
|
||||
*/
|
||||
private function extractMethodThrows(FullyQualified $fullyQualified, Identifier $identifier): array
|
||||
{
|
||||
$method = $identifier->name;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,10 @@ PHP
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function getArrayItemsWithDuplicatedKey(Array_ $array)
|
||||
/**
|
||||
* @return ArrayItem[][]
|
||||
*/
|
||||
private function getArrayItemsWithDuplicatedKey(Array_ $array): array
|
||||
{
|
||||
$arrayItemsByKeys = [];
|
||||
|
||||
|
@ -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'),
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Naming\Tests\Rector\Class_\RenamePropertyToMatchTypeRector\Fixture;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
|
||||
interface UpdateDocName
|
||||
{
|
||||
/**
|
||||
* @param Identifier|Name $value
|
||||
*/
|
||||
public function method(Node $value);
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Naming\Tests\Rector\Class_\RenamePropertyToMatchTypeRector\Fixture;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
|
||||
interface UpdateDocName
|
||||
{
|
||||
/**
|
||||
* @param Identifier|Name $node
|
||||
*/
|
||||
public function method(Node $node);
|
||||
}
|
||||
|
||||
?>
|
@ -8,5 +8,5 @@ use Rector\NetteCodeQuality\NodeResolver\MethodNamesByInputNamesResolver;
|
||||
|
||||
interface MethodNamesByInputNamesResolverAwareInterface
|
||||
{
|
||||
public function setResolver(MethodNamesByInputNamesResolver $methodNamesByInputNamesResolver);
|
||||
public function setResolver(MethodNamesByInputNamesResolver $methodNamesByInputNamesResolver): void;
|
||||
}
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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] === ')') {
|
||||
|
@ -79,7 +79,6 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
|
||||
}
|
||||
|
||||
$arguments = $this->getNonVariableArguments($node);
|
||||
|
||||
if ($arguments === []) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -9,7 +9,7 @@ use Rector\Core\Configuration\ChangeConfiguration;
|
||||
final class RenamedClassesCollector
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $oldToNewClass = [];
|
||||
|
||||
@ -29,7 +29,7 @@ final class RenamedClassesCollector
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getOldToNewClasses(): array
|
||||
{
|
||||
|
@ -78,6 +78,9 @@ final class ClassRenamer
|
||||
$this->betterNodeFinder = $betterNodeFinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $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;
|
||||
|
@ -33,7 +33,7 @@ final class RenameClassRector extends AbstractRector
|
||||
private $classRenamer;
|
||||
|
||||
/**
|
||||
* @param string[] $oldToNewClasses
|
||||
* @param array<string, string> $oldToNewClasses
|
||||
*/
|
||||
public function __construct(
|
||||
ChangeConfiguration $changeConfiguration,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ PHP
|
||||
|
||||
private function refactorClassMethodWithTypehintByParameterPosition(
|
||||
ClassMethod $classMethod,
|
||||
$typehintByParameterPosition
|
||||
array $typehintByParameterPosition
|
||||
): void {
|
||||
foreach ($typehintByParameterPosition as $parameterPosition => $type) {
|
||||
if (! isset($classMethod->params[$parameterPosition])) {
|
||||
|
@ -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;
|
||||
|
@ -7,12 +7,12 @@ namespace Rector\Core\Configuration;
|
||||
final class ChangeConfiguration
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $oldToNewClasses = [];
|
||||
|
||||
/**
|
||||
* @param string[] $oldToNewClasses
|
||||
* @param array<string, string> $oldToNewClasses
|
||||
*/
|
||||
public function setOldToNewClasses(array $oldToNewClasses): void
|
||||
{
|
||||
@ -20,7 +20,7 @@ final class ChangeConfiguration
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getOldToNewClasses(): array
|
||||
{
|
||||
|
@ -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])) {
|
||||
|
@ -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)) {
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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 = [];
|
||||
|
||||
|
@ -27,6 +27,9 @@ final class ClassMethodReflectionHelper
|
||||
$this->phpDocTagsFinder = $phpDocTagsFinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string>
|
||||
*/
|
||||
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;
|
||||
|
@ -6,5 +6,8 @@ namespace Rector\Core\Testing\Contract;
|
||||
|
||||
interface RunnableInterface
|
||||
{
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function run();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -28,6 +28,7 @@ final class ValueResolverTest extends AbstractKernelTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $expected
|
||||
* @dataProvider dataProvider
|
||||
*/
|
||||
public function test($expected, Expr $expr): void
|
||||
|
@ -78,7 +78,7 @@ final class RequireStringArgumentInMethodCallRule implements Rule
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, int> $positionsByMethods
|
||||
* @param array<string, array<int>> $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;
|
||||
}
|
||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user