Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve from_docblock in TypeCombiner #8999

Merged
merged 6 commits into from Dec 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 26 additions & 12 deletions src/Psalm/Internal/Type/TypeCombiner.php
Expand Up @@ -210,6 +210,7 @@ public static function combine(
$new_types = self::handleKeyedArrayEntries(
$combination,
$overwrite_empty_array,
$from_docblock,
);
}

Expand All @@ -225,6 +226,7 @@ public static function combine(
$allow_mixed_union,
$type,
$combination->array_type_params,
$from_docblock,
);
}

Expand All @@ -239,7 +241,7 @@ public static function combine(
foreach ($combination->builtin_type_params as $generic_type => $generic_type_params) {
if ($generic_type === 'iterable') {
assert(count($generic_type_params) <= 2);
$new_types[] = new TIterable($generic_type_params);
$new_types[] = new TIterable($generic_type_params, [], $from_docblock);
} else {
/** @psalm-suppress ArgumentTypeCoercion Caused by the PropertyTypeCoercion above */
$generic_object = new TGenericObject(
Expand All @@ -248,6 +250,7 @@ public static function combine(
false,
false,
$combination->extra_types,
$from_docblock,
);
$new_types[] = $generic_object;

Expand All @@ -267,6 +270,7 @@ public static function combine(
false,
$combination->object_static[$generic_type] ?? false,
$combination->extra_types,
$from_docblock,
);

$new_types[] = $generic_object;
Expand All @@ -293,10 +297,14 @@ public static function combine(

foreach ($object_type->getAtomicTypes() as $object_atomic_type) {
if ($object_atomic_type instanceof TNamedObject) {
$new_types[] = new TClassString($object_atomic_type->value, $object_atomic_type);
$class_type = new TClassString($object_atomic_type->value, $object_atomic_type);
} elseif ($object_atomic_type instanceof TObject) {
$new_types[] = new TClassString();
$class_type = new TClassString();
} else {
continue;
}

$new_types[] = $class_type->setFromDocblock($from_docblock);
}
}
}
Expand Down Expand Up @@ -351,7 +359,7 @@ public static function combine(
continue;
}

$new_types[] = $type;
$new_types[] = $type->setFromDocblock($from_docblock);
}

if (!$new_types && !$has_never) {
Expand Down Expand Up @@ -1321,7 +1329,8 @@ private static function getClassLikes(Codebase $codebase, string $fq_classlike_n
*/
private static function handleKeyedArrayEntries(
TypeCombination $combination,
bool $overwrite_empty_array
bool $overwrite_empty_array,
bool $from_docblock
): array {
$new_types = [];

Expand Down Expand Up @@ -1397,6 +1406,7 @@ private static function handleKeyedArrayEntries(
? null
: [$fallback_key_type, $fallback_value_type],
(bool)$combination->all_arrays_lists,
$from_docblock,
);
} else {
$objectlike = new TKeyedArray(
Expand All @@ -1406,6 +1416,7 @@ private static function handleKeyedArrayEntries(
? null
: [$fallback_key_type, $fallback_value_type],
(bool)$combination->all_arrays_lists,
$from_docblock,
);
}

Expand All @@ -1414,10 +1425,12 @@ private static function handleKeyedArrayEntries(
$key_type = $combination->objectlike_key_type ?? Type::getArrayKey();
$value_type = $combination->objectlike_value_type ?? Type::getMixed();
if ($combination->array_always_filled) {
$new_types[] = new TNonEmptyArray([$key_type, $value_type]);
$array_type = new TNonEmptyArray([$key_type, $value_type]);
} else {
$new_types[] = new TArray([$key_type, $value_type]);
$array_type = new TArray([$key_type, $value_type]);
}

$new_types[] = $array_type->setFromDocblock($from_docblock);
}

// if we're merging an empty array with an object-like, clobber empty array
Expand All @@ -1436,7 +1449,8 @@ private static function getArrayTypeFromGenericParams(
bool $overwrite_empty_array,
bool $allow_mixed_union,
Atomic $type,
array $generic_type_params
array $generic_type_params,
bool $from_docblock
): Atomic {
if ($combination->objectlike_entries) {
$objectlike_generic_type = null;
Expand All @@ -1455,11 +1469,11 @@ private static function getArrayTypeFromGenericParams(
);

if (is_int($property_name)) {
$objectlike_keys[$property_name] = new TLiteralInt($property_name);
$objectlike_keys[$property_name] = new TLiteralInt($property_name, $from_docblock);
} elseif ($type instanceof TKeyedArray && isset($type->class_strings[$property_name])) {
$objectlike_keys[$property_name] = new TLiteralClassString($property_name);
$objectlike_keys[$property_name] = new TLiteralClassString($property_name, $from_docblock);
} else {
$objectlike_keys[$property_name] = new TLiteralString($property_name);
$objectlike_keys[$property_name] = new TLiteralString($property_name, $from_docblock);
}
}

Expand Down Expand Up @@ -1580,6 +1594,6 @@ private static function getArrayTypeFromGenericParams(
}
}

return $array_type;
return $array_type->setFromDocblock($from_docblock);
}
}
8 changes: 7 additions & 1 deletion src/Psalm/Type/Atomic.php
Expand Up @@ -162,7 +162,13 @@ public static function create(
?string $text = null,
bool $from_docblock = false
): Atomic {
$result = self::createInner($value, $analysis_php_version_id, $template_type_map, $type_aliases);
$result = self::createInner(
$value,
$analysis_php_version_id,
$template_type_map,
$type_aliases,
$from_docblock,
);
$result->offset_start = $offset_start;
$result->offset_end = $offset_end;
$result->text = $text;
Expand Down
23 changes: 23 additions & 0 deletions tests/TypeReconciliation/RedundantConditionTest.php
Expand Up @@ -1546,6 +1546,29 @@ function f(array $p) : void {
}',
'error_message' => 'RedundantCondition',
],
'from_docblock should be kept when removing types' => [
'code' => '<?php
/**
* @see https://github.com/vimeo/psalm/issues/8932
*
* @param array|null $value
*
* @return null
*/
function reverseTransform($value)
{
if (null === $value) {
return null;
}

if (!\is_array($value)) {
throw new \Exception("array");
}

return null;
}',
'error_message' => 'DocblockTypeContradiction',
],
];
}
}