Skip to content

Commit 47ee8c5

Browse files
committed
Remove legacy nullable format
Compound types containg `?` nullables are deprecated in php, and not supported by phpstan. In v1 we had a work around for this but this was slow and fragile. The nullable format has been deprecated since 2023 and is now removed. We still produce a deprecation error to warn people about invalid type handling. fixes #184
1 parent 5f9f2be commit 47ee8c5

File tree

2 files changed

+40
-84
lines changed

2 files changed

+40
-84
lines changed

src/TypeResolver.php

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,8 @@ final class TypeResolver
199199
public function __construct(?FqsenResolver $fqsenResolver = null)
200200
{
201201
$this->fqsenResolver = $fqsenResolver ?: new FqsenResolver();
202-
203-
if (class_exists(ParserConfig::class)) {
204-
$this->typeParser = new TypeParser(new ParserConfig([]), new ConstExprParser(new ParserConfig([])));
205-
$this->lexer = new Lexer(new ParserConfig([]));
206-
} else {
207-
$this->typeParser = new TypeParser(new ConstExprParser());
208-
$this->lexer = new Lexer();
209-
}
202+
$this->typeParser = new TypeParser(new ParserConfig([]), new ConstExprParser(new ParserConfig([])));
203+
$this->lexer = new Lexer(new ParserConfig([]));
210204
}
211205

212206
/**
@@ -242,7 +236,19 @@ public function resolve(string $type, ?Context $context = null): Type
242236
$ast = $this->parse($tokenIterator);
243237
$type = $this->createType($ast, $context);
244238

245-
return $this->tryParseRemainingCompoundTypes($tokenIterator, $context, $type);
239+
if (
240+
$tokenIterator->isCurrentTokenType(Lexer::TOKEN_UNION) ||
241+
$tokenIterator->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)
242+
) {
243+
Deprecation::trigger(
244+
'phpdocumentor/type-resolver',
245+
'https://github.com/phpDocumentor/TypeResolver/issues/184',
246+
'Legacy nullable type detected, please update your code as
247+
you are using nullable types in a docblock. support is removed in v2.0.0'
248+
);
249+
}
250+
251+
return $type;
246252
}
247253

248254
public function createType(?TypeNode $type, Context $context): Type
@@ -678,47 +684,6 @@ private function parse(TokenIterator $tokenIterator): TypeNode
678684
return $ast;
679685
}
680686

681-
/**
682-
* Will try to parse unsupported type notations by phpstan
683-
*
684-
* The phpstan parser doesn't support the illegal nullable combinations like this library does.
685-
* This method will warn the user about those notations but for bc purposes we will still have it here.
686-
*/
687-
private function tryParseRemainingCompoundTypes(TokenIterator $tokenIterator, Context $context, Type $type): Type
688-
{
689-
if (
690-
$tokenIterator->isCurrentTokenType(Lexer::TOKEN_UNION) ||
691-
$tokenIterator->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)
692-
) {
693-
Deprecation::trigger(
694-
'phpdocumentor/type-resolver',
695-
'https://github.com/phpDocumentor/TypeResolver/issues/184',
696-
'Legacy nullable type detected, please update your code as
697-
you are using nullable types in a docblock. support will be removed in v2.0.0'
698-
);
699-
}
700-
701-
$continue = true;
702-
while ($continue) {
703-
$continue = false;
704-
while ($tokenIterator->tryConsumeTokenType(Lexer::TOKEN_UNION)) {
705-
$ast = $this->parse($tokenIterator);
706-
$type2 = $this->createType($ast, $context);
707-
$type = new Compound([$type, $type2]);
708-
$continue = true;
709-
}
710-
711-
while ($tokenIterator->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) {
712-
$ast = $this->typeParser->parse($tokenIterator);
713-
$type2 = $this->createType($ast, $context);
714-
$type = new Intersection([$type, $type2]);
715-
$continue = true;
716-
}
717-
}
718-
719-
return $type;
720-
}
721-
722687
/**
723688
* @param TypeNode[] $nodes
724689
*

tests/unit/TypeResolverTest.php

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -895,16 +895,28 @@ public function testArrayKeyValueSpecification(): void
895895
* @dataProvider callableProvider
896896
* @dataProvider constExpressions
897897
* @dataProvider shapeStructures
898-
* @dataProvider illegalLegacyFormatProvider
899898
* @testdox create type from $type
900899
*/
901900
public function testTypeBuilding(string $type, Type $expected, bool $deprecation = false): void
902901
{
903-
if ($deprecation) {
904-
$this->expectDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184');
905-
} else {
906-
$this->expectNoDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184');
907-
}
902+
$this->expectNoDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184');
903+
904+
$fixture = new TypeResolver();
905+
$actual = $fixture->resolve($type, new Context('phpDocumentor'));
906+
907+
self::assertEquals($expected, $actual);
908+
}
909+
910+
/**
911+
* @covers ::__construct
912+
* @covers ::resolve
913+
* @covers ::createType
914+
* @dataProvider illegalLegacyFormatProvider
915+
* @testdox create type from $type
916+
*/
917+
public function testTypeBuildingThrowsError(string $type, Type $expected): void
918+
{
919+
$this->expectDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184');
908920

909921
$fixture = new TypeResolver();
910922
$actual = $fixture->resolve($type, new Context('phpDocumentor'));
@@ -1359,52 +1371,31 @@ public function illegalLegacyFormatProvider(): array
13591371
return [
13601372
[
13611373
'?string |bool',
1362-
new Compound([new Nullable(new String_()), new Boolean()]),
1363-
true,
1374+
new Nullable(new String_()),
13641375
],
13651376
[
13661377
'?string|?bool',
1367-
new Compound([new Nullable(new String_()), new Nullable(new Boolean())]),
1368-
true,
1378+
new Nullable(new String_()),
13691379
],
13701380
[
13711381
'?string|?bool|null',
1372-
new Compound([new Nullable(new String_()), new Nullable(new Boolean()), new Null_()]),
1373-
true,
1382+
new Nullable(new String_()),
13741383
],
13751384
[
13761385
'?string|bool|Foo',
1377-
new Compound([
1378-
new Nullable(new String_()),
1379-
new Boolean(),
1380-
new Object_(new Fqsen('\\phpDocumentor\\Foo')),
1381-
]),
1382-
true,
1386+
new Nullable(new String_()),
13831387
],
13841388
[
13851389
'?string&bool',
1386-
new Intersection([new Nullable(new String_()), new Boolean()]),
1387-
true,
1390+
new Nullable(new String_()),
13881391
],
13891392
[
13901393
'?string&bool|Foo',
1391-
new Intersection(
1392-
[
1393-
new Nullable(new String_()),
1394-
new Compound([new Boolean(), new Object_(new Fqsen('\\phpDocumentor\\Foo'))]),
1395-
]
1396-
),
1397-
true,
1394+
new Nullable(new String_()),
13981395
],
13991396
[
14001397
'?string&?bool|null',
1401-
new Compound(
1402-
[
1403-
new Intersection([new Nullable(new String_()), new Nullable(new Boolean())]),
1404-
new Null_(),
1405-
]
1406-
),
1407-
true,
1398+
new Nullable(new String_()),
14081399
],
14091400
];
14101401
}

0 commit comments

Comments
 (0)