Skip to content

Commit ed91c62

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 7c43071 commit ed91c62

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
@@ -897,16 +897,28 @@ public function testArrayKeyValueSpecification(): void
897897
* @dataProvider callableProvider
898898
* @dataProvider constExpressions
899899
* @dataProvider shapeStructures
900-
* @dataProvider illegalLegacyFormatProvider
901900
* @testdox create type from $type
902901
*/
903902
public function testTypeBuilding(string $type, Type $expected, bool $deprecation = false): void
904903
{
905-
if ($deprecation) {
906-
$this->expectDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184');
907-
} else {
908-
$this->expectNoDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184');
909-
}
904+
$this->expectNoDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184');
905+
906+
$fixture = new TypeResolver();
907+
$actual = $fixture->resolve($type, new Context('phpDocumentor'));
908+
909+
self::assertEquals($expected, $actual);
910+
}
911+
912+
/**
913+
* @covers ::__construct
914+
* @covers ::resolve
915+
* @covers ::createType
916+
* @dataProvider illegalLegacyFormatProvider
917+
* @testdox create type from $type
918+
*/
919+
public function testTypeBuildingThrowsError(string $type, Type $expected): void
920+
{
921+
$this->expectDeprecationWithIdentifier('https://github.com/phpDocumentor/TypeResolver/issues/184');
910922

911923
$fixture = new TypeResolver();
912924
$actual = $fixture->resolve($type, new Context('phpDocumentor'));
@@ -1361,52 +1373,31 @@ public function illegalLegacyFormatProvider(): array
13611373
return [
13621374
[
13631375
'?string |bool',
1364-
new Compound([new Nullable(new String_()), new Boolean()]),
1365-
true,
1376+
new Nullable(new String_()),
13661377
],
13671378
[
13681379
'?string|?bool',
1369-
new Compound([new Nullable(new String_()), new Nullable(new Boolean())]),
1370-
true,
1380+
new Nullable(new String_()),
13711381
],
13721382
[
13731383
'?string|?bool|null',
1374-
new Compound([new Nullable(new String_()), new Nullable(new Boolean()), new Null_()]),
1375-
true,
1384+
new Nullable(new String_()),
13761385
],
13771386
[
13781387
'?string|bool|Foo',
1379-
new Compound([
1380-
new Nullable(new String_()),
1381-
new Boolean(),
1382-
new Object_(new Fqsen('\\phpDocumentor\\Foo')),
1383-
]),
1384-
true,
1388+
new Nullable(new String_()),
13851389
],
13861390
[
13871391
'?string&bool',
1388-
new Intersection([new Nullable(new String_()), new Boolean()]),
1389-
true,
1392+
new Nullable(new String_()),
13901393
],
13911394
[
13921395
'?string&bool|Foo',
1393-
new Intersection(
1394-
[
1395-
new Nullable(new String_()),
1396-
new Compound([new Boolean(), new Object_(new Fqsen('\\phpDocumentor\\Foo'))]),
1397-
]
1398-
),
1399-
true,
1396+
new Nullable(new String_()),
14001397
],
14011398
[
14021399
'?string&?bool|null',
1403-
new Compound(
1404-
[
1405-
new Intersection([new Nullable(new String_()), new Nullable(new Boolean())]),
1406-
new Null_(),
1407-
]
1408-
),
1409-
true,
1400+
new Nullable(new String_()),
14101401
],
14111402
];
14121403
}

0 commit comments

Comments
 (0)