Decouple TraitScopeFaker (#1302)

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Tomas Votruba 2021-11-25 13:21:56 +03:00 committed by GitHub
parent 9ba0f6305f
commit 12ac17392f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 52 additions and 35 deletions

View File

@ -14,7 +14,6 @@ use PhpParser\NodeTraverser;
use PHPStan\AnalysedCodeException;
use PHPStan\Analyser\MutatingScope;
use PHPStan\Analyser\NodeScopeResolver;
use PHPStan\Analyser\ScopeContext;
use PHPStan\BetterReflection\Reflector\ClassReflector;
use PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
@ -25,7 +24,6 @@ use Rector\Caching\FileSystem\DependencyResolver;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\StaticReflection\SourceLocator\ParentAttributeSourceLocator;
use Rector\Core\StaticReflection\SourceLocator\RenamedClassesSourceLocator;
use Rector\Core\Stubs\DummyTraitClass;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\RemoveDeepChainMethodCallNodeVisitor;
use Symplify\PackageBuilder\Reflection\PrivatesAccessor;
@ -53,6 +51,7 @@ final class PHPStanNodeScopeResolver
private PrivatesAccessor $privatesAccessor,
private RenamedClassesSourceLocator $renamedClassesSourceLocator,
private ParentAttributeSourceLocator $parentAttributeSourceLocator,
private TraitScopeFaker $traitScopeFaker,
) {
}
@ -73,7 +72,7 @@ final class PHPStanNodeScopeResolver
$traitReflectionClass = $this->reflectionProvider->getClass($traitName);
$scopeContext = $this->createDummyClassScopeContext($scope);
$scopeContext = $this->traitScopeFaker->createDummyClassScopeContext($scope);
$traitScope = clone $scope;
$this->privatesAccessor->setPrivateProperty($traitScope, 'context', $scopeContext);
@ -208,16 +207,4 @@ final class PHPStanNodeScopeResolver
]);
$this->privatesAccessor->setPrivateProperty($classReflector, 'sourceLocator', $aggregateSourceLocator);
}
private function createDummyClassScopeContext(MutatingScope $mutatingScope): ScopeContext
{
// this has to be faked, because trait PHPStan does not traverse trait without a class
/** @var ScopeContext $scopeContext */
$scopeContext = $this->privatesAccessor->getPrivateProperty($mutatingScope, 'context');
$dummyClassReflection = $this->reflectionProvider->getClass(DummyTraitClass::class);
// faking a class reflection
return ScopeContext::create($scopeContext->getFile())
->enterClass($dummyClassReflection);
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Rector\NodeTypeResolver\PHPStan\Scope;
use PHPStan\Analyser\MutatingScope;
use PHPStan\Analyser\ScopeContext;
use PHPStan\Reflection\ReflectionProvider;
use Rector\Core\Stubs\DummyTraitClass;
use Symplify\PackageBuilder\Reflection\PrivatesAccessor;
final class TraitScopeFaker
{
public function __construct(
private PrivatesAccessor $privatesAccessor,
private ReflectionProvider $reflectionProvider
) {
}
public function createDummyClassScopeContext(MutatingScope $mutatingScope): ScopeContext
{
// this has to be faked, because trait PHPStan does not traverse trait without a class
/** @var ScopeContext $scopeContext */
$scopeContext = $this->privatesAccessor->getPrivateProperty($mutatingScope, 'context');
$dummyClassReflection = $this->reflectionProvider->getClass(DummyTraitClass::class);
// faking a class reflection
return ScopeContext::create($scopeContext->getFile())
->enterClass($dummyClassReflection);
}
}

View File

@ -23,6 +23,7 @@ use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\ElseIf_;
use PhpParser\Node\Stmt\If_;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\FloatType;
@ -168,8 +169,13 @@ CODE_SAMPLE
return null;
}
private function resolveCount(bool $isNegated, FuncCall $funcCall): Identical | Greater
private function resolveCount(bool $isNegated, FuncCall $funcCall): Identical | Greater | null
{
$countedType = $this->getType($funcCall->args[0]->value);
if ($countedType instanceof ArrayType) {
return null;
}
$lNumber = new LNumber(0);
// compare === 0, assumption

View File

@ -17,7 +17,6 @@ use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Stmt\ElseIf_;
use PhpParser\Node\Stmt\If_;
use PHPStan\Analyser\Scope;
use PHPStan\Type\ArrayType;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -94,11 +93,6 @@ CODE_SAMPLE
return null;
}
$parentScope = $parent->getAttribute(AttributeKey::SCOPE);
if (! $parentScope instanceof Scope) {
return null;
}
$processIdentical = $this->processIdenticalOrNotIdentical($parent, $node, $expr);
if ($processIdentical !== null) {
return $processIdentical;
@ -143,14 +137,7 @@ CODE_SAMPLE
private function isArray(Expr $expr): bool
{
/** @var Scope|null $scope */
$scope = $expr->getAttribute(AttributeKey::SCOPE);
if (! $scope instanceof Scope) {
return false;
}
return $scope->getType($expr) instanceof ArrayType;
return $this->getType($expr) instanceof ArrayType;
}
private function processIdenticalOrNotIdentical(Node $node, FuncCall $funcCall, Expr $expr): ?Expr

View File

@ -62,9 +62,7 @@ final class GenericClassStringTypeNormalizer
public function isAllGenericClassStringType(UnionType $unionType): bool
{
$types = $unionType->getTypes();
foreach ($types as $type) {
foreach ($unionType->getTypes() as $type) {
if (! $type instanceof GenericClassStringType) {
return false;
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\Core\PhpParser;
use Nette\Utils\Strings;
use PhpParser\BuilderHelpers;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
@ -14,6 +15,7 @@ use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Yield_;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\ValueObject\SprintfStringAndArgs;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -88,7 +90,12 @@ final class NodeTransformer
{
$arrayItems = $this->transformConcatToItems($concat);
return new Array_($arrayItems);
$array = BuilderHelpers::normalizeValue($arrayItems);
if (! $array instanceof Array_) {
throw new ShouldNotHappenException();
}
return $array;
}
private function splitMessageAndArgs(FuncCall $sprintfFuncCall): ?SprintfStringAndArgs

View File

@ -33,7 +33,7 @@ final class OnCallMethodReturnArray
{
$array = $this->get();
if (count($array) > 0) {
if ($array !== []) {
}
}