From 12ac17392fa3f08687efd047feabd34cea9b1e62 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 25 Nov 2021 13:21:56 +0300 Subject: [PATCH] Decouple TraitScopeFaker (#1302) Co-authored-by: GitHub Action --- .../Scope/PHPStanNodeScopeResolver.php | 17 ++-------- .../PHPStan/Scope/TraitScopeFaker.php | 32 +++++++++++++++++++ .../Rector/If_/ExplicitBoolCompareRector.php | 8 ++++- ...CountArrayToEmptyArrayComparisonRector.php | 15 +-------- .../GenericClassStringTypeNormalizer.php | 4 +-- src/PhpParser/NodeTransformer.php | 9 +++++- .../on_call_method_return_array.php.inc | 2 +- 7 files changed, 52 insertions(+), 35 deletions(-) create mode 100644 packages/NodeTypeResolver/PHPStan/Scope/TraitScopeFaker.php diff --git a/packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php b/packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php index 2c7a53086d4..cf2a5fcfe6f 100644 --- a/packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php +++ b/packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php @@ -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); - } } diff --git a/packages/NodeTypeResolver/PHPStan/Scope/TraitScopeFaker.php b/packages/NodeTypeResolver/PHPStan/Scope/TraitScopeFaker.php new file mode 100644 index 00000000000..a0bb55700be --- /dev/null +++ b/packages/NodeTypeResolver/PHPStan/Scope/TraitScopeFaker.php @@ -0,0 +1,32 @@ +privatesAccessor->getPrivateProperty($mutatingScope, 'context'); + $dummyClassReflection = $this->reflectionProvider->getClass(DummyTraitClass::class); + + // faking a class reflection + return ScopeContext::create($scopeContext->getFile()) + ->enterClass($dummyClassReflection); + } +} diff --git a/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php b/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php index 53bb3759f54..52a3c647d3e 100644 --- a/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php +++ b/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php @@ -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 diff --git a/rules/CodingStyle/Rector/FuncCall/CountArrayToEmptyArrayComparisonRector.php b/rules/CodingStyle/Rector/FuncCall/CountArrayToEmptyArrayComparisonRector.php index c8cd11dd7c0..66e05998468 100644 --- a/rules/CodingStyle/Rector/FuncCall/CountArrayToEmptyArrayComparisonRector.php +++ b/rules/CodingStyle/Rector/FuncCall/CountArrayToEmptyArrayComparisonRector.php @@ -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 diff --git a/rules/TypeDeclaration/TypeAnalyzer/GenericClassStringTypeNormalizer.php b/rules/TypeDeclaration/TypeAnalyzer/GenericClassStringTypeNormalizer.php index 67d99ff441c..bca4a0b8cd3 100644 --- a/rules/TypeDeclaration/TypeAnalyzer/GenericClassStringTypeNormalizer.php +++ b/rules/TypeDeclaration/TypeAnalyzer/GenericClassStringTypeNormalizer.php @@ -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; } diff --git a/src/PhpParser/NodeTransformer.php b/src/PhpParser/NodeTransformer.php index 2b0c3ddb706..5f81393cd9e 100644 --- a/src/PhpParser/NodeTransformer.php +++ b/src/PhpParser/NodeTransformer.php @@ -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 diff --git a/tests/Issues/Issue6561/Fixture/on_call_method_return_array.php.inc b/tests/Issues/Issue6561/Fixture/on_call_method_return_array.php.inc index 851ad91fef8..4393e421886 100644 --- a/tests/Issues/Issue6561/Fixture/on_call_method_return_array.php.inc +++ b/tests/Issues/Issue6561/Fixture/on_call_method_return_array.php.inc @@ -33,7 +33,7 @@ final class OnCallMethodReturnArray { $array = $this->get(); - if (count($array) > 0) { + if ($array !== []) { } }