mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-01 08:50:50 +00:00
PHPStan: require iterable types (#3936)
* phpstan: require iterable types * add link on relative path and line * fix missing class type * typed array in Rector code + add data provide support resolver * remove duplicated set * drop unused yaml ecs config * add out-of-the-box directory for 3rd party packages * static fixes * [rector] static fixes * [cs] static fixes * [rector] [cs] static fixes * generic types Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
parent
e4af8cc721
commit
1c4b510513
|
@ -46,6 +46,7 @@ expectedArguments(
|
|||
\Rector\NodeTypeResolver\Node\AttributeKey::COMMENTS,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::VIRTUAL_NODE,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::CLOSURE_NODE,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::PARAMETER_POSITION,
|
||||
);
|
||||
|
||||
expectedArguments(
|
||||
|
@ -77,6 +78,7 @@ expectedArguments(
|
|||
\Rector\NodeTypeResolver\Node\AttributeKey::COMMENTS,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::VIRTUAL_NODE,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::CLOSURE_NODE,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::PARAMETER_POSITION,
|
||||
);
|
||||
|
||||
expectedArguments(
|
||||
|
|
|
@ -8,6 +8,10 @@ use Rector\Architecture\Rector\MethodCall\ServiceLocatorToDIRector;
|
|||
use Rector\Doctrine\Rector\Class_\RemoveRepositoryFromEntityAnnotationRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
/**
|
||||
* @see https://tomasvotruba.com/blog/2017/10/16/how-to-use-repository-with-doctrine-as-service-in-symfony/
|
||||
* @see https://tomasvotruba.com/blog/2018/04/02/rectify-turn-repositories-to-services-in-symfony/
|
||||
*/
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
|
@ -19,4 +23,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
$services->set(ReplaceParentRepositoryCallsByRepositoryPropertyRector::class);
|
||||
|
||||
$services->set(RemoveRepositoryFromEntityAnnotationRector::class);
|
||||
|
||||
$services->set(ReplaceParentRepositoryCallsByRepositoryPropertyRector::class);
|
||||
};
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Architecture\Rector\Class_\MoveRepositoryFromParentToConstructorRector;
|
||||
use Rector\Architecture\Rector\MethodCall\ReplaceParentRepositoryCallsByRepositoryPropertyRector;
|
||||
use Rector\Doctrine\Rector\Class_\RemoveRepositoryFromEntityAnnotationRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
/**
|
||||
* @see https://tomasvotruba.com/blog/2017/10/16/how-to-use-repository-with-doctrine-as-service-in-symfony/
|
||||
* @see https://tomasvotruba.com/blog/2018/04/02/rectify-turn-repositories-to-services-in-symfony/
|
||||
*/
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(ReplaceParentRepositoryCallsByRepositoryPropertyRector::class);
|
||||
|
||||
$services->set(MoveRepositoryFromParentToConstructorRector::class);
|
||||
|
||||
$services->set(RemoveRepositoryFromEntityAnnotationRector::class);
|
||||
};
|
|
@ -1,3 +0,0 @@
|
|||
# for back compatibility
|
||||
imports:
|
||||
- { resource: 'ecs-after-rector.php' }
|
5
ecs.php
5
ecs.php
|
@ -9,6 +9,7 @@ use PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer;
|
|||
use PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer;
|
||||
use PhpCsFixer\Fixer\Phpdoc\PhpdocTypesFixer;
|
||||
use PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer;
|
||||
use PhpCsFixer\Fixer\ReturnNotation\ReturnAssignmentFixer;
|
||||
use PhpCsFixer\Fixer\Strict\StrictComparisonFixer;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\CodingStandard\Fixer\ArrayNotation\StandaloneLineInMultilineArrayFixer;
|
||||
|
@ -77,6 +78,10 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
'*TypeResolverTest.php',
|
||||
],
|
||||
UnaryOperatorSpacesFixer::class => null,
|
||||
|
||||
// breaks on-purpose annotated variables
|
||||
ReturnAssignmentFixer::class => null,
|
||||
|
||||
StrictComparisonFixer::class => [__DIR__ . '/packages/polyfill/src/ConditionEvaluator.php'],
|
||||
]);
|
||||
|
||||
|
|
|
@ -32,6 +32,11 @@ final class AttributeAwareDataProviderTagValueNode implements PhpDocTagValueNode
|
|||
return $this->method;
|
||||
}
|
||||
|
||||
public function getMethodName(): string
|
||||
{
|
||||
return trim($this->method, '()');
|
||||
}
|
||||
|
||||
public function changeMethod(string $method): void
|
||||
{
|
||||
$this->method = $method;
|
||||
|
|
|
@ -35,7 +35,7 @@ final class AttributeAwareMethodTagValueNodeFactory implements AttributeNodeAwar
|
|||
*/
|
||||
public function create(Node $node, string $docContent): AttributeAwareNodeInterface
|
||||
{
|
||||
$returnType = $this->createAttributeAwareReturnType($node, $docContent);
|
||||
$returnType = $this->attributizeReturnType($node, $docContent);
|
||||
|
||||
foreach ($node->parameters as $key => $parameter) {
|
||||
$node->parameters[$key] = $this->attributeAwareNodeFactory->createFromNode($parameter, $docContent);
|
||||
|
@ -55,15 +55,19 @@ final class AttributeAwareMethodTagValueNodeFactory implements AttributeNodeAwar
|
|||
$this->attributeAwareNodeFactory = $attributeAwareNodeFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TypeNode&AttributeAwareNodeInterface
|
||||
*/
|
||||
private function createAttributeAwareReturnType(MethodTagValueNode $methodTagValueNode, string $docContent)
|
||||
{
|
||||
private function attributizeReturnType(
|
||||
MethodTagValueNode $methodTagValueNode,
|
||||
string $docContent
|
||||
): ?AttributeAwareNodeInterface {
|
||||
if ($methodTagValueNode->returnType !== null) {
|
||||
return $this->attributeAwareNodeFactory->createFromNode($methodTagValueNode->returnType, $docContent);
|
||||
return $this->createAttributeAwareReturnType($methodTagValueNode->returnType, $docContent);
|
||||
}
|
||||
|
||||
return $methodTagValueNode->returnType;
|
||||
return null;
|
||||
}
|
||||
|
||||
private function createAttributeAwareReturnType(TypeNode $typeNode, string $docContent): AttributeAwareNodeInterface
|
||||
{
|
||||
return $this->attributeAwareNodeFactory->createFromNode($typeNode, $docContent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ final class AnnotationItemsResolver
|
|||
|
||||
/**
|
||||
* @param object|Annotation|mixed[] $annotationOrItems
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function resolve($annotationOrItems): array
|
||||
{
|
||||
|
|
|
@ -153,7 +153,7 @@ final class PhpDocInfo
|
|||
}
|
||||
|
||||
/**
|
||||
* @return PhpDocTagNode[]
|
||||
* @return PhpDocTagNode[]|AttributeAwareNodeInterface[]
|
||||
*/
|
||||
public function getTagsByName(string $name): array
|
||||
{
|
||||
|
|
|
@ -31,6 +31,9 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
|
|||
*/
|
||||
protected $tagValueNodeConfiguration;
|
||||
|
||||
/**
|
||||
* @param mixed[] $items
|
||||
*/
|
||||
public function __construct(array $items, ?string $originalContent = null)
|
||||
{
|
||||
$this->items = $items;
|
||||
|
@ -144,6 +147,9 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]|string[]
|
||||
*/
|
||||
protected function filterOutMissingItems(array $contentItems): array
|
||||
{
|
||||
if ($this->tagValueNodeConfiguration->getOrderedVisibleItems() === null) {
|
||||
|
|
|
@ -38,6 +38,9 @@ final class EntityTagValueNode extends AbstractDoctrineTagValueNode implements P
|
|||
return $this->printItemsToAttributeString($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function createAttributeItems(): array
|
||||
{
|
||||
$items = $this->items;
|
||||
|
|
|
@ -107,6 +107,9 @@ final class TableTagValueNode extends AbstractDoctrineTagValueNode implements Si
|
|||
return 'name';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function addCustomItems(array $items): array
|
||||
{
|
||||
if ($this->indexes !== []) {
|
||||
|
|
|
@ -38,6 +38,9 @@ final class ColumnTagValueNode extends AbstractDoctrineTagValueNode implements P
|
|||
return $this->printItemsToAttributeString($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function createAttributeItems(): array
|
||||
{
|
||||
$items = $this->items;
|
||||
|
|
|
@ -60,6 +60,9 @@ final class JoinColumnTagValueNode extends AbstractDoctrineTagValueNode implemen
|
|||
return $this->printItemsToAttributeString($this->createAttributeItems());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function createAttributeItems(): array
|
||||
{
|
||||
$items = $this->items;
|
||||
|
|
|
@ -122,6 +122,9 @@ final class JoinTableTagValueNode extends AbstractDoctrineTagValueNode implement
|
|||
return $joinTableAttributeContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function createItems(): array
|
||||
{
|
||||
$items = [];
|
||||
|
|
|
@ -80,6 +80,9 @@ final class ManyToManyTagValueNode extends AbstractDoctrineTagValueNode implemen
|
|||
return $this->printItemsToAttributeString($this->createAttributeItems());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function createAttributeItems(): array
|
||||
{
|
||||
$items = $this->items;
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNode\PHPUnit;
|
||||
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
|
||||
|
||||
final class DataProviderTagValueNode extends AbstractTagValueNode
|
||||
{
|
||||
}
|
|
@ -12,6 +12,9 @@ use Rector\BetterPhpDocParser\ValueObject\TagValueNodeConfiguration;
|
|||
*/
|
||||
trait PrintTagValueNodeTrait
|
||||
{
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
protected function makeKeysExplicit(array $items): array
|
||||
{
|
||||
foreach ($items as $key => $contentItem) {
|
||||
|
@ -32,6 +35,7 @@ trait PrintTagValueNodeTrait
|
|||
|
||||
/**
|
||||
* @param string[] $skipKeys
|
||||
* @return mixed[]
|
||||
*/
|
||||
protected function completeItemsQuotes(array $items, array $skipKeys = []): array
|
||||
{
|
||||
|
|
|
@ -112,6 +112,9 @@ final class TagValueNodeConfiguration
|
|||
return $this->hasClosingBracket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getKeysByQuotedStatus(): array
|
||||
{
|
||||
return $this->keysByQuotedStatus;
|
||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||
namespace Rector\ChangesReporting\Application;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PHPStan\AnalysedCodeException;
|
||||
use Rector\ChangesReporting\Collector\RectorChangeCollector;
|
||||
use Rector\ConsoleDiffer\DifferAndFormatter;
|
||||
|
@ -87,7 +86,7 @@ final class ErrorAndDiffCollector
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Node[]|Stmt[]
|
||||
* @return Node[]
|
||||
*/
|
||||
public function getRemovedNodes(): array
|
||||
{
|
||||
|
|
|
@ -128,12 +128,15 @@ final class ConsoleOutputFormatter implements OutputFormatterInterface
|
|||
private function reportErrors(array $errors): void
|
||||
{
|
||||
foreach ($errors as $error) {
|
||||
$errorMessage = $error->getMessage();
|
||||
$errorMessage = $this->normalizePathsToRelativeWithLine($errorMessage);
|
||||
|
||||
$message = sprintf(
|
||||
'Could not process "%s" file%s, due to: %s"%s".',
|
||||
$error->getFileInfo()->getRelativeFilePathFromCwd(),
|
||||
$error->getRectorClass() ? ' by "' . $error->getRectorClass() . '"' : '',
|
||||
PHP_EOL,
|
||||
$error->getMessage()
|
||||
$errorMessage
|
||||
);
|
||||
|
||||
if ($error->getLine()) {
|
||||
|
@ -154,6 +157,12 @@ final class ConsoleOutputFormatter implements OutputFormatterInterface
|
|||
$this->reportRemovedNodes($errorAndDiffCollector);
|
||||
}
|
||||
|
||||
private function normalizePathsToRelativeWithLine(string $errorMessage): string
|
||||
{
|
||||
$errorMessage = Strings::replace($errorMessage, '#' . preg_quote(getcwd(), '#') . '/#');
|
||||
return $errorMessage = Strings::replace($errorMessage, '# on line #', ':');
|
||||
}
|
||||
|
||||
private function reportRemovedNodes(ErrorAndDiffCollector $errorAndDiffCollector): void
|
||||
{
|
||||
if ($errorAndDiffCollector->getRemovedNodeCount() === 0) {
|
||||
|
|
|
@ -18,6 +18,9 @@ final class StaticInMemoryProbeStorage implements ProbeStorageInterface
|
|||
self::$probeItems[] = $probeItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getProbeItems(): array
|
||||
{
|
||||
// remove empty values
|
||||
|
|
|
@ -60,6 +60,9 @@ final class ClassChildAnalyzer
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string[]
|
||||
*/
|
||||
private function getChildClasses(Class_ $class): array
|
||||
{
|
||||
$className = $class->getAttribute(AttributeKey::CLASS_NAME);
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Rector\FamilyTree\Reflection;
|
|||
final class FamilyRelationsAnalyzer
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
* @return class-string[]
|
||||
*/
|
||||
public function getChildrenOfClass(string $parentClass): array
|
||||
{
|
||||
|
|
|
@ -23,6 +23,8 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
|
|||
|
||||
/**
|
||||
* All parsed nodes grouped type
|
||||
* @template TNodeType of \PhpParser\Node
|
||||
* @see https://phpstan.org/blog/generics-in-php-using-phpdocs
|
||||
*/
|
||||
final class ParsedNodeCollector
|
||||
{
|
||||
|
@ -57,7 +59,7 @@ final class ParsedNodeCollector
|
|||
private $constantsByType = [];
|
||||
|
||||
/**
|
||||
* @var Node[][]
|
||||
* @var array<array<TNodeType>>
|
||||
*/
|
||||
private $simpleParsedNodesByType = [];
|
||||
|
||||
|
@ -82,9 +84,8 @@ final class ParsedNodeCollector
|
|||
}
|
||||
|
||||
/**
|
||||
* @template T of object
|
||||
* @param class-string<T> $type
|
||||
* @return Node[]|iterable<T>
|
||||
* @param class-string<TNodeType> $type
|
||||
* @return array<TNodeType>
|
||||
*/
|
||||
public function getNodesByType(string $type): array
|
||||
{
|
||||
|
@ -197,7 +198,6 @@ final class ParsedNodeCollector
|
|||
{
|
||||
$newNodesByClass = [];
|
||||
|
||||
/** @var New_[] $news */
|
||||
$news = $this->getNodesByType(New_::class);
|
||||
|
||||
foreach ($news as $new) {
|
||||
|
|
|
@ -153,6 +153,7 @@ final class NodeNameResolver
|
|||
|
||||
/**
|
||||
* @param Name[]|Node[] $nodes
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNames(array $nodes): array
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@ use PHPStan\Type\Type;
|
|||
interface NodeTypeResolverInterface
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
* @return class-string[]
|
||||
*/
|
||||
public function getNodeClasses(): array;
|
||||
|
||||
|
|
|
@ -155,6 +155,9 @@ final class PHPStanServicesFactory
|
|||
return $this->container->getByType(TypeNodeResolver::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function appendPhpstanPHPUnitExtensionIfExists(
|
||||
string $currentWorkingDirectory,
|
||||
array $additionalConfigFiles
|
||||
|
|
|
@ -181,4 +181,9 @@ final class AttributeKey
|
|||
* @var string
|
||||
*/
|
||||
public const CLOSURE_NODE = Closure::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const PARAMETER_POSITION = 'parameter_position';
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use PhpParser\NodeVisitor\NodeConnectingVisitor;
|
|||
use Rector\Core\Configuration\Configuration;
|
||||
use Rector\NodeCollector\NodeVisitor\NodeCollectorNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\FileInfoNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\FunctionLikeParamPositionNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\FunctionMethodAndClassNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\NamespaceNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\PhpDocInfoNodeVisitor;
|
||||
|
@ -71,6 +72,11 @@ final class NodeScopeAndMetadataDecorator
|
|||
*/
|
||||
private $nodeConnectingVisitor;
|
||||
|
||||
/**
|
||||
* @var FunctionLikeParamPositionNodeVisitor
|
||||
*/
|
||||
private $functionLikeParamPositionNodeVisitor;
|
||||
|
||||
public function __construct(
|
||||
CloningVisitor $cloningVisitor,
|
||||
Configuration $configuration,
|
||||
|
@ -81,7 +87,8 @@ final class NodeScopeAndMetadataDecorator
|
|||
PHPStanNodeScopeResolver $phpStanNodeScopeResolver,
|
||||
PhpDocInfoNodeVisitor $phpDocInfoNodeVisitor,
|
||||
StatementNodeVisitor $statementNodeVisitor,
|
||||
NodeConnectingVisitor $nodeConnectingVisitor
|
||||
NodeConnectingVisitor $nodeConnectingVisitor,
|
||||
FunctionLikeParamPositionNodeVisitor $functionLikeParamPositionNodeVisitor
|
||||
) {
|
||||
$this->phpStanNodeScopeResolver = $phpStanNodeScopeResolver;
|
||||
$this->cloningVisitor = $cloningVisitor;
|
||||
|
@ -93,6 +100,7 @@ final class NodeScopeAndMetadataDecorator
|
|||
$this->configuration = $configuration;
|
||||
$this->phpDocInfoNodeVisitor = $phpDocInfoNodeVisitor;
|
||||
$this->nodeConnectingVisitor = $nodeConnectingVisitor;
|
||||
$this->functionLikeParamPositionNodeVisitor = $functionLikeParamPositionNodeVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,6 +140,7 @@ final class NodeScopeAndMetadataDecorator
|
|||
$nodeTraverser->addVisitor($this->functionMethodAndClassNodeVisitor);
|
||||
$nodeTraverser->addVisitor($this->namespaceNodeVisitor);
|
||||
$nodeTraverser->addVisitor($this->phpDocInfoNodeVisitor);
|
||||
$nodeTraverser->addVisitor($this->functionLikeParamPositionNodeVisitor);
|
||||
|
||||
$nodes = $nodeTraverser->traverse($nodes);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ use Rector\TypeDeclaration\PHPStan\Type\ObjectTypeSpecifier;
|
|||
final class NodeTypeResolver
|
||||
{
|
||||
/**
|
||||
* @var NodeTypeResolverInterface[]
|
||||
* @var array<class-string, NodeTypeResolverInterface>
|
||||
*/
|
||||
private $nodeTypeResolvers = [];
|
||||
|
||||
|
|
|
@ -54,8 +54,11 @@ final class ClassAndInterfaceTypeResolver implements NodeTypeResolverInterface
|
|||
return new MixedType();
|
||||
}
|
||||
|
||||
/** @var ClassReflection $classReflection */
|
||||
/** @var ClassReflection|null $classReflection */
|
||||
$classReflection = $nodeScope->getClassReflection();
|
||||
if ($classReflection === null) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
$classTypes = $this->classReflectionTypesResolver->resolve($classReflection);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ use PhpParser\NodeTraverser;
|
|||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\PhpParser\NodeTraverser\CallableNodeTraverser;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
|
||||
|
@ -131,15 +132,23 @@ final class ParamTypeResolver implements NodeTypeResolverInterface
|
|||
|
||||
private function resolveFromFunctionDocBlock(Param $param): Type
|
||||
{
|
||||
/** @var FunctionLike $parentNode */
|
||||
$parentNode = $param->getAttribute(AttributeKey::PARENT_NODE);
|
||||
$phpDocInfo = $this->getFunctionLikePhpDocInfo($param);
|
||||
if ($phpDocInfo === null) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
/** @var string $paramName */
|
||||
$paramName = $this->nodeNameResolver->getName($param);
|
||||
|
||||
/** @var PhpDocInfo $phpDocInfo */
|
||||
$phpDocInfo = $parentNode->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
|
||||
return $phpDocInfo->getParamType($paramName);
|
||||
}
|
||||
|
||||
private function getFunctionLikePhpDocInfo(Param $param): ?PhpDocInfo
|
||||
{
|
||||
$parentNode = $param->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $parentNode instanceof FunctionLike) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return $parentNode->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
|
|||
|
||||
final class ScalarTypeResolver implements NodeTypeResolverInterface
|
||||
{
|
||||
/**
|
||||
* @return class-string[]
|
||||
*/
|
||||
public function getNodeClasses(): array
|
||||
{
|
||||
return [Scalar::class];
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\NodeVisitor;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\FunctionLike;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
final class FunctionLikeParamPositionNodeVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @return Node
|
||||
*/
|
||||
public function enterNode(Node $node): ?Node
|
||||
{
|
||||
if (! $node instanceof FunctionLike) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($node->getParams() as $position => $param) {
|
||||
$param->setAttribute(AttributeKey::PARAMETER_POSITION, $position);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
|
@ -88,10 +88,7 @@ final class FunctionMethodAndClassNodeVisitor extends NodeVisitorAbstract
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|void|null
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
public function enterNode(Node $node): ?Node
|
||||
{
|
||||
$this->processClass($node);
|
||||
$this->processMethod($node);
|
||||
|
|
|
@ -20,10 +20,7 @@ final class PhpDocInfoNodeVisitor extends NodeVisitorAbstract
|
|||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|void|null
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
public function enterNode(Node $node): ?Node
|
||||
{
|
||||
// also binds to the node
|
||||
$this->phpDocInfoFactory->createFromNode($node);
|
||||
|
|
|
@ -7,7 +7,6 @@ namespace Rector\NodeTypeResolver\NodeVisitor;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
final class StatementNodeVisitor extends NodeVisitorAbstract
|
||||
|
@ -28,16 +27,12 @@ final class StatementNodeVisitor extends NodeVisitorAbstract
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|void|null
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
public function enterNode(Node $node): ?Node
|
||||
{
|
||||
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parent === null) {
|
||||
if (! $node instanceof Stmt) {
|
||||
return null;
|
||||
// throw new ShouldNotHappenException('Only statement can appear at top level');
|
||||
}
|
||||
|
||||
$node->setAttribute(AttributeKey::PREVIOUS_STATEMENT, $this->previousStmt);
|
||||
|
@ -45,7 +40,7 @@ final class StatementNodeVisitor extends NodeVisitorAbstract
|
|||
$this->previousStmt = $node;
|
||||
}
|
||||
|
||||
if (isset($node->stmts)) {
|
||||
if (property_exists($node, 'stmts')) {
|
||||
$previous = $node;
|
||||
foreach ((array) $node->stmts as $stmt) {
|
||||
$stmt->setAttribute(AttributeKey::PREVIOUS_STATEMENT, $previous);
|
||||
|
@ -53,15 +48,21 @@ final class StatementNodeVisitor extends NodeVisitorAbstract
|
|||
$previous = $stmt;
|
||||
}
|
||||
}
|
||||
if ($parent && ! $node->getAttribute(AttributeKey::CURRENT_STATEMENT)) {
|
||||
|
||||
$currentStmt = $node->getAttribute(AttributeKey::CURRENT_STATEMENT);
|
||||
|
||||
if ($parent && ! $currentStmt) {
|
||||
$node->setAttribute(
|
||||
AttributeKey::PREVIOUS_STATEMENT,
|
||||
$parent->getAttribute(AttributeKey::PREVIOUS_STATEMENT)
|
||||
);
|
||||
|
||||
$node->setAttribute(
|
||||
AttributeKey::CURRENT_STATEMENT,
|
||||
$parent->getAttribute(AttributeKey::CURRENT_STATEMENT)
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,10 +38,7 @@ final class RemoveDeepChainMethodCallNodeVisitor extends NodeVisitorAbstract
|
|||
$this->nestedChainMethodCallLimit = $nestedChainMethodCallLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|null
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
public function enterNode(Node $node): ?int
|
||||
{
|
||||
if (! $node instanceof Expression) {
|
||||
return null;
|
||||
|
@ -60,7 +57,7 @@ final class RemoveDeepChainMethodCallNodeVisitor extends NodeVisitorAbstract
|
|||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|Node[]|null
|
||||
* @return Nop|Node
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ use Rector\Polyfill\ValueObject\VersionCompareCondition;
|
|||
final class ConditionEvaluator
|
||||
{
|
||||
/**
|
||||
* @return bool|int|mixed|null
|
||||
* @return bool|null|int
|
||||
*/
|
||||
public function evaluate(ConditionInterface $condition)
|
||||
{
|
||||
|
|
|
@ -57,12 +57,18 @@ final class NodesToAddCollector implements NodeCollectorInterface
|
|||
$this->nodesToAddAfter[$position][] = $this->wrapToExpression($addedNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stmt[]
|
||||
*/
|
||||
public function getNodesToAddAfterNode(Node $node): array
|
||||
{
|
||||
$position = spl_object_hash($node);
|
||||
return $this->nodesToAddAfter[$position] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stmt[]
|
||||
*/
|
||||
public function getNodesToAddBeforeNode(Node $node): array
|
||||
{
|
||||
$position = spl_object_hash($node);
|
||||
|
|
|
@ -79,7 +79,7 @@ final class NodesToRemoveCollector implements NodeCollectorInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Node[]|Stmt[]
|
||||
* @return Node[]
|
||||
*/
|
||||
public function getNodesToRemove(): array
|
||||
{
|
||||
|
|
|
@ -71,6 +71,7 @@ final class PropertyToAddCollector implements NodeCollectorInterface
|
|||
|
||||
/**
|
||||
* @var ClassConst[]
|
||||
* @return ClassConst[]
|
||||
*/
|
||||
public function getConstantsByClass(Class_ $class): array
|
||||
{
|
||||
|
@ -79,7 +80,7 @@ final class PropertyToAddCollector implements NodeCollectorInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @var Type[]|null[]
|
||||
* @return Type[]|null[]
|
||||
*/
|
||||
public function getPropertiesByClass(Class_ $class): array
|
||||
{
|
||||
|
@ -88,7 +89,7 @@ final class PropertyToAddCollector implements NodeCollectorInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @var Type[]|null[]
|
||||
* @return Type[]|null[]
|
||||
*/
|
||||
public function getPropertiesWithoutConstructorByClass(Class_ $class): array
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ final class NodeAddingPostRector extends AbstractPostRector
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Node[]|Node|null
|
||||
* @return mixed[]|Node
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
|
|
|
@ -74,7 +74,7 @@ final class NodeRemovingRector extends AbstractPostRector
|
|||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|Node[]|null
|
||||
* @return int|Node
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
|
|
|
@ -105,7 +105,9 @@ final class CreateCommand extends Command
|
|||
{
|
||||
$rectorRecipe = $this->parameterProvider->provideParameter(Option::RECTOR_RECIPE);
|
||||
|
||||
$configuration = $this->configurationFactory->createFromRectorRecipe($rectorRecipe);
|
||||
$isRectorRepository = $this->isRectorRepository();
|
||||
$configuration = $this->configurationFactory->createFromRectorRecipe($rectorRecipe, $isRectorRepository);
|
||||
|
||||
$templateVariables = $this->templateVariablesFactory->createFromConfiguration($configuration);
|
||||
|
||||
// setup psr-4 autoload, if not already in
|
||||
|
@ -118,7 +120,7 @@ final class CreateCommand extends Command
|
|||
$isUnwantedOverride = $this->overrideGuard->isUnwantedOverride(
|
||||
$templateFileInfos,
|
||||
$templateVariables,
|
||||
$configuration->getPackage(),
|
||||
$configuration,
|
||||
$targetDirectory
|
||||
);
|
||||
if ($isUnwantedOverride) {
|
||||
|
@ -143,6 +145,11 @@ final class CreateCommand extends Command
|
|||
return ShellCode::SUCCESS;
|
||||
}
|
||||
|
||||
private function isRectorRepository(): bool
|
||||
{
|
||||
return file_exists(__DIR__ . '/../../../../vendor');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $generatedFilePaths
|
||||
*/
|
||||
|
|
|
@ -17,6 +17,11 @@ final class ComposerPackageAutoloadUpdater
|
|||
*/
|
||||
private const PSR_4 = 'psr-4';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const AUTOLOAD_DEV = 'autoload-dev';
|
||||
|
||||
/**
|
||||
* @var JsonFileSystem
|
||||
*/
|
||||
|
@ -55,8 +60,10 @@ final class ComposerPackageAutoloadUpdater
|
|||
return;
|
||||
}
|
||||
|
||||
$composerJson['autoload'][self::PSR_4][$package->getSrcNamespace()] = $package->getSrcDirectory();
|
||||
$composerJson['autoload-dev'][self::PSR_4][$package->getTestsNamespace()] = $package->getTestsDirectory();
|
||||
$srcAutoload = $configuration->isRectorRepository() ? 'autoload' : self::AUTOLOAD_DEV;
|
||||
$composerJson[$srcAutoload][self::PSR_4][$package->getSrcNamespace()] = $package->getSrcDirectory();
|
||||
|
||||
$composerJson[self::AUTOLOAD_DEV][self::PSR_4][$package->getTestsNamespace()] = $package->getTestsDirectory();
|
||||
|
||||
$this->jsonFileSystem->saveJsonToFile($composerJsonFilePath, $composerJson);
|
||||
|
||||
|
@ -65,7 +72,7 @@ final class ComposerPackageAutoloadUpdater
|
|||
|
||||
private function resolvePackage(Configuration $configuration): Package
|
||||
{
|
||||
if ($configuration->getPackage() === Package::UTILS) {
|
||||
if (! $configuration->isRectorRepository()) {
|
||||
return new Package(
|
||||
'Utils\\Rector\\',
|
||||
'Utils\\Rector\\Tests\\',
|
||||
|
@ -84,7 +91,13 @@ final class ComposerPackageAutoloadUpdater
|
|||
|
||||
private function isPackageAlreadyLoaded(array $composerJson, Package $package): bool
|
||||
{
|
||||
return isset($composerJson['autoload'][self::PSR_4][$package->getSrcNamespace()]);
|
||||
foreach (['autoload', self::AUTOLOAD_DEV] as $autoloadSection) {
|
||||
if (isset($composerJson[$autoloadSection][self::PSR_4][$package->getSrcNamespace()])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function rebuildAutoload(): void
|
||||
|
|
|
@ -32,7 +32,7 @@ final class ConfigurationFactory
|
|||
/**
|
||||
* @param mixed[] $rectorRecipe
|
||||
*/
|
||||
public function createFromRectorRecipe(array $rectorRecipe): Configuration
|
||||
public function createFromRectorRecipe(array $rectorRecipe, bool $isRectorRepository): Configuration
|
||||
{
|
||||
$this->recipeGuard->ensureRecipeIsValid($rectorRecipe);
|
||||
|
||||
|
@ -55,7 +55,8 @@ final class ConfigurationFactory
|
|||
(array) $rectorRecipe[RecipeOption::RULE_CONFIGURATION],
|
||||
array_filter((array) $rectorRecipe[RecipeOption::SOURCE]),
|
||||
$set,
|
||||
$this->isPhpSnippet($rectorRecipe[RecipeOption::CODE_BEFORE])
|
||||
$this->isPhpSnippet($rectorRecipe[RecipeOption::CODE_BEFORE]),
|
||||
$isRectorRepository
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Rector\RectorGenerator\FileSystem;
|
|||
use Nette\Utils\Strings;
|
||||
use Rector\Core\Testing\PHPUnit\StaticPHPUnitEnvironment;
|
||||
use Rector\RectorGenerator\Finder\TemplateFinder;
|
||||
use Rector\RectorGenerator\ValueObject\Configuration;
|
||||
use Rector\RectorGenerator\ValueObject\Package;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
|
@ -18,13 +19,13 @@ final class TemplateFileSystem
|
|||
public function resolveDestination(
|
||||
SmartFileInfo $smartFileInfo,
|
||||
array $templateVariables,
|
||||
string $package,
|
||||
Configuration $configuration,
|
||||
string $targetDirectory
|
||||
): string {
|
||||
$destination = $smartFileInfo->getRelativeFilePathFromDirectory(TemplateFinder::TEMPLATES_DIRECTORY);
|
||||
|
||||
// normalize core package
|
||||
if ($package === Package::UTILS) {
|
||||
if (! $configuration->isRectorRepository()) {
|
||||
// special keyword for 3rd party Rectors, not for core Github contribution
|
||||
$destination = Strings::replace($destination, '#packages\/__Package__#', 'utils/rector');
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ final class FileGenerator
|
|||
$generatedFilePaths[] = $this->generateFileInfoWithTemplateVariables(
|
||||
$fileInfo,
|
||||
$templateVariables,
|
||||
$configuration->getPackage(),
|
||||
$configuration,
|
||||
$destinationDirectory
|
||||
);
|
||||
}
|
||||
|
@ -64,13 +64,13 @@ final class FileGenerator
|
|||
private function generateFileInfoWithTemplateVariables(
|
||||
SmartFileInfo $smartFileInfo,
|
||||
array $templateVariables,
|
||||
string $package,
|
||||
Configuration $configuration,
|
||||
string $targetDirectory
|
||||
): string {
|
||||
$targetFilePath = $this->templateFileSystem->resolveDestination(
|
||||
$smartFileInfo,
|
||||
$templateVariables,
|
||||
$package,
|
||||
$configuration,
|
||||
$targetDirectory
|
||||
);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace Rector\RectorGenerator\Guard;
|
||||
|
||||
use Rector\RectorGenerator\FileSystem\TemplateFileSystem;
|
||||
use Rector\RectorGenerator\ValueObject\Configuration;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
|
@ -32,11 +33,16 @@ final class OverrideGuard
|
|||
public function isUnwantedOverride(
|
||||
array $templateFileInfos,
|
||||
array $templateVariables,
|
||||
string $package,
|
||||
Configuration $configuration,
|
||||
string $targetDirectory
|
||||
): bool {
|
||||
foreach ($templateFileInfos as $templateFileInfo) {
|
||||
if (! $this->doesFileInfoAlreadyExist($templateVariables, $package, $templateFileInfo, $targetDirectory)) {
|
||||
if (! $this->doesFileInfoAlreadyExist(
|
||||
$templateVariables,
|
||||
$configuration,
|
||||
$templateFileInfo,
|
||||
$targetDirectory
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -48,14 +54,14 @@ final class OverrideGuard
|
|||
|
||||
private function doesFileInfoAlreadyExist(
|
||||
array $templateVariables,
|
||||
string $package,
|
||||
Configuration $configuration,
|
||||
SmartFileInfo $templateFileInfo,
|
||||
string $targetDirectory
|
||||
): bool {
|
||||
$destination = $this->templateFileSystem->resolveDestination(
|
||||
$templateFileInfo,
|
||||
$templateVariables,
|
||||
$package,
|
||||
$configuration,
|
||||
$targetDirectory
|
||||
);
|
||||
|
||||
|
|
|
@ -18,6 +18,11 @@ final class Configuration
|
|||
*/
|
||||
private $package;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isRectorRepository = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
@ -95,7 +100,8 @@ final class Configuration
|
|||
array $ruleConfiguration,
|
||||
array $source,
|
||||
?Set $set,
|
||||
bool $isPhpSnippet
|
||||
bool $isPhpSnippet,
|
||||
bool $isRectorRepository
|
||||
) {
|
||||
$this->package = $package;
|
||||
$this->setName($name);
|
||||
|
@ -110,6 +116,7 @@ final class Configuration
|
|||
$this->extraFileContent = $extraFileContent;
|
||||
$this->extraFileName = $extraFileName;
|
||||
$this->ruleConfiguration = $ruleConfiguration;
|
||||
$this->isRectorRepository = $isRectorRepository;
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
|
@ -119,11 +126,19 @@ final class Configuration
|
|||
|
||||
public function getPackage(): string
|
||||
{
|
||||
if (! $this->isRectorRepository) {
|
||||
return 'Utils';
|
||||
}
|
||||
|
||||
return $this->package;
|
||||
}
|
||||
|
||||
public function getPackageDirectory(): string
|
||||
{
|
||||
if (! $this->isRectorRepository) {
|
||||
return 'rector';
|
||||
}
|
||||
|
||||
// special cases
|
||||
if ($this->package === 'PHPUnit') {
|
||||
return 'phpunit';
|
||||
|
@ -200,6 +215,11 @@ final class Configuration
|
|||
return $this->ruleConfiguration;
|
||||
}
|
||||
|
||||
public function isRectorRepository(): bool
|
||||
{
|
||||
return $this->isRectorRepository;
|
||||
}
|
||||
|
||||
private function setName(string $name): void
|
||||
{
|
||||
if (! Strings::endsWith($name, 'Rector')) {
|
||||
|
|
|
@ -87,6 +87,6 @@ final class RectorGeneratorTest extends AbstractKernelTestCase
|
|||
{
|
||||
$rectorRecipe = StaticRectorRecipeFactory::createWithConfiguration();
|
||||
|
||||
return $this->configurationFactory->createFromRectorRecipe($rectorRecipe);
|
||||
return $this->configurationFactory->createFromRectorRecipe($rectorRecipe, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -705,11 +705,4 @@ final class SetList
|
|||
* @var string
|
||||
*/
|
||||
public const UNWRAP_COMPAT = __DIR__ . '/../../../../config/set/unwrap-compat.php';
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const REPOSITORY_AS_SERVICE = __DIR__ . '/../../../../config/set/repository-as-service.php';
|
||||
}
|
||||
|
|
49
phpstan.neon
49
phpstan.neon
|
@ -28,10 +28,11 @@ parameters:
|
|||
# see https://github.com/symplify/coding-standard
|
||||
symplify:
|
||||
max_cognitive_complexity: 9 # default: 8
|
||||
# @todo update, to make classes smaller
|
||||
# max_class_cognitive_complexity: 40 # default: 50
|
||||
max_class_cognitive_complexity: 50
|
||||
|
||||
parent_classes:
|
||||
- Rector
|
||||
|
||||
required_see_types:
|
||||
- PHPStan\Rules\Rule
|
||||
- Rector\Core\Rector\AbstractRector
|
||||
|
@ -70,6 +71,10 @@ parameters:
|
|||
- config
|
||||
|
||||
excludes_analyse:
|
||||
# iterable types
|
||||
- '#with no value type specified in iterable type array#'
|
||||
- '#type specified in iterable type (array|iterable)#'
|
||||
|
||||
# phsptan bug
|
||||
- utils/phpstan-extensions/src/Rule/PreventParentMethodVisibilityOverrideRule.php
|
||||
- utils/phpstan-extensions/src/Rule/KeepRectorNamespaceForRectorRule.php
|
||||
|
@ -90,6 +95,11 @@ parameters:
|
|||
- '*/tests/Rector/Psr4/MultipleClassFileToPsr4ClassesRector/Expected/Just*ExceptionWithoutNamespace.php'
|
||||
|
||||
ignoreErrors:
|
||||
# @todo remove
|
||||
# iterable types
|
||||
- '#with no value type specified in iterable type array#'
|
||||
- '#type specified in iterable type (array|iterable)#'
|
||||
|
||||
# false positive
|
||||
- '#PHPDoc tag \@param for parameter \$node with type float is incompatible with native type PhpParser\\Node#'
|
||||
|
||||
|
@ -118,7 +128,6 @@ parameters:
|
|||
|
||||
# known values
|
||||
- '#Cannot access property \$value on PhpParser\\Node\\Expr\\ArrayItem\|null#'
|
||||
- '#Method Rector\\Symfony\\Rector\\New_\\StringToArrayArgumentProcessRector::findPreviousNodeAssign\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#'
|
||||
|
||||
# known values
|
||||
- '#Strict comparison using === between PhpParser\\Node\\Expr and null will always evaluate to false#'
|
||||
|
@ -179,9 +188,6 @@ parameters:
|
|||
|
||||
- '#Method Rector\\Doctrine\\Rector\\MethodCall\\ChangeSetIdToUuidValueRector\:\:getSetUuidMethodCallOnSameVariable\(\) should return PhpParser\\Node\\Expr\\MethodCall\|null but returns PhpParser\\Node\|null#'
|
||||
|
||||
# bugs
|
||||
- '#Parameter \#1 \$items of class PhpParser\\Node\\Expr\\Array_ constructor expects array<PhpParser\\Node\\Expr\\ArrayItem\>, array<PhpParser\\Node\\Expr\\ArrayItem\|null\> given#'
|
||||
|
||||
# known value
|
||||
- '#Method Rector\\StrictCodeQuality\\Rector\\Stmt\\VarInlineAnnotationToAssertRector\:\:findVariableByName\(\) should return PhpParser\\Node\\Expr\\Variable\|null but returns PhpParser\\Node\|null#'
|
||||
|
||||
|
@ -238,7 +244,6 @@ parameters:
|
|||
|
||||
- '#Parameter \#1 \$sprintfFuncCall of method Rector\\Core\\PhpParser\\NodeTransformer\:\:transformSprintfToArray\(\) expects PhpParser\\Node\\Expr\\FuncCall, PhpParser\\Node given#'
|
||||
- '#Parameter \#1 \$nodes of method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:find\(\) expects array<PhpParser\\Node\>\|PhpParser\\Node, array<PhpParser\\Node\\Stmt\>\|null given#'
|
||||
- '#PHPDoc tag @return with type iterable<object\> is not subtype of native type array#'
|
||||
- '#Method Rector\\SOLID\\Reflection\\ParentConstantReflectionResolver\:\:(.*?)\(\) should return ReflectionClassConstant\|null but returns ReflectionClassConstant\|false#'
|
||||
- '#Parameter \#1 \$firstStmt of method Rector\\Generic\\Rector\\MethodBody\\NormalToFluentRector\:\:isBothMethodCallMatch\(\) expects PhpParser\\Node\\Stmt\\Expression, PhpParser\\Node\\Stmt given#'
|
||||
- '#Method Rector\\Core\\Rector\\AbstractRector\:\:wrapToArg\(\) should return array<PhpParser\\Node\\Arg\> but returns array<PhpParser\\Node\\Arg\|PhpParser\\Node\\Expr\>#'
|
||||
|
@ -287,10 +292,6 @@ parameters:
|
|||
- *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
|
||||
|
@ -317,7 +318,6 @@ parameters:
|
|||
- "#^Cognitive complexity for \"Rector\\\\Php70\\\\EregToPcreTransformer\\:\\:(.*?)\" is (.*?), keep it under 9$#"
|
||||
|
||||
- '#Use explicit return value over magic &reference#'
|
||||
- '#Method Rector\\Order\\StmtOrder\:\:createOldToNewKeys\(\) should return array<int\> but returns array\|false#'
|
||||
|
||||
- '#In method "Rector\\Utils\\ProjectValidator\\Process\\ParallelTaskRunner\:\:(.*?)", caught "Throwable" must be rethrown\. Either catch a more specific exception or add a "throw" clause in the "catch" block to propagate the exception#'
|
||||
# weird
|
||||
|
@ -327,25 +327,20 @@ parameters:
|
|||
- '#Class cognitive complexity for "DumpNodesCommand" is \d+, keep it under 50#'
|
||||
- '#Cognitive complexity for "Rector\\Utils\\DocumentationGenerator\\Command\\DumpNodesCommand\:\:execute\(\)" is \d+, keep it under 9#'
|
||||
|
||||
- '#Method Rector\\Utils\\DocumentationGenerator\\Node\\NodeClassProvider\:\:getNodeClasses\(\) should return array<class\-string\> but returns array<int, \(int\|string\)\>#'
|
||||
|
||||
- '#Parameter \#1 \$node of method Rector\\PostRector\\Collector\\NodesToAddCollector\:\:wrapToExpression\(\) expects PhpParser\\Node\\Expr\|PhpParser\\Node\\Stmt, PhpParser\\Node given#'
|
||||
- '#Access to an undefined property PhpParser\\Node\\Expr\:\:\$class#'
|
||||
- '#Method Rector\\BetterPhpDocParser\\Tests\\PhpDocParser\\AbstractPhpDocInfoTest\:\:parseFileAndGetFirstNodeOfType\(\) should return PhpParser\\Node but returns PhpParser\\Node\|null#'
|
||||
- '#Method Rector\\Core\\Testing\\Finder\\RectorsFinder\:\:findInDirectories\(\) should return array<Rector\\Core\\Contract\\Rector\\RectorInterface\> but returns array<object\>#'
|
||||
- '#Property PhpParser\\Node\\Stmt\\Namespace_\:\:\$stmts \(array<PhpParser\\Node\\Stmt\>\) does not accept array<PhpParser\\Node\>#'
|
||||
|
||||
- '#Cognitive complexity for "Rector\\TypeDeclaration\\PHPStan\\Type\\ObjectTypeSpecifier\:\:matchShortenedObjectType\(\)" is 10, keep it under 9#'
|
||||
- '#Parameter \#1 \$type of method PhpParser\\Builder\\FunctionLike\:\:setReturnType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#'
|
||||
- '#Cognitive complexity for "Rector\\Core\\PhpParser\\Node\\Value\\ValueResolver\:\:getValue\(\)" is \d+, keep it under 9#'
|
||||
- '#Cognitive complexity for "Rector\\NetteKdyby\\NodeResolver\\ListeningMethodsCollector\:\:collectFromClassAndGetSubscribedEventClassMethod\(\)" is 11, keep it under 9#'
|
||||
- '#Cognitive complexity for "Rector\\NetteKdyby\\ContributeEventClassResolver\:\:resolveGetterMethodByEventClassAndParam\(\)" is \d+, keep it under 9#'
|
||||
- '#Parameter \#1 \$type of class PhpParser\\Node\\NullableType constructor expects PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#'
|
||||
- '#Parameter \#1 \$object of function get_class expects object, PhpParser\\Node\|null given#'
|
||||
- '#Class "Rector\\FileSystemRector\\Rector\\Removing\\RemoveProjectFileRector" is missing @see annotation with test case class reference#'
|
||||
- '#Parameter \#1 \$type of method PhpParser\\Builder\\Param\:\:setType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#'
|
||||
- '#Parameter \#1 \$node of method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findFirstAncestorInstanceOf\(\) expects PhpParser\\Node, PhpParser\\Node\\Expr\\Variable\|null given#'
|
||||
- '#Parameter \#1 \$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#'
|
||||
- '#Method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findFirstNonAnonymousClass\(\) should return PhpParser\\Node\\Stmt\\Class_\|null but returns PhpParser\\Node\|null#'
|
||||
|
@ -366,7 +361,6 @@ parameters:
|
|||
- '#Call to an undefined method PhpParser\\Node\\Expr\\Error\|PhpParser\\Node\\Identifier\:\:toString\(\)#'
|
||||
- '#Class Rector\\Renaming\\Tests\\Rector\\MethodCall\\RenameMethodRector\\Fixture\\SkipSelfMethodRename not found#'
|
||||
|
||||
|
||||
# fixed in symplfiy dev
|
||||
-
|
||||
message: '#Separate function "Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ref\(\)" in method call to standalone row to improve readability#'
|
||||
|
@ -381,12 +375,21 @@ parameters:
|
|||
- '#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#'
|
||||
- '#Parameter \#1 \$files of method Symplify\\SmartFileSystem\\Finder\\FinderSanitizer\:\:sanitize\(\) expects \(iterable<SplFileInfo\|string\>&Nette\\Utils\\Finder\)\|Symfony\\Component\\Finder\\Finder, array<string\> given#'
|
||||
- '#Method Rector\\Core\\PhpParser\\Node\\Manipulator\\ChainMethodCallManipulator\:\:resolveRootMethodCall\(\) should return PhpParser\\Node\\Expr\\MethodCall\|null but returns PhpParser\\Node\|null#'
|
||||
- '#Static property Symplify\\PackageBuilder\\Tests\\AbstractKernelTestCase\:\:\$container \(Psr\\Container\\ContainerInterface\) does not accept Rector\\Naming\\Tests\\Rector\\Class_\\RenamePropertyToMatchTypeRector\\Source\\ContainerInterface\|Symfony\\Component\\DependencyInjection\\Container#'
|
||||
- '#Static property Rector\\Core\\Testing\\PHPUnit\\AbstractGenericRectorTestCase\:\:\$allRectorContainer \(Rector\\Naming\\Tests\\Rector\\Class_\\RenamePropertyToMatchTypeRector\\Source\\ContainerInterface\|Symfony\\Component\\DependencyInjection\\Container\|null\) does not accept Psr\\Container\\ContainerInterface#'
|
||||
- '#Separate function "Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ref\(\)" in method call to standalone row to improve readability#'
|
||||
- '#Class with base "(.*?)" name is already used in "_HumbugBox(.*?)#'
|
||||
- '#Class Rector\\MagicDisclosure\\Tests\\Rector\\ClassMethod\\ReturnThisRemoveRector\\FixtureConfiguration\\SomeClass not found#'
|
||||
# stubs
|
||||
- '#Class Nette\\DI\\CompilerExtension not found#'
|
||||
- '#Class Latte\\Macros\\MacroSet not found#'
|
||||
|
||||
|
||||
- '#Static property Symplify\\PackageBuilder\\Tests\\AbstractKernelTestCase\:\:\$container \(Psr\\Container\\ContainerInterface\) does not accept Rector\\Naming\\Tests\\Rector\\Class_\\RenamePropertyToMatchTypeRector\\Source\\ContainerInterface\|Symfony\\Component\\DependencyInjection\\Container#'
|
||||
|
||||
# wtf
|
||||
-
|
||||
message: '#Else branch is unreachable because ternary operator condition is always true#'
|
||||
path: 'rules/psr4/src/Composer/PSR4NamespaceMatcher.php'
|
||||
|
||||
# false positive
|
||||
- '#Empty array passed to foreach#'
|
||||
- '#Parameter \#1 \$arrayItem of method Rector\\NetteKdyby\\NodeResolver\\ListeningMethodsCollector\:\:resolveCustomClassMethodAndEventClass\(\) expects PhpParser\\Node\\Expr\\ArrayItem, PhpParser\\Node given#'
|
||||
- '#Method Rector\\CodeQuality\\Rector\\Class_\\CompleteDynamicPropertiesRector\:\:resolvePropertiesToComplete\(\) should return array<int, PhpParser\\Node\\Stmt\\Property\> but returns array<int, \(int\|string\)\>#'
|
||||
- '#Parameter \#1 \$type of method Rector\\NodeCollector\\NodeCollector\\ParsedNodeCollector<TNodeType of PhpParser\\Node\>\:\:getNodesByType\(\) expects class\-string<TNodeType of PhpParser\\Node\>, string given#'
|
||||
|
|
11
rector.php
11
rector.php
|
@ -4,14 +4,23 @@ declare(strict_types=1);
|
|||
|
||||
use Rector\Core\Configuration\Option;
|
||||
use Rector\Set\ValueObject\SetList;
|
||||
use Rector\TypeDeclaration\Rector\ClassMethod\AddArrayParamDocTypeRector;
|
||||
use Rector\TypeDeclaration\Rector\ClassMethod\AddArrayReturnDocTypeRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
// @todo make part of Rector CI
|
||||
// add array-types
|
||||
$services->set(AddArrayParamDocTypeRector::class);
|
||||
$services->set(AddArrayReturnDocTypeRector::class);
|
||||
|
||||
$containerConfigurator->import(__DIR__ . '/create-rector.php', null, 'not_found');
|
||||
|
||||
$parameters = $containerConfigurator->parameters();
|
||||
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
|
||||
$parameters->set(Option::SETS, [SetList::NAMING, SetList::REPOSITORY_AS_SERVICE]);
|
||||
$parameters->set(Option::SETS, [SetList::NAMING]);
|
||||
$parameters->set(Option::PATHS, [
|
||||
__DIR__ . '/src',
|
||||
__DIR__ . '/tests',
|
||||
|
|
|
@ -32,6 +32,9 @@ final class DoctrineRepositoryAsServiceTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -72,6 +72,9 @@ final class MutualRenameTest extends AbstractFileSystemRectorTestCase
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -47,6 +47,9 @@ final class MoveValueObjectsToValueObjectDirectoryRectorTest extends AbstractFil
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed[]>
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -12,5 +12,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
->public();
|
||||
|
||||
$services->load('Rector\CakePHP\\', __DIR__ . '/../src')
|
||||
->exclude([__DIR__ . '/../src/Rector/*']);
|
||||
->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/ValueObject']);
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ use PhpParser\Node\Expr\Array_;
|
|||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\CakePHP\ValueObject\ArrayItemsAndFluentClass;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
|
@ -163,21 +164,21 @@ PHP
|
|||
return null;
|
||||
}
|
||||
|
||||
[$arrayItems, $fluentCalls] = $this->extractFluentMethods($argumentValue->items, $fluentMethods);
|
||||
$arrayItemsAndFluentClass = $this->extractFluentMethods($argumentValue->items, $fluentMethods);
|
||||
|
||||
if ($arrayItems) {
|
||||
$argumentValue->items = $arrayItems;
|
||||
if ($arrayItemsAndFluentClass->getArrayItems() !== []) {
|
||||
$argumentValue->items = $arrayItemsAndFluentClass->getArrayItems();
|
||||
} else {
|
||||
unset($methodCall->args[$argumentPosition - 1]);
|
||||
}
|
||||
|
||||
if (! $fluentCalls) {
|
||||
if ($arrayItemsAndFluentClass->getFluentCalls() === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$node = $methodCall;
|
||||
|
||||
foreach ($fluentCalls as $method => $arg) {
|
||||
foreach ($arrayItemsAndFluentClass->getFluentCalls() as $method => $arg) {
|
||||
$args = $this->createArgs([$arg]);
|
||||
$node = $this->createMethodCall($node, $method, $args);
|
||||
}
|
||||
|
@ -186,10 +187,10 @@ PHP
|
|||
}
|
||||
|
||||
/**
|
||||
* @param (ArrayItem|null)[] $originalArrayItems
|
||||
* @param array<ArrayItem|null> $originalArrayItems
|
||||
* @param string[] $arrayMap
|
||||
*/
|
||||
private function extractFluentMethods(array $originalArrayItems, array $arrayMap): array
|
||||
private function extractFluentMethods(array $originalArrayItems, array $arrayMap): ArrayItemsAndFluentClass
|
||||
{
|
||||
$newArrayItems = [];
|
||||
$fluentCalls = [];
|
||||
|
@ -199,15 +200,18 @@ PHP
|
|||
continue;
|
||||
}
|
||||
|
||||
/** @var ArrayItem $arrayItem */
|
||||
$key = $arrayItem->key;
|
||||
|
||||
if ($key instanceof String_ && isset($arrayMap[$key->value])) {
|
||||
$fluentCalls[$arrayMap[$key->value]] = $arrayItem->value;
|
||||
/** @var string $methodName */
|
||||
$methodName = $arrayMap[$key->value];
|
||||
$fluentCalls[$methodName] = $arrayItem->value;
|
||||
} else {
|
||||
$newArrayItems[] = $arrayItem;
|
||||
}
|
||||
}
|
||||
|
||||
return [$newArrayItems, $fluentCalls];
|
||||
return new ArrayItemsAndFluentClass($newArrayItems, $fluentCalls);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ PHP
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Property::class];
|
||||
|
|
47
rules/cakephp/src/ValueObject/ArrayItemsAndFluentClass.php
Normal file
47
rules/cakephp/src/ValueObject/ArrayItemsAndFluentClass.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CakePHP\ValueObject;
|
||||
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
|
||||
final class ArrayItemsAndFluentClass
|
||||
{
|
||||
/**
|
||||
* @var ArrayItem[]
|
||||
*/
|
||||
private $arrayItems = [];
|
||||
|
||||
/**
|
||||
* @var array<string, Expr>
|
||||
*/
|
||||
private $fluentCalls = [];
|
||||
|
||||
/**
|
||||
* @param ArrayItem[] $arrayItems
|
||||
* @param array<string, Expr> $fluentCalls
|
||||
*/
|
||||
public function __construct(array $arrayItems, array $fluentCalls)
|
||||
{
|
||||
$this->arrayItems = $arrayItems;
|
||||
$this->fluentCalls = $fluentCalls;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayItem[]
|
||||
*/
|
||||
public function getArrayItems(): array
|
||||
{
|
||||
return $this->arrayItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, Expr>
|
||||
*/
|
||||
public function getFluentCalls(): array
|
||||
{
|
||||
return $this->fluentCalls;
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\CakePHP\Tests\Rector\MethodCall\RenameMethodCallBasedOnParameterRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\CakePHP\Rector\MethodCall\RenameMethodCallBasedOnParameterRector;
|
||||
use Rector\CakePHP\Tests\Rector\MethodCall\RenameMethodCallBasedOnParameterRector\Source\SomeModelType;
|
||||
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
@ -20,7 +21,7 @@ final class RenameMethodCallBasedOnParameterRectorTest extends AbstractRectorTes
|
|||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @return Iterator
|
||||
*/
|
||||
public function provideData(): iterable
|
||||
{
|
||||
|
|
|
@ -113,6 +113,7 @@ PHP
|
|||
// remove other properties that are accessible from this scope
|
||||
/** @var string $class */
|
||||
$class = $this->getName($node);
|
||||
|
||||
foreach ($propertiesToComplete as $key => $propertyToComplete) {
|
||||
/** @var string $propertyToComplete */
|
||||
if (! property_exists($class, $propertyToComplete)) {
|
||||
|
@ -130,44 +131,11 @@ PHP
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Type[]
|
||||
* @return array<string, Type>
|
||||
*/
|
||||
private function resolveFetchedLocalPropertyNameToType(Class_ $class): array
|
||||
{
|
||||
$fetchedLocalPropertyNameToTypes = [];
|
||||
|
||||
$this->traverseNodesWithCallable($class->stmts, function (Node $node) use (
|
||||
&$fetchedLocalPropertyNameToTypes
|
||||
): ?int {
|
||||
// skip anonymous class scope
|
||||
if ($this->isAnonymousClass($node)) {
|
||||
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
|
||||
}
|
||||
|
||||
if (! $node instanceof PropertyFetch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isVariableName($node->var, 'this')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// special Laravel collection scope
|
||||
if ($this->shouldSkipForLaravelCollection($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$propertyName = $this->getName($node->name);
|
||||
if ($propertyName === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$propertyFetchType = $this->resolvePropertyFetchType($node);
|
||||
|
||||
$fetchedLocalPropertyNameToTypes[$propertyName][] = $propertyFetchType;
|
||||
|
||||
return null;
|
||||
});
|
||||
$fetchedLocalPropertyNameToTypes = $this->resolveFetchedLocalPropertyNamesToTypes($class);
|
||||
|
||||
// normalize types to union
|
||||
$fetchedLocalPropertyNameToType = [];
|
||||
|
@ -179,13 +147,14 @@ PHP
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Type[] $fetchedLocalPropertyNameToTypes
|
||||
* @return string[]
|
||||
* @param array<string, Type> $fetchedLocalPropertyNameToTypes
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function resolvePropertiesToComplete(Class_ $class, array $fetchedLocalPropertyNameToTypes): array
|
||||
{
|
||||
$propertyNames = $this->getClassPropertyNames($class);
|
||||
|
||||
/** @var string[] $fetchedLocalPropertyNames */
|
||||
$fetchedLocalPropertyNames = array_keys($fetchedLocalPropertyNameToTypes);
|
||||
|
||||
return array_diff($fetchedLocalPropertyNames, $propertyNames);
|
||||
|
@ -228,6 +197,63 @@ PHP
|
|||
return $newProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, Type[]>
|
||||
*/
|
||||
private function resolveFetchedLocalPropertyNamesToTypes(Class_ $class): array
|
||||
{
|
||||
$fetchedLocalPropertyNameToTypes = [];
|
||||
|
||||
$this->traverseNodesWithCallable($class->stmts, function (Node $node) use (
|
||||
&$fetchedLocalPropertyNameToTypes
|
||||
): ?int {
|
||||
// skip anonymous class scope
|
||||
if ($this->isAnonymousClass($node)) {
|
||||
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
|
||||
}
|
||||
|
||||
if (! $node instanceof PropertyFetch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isVariableName($node->var, 'this')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// special Laravel collection scope
|
||||
if ($this->shouldSkipForLaravelCollection($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$propertyName = $this->getName($node->name);
|
||||
if ($propertyName === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$propertyFetchType = $this->resolvePropertyFetchType($node);
|
||||
|
||||
$fetchedLocalPropertyNameToTypes[$propertyName][] = $propertyFetchType;
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return $fetchedLocalPropertyNameToTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getClassPropertyNames(Class_ $class): array
|
||||
{
|
||||
$propertyNames = [];
|
||||
|
||||
foreach ($class->getProperties() as $property) {
|
||||
$propertyNames[] = $this->getName($property);
|
||||
}
|
||||
|
||||
return $propertyNames;
|
||||
}
|
||||
|
||||
private function shouldSkipForLaravelCollection(Node $node): bool
|
||||
{
|
||||
$staticCallOrClassMethod = $this->betterNodeFinder->findFirstAncestorInstancesOf(
|
||||
|
@ -253,18 +279,4 @@ PHP
|
|||
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getClassPropertyNames(Class_ $class): array
|
||||
{
|
||||
$propertyNames = [];
|
||||
|
||||
foreach ($class->getProperties() as $property) {
|
||||
$propertyNames[] = $this->getName($property);
|
||||
}
|
||||
|
||||
return $propertyNames;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ final class UseImportsAdder
|
|||
* @param Stmt[] $stmts
|
||||
* @param FullyQualifiedObjectType[] $useImportTypes
|
||||
* @param FullyQualifiedObjectType[] $functionUseImportTypes
|
||||
* @return Stmt[]
|
||||
* @return \PhpParser\Node\Stmt[]
|
||||
*/
|
||||
public function addImportsToStmts(array $stmts, array $useImportTypes, array $functionUseImportTypes): array
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Rector\CodingStyle\Node;
|
|||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\BinaryOp\Concat;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\CodingStyle\ValueObject\ConcatStringAndPlaceholders;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
final class ConcatJoiner
|
||||
|
@ -24,10 +25,8 @@ final class ConcatJoiner
|
|||
/**
|
||||
* Joins all String_ nodes to string.
|
||||
* Returns that string + array of non-string nodes that were replaced by hash placeholders
|
||||
*
|
||||
* @return string[]|Expr[][]
|
||||
*/
|
||||
public function joinToStringAndPlaceholderNodes(Concat $concat): array
|
||||
public function joinToStringAndPlaceholderNodes(Concat $concat): ConcatStringAndPlaceholders
|
||||
{
|
||||
$parentNode = $concat->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $parentNode instanceof Concat) {
|
||||
|
@ -37,7 +36,7 @@ final class ConcatJoiner
|
|||
$this->processConcatSide($concat->left);
|
||||
$this->processConcatSide($concat->right);
|
||||
|
||||
return [$this->content, $this->placeholderNodes];
|
||||
return new ConcatStringAndPlaceholders($this->content, $this->placeholderNodes);
|
||||
}
|
||||
|
||||
private function reset(): void
|
||||
|
|
|
@ -27,7 +27,7 @@ final class UseNameAliasToNameResolver
|
|||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
* @return array<string, string[]>
|
||||
*/
|
||||
public function resolve(Use_ $use): array
|
||||
{
|
||||
|
@ -35,6 +35,10 @@ final class UseNameAliasToNameResolver
|
|||
|
||||
$shortNames = $this->shortNameResolver->resolveForNode($use);
|
||||
foreach ($shortNames as $alias => $useImport) {
|
||||
if (! is_string($alias)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$shortName = $this->classNaming->getShortName($useImport);
|
||||
if ($shortName === $alias) {
|
||||
continue;
|
||||
|
|
|
@ -49,6 +49,9 @@ CODE_SAMPLE
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [ClassMethod::class, MethodCall::class, StaticCall::class];
|
||||
|
|
|
@ -202,8 +202,10 @@ PHP
|
|||
{
|
||||
/** @var PhpDocInfo|null $phpDocInfo */
|
||||
$phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if ($phpDocInfo !== null) {
|
||||
$phpDocInfo->removeByType(ReturnTagValueNode::class);
|
||||
if ($phpDocInfo === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$phpDocInfo->removeByType(ReturnTagValueNode::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
|
|||
|
||||
/**
|
||||
* @sponsor Thanks https://spaceflow.io/ for sponsoring this rule - visit them on https://github.com/SpaceFlow-app
|
||||
*
|
||||
* @see \Rector\CodingStyle\Tests\Rector\String_\ManualJsonStringToJsonEncodeArrayRector\ManualJsonStringToJsonEncodeArrayRectorTest
|
||||
*/
|
||||
final class ManualJsonStringToJsonEncodeArrayRector extends AbstractRector
|
||||
|
@ -121,15 +122,17 @@ PHP
|
|||
return null;
|
||||
}
|
||||
|
||||
/** @var Expr[] $placeholderNodes */
|
||||
[$stringValue, $placeholderNodes] = $this->concatJoiner->joinToStringAndPlaceholderNodes($node->expr);
|
||||
$concatStringAndPlaceholders = $this->concatJoiner->joinToStringAndPlaceholderNodes($node->expr);
|
||||
|
||||
// B. just start of a json? join with all the strings that concat so same variable
|
||||
$concatExpressionJoinData = $this->collectContentAndPlaceholderNodesFromNextExpressions($node);
|
||||
|
||||
$placeholderNodes = array_merge($placeholderNodes, $concatExpressionJoinData->getPlaceholdersToNodes());
|
||||
$placeholderNodes = array_merge(
|
||||
$concatStringAndPlaceholders->getPlaceholderNodes(),
|
||||
$concatExpressionJoinData->getPlaceholdersToNodes()
|
||||
);
|
||||
|
||||
/** @var string $stringValue */
|
||||
$stringValue = $concatStringAndPlaceholders->getContent();
|
||||
$stringValue .= $concatExpressionJoinData->getString();
|
||||
|
||||
return $this->removeNodesAndCreateJsonEncodeFromStringValue(
|
||||
|
@ -176,12 +179,12 @@ PHP
|
|||
if ($valueNode instanceof String_) {
|
||||
$concatExpressionJoinData->addString($valueNode->value);
|
||||
} elseif ($valueNode instanceof Concat) {
|
||||
/** @var Expr[] $newPlaceholderNodes */
|
||||
[$content, $newPlaceholderNodes] = $this->concatJoiner->joinToStringAndPlaceholderNodes($valueNode);
|
||||
/** @var string $content */
|
||||
$joinToStringAndPlaceholderNodes = $this->concatJoiner->joinToStringAndPlaceholderNodes($valueNode);
|
||||
|
||||
$content = $joinToStringAndPlaceholderNodes->getContent();
|
||||
$concatExpressionJoinData->addString($content);
|
||||
|
||||
foreach ($newPlaceholderNodes as $placeholder => $expr) {
|
||||
foreach ($joinToStringAndPlaceholderNodes->getPlaceholderNodes() as $placeholder => $expr) {
|
||||
/** @var string $placeholder */
|
||||
$concatExpressionJoinData->addPlaceholderToNode($placeholder, $expr);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace Rector\CodingStyle\Rector\String_;
|
|||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
|
@ -65,7 +64,7 @@ PHP
|
|||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getExistingClasses(String_ $string): array
|
||||
{
|
||||
|
@ -77,6 +76,9 @@ PHP
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getParts(String_ $string, array $classNames): array
|
||||
{
|
||||
$classNames = array_map(function (string $className) {
|
||||
|
@ -93,7 +95,7 @@ PHP
|
|||
|
||||
/**
|
||||
* @param string[] $parts
|
||||
* @return Expr[]
|
||||
* @return ClassConstFetch[]|\PhpParser\Node\Scalar\String_[]
|
||||
*/
|
||||
private function createExpressionsToConcat(array $parts): array
|
||||
{
|
||||
|
|
|
@ -236,6 +236,9 @@ PHP
|
|||
return $this->extractMethodReturns($thrownClass, $methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string[]
|
||||
*/
|
||||
private function identifyThrownThrowablesInMethodCall(MethodCall $methodCall): array
|
||||
{
|
||||
$fullyQualified = $this->classResolver->getClassFromMethodCall($methodCall);
|
||||
|
|
|
@ -35,7 +35,7 @@ final class RemoveUnusedAliasRector extends AbstractRector
|
|||
private $resolvedNodeNames = [];
|
||||
|
||||
/**
|
||||
* @var string[][]
|
||||
* @var array<string, string[]>
|
||||
*/
|
||||
private $useNamesAliasToName = [];
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodingStyle\ValueObject;
|
||||
|
||||
final class ConcatStringAndPlaceholders
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $placeholderNodes = [];
|
||||
|
||||
public function __construct(string $content, array $placeholderNodes)
|
||||
{
|
||||
$this->content = $content;
|
||||
$this->placeholderNodes = $placeholderNodes;
|
||||
}
|
||||
|
||||
public function getContent(): string
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function getPlaceholderNodes(): array
|
||||
{
|
||||
return $this->placeholderNodes;
|
||||
}
|
||||
}
|
|
@ -24,6 +24,9 @@ final class FunctionCallToConstantRectorTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Core\Configuration\Option;
|
||||
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Rector\Renaming\Rector\Class_\RenameClassRector;
|
||||
|
@ -26,6 +27,9 @@ final class ImportRootNamespaceClassesDisabledTest extends AbstractRectorTestCas
|
|||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator
|
||||
*/
|
||||
public function provideData(): iterable
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/FixtureRoot');
|
||||
|
|
|
@ -121,6 +121,9 @@ final class LivingCodeManipulator
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \PhpParser\Node\Expr[]
|
||||
*/
|
||||
private function processBinary(BinaryOp $binaryOp): array
|
||||
{
|
||||
return array_merge(
|
||||
|
@ -129,6 +132,9 @@ final class LivingCodeManipulator
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function processIsset(Isset_ $isset): array
|
||||
{
|
||||
return array_merge(...array_map(function (Expr $expr): array {
|
||||
|
|
|
@ -55,7 +55,7 @@ final class RemoveUnusedAssignVariableRector extends AbstractRector
|
|||
}
|
||||
|
||||
/**
|
||||
* @return class-string[]
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
|
|
|
@ -137,7 +137,7 @@ PHP
|
|||
|
||||
/**
|
||||
* @param StaticCall|FuncCall|MethodCall $node
|
||||
* @return Expr[]
|
||||
* @return \PhpParser\Node\Expr[]|\PhpParser\Node[]
|
||||
*/
|
||||
private function resolveDefaultValuesFromCall(Node $node): array
|
||||
{
|
||||
|
@ -197,6 +197,7 @@ PHP
|
|||
return [];
|
||||
}
|
||||
|
||||
/** @var int[] $keysToRemove */
|
||||
return $keysToRemove;
|
||||
}
|
||||
|
||||
|
@ -213,7 +214,7 @@ PHP
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Expr[]
|
||||
* @return \PhpParser\Node[]|\PhpParser\Node\Expr[]
|
||||
*/
|
||||
private function resolveFuncCallDefaultParamValues(string $nodeName): array
|
||||
{
|
||||
|
|
|
@ -79,7 +79,10 @@ final class UnusedClassResolver
|
|||
|
||||
$cachedUsedClassNames = $this->sortAndUniqueArray($cachedUsedClassNames);
|
||||
|
||||
return $this->cachedUsedClassNames = $cachedUsedClassNames;
|
||||
/** @var string[] $cachedUsedClassNames */
|
||||
$this->cachedUsedClassNames = $cachedUsedClassNames;
|
||||
|
||||
return $this->cachedUsedClassNames;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,7 +40,7 @@ final class UsedClassPropertyExtractor
|
|||
|
||||
/**
|
||||
* @param ClassMethod[] $classMethods
|
||||
* @return Property[]
|
||||
* @return \PhpParser\Node\Stmt\Property[]
|
||||
*/
|
||||
public function extractFromClassMethods(array $classMethods, ?string $parentClassName = null): array
|
||||
{
|
||||
|
|
|
@ -42,6 +42,9 @@ final class DecoupleClassMethodToOwnClassRectorTest extends AbstractRectorTestCa
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -25,6 +25,9 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
|
|||
*/
|
||||
final class ChangeQuerySetParametersMethodParameterFromArrayToArrayCollectionRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [MethodCall::class];
|
||||
|
|
|
@ -51,6 +51,9 @@ final class ReportEntitiesWithAddedPropertiesEventSubscriber implements EventSub
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [AfterProcessEvent::class => 'reportEntities'];
|
||||
|
|
|
@ -48,7 +48,7 @@ final class EntityWithMissingUuidProvider
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Class_[]
|
||||
* @return \PhpParser\Node\Stmt\Class_[]
|
||||
*/
|
||||
public function provide(): array
|
||||
{
|
||||
|
@ -76,7 +76,7 @@ final class EntityWithMissingUuidProvider
|
|||
|
||||
$this->entitiesWithMissingUuidProperty = $entitiesWithMissingUuidProperty;
|
||||
|
||||
return $entitiesWithMissingUuidProperty;
|
||||
return $this->entitiesWithMissingUuidProperty;
|
||||
}
|
||||
|
||||
private function hasClassIdPropertyWithUuidType(Class_ $class): bool
|
||||
|
|
|
@ -25,6 +25,9 @@ final class AddEntityIdByConditionRectorTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -74,7 +74,7 @@ final class CallTypeAnalyzer
|
|||
|
||||
/**
|
||||
* @param MethodCall|StaticCall $node
|
||||
* @return array<int, Type>
|
||||
* @return \PHPStan\Type\Type[]
|
||||
*/
|
||||
private function getMethodParameterTypes(string $className, Node $node): array
|
||||
{
|
||||
|
|
|
@ -200,6 +200,7 @@ PHP
|
|||
/**
|
||||
* @param Arg[] $argumentNodes
|
||||
* @param mixed[] $before
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, int $position, array $before): array
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
/**
|
||||
* @return class-string[]
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
|
|
|
@ -25,6 +25,9 @@ final class ChangeContractMethodSingleToManyRectorTest extends AbstractRectorTes
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -26,6 +26,9 @@ final class AddInterfaceByTraitRectorTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -28,6 +28,9 @@ final class RemoveFuncCallArgRectorTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[][][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -28,6 +28,9 @@ final class RemoveIniGetSetFuncCallRectorTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -24,6 +24,9 @@ final class MethodCallToStaticCallRectorTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][][][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -25,6 +25,9 @@ final class SwapClassMethodArgumentsRectorTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[][][][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -25,6 +25,9 @@ final class StaticCallToMethodCallRectorTest extends AbstractRectorTestCase
|
|||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StaticCallToMethodCall[][][]
|
||||
*/
|
||||
protected function getRectorsWithConfiguration(): array
|
||||
{
|
||||
$configuration = [
|
||||
|
|
|
@ -60,6 +60,9 @@ PHP
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [ArrayItem::class];
|
||||
|
@ -137,7 +140,7 @@ PHP
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Expr[]
|
||||
* @return \PhpParser\Node\Scalar\String_[]|\PhpParser\Node\Expr[]|\PhpParser\Node\Expr\ClassConstFetch[]|FuncCall[]|MethodCall[]
|
||||
*/
|
||||
private function transformRulesSetToExpressionsArray(Expr $expr): array
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Rector\Legacy\Rector\FileSystem;
|
|||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
|
@ -126,7 +127,7 @@ PHP
|
|||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
* @return Node[]
|
||||
* @return \PhpParser\Node[]|Stmt[]
|
||||
*/
|
||||
private function getFileOrNamespaceStmts(array $nodes): array
|
||||
{
|
||||
|
@ -167,7 +168,7 @@ PHP
|
|||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
* @return Node[]
|
||||
* @return \PhpParser\Node\Stmt\Namespace_[]|Class_[]
|
||||
*/
|
||||
private function resolveNodesToPrint(array $nodes, Class_ $class): array
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@ use PhpParser\Node\Expr\MethodCall;
|
|||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\MagicDisclosure\NodeAnalyzer\FluentChainMethodCallNodeAnalyzer;
|
||||
use Rector\MagicDisclosure\ValueObject\AssignAndRootExpr;
|
||||
use Rector\NetteKdyby\Naming\VariableNaming;
|
||||
|
@ -61,6 +62,7 @@ final class NonFluentChainMethodCallFactory
|
|||
|
||||
/**
|
||||
* @param MethodCall[] $chainMethodCalls
|
||||
* @return Expr[]|Return_[]
|
||||
*/
|
||||
public function createFromAssignObjectAndMethodCalls(
|
||||
AssignAndRootExpr $assignAndRootExpr,
|
||||
|
@ -100,7 +102,7 @@ final class NonFluentChainMethodCallFactory
|
|||
|
||||
/**
|
||||
* @param MethodCall[] $chainMethodCalls
|
||||
* @return Expr[]
|
||||
* @return \PhpParser\Node\Expr\Assign[]|\PhpParser\Node\Expr\MethodCall[]
|
||||
*/
|
||||
private function createNonFluentMethodCalls(array $chainMethodCalls, AssignAndRootExpr $assignAndRootExpr): array
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user