1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 12:24:49 +01:00

Fix #299 - add PossiblyInvalidMethodCall

This commit is contained in:
Matt Brown 2017-11-15 11:34:40 -05:00
parent 9111b1c725
commit c5faa2d06a
4 changed files with 61 additions and 9 deletions

View File

@ -158,6 +158,8 @@
<xs:element name="PossiblyFalseReference" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyInvalidArgument" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyInvalidArrayAccess" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyInvalidMethodCall" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyInvalidPropertyAssignment" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyNullArgument" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyNullArrayAccess" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyNullFunctionCall" type="IssueHandlerType" minOccurs="0" />

View File

@ -35,6 +35,7 @@ use Psalm\Issue\ParentNotFound;
use Psalm\Issue\PossiblyFalseArgument;
use Psalm\Issue\PossiblyFalseReference;
use Psalm\Issue\PossiblyInvalidArgument;
use Psalm\Issue\PossiblyInvalidMethodCall;
use Psalm\Issue\PossiblyNullArgument;
use Psalm\Issue\PossiblyNullFunctionCall;
use Psalm\Issue\PossiblyNullReference;
@ -764,6 +765,9 @@ class CallChecker
$non_existent_method_ids = [];
$existent_method_ids = [];
$invalid_method_call_types = [];
$has_valid_method_call_type = false;
$code_location = new CodeLocation($source, $stmt);
if ($class_type && is_string($stmt->name)) {
@ -782,15 +786,7 @@ class CallChecker
case 'Psalm\\Type\\Atomic\\TArray':
case 'Psalm\\Type\\Atomic\\TString':
case 'Psalm\\Type\\Atomic\\TNumericString':
if (IssueBuffer::accepts(
new InvalidMethodCall(
'Cannot call method ' . $stmt->name . ' on ' . $class_type . ' variable ' . $var_id,
$code_location
),
$statements_checker->getSuppressedIssues()
)) {
return false;
}
$invalid_method_call_types[] = (string)$class_type_part;
break;
case 'Psalm\\Type\\Atomic\\TMixed':
@ -810,6 +806,8 @@ class CallChecker
continue;
}
$has_valid_method_call_type = true;
$fq_class_name = $class_type_part->value;
$intersection_types = $class_type_part->getIntersectionTypes();
@ -1030,6 +1028,32 @@ class CallChecker
}
}
if ($invalid_method_call_types) {
$class_type = $invalid_method_call_types[0];
if ($has_valid_method_call_type) {
if (IssueBuffer::accepts(
new PossiblyInvalidMethodCall(
'Cannot call method on possible ' . $class_type . ' variable ' . $var_id,
$code_location
),
$statements_checker->getSuppressedIssues()
)) {
return false;
}
} else {
if (IssueBuffer::accepts(
new InvalidMethodCall(
'Cannot call method on ' . $class_type . ' variable ' . $var_id,
$code_location
),
$statements_checker->getSuppressedIssues()
)) {
return false;
}
}
}
if ($non_existent_method_ids) {
if ($existent_method_ids) {
if (IssueBuffer::accepts(

View File

@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;
class PossiblyInvalidMethodCall extends CodeError
{
}

View File

@ -118,6 +118,26 @@ class MethodCallTest extends TestCase
'MixedAssignment',
],
],
'invalidMethodCall' => [
'<?php
("hello")->someMethod();',
'error_message' => 'InvalidMethodCall',
],
'possiblyInvalidMethodCall' => [
'<?php
class A1 {
public function methodOfA(): void {
}
}
/** @param A1|string $x */
function example($x, bool $isObject) {
if ($isObject) {
$x->methodOfA();
}
}',
'error_message' => 'PossiblyInvalidMethodCall',
],
'selfNonStaticInvocation' => [
'<?php
class A {