From b4d53cbac01ff3e6acb0bec7335dc17dcddb7c03 Mon Sep 17 00:00:00 2001 From: Jaapio Date: Sun, 12 Mar 2023 11:06:26 +0100 Subject: [PATCH] Be strict about deprecations The original implementation was causing issues with deprecations triggered in the wrong conditions. By introducing controlled deprecations using doctrine/deprecation we are able to handle this more properly. The tests are updated to test the correct behavior, a new deprecation issue is created to track the deprecations. --- composer.json | 3 ++- composer.lock | 45 ++++++++++++++++++++++++++++++++- src/TypeResolver.php | 21 +++++++++------ tests/unit/TypeResolverTest.php | 20 +++++++++++++-- 4 files changed, 77 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index e69777c..3138b4c 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "require": { "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" + "phpstan/phpdoc-parser": "^1.13", + "doctrine/deprecations": "^1.0" }, "require-dev": { "ext-tokenizer": "*", diff --git a/composer.lock b/composer.lock index 24293cd..458b4e4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,51 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e012cde7a3d864a1bed7eea7698cf2eb", + "content-hash": "88ac2a4e5f317700e4c63e611b80b60e", "packages": [ + { + "name": "doctrine/deprecations", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + }, + "time": "2022-05-02T15:47:09+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", diff --git a/src/TypeResolver.php b/src/TypeResolver.php index 5cbbe44..32c8755 100644 --- a/src/TypeResolver.php +++ b/src/TypeResolver.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection; +use Doctrine\Deprecations\Deprecation; use InvalidArgumentException; use phpDocumentor\Reflection\PseudoTypes\ArrayShape; use phpDocumentor\Reflection\PseudoTypes\ArrayShapeItem; @@ -103,11 +104,8 @@ use function sprintf; use function strpos; use function strtolower; -use function trigger_error; use function trim; -use const E_USER_DEPRECATED; - final class TypeResolver { /** @var string Definition of the NAMESPACE operator in PHP */ @@ -579,11 +577,18 @@ private function parse(TokenIterator $tokenIterator): TypeNode */ private function tryParseRemainingCompoundTypes(TokenIterator $tokenIterator, Context $context, Type $type): Type { - trigger_error( - 'Legacy nullable type detected, please update your code as - you are using nullable types in a docblock. support will be removed in v2.0.0', - E_USER_DEPRECATED - ); + if ( + $tokenIterator->isCurrentTokenType(Lexer::TOKEN_UNION) || + $tokenIterator->isCurrentTokenType(Lexer::TOKEN_INTERSECTION) + ) { + Deprecation::trigger( + 'phpdocumentor/type-resolver', + 'https://github.com/phpDocumentor/TypeResolver/issues/184', + 'Legacy nullable type detected, please update your code as + you are using nullable types in a docblock. support will be removed in v2.0.0', + ); + } + $continue = true; while ($continue) { $continue = false; diff --git a/tests/unit/TypeResolverTest.php b/tests/unit/TypeResolverTest.php index b3618e4..efb405b 100644 --- a/tests/unit/TypeResolverTest.php +++ b/tests/unit/TypeResolverTest.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection; +use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; use InvalidArgumentException; use phpDocumentor\Reflection\PseudoTypes\CallableString; use phpDocumentor\Reflection\PseudoTypes\ConstExpression; @@ -73,6 +74,8 @@ */ class TypeResolverTest extends TestCase { + use VerifyDeprecations; + /** * @uses \phpDocumentor\Reflection\Types\Context * @uses \phpDocumentor\Reflection\Types\Array_ @@ -855,8 +858,14 @@ public function testArrayKeyValueSpecification(): void * @dataProvider illegalLegacyFormatProvider * @testdox create type from $type */ - public function testTypeBuilding(string $type, Type $expected): void + public function testTypeBuilding(string $type, Type $expected, bool $deprecation = false): void { + if ($deprecation) { + $this->expectDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184'); + } else { + $this->expectNoDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184'); + } + $fixture = new TypeResolver(); $actual = $fixture->resolve($type, new Context('phpDocumentor')); @@ -1090,16 +1099,19 @@ public function illegalLegacyFormatProvider(): array { return [ [ - '?string|bool', + '?string |bool', new Compound([new Nullable(new String_()), new Boolean()]), + true, ], [ '?string|?bool', new Compound([new Nullable(new String_()), new Nullable(new Boolean())]), + true, ], [ '?string|?bool|null', new Compound([new Nullable(new String_()), new Nullable(new Boolean()), new Null_()]), + true, ], [ '?string|bool|Foo', @@ -1108,10 +1120,12 @@ public function illegalLegacyFormatProvider(): array new Boolean(), new Object_(new Fqsen('\\phpDocumentor\\Foo')), ]), + true, ], [ '?string&bool', new Intersection([new Nullable(new String_()), new Boolean()]), + true, ], [ '?string&bool|Foo', @@ -1121,6 +1135,7 @@ public function illegalLegacyFormatProvider(): array new Compound([new Boolean(), new Object_(new Fqsen('\\phpDocumentor\\Foo'))]), ] ), + true, ], [ '?string&?bool|null', @@ -1130,6 +1145,7 @@ public function illegalLegacyFormatProvider(): array new Null_(), ] ), + true, ], ]; }