mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-28 23:10:51 +00:00
[CI] run rules dir by dir to identify static reflection weak sposts (#5720)
* [CI] run rules dir by dir to identify static reflection weak sposts * [ci-review] Rector Rectify * consistency * remove unused property * add data provider test fixture * add InvertedIfFactory to lower complexity * [DeadCode] Skip unused public method if data provider * misc * [DeadCode] Do not remove class method if required by parent ocntract * make use of ContextAnalyzer to find the loop * narrow dirs one level * narrow packages * narrow * use directly * narrow * correct constant name to keep BC * bump deps * add version_compare to removed extra params, just to be sure * do not return function node on unchanged name * narrow * add support for multiple variants * widen * remove double check [skip ci] Co-authored-by: kaizen-ci <info@kaizen-ci.org>
This commit is contained in:
parent
66f6b4a573
commit
d5bf66f9cd
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#permissions-for-the-github_token
|
||||
####
|
||||
name: Rector CI
|
||||
name: Rector
|
||||
|
||||
on:
|
||||
pull_request: null
|
||||
|
@ -22,10 +22,14 @@ jobs:
|
|||
matrix:
|
||||
directories:
|
||||
#- rules
|
||||
- rules/naming
|
||||
- rules/privatization
|
||||
- rules/code-quality
|
||||
- rules/php74
|
||||
- rules/arguments rules/autodiscovery rules/cakephp rules/carbon rules/code-quality rules/code-quality-strict rules/coding-style rules/composer rules/dead-code rules/dead-doc-block rules/defluent rules/dependency-injection rules/doctrine rules/doctrine-code-quality rules/doctrine-gedmo-to-knplabs rules/downgrade-php70 rules/downgrade-php71 rules/downgrade-php72 rules/downgrade-php73
|
||||
|
||||
- rules/downgrade-php74 rules/downgrade-php80 rules/early-return rules/generics rules/laravel rules/legacy rules/mockery-to-prophecy rules/mockista-to-mockery rules/mysql-to-mysqli rules/naming rules/nette rules/nette-code-quality rules/nette-kdyby
|
||||
|
||||
- rules/nette-tester-to-phpunit rules/nette-to-symfony rules/nette-utils-code-quality rules/order rules/php-office rules/php-spec-to-phpunit rules/php52 rules/php53 rules/php54 rules/php55 rules/php56 rules/php70 rules/php71 rules/php72 rules/php73 rules/php74 rules/php80 rules/phpunit rules/phpunit-symfony rules/privatization rules/psr4 rules/removing rules/removing-static rules/renaming rules/restoration rules/sensio rules/symfony rules/symfony-code-quality rules/symfony-php-config rules/symfony2
|
||||
|
||||
- rules/symfony3 rules/symfony4 rules/symfony5 rules/transform rules/type-declaration rules/visibility
|
||||
|
||||
- packages
|
||||
- src
|
||||
- tests
|
|
@ -37,7 +37,7 @@
|
|||
"nette/utils": "^3.2",
|
||||
"nikic/php-parser": "^4.10.4",
|
||||
"phpstan/phpdoc-parser": "^0.4.9",
|
||||
"phpstan/phpstan": "^0.12.79",
|
||||
"phpstan/phpstan": "^0.12.80",
|
||||
"phpstan/phpstan-phpunit": "^0.12.17",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"sebastian/diff": "^4.0.4",
|
||||
|
|
|
@ -13626,7 +13626,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
|
||||
$services->set(InferParamFromClassMethodReturnRector::class)
|
||||
->call('configure', [[
|
||||
InferParamFromClassMethodReturnRector::PARAM_FROM_CLASS_METHOD_RETURNS => ValueObjectInliner::inline([
|
||||
InferParamFromClassMethodReturnRector::INFER_PARAMS_FROM_CLASS_METHOD_RETURNS => ValueObjectInliner::inline([
|
||||
new InferParamFromClassMethodReturn('SomeClass', 'process', 'getNodeTypes'),
|
||||
]),
|
||||
]]);
|
||||
|
|
|
@ -604,3 +604,5 @@ parameters:
|
|||
message: '#Do not use "array_filter" function with complex content, make it more readable with extracted method or single\-line statement#'
|
||||
paths:
|
||||
- src/Application/ActiveRectorsProvider.php
|
||||
|
||||
- '#Content of method "getIfNextReturn\(\)" is duplicated with method "getIfNextReturn\(\)" in "Rector\\EarlyReturn\\NodeFactory\\InvertedIfFactory" class\. Use unique content or service instead#'
|
||||
|
|
|
@ -25,7 +25,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
]);
|
||||
$services->set(InferParamFromClassMethodReturnRector::class)
|
||||
->call('configure', [[
|
||||
InferParamFromClassMethodReturnRector::PARAM_FROM_CLASS_METHOD_RETURNS => $configuration,
|
||||
InferParamFromClassMethodReturnRector::INFER_PARAMS_FROM_CLASS_METHOD_RETURNS => $configuration,
|
||||
]]);
|
||||
|
||||
$services->set(PreferThisOrSelfMethodCallRector::class)
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeadCode\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\PHPUnit\PHPUnitDataProviderTagValueNode;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
use Rector\RemovingStatic\ValueObject\PHPUnitClass;
|
||||
|
||||
final class DataProviderMethodNamesResolver
|
||||
{
|
||||
/**
|
||||
* @var array<string, string[]>
|
||||
*/
|
||||
private $cachedDataProviderMethodNamesByClassHash = [];
|
||||
|
||||
/**
|
||||
* @var PhpDocInfoFactory
|
||||
*/
|
||||
private $phpDocInfoFactory;
|
||||
|
||||
/**
|
||||
* @var NodeTypeResolver
|
||||
*/
|
||||
private $nodeTypeResolver;
|
||||
|
||||
public function __construct(PhpDocInfoFactory $phpDocInfoFactory, NodeTypeResolver $nodeTypeResolver)
|
||||
{
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
$this->nodeTypeResolver = $nodeTypeResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function resolveFromClass(Class_ $class): array
|
||||
{
|
||||
$classKey = spl_object_hash($class);
|
||||
if (isset($this->cachedDataProviderMethodNamesByClassHash[$classKey])) {
|
||||
return $this->cachedDataProviderMethodNamesByClassHash[$classKey];
|
||||
}
|
||||
|
||||
$dataProviderMethodNames = [];
|
||||
$phpunitDataProviderTagValueNodes = $this->resolvePHPUnitDataProviderTagValueNodes($class);
|
||||
|
||||
foreach ($phpunitDataProviderTagValueNodes as $phpunitDataProviderTagValueNode) {
|
||||
$dataProviderMethodNames[] = $phpunitDataProviderTagValueNode->getMethodName();
|
||||
}
|
||||
|
||||
$this->cachedDataProviderMethodNamesByClassHash[$classKey] = $dataProviderMethodNames;
|
||||
|
||||
return $dataProviderMethodNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PHPUnitDataProviderTagValueNode[]
|
||||
*/
|
||||
private function resolvePHPUnitDataProviderTagValueNodes(Class_ $class): array
|
||||
{
|
||||
if (! $this->nodeTypeResolver->isObjectType($class, new ObjectType(PHPUnitClass::TEST_CASE))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$phpunitDataProviderTagValueNodes = [];
|
||||
|
||||
foreach ($class->getMethods() as $classMethod) {
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
|
||||
|
||||
$foundPHPUnitDataProviderTagValueNodes = $phpDocInfo->findAllByType(PHPUnitDataProviderTagValueNode::class);
|
||||
$phpunitDataProviderTagValueNodes = array_merge(
|
||||
$phpunitDataProviderTagValueNodes,
|
||||
$foundPHPUnitDataProviderTagValueNodes
|
||||
);
|
||||
}
|
||||
|
||||
return $phpunitDataProviderTagValueNodes;
|
||||
}
|
||||
}
|
|
@ -114,12 +114,12 @@ final class CallDefaultParamValuesResolver
|
|||
}
|
||||
|
||||
// non existing function
|
||||
$functionNameNode = new Name($functionName);
|
||||
if (! $this->reflectionProvider->hasFunction($functionNameNode, null)) {
|
||||
$name = new Name($functionName);
|
||||
if (! $this->reflectionProvider->hasFunction($name, null)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$functionReflection = $this->reflectionProvider->getFunction($functionNameNode, null);
|
||||
$functionReflection = $this->reflectionProvider->getFunction($name, null);
|
||||
if ($functionReflection->isBuiltin()) {
|
||||
return [];
|
||||
}
|
||||
|
@ -128,10 +128,10 @@ final class CallDefaultParamValuesResolver
|
|||
|
||||
$parametersAcceptor = $functionReflection->getVariants()[0];
|
||||
|
||||
foreach ($parametersAcceptor->getParameters() as $key => $reflectionParameter) {
|
||||
foreach ($parametersAcceptor->getParameters() as $key => $parameterReflection) {
|
||||
/** @var ReflectionParameter $nativeReflectionParameter */
|
||||
$nativeReflectionParameter = $this->privatesAccessor->getPrivateProperty(
|
||||
$reflectionParameter,
|
||||
$parameterReflection,
|
||||
'reflection'
|
||||
);
|
||||
if (! $nativeReflectionParameter->isDefaultValueAvailable()) {
|
||||
|
|
|
@ -7,10 +7,14 @@ namespace Rector\DeadCode\Rector\ClassMethod;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\Caching\Contract\Rector\ZeroCacheRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\DeadCode\NodeAnalyzer\DataProviderMethodNamesResolver;
|
||||
use Rector\NodeCollector\ValueObject\ArrayCallable;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\VendorLocker\NodeVendorLocker\ClassMethodReturnVendorLockResolver;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
|
@ -19,11 +23,29 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
*/
|
||||
final class RemoveUnusedPublicMethodRector extends AbstractRector implements ZeroCacheRectorInterface
|
||||
{
|
||||
/**
|
||||
* @var DataProviderMethodNamesResolver
|
||||
*/
|
||||
private $dataProviderMethodNamesResolver;
|
||||
|
||||
/**
|
||||
* @var MethodCall[]|StaticCall[]|ArrayCallable[]
|
||||
*/
|
||||
private $calls = [];
|
||||
|
||||
/**
|
||||
* @var ClassMethodReturnVendorLockResolver
|
||||
*/
|
||||
private $classMethodReturnVendorLockResolver;
|
||||
|
||||
public function __construct(
|
||||
DataProviderMethodNamesResolver $dataProviderMethodNamesResolver,
|
||||
ClassMethodReturnVendorLockResolver $classMethodReturnVendorLockResolver
|
||||
) {
|
||||
$this->dataProviderMethodNamesResolver = $dataProviderMethodNamesResolver;
|
||||
$this->classMethodReturnVendorLockResolver = $classMethodReturnVendorLockResolver;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Remove unused public method', [
|
||||
|
@ -92,14 +114,8 @@ CODE_SAMPLE
|
|||
return null;
|
||||
}
|
||||
|
||||
/** @var MethodCall[] $calls */
|
||||
$calls = $this->calls;
|
||||
foreach ($calls as $call) {
|
||||
$classMethod = $this->betterNodeFinder->findParentType($call, ClassMethod::class);
|
||||
|
||||
if ($this->nodeComparator->areNodesEqual($classMethod, $node)) {
|
||||
return null;
|
||||
}
|
||||
if ($this->isRecursionCallClassMethod($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->removeNode($node);
|
||||
|
@ -108,6 +124,11 @@ CODE_SAMPLE
|
|||
|
||||
private function shouldSkip(ClassMethod $classMethod): bool
|
||||
{
|
||||
$class = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
|
||||
if (! $class instanceof Class_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->isOpenSourceProjectType()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -116,14 +137,40 @@ CODE_SAMPLE
|
|||
return true;
|
||||
}
|
||||
|
||||
if ($this->classMethodReturnVendorLockResolver->isVendorLocked($classMethod)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($classMethod->isMagic()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->isNames($classMethod, ['test'])) {
|
||||
if ($this->isNames($classMethod, ['test', 'test*'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$class = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
|
||||
|
||||
$phpunitDataProviderMethodNames = $this->dataProviderMethodNamesResolver->resolveFromClass($class);
|
||||
return $this->isNames($classMethod, $phpunitDataProviderMethodNames);
|
||||
}
|
||||
|
||||
private function isRecursionCallClassMethod(ClassMethod $currentClassMethod): bool
|
||||
{
|
||||
/** @var MethodCall[] $calls */
|
||||
$calls = $this->calls;
|
||||
|
||||
foreach ($calls as $call) {
|
||||
$parentClassMethod = $call->getAttribute(AttributeKey::METHOD_NODE);
|
||||
if (! $parentClassMethod) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->nodeComparator->areNodesEqual($parentClassMethod, $currentClassMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,12 +141,12 @@ CODE_SAMPLE
|
|||
return false;
|
||||
}
|
||||
|
||||
$functionNameNode = new Name($functionName);
|
||||
if (! $this->reflectionProvider->hasFunction($functionNameNode, null)) {
|
||||
$name = new Name($functionName);
|
||||
if (! $this->reflectionProvider->hasFunction($name, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$reflectionFunction = $this->reflectionProvider->getFunction($functionNameNode, null);
|
||||
$reflectionFunction = $this->reflectionProvider->getFunction($name, null);
|
||||
|
||||
// skip native functions, hard to analyze without stubs (stubs would make working with IDE non-practical)
|
||||
return $reflectionFunction->isBuiltin();
|
||||
|
|
|
@ -163,8 +163,8 @@ final class ClassUnusedPrivateClassMethodResolver
|
|||
return false;
|
||||
}
|
||||
|
||||
$nativeClassReflection = $classReflection->getNativeReflection();
|
||||
$reflectionMethod = $nativeClassReflection->getMethod($method);
|
||||
$reflectionClass = $classReflection->getNativeReflection();
|
||||
$reflectionMethod = $reflectionClass->getMethod($method);
|
||||
|
||||
return $reflectionMethod->isAbstract();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
namespace Rector\DeadCode\Tests\Rector\ClassMethod\RemoveUnusedPublicMethodRector\Fixture;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\Core\Contract\Rector\PhpRectorInterface;
|
||||
|
||||
final class SkipRequiredByContract extends NodeVisitorAbstract implements PhpRectorInterface
|
||||
{
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
}
|
||||
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
namespace Rector\DeadCode\Tests\Rector\ClassMethod\RemoveUnusedPublicMethodRector\Fixture;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class SkipTestDataProvider extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(): void
|
||||
{
|
||||
$this->assertTrue('yes');
|
||||
}
|
||||
|
||||
public function provideData()
|
||||
{
|
||||
return [1, 2, 3];
|
||||
}
|
||||
}
|
|
@ -17,17 +17,17 @@ final class InjectTagValueNodeToServiceTypeResolver
|
|||
/**
|
||||
* @var JMSDITypeResolver
|
||||
*/
|
||||
private $jmsDITypeResolver;
|
||||
private $jmsdiTypeResolver;
|
||||
|
||||
public function __construct(JMSDITypeResolver $jmsDITypeResolver)
|
||||
public function __construct(JMSDITypeResolver $jmsdiTypeResolver)
|
||||
{
|
||||
$this->jmsDITypeResolver = $jmsDITypeResolver;
|
||||
$this->jmsdiTypeResolver = $jmsdiTypeResolver;
|
||||
}
|
||||
|
||||
public function resolve(Property $property, PhpDocInfo $phpDocInfo, PhpDocTagValueNode $phpDocTagValueNode): Type
|
||||
{
|
||||
if ($phpDocTagValueNode instanceof JMSInjectTagValueNode) {
|
||||
return $this->jmsDITypeResolver->resolve($property, $phpDocTagValueNode);
|
||||
return $this->jmsdiTypeResolver->resolve($property, $phpDocTagValueNode);
|
||||
}
|
||||
|
||||
if ($phpDocTagValueNode instanceof PHPDIInjectTagValueNode) {
|
||||
|
|
|
@ -137,10 +137,8 @@ final class PhpDocFromTypeDeclarationDecorator
|
|||
*/
|
||||
private function isTypeMatch(Node $typeNode, string $requireTypeNodeClass): bool
|
||||
{
|
||||
if (is_a($requireTypeNodeClass, Node::class, true)) {
|
||||
if (! is_a($typeNode, $requireTypeNodeClass, true)) {
|
||||
return false;
|
||||
}
|
||||
if (is_a($requireTypeNodeClass, Node::class, true) && ! is_a($typeNode, $requireTypeNodeClass, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_a($requireTypeNodeClass, Type::class, true)) {
|
||||
|
|
|
@ -285,8 +285,8 @@ CODE_SAMPLE
|
|||
return false;
|
||||
}
|
||||
|
||||
$nativeClassReflection = $classReflection->getNativeReflection();
|
||||
$reflectionMethodReflection = $nativeClassReflection->getMethod($methodName);
|
||||
$reflectionClass = $classReflection->getNativeReflection();
|
||||
$reflectionMethodReflection = $reflectionClass->getMethod($methodName);
|
||||
|
||||
foreach ($reflectionMethodReflection->getParameters() as $reflectionParameter) {
|
||||
if ($reflectionParameter->getName() !== $paramName) {
|
||||
|
|
93
rules/early-return/src/NodeFactory/InvertedIfFactory.php
Normal file
93
rules/early-return/src/NodeFactory/InvertedIfFactory.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\EarlyReturn\NodeFactory;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Stmt\Continue_;
|
||||
use PhpParser\Node\Stmt\If_;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\EarlyReturn\NodeTransformer\ConditionInverter;
|
||||
use Rector\NodeNestingScope\ContextAnalyzer;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
final class InvertedIfFactory
|
||||
{
|
||||
/**
|
||||
* @var BetterNodeFinder
|
||||
*/
|
||||
private $betterNodeFinder;
|
||||
|
||||
/**
|
||||
* @var ConditionInverter
|
||||
*/
|
||||
private $conditionInverter;
|
||||
|
||||
/**
|
||||
* @var ContextAnalyzer
|
||||
*/
|
||||
private $contextAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
BetterNodeFinder $betterNodeFinder,
|
||||
ConditionInverter $conditionInverter,
|
||||
ContextAnalyzer $contextAnalyzer
|
||||
) {
|
||||
$this->betterNodeFinder = $betterNodeFinder;
|
||||
$this->conditionInverter = $conditionInverter;
|
||||
$this->contextAnalyzer = $contextAnalyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Expr[] $conditions
|
||||
* @return If_[]
|
||||
*/
|
||||
public function createFromConditions(If_ $if, array $conditions, Return_ $return): array
|
||||
{
|
||||
$ifs = [];
|
||||
$stmt = $this->contextAnalyzer->isInLoop($if) && ! $this->getIfNextReturn($if)
|
||||
? [new Continue_()]
|
||||
: [$return];
|
||||
|
||||
$getNextReturnExpr = $this->getNextReturnExpr($if);
|
||||
if ($getNextReturnExpr instanceof Return_) {
|
||||
$return->expr = $getNextReturnExpr->expr;
|
||||
}
|
||||
|
||||
foreach ($conditions as $condition) {
|
||||
$invertedCondition = $this->conditionInverter->createInvertedCondition($condition);
|
||||
$if = new If_($invertedCondition);
|
||||
$if->stmts = $stmt;
|
||||
$ifs[] = $if;
|
||||
}
|
||||
|
||||
return $ifs;
|
||||
}
|
||||
|
||||
private function getNextReturnExpr(If_ $if): ?Node
|
||||
{
|
||||
/** @var Closure|null $closure */
|
||||
$closure = $if->getAttribute(AttributeKey::CLOSURE_NODE);
|
||||
if ($closure instanceof Closure) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->betterNodeFinder->findFirstNext($if, function (Node $node): bool {
|
||||
return $node instanceof Return_ && $node->expr instanceof Expr;
|
||||
});
|
||||
}
|
||||
|
||||
private function getIfNextReturn(If_ $if): ?Return_
|
||||
{
|
||||
$nextNode = $if->getAttribute(AttributeKey::NEXT_NODE);
|
||||
if (! $nextNode instanceof Return_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $nextNode;
|
||||
}
|
||||
}
|
|
@ -7,20 +7,15 @@ namespace Rector\EarlyReturn\Rector\If_;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\Stmt\Continue_;
|
||||
use PhpParser\Node\Stmt\Else_;
|
||||
use PhpParser\Node\Stmt\ElseIf_;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\For_;
|
||||
use PhpParser\Node\Stmt\Foreach_;
|
||||
use PhpParser\Node\Stmt\If_;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\Node\Stmt\While_;
|
||||
use Rector\Core\NodeManipulator\IfManipulator;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\EarlyReturn\NodeTransformer\ConditionInverter;
|
||||
use Rector\EarlyReturn\NodeFactory\InvertedIfFactory;
|
||||
use Rector\NodeNestingScope\ContextAnalyzer;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
@ -30,25 +25,27 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
*/
|
||||
final class ChangeAndIfToEarlyReturnRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var array<class-string<Stmt>>
|
||||
*/
|
||||
public const LOOP_TYPES = [Foreach_::class, For_::class, While_::class];
|
||||
|
||||
/**
|
||||
* @var IfManipulator
|
||||
*/
|
||||
private $ifManipulator;
|
||||
|
||||
/**
|
||||
* @var ConditionInverter
|
||||
* @var InvertedIfFactory
|
||||
*/
|
||||
private $conditionInverter;
|
||||
private $invertedIfFactory;
|
||||
|
||||
public function __construct(ConditionInverter $conditionInverter, IfManipulator $ifManipulator)
|
||||
/**
|
||||
* @var ContextAnalyzer
|
||||
*/
|
||||
private $contextAnalyzer;
|
||||
|
||||
public function __construct(IfManipulator $ifManipulator, InvertedIfFactory $invertedIfFactory,
|
||||
ContextAnalyzer $contextAnalyzer)
|
||||
{
|
||||
$this->ifManipulator = $ifManipulator;
|
||||
$this->conditionInverter = $conditionInverter;
|
||||
$this->invertedIfFactory = $invertedIfFactory;
|
||||
$this->contextAnalyzer = $contextAnalyzer;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
|
@ -120,7 +117,8 @@ CODE_SAMPLE
|
|||
? clone $ifNextReturn
|
||||
: new Return_();
|
||||
|
||||
$isInLoop = $this->isIfInLoop($node);
|
||||
$isInLoop = $this->contextAnalyzer->isInLoop($node);
|
||||
|
||||
if (! $ifNextReturn instanceof Return_) {
|
||||
$this->addNodeAfterNode($node->stmts[0], $node);
|
||||
return $this->processReplaceIfs($node, $conditions, $ifNextReturnClone);
|
||||
|
@ -150,7 +148,7 @@ CODE_SAMPLE
|
|||
*/
|
||||
private function processReplaceIfs(If_ $node, array $conditions, Return_ $ifNextReturnClone): If_
|
||||
{
|
||||
$ifs = $this->createInvertedIfNodesFromConditions($node, $conditions, $ifNextReturnClone);
|
||||
$ifs = $this->invertedIfFactory->createFromConditions($node, $conditions, $ifNextReturnClone);
|
||||
$this->mirrorComments($ifs[0], $node);
|
||||
|
||||
foreach ($ifs as $if) {
|
||||
|
@ -171,8 +169,10 @@ CODE_SAMPLE
|
|||
if (! $this->ifManipulator->isIfWithOnlyOneStmt($if)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! $if->cond instanceof BooleanAnd || ! $this->ifManipulator->isIfWithoutElseAndElseIfs($if)) {
|
||||
if (! $if->cond instanceof BooleanAnd) {
|
||||
return true;
|
||||
}
|
||||
if (! $this->ifManipulator->isIfWithoutElseAndElseIfs($if)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -208,32 +208,6 @@ CODE_SAMPLE
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Expr[] $conditions
|
||||
* @return If_[]
|
||||
*/
|
||||
private function createInvertedIfNodesFromConditions(If_ $if, array $conditions, Return_ $return): array
|
||||
{
|
||||
$ifs = [];
|
||||
$stmt = $this->isIfInLoop($if) && ! $this->getIfNextReturn($if)
|
||||
? [new Continue_()]
|
||||
: [$return];
|
||||
|
||||
$getNextReturnExpr = $this->getNextReturnExpr($if);
|
||||
if ($getNextReturnExpr instanceof Return_) {
|
||||
$return->expr = $getNextReturnExpr->expr;
|
||||
}
|
||||
|
||||
foreach ($conditions as $key => $condition) {
|
||||
$invertedCondition = $this->conditionInverter->createInvertedCondition($condition);
|
||||
$if = new If_($invertedCondition);
|
||||
$if->stmts = $stmt;
|
||||
$ifs[] = $if;
|
||||
}
|
||||
|
||||
return $ifs;
|
||||
}
|
||||
|
||||
private function getIfNextReturn(If_ $if): ?Return_
|
||||
{
|
||||
$nextNode = $if->getAttribute(AttributeKey::NEXT_NODE);
|
||||
|
@ -244,25 +218,6 @@ CODE_SAMPLE
|
|||
return $nextNode;
|
||||
}
|
||||
|
||||
private function getNextReturnExpr(If_ $if): ?Return_
|
||||
{
|
||||
$hasClosureParent = (bool) $this->betterNodeFinder->findParentType($if, Closure::class);
|
||||
if ($hasClosureParent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->betterNodeFinder->findFirstNext($if, function (Node $node): bool {
|
||||
return $node instanceof Return_ && $node->expr instanceof Expr;
|
||||
});
|
||||
}
|
||||
|
||||
private function isIfInLoop(If_ $if): bool
|
||||
{
|
||||
$parentLoop = $this->betterNodeFinder->findParentTypes($if, self::LOOP_TYPES);
|
||||
|
||||
return $parentLoop !== null;
|
||||
}
|
||||
|
||||
private function isParentIfReturnsVoidOrParentIfHasNextNode(If_ $if): bool
|
||||
{
|
||||
$parentNode = $if->getAttribute(AttributeKey::PARENT_NODE);
|
||||
|
@ -276,7 +231,7 @@ CODE_SAMPLE
|
|||
|
||||
private function isNestedIfInLoop(If_ $if): bool
|
||||
{
|
||||
if (! $this->isIfInLoop($if)) {
|
||||
if (! $this->contextAnalyzer->isInLoop($if)) {
|
||||
return false;
|
||||
}
|
||||
return (bool) $this->betterNodeFinder->findParentTypes($if, [If_::class, Else_::class, ElseIf_::class]);
|
||||
|
|
|
@ -93,7 +93,7 @@ final class MagicNetteFactoryInterfaceFormControlTypeResolver implements FormCon
|
|||
}
|
||||
|
||||
$classReflection = $this->resolveClassReflectionByMethodCall($node);
|
||||
if ($classReflection === null) {
|
||||
if (! $classReflection instanceof ClassReflection) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ final class MagicNetteFactoryInterfaceFormControlTypeResolver implements FormCon
|
|||
private function resolveReflectionClassMethod(MethodCall $methodCall, string $methodName): ?ClassMethod
|
||||
{
|
||||
$classReflection = $this->resolveClassReflectionByMethodCall($methodCall);
|
||||
if ($classReflection === null) {
|
||||
if (! $classReflection instanceof ClassReflection) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -240,8 +240,8 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
// has method
|
||||
$method = $calledOnType->getMethod($methodName, $scope);
|
||||
$methodReflection = $calledOnType->getMethod($methodName, $scope);
|
||||
|
||||
return ParametersAcceptorSelector::selectSingle($method->getVariants())->getReturnType();
|
||||
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -319,8 +319,8 @@ CODE_SAMPLE
|
|||
return false;
|
||||
}
|
||||
|
||||
$reflectionMethod = $classReflection->getNativeMethod($methodName);
|
||||
$parametersAcceptor = $reflectionMethod->getVariants()[0];
|
||||
$methodReflection = $classReflection->getNativeMethod($methodName);
|
||||
$parametersAcceptor = $methodReflection->getVariants()[0];
|
||||
|
||||
$returnType = $parametersAcceptor->getReturnType();
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ use PhpParser\Node\Expr\Variable;
|
|||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
|
@ -211,7 +212,7 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$classReflection = $scope->getClassReflection();
|
||||
if ($classReflection === null) {
|
||||
if (! $classReflection instanceof ClassReflection) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,9 +37,9 @@ final class PHPUnitTypeDeclarationDecorator
|
|||
}
|
||||
|
||||
$classReflection = $this->reflectionProvider->getClass('PHPUnit\Framework\TestCase');
|
||||
$nativeClassReflection = $classReflection->getNativeReflection();
|
||||
$reflectionClass = $classReflection->getNativeReflection();
|
||||
|
||||
$reflectionMethod = $nativeClassReflection->getMethod(MethodName::SET_UP);
|
||||
$reflectionMethod = $reflectionClass->getMethod(MethodName::SET_UP);
|
||||
if (! $reflectionMethod->hasReturnType()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -186,18 +186,18 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$classReflection = $this->reflectionProvider->getClass($className);
|
||||
$nativeClassReflection = $classReflection->getNativeReflection();
|
||||
$reflectionClass = $classReflection->getNativeReflection();
|
||||
|
||||
$constructorMethodReflection = $nativeClassReflection->getConstructor();
|
||||
if (! $constructorMethodReflection instanceof ReflectionMethod) {
|
||||
$reflectionMethod = $reflectionClass->getConstructor();
|
||||
if (! $reflectionMethod instanceof ReflectionMethod) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! $constructorMethodReflection->isPublic()) {
|
||||
if (! $reflectionMethod->isPublic()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// required parameters in constructor, nothing we can do
|
||||
return ! (bool) $constructorMethodReflection->getNumberOfRequiredParameters();
|
||||
return ! (bool) $reflectionMethod->getNumberOfRequiredParameters();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ use PhpParser\Node\Expr\FuncCall;
|
|||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PHPStan\Reflection\ParametersAcceptor;
|
||||
use PHPStan\Reflection\FunctionReflection;
|
||||
use PHPStan\Reflection\MethodReflection;
|
||||
use PHPStan\Reflection\Type\UnionTypeMethodReflection;
|
||||
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
|
@ -65,16 +66,14 @@ final class RemoveExtraParametersRector extends AbstractRector
|
|||
return null;
|
||||
}
|
||||
|
||||
/** @var ParametersAcceptor $parametersAcceptor */
|
||||
$parametersAcceptor = $this->callReflectionResolver->resolveParametersAcceptor(
|
||||
$functionLikeReflection,
|
||||
$node
|
||||
);
|
||||
if ($functionLikeReflection === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$maximumAllowedParameterCount = $this->resolveMaximumAllowedParameterCount($functionLikeReflection);
|
||||
|
||||
$numberOfParameters = count($parametersAcceptor->getParameters());
|
||||
$numberOfArguments = count($node->args);
|
||||
|
||||
for ($i = $numberOfParameters; $i <= $numberOfArguments; ++$i) {
|
||||
for ($i = $maximumAllowedParameterCount; $i <= $numberOfArguments; ++$i) {
|
||||
unset($node->args[$i]);
|
||||
}
|
||||
|
||||
|
@ -100,20 +99,35 @@ final class RemoveExtraParametersRector extends AbstractRector
|
|||
}
|
||||
}
|
||||
|
||||
$parametersAcceptor = $this->callReflectionResolver->resolveParametersAcceptor(
|
||||
$this->callReflectionResolver->resolveCall($node),
|
||||
$node
|
||||
);
|
||||
|
||||
if (! $parametersAcceptor instanceof ParametersAcceptor) {
|
||||
$reflection = $this->callReflectionResolver->resolveCall($node);
|
||||
if ($reflection === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// can be any number of arguments → nothing to limit here
|
||||
if ($parametersAcceptor->isVariadic()) {
|
||||
if ($reflection->getVariants() === []) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return count($parametersAcceptor->getParameters()) >= count($node->args);
|
||||
foreach ($reflection->getVariants() as $parametersAcceptor) {
|
||||
// can be any number of arguments → nothing to limit here
|
||||
if ($parametersAcceptor->isVariadic()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodReflection|FunctionReflection $reflection
|
||||
*/
|
||||
private function resolveMaximumAllowedParameterCount(object $reflection): int
|
||||
{
|
||||
$parameterCounts = [0];
|
||||
foreach ($reflection->getVariants() as $parametersAcceptor) {
|
||||
$parameterCounts[] = count($parametersAcceptor->getParameters());
|
||||
}
|
||||
|
||||
return (int) max($parameterCounts);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Php71\Tests\Rector\FuncCall\RemoveExtraParametersRector\Fixture;
|
||||
|
||||
final class SkipVersionCompare
|
||||
{
|
||||
/**
|
||||
* @param string|null $value
|
||||
* @return bool|int
|
||||
*/
|
||||
public function run($value)
|
||||
{
|
||||
if ($value === null) {
|
||||
return version_compare('one', 'two');
|
||||
}
|
||||
|
||||
return version_compare('one', 'two', $value);
|
||||
}
|
||||
}
|
|
@ -68,15 +68,13 @@ final class StrncmpMatchAndRefactor implements StrStartWithMatchAndRefactorInter
|
|||
)) {
|
||||
return $this->strStartsWithFactory->createFromFuncCall($binaryOp->left, $isPositive);
|
||||
}
|
||||
|
||||
if ($binaryOp->right instanceof FuncCall && $this->nodeNameResolver->isName(
|
||||
$binaryOp->right,
|
||||
self::FUNCTION_NAME
|
||||
)) {
|
||||
return $this->strStartsWithFactory->createFromFuncCall($binaryOp->right, $isPositive);
|
||||
if (! $binaryOp->right instanceof FuncCall) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
if (! $this->nodeNameResolver->isName($binaryOp->right, self::FUNCTION_NAME)) {
|
||||
return null;
|
||||
}
|
||||
return $this->strStartsWithFactory->createFromFuncCall($binaryOp->right, $isPositive);
|
||||
}
|
||||
|
||||
public function refactorStrStartsWith(StrStartsWith $strStartsWith): ?Node
|
||||
|
|
|
@ -32,16 +32,16 @@ final class StrposMatchAndRefactor implements StrStartWithMatchAndRefactorInterf
|
|||
/**
|
||||
* @var StrStartsWithFuncCallFactory
|
||||
*/
|
||||
private $startsWithFuncCallFactory;
|
||||
private $strStartsWithFuncCallFactory;
|
||||
|
||||
public function __construct(
|
||||
NodeNameResolver $nodeNameResolver,
|
||||
ValueResolver $valueResolver,
|
||||
StrStartsWithFuncCallFactory $startsWithFuncCallFactory
|
||||
StrStartsWithFuncCallFactory $strStartsWithFuncCallFactory
|
||||
) {
|
||||
$this->nodeNameResolver = $nodeNameResolver;
|
||||
$this->valueResolver = $valueResolver;
|
||||
$this->startsWithFuncCallFactory = $startsWithFuncCallFactory;
|
||||
$this->strStartsWithFuncCallFactory = $strStartsWithFuncCallFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,6 +88,6 @@ final class StrposMatchAndRefactor implements StrStartWithMatchAndRefactorInterf
|
|||
$strposFuncCall = $strStartsWith->getFuncCall();
|
||||
$strposFuncCall->name = new Name('str_starts_with');
|
||||
|
||||
return $this->startsWithFuncCallFactory->createStrStartsWith($strStartsWith);
|
||||
return $this->strStartsWithFuncCallFactory->createStrStartsWith($strStartsWith);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,11 +63,6 @@ final class NewUniqueObjectToEntityFactoryRector extends AbstractRector implemen
|
|||
*/
|
||||
private $staticTypesInClassResolver;
|
||||
|
||||
/**
|
||||
* @var array|mixed
|
||||
*/
|
||||
private $typesToServices;
|
||||
|
||||
public function __construct(PropertyNaming $propertyNaming, StaticTypesInClassResolver $staticTypesInClassResolver)
|
||||
{
|
||||
$this->propertyNaming = $propertyNaming;
|
||||
|
|
|
@ -63,9 +63,10 @@ final class RenameFunctionRector extends AbstractRector implements ConfigurableR
|
|||
}
|
||||
|
||||
$node->name = $this->createName($newFunction);
|
||||
return $node;
|
||||
}
|
||||
|
||||
return $node;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,9 +30,10 @@ use Webmozart\Assert\Assert;
|
|||
final class InferParamFromClassMethodReturnRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PARAM_FROM_CLASS_METHOD_RETURNS = 'param_from_class_method_returns';
|
||||
public const INFER_PARAMS_FROM_CLASS_METHOD_RETURNS = 'infer_param_from_class_method_returns';
|
||||
|
||||
/**
|
||||
* @var InferParamFromClassMethodReturn[]
|
||||
|
@ -100,7 +101,7 @@ class SomeClass
|
|||
CODE_SAMPLE
|
||||
,
|
||||
[
|
||||
self::PARAM_FROM_CLASS_METHOD_RETURNS => [
|
||||
self::INFER_PARAMS_FROM_CLASS_METHOD_RETURNS => [
|
||||
new InferParamFromClassMethodReturn('SomeClass', 'process', 'getNodeTypes'),
|
||||
],
|
||||
]
|
||||
|
@ -160,7 +161,7 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
$inferParamsFromClassMethodReturns = $configuration[self::PARAM_FROM_CLASS_METHOD_RETURNS] ?? [];
|
||||
$inferParamsFromClassMethodReturns = $configuration[self::INFER_PARAMS_FROM_CLASS_METHOD_RETURNS] ?? [];
|
||||
Assert::allIsInstanceOf($inferParamsFromClassMethodReturns, InferParamFromClassMethodReturn::class);
|
||||
|
||||
$this->inferParamFromClassMethodReturn = $inferParamsFromClassMethodReturns;
|
||||
|
|
|
@ -156,18 +156,18 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$classReflection = $this->reflectionProvider->getClass($className);
|
||||
$nativeClassReflection = $classReflection->getNativeReflection();
|
||||
return $nativeClassReflection->getConstructor();
|
||||
$reflectionClass = $classReflection->getNativeReflection();
|
||||
return $reflectionClass->getConstructor();
|
||||
}
|
||||
|
||||
private function resolveClassToInstantiateByParameterReflection(ReflectionParameter $reflectionParameter): ?string
|
||||
{
|
||||
$parameterType = $reflectionParameter->getType();
|
||||
if (! $parameterType instanceof ReflectionType) {
|
||||
$reflectionType = $reflectionParameter->getType();
|
||||
if (! $reflectionType instanceof ReflectionType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$requiredType = (string) $parameterType;
|
||||
$requiredType = (string) $reflectionType;
|
||||
|
||||
return $this->classToInstantiateByType[$requiredType] ?? null;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
|
||||
$services->set(InferParamFromClassMethodReturnRector::class)
|
||||
->call('configure', [[
|
||||
InferParamFromClassMethodReturnRector::PARAM_FROM_CLASS_METHOD_RETURNS => $configuration,
|
||||
InferParamFromClassMethodReturnRector::INFER_PARAMS_FROM_CLASS_METHOD_RETURNS => $configuration,
|
||||
]]);
|
||||
};
|
||||
|
|
|
@ -263,9 +263,9 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
$classReflection = $this->reflectionProvider->getClass($className);
|
||||
$nativeClassReflection = $classReflection->getNativeReflection();
|
||||
$reflectionClass = $classReflection->getNativeReflection();
|
||||
|
||||
$constructorReflectionMethod = $nativeClassReflection->getConstructor();
|
||||
$constructorReflectionMethod = $reflectionClass->getConstructor();
|
||||
if (! $constructorReflectionMethod instanceof ReflectionMethod) {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -121,9 +121,9 @@ final class TypeProvidingExprFromClassResolver
|
|||
Scope $scope,
|
||||
ObjectType $objectType
|
||||
): ?PropertyFetch {
|
||||
$nativeReflection = $classReflection->getNativeReflection();
|
||||
$reflectionClass = $classReflection->getNativeReflection();
|
||||
|
||||
foreach ($nativeReflection->getProperties() as $reflectionProperty) {
|
||||
foreach ($reflectionClass->getProperties() as $reflectionProperty) {
|
||||
/** @var PhpPropertyReflection $phpPropertyReflection */
|
||||
$phpPropertyReflection = $classReflection->getProperty($reflectionProperty->getName(), $scope);
|
||||
|
||||
|
|
|
@ -97,12 +97,12 @@ final class CallTypeAnalyzer
|
|||
}
|
||||
|
||||
$methodReflection = $classReflection->getMethod($methodName, $scope);
|
||||
$functionVariant = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
|
||||
$parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
|
||||
|
||||
$parameterTypes = [];
|
||||
|
||||
/** @var ParameterReflection $parameterReflection */
|
||||
foreach ($functionVariant->getParameters() as $parameterReflection) {
|
||||
foreach ($parametersAcceptor->getParameters() as $parameterReflection) {
|
||||
$parameterTypes[] = $parameterReflection->getType();
|
||||
}
|
||||
|
||||
|
|
|
@ -111,26 +111,13 @@ final class PHPUnitDataProviderParamTypeInferer implements ParamTypeInfererInter
|
|||
*/
|
||||
private function resolveReturnStaticArrayTypeByParameterPosition(array $returns, int $parameterPosition): Type
|
||||
{
|
||||
$paramOnPositionTypes = [];
|
||||
$firstReturnedExpr = $returns[0]->expr;
|
||||
|
||||
if (! $returns[0]->expr instanceof Array_) {
|
||||
if (! $firstReturnedExpr instanceof Array_) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
foreach ($returns[0]->expr->items as $singleDataProvidedSet) {
|
||||
if (! $singleDataProvidedSet instanceof ArrayItem || ! $singleDataProvidedSet->value instanceof Array_) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
foreach ($singleDataProvidedSet->value->items as $position => $singleDataProvidedSetItem) {
|
||||
if ($position !== $parameterPosition || ! $singleDataProvidedSetItem instanceof ArrayItem) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$paramOnPositionTypes[] = $this->nodeTypeResolver->resolve($singleDataProvidedSetItem->value);
|
||||
}
|
||||
}
|
||||
|
||||
$paramOnPositionTypes = $this->resolveParamOnPositionTypes($firstReturnedExpr, $parameterPosition);
|
||||
if ($paramOnPositionTypes === []) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
@ -193,4 +180,31 @@ final class PHPUnitDataProviderParamTypeInferer implements ParamTypeInfererInter
|
|||
|
||||
return $this->phpDocInfoFactory->createFromNodeOrEmpty($parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Type[]
|
||||
*/
|
||||
private function resolveParamOnPositionTypes(Array_ $array, int $parameterPosition): array
|
||||
{
|
||||
$paramOnPositionTypes = [];
|
||||
|
||||
foreach ($array->items as $singleDataProvidedSet) {
|
||||
if (! $singleDataProvidedSet instanceof ArrayItem || ! $singleDataProvidedSet->value instanceof Array_) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
foreach ($singleDataProvidedSet->value->items as $position => $singleDataProvidedSetItem) {
|
||||
if ($position !== $parameterPosition) {
|
||||
continue;
|
||||
}
|
||||
if (! $singleDataProvidedSetItem instanceof ArrayItem) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$paramOnPositionTypes[] = $this->nodeTypeResolver->resolve($singleDataProvidedSetItem->value);
|
||||
}
|
||||
}
|
||||
|
||||
return $paramOnPositionTypes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,11 @@ use Rector\TypeDeclaration\Contract\TypeInferer\PropertyTypeInfererInterface;
|
|||
|
||||
final class DoctrineColumnPropertyTypeInferer implements PropertyTypeInfererInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const DATE_TIME_INTERFACE = 'DateTimeInterface';
|
||||
|
||||
/**
|
||||
* @var Type[]
|
||||
*
|
||||
|
@ -72,11 +77,11 @@ final class DoctrineColumnPropertyTypeInferer implements PropertyTypeInfererInte
|
|||
'varbinary' => new StringType(),
|
||||
'set' => new StringType(),
|
||||
// date time objects
|
||||
'date' => new ObjectType('DateTimeInterface'),
|
||||
'datetime' => new ObjectType('DateTimeInterface'),
|
||||
'timestamp' => new ObjectType('DateTimeInterface'),
|
||||
'time' => new ObjectType('DateTimeInterface'),
|
||||
'year' => new ObjectType('DateTimeInterface'),
|
||||
'date' => new ObjectType(self::DATE_TIME_INTERFACE),
|
||||
'datetime' => new ObjectType(self::DATE_TIME_INTERFACE),
|
||||
'timestamp' => new ObjectType(self::DATE_TIME_INTERFACE),
|
||||
'time' => new ObjectType(self::DATE_TIME_INTERFACE),
|
||||
'year' => new ObjectType(self::DATE_TIME_INTERFACE),
|
||||
];
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use Rector\Core\HttpKernel\RectorKernel;
|
|||
use Rector\Core\Stubs\PHPStanStubLoader;
|
||||
use Rector\Core\Stubs\StubLoader;
|
||||
use Rector\Core\ValueObject\Bootstrap\BootstrapConfigs;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symplify\PackageBuilder\Console\Input\StaticInputDetector;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
|
@ -27,7 +28,8 @@ final class RectorContainerFactory
|
|||
|
||||
$environment = $this->createEnvironment($configFileInfos);
|
||||
|
||||
$rectorKernel = new RectorKernel($environment, $isDebug);
|
||||
// mt_rand is needed to invalidate container cache in case of class changes to be registered as services
|
||||
$rectorKernel = new RectorKernel($environment . mt_rand(0, 10000), $isDebug);
|
||||
if ($configFileInfos !== []) {
|
||||
$configFilePaths = $this->unpackRealPathsFromFileInfos($configFileInfos);
|
||||
$rectorKernel->setConfigs($configFilePaths);
|
||||
|
|
Loading…
Reference in New Issue
Block a user