Skip to content

Commit

Permalink
Remove dynamic type checks #2 (#5941)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba authored Mar 21, 2021
1 parent a781b3b commit ae1c6b9
Show file tree
Hide file tree
Showing 38 changed files with 221 additions and 290 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Nette\Utils\Strings;
use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
Expand Down Expand Up @@ -127,7 +128,7 @@ public function parse(TokenIterator $tokenIterator): PhpDocNode
// might be in the middle of annotations
$tokenIterator->tryConsumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC);

$phpDocNode = new PhpDocNode(array_values($children));
$phpDocNode = new PhpDocNode($children);
$docContent = $this->annotationContentResolver->resolveFromTokenIterator($originalTokenIterator);

return $this->phpDocNodeMapper->transform($phpDocNode, $docContent);
Expand Down Expand Up @@ -199,14 +200,14 @@ private function setPhpDocNodeFactories(array $phpDocNodeFactories): void
}
}

private function parseChildAndStoreItsPositions(TokenIterator $tokenIterator): Node
private function parseChildAndStoreItsPositions(TokenIterator $tokenIterator): PhpDocChildNode
{
$originalTokenIterator = clone $tokenIterator;
$docContent = $this->annotationContentResolver->resolveFromTokenIterator($originalTokenIterator);

$tokenStart = $this->getTokenIteratorIndex($tokenIterator);

/** @var PhpDocNode $phpDocNode */
/** @var PhpDocChildNode $phpDocNode */
$phpDocNode = $this->privatesCaller->callPrivateMethod($this, 'parseChild', [$tokenIterator]);

$tokenEnd = $this->resolveTokenEnd($tokenIterator);
Expand Down
8 changes: 4 additions & 4 deletions packages/Caching/FileSystem/DependencyResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Rector\Caching\FileSystem;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Analyser\MutatingScope;
use PHPStan\Dependency\DependencyResolver as PHPStanDependencyResolver;
use PHPStan\File\FileHelper;
use Rector\Core\Configuration\Configuration;
Expand Down Expand Up @@ -40,7 +40,7 @@ public function __construct(
/**
* @return string[]
*/
public function resolveDependencies(Node $node, Scope $scope): array
public function resolveDependencies(Node $node, MutatingScope $mutatingScope): array
{
$fileInfos = $this->configuration->getFileInfos();

Expand All @@ -51,15 +51,15 @@ public function resolveDependencies(Node $node, Scope $scope): array

$dependencyFiles = [];

$nodeDependencies = $this->phpStanDependencyResolver->resolveDependencies($node, $scope);
$nodeDependencies = $this->phpStanDependencyResolver->resolveDependencies($node, $mutatingScope);
foreach ($nodeDependencies as $nodeDependency) {
$dependencyFile = $nodeDependency->getFileName();
if (! $dependencyFile) {
continue;
}

$dependencyFile = $this->fileHelper->normalizePath($dependencyFile);
if ($scope->getFile() === $dependencyFile) {
if ($mutatingScope->getFile() === $dependencyFile) {
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,14 @@ private function resolveClassOrInterfaceScope(ClassLike $classLike, Scope $scope
return $scope->enterClass($classReflection);
}

private function resolveDependentFiles(Node $node, Scope $scope): void
private function resolveDependentFiles(Node $node, MutatingScope $mutatingScope): void
{
if (! $this->configuration->isCacheEnabled()) {
return;
}

try {
$dependentFiles = $this->dependencyResolver->resolveDependencies($node, $scope);
$dependentFiles = $this->dependencyResolver->resolveDependencies($node, $mutatingScope);
foreach ($dependentFiles as $dependentFile) {
$this->dependentFiles[] = $dependentFile;
}
Expand Down
7 changes: 4 additions & 3 deletions packages/NodeTypeResolver/PHPStan/Scope/ScopeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Rector\NodeTypeResolver\PHPStan\Scope;

use PHPStan\Analyser\Scope;
use PHPStan\Analyser\MutatingScope;
use PHPStan\Analyser\ScopeContext;
use PHPStan\Analyser\ScopeFactory as PHPStanScopeFactory;
use Symplify\SmartFileSystem\SmartFileInfo;
Expand All @@ -21,8 +21,9 @@ public function __construct(PHPStanScopeFactory $phpStanScopeFactory)
$this->phpStanScopeFactory = $phpStanScopeFactory;
}

public function createFromFile(SmartFileInfo $fileInfo): Scope
public function createFromFile(SmartFileInfo $fileInfo): MutatingScope
{
return $this->phpStanScopeFactory->create(ScopeContext::create($fileInfo->getRealPath()));
$scopeContext = ScopeContext::create($fileInfo->getRealPath());
return $this->phpStanScopeFactory->create($scopeContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private function processFqnNameImport(
Node $node,
IdentifierTypeNode $identifierTypeNode,
FullyQualifiedObjectType $fullyQualifiedObjectType
): PhpDocParserNode {
): IdentifierTypeNode {
if ($this->classNameImportSkipper->shouldSkipNameForFullyQualifiedObjectType(
$node,
$fullyQualifiedObjectType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
use PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory;
use Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocator\IntermediateSourceLocator;

Expand All @@ -30,7 +29,7 @@ public function __construct(
$this->intermediateSourceLocator = $intermediateSourceLocator;
}

public function create(): SourceLocator
public function create(): MemoizingSourceLocator
{
$phpStanSourceLocator = $this->betterReflectionSourceLocatorFactory->create();

Expand Down
57 changes: 12 additions & 45 deletions packages/NodeTypeResolver/TypeAnalyzer/CountableTypeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
namespace Rector\NodeTypeResolver\TypeAnalyzer;

use PhpParser\Node;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\NodeTypeResolver\NodeTypeCorrector\PregMatchTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeResolver;

Expand All @@ -29,6 +26,11 @@ final class CountableTypeAnalyzer
*/
private $nodeTypeResolver;

/**
* @var ObjectType[]
*/
private $countableObjectTypes = [];

public function __construct(
ArrayTypeAnalyzer $arrayTypeAnalyzer,
NodeTypeResolver $nodeTypeResolver,
Expand All @@ -37,60 +39,25 @@ public function __construct(
$this->arrayTypeAnalyzer = $arrayTypeAnalyzer;
$this->pregMatchTypeCorrector = $pregMatchTypeCorrector;
$this->nodeTypeResolver = $nodeTypeResolver;
}

public function isCountableType(Node $node): bool
{
$nodeType = $this->nodeTypeResolver->resolve($node);
$nodeType = $this->pregMatchTypeCorrector->correct($node, $nodeType);

if ($this->isCountableObjectType($nodeType)) {
return true;
}

return $this->arrayTypeAnalyzer->isArrayType($node);
}

private function isCountableObjectType(Type $type): bool
{
$countableObjectTypes = [
$this->countableObjectTypes = [
new ObjectType('Countable'),
new ObjectType('SimpleXMLElement'),
new ObjectType('ResourceBundle'),
];

if ($type instanceof UnionType) {
return $this->isCountableUnionType($type, $countableObjectTypes);
}

if ($type instanceof ObjectType) {
foreach ($countableObjectTypes as $countableObjectType) {
if (! is_a($type->getClassName(), $countableObjectType->getClassName(), true)) {
continue;
}

return true;
}
}

return false;
}

/**
* @param ObjectType[] $countableObjectTypes
*/
private function isCountableUnionType(UnionType $unionType, array $countableObjectTypes): bool
public function isCountableType(Node $node): bool
{
if ($unionType->isSubTypeOf(new NullType())->yes()) {
return false;
}
$nodeType = $this->nodeTypeResolver->resolve($node);
$nodeType = $this->pregMatchTypeCorrector->correct($node, $nodeType);

foreach ($countableObjectTypes as $countableObjectType) {
if ($unionType->isSuperTypeOf($countableObjectType)->yes()) {
foreach ($this->countableObjectTypes as $countableObjectType) {
if ($countableObjectType->isSuperTypeOf($nodeType)->yes()) {
return true;
}
}

return false;
return $this->arrayTypeAnalyzer->isArrayType($node);
}
}
19 changes: 10 additions & 9 deletions packages/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,15 +309,6 @@ private function resolveCompatibleObjectCandidate(UnionType $unionType): ?TypeWi
return null;
}

private function areTypeWithClassNamesRelated(TypeWithClassName $firstType, TypeWithClassName $secondType): bool
{
if (is_a($firstType->getClassName(), $secondType->getClassName(), true)) {
return true;
}

return is_a($secondType->getClassName(), $firstType->getClassName(), true);
}

private function matchTwoObjectTypes(UnionType $unionType): ?TypeWithClassName
{
/** @var TypeWithClassName $unionedType */
Expand All @@ -335,6 +326,16 @@ private function matchTwoObjectTypes(UnionType $unionType): ?TypeWithClassName
return null;
}

private function areTypeWithClassNamesRelated(TypeWithClassName $firstType, TypeWithClassName $secondType): bool
{
if ($firstType->accepts($secondType, false)->yes()) {
return true;
}

return $secondType->accepts($firstType, false)
->yes();
}

private function correctObjectType(TypeWithClassName $typeWithClassName): TypeWithClassName
{
if ($typeWithClassName->getClassName() === NodeAbstract::class) {
Expand Down
5 changes: 1 addition & 4 deletions packages/PHPStanStaticTypeMapper/Utils/TypeUnwrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ public function unwrapFirstObjectTypeFromUnionType(Type $type): Type
return $type;
}

/**
* @return Type|UnionType
*/
public function removeNullTypeFromUnionType(UnionType $unionType): Type
public function removeNullTypeFromUnionType(UnionType $unionType): UnionType
{
$unionedTypesWithoutNullType = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StaticType;
use PHPStan\Type\SubtractableType;
use PHPStan\Type\Type;
use Rector\NodeCollector\ScopeResolver\ParentClassScopeResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
Expand Down Expand Up @@ -97,7 +98,7 @@ public function mapToPHPStanType(TypeNode $typeNode, Node $node, NameScope $name
return $this->objectTypeSpecifier->narrowToFullyQualifiedOrAliasedObjectType($node, $objectType);
}

private function mapSelf(Node $node): Type
private function mapSelf(Node $node): SubtractableType
{
/** @var string|null $className */
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
Expand Down
Loading

0 comments on commit ae1c6b9

Please sign in to comment.