Skip to content

Commit

Permalink
feat(refactor): get rid of more instanceof *Type (#1475)
Browse files Browse the repository at this point in the history
  • Loading branch information
canvural committed Dec 9, 2022
1 parent 1a11021 commit f7f0cd4
Show file tree
Hide file tree
Showing 19 changed files with 80 additions and 51 deletions.
5 changes: 3 additions & 2 deletions src/Methods/BuilderHelper.php
Expand Up @@ -22,6 +22,7 @@
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\VerbosityLevel;

class BuilderHelper
Expand Down Expand Up @@ -211,7 +212,7 @@ public function determineBuilderName(string $modelClassName): string
return EloquentBuilder::class;
}

if ($returnType instanceof ObjectType) {
if ($returnType instanceof TypeWithClassName) {
return $returnType->getClassName();
}

Expand All @@ -223,7 +224,7 @@ public function determineCollectionClassName(string $modelClassName): string
try {
$newCollectionMethod = $this->reflectionProvider->getClass($modelClassName)->getNativeMethod('newCollection');
$returnType = ParametersAcceptorSelector::selectSingle($newCollectionMethod->getVariants())->getReturnType();
if ($returnType instanceof ObjectType) {
if ($returnType instanceof TypeWithClassName) {
return $returnType->getClassName();
}

Expand Down
3 changes: 2 additions & 1 deletion src/Methods/HigherOrderTapProxyExtension.php
Expand Up @@ -10,6 +10,7 @@
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeWithClassName;

final class HigherOrderTapProxyExtension implements MethodsClassReflectionExtension
{
Expand All @@ -23,7 +24,7 @@ public function hasMethod(ClassReflection $classReflection, string $methodName):

$templateType = $templateTypeMap->getType('TClass');

if (! $templateType instanceof ObjectType) {
if (! $templateType instanceof TypeWithClassName) {
return false;
}

Expand Down
3 changes: 2 additions & 1 deletion src/ReturnTypes/BuilderModelFindExtension.php
Expand Up @@ -22,6 +22,7 @@
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeWithClassName;

/**
* @internal
Expand Down Expand Up @@ -61,7 +62,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool

$model = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TModelClass');

if (! $model instanceof ObjectType) {
if (! $model instanceof TypeWithClassName) {
return false;
}

Expand Down
Expand Up @@ -17,6 +17,7 @@
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeTraverser;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;

class CollectionGenericStaticMethodDynamicMethodReturnTypeExtension implements DynamicMethodReturnTypeExtension
Expand Down Expand Up @@ -62,7 +63,7 @@ public function getTypeFromMethodCall(

$calledOnType = $scope->getType($methodCall->var);

if (! $calledOnType instanceof ObjectType) {
if (! $calledOnType instanceof TypeWithClassName) {
return $returnType;
}

Expand Down
3 changes: 2 additions & 1 deletion src/ReturnTypes/EloquentBuilderExtension.php
Expand Up @@ -19,6 +19,7 @@
use PHPStan\Type\IntegerType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;

final class EloquentBuilderExtension implements DynamicMethodReturnTypeExtension
{
Expand Down Expand Up @@ -58,7 +59,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool

$templateTypeMap = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap();

if (! $templateTypeMap->getType('TModelClass') instanceof ObjectType) {
if (! $templateTypeMap->getType('TModelClass') instanceof TypeWithClassName) {
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions src/ReturnTypes/HigherOrderTapProxyExtension.php
Expand Up @@ -11,8 +11,8 @@
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;

/**
* @internal
Expand Down Expand Up @@ -46,7 +46,7 @@ public function getTypeFromMethodCall(
$type = $scope->getType($methodCall->var);
if ($type instanceof GenericObjectType) {
$types = $type->getTypes();
if (count($types) === 1 && $types[0] instanceof ObjectType) {
if (count($types) === 1 && $types[0] instanceof TypeWithClassName) {
return $types[0];
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/ReturnTypes/RelationCollectionExtension.php
Expand Up @@ -17,6 +17,7 @@
use PHPStan\Type\IntegerType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;

/**
* @internal
Expand Down Expand Up @@ -50,7 +51,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool

$modelType = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TRelatedModel');

if (! $modelType instanceof ObjectType) {
if (! $modelType instanceof TypeWithClassName) {
return false;
}

Expand Down
3 changes: 2 additions & 1 deletion src/ReturnTypes/RelationFindExtension.php
Expand Up @@ -22,6 +22,7 @@
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeWithClassName;

/**
* @internal
Expand Down Expand Up @@ -59,7 +60,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool

$modelType = $methodReflection->getDeclaringClass()->getActiveTemplateTypeMap()->getType('TRelatedModel');

if (! $modelType instanceof ObjectType) {
if (! $modelType instanceof TypeWithClassName) {
return false;
}

Expand Down
28 changes: 15 additions & 13 deletions src/Rules/ModelProperties/ModelPropertiesRuleHelper.php
Expand Up @@ -14,8 +14,6 @@
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\ShouldNotHappenException;
use PHPStan\Type\ArrayType;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\GeneralizePrecision;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
Expand Down Expand Up @@ -62,17 +60,21 @@ public function check(MethodReflection $methodReflection, Scope $scope, array $a

$argType = $scope->getType($argValue);

if ($argType instanceof ConstantArrayType) {
if ($argType->isConstantArray()->yes()) {
$errors = [];

$keyType = $argType->getKeyType()->generalize(GeneralizePrecision::lessSpecific());
$constantArrays = $argType->getConstantArrays();

if ($keyType->isInteger()->yes()) {
$valueTypes = $argType->getValuesArray()->getValueTypes();
} elseif ($keyType->isString()->yes()) {
$valueTypes = $argType->getKeysArray()->getValueTypes();
} else {
$valueTypes = [];
$valueTypes = [];

foreach ($constantArrays as $constantArray) {
$keyType = $constantArray->getKeyType()->generalize(GeneralizePrecision::lessSpecific());

if ($keyType->isInteger()->yes()) {
$valueTypes = array_merge($valueTypes, $constantArray->getValuesArray()->getValueTypes());
} elseif ($keyType->isString()->yes()) {
$valueTypes = array_merge($valueTypes, $constantArray->getKeysArray()->getValueTypes());
}
}

foreach ($valueTypes as $valueType) {
Expand Down Expand Up @@ -159,9 +161,9 @@ public function hasModelPropertyParameter(
return [$index, new ObjectType($modelReflection->getName())];
}
}
} elseif ($type instanceof ArrayType) {
$keyType = $type->getKeyType();
$itemType = $type->getItemType();
} elseif ($type->isArray()->yes()) {
$keyType = $type->getIterableKeyType();
$itemType = $type->getIterableValueType();

if ($keyType instanceof GenericModelPropertyType) {
return [$index, $keyType->getGenericType()];
Expand Down
12 changes: 7 additions & 5 deletions src/Rules/ModelProperties/ModelPropertyStaticCallRule.php
Expand Up @@ -13,10 +13,10 @@
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;

/**
* @implements \PHPStan\Rules\Rule<\PhpParser\Node\Expr\StaticCall>
Expand Down Expand Up @@ -116,9 +116,11 @@ static function (Type $type) use ($methodName): bool {
return [];
}

if ($classType instanceof ConstantStringType) {
$modelClassName = $classType->getValue();
} elseif ($classType instanceof ObjectType) {
$strings = TypeUtils::getConstantStrings($classType);

if (count($strings) === 1) {
$modelClassName = $strings[0]->getValue();
} elseif ($classType instanceof TypeWithClassName) {
$modelClassName = $classType->getClassName();
} else {
return [];
Expand Down
3 changes: 2 additions & 1 deletion src/Rules/ModelRuleHelper.php
Expand Up @@ -13,6 +13,7 @@
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeWithClassName;

final class ModelRuleHelper
{
Expand All @@ -39,7 +40,7 @@ public function findModelReflectionFromType(Type $type): ?ClassReflection

$modelType = TypeCombinator::removeNull($modelType);

if (! $modelType instanceof ObjectType) {
if (! $modelType instanceof TypeWithClassName) {
return null;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Rules/OctaneCompatibilityRule.php
Expand Up @@ -13,6 +13,7 @@
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeWithClassName;

/**
* @implements Rule<MethodCall>
Expand Down Expand Up @@ -43,7 +44,7 @@ public function processNode(Node $node, Scope $scope): array

$calledOnType = $scope->getType($node->var);

if (! $calledOnType instanceof ObjectType) {
if (! $calledOnType instanceof TypeWithClassName) {
return [];
}

Expand Down
24 changes: 14 additions & 10 deletions src/Rules/RelationExistenceRule.php
Expand Up @@ -72,15 +72,19 @@ public function processNode(Node $node, Scope $scope): array
$relations = [];

if ($valueType->isConstantArray()->yes()) {
$relations = array_merge(
$relations,
...array_map(function (Type $type) {
return TypeUtils::getConstantStrings($type);
}, $valueType->getKeyTypes()), // @phpstan-ignore-line
...array_map(function (Type $type) {
return TypeUtils::getConstantStrings($type);
}, $valueType->getValueTypes()), // @phpstan-ignore-line
);
$arrays = $valueType->getConstantArrays();

foreach ($arrays as $array) {
$relations = array_merge(
$relations,
...array_map(function (Type $type) {
return TypeUtils::getConstantStrings($type);
}, $array->getKeyTypes()),
...array_map(function (Type $type) {
return TypeUtils::getConstantStrings($type);
}, $array->getValueTypes()),
);
}
} else {
$constants = TypeUtils::getConstantStrings($valueType);

Expand Down Expand Up @@ -153,7 +157,7 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$errors += $closure($calledOnType, $relationName, $node);
$errors = array_merge($errors, $closure($calledOnType, $relationName, $node));
}

return $errors;
Expand Down
3 changes: 1 addition & 2 deletions src/Types/ModelProperty/GenericModelPropertyType.php
Expand Up @@ -5,7 +5,6 @@
namespace NunoMaduro\Larastan\Types\ModelProperty;

use PHPStan\TrinaryLogic;
use PHPStan\Type\ClassStringType;
use PHPStan\Type\CompoundType;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\Generic\TemplateType;
Expand Down Expand Up @@ -82,7 +81,7 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
$typeToInfer = new ObjectType($receivedType->getValue());
} elseif ($receivedType instanceof self) {
$typeToInfer = $receivedType->type;
} elseif ($receivedType instanceof ClassStringType) {
} elseif ($receivedType->isClassStringType()->yes()) {
$typeToInfer = $this->getGenericType();

if ($typeToInfer instanceof TemplateType) {
Expand Down
3 changes: 2 additions & 1 deletion src/Types/ModelRelationsDynamicMethodReturnTypeExtension.php
Expand Up @@ -17,6 +17,7 @@
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;

class ModelRelationsDynamicMethodReturnTypeExtension implements DynamicMethodReturnTypeExtension
{
Expand All @@ -41,7 +42,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool

$returnType = $variants->getReturnType();

if (! $returnType instanceof ObjectType) {
if (! $returnType instanceof TypeWithClassName) {
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Types/RelationDynamicMethodReturnTypeExtension.php
Expand Up @@ -6,7 +6,6 @@

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionVariant;
Expand All @@ -20,6 +19,7 @@
use PHPStan\Type\StaticType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;

class RelationDynamicMethodReturnTypeExtension implements DynamicMethodReturnTypeExtension
{
Expand Down Expand Up @@ -57,7 +57,7 @@ public function getTypeFromMethodCall(
$functionVariant = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
$returnType = $functionVariant->getReturnType();

if (! $returnType instanceof ObjectType) {
if (! $returnType instanceof TypeWithClassName) {
return $returnType;
}

Expand Down
12 changes: 7 additions & 5 deletions src/Types/RelationParserHelper.php
Expand Up @@ -12,10 +12,10 @@
use PHPStan\Parser\Parser;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\Generic\GenericClassStringType;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;

class RelationParserHelper
{
Expand Down Expand Up @@ -87,14 +87,16 @@ public function findRelatedModelInRelationMethod(
$argType = $methodScope->getType($methodCall->getArgs()[0]->value);
$returnClass = null;

if ($argType instanceof ConstantStringType) {
$returnClass = $argType->getValue();
$constantStrings = TypeUtils::getConstantStrings($argType);

if (count($constantStrings) === 1) {
$returnClass = $constantStrings[0]->getValue();
}

if ($argType instanceof GenericClassStringType) {
$modelType = $argType->getGenericType();

if (! $modelType instanceof ObjectType) {
if (! $modelType instanceof TypeWithClassName) {
return null;
}

Expand Down
3 changes: 3 additions & 0 deletions tests/Rules/Data/relation-existence-rule.php
Expand Up @@ -50,3 +50,6 @@
\App\User::query()->with('foo:id,name');
\App\User::with(['foo:id', 'accounts']);
\App\User::query()->with(['foo:id', 'accounts']);

/** @var array{foo:string}|array{0: 'bar'} $a */
\App\User::with($a);

0 comments on commit f7f0cd4

Please sign in to comment.