Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(refactor): get rid of more instanceof *Type #1475

Merged
merged 1 commit into from Dec 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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);