From fb77c3393a7d3fa6b677dbd8b5ff084f54b967bb Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Fri, 4 Nov 2016 22:11:46 -0400 Subject: [PATCH] Tighten up rules --- src/Psalm/Type.php | 128 ++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 61 deletions(-) diff --git a/src/Psalm/Type.php b/src/Psalm/Type.php index 4b88c0822..a9736a0d6 100644 --- a/src/Psalm/Type.php +++ b/src/Psalm/Type.php @@ -453,68 +453,10 @@ abstract class Type $value_types = []; foreach ($types as $type) { - if ($type instanceof Union) { - throw new \InvalidArgumentException('Union type not expected here'); - } + $result = self::scrapeTypeProperties($type, $key_types, $value_types); - // if we see the magic empty value and there's more than one type, ignore it - if ($type->value === 'empty') { - continue; - } - - if ($type->value === 'mixed') { - return Type::getMixed(); - } - - if ($type->value === 'void') { - $type->value = 'null'; - } - - // deal with false|bool => bool - if ($type->value === 'false' && isset($value_types['bool'])) { - continue; - } elseif ($type->value === 'bool' && isset($value_types['false'])) { - unset($value_types['false']); - } - - if ($type instanceof Generic) { - if (!isset($value_types[$type->value])) { - $value_types[$type->value] = []; - } - - $value_type_param_index = count($type->type_params) - 1; - $value_types[$type->value][(string) $type->type_params[$value_type_param_index]] = - $type->type_params[$value_type_param_index]; - - if ($value_type_param_index) { - $key_types[$type->value][(string) $type->type_params[0]] = $type->type_params[0]; - } - } elseif ($type instanceof ObjectLike) { - if (!isset($value_types['object-like'])) { - /** @var array */ - $value_types['object-like'] = []; - } - - foreach ($type->properties as $candidate_property_name => $candidate_property_type) { - if (!isset($value_types['object-like'][$candidate_property_name])) { - $value_types['object-like'][$candidate_property_name] = $candidate_property_type; - } else { - $value_types['object-like'][$candidate_property_name] = Type::combineUnionTypes( - $value_types['object-like'][$candidate_property_name], - $candidate_property_type - ); - } - } - } else { - if (!isset($value_types[$type->value])) { - $value_types[$type->value] = []; - } - - if ($type->value === 'array') { - throw new \InvalidArgumentException('Cannot have a non-generic array'); - } - - $value_types[$type->value][(string) $type] = null; + if ($result) { + return $result; } } @@ -597,4 +539,68 @@ abstract class Type return new Union($new_types); } + + /** + * @param Atomic $type + * @param array> &$key_types + * @param array> &$value_types + * @return null|Union + */ + public static function scrapeTypeProperties(Atomic $type, array &$key_types, array &$value_types) + { + // if we see the magic empty value and there's more than one type, ignore it + if ($type->value === 'empty') { + return null; + } + + if ($type->value === 'mixed') { + return Type::getMixed(); + } + + if ($type->value === 'void') { + $type->value = 'null'; + } + + // deal with false|bool => bool + if ($type->value === 'false' && isset($value_types['bool'])) { + return null; + } elseif ($type->value === 'bool' && isset($value_types['false'])) { + unset($value_types['false']); + } + + if ($type instanceof Generic) { + if (!isset($value_types[$type->value])) { + $value_types[$type->value] = []; + } + + $value_type_param_index = count($type->type_params) - 1; + $value_types[$type->value][(string) $type->type_params[$value_type_param_index]] = + $type->type_params[$value_type_param_index]; + + if ($value_type_param_index) { + $key_types[$type->value][(string) $type->type_params[0]] = $type->type_params[0]; + } + } elseif ($type instanceof ObjectLike) { + foreach ($type->properties as $candidate_property_name => $candidate_property_type) { + if (!isset($value_types['object-like'][$candidate_property_name])) { + $value_types['object-like'][$candidate_property_name] = $candidate_property_type; + } else { + $value_types['object-like'][$candidate_property_name] = Type::combineUnionTypes( + $value_types['object-like'][$candidate_property_name], + $candidate_property_type + ); + } + } + } else { + if (!isset($value_types[$type->value])) { + $value_types[$type->value] = []; + } + + if ($type->value === 'array') { + throw new \InvalidArgumentException('Cannot have a non-generic array'); + } + + $value_types[$type->value][(string) $type] = null; + } + } }