From 0e23fab5d2baffd89141af0890746985c3d06097 Mon Sep 17 00:00:00 2001 From: Brown Date: Tue, 18 Feb 2020 12:53:54 -0500 Subject: [PATCH] Detect bugs similar to that which caused #2832 --- src/Psalm/Internal/Analyzer/MethodAnalyzer.php | 10 +++++++--- .../Analyzer/Statements/Expression/CallAnalyzer.php | 4 ++-- src/Psalm/Internal/Analyzer/TypeAnalyzer.php | 12 +++++++++--- src/Psalm/Internal/Type/AssertionReconciler.php | 2 +- src/Psalm/Internal/Visitor/ReflectorVisitor.php | 2 -- tests/ArrayAccessTest.php | 9 +++++++++ 6 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/MethodAnalyzer.php b/src/Psalm/Internal/Analyzer/MethodAnalyzer.php index a25919960..4c8921e80 100644 --- a/src/Psalm/Internal/Analyzer/MethodAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/MethodAnalyzer.php @@ -170,7 +170,10 @@ class MethodAnalyzer extends FunctionLikeAnalyzer if ($codebase->methods->methodExists( $method_id, $calling_function_id, - $calling_function_id !== $method_id ? $code_location : null, + !$calling_function_id + || strtolower($calling_function_id) !== strtolower((string) $method_id) + ? $code_location + : null, null, $code_location->file_path )) { @@ -319,8 +322,9 @@ class MethodAnalyzer extends FunctionLikeAnalyzer if (!$declaring_method_id) { if ($method_name === '__construct' - || $method_id === 'Closure::__invoke' - || $method_id === 'Closure::fromcallable' + || ($method_id->fq_class_name === 'Closure' + && ($method_id->method_name === 'fromcallable' + || $method_id->method_name === '__invoke')) ) { return null; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index 2291c1695..8f1cc1186 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -107,7 +107,7 @@ class CallAnalyzer if ((string) $method_id !== $source->getId()) { if ($context->collect_initializations) { - if (isset($context->initialized_methods[$method_id])) { + if (isset($context->initialized_methods[(string) $method_id])) { return; } @@ -115,7 +115,7 @@ class CallAnalyzer $context->initialized_methods = []; } - $context->initialized_methods[$method_id] = true; + $context->initialized_methods[(string) $method_id] = true; } $project_analyzer->getMethodMutations( diff --git a/src/Psalm/Internal/Analyzer/TypeAnalyzer.php b/src/Psalm/Internal/Analyzer/TypeAnalyzer.php index b428d2c0d..fae49da6b 100644 --- a/src/Psalm/Internal/Analyzer/TypeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/TypeAnalyzer.php @@ -454,21 +454,27 @@ class TypeAnalyzer $first_comparison_result = new TypeComparisonResult(); $second_comparison_result = new TypeComparisonResult(); - $either_contains = self::isAtomicContainedBy( + $either_contains = (self::isAtomicContainedBy( $codebase, $type1_part, $type2_part, true, false, $first_comparison_result - ) || self::isAtomicContainedBy( + ) + && !$first_comparison_result->to_string_cast + ) || (self::isAtomicContainedBy( $codebase, $type2_part, $type1_part, true, false, $second_comparison_result - ) || ($first_comparison_result->type_coerced && $second_comparison_result->type_coerced); + ) + && !$second_comparison_result->to_string_cast + ) || ($first_comparison_result->type_coerced + && $second_comparison_result->type_coerced + ); if ($either_contains) { return true; diff --git a/src/Psalm/Internal/Type/AssertionReconciler.php b/src/Psalm/Internal/Type/AssertionReconciler.php index 946f1b0d0..03b9f1eb8 100644 --- a/src/Psalm/Internal/Type/AssertionReconciler.php +++ b/src/Psalm/Internal/Type/AssertionReconciler.php @@ -2594,7 +2594,7 @@ class AssertionReconciler extends \Psalm\Type\Reconciler } /** -* @param string[] $suppressed_issues + * @param string[] $suppressed_issues */ private static function handleLiteralEquality( string $assertion, diff --git a/src/Psalm/Internal/Visitor/ReflectorVisitor.php b/src/Psalm/Internal/Visitor/ReflectorVisitor.php index 3412c4a1a..550ffaa59 100644 --- a/src/Psalm/Internal/Visitor/ReflectorVisitor.php +++ b/src/Psalm/Internal/Visitor/ReflectorVisitor.php @@ -3273,8 +3273,6 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse if ($property_storage->type && $property_storage->type !== $property_storage->signature_type - && (!$property_storage->signature_type - || $doc_var_group_type !== $property_storage->signature_type->getId()) ) { if (!$property_storage->signature_type) { $property_storage->type_location = $doc_var_location; diff --git a/tests/ArrayAccessTest.php b/tests/ArrayAccessTest.php index 0391867ec..218e5bcdd 100644 --- a/tests/ArrayAccessTest.php +++ b/tests/ArrayAccessTest.php @@ -1135,6 +1135,15 @@ class ArrayAccessTest extends TestCase }', 'error_message' => 'LessSpecificReturnStatement', ], + 'simpleXmlArrayFetchResultCannotEqualString' => [ + ' 'TypeDoesNotContainType', + ], ]; } }