From ddd36040f73cc5c23a73dbc39e1c390817c34062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20A=2E=20L=C3=B3pez=20L=C3=B3pez?= Date: Sat, 11 Jan 2025 21:23:29 -0500 Subject: [PATCH 1/3] Setup for upgrade --- composer.json | 1 + phpstan.neon | 2 ++ 2 files changed, 3 insertions(+) diff --git a/composer.json b/composer.json index d2ecb85..436d8af 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,7 @@ }, "require-dev": { "maglnet/composer-require-checker": "^4.7", + "phpstan/phpstan-deprecation-rules": "^1.2", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "^10.2", "symplify/easy-coding-standard": "^12.1" diff --git a/phpstan.neon b/phpstan.neon index 05aafa2..d84b9e1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,6 +2,8 @@ includes: - extension.neon - vendor/phpstan/phpstan-phpunit/extension.neon - vendor/phpstan/phpstan-phpunit/rules.neon + - phar://phpstan.phar/conf/bleedingEdge.neon + - vendor/phpstan/phpstan-deprecation-rules/rules.neon parameters: ignoreErrors: From 4d631a6063e91aa349fd6b41beadc34a4605355a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20A=2E=20L=C3=B3pez=20L=C3=B3pez?= Date: Sat, 11 Jan 2025 21:23:46 -0500 Subject: [PATCH 2/3] Changes by `ecs` --- .../ApplicationPropertiesClassReflectionExtension.php | 2 +- src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php | 8 ++++---- src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php | 8 ++++---- ...ActiveRecordDynamicStaticMethodReturnTypeExtension.php | 4 ++-- tests/ServiceMapTest.php | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Reflection/ApplicationPropertiesClassReflectionExtension.php b/src/Reflection/ApplicationPropertiesClassReflectionExtension.php index 0b0424c..81962dc 100644 --- a/src/Reflection/ApplicationPropertiesClassReflectionExtension.php +++ b/src/Reflection/ApplicationPropertiesClassReflectionExtension.php @@ -21,7 +21,7 @@ final class ApplicationPropertiesClassReflectionExtension implements PropertiesC public function __construct( private readonly AnnotationsPropertiesClassReflectionExtension $annotationsProperties, private readonly ReflectionProvider $reflectionProvider, - private readonly ServiceMap $serviceMap + private readonly ServiceMap $serviceMap, ) {} public function hasProperty(ClassReflection $classReflection, string $propertyName): bool diff --git a/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php b/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php index b75663d..28046ea 100644 --- a/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php +++ b/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php @@ -54,7 +54,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool public function getTypeFromMethodCall( MethodReflection $methodReflection, MethodCall $methodCall, - Scope $scope + Scope $scope, ): Type { $calledOnType = $scope->getType($methodCall->var); if (!$calledOnType instanceof ActiveQueryObjectType) { @@ -63,7 +63,7 @@ public function getTypeFromMethodCall( 'Unexpected type %s during method call %s at line %d', get_class($calledOnType), $methodReflection->getName(), - $methodCall->getLine() + $methodCall->getLine(), ), ); } @@ -90,7 +90,7 @@ public function getTypeFromMethodCall( new NullType(), $calledOnType->isAsArray() ? new ArrayType(new StringType(), new MixedType()) - : new ActiveRecordObjectType($calledOnType->getModelClass()) + : new ActiveRecordObjectType($calledOnType->getModelClass()), ); } @@ -98,7 +98,7 @@ public function getTypeFromMethodCall( new IntegerType(), $calledOnType->isAsArray() ? new ArrayType(new StringType(), new MixedType()) - : new ActiveRecordObjectType($calledOnType->getModelClass()) + : new ActiveRecordObjectType($calledOnType->getModelClass()), ); } } diff --git a/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php b/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php index 9346e3a..93abee9 100644 --- a/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php +++ b/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php @@ -35,7 +35,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool public function getTypeFromMethodCall( MethodReflection $methodReflection, MethodCall $methodCall, - Scope $scope + Scope $scope, ): Type { $arg = $methodCall->args[0]; @@ -45,7 +45,7 @@ public function getTypeFromMethodCall( 'Unexpected arg %s during method call %s at line %d', get_class($arg), $methodReflection->getName(), - $methodCall->getLine() + $methodCall->getLine(), ), ); } @@ -56,8 +56,8 @@ public function getTypeFromMethodCall( sprintf( 'Invalid argument provided to method %s' . PHP_EOL . 'Hint: You should use ::class instead of ::className()', - $methodReflection->getName() - ) + $methodReflection->getName(), + ), ); } diff --git a/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php b/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php index 26adea7..1675aaa 100644 --- a/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php +++ b/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php @@ -57,7 +57,7 @@ public function isStaticMethodSupported(MethodReflection $methodReflection): boo public function getTypeFromStaticMethodCall( MethodReflection $methodReflection, StaticCall $methodCall, - Scope $scope + Scope $scope, ): Type { $className = $methodCall->class; $returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); @@ -75,7 +75,7 @@ public function getTypeFromStaticMethodCall( if ($returnType instanceof UnionType) { return TypeCombinator::union( new NullType(), - new ActiveRecordObjectType($name) + new ActiveRecordObjectType($name), ); } diff --git a/tests/ServiceMapTest.php b/tests/ServiceMapTest.php index c1257f5..57d5684 100644 --- a/tests/ServiceMapTest.php +++ b/tests/ServiceMapTest.php @@ -45,7 +45,7 @@ public function testThrowExceptionWhenServiceHasUnsupportedType(): void $this->expectExceptionMessage('Unsupported service definition for unsupported-type'); new ServiceMap( - __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'yii-config-invalid-unsupported-type.php' + __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'yii-config-invalid-unsupported-type.php', ); } @@ -58,7 +58,7 @@ public function testThrowExceptionWhenServiceHasUnsupportedArray(): void $this->expectExceptionMessage('Cannot guess service definition for unsupported-array'); new ServiceMap( - __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'yii-config-invalid-unsupported-array.php' + __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'yii-config-invalid-unsupported-array.php', ); } @@ -71,7 +71,7 @@ public function testThrowExceptionWhenComponentHasInvalidValue(): void $this->expectExceptionMessage('Invalid value for component with id customComponent. Expected object or array.'); new ServiceMap( - __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'yii-config-invalid-component.php' + __DIR__ . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . 'yii-config-invalid-component.php', ); } From 21afef8bcec4ed20bc199c5530aa6c30b8dcdaa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20A=2E=20L=C3=B3pez=20L=C3=B3pez?= Date: Sun, 12 Jan 2025 12:09:23 -0500 Subject: [PATCH 3/3] Fix all errors at level 1 --- ...eQueryDynamicMethodReturnTypeExtension.php | 11 +++---- ...RecordDynamicMethodReturnTypeExtension.php | 3 +- ...DynamicStaticMethodReturnTypeExtension.php | 30 ++++++++++++------- src/Type/ActiveRecordObjectType.php | 5 ++-- ...tainerDynamicMethodReturnTypeExtension.php | 6 +++- ...ectionDynamicMethodReturnTypeExtension.php | 2 +- 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php b/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php index 28046ea..9adcb0d 100644 --- a/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php +++ b/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php @@ -38,10 +38,11 @@ public function getClass(): string */ public function isMethodSupported(MethodReflection $methodReflection): bool { - if ( - ParametersAcceptorSelector::selectSingle($methodReflection->getVariants()) - ->getReturnType() instanceof ThisType - ) { + /** @phpstan-ignore staticMethod.deprecated */ + $returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants()) + ->getReturnType(); + + if ($returnType instanceof ThisType) { return true; } @@ -72,7 +73,7 @@ public function getTypeFromMethodCall( if ($methodName === 'asArray') { $argType = isset($methodCall->args[0]) && $methodCall->args[0] instanceof Arg ? $scope->getType($methodCall->args[0]->value) : new ConstantBooleanType(true); - if (!$argType instanceof ConstantBooleanType) { + if ($argType->isBoolean()->no()) { throw new ShouldNotHappenException( sprintf('Invalid argument provided to asArray method at line %d', $methodCall->getLine()), ); diff --git a/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php b/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php index 93abee9..551353b 100644 --- a/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php +++ b/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php @@ -9,7 +9,6 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\MethodReflection; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicMethodReturnTypeExtension; use PHPStan\Type\Type; use yii\db\ActiveRecord; @@ -51,7 +50,7 @@ public function getTypeFromMethodCall( } $argType = $scope->getType($arg->value); - if (!$argType instanceof ConstantStringType) { + if (count($argType->getConstantStrings()) === 0) { throw new ShouldNotHappenException( sprintf( 'Invalid argument provided to method %s' . PHP_EOL . diff --git a/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php b/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php index 1675aaa..f5425c5 100644 --- a/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php +++ b/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php @@ -9,10 +9,10 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParametersAcceptorSelector; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\ShouldNotHappenException; use PHPStan\Type\DynamicStaticMethodReturnTypeExtension; use PHPStan\Type\NullType; -use PHPStan\Type\ObjectType; use PHPStan\Type\ThisType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -20,10 +20,16 @@ use yii\db\ActiveQuery; use yii\db\ActiveRecord; -use function is_a; - final class ActiveRecordDynamicStaticMethodReturnTypeExtension implements DynamicStaticMethodReturnTypeExtension { + private ReflectionProvider $reflectionProvider; + + public function __construct( + ReflectionProvider $reflectionProvider, + ) { + $this->reflectionProvider = $reflectionProvider; + } + public function getClass(): string { return ActiveRecord::class; @@ -34,6 +40,7 @@ public function getClass(): string */ public function isStaticMethodSupported(MethodReflection $methodReflection): bool { + /** @phpstan-ignore staticMethod.deprecated */ $returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); if ($returnType instanceof ThisType) { return true; @@ -41,26 +48,27 @@ public function isStaticMethodSupported(MethodReflection $methodReflection): boo if ($returnType instanceof UnionType) { foreach ($returnType->getTypes() as $type) { - if ($type instanceof ObjectType) { - return is_a($type->getClassName(), $this->getClass(), true); + if ($type->isObject()->yes()) { + return $this->reflectionProvider->hasClass($this->getClass()) && + $type->getClassName() === $this->getClass(); } } } - return $returnType instanceof ObjectType && - is_a($returnType->getClassName(), ActiveQuery::class, true); + return $returnType->isObject()->yes() && $returnType->getClassName() === ActiveQuery::class; } - /** - * @throws ShouldNotHappenException - */ public function getTypeFromStaticMethodCall( MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope, ): Type { $className = $methodCall->class; - $returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + $returnType = ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); if (!$className instanceof Name) { return $returnType; diff --git a/src/Type/ActiveRecordObjectType.php b/src/Type/ActiveRecordObjectType.php index b25b146..d5b8fcd 100644 --- a/src/Type/ActiveRecordObjectType.php +++ b/src/Type/ActiveRecordObjectType.php @@ -7,7 +7,6 @@ use ArrayAccess; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; -use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ErrorType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; @@ -19,7 +18,7 @@ final class ActiveRecordObjectType extends ObjectType */ public function hasOffsetValueType(Type $offsetType): TrinaryLogic { - if (!$offsetType instanceof ConstantStringType) { + if (count($offsetType->getConstantStrings()) === 0) { return TrinaryLogic::createNo(); } @@ -32,7 +31,7 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type { - if ($offsetType instanceof ConstantStringType && $this->hasProperty($offsetType->getValue())->no()) { + if (count($offsetType->getConstantStrings()) > 0 && $this->hasProperty($offsetType->getValue())->no()) { return new ErrorType(); } diff --git a/src/Type/ContainerDynamicMethodReturnTypeExtension.php b/src/Type/ContainerDynamicMethodReturnTypeExtension.php index fd4d57c..0c63c52 100644 --- a/src/Type/ContainerDynamicMethodReturnTypeExtension.php +++ b/src/Type/ContainerDynamicMethodReturnTypeExtension.php @@ -42,6 +42,10 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method } } - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } } diff --git a/src/Type/HeaderCollectionDynamicMethodReturnTypeExtension.php b/src/Type/HeaderCollectionDynamicMethodReturnTypeExtension.php index da83128..6631a4a 100644 --- a/src/Type/HeaderCollectionDynamicMethodReturnTypeExtension.php +++ b/src/Type/HeaderCollectionDynamicMethodReturnTypeExtension.php @@ -45,7 +45,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method /** @var Arg $arg */ $arg = $methodCall->args[2]; if ($arg->value instanceof ConstFetch) { - $value = $arg->value->name->parts[0]; + $value = $arg->value->name->getParts()[0]; if ($value === 'true') { // $first === true, therefore string return new StringType();