1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Fix #457 - fix objectlike property isset check

This commit is contained in:
Matthew Brown 2018-02-10 23:30:40 -05:00
parent 24416feb62
commit 217233472c
4 changed files with 47 additions and 15 deletions

View File

@ -595,11 +595,6 @@ class MethodCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
$property_id = $fq_class_name . '::$' . $prop_name;
$class_storage = $project_checker->classlike_storage_provider->get($fq_class_name);
// if the property exists on the object, everything is good
if ($project_checker->codebase->properties->propertyExists($property_id)) {
return true;
}
switch ($method_name) {
case '__set':
// If `@psalm-seal-properties` is set, the property must be defined with
@ -619,9 +614,12 @@ class MethodCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
// If a `@property` annotation is set, the type of the value passed to the
// magic setter must match the annotation.
$second_arg_type = $stmt->args[1]->value->inferredType;
$second_arg_type = isset($stmt->args[1]->value->inferredType)
? $stmt->args[1]->value->inferredType
: null;
if (isset($class_storage->pseudo_property_set_types['$' . $prop_name])
&& isset($second_arg_type)
&& $second_arg_type
&& !TypeChecker::isContainedBy(
$project_checker->codebase,
$second_arg_type,

View File

@ -385,12 +385,13 @@ class TypeChecker
if ($container_type_part instanceof ObjectLike && $input_type_part instanceof ObjectLike) {
$all_types_contain = true;
foreach ($input_type_part->properties as $key => $input_property_type) {
if (!isset($container_type_part->properties[$key])) {
return false;
foreach ($container_type_part->properties as $key => $container_property_type) {
if (!isset($input_type_part->properties[$key])) {
$all_types_contain = false;
continue;
}
$container_property_type = $container_type_part->properties[$key];
$input_property_type = $input_type_part->properties[$key];
if (!$input_property_type->isEmpty() &&
!self::isContainedBy(
@ -399,9 +400,9 @@ class TypeChecker
$container_property_type,
$input_property_type->ignore_nullable_issues,
$input_property_type->ignore_falsable_issues,
$has_scalar_match,
$type_coerced,
$type_coerced_from_mixed
$property_has_scalar_match,
$property_type_coerced,
$property_type_coerced_from_mixed
)
) {
if (self::isContainedBy($codebase, $container_property_type, $input_property_type)) {

View File

@ -621,7 +621,7 @@ class FunctionCallTest extends TestCase
}
a(["a" => "hello"]);',
'error_message' => 'InvalidScalarArgument',
'error_message' => 'InvalidArgument',
],
'possiblyNullFunctionCall' => [
'<?php

View File

@ -732,6 +732,22 @@ class TypeReconciliationTest extends TestCase
echo "cool";
}',
],
'specificArrayFields' => [
'<?php
/**
* @param array{field:string} $array
*/
function print_field($array) : void {
echo $array["field"];
}
/**
* @param array{field:string,otherField:string} $array
*/
function has_mix_of_fields($array) : void {
print_field($array);
}',
],
];
}
@ -817,6 +833,23 @@ class TypeReconciliationTest extends TestCase
}',
'error_message' => 'TypeDoesNotContainType',
],
'lessSpecificArrayFields' => [
'<?php
/**
* @param array{field:string, otherField:string} $array
*/
function print_field($array) : void {
echo $array["field"] . " " . $array["otherField"];
}
/**
* @param array{field:string} $array
*/
function has_mix_of_fields($array) : void {
print_field($array);
}',
'error_message' => 'PossiblyInvalidArgument',
],
];
}
}