diff --git a/composer.json b/composer.json index f4db949..c155b57 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ }, "require-dev": { "azjezz/psl": "^1.6||^2.0", - "nikic/php-parser": "^4.14.0", + "composer/semver": "^3.3", + "nikic/php-parser": "^4.14.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.0", diff --git a/tests/Type/PslTypeSpecifyingExtensionTest.php b/tests/Type/PslTypeSpecifyingExtensionTest.php index dd5f603..cfcb288 100644 --- a/tests/Type/PslTypeSpecifyingExtensionTest.php +++ b/tests/Type/PslTypeSpecifyingExtensionTest.php @@ -2,6 +2,8 @@ namespace Psl\PHPStan\Type; +use Composer\InstalledVersions; +use Composer\Semver\VersionParser; use PHPStan\Testing\TypeInferenceTestCase; class PslTypeSpecifyingExtensionTest extends TypeInferenceTestCase @@ -15,6 +17,11 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/coerce.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/assert.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/matches.php'); + if (InstalledVersions::satisfies(new VersionParser(), 'azjezz/psl', '<2.0.0')) { + yield from $this->gatherAssertTypes(__DIR__ . '/data/complexTypev1.php'); + } else { + yield from $this->gatherAssertTypes(__DIR__ . '/data/complexTypev2.php'); + } } /** diff --git a/tests/Type/data/coerce.php b/tests/Type/data/coerce.php index ab6f45a..45b17ab 100644 --- a/tests/Type/data/coerce.php +++ b/tests/Type/data/coerce.php @@ -23,9 +23,10 @@ public function coerceShape(array $input): void ])), ]); - $input = $specification->coerce($input); + $output = $specification->coerce($input); - assertType('array{name: string, age: int, location?: array{city: string, state: string, country: string}}', $input); + assertType('array{name: string, age: int, location?: array{city: string, state: string, country: string}}', $output); + assertType('array', $input); } public function coerceInt($i): void @@ -33,6 +34,7 @@ public function coerceInt($i): void $spec = Type\int(); $coerced = $spec->coerce($i); assertType('int', $coerced); + assertType('mixed', $i); } public function coerceWrongShape(): void diff --git a/tests/Type/data/complexTypev1.php b/tests/Type/data/complexTypev1.php new file mode 100644 index 0000000..cf56a98 --- /dev/null +++ b/tests/Type/data/complexTypev1.php @@ -0,0 +1,32 @@ + $intNullOrString, + 'transportation' => $bikeAndPlane, + 'something' => Type\union($intNullOrString, $bikeAndPlane) + ]); + + $output = $shape->coerce($input); + assertType('array{name_or_length: int|string|null, transportation: PslComplexV1Test\Bike&PslComplexV1Test\Plane, something: int|(PslComplexV1Test\Bike&PslComplexV1Test\Plane)|string|null}', $output); + } + +} diff --git a/tests/Type/data/complexTypev2.php b/tests/Type/data/complexTypev2.php new file mode 100644 index 0000000..7de9dca --- /dev/null +++ b/tests/Type/data/complexTypev2.php @@ -0,0 +1,28 @@ += 2.0.0 + */ +class ComplexTypesV2 +{ + public function coerceShapeWithComplexTypes($input): void + { + $intNullOrString = Type\union(Type\int(), Type\nullable(Type\string())); + $bikeAndPlane = Type\intersection(Type\instance_of(Bike::class), Type\instance_of(Plane::class)); + $shape = Type\shape([ + 'name_or_length' => $intNullOrString, + 'transportation' => $bikeAndPlane, + 'something' => Type\union($intNullOrString, $bikeAndPlane) + ]); + + $output = $shape->coerce($input); + assertType('array{name_or_length: int|string|null, transportation: PslComplexV2Test\Bike&PslComplexV2Test\Plane, something: int|(PslComplexV2Test\Bike&PslComplexV2Test\Plane)|string|null}', $output); + } +}