1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Fix #1279 - speed up analysis of large arrays

This commit is contained in:
Brown 2019-02-04 16:06:14 -05:00
parent 6ae2ee809c
commit bbf013bfb8

View File

@ -9,6 +9,7 @@ use Psalm\Context;
use Psalm\Issue\DuplicateArrayKey; use Psalm\Issue\DuplicateArrayKey;
use Psalm\IssueBuffer; use Psalm\IssueBuffer;
use Psalm\Type; use Psalm\Type;
use Psalm\Internal\Type\TypeCombination;
use Psalm\Type\Atomic\TInt; use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TString; use Psalm\Type\Atomic\TString;
@ -36,9 +37,8 @@ class ArrayAnalyzer
return null; return null;
} }
$item_key_type = null; $item_key_atomic_types = [];
$item_value_atomic_types = [];
$item_value_type = null;
$property_types = []; $property_types = [];
$class_strings = []; $class_strings = [];
@ -73,11 +73,7 @@ class ArrayAnalyzer
$key_type = Type::getInt(false, (int) $item->key->value); $key_type = Type::getInt(false, (int) $item->key->value);
} }
if ($item_key_type) { $item_key_atomic_types = array_merge($item_key_atomic_types, array_values($key_type->getTypes()));
$item_key_type = Type::combineUnionTypes($key_type, $item_key_type, $codebase, false, true, 30);
} else {
$item_key_type = $key_type;
}
if ($item->key->inferredType->isSingleStringLiteral()) { if ($item->key->inferredType->isSingleStringLiteral()) {
$item_key_literal_type = $item->key->inferredType->getSingleStringLiteral(); $item_key_literal_type = $item->key->inferredType->getSingleStringLiteral();
@ -96,7 +92,7 @@ class ArrayAnalyzer
} }
} else { } else {
$item_key_value = $int_offset + $int_offset_diff; $item_key_value = $int_offset + $int_offset_diff;
$item_key_type = Type::getInt(); $item_key_atomic_types[] = new Type\Atomic\TInt();
} }
if ($item_key_value !== null) { if ($item_key_value !== null) {
@ -119,7 +115,7 @@ class ArrayAnalyzer
return false; return false;
} }
if ($item_value_type && $item_value_type->hasMixed() && !$can_create_objectlike) { if ($item_value_atomic_types && !$can_create_objectlike) {
continue; continue;
} }
@ -130,29 +126,44 @@ class ArrayAnalyzer
$can_create_objectlike = false; $can_create_objectlike = false;
} }
if ($item_value_type) { $item_value_atomic_types = array_merge(
$item_value_type = Type::combineUnionTypes( $item_value_atomic_types,
$item->value->inferredType, array_values($item->value->inferredType->getTypes())
clone $item_value_type, );
$codebase,
false,
true,
30
);
} else {
$item_value_type = $item->value->inferredType;
}
} else { } else {
$item_value_type = Type::getMixed(); $item_value_atomic_types[] = new Type\Atomic\TMixed();
if ($item_key_value !== null && count($property_types) <= 50) { if ($item_key_value !== null && count($property_types) <= 50) {
$property_types[$item_key_value] = $item_value_type; $property_types[$item_key_value] = Type::getMixed();
} else { } else {
$can_create_objectlike = false; $can_create_objectlike = false;
} }
} }
} }
if ($item_key_atomic_types) {
$item_key_type = TypeCombination::combineTypes(
$item_key_atomic_types,
$codebase,
false,
true,
30
);
} else {
$item_key_type = null;
}
if ($item_value_atomic_types) {
$item_value_type = TypeCombination::combineTypes(
$item_value_atomic_types,
$codebase,
false,
true,
30
);
} else {
$item_value_type = null;
}
// if this array looks like an object-like array, let's return that instead // if this array looks like an object-like array, let's return that instead
if ($item_value_type if ($item_value_type
&& $item_key_type && $item_key_type