Skip to content

Commit 8c64537

Browse files
Solve duplicates in UnionType description
1 parent 2d4a799 commit 8c64537

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

src/Type/UnionType.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
use PHPStan\Type\Generic\TemplateTypeVariance;
2828
use PHPStan\Type\Generic\TemplateUnionType;
2929
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
30+
use function array_diff_assoc;
31+
use function array_fill_keys;
3032
use function array_map;
3133
use function array_merge;
3234
use function array_slice;
@@ -293,6 +295,22 @@ public function describe(VerbosityLevel $level): string
293295
}
294296
}
295297

298+
if ($level->isPrecise()) {
299+
$duplicates = array_diff_assoc($typeNames, array_unique($typeNames));
300+
if (count($duplicates) > 0) {
301+
$indexByDuplicate = array_fill_keys($duplicates, 0);
302+
foreach ($typeNames as $key => $typeName) {
303+
if (!isset($indexByDuplicate[$typeName])) {
304+
continue;
305+
}
306+
307+
$typeNames[$key] = $typeName . '#' . ++$indexByDuplicate[$typeName];
308+
}
309+
}
310+
} else {
311+
$typeNames = array_unique($typeNames);
312+
}
313+
296314
if (count($typeNames) > 1024) {
297315
return implode('|', array_slice($typeNames, 0, 1024)) . "|\u{2026}";
298316
}

src/Type/VerbosityLevel.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ public function isValue(): bool
7878
return $this->value === self::VALUE;
7979
}
8080

81+
public function isPrecise(): bool
82+
{
83+
return $this->value === self::PRECISE;
84+
}
85+
8186
/** @api */
8287
public static function getRecommendedLevelByType(Type $acceptingType, ?Type $acceptedType = null): self
8388
{

tests/PHPStan/Type/UnionTypeTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,11 +717,13 @@ public function dataDescribe(): array
717717
new UnionType([new IntegerType(), new StringType()]),
718718
'int|string',
719719
'int|string',
720+
'int|string',
720721
],
721722
[
722723
new UnionType([new IntegerType(), new StringType(), new NullType()]),
723724
'int|string|null',
724725
'int|string|null',
726+
'int|string|null',
725727
],
726728
[
727729
new UnionType([
@@ -742,6 +744,7 @@ public function dataDescribe(): array
742744
new ConstantStringType('1'),
743745
]),
744746
"1|2|2.2|10|'1'|'10'|'10aaa'|'11aaa'|'1aaa'|'2'|'2aaa'|'foo'|stdClass|true|null",
747+
"1|2|2.2|10|'1'|'10'|'10aaa'|'11aaa'|'1aaa'|'2'|'2aaa'|'foo'|stdClass|true|null",
745748
'float|int|stdClass|string|true|null',
746749
],
747750
[
@@ -763,6 +766,7 @@ public function dataDescribe(): array
763766
new ConstantStringType('aaa'),
764767
),
765768
'\'aaa\'|array{a: int, b: float}|array{a: string, b: bool}',
769+
'\'aaa\'|array{a: int, b: float}|array{a: string, b: bool}',
766770
'array<string, bool|float|int|string>|string',
767771
],
768772
[
@@ -784,6 +788,7 @@ public function dataDescribe(): array
784788
new ConstantStringType('aaa'),
785789
),
786790
'\'aaa\'|array{a: string, b: bool}|array{b: int, c: float}',
791+
'\'aaa\'|array{a: string, b: bool}|array{b: int, c: float}',
787792
'array<string, bool|float|int|string>|string',
788793
],
789794
[
@@ -805,6 +810,7 @@ public function dataDescribe(): array
805810
new ConstantStringType('aaa'),
806811
),
807812
'\'aaa\'|array{a: string, b: bool}|array{c: int, d: float}',
813+
'\'aaa\'|array{a: string, b: bool}|array{c: int, d: float}',
808814
'array<string, bool|float|int|string>|string',
809815
],
810816
[
@@ -825,6 +831,7 @@ public function dataDescribe(): array
825831
]),
826832
),
827833
'array{int, bool, float}|array{string}',
834+
'array{int, bool, float}|array{string}',
828835
'array<int, bool|float|int|string>',
829836
],
830837
[
@@ -837,6 +844,7 @@ public function dataDescribe(): array
837844
]),
838845
),
839846
'array{}|array{foooo: \'barrr\'}',
847+
'array{}|array{foooo: \'barrr\'}',
840848
'array<string, string>',
841849
],
842850
[
@@ -848,6 +856,7 @@ public function dataDescribe(): array
848856
]),
849857
),
850858
'int|numeric-string',
859+
'int|numeric-string',
851860
'int|string',
852861
],
853862
[
@@ -857,6 +866,7 @@ public function dataDescribe(): array
857866
),
858867
'int<0, 4>|int<6, 10>',
859868
'int<0, 4>|int<6, 10>',
869+
'int<0, 4>|int<6, 10>',
860870
],
861871
[
862872
TypeCombinator::union(
@@ -868,6 +878,7 @@ public function dataDescribe(): array
868878
),
869879
new NullType(),
870880
),
881+
'TFoo of int (class foo, parameter)|null',
871882
'(TFoo of int)|null',
872883
'(TFoo of int)|null',
873884
],
@@ -881,6 +892,7 @@ public function dataDescribe(): array
881892
),
882893
new GenericClassStringType(new ObjectType('Abc')),
883894
),
895+
'class-string<Abc>|TFoo of int (class foo, parameter)',
884896
'class-string<Abc>|TFoo of int',
885897
'class-string<Abc>|TFoo of int',
886898
],
@@ -894,6 +906,7 @@ public function dataDescribe(): array
894906
),
895907
new NullType(),
896908
),
909+
'TFoo (class foo, parameter)|null',
897910
'TFoo|null',
898911
'TFoo|null',
899912
],
@@ -912,9 +925,16 @@ public function dataDescribe(): array
912925
),
913926
new NullType(),
914927
),
928+
'TFoo of TBar (class foo, parameter) (class foo, parameter)|null',
915929
'(TFoo of TBar)|null',
916930
'(TFoo of TBar)|null',
917931
],
932+
[
933+
new UnionType([new ObjectType('Foo'), new ObjectType('Foo')]),
934+
'Foo#1|Foo#2',
935+
'Foo',
936+
'Foo',
937+
],
918938
];
919939
}
920940

@@ -923,10 +943,12 @@ public function dataDescribe(): array
923943
*/
924944
public function testDescribe(
925945
Type $type,
946+
string $expectedPreciseDescription,
926947
string $expectedValueDescription,
927948
string $expectedTypeOnlyDescription,
928949
): void
929950
{
951+
$this->assertSame($expectedPreciseDescription, $type->describe(VerbosityLevel::precise()));
930952
$this->assertSame($expectedValueDescription, $type->describe(VerbosityLevel::value()));
931953
$this->assertSame($expectedTypeOnlyDescription, $type->describe(VerbosityLevel::typeOnly()));
932954
}

0 commit comments

Comments
 (0)