From f9ced23730b8ecd45ea0f435d888f7b106444974 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 6 Nov 2021 02:38:24 +0100 Subject: [PATCH 01/13] PHP 8 support and BetterReflection 5.x upgrade This patch brings in PHP 8.0 and 8.1 support through the massive work done by @kukulich on `roave/better-reflection` over the past few months. The upgrade is mostly smooth, but we have some rough edges with: * [x] `TypeIsCovariant`, which needs `ReflectionType`s as well as `Reflector`s * [x] `TypeIsContravariant`, which needs `ReflectionType`s as well as `Reflector`s * [ ] `ReturnTypeCovarianceChanged` uses hacky reflection to get a `Reflector` from a `ReflectionFunctionAbstract` (internal state!) * [ ] `ParameterTypeContravarianceChanged` uses hacky reflection to get a `Reflector` from a `ReflectionFunctionAbstract` (internal state!) * [ ] we miss tests for covariance/contravariance with `ReflectionUnionType` and `ReflectionIntersectionType` (`infection/infection` will highlight that) --- .github/workflows/backwards-compatibility.yml | 3 +- composer.json | 13 +- composer.lock | 134 ++++++++------- src/Change.php | 10 +- src/CompareApi.php | 14 +- src/CompareClasses.php | 20 +-- .../FunctionBased/ParameterTypeChanged.php | 3 +- .../ParameterTypeContravarianceChanged.php | 25 ++- .../FunctionBased/ReturnTypeChanged.php | 3 +- .../ReturnTypeCovarianceChanged.php | 23 ++- .../Variance/TypeIsContravariant.php | 24 ++- .../Variance/TypeIsCovariant.php | 32 +++- .../Variance/TypeWithReflectorScope.php | 30 ++++ .../ComposerInstallationReflectorFactory.php | 7 +- .../StaticClassMapSourceLocator.php | 4 +- .../ClassBased/AncestorRemovedTest.php | 10 +- .../ClassBased/ClassBecameAbstractTest.php | 10 +- .../ClassBased/ClassBecameFinalTest.php | 22 +-- .../ClassBased/ClassBecameInterfaceTest.php | 10 +- .../ClassBased/ClassBecameInternalTest.php | 22 +-- .../ClassBased/ClassBecameTraitTest.php | 10 +- .../ClassBased/ConstantChangedTest.php | 6 +- .../ClassBased/ConstantRemovedTest.php | 10 +- .../ExcludeAnonymousClassesTest.php | 12 +- .../ClassBased/ExcludeInternalClassTest.php | 12 +- .../BCBreak/ClassBased/MethodChangedTest.php | 6 +- .../BCBreak/ClassBased/MethodRemovedTest.php | 10 +- .../ClassBased/PropertyChangedTest.php | 6 +- .../ClassBased/PropertyRemovedTest.php | 34 ++-- .../ClassConstantValueChangedTest.php | 10 +- .../ClassConstantVisibilityReducedTest.php | 10 +- .../ExcludeInternalFunctionTest.php | 11 +- .../FunctionBecameInternalTest.php | 13 +- .../ParameterByReferenceChangedTest.php | 21 +-- .../ParameterDefaultValueChangedTest.php | 21 +-- .../ParameterTypeChangedTest.php | 21 +-- ...ParameterTypeContravarianceChangedTest.php | 21 +-- .../RequiredParameterAmountIncreasedTest.php | 21 +-- .../ReturnTypeByReferenceChangedTest.php | 23 ++- .../FunctionBased/ReturnTypeChangedTest.php | 21 +-- .../ReturnTypeCovarianceChangedTest.php | 23 ++- .../InterfaceBased/AncestorRemovedTest.php | 10 +- .../ExcludeInternalInterfaceTest.php | 10 +- .../InterfaceBecameClassTest.php | 10 +- .../InterfaceBecameTraitTest.php | 10 +- .../InterfaceBased/MethodAddedTest.php | 10 +- .../MethodBased/ExcludeInternalMethodTest.php | 10 +- .../MethodBased/MethodBecameFinalTest.php | 10 +- .../MethodConcretenessChangedTest.php | 10 +- .../MethodBased/MethodScopeChangedTest.php | 10 +- .../MethodVisibilityReducedTest.php | 10 +- .../ExcludeInternalPropertyTest.php | 10 +- .../PropertyBecameInternalTest.php | 10 +- .../PropertyDefaultValueChangedTest.php | 10 +- .../PropertyDocumentedTypeChangedTest.php | 10 +- .../PropertyScopeChangedTest.php | 10 +- .../PropertyVisibilityReducedTest.php | 10 +- .../TraitBased/ExcludeInternalTraitTest.php | 10 +- .../TraitBased/TraitBecameClassTest.php | 10 +- .../TraitBased/TraitBecameInterfaceTest.php | 10 +- .../Variance/TypeIsContravariantTest.php | 142 ++++++++-------- .../Variance/TypeIsCovariantTest.php | 154 ++++++++++-------- ...mposerInstallationReflectorFactoryTest.php | 2 +- .../ReflectionFunctionAbstractNameTest.php | 14 +- .../Formatter/ReflectionPropertyNameTest.php | 28 ++-- .../LocateSourcesViaComposerJsonTest.php | 6 +- .../StaticClassMapSourceLocatorTest.php | 1 + test/unit/StringReflectorFactory.php | 7 +- 68 files changed, 696 insertions(+), 589 deletions(-) create mode 100644 src/DetectChanges/Variance/TypeWithReflectorScope.php diff --git a/.github/workflows/backwards-compatibility.yml b/.github/workflows/backwards-compatibility.yml index 6174d734..f9781259 100644 --- a/.github/workflows/backwards-compatibility.yml +++ b/.github/workflows/backwards-compatibility.yml @@ -15,7 +15,8 @@ jobs: dependencies: - "locked" php-version: - - "7.4" + - "8.0" + - "8.1" operating-system: - "ubuntu-latest" diff --git a/composer.json b/composer.json index a6c71b4c..e0847542 100644 --- a/composer.json +++ b/composer.json @@ -2,13 +2,13 @@ "name": "roave/backward-compatibility-check", "description": "Tool to compare two revisions of a public API to check for BC breaks", "require": { - "php": "^7.4.7", + "php": "~8.0.0 || ~8.1.0", "ext-json": "*", - "azjezz/psl": "^1.6.1", + "azjezz/psl": "^1.9.0", "composer/composer": "^2.1.11", "nikolaposa/version": "^4.1.0", - "ocramius/package-versions": "^2.1.0", - "roave/better-reflection": "^4.12.2", + "ocramius/package-versions": "^2.4.0", + "roave/better-reflection": "5.0.x-dev@DEV", "symfony/console": "^5.3.10" }, "license": "MIT", @@ -45,6 +45,9 @@ "bin/roave-backward-compatibility-check" ], "config": { - "sort-packages": true + "sort-packages": true, + "platform": { + "php": "8.0.99" + } } } diff --git a/composer.lock b/composer.lock index e712d6b1..aca68d4f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2f49715319b3e79d1ff656f355a94458", + "content-hash": "7b1ed5ff940c03d0edc4a7e3a453c53b", "packages": [ { "name": "azjezz/psl", - "version": "1.6.1", + "version": "1.9.2", "source": { "type": "git", "url": "https://github.com/azjezz/psl.git", - "reference": "60683bf0f79efc8deaeb1069f0c25c3212427411" + "reference": "ebbc67d4ad71de1d1c308da67bbb844182f2718b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/azjezz/psl/zipball/60683bf0f79efc8deaeb1069f0c25c3212427411", - "reference": "60683bf0f79efc8deaeb1069f0c25c3212427411", + "url": "https://api.github.com/repos/azjezz/psl/zipball/ebbc67d4ad71de1d1c308da67bbb844182f2718b", + "reference": "ebbc67d4ad71de1d1c308da67bbb844182f2718b", "shasum": "" }, "require": { @@ -26,7 +26,10 @@ "ext-json": "*", "ext-mbstring": "*", "ext-sodium": "*", - "php": "^7.4 || ^8.0" + "php": "~8.0.0 || ~8.1.0" + }, + "suggest": { + "php-standard-library/psalm-plugin": "Psalm integration" }, "type": "library", "extra": { @@ -59,9 +62,15 @@ "description": "PHP Standard Library", "support": { "issues": "https://github.com/azjezz/psl/issues", - "source": "https://github.com/azjezz/psl/tree/1.6.1" + "source": "https://github.com/azjezz/psl/tree/1.9.2" }, - "time": "2021-05-19T11:49:49+00:00" + "funding": [ + { + "url": "https://opencollective.com/php-standard-library", + "type": "open_collective" + } + ], + "time": "2021-11-10T19:56:56+00:00" }, { "name": "beberlei/assert", @@ -599,23 +608,24 @@ }, { "name": "jetbrains/phpstorm-stubs", - "version": "v2019.3", + "version": "v2021.3", "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "883b6facd78e01c0743b554af86fa590c2573f40" + "reference": "c790a8fa467ff5d3f11b0e7c1f3698abbe37b182" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/883b6facd78e01c0743b554af86fa590c2573f40", - "reference": "883b6facd78e01c0743b554af86fa590c2573f40", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/c790a8fa467ff5d3f11b0e7c1f3698abbe37b182", + "reference": "c790a8fa467ff5d3f11b0e7c1f3698abbe37b182", "shasum": "" }, "require-dev": { - "nikic/php-parser": "^4", - "php": "^7.1", - "phpdocumentor/reflection-docblock": "^4.3", - "phpunit/phpunit": "^7" + "friendsofphp/php-cs-fixer": "dev-master", + "nikic/php-parser": "@stable", + "php": "^8.0", + "phpdocumentor/reflection-docblock": "@stable", + "phpunit/phpunit": "@stable" }, "type": "library", "autoload": { @@ -640,9 +650,9 @@ "type" ], "support": { - "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" + "source": "https://github.com/JetBrains/phpstorm-stubs/tree/v2021.3" }, - "time": "2019-12-05T16:56:26+00:00" + "time": "2021-10-19T20:06:47+00:00" }, { "name": "justinrainbow/json-schema", @@ -716,16 +726,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.13.1", + "version": "v4.13.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd" + "reference": "210577fe3cf7badcc5814d99455df46564f3c077" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/63a79e8daa781cac14e5195e63ed8ae231dd10fd", - "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077", "shasum": "" }, "require": { @@ -766,9 +776,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" }, - "time": "2021-11-03T20:52:16+00:00" + "time": "2021-11-30T19:35:32+00:00" }, { "name": "nikolaposa/version", @@ -833,32 +843,32 @@ }, { "name": "ocramius/package-versions", - "version": "2.1.0", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/Ocramius/PackageVersions.git", - "reference": "a7e35c34bc166a5684a1e2f13da7b1d6a821349d" + "reference": "8e96fb9f4671eff86e8e487ff45c49bdc2d2d677" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a7e35c34bc166a5684a1e2f13da7b1d6a821349d", - "reference": "a7e35c34bc166a5684a1e2f13da7b1d6a821349d", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/8e96fb9f4671eff86e8e487ff45c49bdc2d2d677", + "reference": "8e96fb9f4671eff86e8e487ff45c49bdc2d2d677", "shasum": "" }, "require": { - "composer-runtime-api": "^2.0.0", - "php": "^7.4.7 || ~8.0.0" + "composer-runtime-api": "^2.1.0", + "php": "~8.0.0 || ~8.1.0" }, "replace": { "composer/package-versions-deprecated": "*" }, "require-dev": { - "composer/composer": "^2.0.0@dev", - "doctrine/coding-standard": "^8.1.0", + "composer/composer": "^2.1.8", + "doctrine/coding-standard": "^9.0.0", "ext-zip": "^1.15.0", - "infection/infection": "dev-master#8d6c4d6b15ec58d3190a78b7774a5d604ec1075a", - "phpunit/phpunit": "~9.3.11", - "vimeo/psalm": "^4.0.1" + "phpunit/phpunit": "^9.5.9", + "roave/infection-static-analysis-plugin": "^1.10.0", + "vimeo/psalm": "^4.10.0" }, "type": "library", "autoload": { @@ -879,7 +889,7 @@ "description": "Provides efficient querying for installed package versions (no runtime IO)", "support": { "issues": "https://github.com/Ocramius/PackageVersions/issues", - "source": "https://github.com/Ocramius/PackageVersions/tree/2.1.0" + "source": "https://github.com/Ocramius/PackageVersions/tree/2.4.0" }, "funding": [ { @@ -891,7 +901,7 @@ "type": "tidelift" } ], - "time": "2020-10-21T13:48:04+00:00" + "time": "2021-09-19T02:32:19+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -1203,44 +1213,42 @@ }, { "name": "roave/better-reflection", - "version": "4.12.2", + "version": "5.0.x-dev", "source": { "type": "git", "url": "https://github.com/Roave/BetterReflection.git", - "reference": "73c376c7245b2928837ed1e8bef446f57f1148a0" + "reference": "1f7a13be41d110e132fb8f8ec0fce159c9c4639f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/BetterReflection/zipball/73c376c7245b2928837ed1e8bef446f57f1148a0", - "reference": "73c376c7245b2928837ed1e8bef446f57f1148a0", + "url": "https://api.github.com/repos/Roave/BetterReflection/zipball/1f7a13be41d110e132fb8f8ec0fce159c9c4639f", + "reference": "1f7a13be41d110e132fb8f8ec0fce159c9c4639f", "shasum": "" }, "require": { "ext-json": "*", - "jetbrains/phpstorm-stubs": "2019.3", - "nikic/php-parser": "^4.6.0", - "php": ">=7.4.1,<7.5.0", - "phpdocumentor/reflection-docblock": "^5.2.2", - "phpdocumentor/type-resolver": "^1.4.0", - "roave/signature": "^1.3" + "jetbrains/phpstorm-stubs": "2021.3", + "nikic/php-parser": "^4.13.2", + "php": "~8.0.12 || ~8.1.0", + "phpdocumentor/reflection-docblock": "^5.3.0", + "phpdocumentor/type-resolver": "^1.5.0", + "roave/signature": "^1.5" + }, + "conflict": { + "thecodingmachine/safe": "<1.1.3" }, "require-dev": { - "doctrine/coding-standard": "^8.2.0", - "infection/infection": "^0.20.0", - "phpstan/phpstan": "0.12.25", - "phpunit/phpunit": "^9.4.4", - "roave/infection-static-analysis-plugin": "^1.2", - "vimeo/psalm": "^4.2" + "doctrine/coding-standard": "^9.0.0", + "phpstan/phpstan": "^1.2.0", + "phpunit/phpunit": "^9.5.9", + "roave/infection-static-analysis-plugin": "^1.12.0", + "vimeo/psalm": "^4.13.1" }, "suggest": { "composer/composer": "Required to use the ComposerSourceLocator" }, + "default-branch": true, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, "autoload": { "psr-4": { "Roave\\BetterReflection\\": "src" @@ -1275,9 +1283,9 @@ "description": "Better Reflection - an improved code reflection API", "support": { "issues": "https://github.com/Roave/BetterReflection/issues", - "source": "https://github.com/Roave/BetterReflection/tree/4.12.2" + "source": "https://github.com/Roave/BetterReflection/tree/5.0.x" }, - "time": "2020-12-17T17:48:54+00:00" + "time": "2021-12-03T17:55:40+00:00" }, { "name": "roave/signature", @@ -6223,14 +6231,18 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { + "roave/better-reflection": 20, "roave/security-advisories": 20 }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.4.7", + "php": "~8.0.0 || ~8.1.0", "ext-json": "*" }, "platform-dev": [], + "platform-overrides": { + "php": "8.0.99" + }, "plugin-api-version": "2.1.0" } diff --git a/src/Change.php b/src/Change.php index a18fab3a..6a1222be 100644 --- a/src/Change.php +++ b/src/Change.php @@ -7,9 +7,7 @@ use Psl\Str; use Throwable; -/** - * @todo this class probably needs subclassing or being turned into an interface - */ +/** @psalm-immutable */ final class Change { private const ADDED = 'added'; @@ -17,12 +15,14 @@ final class Change private const REMOVED = 'removed'; private const SKIPPED = 'skipped'; + /** @psalm-var self::* */ private string $modificationType; private string $description; private bool $isBcBreak; + /** @psalm-param self::* $modificationType */ private function __construct(string $modificationType, string $description, bool $isBcBreak) { $this->modificationType = $modificationType; @@ -30,21 +30,25 @@ private function __construct(string $modificationType, string $description, bool $this->isBcBreak = $isBcBreak; } + /** @psalm-pure */ public static function added(string $description, bool $isBcBreak): self { return new self(self::ADDED, $description, $isBcBreak); } + /** @psalm-pure */ public static function changed(string $description, bool $isBcBreak): self { return new self(self::CHANGED, $description, $isBcBreak); } + /** @psalm-pure */ public static function removed(string $description, bool $isBcBreak): self { return new self(self::REMOVED, $description, $isBcBreak); } + /** @psalm-pure */ public static function skippedDueToFailure(Throwable $failure): self { // @TODO Note: we may consider importing the full exception for better printing later on diff --git a/src/CompareApi.php b/src/CompareApi.php index bef5361c..6c2b42a8 100644 --- a/src/CompareApi.php +++ b/src/CompareApi.php @@ -4,20 +4,20 @@ namespace Roave\BackwardCompatibility; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\Reflector; interface CompareApi { /** - * @param ClassReflector $definedSymbols containing only defined symbols we want to check - * @param ClassReflector $pastSourcesWithDependencies capable of giving us symbols with their dependencies from the + * @param Reflector $definedSymbols containing only defined symbols we want to check + * @param Reflector $pastSourcesWithDependencies capable of giving us symbols with their dependencies from the * old version of the sources - * @param ClassReflector $newSourcesWithDependencies capable of giving us symbols with their dependencies from the + * @param Reflector $newSourcesWithDependencies capable of giving us symbols with their dependencies from the * new version of the sources */ public function __invoke( - ClassReflector $definedSymbols, - ClassReflector $pastSourcesWithDependencies, - ClassReflector $newSourcesWithDependencies + Reflector $definedSymbols, + Reflector $pastSourcesWithDependencies, + Reflector $newSourcesWithDependencies ): Changes; } diff --git a/src/CompareClasses.php b/src/CompareClasses.php index e6306a29..8f65dd21 100644 --- a/src/CompareClasses.php +++ b/src/CompareClasses.php @@ -11,8 +11,8 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\InterfaceBased; use Roave\BackwardCompatibility\DetectChanges\BCBreak\TraitBased\TraitBased; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound; +use Roave\BetterReflection\Reflector\Reflector; final class CompareClasses implements CompareApi { @@ -33,13 +33,13 @@ public function __construct( } public function __invoke( - ClassReflector $definedSymbols, - ClassReflector $pastSourcesWithDependencies, - ClassReflector $newSourcesWithDependencies + Reflector $definedSymbols, + Reflector $pastSourcesWithDependencies, + Reflector $newSourcesWithDependencies ): Changes { $definedApiClassNames = Dict\map( Dict\filter( - $definedSymbols->getAllClasses(), + $definedSymbols->reflectAllClasses(), function (ReflectionClass $class): bool { return ! ($class->isAnonymous() || $this->isInternalDocComment($class->getDocComment())); } @@ -63,11 +63,11 @@ static function (ReflectionClass $class): string { */ private function makeSymbolsIterator( array $definedApiClassNames, - ClassReflector $pastSourcesWithDependencies, - ClassReflector $newSourcesWithDependencies + Reflector $pastSourcesWithDependencies, + Reflector $newSourcesWithDependencies ): iterable { foreach ($definedApiClassNames as $apiClassName) { - $oldSymbol = $pastSourcesWithDependencies->reflect($apiClassName); + $oldSymbol = $pastSourcesWithDependencies->reflectClass($apiClassName); yield from $this->examineSymbol($oldSymbol, $newSourcesWithDependencies); } @@ -76,10 +76,10 @@ private function makeSymbolsIterator( /** @return iterable */ private function examineSymbol( ReflectionClass $oldSymbol, - ClassReflector $newSourcesWithDependencies + Reflector $newSourcesWithDependencies ): iterable { try { - $newClass = $newSourcesWithDependencies->reflect($oldSymbol->getName()); + $newClass = $newSourcesWithDependencies->reflectClass($oldSymbol->getName()); } catch (IdentifierNotFound $exception) { yield Change::removed(Str\format('Class %s has been deleted', $oldSymbol->getName()), true); diff --git a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeChanged.php index 8b96f770..38d1cef4 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeChanged.php @@ -79,7 +79,6 @@ private function typeToString(?ReflectionType $type): string return 'no type'; } - return ($type->allowsNull() ? '?' : '') - . $type->__toString(); + return $type->__toString(); } } diff --git a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php index 95a9a3c5..68f7bda5 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php @@ -6,13 +6,17 @@ use Psl\Dict; use Psl\Str; +use Psl\Type; +use ReflectionProperty; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; +use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; use Roave\BetterReflection\Reflection\ReflectionParameter; use Roave\BetterReflection\Reflection\ReflectionType; +use Roave\BetterReflection\Reflector\Reflector; /** * When a parameter type changes, the new type should be wider than the previous type, or else @@ -48,7 +52,11 @@ private function compareParameter(ReflectionParameter $fromParameter, Reflection $fromType = $fromParameter->getType(); $toType = $toParameter->getType(); - if (($this->typeIsContravariant)($fromType, $toType)) { + + if (($this->typeIsContravariant)( + new TypeWithReflectorScope($fromType, $this->extractReflector($fromParameter)), + new TypeWithReflectorScope($toType, $this->extractReflector($toParameter)), + )) { return Changes::empty(); } @@ -70,7 +78,18 @@ private function typeToString(?ReflectionType $type): string return 'no type'; } - return ($type->allowsNull() ? '?' : '') - . $type->__toString(); + return $type->__toString(); + } + + + /** @TODO may the gods of BC compliance be merciful on me */ + private function extractReflector(ReflectionParameter $parameter): Reflector + { + $reflectionReflector = new ReflectionProperty(ReflectionFunctionAbstract::class, 'reflector'); + + $reflectionReflector->setAccessible(true); + + return Type\object(Reflector::class) + ->coerce($reflectionReflector->getValue($parameter->getDeclaringFunction())); } } diff --git a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeChanged.php index 296fadc7..7eea221a 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeChanged.php @@ -51,7 +51,6 @@ private function typeToString(?ReflectionType $type): string return 'no type'; } - return ($type->allowsNull() ? '?' : '') - . $type->__toString(); + return $type->__toString(); } } diff --git a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php index dfe47f26..5147aa76 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php @@ -5,12 +5,16 @@ namespace Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased; use Psl\Str; +use Psl\Type; +use ReflectionProperty; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; +use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; use Roave\BetterReflection\Reflection\ReflectionType; +use Roave\BetterReflection\Reflector\Reflector; /** * When the return type of a function changes, the new return type must be covariant to the current type. @@ -34,7 +38,10 @@ public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFun $fromReturnType = $fromFunction->getReturnType(); $toReturnType = $toFunction->getReturnType(); - if (($this->typeIsCovariant)($fromReturnType, $toReturnType)) { + if (($this->typeIsCovariant)( + new TypeWithReflectorScope($fromReturnType, $this->extractReflector($fromFunction)), + new TypeWithReflectorScope($toReturnType, $this->extractReflector($toFunction)), + )) { return Changes::empty(); } @@ -55,7 +62,17 @@ private function typeToString(?ReflectionType $type): string return 'no type'; } - return ($type->allowsNull() ? '?' : '') - . $type->__toString(); + return $type->__toString(); + } + + /** @TODO may the gods of BC compliance be merciful on me */ + private function extractReflector(ReflectionFunctionAbstract $function): Reflector + { + $reflectionReflector = new ReflectionProperty(ReflectionFunctionAbstract::class, 'reflector'); + + $reflectionReflector->setAccessible(true); + + return Type\object(Reflector::class) + ->coerce($reflectionReflector->getValue($function)); } } diff --git a/src/DetectChanges/Variance/TypeIsContravariant.php b/src/DetectChanges/Variance/TypeIsContravariant.php index 31ba0dff..7bbda1a0 100644 --- a/src/DetectChanges/Variance/TypeIsContravariant.php +++ b/src/DetectChanges/Variance/TypeIsContravariant.php @@ -6,6 +6,7 @@ use Psl\Iter; use Psl\Str; +use Roave\BetterReflection\Reflection\ReflectionNamedType; use Roave\BetterReflection\Reflection\ReflectionType; /** @@ -13,13 +14,18 @@ * have a `$type->includes($otherType)` check with actual types represented as value objects, * but that is a massive piece of work that should be done by importing an external library * instead, if this class no longer suffices. + * + * @TODO introduce union/intersection type support here */ final class TypeIsContravariant { public function __invoke( - ?ReflectionType $type, - ?ReflectionType $comparedType + TypeWithReflectorScope $originalType, + TypeWithReflectorScope $newType ): bool { + $type = $originalType->type; + $comparedType = $newType->type; + if ($comparedType === null) { return true; } @@ -29,12 +35,17 @@ public function __invoke( return false; } + if (! $type instanceof ReflectionNamedType || ! $comparedType instanceof ReflectionNamedType) { + // @TODO we'll assume everyting is fine, for now - union and intersection types still need test additions + return true; + } + if ($type->allowsNull() && ! $comparedType->allowsNull()) { return false; } - $typeAsString = $type->__toString(); - $comparedTypeAsString = $comparedType->__toString(); + $typeAsString = $type->getName(); + $comparedTypeAsString = $comparedType->getName(); if (Str\lowercase($typeAsString) === Str\lowercase($comparedTypeAsString)) { return true; @@ -63,9 +74,10 @@ public function __invoke( return false; } - $typeReflectionClass = $type->targetReflectionClass(); + $typeReflectionClass = $originalType->originatingReflector->reflectClass($typeAsString); + $comparedTypeClass = $newType->originatingReflector->reflectClass($comparedTypeAsString); - if ($comparedType->targetReflectionClass()->isInterface()) { + if ($comparedTypeClass->isInterface()) { return $typeReflectionClass->implementsInterface($comparedTypeAsString); } diff --git a/src/DetectChanges/Variance/TypeIsCovariant.php b/src/DetectChanges/Variance/TypeIsCovariant.php index 4c819c44..90287065 100644 --- a/src/DetectChanges/Variance/TypeIsCovariant.php +++ b/src/DetectChanges/Variance/TypeIsCovariant.php @@ -6,7 +6,7 @@ use Psl\Iter; use Psl\Str; -use Roave\BetterReflection\Reflection\ReflectionType; +use Roave\BetterReflection\Reflection\ReflectionNamedType; use Traversable; /** @@ -14,13 +14,19 @@ * have a `$type->includes($otherType)` check with actual types represented as value objects, * but that is a massive piece of work that should be done by importing an external library * instead, if this class no longer suffices. + * + * @TODO introduce union/intersection type support here */ final class TypeIsCovariant { public function __invoke( - ?ReflectionType $type, - ?ReflectionType $comparedType - ): bool { + TypeWithReflectorScope $originalType, + TypeWithReflectorScope $newType + ): bool + { + $type = $originalType->type; + $comparedType = $newType->type; + if ($type === null) { // everything can be covariant to `mixed` return true; @@ -31,12 +37,17 @@ public function __invoke( return false; } + if (! $type instanceof ReflectionNamedType || ! $comparedType instanceof ReflectionNamedType) { + // @TODO we'll assume everyting is fine, for now - union and intersection types still need test additions + return true; + } + if ($comparedType->allowsNull() && ! $type->allowsNull()) { return false; } - $typeAsString = $type->__toString(); - $comparedTypeAsString = $comparedType->__toString(); + $typeAsString = $type->getName(); + $comparedTypeAsString = $comparedType->getName(); if (Str\lowercase($typeAsString) === Str\lowercase($comparedTypeAsString)) { return true; @@ -58,7 +69,9 @@ public function __invoke( } if ($typeAsString === 'iterable' && ! $comparedType->isBuiltin()) { - if ($comparedType->targetReflectionClass()->implementsInterface(Traversable::class)) { + $comparedTypeReflectionClass = $newType->originatingReflector->reflectClass($comparedType->getName()); + + if ($comparedTypeReflectionClass->implementsInterface(Traversable::class)) { // `iterable` can be restricted via any `Iterator` implementation return true; } @@ -74,9 +87,10 @@ public function __invoke( return false; } - $comparedTypeReflectionClass = $comparedType->targetReflectionClass(); + $originalTypeReflectionClass = $originalType->originatingReflector->reflectClass($typeAsString); + $comparedTypeReflectionClass = $newType->originatingReflector->reflectClass($comparedTypeAsString); - if ($type->targetReflectionClass()->isInterface()) { + if ($originalTypeReflectionClass->isInterface()) { return $comparedTypeReflectionClass->implementsInterface($typeAsString); } diff --git a/src/DetectChanges/Variance/TypeWithReflectorScope.php b/src/DetectChanges/Variance/TypeWithReflectorScope.php new file mode 100644 index 00000000..343cc6d6 --- /dev/null +++ b/src/DetectChanges/Variance/TypeWithReflectorScope.php @@ -0,0 +1,30 @@ +locateSources)($installationDirectory), $dependencies, diff --git a/src/SourceLocator/StaticClassMapSourceLocator.php b/src/SourceLocator/StaticClassMapSourceLocator.php index 0c91ae62..55c77af1 100644 --- a/src/SourceLocator/StaticClassMapSourceLocator.php +++ b/src/SourceLocator/StaticClassMapSourceLocator.php @@ -32,7 +32,7 @@ public function __construct( $realPaths = Dict\map($classMap, static function (string $file): string { return Type\string()->assert(Filesystem\canonicalize($file)); }); - + Psl\invariant(Iter\all($realPaths, static function (string $file): bool { return Filesystem\is_file($file); }), 'Invalid class-map.'); @@ -52,6 +52,6 @@ protected function createLocatedSource(Identifier $identifier): ?LocatedSource return null; } - return new LocatedSource(Filesystem\read_file($classFile), $classFile); + return new LocatedSource(Filesystem\read_file($classFile), $identifier->getName(), $classFile); } } diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/AncestorRemovedTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/AncestorRemovedTest.php index 57b56034..58ee700b 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/AncestorRemovedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/AncestorRemovedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\AncestorRemoved; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -49,7 +49,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $className, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($className), - $toReflector->reflect($className), + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), $errors, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameAbstractTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameAbstractTest.php index 9e5a3ff4..f8c41c6a 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameAbstractTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameAbstractTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ClassBecameAbstract; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -49,7 +49,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $className, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($className), - $toReflector->reflect($className), + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), $errors, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameFinalTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameFinalTest.php index d3d61626..2f8b09a3 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameFinalTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameFinalTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ClassBecameFinal; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_map; @@ -44,7 +44,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' [ - $fromReflector->reflect('A'), - $toReflector->reflect('A'), + $fromReflector->reflectClass('A'), + $toReflector->reflectClass('A'), ['[BC] CHANGED: Class A became final'], ], 'B' => [ - $fromReflector->reflect('B'), - $toReflector->reflect('B'), + $fromReflector->reflectClass('B'), + $toReflector->reflectClass('B'), [], ], 'C' => [ - $fromReflector->reflect('C'), - $toReflector->reflect('C'), + $fromReflector->reflectClass('C'), + $toReflector->reflectClass('C'), [], ], 'D' => [ - $fromReflector->reflect('D'), - $toReflector->reflect('D'), + $fromReflector->reflectClass('D'), + $toReflector->reflectClass('D'), [], ], ]; diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInterfaceTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInterfaceTest.php index 43163378..214b32b0 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInterfaceTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInterfaceTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ClassBecameInterface; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -46,7 +46,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $className, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($className), - $toReflector->reflect($className), + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), $errors, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInternalTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInternalTest.php index 68253bd2..cf50cb2a 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInternalTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInternalTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ClassBecameInternal; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_map; @@ -45,7 +45,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' [ - $fromReflector->reflect('A'), - $toReflector->reflect('A'), + $fromReflector->reflectClass('A'), + $toReflector->reflectClass('A'), [], ], 'B' => [ - $fromReflector->reflect('B'), - $toReflector->reflect('B'), + $fromReflector->reflectClass('B'), + $toReflector->reflectClass('B'), ['[BC] CHANGED: B was marked "@internal"'], ], 'C' => [ - $fromReflector->reflect('C'), - $toReflector->reflect('C'), + $fromReflector->reflectClass('C'), + $toReflector->reflectClass('C'), [], ], 'D' => [ - $fromReflector->reflect('D'), - $toReflector->reflect('D'), + $fromReflector->reflectClass('D'), + $toReflector->reflectClass('D'), [], ], ]; diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameTraitTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameTraitTest.php index 960907f9..742843d9 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameTraitTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameTraitTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ClassBecameTrait; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -49,7 +49,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $className, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($className), - $toReflector->reflect($className), + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), $errors, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ConstantChangedTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ConstantChangedTest.php index 85af5c5c..8bd3c6b9 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ConstantChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ConstantChangedTest.php @@ -11,7 +11,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassConstantBased\ClassConstantBased; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClassConstant; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\Assertion; @@ -75,8 +75,8 @@ class TheClass { Change::added('d', true) ), (new ConstantChanged($comparator))( - (new ClassReflector($fromLocator))->reflect('TheClass'), - (new ClassReflector($toLocator))->reflect('TheClass') + (new DefaultReflector($fromLocator))->reflectClass('TheClass'), + (new DefaultReflector($toLocator))->reflectClass('TheClass') ) ); } diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ConstantRemovedTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ConstantRemovedTest.php index da705b8e..2c5fb4ec 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ConstantRemovedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ConstantRemovedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ConstantRemoved; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator; use function array_map; @@ -47,14 +47,14 @@ public function classesToBeTested(): array return [ 'RoaveTestAsset\\ClassWithConstantsBeingRemoved' => [ - (new ClassReflector(new SingleFileSourceLocator( + (new DefaultReflector(new SingleFileSourceLocator( __DIR__ . '/../../../../asset/api/old/ClassWithConstantsBeingRemoved.php', $locator - )))->reflect('RoaveTestAsset\\ClassWithConstantsBeingRemoved'), - (new ClassReflector(new SingleFileSourceLocator( + )))->reflectClass('RoaveTestAsset\\ClassWithConstantsBeingRemoved'), + (new DefaultReflector(new SingleFileSourceLocator( __DIR__ . '/../../../../asset/api/new/ClassWithConstantsBeingRemoved.php', $locator - )))->reflect('RoaveTestAsset\\ClassWithConstantsBeingRemoved'), + )))->reflectClass('RoaveTestAsset\\ClassWithConstantsBeingRemoved'), [ '[BC] REMOVED: Constant RoaveTestAsset\ClassWithConstantsBeingRemoved::removedPublicConstant was removed', '[BC] REMOVED: Constant RoaveTestAsset\ClassWithConstantsBeingRemoved::nameCaseChangePublicConstant was removed', diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ExcludeAnonymousClassesTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ExcludeAnonymousClassesTest.php index 75eb5bf9..d98f76fa 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ExcludeAnonymousClassesTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ExcludeAnonymousClassesTest.php @@ -10,7 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ExcludeAnonymousClasses; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function reset; @@ -20,7 +20,7 @@ final class ExcludeAnonymousClassesTest extends TestCase public function testNormalClassesAreNotExcluded(): void { $locator = (new BetterReflection())->astLocator(); - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('ANormalClass'); - $toReflection = $reflector->reflect('ANormalClass'); + $fromReflection = $reflector->reflectClass('ANormalClass'); + $toReflection = $reflector->reflectClass('ANormalClass'); $check = $this->createMock(ClassBased::class); $check->expects(self::once()) @@ -44,7 +44,7 @@ class ANormalClass {} public function testAnonymousClassesAreExcluded(): void { $locator = (new BetterReflection())->astLocator(); - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' getAllClasses(); + $allClasses = $reflector->reflectAllClasses(); $anonymousClassReflection = reset($allClasses); self::assertInstanceOf(ReflectionClass::class, $anonymousClassReflection); diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ExcludeInternalClassTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ExcludeInternalClassTest.php index 590ed91f..da994b63 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ExcludeInternalClassTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ExcludeInternalClassTest.php @@ -10,7 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ClassBased; use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ExcludeInternalClass; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; /** @covers \Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ExcludeInternalClass */ @@ -19,7 +19,7 @@ final class ExcludeInternalClassTest extends TestCase public function testNormalClassesAreNotExcluded(): void { $locator = (new BetterReflection())->astLocator(); - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('ANormalClass'); - $toReflection = $reflector->reflect('ANormalClass'); + $fromReflection = $reflector->reflectClass('ANormalClass'); + $toReflection = $reflector->reflectClass('ANormalClass'); $check = $this->createMock(ClassBased::class); $check->expects(self::once()) @@ -46,7 +46,7 @@ class ANormalClass {} public function testInternalClassesAreExcluded(): void { $locator = (new BetterReflection())->astLocator(); - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('AnInternalClass'); + $reflection = $reflector->reflectClass('AnInternalClass'); $check = $this->createMock(ClassBased::class); $check->expects(self::never())->method('__invoke'); diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/MethodChangedTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/MethodChangedTest.php index d702f20a..0fb3f4be 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/MethodChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/MethodChangedTest.php @@ -11,7 +11,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\MethodBased\MethodBased; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionMethod; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\Assertion; @@ -78,8 +78,8 @@ public function g() {} Change::added('G', true) ), (new MethodChanged($comparator))( - (new ClassReflector($fromLocator))->reflect('TheClass'), - (new ClassReflector($toLocator))->reflect('TheClass') + (new DefaultReflector($fromLocator))->reflectClass('TheClass'), + (new DefaultReflector($toLocator))->reflectClass('TheClass') ) ); } diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/MethodRemovedTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/MethodRemovedTest.php index c0e0d45c..a841bdbb 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/MethodRemovedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/MethodRemovedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\MethodRemoved; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator; use function array_map; @@ -47,14 +47,14 @@ public function classesToBeTested(): array return [ 'RoaveTestAsset\\ClassWithMethodsBeingRemoved' => [ - (new ClassReflector(new SingleFileSourceLocator( + (new DefaultReflector(new SingleFileSourceLocator( __DIR__ . '/../../../../asset/api/old/ClassWithMethodsBeingRemoved.php', $locator - )))->reflect('RoaveTestAsset\\ClassWithMethodsBeingRemoved'), - (new ClassReflector(new SingleFileSourceLocator( + )))->reflectClass('RoaveTestAsset\\ClassWithMethodsBeingRemoved'), + (new DefaultReflector(new SingleFileSourceLocator( __DIR__ . '/../../../../asset/api/new/ClassWithMethodsBeingRemoved.php', $locator - )))->reflect('RoaveTestAsset\\ClassWithMethodsBeingRemoved'), + )))->reflectClass('RoaveTestAsset\\ClassWithMethodsBeingRemoved'), [ '[BC] REMOVED: Method RoaveTestAsset\ClassWithMethodsBeingRemoved#removedPublicMethod() was removed', '[BC] REMOVED: Method RoaveTestAsset\ClassWithMethodsBeingRemoved#removedProtectedMethod() was removed', diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/PropertyChangedTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/PropertyChangedTest.php index 92d7e004..17bb37c5 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/PropertyChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/PropertyChangedTest.php @@ -11,7 +11,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyBased; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\Assertion; @@ -75,8 +75,8 @@ class TheClass { Change::added('d', true) ), (new PropertyChanged($comparator))( - (new ClassReflector($fromLocator))->reflect('TheClass'), - (new ClassReflector($toLocator))->reflect('TheClass') + (new DefaultReflector($fromLocator))->reflectClass('TheClass'), + (new DefaultReflector($toLocator))->reflectClass('TheClass') ) ); } diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/PropertyRemovedTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/PropertyRemovedTest.php index ec3ced1c..7e8e934d 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/PropertyRemovedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/PropertyRemovedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\PropertyRemoved; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; @@ -48,14 +48,14 @@ public function classesToBeTested(): array return [ 'RoaveTestAsset\\ClassWithPropertiesBeingRemoved' => [ - (new ClassReflector(new SingleFileSourceLocator( + (new DefaultReflector(new SingleFileSourceLocator( __DIR__ . '/../../../../asset/api/old/ClassWithPropertiesBeingRemoved.php', $locator - )))->reflect('RoaveTestAsset\\ClassWithPropertiesBeingRemoved'), - (new ClassReflector(new SingleFileSourceLocator( + )))->reflectClass('RoaveTestAsset\\ClassWithPropertiesBeingRemoved'), + (new DefaultReflector(new SingleFileSourceLocator( __DIR__ . '/../../../../asset/api/new/ClassWithPropertiesBeingRemoved.php', $locator - )))->reflect('RoaveTestAsset\\ClassWithPropertiesBeingRemoved'), + )))->reflectClass('RoaveTestAsset\\ClassWithPropertiesBeingRemoved'), [ '[BC] REMOVED: Property RoaveTestAsset\ClassWithPropertiesBeingRemoved#$removedPublicProperty was removed', '[BC] REMOVED: Property RoaveTestAsset\ClassWithPropertiesBeingRemoved#$nameCaseChangePublicProperty was removed', @@ -64,7 +64,7 @@ public function classesToBeTested(): array ], ], 'Decreased property visibility / removed properties in a final class - only `public` properties affect BC' => [ - (new ClassReflector(new StringSourceLocator( + (new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('FinalClass'), - (new ClassReflector(new StringSourceLocator( + )))->reflectClass('FinalClass'), + (new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('FinalClass'), + )))->reflectClass('FinalClass'), [ '[BC] REMOVED: Property FinalClass#$decreasedVisibilityPublicProperty was removed', '[BC] REMOVED: Property FinalClass#$removedPublicProperty was removed', ], ], 'removed trait use from class' => [ - (new ClassReflector(new StringSourceLocator( + (new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('TestClass'), - (new ClassReflector(new StringSourceLocator( + )))->reflectClass('TestClass'), + (new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('TestClass'), + )))->reflectClass('TestClass'), ['[BC] REMOVED: Property TestClass#$testProperty was removed'], ], 'removed property from trait' => [ - (new ClassReflector(new StringSourceLocator( + (new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('TestClass'), - (new ClassReflector(new StringSourceLocator( + )))->reflectClass('TestClass'), + (new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('TestClass'), + )))->reflectClass('TestClass'), ['[BC] REMOVED: Property TestClass#$testProperty was removed'], ], ]; diff --git a/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantValueChangedTest.php b/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantValueChangedTest.php index 37373e4d..672f9680 100644 --- a/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantValueChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantValueChangedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassConstantBased\ClassConstantValueChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClassConstant; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -100,10 +100,10 @@ class TheClass { $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'publicNullToNull' => [], diff --git a/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantVisibilityReducedTest.php b/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantVisibilityReducedTest.php index a2bc885f..4390be42 100644 --- a/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantVisibilityReducedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantVisibilityReducedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassConstantBased\ClassConstantVisibilityReduced; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClassConstant; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\TypeRestriction; use function array_map; @@ -90,10 +90,10 @@ class TheClass { $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ExcludeInternalFunctionTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ExcludeInternalFunctionTest.php index f0ff6eca..6844a66f 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ExcludeInternalFunctionTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ExcludeInternalFunctionTest.php @@ -10,8 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ExcludeInternalFunction; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\FunctionBased; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; /** @covers \Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ExcludeInternalFunction */ @@ -28,8 +27,8 @@ function a() {} , (new BetterReflection())->astLocator() ); - $function = (new FunctionReflector($source, new ClassReflector($source))) - ->reflect('a'); + $function = (new DefaultReflector($source)) + ->reflectFunction('a'); $check = $this->createMock(FunctionBased::class); $check->expects(self::once()) @@ -55,8 +54,8 @@ function a() {} , (new BetterReflection())->astLocator() ); - $function = (new FunctionReflector($source, new ClassReflector($source))) - ->reflect('a'); + $function = (new DefaultReflector($source)) + ->reflectFunction('a'); $check = $this->createMock(FunctionBased::class); $check->expects(self::never()) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php index 847d79e2..ecdc8d74 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php @@ -9,8 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\FunctionBecameInternal; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -79,10 +78,8 @@ function d() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'a' => [], @@ -97,8 +94,8 @@ function d() {} /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ static function (string $function, array $errorMessages) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php index ac3eae36..1221ac1f 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php @@ -9,8 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ParameterByReferenceChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; use function array_map; @@ -98,10 +97,8 @@ function changed2(& $a) {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'valueToReference' => [ @@ -126,8 +123,8 @@ function changed2(& $a) {} /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, @@ -137,16 +134,16 @@ static function (string $function, array $errorMessages) use ($fromReflector, $t ), [ 'N1\C::changed1' => [ - $fromClassReflector->reflect('N1\C')->getMethod('changed1'), - $toClassReflector->reflect('N1\C')->getMethod('changed1'), + $fromReflector->reflectClass('N1\C')->getMethod('changed1'), + $toReflector->reflectClass('N1\C')->getMethod('changed1'), [ '[BC] CHANGED: The parameter $a of N1\C::changed1() changed from by-value to by-reference', ], ], 'N1\C#changed2' => [ - $fromClassReflector->reflect('N1\C')->getMethod('changed2'), - $toClassReflector->reflect('N1\C')->getMethod('changed2'), + $fromReflector->reflectClass('N1\C')->getMethod('changed2'), + $toReflector->reflectClass('N1\C')->getMethod('changed2'), [ '[BC] CHANGED: The parameter $a of N1\C#changed2() changed from by-value to by-reference', ], diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php index c5bd97ae..2fb125b0 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php @@ -9,8 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ParameterDefaultValueChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; use function array_map; @@ -96,10 +95,8 @@ function changed2($a = 2) {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'changed' => [ @@ -126,8 +123,8 @@ function changed2($a = 2) {} /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, @@ -137,15 +134,15 @@ static function (string $function, array $errorMessages) use ($fromReflector, $t ), [ 'C::changed1' => [ - $fromClassReflector->reflect('C')->getMethod('changed1'), - $toClassReflector->reflect('C')->getMethod('changed1'), + $fromReflector->reflectClass('C')->getMethod('changed1'), + $toReflector->reflectClass('C')->getMethod('changed1'), [ '[BC] CHANGED: Default parameter value for parameter $a of C::changed1() changed from 1 to 2', ], ], 'C#changed2' => [ - $fromClassReflector->reflect('C')->getMethod('changed2'), - $toClassReflector->reflect('C')->getMethod('changed2'), + $fromReflector->reflectClass('C')->getMethod('changed2'), + $toReflector->reflectClass('C')->getMethod('changed2'), [ '[BC] CHANGED: Default parameter value for parameter $a of C#changed2() changed from 1 to 2', ], diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php index 21dcfe50..c9de0ff1 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php @@ -9,8 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ParameterTypeChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; use function array_map; @@ -125,10 +124,8 @@ function changed2(int $a, int $b) {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'changed' => [ @@ -159,8 +156,8 @@ function changed2(int $a, int $b) {} /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, @@ -170,8 +167,8 @@ static function (string $function, array $errorMessages) use ($fromReflector, $t ), [ 'N4\C::changed1' => [ - $fromClassReflector->reflect('N4\C')->getMethod('changed1'), - $toClassReflector->reflect('N4\C')->getMethod('changed1'), + $fromReflector->reflectClass('N4\C')->getMethod('changed1'), + $toReflector->reflectClass('N4\C')->getMethod('changed1'), [ '[BC] CHANGED: The parameter $a of N4\C::changed1() changed from no type to int', '[BC] CHANGED: The parameter $b of N4\C::changed1() changed from no type to int', @@ -179,8 +176,8 @@ static function (string $function, array $errorMessages) use ($fromReflector, $t ], ], 'N4\C#changed2' => [ - $fromClassReflector->reflect('N4\C')->getMethod('changed2'), - $toClassReflector->reflect('N4\C')->getMethod('changed2'), + $fromReflector->reflectClass('N4\C')->getMethod('changed2'), + $toReflector->reflectClass('N4\C')->getMethod('changed2'), [ '[BC] CHANGED: The parameter $a of N4\C#changed2() changed from no type to int', '[BC] CHANGED: The parameter $b of N4\C#changed2() changed from no type to int', diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php index d9bd7f1a..5cfe6a4d 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php @@ -10,8 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; use function array_map; @@ -126,10 +125,8 @@ function changed2(int $a, int $b) {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'changed' => [ @@ -160,8 +157,8 @@ function changed2(int $a, int $b) {} /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, @@ -171,8 +168,8 @@ function (string $function, array $errorMessages) use ($fromReflector, $toReflec ), [ 'N4\C::changed1' => [ - $fromClassReflector->reflect('N4\C')->getMethod('changed1'), - $toClassReflector->reflect('N4\C')->getMethod('changed1'), + $fromReflector->reflectClass('N4\C')->getMethod('changed1'), + $toReflector->reflectClass('N4\C')->getMethod('changed1'), [ '[BC] CHANGED: The parameter $a of N4\C::changed1() changed from no type to a non-contravariant int', '[BC] CHANGED: The parameter $b of N4\C::changed1() changed from no type to a non-contravariant int', @@ -180,8 +177,8 @@ function (string $function, array $errorMessages) use ($fromReflector, $toReflec ], ], 'N4\C#changed2' => [ - $fromClassReflector->reflect('N4\C')->getMethod('changed2'), - $toClassReflector->reflect('N4\C')->getMethod('changed2'), + $fromReflector->reflectClass('N4\C')->getMethod('changed2'), + $toReflector->reflectClass('N4\C')->getMethod('changed2'), [ '[BC] CHANGED: The parameter $a of N4\C#changed2() changed from no type to a non-contravariant int', '[BC] CHANGED: The parameter $b of N4\C#changed2() changed from no type to a non-contravariant int', diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php index 496b9abd..b3d556c1 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php @@ -9,8 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\RequiredParameterAmountIncreased; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; use function array_map; @@ -106,10 +105,8 @@ function changed2($a, $b, $c, $d) {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'parametersIncreased' => ['[BC] CHANGED: The number of required arguments for parametersIncreased() increased from 3 to 4'], @@ -131,8 +128,8 @@ function changed2($a, $b, $c, $d) {} /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, @@ -142,15 +139,15 @@ function (string $function, array $errorMessages) use ($fromReflector, $toReflec ), [ 'N1\C::changed1' => [ - $fromClassReflector->reflect('N1\C')->getMethod('changed1'), - $toClassReflector->reflect('N1\C')->getMethod('changed1'), + $fromReflector->reflectClass('N1\C')->getMethod('changed1'), + $toReflector->reflectClass('N1\C')->getMethod('changed1'), [ '[BC] CHANGED: The number of required arguments for N1\C::changed1() increased from 3 to 4', ], ], 'N1\C#changed2' => [ - $fromClassReflector->reflect('N1\C')->getMethod('changed2'), - $toClassReflector->reflect('N1\C')->getMethod('changed2'), + $fromReflector->reflectClass('N1\C')->getMethod('changed2'), + $toReflector->reflectClass('N1\C')->getMethod('changed2'), [ '[BC] CHANGED: The number of required arguments for N1\C#changed2() increased from 3 to 4', ], diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php index 6e4d745d..c5e67d12 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php @@ -9,8 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ReturnTypeByReferenceChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; use function array_map; @@ -94,10 +93,8 @@ function & changed2() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'valueToReference' => [ @@ -115,10 +112,10 @@ function & changed2() {} array_keys($functions), array_map( /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { + static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, @@ -128,13 +125,13 @@ function (string $function, array $errorMessages) use ($fromReflector, $toReflec ), [ 'N1\C::changed1' => [ - $fromClassReflector->reflect('N1\C')->getMethod('changed1'), - $toClassReflector->reflect('N1\C')->getMethod('changed1'), + $fromReflector->reflectClass('N1\C')->getMethod('changed1'), + $toReflector->reflectClass('N1\C')->getMethod('changed1'), ['[BC] CHANGED: The return value of N1\C::changed1() changed from by-value to by-reference'], ], 'N1\C#changed2' => [ - $fromClassReflector->reflect('N1\C')->getMethod('changed2'), - $toClassReflector->reflect('N1\C')->getMethod('changed2'), + $fromReflector->reflectClass('N1\C')->getMethod('changed2'), + $toReflector->reflectClass('N1\C')->getMethod('changed2'), ['[BC] CHANGED: The return value of N1\C#changed2() changed from by-value to by-reference'], ], ] diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php index 4bbb9169..2c3c6a89 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php @@ -9,8 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ReturnTypeChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; use function array_map; @@ -124,10 +123,8 @@ function changed2() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'changed' => [ @@ -155,8 +152,8 @@ function changed2() {} /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, @@ -166,13 +163,13 @@ function (string $function, array $errorMessages) use ($fromReflector, $toReflec ), [ 'N4\C::changed1' => [ - $fromClassReflector->reflect('N4\C')->getMethod('changed1'), - $toClassReflector->reflect('N4\C')->getMethod('changed1'), + $fromReflector->reflectClass('N4\C')->getMethod('changed1'), + $toReflector->reflectClass('N4\C')->getMethod('changed1'), ['[BC] CHANGED: The return type of N4\C::changed1() changed from int to no type'], ], 'N4\C#changed2' => [ - $fromClassReflector->reflect('N4\C')->getMethod('changed2'), - $toClassReflector->reflect('N4\C')->getMethod('changed2'), + $fromReflector->reflectClass('N4\C')->getMethod('changed2'), + $toReflector->reflectClass('N4\C')->getMethod('changed2'), ['[BC] CHANGED: The return type of N4\C#changed2() changed from int to no type'], ], ] diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php index 79036dc6..49b253ef 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php @@ -10,8 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; use function array_map; @@ -125,10 +124,8 @@ function changed2() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromReflector = new FunctionReflector($fromLocator, $fromClassReflector); - $toReflector = new FunctionReflector($toLocator, $toClassReflector); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'changed' => [ @@ -154,10 +151,10 @@ function changed2() {} array_keys($functions), array_map( /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { + static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { return [ - $fromReflector->reflect($function), - $toReflector->reflect($function), + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), $errorMessages, ]; }, @@ -167,13 +164,13 @@ function (string $function, array $errorMessages) use ($fromReflector, $toReflec ), [ 'N4\C::changed1' => [ - $fromClassReflector->reflect('N4\C')->getMethod('changed1'), - $toClassReflector->reflect('N4\C')->getMethod('changed1'), + $fromReflector->reflectClass('N4\C')->getMethod('changed1'), + $toReflector->reflectClass('N4\C')->getMethod('changed1'), ['[BC] CHANGED: The return type of N4\C::changed1() changed from int to the non-covariant no type'], ], 'N4\C#changed2' => [ - $fromClassReflector->reflect('N4\C')->getMethod('changed2'), - $toClassReflector->reflect('N4\C')->getMethod('changed2'), + $fromReflector->reflectClass('N4\C')->getMethod('changed2'), + $toReflector->reflectClass('N4\C')->getMethod('changed2'), ['[BC] CHANGED: The return type of N4\C#changed2() changed from int to the non-covariant no type'], ], ] diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/AncestorRemovedTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/AncestorRemovedTest.php index a5a329f2..5a3da30d 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/AncestorRemovedTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/AncestorRemovedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\AncestorRemoved; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -49,7 +49,7 @@ public function testDiffs( public function interfacesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $interfaceName, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($interfaceName), - $toReflector->reflect($interfaceName), + $fromReflector->reflectClass($interfaceName), + $toReflector->reflectClass($interfaceName), $errors, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/ExcludeInternalInterfaceTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/ExcludeInternalInterfaceTest.php index f03e8f8c..a01058a3 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/ExcludeInternalInterfaceTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/ExcludeInternalInterfaceTest.php @@ -10,7 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\ExcludeInternalInterface; use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\InterfaceBased; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; /** @covers \Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\ExcludeInternalInterface */ @@ -19,7 +19,7 @@ final class ExcludeInternalInterfaceTest extends TestCase public function testNormalInterfacesAreNotExcluded(): void { $locator = (new BetterReflection())->astLocator(); - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('ANormalInterface'); + $reflection = $reflector->reflectClass('ANormalInterface'); $check = $this->createMock(InterfaceBased::class); $check->expects(self::once()) @@ -45,7 +45,7 @@ interface ANormalInterface {} public function testInternalInterfacesAreExcluded(): void { $locator = (new BetterReflection())->astLocator(); - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('AnInternalInterface'); + $reflection = $reflector->reflectClass('AnInternalInterface'); $check = $this->createMock(InterfaceBased::class); $check->expects(self::never())->method('__invoke'); diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameClassTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameClassTest.php index 40a687e5..91319f5f 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameClassTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameClassTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\InterfaceBecameClass; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -46,7 +46,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $className, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($className), - $toReflector->reflect($className), + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), $errors, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameTraitTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameTraitTest.php index 2582c832..ce18c5d2 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameTraitTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameTraitTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\InterfaceBecameTrait; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -46,7 +46,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $className, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($className), - $toReflector->reflect($className), + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), $errors, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/MethodAddedTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/MethodAddedTest.php index a50d4e79..39ae7912 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/MethodAddedTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/MethodAddedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\MethodAdded; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -100,8 +100,8 @@ public function c() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); $properties = [ 'A' => ['[BC] ADDED: Method added() was added to interface A'], @@ -123,8 +123,8 @@ public function c() {} static function (string $className, array $errorMessages) use ($fromClassReflector, $toClassReflector ): array { return [ - $fromClassReflector->reflect($className), - $toClassReflector->reflect($className), + $fromClassReflector->reflectClass($className), + $toClassReflector->reflectClass($className), $errorMessages, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/ExcludeInternalMethodTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/ExcludeInternalMethodTest.php index 2421c20c..a8a991da 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/ExcludeInternalMethodTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/ExcludeInternalMethodTest.php @@ -10,7 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\MethodBased\ExcludeInternalMethod; use Roave\BackwardCompatibility\DetectChanges\BCBreak\MethodBased\MethodBased; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; /** @covers \Roave\BackwardCompatibility\DetectChanges\BCBreak\MethodBased\ExcludeInternalMethod */ @@ -18,7 +18,7 @@ final class ExcludeInternalMethodTest extends TestCase { public function testNormalMethodsAreNotExcluded(): void { - $method = (new ClassReflector(new StringSourceLocator( + $method = (new DefaultReflector(new StringSourceLocator( <<<'PHP' astLocator() ))) - ->reflect('A') + ->reflectClass('A') ->getMethod('method'); $check = $this->createMock(MethodBased::class); @@ -46,7 +46,7 @@ function method() {} public function testInternalFunctionsAreExcluded(): void { - $method = (new ClassReflector(new StringSourceLocator( + $method = (new DefaultReflector(new StringSourceLocator( <<<'PHP' astLocator() ))) - ->reflect('A') + ->reflectClass('A') ->getMethod('method'); $check = $this->createMock(MethodBased::class); diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/MethodBecameFinalTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/MethodBecameFinalTest.php index 7ebafa3a..c500a631 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/MethodBecameFinalTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/MethodBecameFinalTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\MethodBased\MethodBecameFinal; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionMethod; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -100,10 +100,10 @@ private final function privateFinalToFinal() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'publicOverrideableToFinal' => ['[BC] CHANGED: Method publicOverrideableToFinal() of class TheClass became final'], diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/MethodConcretenessChangedTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/MethodConcretenessChangedTest.php index 148c2485..79d31515 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/MethodConcretenessChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/MethodConcretenessChangedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\MethodBased\MethodConcretenessChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionMethod; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -100,10 +100,10 @@ private abstract function privateAbstractToAbstract() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'publicConcreteToAbstract' => ['[BC] CHANGED: Method publicConcreteToAbstract() of class TheClass changed from concrete to abstract'], diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/MethodScopeChangedTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/MethodScopeChangedTest.php index 17203cc7..e622d456 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/MethodScopeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/MethodScopeChangedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\MethodBased\MethodScopeChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionMethod; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -100,10 +100,10 @@ private static function privateStaticToStatic() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'publicInstanceToStatic' => ['[BC] CHANGED: Method publicInstanceToStatic() of class TheClass changed scope from instance to static'], diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/MethodVisibilityReducedTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/MethodVisibilityReducedTest.php index ca4534a2..a2298a82 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/MethodVisibilityReducedTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/MethodVisibilityReducedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\MethodBased\MethodVisibilityReduced; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionMethod; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -90,10 +90,10 @@ public function privateIncreasedToPublic() {} $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/ExcludeInternalPropertyTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/ExcludeInternalPropertyTest.php index 541d924e..6901a4ab 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/ExcludeInternalPropertyTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/ExcludeInternalPropertyTest.php @@ -10,7 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\ExcludeInternalProperty; use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyBased; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; /** @covers \Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\ExcludeInternalProperty */ @@ -18,7 +18,7 @@ final class ExcludeInternalPropertyTest extends TestCase { public function testNormalPropertiesAreNotExcluded(): void { - $property = (new ClassReflector(new StringSourceLocator( + $property = (new DefaultReflector(new StringSourceLocator( <<<'PHP' astLocator() ))) - ->reflect('A') + ->reflectClass('A') ->getProperty('property'); self::assertNotNull($property); @@ -48,7 +48,7 @@ class A { public function testInternalPropertiesAreExcluded(): void { - $property = (new ClassReflector(new StringSourceLocator( + $property = (new DefaultReflector(new StringSourceLocator( <<<'PHP' astLocator() ))) - ->reflect('A') + ->reflectClass('A') ->getProperty('property'); self::assertNotNull($property); diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyBecameInternalTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyBecameInternalTest.php index 3ab6b466..37e79b9c 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyBecameInternalTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyBecameInternalTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyBecameInternal; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\TypeRestriction; @@ -85,10 +85,10 @@ class TheClass { $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'nonInternal' => [], diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDefaultValueChangedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDefaultValueChangedTest.php index d1ececa4..bf65aabd 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDefaultValueChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDefaultValueChangedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyDefaultValueChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\TypeRestriction; @@ -113,10 +113,10 @@ class TheClass { $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'publicNothingToNothing' => [], diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChangedTest.php index a0c6b908..3d0d0677 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChangedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyDocumentedTypeChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\TypeRestriction; @@ -202,10 +202,10 @@ class TheClass { $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'publicNoDocblockToNoDocblock' => [], diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyScopeChangedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyScopeChangedTest.php index 9abe13bb..b9a80346 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyScopeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyScopeChangedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyScopeChanged; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\TypeRestriction; @@ -101,10 +101,10 @@ class TheClass { $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'publicInstanceToStatic' => ['[BC] CHANGED: Property $publicInstanceToStatic of TheClass changed scope from instance to static'], diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyVisibilityReducedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyVisibilityReducedTest.php index 92467484..76a49145 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyVisibilityReducedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyVisibilityReducedTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyVisibilityReduced; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use RoaveTest\BackwardCompatibility\TypeRestriction; @@ -91,10 +91,10 @@ class TheClass { $astLocator ); - $fromClassReflector = new ClassReflector($fromLocator); - $toClassReflector = new ClassReflector($toLocator); - $fromClass = $fromClassReflector->reflect('TheClass'); - $toClass = $toClassReflector->reflect('TheClass'); + $fromClassReflector = new DefaultReflector($fromLocator); + $toClassReflector = new DefaultReflector($toLocator); + $fromClass = $fromClassReflector->reflectClass('TheClass'); + $toClass = $toClassReflector->reflectClass('TheClass'); $properties = [ 'publicMaintainedPublic' => [], diff --git a/test/unit/DetectChanges/BCBreak/TraitBased/ExcludeInternalTraitTest.php b/test/unit/DetectChanges/BCBreak/TraitBased/ExcludeInternalTraitTest.php index 42a85e33..f4b66ef8 100644 --- a/test/unit/DetectChanges/BCBreak/TraitBased/ExcludeInternalTraitTest.php +++ b/test/unit/DetectChanges/BCBreak/TraitBased/ExcludeInternalTraitTest.php @@ -10,7 +10,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\TraitBased\ExcludeInternalTrait; use Roave\BackwardCompatibility\DetectChanges\BCBreak\TraitBased\TraitBased; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; /** @covers \Roave\BackwardCompatibility\DetectChanges\BCBreak\TraitBased\ExcludeInternalTrait */ @@ -19,7 +19,7 @@ final class ExcludeInternalTraitTest extends TestCase public function testNormalTraitsAreNotExcluded(): void { $locator = (new BetterReflection())->astLocator(); - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('ANormalTrait'); + $reflection = $reflector->reflectClass('ANormalTrait'); $check = $this->createMock(TraitBased::class); $check->expects(self::once()) @@ -45,7 +45,7 @@ trait ANormalTrait {} public function testInternalTraitsAreExcluded(): void { $locator = (new BetterReflection())->astLocator(); - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' reflect('AnInternalTrait'); + $reflection = $reflector->reflectClass('AnInternalTrait'); $check = $this->createMock(TraitBased::class); $check->expects(self::never())->method('__invoke'); diff --git a/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameClassTest.php b/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameClassTest.php index db5f2fc5..0fd0d601 100644 --- a/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameClassTest.php +++ b/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameClassTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\TraitBased\TraitBecameClass; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -49,7 +49,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $className, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($className), - $toReflector->reflect($className), + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), $errors, ]; }, diff --git a/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameInterfaceTest.php b/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameInterfaceTest.php index 4eb0bf00..bb90af1c 100644 --- a/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameInterfaceTest.php +++ b/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameInterfaceTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\TraitBased\TraitBecameInterface; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClass; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -49,7 +49,7 @@ public function testDiffs( public function classesToBeTested(): array { $locator = (new BetterReflection())->astLocator(); - $fromReflector = new ClassReflector(new StringSourceLocator( + $fromReflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' $errors https://github.com/vimeo/psalm/issues/2772 */ static function (string $className, array $errors) use ($fromReflector, $toReflector): array { return [ - $fromReflector->reflect($className), - $toReflector->reflect($className), + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), $errors, ]; }, diff --git a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php index 890454f5..bd303048 100644 --- a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php @@ -4,11 +4,14 @@ namespace RoaveTest\BackwardCompatibility\DetectChanges\Variance; +use PhpParser\Node\Identifier; +use PhpParser\Node\NullableType; use PHPUnit\Framework\TestCase; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; +use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionType; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_map; @@ -20,8 +23,8 @@ final class TypeIsContravariantTest extends TestCase * @dataProvider checkedTypes */ public function testContravariance( - ?ReflectionType $type, - ?ReflectionType $newType, + TypeWithReflectorScope $type, + TypeWithReflectorScope $newType, bool $expectedToBeContravariant ): void { self::assertSame( @@ -32,11 +35,11 @@ public function testContravariance( /** * @return array> - * @psalm-return array + * @psalm-return array */ public function checkedTypes(): array { - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' astLocator() )); - return [ + $types = [ 'no type to no type is contravariant with itself' => [ null, null, @@ -62,161 +65,170 @@ class CClass extends BClass {} ], 'no type to void type is not contravariant' => [ null, - ReflectionType::createFromTypeAndReflector('void', false, $reflector), + ReflectionType::createFromNode(new Identifier('void')), false, ], 'void type to no type is contravariant' => [ - ReflectionType::createFromTypeAndReflector('void', false, $reflector), + ReflectionType::createFromNode(new Identifier('void')), null, true, ], 'void type to scalar type is contravariant' => [ - ReflectionType::createFromTypeAndReflector('void', false, $reflector), - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('void')), + ReflectionType::createFromNode(new Identifier('string')), true, ], 'void type to class type is contravariant' => [ - ReflectionType::createFromTypeAndReflector('void', false, $reflector), - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('void')), + ReflectionType::createFromNode(new Identifier('AClass')), true, ], 'scalar type to no type is contravariant' => [ - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), null, true, ], 'no type to scalar type is not contravariant' => [ null, - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), false, ], 'class type to no type is contravariant' => [ - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('AClass')), null, true, ], 'no type to class type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('AClass')), null, true, ], 'iterable to array is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('array', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('array')), false, ], 'array to iterable is contravariant' => [ - ReflectionType::createFromTypeAndReflector('array', false, $reflector), - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), + ReflectionType::createFromNode(new Identifier('array')), + ReflectionType::createFromNode(new Identifier('iterable')), true, ], 'iterable to non-iterable class type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), false, ], 'iterable to iterable class type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('Iterator', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('Iterator')), false, ], 'non-iterable class to iterable type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), false, ], 'iterable class type to iterable is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('Iterator', false, $reflector), - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), + ReflectionType::createFromNode(new Identifier('Iterator')), + ReflectionType::createFromNode(new Identifier('iterable')), false, ], 'object to class type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('object', false, $reflector), - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('object')), + ReflectionType::createFromNode(new Identifier('AClass')), false, ], 'class type to object is contravariant' => [ - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), - ReflectionType::createFromTypeAndReflector('object', false, $reflector), + ReflectionType::createFromNode(new Identifier('AClass')), + ReflectionType::createFromNode(new Identifier('object')), true, ], 'class type to scalar type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('AClass')), + ReflectionType::createFromNode(new Identifier('string')), false, ], 'scalar type to class type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('string', false, $reflector), - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), + ReflectionType::createFromNode(new Identifier('AClass')), false, ], 'scalar type (string) to different scalar type (int) is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('string', false, $reflector), - ReflectionType::createFromTypeAndReflector('int', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), + ReflectionType::createFromNode(new Identifier('int')), false, ], 'scalar type (int) to different scalar type (float) is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('int', false, $reflector), - ReflectionType::createFromTypeAndReflector('float', false, $reflector), + ReflectionType::createFromNode(new Identifier('int')), + ReflectionType::createFromNode(new Identifier('float')), false, ], 'object type to scalar type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('object', false, $reflector), - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('object')), + ReflectionType::createFromNode(new Identifier('string')), false, ], 'scalar type to object type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('string', false, $reflector), - ReflectionType::createFromTypeAndReflector('object', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), + ReflectionType::createFromNode(new Identifier('object')), false, ], 'class to superclass is contravariant' => [ - ReflectionType::createFromTypeAndReflector('BClass', false, $reflector), - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('BClass')), + ReflectionType::createFromNode(new Identifier('AClass')), true, ], 'class to subclass is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('BClass', false, $reflector), - ReflectionType::createFromTypeAndReflector('CClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('BClass')), + ReflectionType::createFromNode(new Identifier('CClass')), false, ], 'class to implemented interface is contravariant' => [ - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), - ReflectionType::createFromTypeAndReflector('AnInterface', false, $reflector), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + ReflectionType::createFromNode(new Identifier('AnInterface')), true, ], 'class to not implemented interface is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), - ReflectionType::createFromTypeAndReflector('Traversable', false, $reflector), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + ReflectionType::createFromNode(new Identifier('Traversable')), false, ], 'interface to parent interface is contravariant' => [ - ReflectionType::createFromTypeAndReflector('Iterator', false, $reflector), - ReflectionType::createFromTypeAndReflector('Traversable', false, $reflector), + ReflectionType::createFromNode(new Identifier('Iterator')), + ReflectionType::createFromNode(new Identifier('Traversable')), true, ], 'interface to child interface is contravariant' => [ - ReflectionType::createFromTypeAndReflector('Traversable', false, $reflector), - ReflectionType::createFromTypeAndReflector('Iterator', false, $reflector), + ReflectionType::createFromNode(new Identifier('Traversable')), + ReflectionType::createFromNode(new Identifier('Iterator')), false, ], ]; + + return array_map( + static fn (array $types): array => [ + new TypeWithReflectorScope($types[0], $reflector), + new TypeWithReflectorScope($types[1], $reflector), + $types[2] + ], + $types + ); } /** * @dataProvider existingTypes */ - public function testContravarianceConsidersSameTypeAlwaysContravariant(?ReflectionType $type): void + public function testContravarianceConsidersSameTypeAlwaysContravariant(TypeWithReflectorScope $type): void { self::assertTrue( (new TypeIsContravariant())($type, $type) ); } - /** @return (ReflectionType|null)[][] */ + /** @return TypeWithReflectorScope[][] */ public function existingTypes(): array { - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' astLocator() )); - $nullable = ReflectionType::createFromTypeAndReflector($type, true, $reflector); - $notNullable = ReflectionType::createFromTypeAndReflector($type, false, $reflector); + $nullable = new TypeWithReflectorScope(ReflectionType::createFromNode(new NullableType(new Identifier($type))), $reflector); + $notNullable = new TypeWithReflectorScope(ReflectionType::createFromNode(new Identifier($type)), $reflector); $isContravariant = new TypeIsContravariant(); diff --git a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php index d7ca55e7..fe799ccc 100644 --- a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php @@ -4,11 +4,14 @@ namespace RoaveTest\BackwardCompatibility\DetectChanges\Variance; +use PhpParser\Node\Identifier; +use PhpParser\Node\NullableType; use PHPUnit\Framework\TestCase; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; +use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionType; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_map; @@ -20,8 +23,8 @@ final class TypeIsCovariantTest extends TestCase * @dataProvider checkedTypes */ public function testCovariance( - ?ReflectionType $type, - ?ReflectionType $newType, + TypeWithReflectorScope $type, + TypeWithReflectorScope $newType, bool $expectedToBeContravariant ): void { self::assertSame( @@ -32,11 +35,11 @@ public function testCovariance( /** * @return array> - * @psalm-return array + * @psalm-return array */ public function checkedTypes(): array { - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' astLocator() )); - return [ + $types = [ 'no type to void type is covariant' => [ null, - ReflectionType::createFromTypeAndReflector('void', false, $reflector), + ReflectionType::createFromNode(new Identifier('void')), true, ], 'void type to no type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('void', false, $reflector), + ReflectionType::createFromNode(new Identifier('void')), null, false, ], 'void type to scalar type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('void', false, $reflector), - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('void')), + ReflectionType::createFromNode(new Identifier('string')), false, ], 'void type to class type is covariant' => [ - ReflectionType::createFromTypeAndReflector('void', false, $reflector), - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('void')), + ReflectionType::createFromNode(new Identifier('AClass')), false, ], 'scalar type to no type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), null, false, ], 'no type to scalar type is covariant' => [ null, - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), true, ], 'class type to no type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('AClass')), null, false, ], 'no type to class type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('AClass')), null, false, ], 'iterable to array is covariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('array', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('array')), true, ], 'iterable to scalar is not covariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('int', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('int')), false, ], 'scalar to iterable is not covariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('int', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('int')), false, ], 'array to iterable is not covariant' => [ - ReflectionType::createFromTypeAndReflector('array', false, $reflector), - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), + ReflectionType::createFromNode(new Identifier('array')), + ReflectionType::createFromNode(new Identifier('iterable')), false, ], 'iterable to non-iterable class type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), false, ], 'iterable to iterable class type is covariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('Iterator', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('Iterator')), true, ], 'non-iterable class to iterable type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), + ReflectionType::createFromNode(new Identifier('iterable')), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), false, ], 'iterable class type to iterable is not covariant' => [ - ReflectionType::createFromTypeAndReflector('Iterator', false, $reflector), - ReflectionType::createFromTypeAndReflector('iterable', false, $reflector), + ReflectionType::createFromNode(new Identifier('Iterator')), + ReflectionType::createFromNode(new Identifier('iterable')), false, ], 'object to class type is covariant' => [ - ReflectionType::createFromTypeAndReflector('object', false, $reflector), - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('object')), + ReflectionType::createFromNode(new Identifier('AClass')), true, ], 'class type to object is not covariant' => [ - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), - ReflectionType::createFromTypeAndReflector('object', false, $reflector), + ReflectionType::createFromNode(new Identifier('AClass')), + ReflectionType::createFromNode(new Identifier('object')), false, ], 'class type to scalar type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('AClass')), + ReflectionType::createFromNode(new Identifier('string')), false, ], 'scalar type to class type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('string', false, $reflector), - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), + ReflectionType::createFromNode(new Identifier('AClass')), false, ], 'scalar type (string) to different scalar type (int) is not covariant' => [ - ReflectionType::createFromTypeAndReflector('string', false, $reflector), - ReflectionType::createFromTypeAndReflector('int', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), + ReflectionType::createFromNode(new Identifier('int')), false, ], 'scalar type (int) to different scalar type (float) is not covariant' => [ - ReflectionType::createFromTypeAndReflector('int', false, $reflector), - ReflectionType::createFromTypeAndReflector('float', false, $reflector), + ReflectionType::createFromNode(new Identifier('int')), + ReflectionType::createFromNode(new Identifier('float')), false, ], 'object type to scalar type is not contravariant' => [ - ReflectionType::createFromTypeAndReflector('object', false, $reflector), - ReflectionType::createFromTypeAndReflector('string', false, $reflector), + ReflectionType::createFromNode(new Identifier('object')), + ReflectionType::createFromNode(new Identifier('string')), false, ], 'scalar type to object type is not covariant' => [ - ReflectionType::createFromTypeAndReflector('string', false, $reflector), - ReflectionType::createFromTypeAndReflector('object', false, $reflector), + ReflectionType::createFromNode(new Identifier('string')), + ReflectionType::createFromNode(new Identifier('object')), false, ], 'class to superclass is not covariant' => [ - ReflectionType::createFromTypeAndReflector('BClass', false, $reflector), - ReflectionType::createFromTypeAndReflector('AClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('BClass')), + ReflectionType::createFromNode(new Identifier('AClass')), false, ], 'class to subclass is covariant' => [ - ReflectionType::createFromTypeAndReflector('BClass', false, $reflector), - ReflectionType::createFromTypeAndReflector('CClass', false, $reflector), + ReflectionType::createFromNode(new Identifier('BClass')), + ReflectionType::createFromNode(new Identifier('CClass')), true, ], 'class to implemented interface is not covariant' => [ - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), - ReflectionType::createFromTypeAndReflector('AnInterface', false, $reflector), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + ReflectionType::createFromNode(new Identifier('AnInterface')), false, ], 'interface to implementing class is covariant' => [ - ReflectionType::createFromTypeAndReflector('AnInterface', false, $reflector), - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), + ReflectionType::createFromNode(new Identifier('AnInterface')), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), true, ], 'class to not implemented interface is not covariant' => [ - ReflectionType::createFromTypeAndReflector('AnotherClassWithMultipleInterfaces', false, $reflector), - ReflectionType::createFromTypeAndReflector('Traversable', false, $reflector), + ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + ReflectionType::createFromNode(new Identifier('Traversable')), false, ], 'interface to parent interface is not covariant' => [ - ReflectionType::createFromTypeAndReflector('Iterator', false, $reflector), - ReflectionType::createFromTypeAndReflector('Traversable', false, $reflector), + ReflectionType::createFromNode(new Identifier('Iterator')), + ReflectionType::createFromNode(new Identifier('Traversable')), false, ], 'interface to child interface is covariant' => [ - ReflectionType::createFromTypeAndReflector('Traversable', false, $reflector), - ReflectionType::createFromTypeAndReflector('Iterator', false, $reflector), + ReflectionType::createFromNode(new Identifier('Traversable')), + ReflectionType::createFromNode(new Identifier('Iterator')), true, ], ]; + + return array_map( + static fn (array $types): array => [ + new TypeWithReflectorScope($types[0], $reflector), + new TypeWithReflectorScope($types[1], $reflector), + $types[2] + ], + $types + ); } /** * @dataProvider existingTypes */ - public function testCovarianceConsidersSameTypeAlwaysCovariant(?ReflectionType $type): void + public function testCovarianceConsidersSameTypeAlwaysCovariant(TypeWithReflectorScope $type): void { self::assertTrue( (new TypeIsCovariant())($type, $type) ); } - /** @return (ReflectionType|null)[][] */ + /** @return TypeWithReflectorScope[][] */ public function existingTypes(): array { - $reflector = new ClassReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' astLocator() )); - $nullable = ReflectionType::createFromTypeAndReflector($type, true, $reflector); - $notNullable = ReflectionType::createFromTypeAndReflector($type, false, $reflector); + $nullable = new TypeWithReflectorScope(ReflectionType::createFromNode(new NullableType(new Identifier($type))), $reflector); + $notNullable = new TypeWithReflectorScope(ReflectionType::createFromNode(new Identifier($type)), $reflector); $isCovariant = new TypeIsCovariant(); diff --git a/test/unit/Factory/ComposerInstallationReflectorFactoryTest.php b/test/unit/Factory/ComposerInstallationReflectorFactoryTest.php index e566dfbe..fa4fd00d 100644 --- a/test/unit/Factory/ComposerInstallationReflectorFactoryTest.php +++ b/test/unit/Factory/ComposerInstallationReflectorFactoryTest.php @@ -49,7 +49,7 @@ class Dummy {} $path, $this->createMock(SourceLocator::class) ) - ->reflect('Dummy') + ->reflectClass('Dummy') ->getDocComment() ); } diff --git a/test/unit/Formatter/ReflectionFunctionAbstractNameTest.php b/test/unit/Formatter/ReflectionFunctionAbstractNameTest.php index 7fb98057..7cefb9c6 100644 --- a/test/unit/Formatter/ReflectionFunctionAbstractNameTest.php +++ b/test/unit/Formatter/ReflectionFunctionAbstractNameTest.php @@ -8,8 +8,7 @@ use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; -use Roave\BetterReflection\Reflector\ClassReflector; -use Roave\BetterReflection\Reflector\FunctionReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; /** @@ -55,24 +54,23 @@ function e() {} (new BetterReflection())->astLocator() ); - $classReflector = new ClassReflector($locator); - $functionReflector = new FunctionReflector($locator, $classReflector); + $reflector = new DefaultReflector($locator); return [ 'a' => [ - $functionReflector->reflect('a'), + $reflector->reflectFunction('a'), 'a()', ], 'N1\b' => [ - $functionReflector->reflect('N1\b'), + $reflector->reflectFunction('N1\b'), 'N1\b()', ], 'N2\C::d' => [ - $classReflector->reflect('N2\C')->getMethod('d'), + $reflector->reflectClass('N2\C')->getMethod('d'), 'N2\C::d()', ], 'N2\C#e' => [ - $classReflector->reflect('N2\C')->getMethod('e'), + $reflector->reflectClass('N2\C')->getMethod('e'), 'N2\C#e()', ], ]; diff --git a/test/unit/Formatter/ReflectionPropertyNameTest.php b/test/unit/Formatter/ReflectionPropertyNameTest.php index 6c07472f..c094d43c 100644 --- a/test/unit/Formatter/ReflectionPropertyNameTest.php +++ b/test/unit/Formatter/ReflectionPropertyNameTest.php @@ -8,7 +8,7 @@ use Roave\BackwardCompatibility\Formatter\ReflectionPropertyName; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -75,22 +75,22 @@ class D { (new BetterReflection())->astLocator() ); - $classReflector = new ClassReflector($locator); + $classReflector = new DefaultReflector($locator); /** @var array $properties */ $properties = [ - 'A::$b' => $classReflector->reflect('A')->getProperty('b'), - 'A#$c' => $classReflector->reflect('A')->getProperty('c'), - 'TestTrait::$b' => $classReflector->reflect('TestTrait')->getProperty('b'), - 'TestTrait#$c' => $classReflector->reflect('TestTrait')->getProperty('c'), - 'B::$b' => $classReflector->reflect('B')->getProperty('b'), - 'B#$c' => $classReflector->reflect('B')->getProperty('c'), - 'B#$d' => $classReflector->reflect('B')->getProperty('d'), - 'C#$c' => $classReflector->reflect('C')->getProperty('c'), - 'D#$c' => $classReflector->reflect('D')->getProperty('c'), - 'A#$d' => $classReflector->reflect('E')->getProperty('d'), - 'N1\D::$e' => $classReflector->reflect('N1\D')->getProperty('e'), - 'N1\D#$f' => $classReflector->reflect('N1\D')->getProperty('f'), + 'A::$b' => $classReflector->reflectClass('A')->getProperty('b'), + 'A#$c' => $classReflector->reflectClass('A')->getProperty('c'), + 'TestTrait::$b' => $classReflector->reflectClass('TestTrait')->getProperty('b'), + 'TestTrait#$c' => $classReflector->reflectClass('TestTrait')->getProperty('c'), + 'B::$b' => $classReflector->reflectClass('B')->getProperty('b'), + 'B#$c' => $classReflector->reflectClass('B')->getProperty('c'), + 'B#$d' => $classReflector->reflectClass('B')->getProperty('d'), + 'C#$c' => $classReflector->reflectClass('C')->getProperty('c'), + 'D#$c' => $classReflector->reflectClass('D')->getProperty('c'), + 'A#$d' => $classReflector->reflectClass('E')->getProperty('d'), + 'N1\D::$e' => $classReflector->reflectClass('N1\D')->getProperty('e'), + 'N1\D#$f' => $classReflector->reflectClass('N1\D')->getProperty('f'), ]; return array_combine( diff --git a/test/unit/LocateSources/LocateSourcesViaComposerJsonTest.php b/test/unit/LocateSources/LocateSourcesViaComposerJsonTest.php index 548d5fe2..60bf83ef 100644 --- a/test/unit/LocateSources/LocateSourcesViaComposerJsonTest.php +++ b/test/unit/LocateSources/LocateSourcesViaComposerJsonTest.php @@ -7,7 +7,7 @@ use PHPUnit\Framework\TestCase; use Roave\BackwardCompatibility\LocateSources\LocateSourcesViaComposerJson; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; /** * @covers \Roave\BackwardCompatibility\LocateSources\LocateSourcesViaComposerJson @@ -25,14 +25,14 @@ protected function setUp(): void public function testCanLocateClassInMappendAutoloadDefinitions(): void { - $reflector = new ClassReflector( + $reflector = new DefaultReflector( ($this->locateSources)(__DIR__ . '/../../asset/located-sources/composer-definition-with-everything') ); self::assertSame( 'baz\\LocatedClass', $reflector - ->reflect('baz\\LocatedClass') + ->reflectClass('baz\\LocatedClass') ->getName() ); } diff --git a/test/unit/SourceLocator/StaticClassMapSourceLocatorTest.php b/test/unit/SourceLocator/StaticClassMapSourceLocatorTest.php index 30d726ec..a0488d41 100644 --- a/test/unit/SourceLocator/StaticClassMapSourceLocatorTest.php +++ b/test/unit/SourceLocator/StaticClassMapSourceLocatorTest.php @@ -82,6 +82,7 @@ public function testWillLocateThisClass(string $thisClassFilePath): void ->with($this->reflector, self::callback(static function (LocatedSource $source): bool { self::assertSame(Filesystem\read_file(__FILE__), $source->getSource()); self::assertSame(__FILE__, $source->getFileName()); + self::assertSame(self::class, $source->getName()); self::assertNull($source->getExtensionName()); return true; diff --git a/test/unit/StringReflectorFactory.php b/test/unit/StringReflectorFactory.php index 32c3107b..f1c062cc 100644 --- a/test/unit/StringReflectorFactory.php +++ b/test/unit/StringReflectorFactory.php @@ -5,7 +5,8 @@ namespace RoaveTest\BackwardCompatibility; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflector\ClassReflector; +use Roave\BetterReflection\Reflector\DefaultReflector; +use Roave\BetterReflection\Reflector\Reflector; use Roave\BetterReflection\SourceLocator\Exception\EmptyPhpSourceCode; use Roave\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber; use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator; @@ -18,12 +19,12 @@ final class StringReflectorFactory /** * @throws EmptyPhpSourceCode */ - public function __invoke(string $sourceCode): ClassReflector + public function __invoke(string $sourceCode): Reflector { $astLocator = (new BetterReflection())->astLocator(); $stubber = new ReflectionSourceStubber(); - return new ClassReflector( + return new DefaultReflector( new AggregateSourceLocator([ new PhpInternalSourceLocator($astLocator, $stubber), new EvaledCodeSourceLocator($astLocator, $stubber), From f6739c91e4acb0efea6beac6d3605d8502e489be Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 6 Nov 2021 02:50:01 +0100 Subject: [PATCH 02/13] Ensure `IteratorAggregate` is implemented exactly as it is in PHP 8.1 tentative types Ref: https://wiki.php.net/rfc/internal_method_return_types --- src/Changes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Changes.php b/src/Changes.php index f071250a..778ed6d4 100644 --- a/src/Changes.php +++ b/src/Changes.php @@ -78,7 +78,7 @@ public function mergeWith(self $other): self * * @return Traversable */ - public function getIterator(): iterable + public function getIterator(): Traversable { foreach ($this->bufferedChanges as $change) { yield $change; From d6fa8b0ee9fee0f16fe791a9222c572d58df0a79 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 6 Nov 2021 02:50:53 +0100 Subject: [PATCH 03/13] Applied automated CS fixes --- .../ParameterTypeContravarianceChanged.php | 11 ++++++----- .../FunctionBased/ReturnTypeCovarianceChanged.php | 10 ++++++---- src/DetectChanges/Variance/TypeIsContravariant.php | 3 +-- src/DetectChanges/Variance/TypeIsCovariant.php | 3 +-- src/DetectChanges/Variance/TypeWithReflectorScope.php | 2 -- .../FunctionBased/FunctionBecameInternalTest.php | 4 ++-- .../Variance/TypeIsContravariantTest.php | 2 +- .../DetectChanges/Variance/TypeIsCovariantTest.php | 2 +- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php index 68f7bda5..b958779f 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php @@ -53,10 +53,12 @@ private function compareParameter(ReflectionParameter $fromParameter, Reflection $toType = $toParameter->getType(); - if (($this->typeIsContravariant)( - new TypeWithReflectorScope($fromType, $this->extractReflector($fromParameter)), - new TypeWithReflectorScope($toType, $this->extractReflector($toParameter)), - )) { + if ( + ($this->typeIsContravariant)( + new TypeWithReflectorScope($fromType, $this->extractReflector($fromParameter)), + new TypeWithReflectorScope($toType, $this->extractReflector($toParameter)), + ) + ) { return Changes::empty(); } @@ -81,7 +83,6 @@ private function typeToString(?ReflectionType $type): string return $type->__toString(); } - /** @TODO may the gods of BC compliance be merciful on me */ private function extractReflector(ReflectionParameter $parameter): Reflector { diff --git a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php index 5147aa76..ad6abb24 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php @@ -38,10 +38,12 @@ public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFun $fromReturnType = $fromFunction->getReturnType(); $toReturnType = $toFunction->getReturnType(); - if (($this->typeIsCovariant)( - new TypeWithReflectorScope($fromReturnType, $this->extractReflector($fromFunction)), - new TypeWithReflectorScope($toReturnType, $this->extractReflector($toFunction)), - )) { + if ( + ($this->typeIsCovariant)( + new TypeWithReflectorScope($fromReturnType, $this->extractReflector($fromFunction)), + new TypeWithReflectorScope($toReturnType, $this->extractReflector($toFunction)), + ) + ) { return Changes::empty(); } diff --git a/src/DetectChanges/Variance/TypeIsContravariant.php b/src/DetectChanges/Variance/TypeIsContravariant.php index 7bbda1a0..76add1c6 100644 --- a/src/DetectChanges/Variance/TypeIsContravariant.php +++ b/src/DetectChanges/Variance/TypeIsContravariant.php @@ -7,7 +7,6 @@ use Psl\Iter; use Psl\Str; use Roave\BetterReflection\Reflection\ReflectionNamedType; -use Roave\BetterReflection\Reflection\ReflectionType; /** * This is a simplistic contravariant type check. A more appropriate approach would be to @@ -75,7 +74,7 @@ public function __invoke( } $typeReflectionClass = $originalType->originatingReflector->reflectClass($typeAsString); - $comparedTypeClass = $newType->originatingReflector->reflectClass($comparedTypeAsString); + $comparedTypeClass = $newType->originatingReflector->reflectClass($comparedTypeAsString); if ($comparedTypeClass->isInterface()) { return $typeReflectionClass->implementsInterface($comparedTypeAsString); diff --git a/src/DetectChanges/Variance/TypeIsCovariant.php b/src/DetectChanges/Variance/TypeIsCovariant.php index 90287065..c8cc29d2 100644 --- a/src/DetectChanges/Variance/TypeIsCovariant.php +++ b/src/DetectChanges/Variance/TypeIsCovariant.php @@ -22,8 +22,7 @@ final class TypeIsCovariant public function __invoke( TypeWithReflectorScope $originalType, TypeWithReflectorScope $newType - ): bool - { + ): bool { $type = $originalType->type; $comparedType = $newType->type; diff --git a/src/DetectChanges/Variance/TypeWithReflectorScope.php b/src/DetectChanges/Variance/TypeWithReflectorScope.php index 343cc6d6..6694deb1 100644 --- a/src/DetectChanges/Variance/TypeWithReflectorScope.php +++ b/src/DetectChanges/Variance/TypeWithReflectorScope.php @@ -6,7 +6,6 @@ use Roave\BetterReflection\Reflection\ReflectionIntersectionType; use Roave\BetterReflection\Reflection\ReflectionNamedType; -use Roave\BetterReflection\Reflection\ReflectionType; use Roave\BetterReflection\Reflection\ReflectionUnionType; use Roave\BetterReflection\Reflector\Reflector; @@ -17,7 +16,6 @@ * still respect variance rules. * * @psalm-immutable - * * @psalm-internal \Roave\BackwardCompatibility */ final class TypeWithReflectorScope diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php index ecdc8d74..877d4e85 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php @@ -78,8 +78,8 @@ function d() {} $astLocator ); - $fromReflector = new DefaultReflector($fromLocator); - $toReflector = new DefaultReflector($toLocator); + $fromReflector = new DefaultReflector($fromLocator); + $toReflector = new DefaultReflector($toLocator); $functions = [ 'a' => [], diff --git a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php index bd303048..2cbbb811 100644 --- a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php @@ -209,7 +209,7 @@ class CClass extends BClass {} static fn (array $types): array => [ new TypeWithReflectorScope($types[0], $reflector), new TypeWithReflectorScope($types[1], $reflector), - $types[2] + $types[2], ], $types ); diff --git a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php index fe799ccc..50f35c1c 100644 --- a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php @@ -220,7 +220,7 @@ class CClass extends BClass {} static fn (array $types): array => [ new TypeWithReflectorScope($types[0], $reflector), new TypeWithReflectorScope($types[1], $reflector), - $types[2] + $types[2], ], $types ); From 0cd7b62e3b29cd981dcdbaafd28ed08124655c5f Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 6 Nov 2021 22:44:02 +0100 Subject: [PATCH 04/13] Upgraded to `azjezz/psl`, which should fix `php:8.1.0` compatibility Ref https://github.com/azjezz/psl/releases/tag/1.9.1 Ref https://github.com/azjezz/psl/commit/9fdb771b1d04e57b7ad82fe01a367a37075e47d2 Thanks @azjezz ! --- composer.json | 2 +- composer.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e0847542..aa6aaa3a 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "require": { "php": "~8.0.0 || ~8.1.0", "ext-json": "*", - "azjezz/psl": "^1.9.0", + "azjezz/psl": "^1.9.1", "composer/composer": "^2.1.11", "nikolaposa/version": "^4.1.0", "ocramius/package-versions": "^2.4.0", diff --git a/composer.lock b/composer.lock index aca68d4f..55ff88be 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7b1ed5ff940c03d0edc4a7e3a453c53b", + "content-hash": "8a31330d9b404a2b6ed1498e438a7f0a", "packages": [ { "name": "azjezz/psl", From cfc9528874c43a71084182d615bc5ded5a3add13 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 6 Nov 2021 23:34:34 +0100 Subject: [PATCH 05/13] Prevent installation with incompatible `symfony/process` versions Sadly, `symfony/symfony` declared `php:>=7.1` compatibility many moons ago: that is generally technical lack of vision and responsibility on their end, but that ship has sailed. This means that a `composer update` can and **will** install a dependency graph that is incompatible with your system's dependencies. This change prevents installation of `symfony/process` in versions too archaic to actually function. As a side-effect, `vimeo/psalm` was also upgraded to its latest and greatest. Ref: https://github.com/vimeo/psalm/releases/tag/4.12.0 --- composer.json | 3 +++ composer.lock | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index aa6aaa3a..50bfd0da 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,9 @@ "squizlabs/php_codesniffer": "^3.6.1", "vimeo/psalm": "^4.12.0" }, + "conflict": { + "symfony/process": "<5.3.7" + }, "autoload": { "psr-4": { "Roave\\BackwardCompatibility\\": "src" diff --git a/composer.lock b/composer.lock index 55ff88be..315c28a9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8a31330d9b404a2b6ed1498e438a7f0a", + "content-hash": "7a5dcc0fead6209c696b336ad59bd0cc", "packages": [ { "name": "azjezz/psl", From f8c25b356ab752fc962faceae1f72e0566604480 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 Dec 2021 04:51:31 +0100 Subject: [PATCH 06/13] Upgraded `roave/better-reflection` to be compatible with https://github.com/Roave/BetterReflection/commit/1f7a13be41d110e132fb8f8ec0fce159c9c4639f This also handles the upcoming BC break of https://github.com/Roave/BetterReflection/pull/900 Some big changes: * `PropertyDocumentedTypeChanged` no longer exists: we use only `PropertyTypeChanged` for now. This is a step backwards, but it is needed to prevent issues around docblocks being too advanced for this library to parse them, for now. * see https://github.com/CuyZ/Valinor/issues/6 * see https://github.com/phpstan/phpstan-src/tree/447cd102d946a2d9883ac82793195275f54296a9/src/Type * see https://github.com/vimeo/psalm/tree/f1d47cc662500589e200a978e3af85488a5236cf/src/Psalm/Type * see https://github.com/phpDocumentor/ReflectionDocBlock/blob/622548b623e81ca6d78b721c5e029f4ce664f170/src/DocBlock/Tags/Param.php#L35 * see https://github.com/phpstan/phpdoc-parser/blob/d639142cf83e91a07b4862217a6f8aa65ee10d08/tests/PHPStan/Parser/TypeParserTest.php#L64 * /cc @tomasnorre this sadly effectively reverts https://github.com/Roave/BackwardCompatibilityCheck/pull/340 - it is too much effort to dive into further advanced types :-( * `PropertyTypeChanged` only expects the property to be both covariant and contravariant: if not, then a BC break was introduced (this re-uses some internal variance checks, simplifying code substantially) * usage of `ReflectionFunctionAbstract` is no longer present in the library: always using an union of `ReflectionMethod|ReflectionFunction` instead (as in `roave/better-reflection:^5`) * `FunctionName` is now `@internal`, since it's only used for internal rendering purposes --- bin/roave-backward-compatibility-check.php | 8 +- .../BCBreak/ClassBased/MethodRemoved.php | 6 +- .../FunctionBased/ExcludeInternalFunction.php | 9 +- .../BCBreak/FunctionBased/FunctionBased.php | 14 +- .../FunctionBased/FunctionBecameInternal.php | 15 +- .../MultipleChecksOnAFunction.php | 24 ++- .../ParameterByReferenceChanged.php | 15 +- .../ParameterDefaultValueChanged.php | 17 +- .../FunctionBased/ParameterTypeChanged.php | 15 +- .../ParameterTypeContravarianceChanged.php | 38 +--- .../RequiredParameterAmountIncreased.php | 15 +- .../ReturnTypeByReferenceChanged.php | 15 +- .../FunctionBased/ReturnTypeChanged.php | 15 +- .../ReturnTypeCovarianceChanged.php | 37 +--- .../FunctionBased/SkipFunctionBasedErrors.php | 9 +- .../PropertyDocumentedTypeChanged.php | 59 ------ .../PropertyBased/PropertyTypeChanged.php | 59 ++++++ .../Variance/TypeIsContravariant.php | 16 +- .../Variance/TypeIsCovariant.php | 21 +- .../Variance/TypeWithReflectorScope.php | 28 --- ...ctionAbstractName.php => FunctionName.php} | 7 +- .../FunctionBecameInternalTest.php | 14 +- .../MultipleChecksOnAFunctionTest.php | 6 +- .../ParameterByReferenceChangedTest.php | 15 +- .../ParameterDefaultValueChangedTest.php | 15 +- .../ParameterTypeChangedTest.php | 15 +- ...ParameterTypeContravarianceChangedTest.php | 15 +- .../RequiredParameterAmountIncreasedTest.php | 15 +- .../ReturnTypeByReferenceChangedTest.php | 15 +- .../FunctionBased/ReturnTypeChangedTest.php | 15 +- .../ReturnTypeCovarianceChangedTest.php | 15 +- .../SkipFunctionBasedErrorsTest.php | 10 +- ...edTest.php => PropertyTypeChangedTest.php} | 36 ++-- .../Variance/TypeIsContravariantTest.php | 172 +++++++++------- .../Variance/TypeIsCovariantTest.php | 187 +++++++++++------- .../ReflectionFunctionAbstractNameTest.php | 18 +- 36 files changed, 556 insertions(+), 449 deletions(-) delete mode 100644 src/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChanged.php create mode 100644 src/DetectChanges/BCBreak/PropertyBased/PropertyTypeChanged.php delete mode 100644 src/DetectChanges/Variance/TypeWithReflectorScope.php rename src/Formatter/{ReflectionFunctionAbstractName.php => FunctionName.php} (73%) rename test/unit/DetectChanges/BCBreak/PropertyBased/{PropertyDocumentedTypeChangedTest.php => PropertyTypeChangedTest.php} (81%) diff --git a/bin/roave-backward-compatibility-check.php b/bin/roave-backward-compatibility-check.php index 27f43ccb..b6242d67 100644 --- a/bin/roave-backward-compatibility-check.php +++ b/bin/roave-backward-compatibility-check.php @@ -114,7 +114,7 @@ static function (string $installationPath) use ($composerIo): Installer { new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\OnlyPublicPropertyChanged( new PropertyBased\MultipleChecksOnAProperty( new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyBecameInternal()), - new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyDocumentedTypeChanged()), + new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyTypeChanged(new TypeIsContravariant(), new TypeIsCovariant())), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyDefaultValueChanged()), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyVisibilityReduced()), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyScopeChanged()) @@ -123,7 +123,7 @@ static function (string $installationPath) use ($composerIo): Installer { new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\OnlyProtectedPropertyChanged( new PropertyBased\MultipleChecksOnAProperty( new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyBecameInternal()), - new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyDocumentedTypeChanged()), + new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyTypeChanged(new TypeIsContravariant(), new TypeIsCovariant())), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyDefaultValueChanged()), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyVisibilityReduced()), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyScopeChanged()) @@ -193,7 +193,7 @@ static function (string $installationPath) use ($composerIo): Installer { new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\OnlyPublicPropertyChanged( new PropertyBased\MultipleChecksOnAProperty( new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyBecameInternal()), - new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyDocumentedTypeChanged()), + new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyTypeChanged(new TypeIsContravariant(), new TypeIsCovariant())), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyDefaultValueChanged()), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyVisibilityReduced()), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyScopeChanged()) @@ -271,7 +271,7 @@ static function (string $installationPath) use ($composerIo): Installer { new ClassBased\SkipClassBasedErrors(new ClassBased\PropertyChanged( new PropertyBased\MultipleChecksOnAProperty( new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyBecameInternal()), - new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyDocumentedTypeChanged()), + new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyTypeChanged(new TypeIsContravariant(), new TypeIsCovariant())), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyDefaultValueChanged()), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyVisibilityReduced()), new PropertyBased\SkipPropertyBasedErrors(new PropertyBased\PropertyScopeChanged()) diff --git a/src/DetectChanges/BCBreak/ClassBased/MethodRemoved.php b/src/DetectChanges/BCBreak/ClassBased/MethodRemoved.php index 26f31dcb..19e21564 100644 --- a/src/DetectChanges/BCBreak/ClassBased/MethodRemoved.php +++ b/src/DetectChanges/BCBreak/ClassBased/MethodRemoved.php @@ -10,17 +10,17 @@ use Psl\Vec; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; +use Roave\BackwardCompatibility\Formatter\FunctionName; use Roave\BetterReflection\Reflection\ReflectionClass; use Roave\BetterReflection\Reflection\ReflectionMethod; final class MethodRemoved implements ClassBased { - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct() { - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } public function __invoke(ReflectionClass $fromClass, ReflectionClass $toClass): Changes diff --git a/src/DetectChanges/BCBreak/FunctionBased/ExcludeInternalFunction.php b/src/DetectChanges/BCBreak/FunctionBased/ExcludeInternalFunction.php index 5e7aca5f..c3d11511 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ExcludeInternalFunction.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ExcludeInternalFunction.php @@ -6,7 +6,8 @@ use Psl\Regex; use Roave\BackwardCompatibility\Changes; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; /** * Functions marked "internal" (docblock) are not affected by BC checks. @@ -20,8 +21,10 @@ public function __construct(FunctionBased $check) $this->check = $check; } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { if ($this->isInternalDocComment($fromFunction->getDocComment())) { return Changes::empty(); } diff --git a/src/DetectChanges/BCBreak/FunctionBased/FunctionBased.php b/src/DetectChanges/BCBreak/FunctionBased/FunctionBased.php index 2f41d7e3..ced4e469 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/FunctionBased.php +++ b/src/DetectChanges/BCBreak/FunctionBased/FunctionBased.php @@ -5,9 +5,19 @@ namespace Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased; use Roave\BackwardCompatibility\Changes; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; interface FunctionBased { - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes; + /** + * @template T of ReflectionMethod|ReflectionFunction + * + * @param T $fromFunction + * @param T $toFunction + */ + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes; } diff --git a/src/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternal.php b/src/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternal.php index 38d2feef..dc8d8941 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternal.php +++ b/src/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternal.php @@ -8,23 +8,26 @@ use Psl\Str; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; /** * A function that is marked internal is no available to downstream consumers. */ final class FunctionBecameInternal implements FunctionBased { - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct() { - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { if ( $this->isInternalDocComment($toFunction->getDocComment()) && ! $this->isInternalDocComment($fromFunction->getDocComment()) diff --git a/src/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunction.php b/src/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunction.php index ce30bd80..3753b87e 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunction.php +++ b/src/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunction.php @@ -6,7 +6,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; final class MultipleChecksOnAFunction implements FunctionBased { @@ -18,14 +19,25 @@ public function __construct(FunctionBased ...$checks) $this->checks = $checks; } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { return Changes::fromIterator($this->multipleChecks($fromFunction, $toFunction)); } - /** @return iterable */ - private function multipleChecks(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): iterable - { + /** + * @template T of ReflectionMethod|ReflectionFunction + * + * @param T $fromFunction + * @param T $toFunction + * + * @return iterable + */ + private function multipleChecks( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): iterable { foreach ($this->checks as $check) { yield from $check($fromFunction, $toFunction); } diff --git a/src/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChanged.php index 19b84849..887f2e02 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChanged.php @@ -8,8 +8,9 @@ use Psl\Str; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflection\ReflectionParameter; /** @@ -19,15 +20,17 @@ */ final class ParameterByReferenceChanged implements FunctionBased { - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct() { - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { $fromParameters = $fromFunction->getParameters(); $toParameters = $toFunction->getParameters(); $changes = Changes::empty(); diff --git a/src/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChanged.php index aa2a2c84..2dd08ab0 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChanged.php @@ -8,8 +8,9 @@ use Psl\Str; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflection\ReflectionParameter; use function var_export; @@ -20,15 +21,17 @@ */ final class ParameterDefaultValueChanged implements FunctionBased { - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct() { - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { $fromParametersWithDefaults = $this->defaultParameterValues($fromFunction); $toParametersWithDefaults = $this->defaultParameterValues($toFunction); @@ -58,7 +61,7 @@ public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFun } /** @return ReflectionParameter[] indexed by parameter index */ - private function defaultParameterValues(ReflectionFunctionAbstract $function): array + private function defaultParameterValues(ReflectionMethod|ReflectionFunction $function): array { return Dict\filter( $function->getParameters(), diff --git a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeChanged.php index 38d1cef4..daff79f1 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeChanged.php @@ -8,8 +8,9 @@ use Psl\Str; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflection\ReflectionParameter; use Roave\BetterReflection\Reflection\ReflectionType; @@ -21,15 +22,17 @@ */ final class ParameterTypeChanged implements FunctionBased { - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct() { - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { return Changes::fromIterator($this->checkSymbols( $fromFunction->getParameters(), $toFunction->getParameters() diff --git a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php index b958779f..f82eb6c1 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChanged.php @@ -6,17 +6,14 @@ use Psl\Dict; use Psl\Str; -use Psl\Type; -use ReflectionProperty; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; -use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflection\ReflectionParameter; use Roave\BetterReflection\Reflection\ReflectionType; -use Roave\BetterReflection\Reflector\Reflector; /** * When a parameter type changes, the new type should be wider than the previous type, or else @@ -26,16 +23,18 @@ final class ParameterTypeContravarianceChanged implements FunctionBased { private TypeIsContravariant $typeIsContravariant; - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct(TypeIsContravariant $typeIsContravariant) { $this->typeIsContravariant = $typeIsContravariant; - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { $fromParameters = $fromFunction->getParameters(); $toParameters = $toFunction->getParameters(); $changes = Changes::empty(); @@ -52,13 +51,7 @@ private function compareParameter(ReflectionParameter $fromParameter, Reflection $fromType = $fromParameter->getType(); $toType = $toParameter->getType(); - - if ( - ($this->typeIsContravariant)( - new TypeWithReflectorScope($fromType, $this->extractReflector($fromParameter)), - new TypeWithReflectorScope($toType, $this->extractReflector($toParameter)), - ) - ) { + if (($this->typeIsContravariant)($fromType, $toType)) { return Changes::empty(); } @@ -82,15 +75,4 @@ private function typeToString(?ReflectionType $type): string return $type->__toString(); } - - /** @TODO may the gods of BC compliance be merciful on me */ - private function extractReflector(ReflectionParameter $parameter): Reflector - { - $reflectionReflector = new ReflectionProperty(ReflectionFunctionAbstract::class, 'reflector'); - - $reflectionReflector->setAccessible(true); - - return Type\object(Reflector::class) - ->coerce($reflectionReflector->getValue($parameter->getDeclaringFunction())); - } } diff --git a/src/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreased.php b/src/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreased.php index db39a4e0..b4dede6d 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreased.php +++ b/src/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreased.php @@ -7,8 +7,9 @@ use Psl\Str; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; /** * When new parameters are added, they must be optional, or else the callers will provide an insufficient @@ -16,15 +17,17 @@ */ final class RequiredParameterAmountIncreased implements FunctionBased { - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct() { - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { $fromRequiredParameters = $fromFunction->getNumberOfRequiredParameters(); $toRequiredParameters = $toFunction->getNumberOfRequiredParameters(); diff --git a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChanged.php index b86935ca..7ead9c50 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChanged.php @@ -7,8 +7,9 @@ use Psl\Str; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; /** * PHP still (sadly) supports by-ref return types, so the type is wildly different between by-ref and by-val, and @@ -16,15 +17,17 @@ */ final class ReturnTypeByReferenceChanged implements FunctionBased { - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct() { - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { $fromReturnsReference = $fromFunction->returnsReference(); $toReturnsReference = $toFunction->returnsReference(); diff --git a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeChanged.php index 7eea221a..d1d95069 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeChanged.php @@ -7,8 +7,9 @@ use Psl\Str; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflection\ReflectionType; /** @@ -18,15 +19,17 @@ */ final class ReturnTypeChanged implements FunctionBased { - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct() { - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { $fromReturnType = $this->typeToString($fromFunction->getReturnType()); $toReturnType = $this->typeToString($toFunction->getReturnType()); diff --git a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php index ad6abb24..c328650c 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php +++ b/src/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChanged.php @@ -5,16 +5,13 @@ namespace Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased; use Psl\Str; -use Psl\Type; -use ReflectionProperty; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; -use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BackwardCompatibility\Formatter\FunctionName; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflection\ReflectionType; -use Roave\BetterReflection\Reflector\Reflector; /** * When the return type of a function changes, the new return type must be covariant to the current type. @@ -25,25 +22,22 @@ final class ReturnTypeCovarianceChanged implements FunctionBased { private TypeIsCovariant $typeIsCovariant; - private ReflectionFunctionAbstractName $formatFunction; + private FunctionName $formatFunction; public function __construct(TypeIsCovariant $typeIsCovariant) { $this->typeIsCovariant = $typeIsCovariant; - $this->formatFunction = new ReflectionFunctionAbstractName(); + $this->formatFunction = new FunctionName(); } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { $fromReturnType = $fromFunction->getReturnType(); $toReturnType = $toFunction->getReturnType(); - if ( - ($this->typeIsCovariant)( - new TypeWithReflectorScope($fromReturnType, $this->extractReflector($fromFunction)), - new TypeWithReflectorScope($toReturnType, $this->extractReflector($toFunction)), - ) - ) { + if (($this->typeIsCovariant)($fromReturnType, $toReturnType)) { return Changes::empty(); } @@ -66,15 +60,4 @@ private function typeToString(?ReflectionType $type): string return $type->__toString(); } - - /** @TODO may the gods of BC compliance be merciful on me */ - private function extractReflector(ReflectionFunctionAbstract $function): Reflector - { - $reflectionReflector = new ReflectionProperty(ReflectionFunctionAbstract::class, 'reflector'); - - $reflectionReflector->setAccessible(true); - - return Type\object(Reflector::class) - ->coerce($reflectionReflector->getValue($function)); - } } diff --git a/src/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrors.php b/src/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrors.php index 646788ed..6de411cb 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrors.php +++ b/src/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrors.php @@ -6,7 +6,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Throwable; final class SkipFunctionBasedErrors implements FunctionBased @@ -18,8 +19,10 @@ public function __construct(FunctionBased $next) $this->next = $next; } - public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction): Changes - { + public function __invoke( + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction + ): Changes { try { return ($this->next)($fromFunction, $toFunction); } catch (Throwable $failure) { diff --git a/src/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChanged.php b/src/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChanged.php deleted file mode 100644 index 138cc324..00000000 --- a/src/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChanged.php +++ /dev/null @@ -1,59 +0,0 @@ -formatProperty = new ReflectionPropertyName(); - } - - public function __invoke(ReflectionProperty $fromProperty, ReflectionProperty $toProperty): Changes - { - $toNativeType = []; - $toType = $toProperty->getType(); - if ($toType !== null) { - $toNativeType[] = $toType->getName(); - } - - if ($fromProperty->getDocComment() === '') { - return Changes::empty(); - } - - $fromTypes = Vec\sort($fromProperty->getDocBlockTypeStrings()); - $toTypes = Vec\sort(array_merge($toNativeType, $toProperty->getDocBlockTypeStrings())); - - if ($fromTypes === $toTypes) { - return Changes::empty(); - } - - return Changes::fromList(Change::changed( - Str\format( - 'Type documentation for property %s changed from %s to %s', - ($this->formatProperty)($fromProperty), - Str\join($fromTypes, '|') ?: 'having no type', - Str\join($toTypes, '|') ?: 'having no type' - ), - true - )); - } -} diff --git a/src/DetectChanges/BCBreak/PropertyBased/PropertyTypeChanged.php b/src/DetectChanges/BCBreak/PropertyBased/PropertyTypeChanged.php new file mode 100644 index 00000000..cf0336dd --- /dev/null +++ b/src/DetectChanges/BCBreak/PropertyBased/PropertyTypeChanged.php @@ -0,0 +1,59 @@ +formatProperty = new ReflectionPropertyName(); + } + + public function __invoke(ReflectionProperty $fromProperty, ReflectionProperty $toProperty): Changes + { + $fromType = $fromProperty->getType(); + $toType = $toProperty->getType(); + + if (($this->typeIsCovariant)($fromType, $toType) && ($this->typeIsContravariant)($fromType, $toType)) { + return Changes::empty(); + } + + return Changes::fromList(Change::changed( + Str\format( + 'Type type of property %s changed from %s to %s', + ($this->formatProperty)($fromProperty), + $fromType?->__toString() ?? 'having no type', + $toType?->__toString() ?? 'having no type' + ), + true + )); + } +} diff --git a/src/DetectChanges/Variance/TypeIsContravariant.php b/src/DetectChanges/Variance/TypeIsContravariant.php index 76add1c6..cb62f930 100644 --- a/src/DetectChanges/Variance/TypeIsContravariant.php +++ b/src/DetectChanges/Variance/TypeIsContravariant.php @@ -7,6 +7,7 @@ use Psl\Iter; use Psl\Str; use Roave\BetterReflection\Reflection\ReflectionNamedType; +use Roave\BetterReflection\Reflection\ReflectionType; /** * This is a simplistic contravariant type check. A more appropriate approach would be to @@ -19,12 +20,9 @@ final class TypeIsContravariant { public function __invoke( - TypeWithReflectorScope $originalType, - TypeWithReflectorScope $newType + ?ReflectionType $type, + ?ReflectionType $comparedType ): bool { - $type = $originalType->type; - $comparedType = $newType->type; - if ($comparedType === null) { return true; } @@ -73,13 +71,13 @@ public function __invoke( return false; } - $typeReflectionClass = $originalType->originatingReflector->reflectClass($typeAsString); - $comparedTypeClass = $newType->originatingReflector->reflectClass($comparedTypeAsString); + $typeReflectionClass = $type->getClass(); + $comparedTypeClass = $comparedType->getClass(); if ($comparedTypeClass->isInterface()) { - return $typeReflectionClass->implementsInterface($comparedTypeAsString); + return $typeReflectionClass->implementsInterface($comparedTypeClass->getName()); } - return Iter\contains($typeReflectionClass->getParentClassNames(), $comparedTypeAsString); + return Iter\contains($typeReflectionClass->getParentClassNames(), $comparedTypeClass->getName()); } } diff --git a/src/DetectChanges/Variance/TypeIsCovariant.php b/src/DetectChanges/Variance/TypeIsCovariant.php index c8cc29d2..ef0e9e5c 100644 --- a/src/DetectChanges/Variance/TypeIsCovariant.php +++ b/src/DetectChanges/Variance/TypeIsCovariant.php @@ -7,6 +7,7 @@ use Psl\Iter; use Psl\Str; use Roave\BetterReflection\Reflection\ReflectionNamedType; +use Roave\BetterReflection\Reflection\ReflectionType; use Traversable; /** @@ -20,12 +21,9 @@ final class TypeIsCovariant { public function __invoke( - TypeWithReflectorScope $originalType, - TypeWithReflectorScope $newType + ?ReflectionType $type, + ?ReflectionType $comparedType ): bool { - $type = $originalType->type; - $comparedType = $newType->type; - if ($type === null) { // everything can be covariant to `mixed` return true; @@ -68,7 +66,7 @@ public function __invoke( } if ($typeAsString === 'iterable' && ! $comparedType->isBuiltin()) { - $comparedTypeReflectionClass = $newType->originatingReflector->reflectClass($comparedType->getName()); + $comparedTypeReflectionClass = $comparedType->getClass(); if ($comparedTypeReflectionClass->implementsInterface(Traversable::class)) { // `iterable` can be restricted via any `Iterator` implementation @@ -86,13 +84,16 @@ public function __invoke( return false; } - $originalTypeReflectionClass = $originalType->originatingReflector->reflectClass($typeAsString); - $comparedTypeReflectionClass = $newType->originatingReflector->reflectClass($comparedTypeAsString); + $originalTypeReflectionClass = $type->getClass(); + $comparedTypeReflectionClass = $comparedType->getClass(); if ($originalTypeReflectionClass->isInterface()) { - return $comparedTypeReflectionClass->implementsInterface($typeAsString); + return $comparedTypeReflectionClass->implementsInterface($originalTypeReflectionClass->getName()); } - return Iter\contains($comparedTypeReflectionClass->getParentClassNames(), $typeAsString); + return Iter\contains( + $comparedTypeReflectionClass->getParentClassNames(), + $originalTypeReflectionClass->getName() + ); } } diff --git a/src/DetectChanges/Variance/TypeWithReflectorScope.php b/src/DetectChanges/Variance/TypeWithReflectorScope.php deleted file mode 100644 index 6694deb1..00000000 --- a/src/DetectChanges/Variance/TypeWithReflectorScope.php +++ /dev/null @@ -1,28 +0,0 @@ -isStatic()) { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php index 877d4e85..f9775dd7 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php @@ -8,7 +8,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\FunctionBecameInternal; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; @@ -26,8 +27,8 @@ final class FunctionBecameInternalTest extends TestCase * @dataProvider functionsToBeTested */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ): void { $changes = (new FunctionBecameInternal())($fromFunction, $toFunction); @@ -41,8 +42,11 @@ public function testDiffs( } /** - * @return array>> - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested(): array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunctionTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunctionTest.php index 04796119..6cf60e0a 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunctionTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunctionTest.php @@ -9,7 +9,7 @@ use Roave\BackwardCompatibility\Changes; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\FunctionBased; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\MultipleChecksOnAFunction; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; use RoaveTest\BackwardCompatibility\Assertion; /** @@ -25,8 +25,8 @@ public function testChecksAllGivenCheckers(): void $multiCheck = new MultipleChecksOnAFunction($checker1, $checker2, $checker3); - $from = $this->createMock(ReflectionFunctionAbstract::class); - $to = $this->createMock(ReflectionFunctionAbstract::class); + $from = $this->createMock(ReflectionFunction::class); + $to = $this->createMock(ReflectionFunction::class); $checker1 ->expects(self::once()) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php index 1221ac1f..c40172a3 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php @@ -8,7 +8,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ParameterByReferenceChanged; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -26,8 +27,8 @@ final class ParameterByReferenceChangedTest extends TestCase * @param string[] $expectedMessages */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ) : void { $changes = (new ParameterByReferenceChanged())($fromFunction, $toFunction); @@ -41,9 +42,11 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested() : array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php index 2fb125b0..42b60d40 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php @@ -8,7 +8,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ParameterDefaultValueChanged; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -26,8 +27,8 @@ final class ParameterDefaultValueChangedTest extends TestCase * @param string[] $expectedMessages */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ) : void { $changes = (new ParameterDefaultValueChanged())($fromFunction, $toFunction); @@ -41,9 +42,11 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested() : array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php index c9de0ff1..674741b2 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php @@ -8,7 +8,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ParameterTypeChanged; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -26,8 +27,8 @@ final class ParameterTypeChangedTest extends TestCase * @param string[] $expectedMessages */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ) : void { $changes = (new ParameterTypeChanged())($fromFunction, $toFunction); @@ -41,9 +42,11 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested() : array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php index 5cfe6a4d..c2ab8f6e 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php @@ -9,7 +9,8 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ParameterTypeContravarianceChanged; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -27,8 +28,8 @@ final class ParameterTypeContravarianceChangedTest extends TestCase * @param string[] $expectedMessages */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ) : void { $changes = (new ParameterTypeContravarianceChanged(new TypeIsContravariant()))($fromFunction, $toFunction); @@ -42,9 +43,11 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested() : array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php index b3d556c1..3b896c83 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php @@ -8,7 +8,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\RequiredParameterAmountIncreased; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -26,8 +27,8 @@ final class RequiredParameterAmountIncreasedTest extends TestCase * @param string[] $expectedMessages */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ) : void { $changes = (new RequiredParameterAmountIncreased())($fromFunction, $toFunction); @@ -41,9 +42,11 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested() : array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php index c5e67d12..7f251006 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php @@ -8,7 +8,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ReturnTypeByReferenceChanged; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -26,8 +27,8 @@ final class ReturnTypeByReferenceChangedTest extends TestCase * @param string[] $expectedMessages */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ) : void { $changes = (new ReturnTypeByReferenceChanged())($fromFunction, $toFunction); @@ -41,9 +42,11 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested() : array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php index 2c3c6a89..75c6b9c4 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php @@ -8,7 +8,8 @@ use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ReturnTypeChanged; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -26,8 +27,8 @@ final class ReturnTypeChangedTest extends TestCase * @param string[] $expectedMessages */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ) : void { $changes = (new ReturnTypeChanged())($fromFunction, $toFunction); @@ -41,9 +42,11 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested() : array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php index 49b253ef..51989efc 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php @@ -9,7 +9,8 @@ use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\ReturnTypeCovarianceChanged; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_combine; @@ -27,8 +28,8 @@ final class ReturnTypeCovarianceChangedTest extends TestCase * @param string[] $expectedMessages */ public function testDiffs( - ReflectionFunctionAbstract $fromFunction, - ReflectionFunctionAbstract $toFunction, + ReflectionMethod|ReflectionFunction $fromFunction, + ReflectionMethod|ReflectionFunction $toFunction, array $expectedMessages ) : void { $changes = (new ReturnTypeCovarianceChanged(new TypeIsCovariant()))($fromFunction, $toFunction); @@ -42,9 +43,11 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ public function functionsToBeTested() : array { diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrorsTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrorsTest.php index 4a3a7564..b42656d4 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrorsTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrorsTest.php @@ -11,8 +11,8 @@ use Roave\BackwardCompatibility\Changes; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\FunctionBased; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\SkipFunctionBasedErrors; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; use function uniqid; /** @@ -33,8 +33,8 @@ protected function setUp(): void public function testWillForwardChecks(): void { - $fromFunction = $this->createMock(ReflectionFunctionAbstract::class); - $toFunction = $this->createMock(ReflectionFunctionAbstract::class); + $fromFunction = $this->createMock(ReflectionFunction::class); + $toFunction = $this->createMock(ReflectionFunction::class); $expectedChanges = Changes::fromList(Change::added( uniqid('foo', true), true @@ -52,8 +52,8 @@ public function testWillForwardChecks(): void public function testWillCollectFailures(): void { - $fromFunction = $this->createMock(ReflectionFunctionAbstract::class); - $toFunction = $this->createMock(ReflectionFunctionAbstract::class); + $fromFunction = $this->createMock(ReflectionFunction::class); + $toFunction = $this->createMock(ReflectionFunction::class); $exception = new Exception(); $this diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyTypeChangedTest.php similarity index 81% rename from test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChangedTest.php rename to test/unit/DetectChanges/BCBreak/PropertyBased/PropertyTypeChangedTest.php index 3d0d0677..a2ea72c1 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDocumentedTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyTypeChangedTest.php @@ -6,7 +6,9 @@ use PHPUnit\Framework\TestCase; use Roave\BackwardCompatibility\Change; -use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyDocumentedTypeChanged; +use Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyTypeChanged; +use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; +use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; use Roave\BetterReflection\Reflector\DefaultReflector; @@ -19,9 +21,9 @@ use function iterator_to_array; /** - * @covers \Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyDocumentedTypeChanged + * @covers \Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased\PropertyTypeChanged */ -final class PropertyDocumentedTypeChangedTest extends TestCase +final class PropertyTypeChangedTest extends TestCase { /** * @param string[] $expectedMessages @@ -33,7 +35,10 @@ public function testDiffs( ReflectionProperty $toProperty, array $expectedMessages ): void { - $changes = (new PropertyDocumentedTypeChanged())($fromProperty, $toProperty); + $changes = (new PropertyTypeChanged( + new TypeIsContravariant(), + new TypeIsCovariant() + ))($fromProperty, $toProperty); self::assertSame( $expectedMessages, @@ -123,6 +128,8 @@ class TheClass { * @var int */ public $propertyWithDocblockTypeHintChangeToNativeTypeHintAndTypeChange; + + public int $propertyWithDeclaredTypeRemoved; } PHP , @@ -196,6 +203,8 @@ class TheClass { public int $propertyWithDocblockTypeHintChangeToNativeTypeHint; public float $propertyWithDocblockTypeHintChangeToNativeTypeHintAndTypeChange; + + public $propertyWithDeclaredTypeRemoved; } PHP , @@ -207,22 +216,27 @@ class TheClass { $fromClass = $fromClassReflector->reflectClass('TheClass'); $toClass = $toClassReflector->reflectClass('TheClass'); + // Note: lots of docblock-related tests report no BC breaks here. This is because this change checker does + // not operate on documented types anymore. Documented types are too advanced for this library to inspect, + // right now, since psalm/phpstan/psr-5 are constantly evolving. The library will limit itself in + // inspecting reflection-based type changes (for now). $properties = [ 'publicNoDocblockToNoDocblock' => [], 'publicNoDocblockToDocblock' => [], - 'publicNoTypeDocblockToDocblock' => ['[BC] CHANGED: Type documentation for property TheClass#$publicNoTypeDocblockToDocblock changed from having no type to int'], + 'publicNoTypeDocblockToDocblock' => [], 'publicDocblockToSameDocblock' => [], - 'publicDocblockToDifferentDocblock' => ['[BC] CHANGED: Type documentation for property TheClass#$publicDocblockToDifferentDocblock changed from int to float'], - 'publicDocblockToNoDocblock' => ['[BC] CHANGED: Type documentation for property TheClass#$publicDocblockToNoDocblock changed from int to having no type'], + 'publicDocblockToDifferentDocblock' => [], + 'publicDocblockToNoDocblock' => [], 'publicCompositeTypeDocblockToSameTypeDocblock' => [], 'publicCompositeTypeDocblockToSameTypeDocblockWithDifferentSorting' => [], - 'publicCompositeTypeDocblockToDifferentCompositeTypeDocblock' => ['[BC] CHANGED: Type documentation for property TheClass#$publicCompositeTypeDocblockToDifferentCompositeTypeDocblock changed from float|int to float|int|string'], - 'privateDocblockToDifferentDocblock' => ['[BC] CHANGED: Type documentation for property TheClass#$privateDocblockToDifferentDocblock changed from int to float'], + 'publicCompositeTypeDocblockToDifferentCompositeTypeDocblock' => [], + 'privateDocblockToDifferentDocblock' => [], 'duplicatePropertyTypesBeingDeduplicatedAreNotBcBreaks' => [], 'propertyTypeBeingDuplicatedAreNotBcBreaks' => [], 'propertyWithComplexDocblockThatCannotBeParsed' => [], - 'propertyWithDocblockTypeHintChangeToNativeTypeHint' => [], - 'propertyWithDocblockTypeHintChangeToNativeTypeHintAndTypeChange' => ['[BC] CHANGED: Type documentation for property TheClass#$propertyWithDocblockTypeHintChangeToNativeTypeHintAndTypeChange changed from int to float'], + 'propertyWithDocblockTypeHintChangeToNativeTypeHint' => ['[BC] CHANGED: Type type of property TheClass#$propertyWithDocblockTypeHintChangeToNativeTypeHint changed from having no type to int'], + 'propertyWithDocblockTypeHintChangeToNativeTypeHintAndTypeChange' => ['[BC] CHANGED: Type type of property TheClass#$propertyWithDocblockTypeHintChangeToNativeTypeHintAndTypeChange changed from having no type to float'], + 'propertyWithDeclaredTypeRemoved' => ['[BC] CHANGED: Type type of property TheClass#$propertyWithDeclaredTypeRemoved changed from int to having no type'], ]; return array_combine( diff --git a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php index 2cbbb811..0c8473db 100644 --- a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php @@ -7,11 +7,14 @@ use PhpParser\Node\Identifier; use PhpParser\Node\NullableType; use PHPUnit\Framework\TestCase; +use Psl\Type; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; use Roave\BetterReflection\BetterReflection; +use Roave\BetterReflection\Reflection\ReflectionProperty; use Roave\BetterReflection\Reflection\ReflectionType; use Roave\BetterReflection\Reflector\DefaultReflector; +use Roave\BetterReflection\Reflector\Reflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_map; @@ -23,8 +26,8 @@ final class TypeIsContravariantTest extends TestCase * @dataProvider checkedTypes */ public function testContravariance( - TypeWithReflectorScope $type, - TypeWithReflectorScope $newType, + ?ReflectionType $type, + ?ReflectionType $newType, bool $expectedToBeContravariant ): void { self::assertSame( @@ -34,8 +37,11 @@ public function testContravariance( } /** - * @return array> - * @psalm-return array + * @return array */ public function checkedTypes(): array { @@ -52,11 +58,18 @@ class AnotherClassWithMultipleInterfaces implements AnInterface, AnotherInterfac class AClass {} class BClass extends AClass {} class CClass extends BClass {} +final class OwnerPropertyContainer { private $owner; } PHP , (new BetterReflection())->astLocator() )); + $owner = Type\object(ReflectionProperty::class) + ->coerce( + $reflector->reflectClass('OwnerPropertyContainer') + ->getProperty('owner') + ); + $types = [ 'no type to no type is contravariant with itself' => [ null, @@ -65,150 +78,154 @@ class CClass extends BClass {} ], 'no type to void type is not contravariant' => [ null, - ReflectionType::createFromNode(new Identifier('void')), + new Identifier('void'), false, ], 'void type to no type is contravariant' => [ - ReflectionType::createFromNode(new Identifier('void')), + new Identifier('void'), null, true, ], 'void type to scalar type is contravariant' => [ - ReflectionType::createFromNode(new Identifier('void')), - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('void'), + new Identifier('string'), true, ], 'void type to class type is contravariant' => [ - ReflectionType::createFromNode(new Identifier('void')), - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('void'), + new Identifier('AClass'), true, ], 'scalar type to no type is contravariant' => [ - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('string'), null, true, ], 'no type to scalar type is not contravariant' => [ null, - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('string'), false, ], 'class type to no type is contravariant' => [ - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('AClass'), null, true, ], 'no type to class type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('AClass'), null, true, ], 'iterable to array is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('array')), + new Identifier('iterable'), + new Identifier('array'), false, ], 'array to iterable is contravariant' => [ - ReflectionType::createFromNode(new Identifier('array')), - ReflectionType::createFromNode(new Identifier('iterable')), + new Identifier('array'), + new Identifier('iterable'), true, ], 'iterable to non-iterable class type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + new Identifier('iterable'), + new Identifier('AnotherClassWithMultipleInterfaces'), false, ], 'iterable to iterable class type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('Iterator')), + new Identifier('iterable'), + new Identifier('Iterator'), false, ], 'non-iterable class to iterable type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + new Identifier('iterable'), + new Identifier('AnotherClassWithMultipleInterfaces'), false, ], 'iterable class type to iterable is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('Iterator')), - ReflectionType::createFromNode(new Identifier('iterable')), + new Identifier('Iterator'), + new Identifier('iterable'), false, ], 'object to class type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('object')), - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('object'), + new Identifier('AClass'), false, ], 'class type to object is contravariant' => [ - ReflectionType::createFromNode(new Identifier('AClass')), - ReflectionType::createFromNode(new Identifier('object')), + new Identifier('AClass'), + new Identifier('object'), true, ], 'class type to scalar type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('AClass')), - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('AClass'), + new Identifier('string'), false, ], 'scalar type to class type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('string')), - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('string'), + new Identifier('AClass'), false, ], 'scalar type (string) to different scalar type (int) is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('string')), - ReflectionType::createFromNode(new Identifier('int')), + new Identifier('string'), + new Identifier('int'), false, ], 'scalar type (int) to different scalar type (float) is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('int')), - ReflectionType::createFromNode(new Identifier('float')), + new Identifier('int'), + new Identifier('float'), false, ], 'object type to scalar type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('object')), - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('object'), + new Identifier('string'), false, ], 'scalar type to object type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('string')), - ReflectionType::createFromNode(new Identifier('object')), + new Identifier('string'), + new Identifier('object'), false, ], 'class to superclass is contravariant' => [ - ReflectionType::createFromNode(new Identifier('BClass')), - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('BClass'), + new Identifier('AClass'), true, ], 'class to subclass is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('BClass')), - ReflectionType::createFromNode(new Identifier('CClass')), + new Identifier('BClass'), + new Identifier('CClass'), false, ], 'class to implemented interface is contravariant' => [ - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), - ReflectionType::createFromNode(new Identifier('AnInterface')), + new Identifier('AnotherClassWithMultipleInterfaces'), + new Identifier('AnInterface'), true, ], 'class to not implemented interface is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), - ReflectionType::createFromNode(new Identifier('Traversable')), + new Identifier('AnotherClassWithMultipleInterfaces'), + new Identifier('Traversable'), false, ], 'interface to parent interface is contravariant' => [ - ReflectionType::createFromNode(new Identifier('Iterator')), - ReflectionType::createFromNode(new Identifier('Traversable')), + new Identifier('Iterator'), + new Identifier('Traversable'), true, ], 'interface to child interface is contravariant' => [ - ReflectionType::createFromNode(new Identifier('Traversable')), - ReflectionType::createFromNode(new Identifier('Iterator')), + new Identifier('Traversable'), + new Identifier('Iterator'), false, ], ]; return array_map( static fn (array $types): array => [ - new TypeWithReflectorScope($types[0], $reflector), - new TypeWithReflectorScope($types[1], $reflector), + $types[0] === null + ? null + : self::identifierType($reflector, $owner, $types[0]), + $types[1] === null + ? null + : self::identifierType($reflector, $owner, $types[1]), $types[2], ], $types @@ -218,14 +235,14 @@ class CClass extends BClass {} /** * @dataProvider existingTypes */ - public function testContravarianceConsidersSameTypeAlwaysContravariant(TypeWithReflectorScope $type): void + public function testContravarianceConsidersSameTypeAlwaysContravariant(?ReflectionType $type): void { self::assertTrue( (new TypeIsContravariant())($type, $type) ); } - /** @return TypeWithReflectorScope[][] */ + /** @return list */ public function existingTypes(): array { $reflector = new DefaultReflector(new StringSourceLocator( @@ -234,20 +251,25 @@ public function existingTypes(): array interface Traversable {} class AClass {} +final class OwnerPropertyContainer { private $owner; } PHP , (new BetterReflection())->astLocator() )); + $owner = Type\object(ReflectionProperty::class) + ->coerce( + $reflector->reflectClass('OwnerPropertyContainer') + ->getProperty('owner') + ); + return array_merge( - [[new TypeWithReflectorScope(null, $reflector)]], + [[null]], array_merge(...array_map( - static function (string $type) use ($reflector): array { - return [ - [new TypeWithReflectorScope(ReflectionType::createFromNode(new Identifier($type)), $reflector)], - [new TypeWithReflectorScope(ReflectionType::createFromNode(new NullableType(new Identifier($type))), $reflector)], - ]; - }, + static fn (string $type): array => [ + [self::identifierType($reflector, $owner, new Identifier($type))], + [self::identifierType($reflector, $owner, new NullableType(new Identifier($type)))], + ], [ 'int', 'string', @@ -274,12 +296,20 @@ public function testContravarianceConsidersNullability(string $type): void interface Traversable {} class AClass {} +final class OwnerPropertyContainer { private $owner; } PHP , (new BetterReflection())->astLocator() )); - $nullable = new TypeWithReflectorScope(ReflectionType::createFromNode(new NullableType(new Identifier($type))), $reflector); - $notNullable = new TypeWithReflectorScope(ReflectionType::createFromNode(new Identifier($type)), $reflector); + + $owner = Type\object(ReflectionProperty::class) + ->coerce( + $reflector->reflectClass('OwnerPropertyContainer') + ->getProperty('owner') + ); + + $nullable = self::identifierType($reflector, $owner, new NullableType(new Identifier($type))); + $notNullable = self::identifierType($reflector, $owner, new Identifier($type)); $isContravariant = new TypeIsContravariant(); @@ -302,4 +332,12 @@ public function existingNullableTypeStrings(): array ['AClass'], ]; } + + private static function identifierType( + Reflector $reflector, + ReflectionProperty $owner, + Identifier|NullableType $identifier + ): ReflectionType { + return ReflectionType::createFromNode($reflector, $owner, $identifier); + } } diff --git a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php index 50f35c1c..73418cf1 100644 --- a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php @@ -7,11 +7,13 @@ use PhpParser\Node\Identifier; use PhpParser\Node\NullableType; use PHPUnit\Framework\TestCase; +use Psl\Type; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; -use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; use Roave\BetterReflection\BetterReflection; +use Roave\BetterReflection\Reflection\ReflectionProperty; use Roave\BetterReflection\Reflection\ReflectionType; use Roave\BetterReflection\Reflector\DefaultReflector; +use Roave\BetterReflection\Reflector\Reflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; use function array_map; @@ -23,8 +25,8 @@ final class TypeIsCovariantTest extends TestCase * @dataProvider checkedTypes */ public function testCovariance( - TypeWithReflectorScope $type, - TypeWithReflectorScope $newType, + ?ReflectionType $type, + ?ReflectionType $newType, bool $expectedToBeContravariant ): void { self::assertSame( @@ -34,8 +36,11 @@ public function testCovariance( } /** - * @return array> - * @psalm-return array + * @return array */ public function checkedTypes(): array { @@ -52,174 +57,185 @@ class AnotherClassWithMultipleInterfaces implements AnInterface, AnotherInterfac class AClass {} class BClass extends AClass {} class CClass extends BClass {} +final class OwnerPropertyContainer { private $owner; } PHP , (new BetterReflection())->astLocator() )); + $owner = Type\object(ReflectionProperty::class) + ->coerce( + $reflector->reflectClass('OwnerPropertyContainer') + ->getProperty('owner') + ); + $types = [ 'no type to void type is covariant' => [ null, - ReflectionType::createFromNode(new Identifier('void')), + new Identifier('void'), true, ], 'void type to no type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('void')), + new Identifier('void'), null, false, ], 'void type to scalar type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('void')), - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('void'), + new Identifier('string'), false, ], 'void type to class type is covariant' => [ - ReflectionType::createFromNode(new Identifier('void')), - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('void'), + new Identifier('AClass'), false, ], 'scalar type to no type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('string'), null, false, ], 'no type to scalar type is covariant' => [ null, - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('string'), true, ], 'class type to no type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('AClass'), null, false, ], 'no type to class type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('AClass'), null, false, ], 'iterable to array is covariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('array')), + new Identifier('iterable'), + new Identifier('array'), true, ], 'iterable to scalar is not covariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('int')), + new Identifier('iterable'), + new Identifier('int'), false, ], 'scalar to iterable is not covariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('int')), + new Identifier('iterable'), + new Identifier('int'), false, ], 'array to iterable is not covariant' => [ - ReflectionType::createFromNode(new Identifier('array')), - ReflectionType::createFromNode(new Identifier('iterable')), + new Identifier('array'), + new Identifier('iterable'), false, ], 'iterable to non-iterable class type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + new Identifier('iterable'), + new Identifier('AnotherClassWithMultipleInterfaces'), false, ], 'iterable to iterable class type is covariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('Iterator')), + new Identifier('iterable'), + new Identifier('Iterator'), true, ], 'non-iterable class to iterable type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('iterable')), - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + new Identifier('iterable'), + new Identifier('AnotherClassWithMultipleInterfaces'), false, ], 'iterable class type to iterable is not covariant' => [ - ReflectionType::createFromNode(new Identifier('Iterator')), - ReflectionType::createFromNode(new Identifier('iterable')), + new Identifier('Iterator'), + new Identifier('iterable'), false, ], 'object to class type is covariant' => [ - ReflectionType::createFromNode(new Identifier('object')), - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('object'), + new Identifier('AClass'), true, ], 'class type to object is not covariant' => [ - ReflectionType::createFromNode(new Identifier('AClass')), - ReflectionType::createFromNode(new Identifier('object')), + new Identifier('AClass'), + new Identifier('object'), false, ], 'class type to scalar type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('AClass')), - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('AClass'), + new Identifier('string'), false, ], 'scalar type to class type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('string')), - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('string'), + new Identifier('AClass'), false, ], 'scalar type (string) to different scalar type (int) is not covariant' => [ - ReflectionType::createFromNode(new Identifier('string')), - ReflectionType::createFromNode(new Identifier('int')), + new Identifier('string'), + new Identifier('int'), false, ], 'scalar type (int) to different scalar type (float) is not covariant' => [ - ReflectionType::createFromNode(new Identifier('int')), - ReflectionType::createFromNode(new Identifier('float')), + new Identifier('int'), + new Identifier('float'), false, ], 'object type to scalar type is not contravariant' => [ - ReflectionType::createFromNode(new Identifier('object')), - ReflectionType::createFromNode(new Identifier('string')), + new Identifier('object'), + new Identifier('string'), false, ], 'scalar type to object type is not covariant' => [ - ReflectionType::createFromNode(new Identifier('string')), - ReflectionType::createFromNode(new Identifier('object')), + new Identifier('string'), + new Identifier('object'), false, ], 'class to superclass is not covariant' => [ - ReflectionType::createFromNode(new Identifier('BClass')), - ReflectionType::createFromNode(new Identifier('AClass')), + new Identifier('BClass'), + new Identifier('AClass'), false, ], 'class to subclass is covariant' => [ - ReflectionType::createFromNode(new Identifier('BClass')), - ReflectionType::createFromNode(new Identifier('CClass')), + new Identifier('BClass'), + new Identifier('CClass'), true, ], 'class to implemented interface is not covariant' => [ - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), - ReflectionType::createFromNode(new Identifier('AnInterface')), + new Identifier('AnotherClassWithMultipleInterfaces'), + new Identifier('AnInterface'), false, ], 'interface to implementing class is covariant' => [ - ReflectionType::createFromNode(new Identifier('AnInterface')), - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), + new Identifier('AnInterface'), + new Identifier('AnotherClassWithMultipleInterfaces'), true, ], 'class to not implemented interface is not covariant' => [ - ReflectionType::createFromNode(new Identifier('AnotherClassWithMultipleInterfaces')), - ReflectionType::createFromNode(new Identifier('Traversable')), + new Identifier('AnotherClassWithMultipleInterfaces'), + new Identifier('Traversable'), false, ], 'interface to parent interface is not covariant' => [ - ReflectionType::createFromNode(new Identifier('Iterator')), - ReflectionType::createFromNode(new Identifier('Traversable')), + new Identifier('Iterator'), + new Identifier('Traversable'), false, ], 'interface to child interface is covariant' => [ - ReflectionType::createFromNode(new Identifier('Traversable')), - ReflectionType::createFromNode(new Identifier('Iterator')), + new Identifier('Traversable'), + new Identifier('Iterator'), true, ], ]; return array_map( static fn (array $types): array => [ - new TypeWithReflectorScope($types[0], $reflector), - new TypeWithReflectorScope($types[1], $reflector), + $types[0] === null + ? null + : self::identifierType($reflector, $owner, $types[0]), + $types[1] === null + ? null + : self::identifierType($reflector, $owner, $types[1]), $types[2], ], $types @@ -229,14 +245,16 @@ class CClass extends BClass {} /** * @dataProvider existingTypes */ - public function testCovarianceConsidersSameTypeAlwaysCovariant(TypeWithReflectorScope $type): void + public function testCovarianceConsidersSameTypeAlwaysCovariant(?ReflectionType $type): void { self::assertTrue( (new TypeIsCovariant())($type, $type) ); } - /** @return TypeWithReflectorScope[][] */ + /** + * @return list + */ public function existingTypes(): array { $reflector = new DefaultReflector(new StringSourceLocator( @@ -245,20 +263,25 @@ public function existingTypes(): array interface Traversable {} class AClass {} +final class OwnerPropertyContainer { private $owner; } PHP , (new BetterReflection())->astLocator() )); + $owner = Type\object(ReflectionProperty::class) + ->coerce( + $reflector->reflectClass('OwnerPropertyContainer') + ->getProperty('owner') + ); + return array_merge( - [[new TypeWithReflectorScope(null, $reflector)]], + [[null]], array_merge(...array_map( - static function (string $type) use ($reflector): array { - return [ - [new TypeWithReflectorScope(ReflectionType::createFromNode(new Identifier($type)), $reflector)], - [new TypeWithReflectorScope(ReflectionType::createFromNode(new NullableType(new Identifier($type))), $reflector)], - ]; - }, + static fn (string $type): array => [ + [self::identifierType($reflector, $owner, new Identifier($type))], + [self::identifierType($reflector, $owner, new NullableType(new Identifier($type)))], + ], [ 'int', 'string', @@ -285,12 +308,20 @@ public function testCovarianceConsidersNullability(string $type): void interface Traversable {} class AClass {} +final class OwnerPropertyContainer { private $owner; } PHP , (new BetterReflection())->astLocator() )); - $nullable = new TypeWithReflectorScope(ReflectionType::createFromNode(new NullableType(new Identifier($type))), $reflector); - $notNullable = new TypeWithReflectorScope(ReflectionType::createFromNode(new Identifier($type)), $reflector); + + $owner = Type\object(ReflectionProperty::class) + ->coerce( + $reflector->reflectClass('OwnerPropertyContainer') + ->getProperty('owner') + ); + + $nullable = self::identifierType($reflector, $owner, new NullableType(new Identifier($type))); + $notNullable = self::identifierType($reflector, $owner, new Identifier($type)); $isCovariant = new TypeIsCovariant(); @@ -313,4 +344,12 @@ public function existingNullableTypeStrings(): array ['AClass'], ]; } + + private static function identifierType( + Reflector $reflector, + ReflectionProperty $owner, + Identifier|NullableType $identifier + ): ReflectionType { + return ReflectionType::createFromNode($reflector, $owner, $identifier); + } } diff --git a/test/unit/Formatter/ReflectionFunctionAbstractNameTest.php b/test/unit/Formatter/ReflectionFunctionAbstractNameTest.php index 7cefb9c6..1b4e907a 100644 --- a/test/unit/Formatter/ReflectionFunctionAbstractNameTest.php +++ b/test/unit/Formatter/ReflectionFunctionAbstractNameTest.php @@ -5,29 +5,31 @@ namespace RoaveTest\BackwardCompatibility\Formatter; use PHPUnit\Framework\TestCase; -use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName; +use Roave\BackwardCompatibility\Formatter\FunctionName; use Roave\BetterReflection\BetterReflection; -use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract; +use Roave\BetterReflection\Reflection\ReflectionFunction; +use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; /** - * @covers \Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName + * @covers \Roave\BackwardCompatibility\Formatter\FunctionName */ final class ReflectionFunctionAbstractNameTest extends TestCase { /** * @dataProvider functionsToBeTested */ - public function testName(ReflectionFunctionAbstract $function, string $expectedName) : void + public function testName(ReflectionFunction|ReflectionMethod $function, string $expectedName) : void { - self::assertSame($expectedName, (new ReflectionFunctionAbstractName())($function)); + self::assertSame($expectedName, (new FunctionName())($function)); } /** - * @return array> - * - * @psalm-return array + * @return array */ public function functionsToBeTested() : array { From ed882dd781b1a630b0d70f7f06391992f20572cd Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 Dec 2021 05:14:24 +0100 Subject: [PATCH 07/13] Restricting internal types usages to `tests/`, included `psalm/plugin-phpunit` This change ensures that we don't use `@internal` symbols in `src/` (too dangerous, for long-term usage), and makes the type checking much stricter, thanks to `psalm/plugin-phpunit`. Since `vimeo/psalm` has been upgraded, and https://github.com/vimeo/psalm/issues/2772 no longer applies, we can also remove a lot of manually written code that was safe to clean up. --- composer.json | 1 + composer.lock | 62 ++++++++++++++++++- psalm.xml | 24 +++++-- .../BCBreak/FunctionBased/FunctionBased.php | 4 +- .../MultipleChecksOnAFunction.php | 4 +- .../PropertyBased/PropertyTypeChanged.php | 3 - src/Git/CheckedOutRepository.php | 9 +-- src/Git/Revision.php | 14 ++--- .../ClassBased/AncestorRemovedTest.php | 13 ++-- .../ClassBased/ClassBecameAbstractTest.php | 13 ++-- .../ClassBased/ClassBecameInterfaceTest.php | 13 ++-- .../ClassBased/ClassBecameTraitTest.php | 13 ++-- .../ClassConstantValueChangedTest.php | 27 ++++---- .../ClassConstantVisibilityReducedTest.php | 29 ++++----- .../FunctionBecameInternalTest.php | 13 ++-- .../ParameterByReferenceChangedTest.php | 13 ++-- .../ParameterDefaultValueChangedTest.php | 13 ++-- .../ParameterTypeChangedTest.php | 13 ++-- ...ParameterTypeContravarianceChangedTest.php | 13 ++-- .../RequiredParameterAmountIncreasedTest.php | 13 ++-- .../ReturnTypeByReferenceChangedTest.php | 13 ++-- .../FunctionBased/ReturnTypeChangedTest.php | 13 ++-- .../ReturnTypeCovarianceChangedTest.php | 13 ++-- .../SkipFunctionBasedErrorsTest.php | 2 +- .../InterfaceBased/AncestorRemovedTest.php | 13 ++-- .../InterfaceBecameClassTest.php | 13 ++-- .../InterfaceBecameTraitTest.php | 13 ++-- .../InterfaceBased/MethodAddedTest.php | 14 ++--- .../MethodBased/MethodBecameFinalTest.php | 13 ++-- .../MethodConcretenessChangedTest.php | 13 ++-- .../MethodBased/MethodScopeChangedTest.php | 13 ++-- .../MethodVisibilityReducedTest.php | 13 ++-- .../PropertyBecameInternalTest.php | 13 ++-- .../PropertyDefaultValueChangedTest.php | 13 ++-- .../PropertyScopeChangedTest.php | 13 ++-- .../PropertyBased/PropertyTypeChangedTest.php | 13 ++-- .../PropertyVisibilityReducedTest.php | 13 ++-- .../TraitBased/TraitBecameClassTest.php | 13 ++-- .../TraitBased/TraitBecameInterfaceTest.php | 13 ++-- .../Variance/TypeIsContravariantTest.php | 3 +- .../Variance/TypeIsCovariantTest.php | 2 +- 41 files changed, 268 insertions(+), 281 deletions(-) diff --git a/composer.json b/composer.json index 50bfd0da..edeb48fb 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ "doctrine/coding-standard": "^9.0.0", "php-standard-library/psalm-plugin": "^1.1.1", "phpunit/phpunit": "^9.5.10", + "psalm/plugin-phpunit": "^0.16.1", "roave/infection-static-analysis-plugin": "^1.10", "roave/security-advisories": "dev-master", "squizlabs/php_codesniffer": "^3.6.1", diff --git a/composer.lock b/composer.lock index 315c28a9..4681d700 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7a5dcc0fead6209c696b336ad59bd0cc", + "content-hash": "9fbf22a18367cd78eef22c43a7948309", "packages": [ { "name": "azjezz/psl", @@ -4223,6 +4223,66 @@ ], "time": "2021-09-25T07:38:51+00:00" }, + { + "name": "psalm/plugin-phpunit", + "version": "0.16.1", + "source": { + "type": "git", + "url": "https://github.com/psalm/psalm-plugin-phpunit.git", + "reference": "5dd3be04f37a857d52880ef6af2524a441dfef24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/5dd3be04f37a857d52880ef6af2524a441dfef24", + "reference": "5dd3be04f37a857d52880ef6af2524a441dfef24", + "shasum": "" + }, + "require": { + "composer/package-versions-deprecated": "^1.10", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "ext-simplexml": "*", + "php": "^7.1 || ^8.0", + "vimeo/psalm": "dev-master || dev-4.x || ^4.5" + }, + "conflict": { + "phpunit/phpunit": "<7.5" + }, + "require-dev": { + "codeception/codeception": "^4.0.3", + "php": "^7.3 || ^8.0", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0", + "squizlabs/php_codesniffer": "^3.3.1", + "weirdan/codeception-psalm-module": "^0.11.0", + "weirdan/prophecy-shim": "^1.0 || ^2.0" + }, + "type": "psalm-plugin", + "extra": { + "psalm": { + "pluginClass": "Psalm\\PhpUnitPlugin\\Plugin" + } + }, + "autoload": { + "psr-4": { + "Psalm\\PhpUnitPlugin\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Brown", + "email": "github@muglug.com" + } + ], + "description": "Psalm plugin for PHPUnit", + "support": { + "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues", + "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.16.1" + }, + "time": "2021-06-18T23:56:46+00:00" + }, { "name": "roave/infection-static-analysis-plugin", "version": "1.10.0", diff --git a/psalm.xml b/psalm.xml index 4682e7e6..71f01eb7 100644 --- a/psalm.xml +++ b/psalm.xml @@ -11,15 +11,31 @@ + + + - - - + + + + + + + + + + + + + + + - + + diff --git a/src/DetectChanges/BCBreak/FunctionBased/FunctionBased.php b/src/DetectChanges/BCBreak/FunctionBased/FunctionBased.php index ced4e469..5fd756c2 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/FunctionBased.php +++ b/src/DetectChanges/BCBreak/FunctionBased/FunctionBased.php @@ -11,10 +11,10 @@ interface FunctionBased { /** - * @template T of ReflectionMethod|ReflectionFunction - * * @param T $fromFunction * @param T $toFunction + * + * @template T of ReflectionMethod|ReflectionFunction */ public function __invoke( ReflectionMethod|ReflectionFunction $fromFunction, diff --git a/src/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunction.php b/src/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunction.php index 3753b87e..d31a4893 100644 --- a/src/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunction.php +++ b/src/DetectChanges/BCBreak/FunctionBased/MultipleChecksOnAFunction.php @@ -27,12 +27,12 @@ public function __invoke( } /** - * @template T of ReflectionMethod|ReflectionFunction - * * @param T $fromFunction * @param T $toFunction * * @return iterable + * + * @template T of ReflectionMethod|ReflectionFunction */ private function multipleChecks( ReflectionMethod|ReflectionFunction $fromFunction, diff --git a/src/DetectChanges/BCBreak/PropertyBased/PropertyTypeChanged.php b/src/DetectChanges/BCBreak/PropertyBased/PropertyTypeChanged.php index cf0336dd..05c82e5d 100644 --- a/src/DetectChanges/BCBreak/PropertyBased/PropertyTypeChanged.php +++ b/src/DetectChanges/BCBreak/PropertyBased/PropertyTypeChanged.php @@ -5,7 +5,6 @@ namespace Roave\BackwardCompatibility\DetectChanges\BCBreak\PropertyBased; use Psl\Str; -use Psl\Vec; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\Changes; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; @@ -13,8 +12,6 @@ use Roave\BackwardCompatibility\Formatter\ReflectionPropertyName; use Roave\BetterReflection\Reflection\ReflectionProperty; -use function array_merge; - /** * Type declarations for properties are invariant: you can't restrict the type because the consumer may * write invalid values to it, and you cannot widen the type because the consumer may expect a specific diff --git a/src/Git/CheckedOutRepository.php b/src/Git/CheckedOutRepository.php index c00faf4d..35cce718 100644 --- a/src/Git/CheckedOutRepository.php +++ b/src/Git/CheckedOutRepository.php @@ -9,9 +9,7 @@ final class CheckedOutRepository { - private string $path; - - private function __construct() + private function __construct(private string $path) { } @@ -19,10 +17,7 @@ public static function fromPath(string $path): self { Psl\invariant(Filesystem\is_directory($path . '/.git'), 'Directory "%s" is not a GIT repository.', $path); - $instance = new self(); - $instance->path = $path; - - return $instance; + return new self($path); } public function __toString(): string diff --git a/src/Git/Revision.php b/src/Git/Revision.php index 0f340c89..20146acb 100644 --- a/src/Git/Revision.php +++ b/src/Git/Revision.php @@ -7,12 +7,12 @@ use Psl; use Psl\Regex; use Psl\Str; +use Psl\Type; final class Revision { - private string $sha1; - - private function __construct() + /** @param non-empty-string $sha1 */ + private function __construct(private string $sha1) { } @@ -20,10 +20,10 @@ public static function fromSha1(string $sha1): self { Psl\invariant(Regex\matches($sha1, '/^[a-zA-Z0-9]{40}$/'), 'Invalid SHA1 hash.'); - $instance = new self(); - $instance->sha1 = Str\trim_right($sha1); - - return $instance; + return new self( + Type\non_empty_string() + ->assert(Str\trim_right($sha1)) + ); } public function __toString(): string diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/AncestorRemovedTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/AncestorRemovedTest.php index 58ee700b..10c369d8 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/AncestorRemovedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/AncestorRemovedTest.php @@ -132,14 +132,11 @@ class ClassWithInvertedInterfaceNames implements IG, IE {} return array_combine( array_keys($classes), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($className), - $toReflector->reflectClass($className), - $errors, - ]; - }, + static fn (string $className, array $errors): array => [ + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), + $errors, + ], array_keys($classes), $classes ) diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameAbstractTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameAbstractTest.php index f8c41c6a..6bc700ac 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameAbstractTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameAbstractTest.php @@ -99,14 +99,11 @@ interface AbstractToInterface {} return array_combine( array_keys($classes), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($className), - $toReflector->reflectClass($className), - $errors, - ]; - }, + static fn (string $className, array $errors): array => [ + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), + $errors, + ], array_keys($classes), $classes ) diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInterfaceTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInterfaceTest.php index 214b32b0..9635d4cc 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInterfaceTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameInterfaceTest.php @@ -105,14 +105,11 @@ trait TraitToTrait {} return array_combine( array_keys($classes), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($className), - $toReflector->reflectClass($className), - $errors, - ]; - }, + static fn (string $className, array $errors): array => [ + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), + $errors, + ], array_keys($classes), $classes ) diff --git a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameTraitTest.php b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameTraitTest.php index 742843d9..ad5868ba 100644 --- a/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameTraitTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassBased/ClassBecameTraitTest.php @@ -108,14 +108,11 @@ trait TraitToTrait {} return array_combine( array_keys($classes), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($className), - $toReflector->reflectClass($className), - $errors, - ]; - }, + static fn (string $className, array $errors): array => [ + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), + $errors, + ], array_keys($classes), $classes ) diff --git a/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantValueChangedTest.php b/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantValueChangedTest.php index 672f9680..601c2c9c 100644 --- a/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantValueChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantValueChangedTest.php @@ -5,6 +5,7 @@ namespace RoaveTest\BackwardCompatibility\DetectChanges\BCBreak\ClassConstantBased; use PHPUnit\Framework\TestCase; +use Psl\Type; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassConstantBased\ClassConstantValueChanged; use Roave\BetterReflection\BetterReflection; @@ -25,7 +26,7 @@ final class ClassConstantValueChangedTest extends TestCase /** * @param string[] $expectedMessages * - * @dataProvider propertiesToBeTested + * @dataProvider constantsToBeTested */ public function testDiffs( ReflectionClassConstant $fromConstant, @@ -43,10 +44,13 @@ public function testDiffs( } /** - * @return array>> - * @psalm-return array}> + * @return array + * }> */ - public function propertiesToBeTested(): array + public function constantsToBeTested(): array { $astLocator = (new BetterReflection())->astLocator(); @@ -123,14 +127,13 @@ class TheClass { return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $constant, array $errorMessages) use ($fromClass, $toClass): array { - return [ - $fromClass->getReflectionConstant($constant), - $toClass->getReflectionConstant($constant), - $errorMessages, - ]; - }, + static fn (string $constant, array $errorMessages): array => [ + Type\object(ReflectionClassConstant::class) + ->coerce($fromClass->getReflectionConstant($constant)), + Type\object(ReflectionClassConstant::class) + ->coerce($toClass->getReflectionConstant($constant)), + $errorMessages, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantVisibilityReducedTest.php b/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantVisibilityReducedTest.php index 4390be42..da921ad4 100644 --- a/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantVisibilityReducedTest.php +++ b/test/unit/DetectChanges/BCBreak/ClassConstantBased/ClassConstantVisibilityReducedTest.php @@ -5,13 +5,13 @@ namespace RoaveTest\BackwardCompatibility\DetectChanges\BCBreak\ClassConstantBased; use PHPUnit\Framework\TestCase; +use Psl\Type; use Roave\BackwardCompatibility\Change; use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassConstantBased\ClassConstantVisibilityReduced; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionClassConstant; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; -use RoaveTest\BackwardCompatibility\TypeRestriction; use function array_map; use function iterator_to_array; use function array_combine; @@ -22,7 +22,7 @@ final class ClassConstantVisibilityReducedTest extends TestCase { /** - * @dataProvider propertiesToBeTested + * @dataProvider constantsToBeTested * * @param string[] $expectedMessages */ @@ -42,11 +42,13 @@ public function testDiffs( } /** - * @return array>> - * - * @psalm-return array}> + * @return array + * }> */ - public function propertiesToBeTested() : array + public function constantsToBeTested() : array { $astLocator = (new BetterReflection())->astLocator(); @@ -117,14 +119,13 @@ class TheClass { return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - function (string $constant, array $errorMessages) use ($fromClass, $toClass) : array { - return [ - $fromClass->getReflectionConstant($constant), - $toClass->getReflectionConstant($constant), - $errorMessages, - ]; - }, + static fn (string $constant, array $errorMessages): array => [ + Type\object(ReflectionClassConstant::class) + ->coerce($fromClass->getReflectionConstant($constant)), + Type\object(ReflectionClassConstant::class) + ->coerce($toClass->getReflectionConstant($constant)), + $errorMessages, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php index f9775dd7..0f66d491 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/FunctionBecameInternalTest.php @@ -95,14 +95,11 @@ function d() {} return array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $function, array $errorMessages) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php index c40172a3..aa34aad0 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterByReferenceChangedTest.php @@ -123,14 +123,11 @@ function changed2(& $a) {} array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php index 42b60d40..65986603 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterDefaultValueChangedTest.php @@ -123,14 +123,11 @@ function changed2($a = 2) {} array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php index 674741b2..29b6ce70 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php @@ -156,14 +156,11 @@ function changed2(int $a, int $b) {} array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php index c2ab8f6e..3911514f 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php @@ -157,14 +157,11 @@ function changed2(int $a, int $b) {} array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php index 3b896c83..e0c7ae38 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/RequiredParameterAmountIncreasedTest.php @@ -128,14 +128,11 @@ function changed2($a, $b, $c, $d) {} array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php index 7f251006..9e0d5ca1 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeByReferenceChangedTest.php @@ -114,14 +114,11 @@ function & changed2() {} array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php index 75c6b9c4..b0ee7598 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php @@ -152,14 +152,11 @@ function changed2() {} array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php index 51989efc..e334f694 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php @@ -153,14 +153,11 @@ function changed2() {} array_combine( array_keys($functions), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $function, array $errorMessages) use ($fromReflector, $toReflector) : array { - return [ - $fromReflector->reflectFunction($function), - $toReflector->reflectFunction($function), - $errorMessages, - ]; - }, + static fn (string $function, array $errors): array => [ + $fromReflector->reflectFunction($function), + $toReflector->reflectFunction($function), + $errors, + ], array_keys($functions), $functions ) diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrorsTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrorsTest.php index b42656d4..b5ff7c13 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrorsTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/SkipFunctionBasedErrorsTest.php @@ -11,8 +11,8 @@ use Roave\BackwardCompatibility\Changes; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\FunctionBased; use Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased\SkipFunctionBasedErrors; - use Roave\BetterReflection\Reflection\ReflectionFunction; + use function uniqid; /** diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/AncestorRemovedTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/AncestorRemovedTest.php index 5a3da30d..b03a4401 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/AncestorRemovedTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/AncestorRemovedTest.php @@ -98,14 +98,11 @@ interface ParentInterfaceOrderSwapped extends ID, IA {} return array_combine( array_keys($interfaces), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $interfaceName, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($interfaceName), - $toReflector->reflectClass($interfaceName), - $errors, - ]; - }, + static fn (string $interfaceName, array $errors): array => [ + $fromReflector->reflectClass($interfaceName), + $toReflector->reflectClass($interfaceName), + $errors, + ], array_keys($interfaces), $interfaces ) diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameClassTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameClassTest.php index 91319f5f..71202467 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameClassTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameClassTest.php @@ -105,14 +105,11 @@ trait TraitToTrait {} return array_combine( array_keys($classes), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($className), - $toReflector->reflectClass($className), - $errors, - ]; - }, + static fn (string $interfaceName, array $errors): array => [ + $fromReflector->reflectClass($interfaceName), + $toReflector->reflectClass($interfaceName), + $errors, + ], array_keys($classes), $classes ) diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameTraitTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameTraitTest.php index ce18c5d2..ce9fc26e 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameTraitTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/InterfaceBecameTraitTest.php @@ -105,14 +105,11 @@ trait TraitToTrait {} return array_combine( array_keys($classes), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($className), - $toReflector->reflectClass($className), - $errors, - ]; - }, + static fn (string $interfaceName, array $errors): array => [ + $fromReflector->reflectClass($interfaceName), + $toReflector->reflectClass($interfaceName), + $errors, + ], array_keys($classes), $classes ) diff --git a/test/unit/DetectChanges/BCBreak/InterfaceBased/MethodAddedTest.php b/test/unit/DetectChanges/BCBreak/InterfaceBased/MethodAddedTest.php index 39ae7912..f686aba5 100644 --- a/test/unit/DetectChanges/BCBreak/InterfaceBased/MethodAddedTest.php +++ b/test/unit/DetectChanges/BCBreak/InterfaceBased/MethodAddedTest.php @@ -119,15 +119,11 @@ public function c() {} return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errorMessages) use ($fromClassReflector, $toClassReflector - ): array { - return [ - $fromClassReflector->reflectClass($className), - $toClassReflector->reflectClass($className), - $errorMessages, - ]; - }, + static fn (string $className, array $errors): array => [ + $fromClassReflector->reflectClass($className), + $toClassReflector->reflectClass($className), + $errors, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/MethodBecameFinalTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/MethodBecameFinalTest.php index c500a631..3f3e5f45 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/MethodBecameFinalTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/MethodBecameFinalTest.php @@ -125,14 +125,11 @@ private final function privateFinalToFinal() {} return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $methodName, array $errorMessages) use ($fromClass, $toClass): array { - return [ - $fromClass->getMethod($methodName), - $toClass->getMethod($methodName), - $errorMessages, - ]; - }, + static fn (string $methodName, array $errors): array => [ + $fromClass->getMethod($methodName), + $toClass->getMethod($methodName), + $errors, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/MethodConcretenessChangedTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/MethodConcretenessChangedTest.php index 79d31515..15d70a1f 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/MethodConcretenessChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/MethodConcretenessChangedTest.php @@ -125,14 +125,11 @@ private abstract function privateAbstractToAbstract() {} return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $methodName, array $errorMessages) use ($fromClass, $toClass): array { - return [ - $fromClass->getMethod($methodName), - $toClass->getMethod($methodName), - $errorMessages, - ]; - }, + static fn (string $methodName, array $errors): array => [ + $fromClass->getMethod($methodName), + $toClass->getMethod($methodName), + $errors, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/MethodScopeChangedTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/MethodScopeChangedTest.php index e622d456..14d15e9a 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/MethodScopeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/MethodScopeChangedTest.php @@ -125,14 +125,11 @@ private static function privateStaticToStatic() {} return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $methodName, array $errorMessages) use ($fromClass, $toClass): array { - return [ - $fromClass->getMethod($methodName), - $toClass->getMethod($methodName), - $errorMessages, - ]; - }, + static fn (string $methodName, array $errors): array => [ + $fromClass->getMethod($methodName), + $toClass->getMethod($methodName), + $errors, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/MethodBased/MethodVisibilityReducedTest.php b/test/unit/DetectChanges/BCBreak/MethodBased/MethodVisibilityReducedTest.php index a2298a82..1d69bd4b 100644 --- a/test/unit/DetectChanges/BCBreak/MethodBased/MethodVisibilityReducedTest.php +++ b/test/unit/DetectChanges/BCBreak/MethodBased/MethodVisibilityReducedTest.php @@ -111,14 +111,11 @@ public function privateIncreasedToPublic() {} return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $method, array $errorMessages) use ($fromClass, $toClass): array { - return [ - $fromClass->getMethod($method), - $toClass->getMethod($method), - $errorMessages, - ]; - }, + static fn (string $methodName, array $errors): array => [ + $fromClass->getMethod($methodName), + $toClass->getMethod($methodName), + $errors, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyBecameInternalTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyBecameInternalTest.php index 37e79b9c..b6162a82 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyBecameInternalTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyBecameInternalTest.php @@ -100,14 +100,11 @@ class TheClass { return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $property, array $errorMessages) use ($fromClass, $toClass): array { - return [ - TypeRestriction::object($fromClass->getProperty($property)), - TypeRestriction::object($toClass->getProperty($property)), - $errorMessages, - ]; - }, + static fn (string $property, array $errorMessages): array => [ + TypeRestriction::object($fromClass->getProperty($property)), + TypeRestriction::object($toClass->getProperty($property)), + $errorMessages, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDefaultValueChangedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDefaultValueChangedTest.php index bf65aabd..9e09d8a2 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDefaultValueChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyDefaultValueChangedTest.php @@ -142,14 +142,11 @@ class TheClass { return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $property, array $errorMessages) use ($fromClass, $toClass): array { - return [ - TypeRestriction::object($fromClass->getProperty($property)), - TypeRestriction::object($toClass->getProperty($property)), - $errorMessages, - ]; - }, + static fn (string $property, array $errorMessages): array => [ + TypeRestriction::object($fromClass->getProperty($property)), + TypeRestriction::object($toClass->getProperty($property)), + $errorMessages, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyScopeChangedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyScopeChangedTest.php index b9a80346..ced1d786 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyScopeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyScopeChangedTest.php @@ -126,14 +126,11 @@ class TheClass { return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $property, array $errorMessages) use ($fromClass, $toClass): array { - return [ - TypeRestriction::object($fromClass->getProperty($property)), - TypeRestriction::object($toClass->getProperty($property)), - $errorMessages, - ]; - }, + static fn (string $property, array $errorMessages): array => [ + TypeRestriction::object($fromClass->getProperty($property)), + TypeRestriction::object($toClass->getProperty($property)), + $errorMessages, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyTypeChangedTest.php index a2ea72c1..7024d24f 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyTypeChangedTest.php @@ -242,14 +242,11 @@ class TheClass { return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $property, array $errorMessages) use ($fromClass, $toClass): array { - return [ - TypeRestriction::object($fromClass->getProperty($property)), - TypeRestriction::object($toClass->getProperty($property)), - $errorMessages, - ]; - }, + static fn (string $property, array $errorMessages): array => [ + TypeRestriction::object($fromClass->getProperty($property)), + TypeRestriction::object($toClass->getProperty($property)), + $errorMessages, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyVisibilityReducedTest.php b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyVisibilityReducedTest.php index 76a49145..f9a5560b 100644 --- a/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyVisibilityReducedTest.php +++ b/test/unit/DetectChanges/BCBreak/PropertyBased/PropertyVisibilityReducedTest.php @@ -111,14 +111,11 @@ class TheClass { return array_combine( array_keys($properties), array_map( - /** @psalm-param list $errorMessages https://github.com/vimeo/psalm/issues/2772 */ - static function (string $property, array $errorMessages) use ($fromClass, $toClass): array { - return [ - TypeRestriction::object($fromClass->getProperty($property)), - TypeRestriction::object($toClass->getProperty($property)), - $errorMessages, - ]; - }, + static fn (string $property, array $errorMessages): array => [ + TypeRestriction::object($fromClass->getProperty($property)), + TypeRestriction::object($toClass->getProperty($property)), + $errorMessages, + ], array_keys($properties), $properties ) diff --git a/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameClassTest.php b/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameClassTest.php index 0fd0d601..37cae936 100644 --- a/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameClassTest.php +++ b/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameClassTest.php @@ -93,14 +93,11 @@ interface InterfaceToInterface {} return array_combine( array_keys($classes), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($className), - $toReflector->reflectClass($className), - $errors, - ]; - }, + static fn (string $className, array $errors): array => [ + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), + $errors, + ], array_keys($classes), $classes ) diff --git a/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameInterfaceTest.php b/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameInterfaceTest.php index bb90af1c..f1f25528 100644 --- a/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameInterfaceTest.php +++ b/test/unit/DetectChanges/BCBreak/TraitBased/TraitBecameInterfaceTest.php @@ -93,14 +93,11 @@ interface InterfaceToInterface {} return array_combine( array_keys($classes), array_map( - /** @psalm-param list $errors https://github.com/vimeo/psalm/issues/2772 */ - static function (string $className, array $errors) use ($fromReflector, $toReflector): array { - return [ - $fromReflector->reflectClass($className), - $toReflector->reflectClass($className), - $errors, - ]; - }, + static fn (string $className, array $errors): array => [ + $fromReflector->reflectClass($className), + $toReflector->reflectClass($className), + $errors, + ], array_keys($classes), $classes ) diff --git a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php index 0c8473db..17f4af2c 100644 --- a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php @@ -9,7 +9,6 @@ use PHPUnit\Framework\TestCase; use Psl\Type; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; -use Roave\BackwardCompatibility\DetectChanges\Variance\TypeWithReflectorScope; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflection\ReflectionProperty; use Roave\BetterReflection\Reflection\ReflectionType; @@ -290,7 +289,7 @@ final class OwnerPropertyContainer { private $owner; } */ public function testContravarianceConsidersNullability(string $type): void { - $reflector = new DefaultReflector(new StringSourceLocator( + $reflector = new DefaultReflector(new StringSourceLocator( <<<'PHP' Date: Sun, 5 Dec 2021 06:22:38 +0100 Subject: [PATCH 08/13] Implemented covariance/contravariance checks for the new `mixed` and `never` types Ref: https://wiki.php.net/rfc/mixed_type_v2 Ref: https://wiki.php.net/rfc/noreturn_type --- .../Variance/TypeIsContravariant.php | 9 +++- .../Variance/TypeIsCovariant.php | 5 ++ .../Variance/TypeIsContravariantTest.php | 42 +++++++++++++++++ .../Variance/TypeIsCovariantTest.php | 47 +++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/DetectChanges/Variance/TypeIsContravariant.php b/src/DetectChanges/Variance/TypeIsContravariant.php index cb62f930..219bb4bf 100644 --- a/src/DetectChanges/Variance/TypeIsContravariant.php +++ b/src/DetectChanges/Variance/TypeIsContravariant.php @@ -23,7 +23,14 @@ public function __invoke( ?ReflectionType $type, ?ReflectionType $comparedType ): bool { - if ($comparedType === null) { + if ( + ($type && $type->__toString() === 'never') + || ($comparedType && $comparedType->__toString() === 'never') + ) { + return false; + } + + if ($comparedType === null || $comparedType->__toString() === 'mixed') { return true; } diff --git a/src/DetectChanges/Variance/TypeIsCovariant.php b/src/DetectChanges/Variance/TypeIsCovariant.php index ef0e9e5c..90b98e31 100644 --- a/src/DetectChanges/Variance/TypeIsCovariant.php +++ b/src/DetectChanges/Variance/TypeIsCovariant.php @@ -50,6 +50,11 @@ public function __invoke( return true; } + if ($typeAsString === 'mixed' || $comparedTypeAsString === 'never') { + // everything is covariant to `mixed` or `never` + return true; + } + if ($typeAsString === 'void') { // nothing is covariant to `void` return false; diff --git a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php index 17f4af2c..99db26e2 100644 --- a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php @@ -19,6 +19,7 @@ use function array_map; use function array_merge; +/** @covers \Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant */ final class TypeIsContravariantTest extends TestCase { /** @@ -80,6 +81,11 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('void'), false, ], + 'scalar type to void type is not covariant - note that void is enforced, and has no substitutes in PHP' => [ + new Identifier('string'), + new Identifier('void'), + false, + ], 'void type to no type is contravariant' => [ new Identifier('void'), null, @@ -95,6 +101,32 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('AClass'), true, ], + 'mixed to no type is contravariant' => [ + new Identifier('mixed'), + null, + true, + ], + 'no type to mixed is contravariant' => [ + null, + new Identifier('mixed'), + true, + ], + + 'never to no type is not contravariant - note that never is enforced, and has no substitutes in PHP' => [ + new Identifier('never'), + null, + false, + ], + 'no type to never is not contravariant - note that never is enforced, and has no substitutes in PHP' => [ + null, + new Identifier('never'), + false, + ], + 'scalar type to never is not contravariant - note that never is enforced, and has no substitutes in PHP' => [ + new Identifier('int'), + new Identifier('never'), + false, + ], 'scalar type to no type is contravariant' => [ new Identifier('string'), null, @@ -155,6 +187,16 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('object'), true, ], + 'mixed to object is not contravariant' => [ + new Identifier('mixed'), + new Identifier('object'), + false, + ], + 'object to mixed is contravariant' => [ + new Identifier('object'), + new Identifier('mixed'), + true, + ], 'class type to scalar type is not contravariant' => [ new Identifier('AClass'), new Identifier('string'), diff --git a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php index 30715959..bb3bbe50 100644 --- a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php @@ -19,6 +19,7 @@ use function array_map; use function array_merge; +/** @covers \Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant */ final class TypeIsCovariantTest extends TestCase { /** @@ -75,6 +76,11 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('void'), true, ], + 'scalar type to void type is not covariant' => [ + new Identifier('string'), + new Identifier('void'), + false, + ], 'void type to no type is not covariant' => [ new Identifier('void'), null, @@ -90,6 +96,32 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('AClass'), false, ], + 'mixed to no type is not covariant' => [ + new Identifier('mixed'), + null, + false, + ], + 'no type to mixed is covariant' => [ + null, + new Identifier('mixed'), + true, + ], + + 'never to no type is not covariant' => [ + new Identifier('never'), + null, + false, + ], + 'no type to never is covariant' => [ + null, + new Identifier('never'), + true, + ], + 'scalar type to never is covariant' => [ + new Identifier('int'), + new Identifier('never'), + true, + ], 'scalar type to no type is not covariant' => [ new Identifier('string'), null, @@ -160,6 +192,16 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('object'), false, ], + 'mixed to object is covariant' => [ + new Identifier('mixed'), + new Identifier('object'), + true, + ], + 'object to mixed is not covariant' => [ + new Identifier('object'), + new Identifier('mixed'), + false, + ], 'class type to scalar type is not covariant' => [ new Identifier('AClass'), @@ -283,6 +325,9 @@ final class OwnerPropertyContainer { private $owner; } [self::identifierType($reflector, $owner, new NullableType(new Identifier($type)))], ], [ + 'mixed', + 'never', + 'void', 'int', 'string', 'float', @@ -290,6 +335,7 @@ final class OwnerPropertyContainer { private $owner; } 'array', 'iterable', 'callable', + 'object', 'Traversable', 'AClass', ] @@ -340,6 +386,7 @@ public function existingNullableTypeStrings(): array ['array'], ['iterable'], ['callable'], + ['object'], ['Traversable'], ['AClass'], ]; From 06ab4f5365ff0e03dd38526423f45ba26cc53cf7 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 Dec 2021 07:39:36 +0100 Subject: [PATCH 09/13] Implemented variance checks for union types Ref: https://wiki.php.net/rfc/union_types_v2 --- .../Variance/TypeIsContravariant.php | 20 ++++++++++ .../Variance/TypeIsCovariant.php | 20 ++++++++++ .../Variance/TypeIsContravariantTest.php | 39 ++++++++++++++++++- .../Variance/TypeIsCovariantTest.php | 39 ++++++++++++++++++- 4 files changed, 116 insertions(+), 2 deletions(-) diff --git a/src/DetectChanges/Variance/TypeIsContravariant.php b/src/DetectChanges/Variance/TypeIsContravariant.php index 219bb4bf..58e81cd5 100644 --- a/src/DetectChanges/Variance/TypeIsContravariant.php +++ b/src/DetectChanges/Variance/TypeIsContravariant.php @@ -8,6 +8,7 @@ use Psl\Str; use Roave\BetterReflection\Reflection\ReflectionNamedType; use Roave\BetterReflection\Reflection\ReflectionType; +use Roave\BetterReflection\Reflection\ReflectionUnionType; /** * This is a simplistic contravariant type check. A more appropriate approach would be to @@ -39,11 +40,30 @@ public function __invoke( return false; } + if ($type instanceof ReflectionUnionType) { + return Iter\all( + $type->getTypes(), + fn (ReflectionNamedType $type): bool => $this($type, $comparedType) + ); + } + + if ($comparedType instanceof ReflectionUnionType) { + return Iter\any( + $comparedType->getTypes(), + fn (ReflectionNamedType $comparedType): bool => $this($type, $comparedType) + ); + } + if (! $type instanceof ReflectionNamedType || ! $comparedType instanceof ReflectionNamedType) { // @TODO we'll assume everyting is fine, for now - union and intersection types still need test additions return true; } + return $this->compareNamedTypes($type, $comparedType); + } + + private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedType $comparedType): bool + { if ($type->allowsNull() && ! $comparedType->allowsNull()) { return false; } diff --git a/src/DetectChanges/Variance/TypeIsCovariant.php b/src/DetectChanges/Variance/TypeIsCovariant.php index 90b98e31..0e2102d5 100644 --- a/src/DetectChanges/Variance/TypeIsCovariant.php +++ b/src/DetectChanges/Variance/TypeIsCovariant.php @@ -8,6 +8,7 @@ use Psl\Str; use Roave\BetterReflection\Reflection\ReflectionNamedType; use Roave\BetterReflection\Reflection\ReflectionType; +use Roave\BetterReflection\Reflection\ReflectionUnionType; use Traversable; /** @@ -34,11 +35,30 @@ public function __invoke( return false; } + if ($comparedType instanceof ReflectionUnionType) { + return Iter\all( + $comparedType->getTypes(), + fn (ReflectionNamedType $comparedType): bool => $this($type, $comparedType) + ); + } + + if ($type instanceof ReflectionUnionType) { + return Iter\any( + $type->getTypes(), + fn (ReflectionNamedType $type): bool => $this($type, $comparedType) + ); + } + if (! $type instanceof ReflectionNamedType || ! $comparedType instanceof ReflectionNamedType) { // @TODO we'll assume everyting is fine, for now - union and intersection types still need test additions return true; } + return $this->compareNamedTypes($type, $comparedType); + } + + private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedType $comparedType): bool + { if ($comparedType->allowsNull() && ! $type->allowsNull()) { return false; } diff --git a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php index 99db26e2..ff73b183 100644 --- a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php @@ -6,6 +6,7 @@ use PhpParser\Node\Identifier; use PhpParser\Node\NullableType; +use PhpParser\Node\UnionType; use PHPUnit\Framework\TestCase; use Psl\Type; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; @@ -257,6 +258,42 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('Iterator'), false, ], + + 'scalar type to union type is contravariant' => [ + new Identifier('int'), + new UnionType([new Identifier('int'), new Identifier('string')]), + true, + ], + 'union type to scalar is not contravariant' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new Identifier('int'), + false, + ], + 'same union type is contravariant' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new UnionType([new Identifier('int'), new Identifier('string')]), + true, + ], + 'same union type (in reverse order) is covariant' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new UnionType([new Identifier('string'), new Identifier('int')]), + true, + ], + 'incompatible union types are not contravariant' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new UnionType([new Identifier('float'), new Identifier('bool')]), + false, + ], + 'union type to wider union type is contravariant - https://3v4l.org/jO1eE#v8.1rc3' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new UnionType([new Identifier('int'), new Identifier('string'), new Identifier('float')]), + true, + ], + 'union type to narrower union type is not contravariant - https://3v4l.org/SOUBk#v8.1rc3' => [ + new UnionType([new Identifier('int'), new Identifier('string'), new Identifier('float')]), + new UnionType([new Identifier('int'), new Identifier('string')]), + false, + ], ]; return array_map( @@ -377,7 +414,7 @@ public function existingNullableTypeStrings(): array private static function identifierType( Reflector $reflector, ReflectionProperty $owner, - Identifier|NullableType $identifier + Identifier|NullableType|UnionType $identifier ): ReflectionType { return ReflectionType::createFromNode($reflector, $owner, $identifier); } diff --git a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php index bb3bbe50..8464ca39 100644 --- a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php @@ -6,6 +6,7 @@ use PhpParser\Node\Identifier; use PhpParser\Node\NullableType; +use PhpParser\Node\UnionType; use PHPUnit\Framework\TestCase; use Psl\Type; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; @@ -268,6 +269,42 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('Iterator'), true, ], + + 'scalar type to union type is not covariant' => [ + new Identifier('int'), + new UnionType([new Identifier('int'), new Identifier('string')]), + false, + ], + 'union type to scalar is covariant' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new Identifier('int'), + true, + ], + 'same union type is covariant' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new UnionType([new Identifier('int'), new Identifier('string')]), + true, + ], + 'same union type (in reverse order) is covariant' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new UnionType([new Identifier('string'), new Identifier('int')]), + true, + ], + 'incompatible union types are not covariant' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new UnionType([new Identifier('float'), new Identifier('bool')]), + false, + ], + 'union type to wider union type is not covariant - https://3v4l.org/Tudl8#v8.1rc3' => [ + new UnionType([new Identifier('int'), new Identifier('string')]), + new UnionType([new Identifier('int'), new Identifier('string'), new Identifier('float')]), + false, + ], + 'union type to narrower union type is covariant - https://3v4l.org/RB2fC#v8.1rc3' => [ + new UnionType([new Identifier('int'), new Identifier('string'), new Identifier('float')]), + new UnionType([new Identifier('int'), new Identifier('string')]), + true, + ], ]; return array_map( @@ -395,7 +432,7 @@ public function existingNullableTypeStrings(): array private static function identifierType( Reflector $reflector, ReflectionProperty $owner, - Identifier|NullableType $identifier + Identifier|NullableType|UnionType $identifier ): ReflectionType { return ReflectionType::createFromNode($reflector, $owner, $identifier); } From 9714b6f1afd865b44143f361d563527faea9d985 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 Dec 2021 08:03:49 +0100 Subject: [PATCH 10/13] Implemented variance checks for intersection types Ref: https://wiki.php.net/rfc/pure-intersection-types --- .../Variance/TypeIsContravariant.php | 23 ++++--- .../Variance/TypeIsCovariant.php | 27 +++++--- .../Variance/TypeIsContravariantTest.php | 63 ++++++++++++++++--- .../Variance/TypeIsCovariantTest.php | 63 ++++++++++++++++--- 4 files changed, 140 insertions(+), 36 deletions(-) diff --git a/src/DetectChanges/Variance/TypeIsContravariant.php b/src/DetectChanges/Variance/TypeIsContravariant.php index 58e81cd5..3a09ea03 100644 --- a/src/DetectChanges/Variance/TypeIsContravariant.php +++ b/src/DetectChanges/Variance/TypeIsContravariant.php @@ -6,8 +6,8 @@ use Psl\Iter; use Psl\Str; +use Roave\BetterReflection\Reflection\ReflectionIntersectionType; use Roave\BetterReflection\Reflection\ReflectionNamedType; -use Roave\BetterReflection\Reflection\ReflectionType; use Roave\BetterReflection\Reflection\ReflectionUnionType; /** @@ -15,14 +15,12 @@ * have a `$type->includes($otherType)` check with actual types represented as value objects, * but that is a massive piece of work that should be done by importing an external library * instead, if this class no longer suffices. - * - * @TODO introduce union/intersection type support here */ final class TypeIsContravariant { public function __invoke( - ?ReflectionType $type, - ?ReflectionType $comparedType + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $type, + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $comparedType ): bool { if ( ($type && $type->__toString() === 'never') @@ -54,9 +52,18 @@ public function __invoke( ); } - if (! $type instanceof ReflectionNamedType || ! $comparedType instanceof ReflectionNamedType) { - // @TODO we'll assume everyting is fine, for now - union and intersection types still need test additions - return true; + if ($comparedType instanceof ReflectionIntersectionType) { + return Iter\all( + $comparedType->getTypes(), + fn (ReflectionNamedType $comparedType): bool => $this($type, $comparedType) + ); + } + + if ($type instanceof ReflectionIntersectionType) { + return Iter\any( + $type->getTypes(), + fn (ReflectionNamedType $type): bool => $this($type, $comparedType) + ); } return $this->compareNamedTypes($type, $comparedType); diff --git a/src/DetectChanges/Variance/TypeIsCovariant.php b/src/DetectChanges/Variance/TypeIsCovariant.php index 0e2102d5..6f54de96 100644 --- a/src/DetectChanges/Variance/TypeIsCovariant.php +++ b/src/DetectChanges/Variance/TypeIsCovariant.php @@ -6,8 +6,8 @@ use Psl\Iter; use Psl\Str; +use Roave\BetterReflection\Reflection\ReflectionIntersectionType; use Roave\BetterReflection\Reflection\ReflectionNamedType; -use Roave\BetterReflection\Reflection\ReflectionType; use Roave\BetterReflection\Reflection\ReflectionUnionType; use Traversable; @@ -16,14 +16,12 @@ * have a `$type->includes($otherType)` check with actual types represented as value objects, * but that is a massive piece of work that should be done by importing an external library * instead, if this class no longer suffices. - * - * @TODO introduce union/intersection type support here */ final class TypeIsCovariant { public function __invoke( - ?ReflectionType $type, - ?ReflectionType $comparedType + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $type, + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $comparedType ): bool { if ($type === null) { // everything can be covariant to `mixed` @@ -35,6 +33,20 @@ public function __invoke( return false; } + if ($type instanceof ReflectionIntersectionType) { + return Iter\all( + $type->getTypes(), + fn (ReflectionNamedType $type): bool => $this($type, $comparedType) + ); + } + + if ($comparedType instanceof ReflectionIntersectionType) { + return Iter\any( + $comparedType->getTypes(), + fn (ReflectionNamedType $comparedType): bool => $this($type, $comparedType) + ); + } + if ($comparedType instanceof ReflectionUnionType) { return Iter\all( $comparedType->getTypes(), @@ -49,11 +61,6 @@ public function __invoke( ); } - if (! $type instanceof ReflectionNamedType || ! $comparedType instanceof ReflectionNamedType) { - // @TODO we'll assume everyting is fine, for now - union and intersection types still need test additions - return true; - } - return $this->compareNamedTypes($type, $comparedType); } diff --git a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php index ff73b183..d616a2f2 100644 --- a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php @@ -5,14 +5,18 @@ namespace RoaveTest\BackwardCompatibility\DetectChanges\Variance; use PhpParser\Node\Identifier; +use PhpParser\Node\IntersectionType; use PhpParser\Node\NullableType; use PhpParser\Node\UnionType; use PHPUnit\Framework\TestCase; use Psl\Type; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsContravariant; use Roave\BetterReflection\BetterReflection; +use Roave\BetterReflection\Reflection\ReflectionIntersectionType; +use Roave\BetterReflection\Reflection\ReflectionNamedType; use Roave\BetterReflection\Reflection\ReflectionProperty; use Roave\BetterReflection\Reflection\ReflectionType; +use Roave\BetterReflection\Reflection\ReflectionUnionType; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\Reflector\Reflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; @@ -27,8 +31,8 @@ final class TypeIsContravariantTest extends TestCase * @dataProvider checkedTypes */ public function testContravariance( - ?ReflectionType $type, - ?ReflectionType $newType, + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $type, + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $newType, bool $expectedToBeContravariant ): void { self::assertSame( @@ -39,8 +43,8 @@ public function testContravariance( /** * @return array */ @@ -54,6 +58,10 @@ interface Traversable {} interface Iterator extends Traversable {} interface AnInterface {} interface AnotherInterface {} +interface A {} +interface B {} +interface C {} +interface D {} class AnotherClass implements AnInterface {} class AnotherClassWithMultipleInterfaces implements AnInterface, AnotherInterface {} class AClass {} @@ -294,6 +302,42 @@ final class OwnerPropertyContainer { private $owner; } new UnionType([new Identifier('int'), new Identifier('string')]), false, ], + + 'object type to intersection type is not contravariant' => [ + new Identifier('A'), + new IntersectionType([new Identifier('A'), new Identifier('B')]), + false, + ], + 'intersection type to object type is contravariant' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new Identifier('A'), + true, + ], + 'same intersection type is contravariant' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new IntersectionType([new Identifier('A'), new Identifier('B')]), + true, + ], + 'same intersection type (in reverse order) is contravariant' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new IntersectionType([new Identifier('B'), new Identifier('A')]), + true, + ], + 'incompatible intersection types are not contravariant' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new IntersectionType([new Identifier('C'), new Identifier('D')]), + false, + ], + 'intersection type to stricter intersection type is not contravariant - https://3v4l.org/pjnRe#v8.1rc3' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new IntersectionType([new Identifier('A'), new Identifier('B'), new Identifier('C')]), + false, + ], + 'intersection type to less specific intersection type is contravariant - https://3v4l.org/2s8CW#v8.1rc3' => [ + new IntersectionType([new Identifier('A'), new Identifier('B'), new Identifier('C')]), + new IntersectionType([new Identifier('A'), new Identifier('B')]), + true, + ], ]; return array_map( @@ -313,14 +357,15 @@ final class OwnerPropertyContainer { private $owner; } /** * @dataProvider existingTypes */ - public function testContravarianceConsidersSameTypeAlwaysContravariant(?ReflectionType $type): void - { + public function testContravarianceConsidersSameTypeAlwaysContravariant( + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $type + ): void { self::assertTrue( (new TypeIsContravariant())($type, $type) ); } - /** @return list */ + /** @return list */ public function existingTypes(): array { $reflector = new DefaultReflector(new StringSourceLocator( @@ -414,8 +459,8 @@ public function existingNullableTypeStrings(): array private static function identifierType( Reflector $reflector, ReflectionProperty $owner, - Identifier|NullableType|UnionType $identifier - ): ReflectionType { + Identifier|NullableType|UnionType|IntersectionType $identifier + ): ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType { return ReflectionType::createFromNode($reflector, $owner, $identifier); } } diff --git a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php index 8464ca39..18a35979 100644 --- a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php @@ -5,14 +5,18 @@ namespace RoaveTest\BackwardCompatibility\DetectChanges\Variance; use PhpParser\Node\Identifier; +use PhpParser\Node\IntersectionType; use PhpParser\Node\NullableType; use PhpParser\Node\UnionType; use PHPUnit\Framework\TestCase; use Psl\Type; use Roave\BackwardCompatibility\DetectChanges\Variance\TypeIsCovariant; use Roave\BetterReflection\BetterReflection; +use Roave\BetterReflection\Reflection\ReflectionIntersectionType; +use Roave\BetterReflection\Reflection\ReflectionNamedType; use Roave\BetterReflection\Reflection\ReflectionProperty; use Roave\BetterReflection\Reflection\ReflectionType; +use Roave\BetterReflection\Reflection\ReflectionUnionType; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\Reflector\Reflector; use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator; @@ -27,8 +31,8 @@ final class TypeIsCovariantTest extends TestCase * @dataProvider checkedTypes */ public function testCovariance( - ?ReflectionType $type, - ?ReflectionType $newType, + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $type, + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $newType, bool $expectedToBeContravariant ): void { self::assertSame( @@ -39,8 +43,8 @@ public function testCovariance( /** * @return array */ @@ -54,6 +58,10 @@ interface Traversable {} interface Iterator extends Traversable {} interface AnInterface {} interface AnotherInterface {} +interface A {} +interface B {} +interface C {} +interface D {} class AnotherClass implements AnInterface {} class AnotherClassWithMultipleInterfaces implements AnInterface, AnotherInterface {} class AClass {} @@ -305,6 +313,42 @@ final class OwnerPropertyContainer { private $owner; } new UnionType([new Identifier('int'), new Identifier('string')]), true, ], + + 'object type to intersection type is covariant' => [ + new Identifier('A'), + new IntersectionType([new Identifier('A'), new Identifier('B')]), + true, + ], + 'intersection type to object type is not covariant' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new Identifier('A'), + false, + ], + 'same intersection type is covariant' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new IntersectionType([new Identifier('A'), new Identifier('B')]), + true, + ], + 'same intersection type (in reverse order) is covariant' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new IntersectionType([new Identifier('B'), new Identifier('A')]), + true, + ], + 'incompatible intersection types are not covariant' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new IntersectionType([new Identifier('C'), new Identifier('D')]), + false, + ], + 'intersection type to stricter intersection type is covariant - https://3v4l.org/NoV52#v8.1rc3' => [ + new IntersectionType([new Identifier('A'), new Identifier('B')]), + new IntersectionType([new Identifier('A'), new Identifier('B'), new Identifier('C')]), + true, + ], + 'intersection type to less specific intersection type is not covariant - https://3v4l.org/8FSuK#v8.1rc3' => [ + new IntersectionType([new Identifier('A'), new Identifier('B'), new Identifier('C')]), + new IntersectionType([new Identifier('A'), new Identifier('B')]), + false, + ], ]; return array_map( @@ -324,15 +368,16 @@ final class OwnerPropertyContainer { private $owner; } /** * @dataProvider existingTypes */ - public function testCovarianceConsidersSameTypeAlwaysCovariant(?ReflectionType $type): void - { + public function testCovarianceConsidersSameTypeAlwaysCovariant( + ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType|null $type + ): void { self::assertTrue( (new TypeIsCovariant())($type, $type) ); } /** - * @return list + * @return list */ public function existingTypes(): array { @@ -432,8 +477,8 @@ public function existingNullableTypeStrings(): array private static function identifierType( Reflector $reflector, ReflectionProperty $owner, - Identifier|NullableType|UnionType $identifier - ): ReflectionType { + Identifier|NullableType|UnionType|IntersectionType $identifier + ): ReflectionIntersectionType|ReflectionUnionType|ReflectionNamedType { return ReflectionType::createFromNode($reflector, $owner, $identifier); } } From ace329f5c35bf77ccd862302fc909b7fbc2f6a48 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 Dec 2021 11:28:57 +0100 Subject: [PATCH 11/13] Added tests for nullability + union types variance checks This change strictly depends on https://github.com/Roave/BetterReflection/pull/902, and once that's merged, new `infection/infection` mutations should appear, showing us code that can safely be removed. --- .../Variance/TypeIsCovariant.php | 12 ++- .../ParameterTypeChangedTest.php | 4 +- ...ParameterTypeContravarianceChangedTest.php | 4 +- .../FunctionBased/ReturnTypeChangedTest.php | 2 +- .../ReturnTypeCovarianceChangedTest.php | 2 +- .../Variance/TypeIsContravariantTest.php | 30 ++++++ .../Variance/TypeIsCovariantTest.php | 92 +++++++++++++------ 7 files changed, 109 insertions(+), 37 deletions(-) diff --git a/src/DetectChanges/Variance/TypeIsCovariant.php b/src/DetectChanges/Variance/TypeIsCovariant.php index 6f54de96..a538efb1 100644 --- a/src/DetectChanges/Variance/TypeIsCovariant.php +++ b/src/DetectChanges/Variance/TypeIsCovariant.php @@ -66,7 +66,7 @@ public function __invoke( private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedType $comparedType): bool { - if ($comparedType->allowsNull() && ! $type->allowsNull()) { + if (self::allowsNull($comparedType) && ! self::allowsNull($type)) { return false; } @@ -77,6 +77,10 @@ private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedTyp return true; } + if ($comparedTypeAsString === 'null' && self::allowsNull($type)) { + return true; + } + if ($typeAsString === 'mixed' || $comparedTypeAsString === 'never') { // everything is covariant to `mixed` or `never` return true; @@ -128,4 +132,10 @@ private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedTyp $originalTypeReflectionClass->getName() ); } + + private static function allowsNull(ReflectionNamedType $type): bool + { + return $type->allowsNull() + || $type->__toString() === 'null'; + } } diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php index 29b6ce70..bbdc73c3 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeChangedTest.php @@ -146,8 +146,8 @@ function changed2(int $a, int $b) {} ], 'N2\untouched' => [], 'N3\changed' => [ - '[BC] CHANGED: The parameter $a of N3\changed() changed from ?int to int', - '[BC] CHANGED: The parameter $b of N3\changed() changed from ?int to int', + '[BC] CHANGED: The parameter $a of N3\changed() changed from int|null to int', + '[BC] CHANGED: The parameter $b of N3\changed() changed from int|null to int', ], 'N3\untouched' => [], ]; diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php index 3911514f..f9563bb4 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ParameterTypeContravarianceChangedTest.php @@ -147,8 +147,8 @@ function changed2(int $a, int $b) {} ], 'N2\untouched' => [], 'N3\changed' => [ - '[BC] CHANGED: The parameter $a of N3\changed() changed from ?int to a non-contravariant int', - '[BC] CHANGED: The parameter $b of N3\changed() changed from ?int to a non-contravariant int', + '[BC] CHANGED: The parameter $a of N3\changed() changed from int|null to a non-contravariant int', + '[BC] CHANGED: The parameter $b of N3\changed() changed from int|null to a non-contravariant int', ], 'N3\untouched' => [], ]; diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php index b0ee7598..7bf9a54e 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeChangedTest.php @@ -139,7 +139,7 @@ function changed2() {} ], 'N1\untouched' => [], 'N2\changed' => [ - '[BC] CHANGED: The return type of N2\changed() changed from int to ?int', + '[BC] CHANGED: The return type of N2\changed() changed from int to int|null', ], 'N2\untouched' => [], 'N3\changed' => [ diff --git a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php index e334f694..c86f9203 100644 --- a/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php +++ b/test/unit/DetectChanges/BCBreak/FunctionBased/ReturnTypeCovarianceChangedTest.php @@ -140,7 +140,7 @@ function changed2() {} ], 'N1\untouched' => [], 'N2\changed' => [ - '[BC] CHANGED: The return type of N2\changed() changed from int to the non-covariant ?int', + '[BC] CHANGED: The return type of N2\changed() changed from int to the non-covariant int|null', ], 'N2\untouched' => [], 'N3\changed' => [ diff --git a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php index d616a2f2..1b1c6afa 100644 --- a/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsContravariantTest.php @@ -85,6 +85,16 @@ final class OwnerPropertyContainer { private $owner; } null, true, ], + 'nullable type to null is not contravariant - this does not occur in the real world, but is an important base invariant' => [ + new NullableType(new Identifier('AnInterface')), + new Identifier('null'), + false, + ], + 'null to nullable type is covariant - this does not occur in the real world, but is an important base invariant' => [ + new Identifier('null'), + new NullableType(new Identifier('AnInterface')), + true, + ], 'no type to void type is not contravariant' => [ null, new Identifier('void'), @@ -302,6 +312,26 @@ final class OwnerPropertyContainer { private $owner; } new UnionType([new Identifier('int'), new Identifier('string')]), false, ], + 'nullable union type is equivalent to shorthand null definition' => [ + new UnionType([new Identifier('A'), new Identifier('null')]), + new NullableType(new Identifier('A')), + true, + ], + 'shorthand nullable definition is equivalent to nullable union type' => [ + new NullableType(new Identifier('A')), + new UnionType([new Identifier('A'), new Identifier('null')]), + true, + ], + 'shorthand nullable definition to union type with added type is contravariant' => [ + new NullableType(new Identifier('A')), + new UnionType([new Identifier('A'), new Identifier('B'), new Identifier('null')]), + true, + ], + 'nullable union type to shorthand nullable definition is not contravariant' => [ + new UnionType([new Identifier('A'), new Identifier('B'), new Identifier('null')]), + new NullableType(new Identifier('A')), + false, + ], 'object type to intersection type is not contravariant' => [ new Identifier('A'), diff --git a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php index 18a35979..75516283 100644 --- a/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php +++ b/test/unit/DetectChanges/Variance/TypeIsCovariantTest.php @@ -80,53 +80,63 @@ final class OwnerPropertyContainer { private $owner; } ); $types = [ - 'no type to void type is covariant' => [ + 'no type to void type is covariant' => [ null, new Identifier('void'), true, ], - 'scalar type to void type is not covariant' => [ + 'nullable type to null is covariant - this does not occur in the real world, but is an important base invariant' => [ + new NullableType(new Identifier('AnInterface')), + new Identifier('null'), + true, + ], + 'null to nullable type is not covariant - this does not occur in the real world, but is an important base invariant' => [ + new Identifier('null'), + new NullableType(new Identifier('AnInterface')), + false, + ], + 'scalar type to void type is not covariant' => [ new Identifier('string'), new Identifier('void'), false, ], - 'void type to no type is not covariant' => [ + 'void type to no type is not covariant' => [ new Identifier('void'), null, false, ], - 'void type to scalar type is not covariant' => [ + 'void type to scalar type is not covariant' => [ new Identifier('void'), new Identifier('string'), false, ], - 'void type to class type is covariant' => [ + 'void type to class type is covariant' => [ new Identifier('void'), new Identifier('AClass'), false, ], - 'mixed to no type is not covariant' => [ + 'mixed to no type is not covariant' => [ new Identifier('mixed'), null, false, ], - 'no type to mixed is covariant' => [ + 'no type to mixed is covariant' => [ null, new Identifier('mixed'), true, ], - 'never to no type is not covariant' => [ + 'never to no type is not covariant' => [ new Identifier('never'), null, false, ], - 'no type to never is covariant' => [ + 'no type to never is covariant' => [ null, new Identifier('never'), true, ], - 'scalar type to never is covariant' => [ + 'scalar type to never is covariant' => [ new Identifier('int'), new Identifier('never'), true, @@ -151,22 +161,22 @@ final class OwnerPropertyContainer { private $owner; } null, false, ], - 'iterable to array is covariant' => [ + 'iterable to array is covariant' => [ new Identifier('iterable'), new Identifier('array'), true, ], - 'iterable to scalar is not covariant' => [ + 'iterable to scalar is not covariant' => [ new Identifier('iterable'), new Identifier('int'), false, ], - 'scalar to iterable is not covariant' => [ + 'scalar to iterable is not covariant' => [ new Identifier('iterable'), new Identifier('int'), false, ], - 'array to iterable is not covariant' => [ + 'array to iterable is not covariant' => [ new Identifier('array'), new Identifier('iterable'), false, @@ -201,12 +211,12 @@ final class OwnerPropertyContainer { private $owner; } new Identifier('object'), false, ], - 'mixed to object is covariant' => [ + 'mixed to object is covariant' => [ new Identifier('mixed'), new Identifier('object'), true, ], - 'object to mixed is not covariant' => [ + 'object to mixed is not covariant' => [ new Identifier('object'), new Identifier('mixed'), false, @@ -278,73 +288,93 @@ final class OwnerPropertyContainer { private $owner; } true, ], - 'scalar type to union type is not covariant' => [ + 'scalar type to union type is not covariant' => [ new Identifier('int'), new UnionType([new Identifier('int'), new Identifier('string')]), false, ], - 'union type to scalar is covariant' => [ + 'union type to scalar is covariant' => [ new UnionType([new Identifier('int'), new Identifier('string')]), new Identifier('int'), true, ], - 'same union type is covariant' => [ + 'same union type is covariant' => [ new UnionType([new Identifier('int'), new Identifier('string')]), new UnionType([new Identifier('int'), new Identifier('string')]), true, ], - 'same union type (in reverse order) is covariant' => [ + 'same union type (in reverse order) is covariant' => [ new UnionType([new Identifier('int'), new Identifier('string')]), new UnionType([new Identifier('string'), new Identifier('int')]), true, ], - 'incompatible union types are not covariant' => [ + 'incompatible union types are not covariant' => [ new UnionType([new Identifier('int'), new Identifier('string')]), new UnionType([new Identifier('float'), new Identifier('bool')]), false, ], - 'union type to wider union type is not covariant - https://3v4l.org/Tudl8#v8.1rc3' => [ + 'union type to wider union type is not covariant - https://3v4l.org/Tudl8#v8.1rc3' => [ new UnionType([new Identifier('int'), new Identifier('string')]), new UnionType([new Identifier('int'), new Identifier('string'), new Identifier('float')]), false, ], - 'union type to narrower union type is covariant - https://3v4l.org/RB2fC#v8.1rc3' => [ + 'union type to narrower union type is covariant - https://3v4l.org/RB2fC#v8.1rc3' => [ new UnionType([new Identifier('int'), new Identifier('string'), new Identifier('float')]), new UnionType([new Identifier('int'), new Identifier('string')]), true, ], + 'nullable union type is equivalent to shorthand null definition' => [ + new UnionType([new Identifier('A'), new Identifier('null')]), + new NullableType(new Identifier('A')), + true, + ], + 'shorthand nullable definition is equivalent to nullable union type' => [ + new NullableType(new Identifier('A')), + new UnionType([new Identifier('A'), new Identifier('null')]), + true, + ], + 'shorthand nullable definition to union type with added type is not covariant' => [ + new NullableType(new Identifier('A')), + new UnionType([new Identifier('A'), new Identifier('B'), new Identifier('null')]), + false, + ], + 'nullable union type to shorthand nullable definition is covariant' => [ + new UnionType([new Identifier('A'), new Identifier('B'), new Identifier('null')]), + new NullableType(new Identifier('A')), + true, + ], - 'object type to intersection type is covariant' => [ + 'object type to intersection type is covariant' => [ new Identifier('A'), new IntersectionType([new Identifier('A'), new Identifier('B')]), true, ], - 'intersection type to object type is not covariant' => [ + 'intersection type to object type is not covariant' => [ new IntersectionType([new Identifier('A'), new Identifier('B')]), new Identifier('A'), false, ], - 'same intersection type is covariant' => [ + 'same intersection type is covariant' => [ new IntersectionType([new Identifier('A'), new Identifier('B')]), new IntersectionType([new Identifier('A'), new Identifier('B')]), true, ], - 'same intersection type (in reverse order) is covariant' => [ + 'same intersection type (in reverse order) is covariant' => [ new IntersectionType([new Identifier('A'), new Identifier('B')]), new IntersectionType([new Identifier('B'), new Identifier('A')]), true, ], - 'incompatible intersection types are not covariant' => [ + 'incompatible intersection types are not covariant' => [ new IntersectionType([new Identifier('A'), new Identifier('B')]), new IntersectionType([new Identifier('C'), new Identifier('D')]), false, ], - 'intersection type to stricter intersection type is covariant - https://3v4l.org/NoV52#v8.1rc3' => [ + 'intersection type to stricter intersection type is covariant - https://3v4l.org/NoV52#v8.1rc3' => [ new IntersectionType([new Identifier('A'), new Identifier('B')]), new IntersectionType([new Identifier('A'), new Identifier('B'), new Identifier('C')]), true, ], - 'intersection type to less specific intersection type is not covariant - https://3v4l.org/8FSuK#v8.1rc3' => [ + 'intersection type to less specific intersection type is not covariant - https://3v4l.org/8FSuK#v8.1rc3' => [ new IntersectionType([new Identifier('A'), new Identifier('B'), new Identifier('C')]), new IntersectionType([new Identifier('A'), new Identifier('B')]), false, @@ -414,6 +444,7 @@ final class OwnerPropertyContainer { private $owner; } 'string', 'float', 'bool', + 'false', 'array', 'iterable', 'callable', @@ -465,6 +496,7 @@ public function existingNullableTypeStrings(): array ['string'], ['float'], ['bool'], + ['false'], ['array'], ['iterable'], ['callable'], From 19580dd2f173e9c7bba5f698d2db89a6aecba22a Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 Dec 2021 13:55:25 +0100 Subject: [PATCH 12/13] Upgraded to latest `roave/better-reflection:5.0.x-dev` to include https://github.com/Roave/BetterReflection/pull/902 --- composer.lock | 448 +++++++++++++++++++++++++------------------------- 1 file changed, 223 insertions(+), 225 deletions(-) diff --git a/composer.lock b/composer.lock index 4681d700..f27f8c08 100644 --- a/composer.lock +++ b/composer.lock @@ -903,166 +903,6 @@ ], "time": "2021-09-19T02:32:19+00:00" }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.5.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/a12f7e301eb7258bb68acd89d4aefa05c2906cae", - "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.1" - }, - "time": "2021-10-02T14:08:47+00:00" - }, { "name": "psr/container", "version": "1.1.2", @@ -1217,12 +1057,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/BetterReflection.git", - "reference": "1f7a13be41d110e132fb8f8ec0fce159c9c4639f" + "reference": "2b64de37d13452b8c85e246aeddcc5af98234156" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/BetterReflection/zipball/1f7a13be41d110e132fb8f8ec0fce159c9c4639f", - "reference": "1f7a13be41d110e132fb8f8ec0fce159c9c4639f", + "url": "https://api.github.com/repos/Roave/BetterReflection/zipball/2b64de37d13452b8c85e246aeddcc5af98234156", + "reference": "2b64de37d13452b8c85e246aeddcc5af98234156", "shasum": "" }, "require": { @@ -1230,8 +1070,6 @@ "jetbrains/phpstorm-stubs": "2021.3", "nikic/php-parser": "^4.13.2", "php": "~8.0.12 || ~8.1.0", - "phpdocumentor/reflection-docblock": "^5.3.0", - "phpdocumentor/type-resolver": "^1.5.0", "roave/signature": "^1.5" }, "conflict": { @@ -1242,7 +1080,7 @@ "phpstan/phpstan": "^1.2.0", "phpunit/phpunit": "^9.5.9", "roave/infection-static-analysis-plugin": "^1.12.0", - "vimeo/psalm": "^4.13.1" + "vimeo/psalm": "^4.14.0" }, "suggest": { "composer/composer": "Required to use the ComposerSourceLocator" @@ -1285,7 +1123,7 @@ "issues": "https://github.com/Roave/BetterReflection/issues", "source": "https://github.com/Roave/BetterReflection/tree/5.0.x" }, - "time": "2021-12-03T17:55:40+00:00" + "time": "2021-12-05T10:43:04+00:00" }, { "name": "roave/signature", @@ -2438,64 +2276,6 @@ } ], "time": "2021-10-27T18:21:46+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.10.0" - }, - "time": "2021-03-09T10:59:23+00:00" } ], "packages-dev": [ @@ -3686,6 +3466,166 @@ }, "time": "2021-04-11T12:56:19+00:00" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + }, + "time": "2021-10-19T17:43:47+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/a12f7e301eb7258bb68acd89d4aefa05c2906cae", + "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.1" + }, + "time": "2021-10-02T14:08:47+00:00" + }, { "name": "phpspec/prophecy", "version": "1.14.0", @@ -6237,6 +6177,64 @@ }, "time": "2021-11-06T10:31:17+00:00" }, + { + "name": "webmozart/assert", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" + }, + "time": "2021-03-09T10:59:23+00:00" + }, { "name": "webmozart/path-util", "version": "2.3.0", From a8ec81eac7d40c99ff073ad63a349486089abd5c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 5 Dec 2021 14:06:28 +0100 Subject: [PATCH 13/13] Removed all code relying on `ReflectionType#allowsNull()` checks: not necessary with union types As per previous commit, `roave/better-reflection` has been upgraded so that nullable types are always represented as union types: this simplifies the logic massively, because, except for some edge cases, all nullability problems become a set intersection problem, rather than some ad-hoc conditionals. This further demonstrates that nullable types as union types is really valuable. Ref: https://twitter.com/Ocramius/status/1467392834558992390 --- src/DetectChanges/Variance/TypeIsContravariant.php | 4 ---- src/DetectChanges/Variance/TypeIsCovariant.php | 14 -------------- 2 files changed, 18 deletions(-) diff --git a/src/DetectChanges/Variance/TypeIsContravariant.php b/src/DetectChanges/Variance/TypeIsContravariant.php index 3a09ea03..4a09fd3e 100644 --- a/src/DetectChanges/Variance/TypeIsContravariant.php +++ b/src/DetectChanges/Variance/TypeIsContravariant.php @@ -71,10 +71,6 @@ public function __invoke( private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedType $comparedType): bool { - if ($type->allowsNull() && ! $comparedType->allowsNull()) { - return false; - } - $typeAsString = $type->getName(); $comparedTypeAsString = $comparedType->getName(); diff --git a/src/DetectChanges/Variance/TypeIsCovariant.php b/src/DetectChanges/Variance/TypeIsCovariant.php index a538efb1..74115020 100644 --- a/src/DetectChanges/Variance/TypeIsCovariant.php +++ b/src/DetectChanges/Variance/TypeIsCovariant.php @@ -66,10 +66,6 @@ public function __invoke( private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedType $comparedType): bool { - if (self::allowsNull($comparedType) && ! self::allowsNull($type)) { - return false; - } - $typeAsString = $type->getName(); $comparedTypeAsString = $comparedType->getName(); @@ -77,10 +73,6 @@ private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedTyp return true; } - if ($comparedTypeAsString === 'null' && self::allowsNull($type)) { - return true; - } - if ($typeAsString === 'mixed' || $comparedTypeAsString === 'never') { // everything is covariant to `mixed` or `never` return true; @@ -132,10 +124,4 @@ private function compareNamedTypes(ReflectionNamedType $type, ReflectionNamedTyp $originalTypeReflectionClass->getName() ); } - - private static function allowsNull(ReflectionNamedType $type): bool - { - return $type->allowsNull() - || $type->__toString() === 'null'; - } }