mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 21:38:22 +01:00
decouple PhpDocTypeChanger
This commit is contained in:
parent
110316f471
commit
8b1cdcb46e
@ -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
|
||||
@ -347,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
|
||||
@ -419,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -462,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) {
|
||||
@ -483,13 +436,6 @@ final class PhpDocInfo
|
||||
return $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType($phpDocTagValueNode, $this->node);
|
||||
}
|
||||
|
||||
private function getReturnTagValue(): ?AttributeAwareReturnTagValueNode
|
||||
{
|
||||
/** @var AttributeAwareReturnTagValueNode[] $returnTagValueNodes */
|
||||
$returnTagValueNodes = $this->phpDocNode->getReturnTagValues();
|
||||
return $returnTagValueNodes[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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ namespace Rector\BetterPhpDocParser\Printer;
|
||||
use Nette\Utils\Strings;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
@ -77,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,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 '';
|
||||
}
|
||||
|
||||
@ -162,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,
|
||||
@ -371,16 +358,19 @@ final class PhpDocInfoPrinter
|
||||
*/
|
||||
private function resolveTagSpaceSeparator(PhpDocTagNode $phpDocTagNode): string
|
||||
{
|
||||
if ($this->isCommonTag($phpDocTagNode)) {
|
||||
return ' ';
|
||||
}
|
||||
|
||||
$originalContent = $this->phpDocInfo->getOriginalContent();
|
||||
$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
|
||||
|
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');
|
||||
|
@ -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;
|
||||
|
@ -270,12 +270,12 @@ PHP
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Name|Identifier $usedName
|
||||
* @param Name|Identifier $usedNameNode
|
||||
*/
|
||||
private function renameInterface(string $lastName, Interface_ $interface, Node $usedName): void
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user