From 0e933e2927c9468edf08f765c4b767e72bc7570a Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Fri, 27 Dec 2019 14:50:16 +0100 Subject: [PATCH] fix union type for ParamTypeDeclarationRector --- .../NodeTypeResolver/src/StaticTypeMapper.php | 29 +++++++++--- ...hange_union_type_mutually_children.php.inc | 47 +++++++++++++++++++ .../Fixture/skip_union_type.php.inc | 23 +++++++++ 3 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/Fixture/change_union_type_mutually_children.php.inc create mode 100644 packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/Fixture/skip_union_type.php.inc diff --git a/packages/NodeTypeResolver/src/StaticTypeMapper.php b/packages/NodeTypeResolver/src/StaticTypeMapper.php index 4be091d0076..61d09f102e7 100644 --- a/packages/NodeTypeResolver/src/StaticTypeMapper.php +++ b/packages/NodeTypeResolver/src/StaticTypeMapper.php @@ -722,18 +722,26 @@ final class StaticTypeMapper return $phpParserUnionType; } - // we need exactly one type + // do the type should be compatible with all other types, e.g. A extends B, B foreach ($unionType->getTypes() as $unionedType) { if (! $unionedType instanceof TypeWithClassName) { return null; } + + foreach ($unionType->getTypes() as $nestedUnionedType) { + if (! $nestedUnionedType instanceof TypeWithClassName) { + return null; + } + + if (! $this->areTypeWithClassNamesRelated($unionedType, $nestedUnionedType)) { + continue 2; + } + } + + return new FullyQualified($unionedType->getClassName()); } - // @todo the type should be compatible with all other types, check with is_a()? - /** @var TypeWithClassName $firstObjectType */ - $firstObjectType = $unionType->getTypes()[0]; - - return new FullyQualified($firstObjectType->getClassName()); + return null; } private function mapScalarStringToType(string $scalarName): ?Type @@ -805,4 +813,13 @@ final class StaticTypeMapper return new PhpParserUnionType($phpParserUnionedTypes); } + + private function areTypeWithClassNamesRelated(TypeWithClassName $firstType, TypeWithClassName $secondType): bool + { + if (is_a($firstType->getClassName(), $secondType->getClassName(), true)) { + return true; + } + + return is_a($secondType->getClassName(), $firstType->getClassName(), true); + } } diff --git a/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/Fixture/change_union_type_mutually_children.php.inc b/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/Fixture/change_union_type_mutually_children.php.inc new file mode 100644 index 00000000000..140c7e4fadd --- /dev/null +++ b/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/Fixture/change_union_type_mutually_children.php.inc @@ -0,0 +1,47 @@ + +----- + diff --git a/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/Fixture/skip_union_type.php.inc b/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/Fixture/skip_union_type.php.inc new file mode 100644 index 00000000000..e0e810f6b18 --- /dev/null +++ b/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/Fixture/skip_union_type.php.inc @@ -0,0 +1,23 @@ +