diff --git a/.github/workflows/run_on_project.yaml b/.github/workflows/run_on_project.yaml index 941cd8a2..b9c25ed2 100644 --- a/.github/workflows/run_on_project.yaml +++ b/.github/workflows/run_on_project.yaml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - php_version: ['8.2'] + php_version: ['8.4'] steps: - @@ -24,7 +24,7 @@ jobs: - run: composer require rector/argtyper --ansi - # clone laravel project with dependencies + # clone symfony/console project with dependencies - run: git clone https://github.com/symfony/console.git --depth=1 - run: composer install --working-dir console --ansi diff --git a/src/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector.php b/src/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector.php index 0a259cb2..28a79e90 100644 --- a/src/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector.php +++ b/src/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector.php @@ -91,11 +91,11 @@ public function refactor(Node $node): ?Class_ continue; } - // keep nullability if the param is already nullable or implicitly nullable via a null default, - // otherwise the "?" would be dropped and the param would become implicitly nullable (deprecated) + // a null default value implies the type must stay nullable $isNullable = $classMethodType->isNullable() || $param->type instanceof NullableType || $this->hasNullDefault($param); + $typeNode = TypeResolver::resolveTypeNode($classMethodType->getType()); if ($this->shouldSkipOverride($param, $classMethodType)) { diff --git a/src/Rector/Rector/Function_/AddFunctionParamTypeRector.php b/src/Rector/Rector/Function_/AddFunctionParamTypeRector.php index 7db7c8c7..b58277e5 100644 --- a/src/Rector/Rector/Function_/AddFunctionParamTypeRector.php +++ b/src/Rector/Rector/Function_/AddFunctionParamTypeRector.php @@ -5,8 +5,10 @@ namespace Rector\ArgTyper\Rector\Rector\Function_; use PhpParser\Node; +use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Name; use PhpParser\Node\NullableType; +use PhpParser\Node\Param; use PhpParser\Node\Stmt\Function_; use PHPStan\Type\NeverType; use PHPStan\Type\NullType; @@ -64,7 +66,8 @@ public function refactor(Node $node): ?Function_ continue; } - $isNullable = $paramFunctionType->isNullable(); + // a null default value implies the type must stay nullable + $isNullable = $paramFunctionType->isNullable() || $this->hasDefaultNull($param); $typeNode = TypeResolver::resolveTypeNode($paramFunctionType->getType()); if ($paramFunctionType->isObjectType() && ($param->type instanceof Name || ($param->type instanceof NullableType && $param->type->type instanceof Name))) { @@ -87,4 +90,13 @@ public function refactor(Node $node): ?Function_ return $node; } + + private function hasDefaultNull(Param $param): bool + { + if (! $param->default instanceof ConstFetch) { + return false; + } + + return $param->default->name->toLowerString() === 'null'; + } } diff --git a/tests/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector/AddClassMethodParamTypeRectorTest.php b/tests/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector/AddClassMethodParamTypeRectorTest.php index d637a5e6..1dfaa04f 100644 --- a/tests/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector/AddClassMethodParamTypeRectorTest.php +++ b/tests/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector/AddClassMethodParamTypeRectorTest.php @@ -10,6 +10,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use Rector\ArgTyper\Configuration\CallLikeTypesConfigurationProvider; use Rector\ArgTyper\Rector\ValueObject\ClassMethodType; +use Rector\ArgTyper\Tests\Rector\Rector\ClassMethod\AddClassMethodParamTypeRector\Fixture\AddNullableForDefaultNull; use Rector\ArgTyper\Tests\Rector\Rector\ClassMethod\AddClassMethodParamTypeRector\Fixture\AddNullableScalarFromNullDefault; use Rector\ArgTyper\Tests\Rector\Rector\ClassMethod\AddClassMethodParamTypeRector\Fixture\KeepDateTimeInterface; use Rector\ArgTyper\Tests\Rector\Rector\ClassMethod\AddClassMethodParamTypeRector\Fixture\KeepNullableDateTimeInterface; @@ -35,6 +36,7 @@ public function test(string $filePath): void new ClassMethodType(KeepNullableDateTimeInterface::class, 'record', 0, 'object:' . \DateTime::class), new ClassMethodType(KeepDateTimeInterface::class, 'record', 0, 'object:' . \DateTime::class), new ClassMethodType(SkipIntToFloatOverride::class, 'passInteger', 0, IntegerType::class), + new ClassMethodType(AddNullableForDefaultNull::class, 'run', 0, StringType::class), new ClassMethodType(KeepNullableScalarParam::class, 'translate', 0, StringType::class), new ClassMethodType(AddNullableScalarFromNullDefault::class, 'translate', 0, StringType::class), ]; diff --git a/tests/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector/Fixture/add_nullable_for_default_null.php.inc b/tests/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector/Fixture/add_nullable_for_default_null.php.inc new file mode 100644 index 00000000..e6a45dec --- /dev/null +++ b/tests/Rector/Rector/ClassMethod/AddClassMethodParamTypeRector/Fixture/add_nullable_for_default_null.php.inc @@ -0,0 +1,25 @@ + +----- + diff --git a/tests/Rector/Rector/Function_/AddFunctionParamTypeRector/AddFunctionParamTypeRectorTest.php b/tests/Rector/Rector/Function_/AddFunctionParamTypeRector/AddFunctionParamTypeRectorTest.php index e53eb5ba..7d57af80 100644 --- a/tests/Rector/Rector/Function_/AddFunctionParamTypeRector/AddFunctionParamTypeRectorTest.php +++ b/tests/Rector/Rector/Function_/AddFunctionParamTypeRector/AddFunctionParamTypeRectorTest.php @@ -28,6 +28,11 @@ public function test(string $filePath): void 0, StringType::class ), + new FuncCallType( + 'Rector\ArgTyper\Tests\Rector\Rector\Function_\AddFunctionParamTypeRector\Fixture\defaultNullFunction', + 0, + StringType::class + ), ]); $this->doTestFile($filePath); diff --git a/tests/Rector/Rector/Function_/AddFunctionParamTypeRector/Fixture/default_null_function.php.inc b/tests/Rector/Rector/Function_/AddFunctionParamTypeRector/Fixture/default_null_function.php.inc new file mode 100644 index 00000000..05f711cb --- /dev/null +++ b/tests/Rector/Rector/Function_/AddFunctionParamTypeRector/Fixture/default_null_function.php.inc @@ -0,0 +1,19 @@ + +----- +