mirror of
https://github.com/danog/psalm.git
synced 2024-11-29 20:28:59 +01:00
Add more specific UndefinedMagicMethod issue
This commit is contained in:
parent
8e786a17dd
commit
083fbc55e1
@ -341,6 +341,7 @@
|
||||
<xs:element name="UndefinedFunction" type="FunctionIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UndefinedInterface" type="ClassIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UndefinedInterfaceMethod" type="MethodIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UndefinedMagicMethod" type="MethodIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UndefinedMagicPropertyAssignment" type="PropertyIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UndefinedMagicPropertyFetch" type="PropertyIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UndefinedMethod" type="MethodIssueHandlerType" minOccurs="0" />
|
||||
|
@ -2304,6 +2304,22 @@ class C {}
|
||||
interface I extends C {}
|
||||
```
|
||||
|
||||
### UndefinedMagicMethod
|
||||
|
||||
Emitted when calling a magic method that doesn’t exist
|
||||
|
||||
```php
|
||||
/**
|
||||
* @method bar():string
|
||||
*/
|
||||
class A {
|
||||
public function __call(string $name, array $args) {
|
||||
return "cool";
|
||||
}
|
||||
}
|
||||
(new A)->foo();
|
||||
```
|
||||
|
||||
### UndefinedMagicPropertyAssignment
|
||||
|
||||
Emitted when assigning a property on an object that doesn’t have that magic property defined
|
||||
|
@ -27,6 +27,7 @@ use Psalm\Issue\PossiblyNullReference;
|
||||
use Psalm\Issue\PossiblyUndefinedMethod;
|
||||
use Psalm\Issue\PropertyTypeCoercion;
|
||||
use Psalm\Issue\UndefinedInterfaceMethod;
|
||||
use Psalm\Issue\UndefinedMagicMethod;
|
||||
use Psalm\Issue\UndefinedMethod;
|
||||
use Psalm\Issue\UndefinedThisPropertyAssignment;
|
||||
use Psalm\Issue\UndefinedThisPropertyFetch;
|
||||
@ -188,6 +189,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
|
||||
$non_existent_class_method_ids = [];
|
||||
$non_existent_interface_method_ids = [];
|
||||
$non_existent_magic_method_ids = [];
|
||||
$existent_method_ids = [];
|
||||
$has_mixed_method_call = false;
|
||||
|
||||
@ -228,7 +230,8 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$invalid_method_call_types,
|
||||
$existent_method_ids,
|
||||
$non_existent_class_method_ids,
|
||||
$non_existent_interface_method_ids
|
||||
$non_existent_interface_method_ids,
|
||||
$non_existent_magic_method_ids
|
||||
);
|
||||
|
||||
if ($result === false) {
|
||||
@ -266,6 +269,21 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
}
|
||||
}
|
||||
|
||||
if ($non_existent_magic_method_ids) {
|
||||
if ($context->check_methods) {
|
||||
if (IssueBuffer::accepts(
|
||||
new UndefinedMagicMethod(
|
||||
'Magic method ' . $non_existent_magic_method_ids[0] . ' does not exist',
|
||||
new CodeLocation($source, $stmt->name),
|
||||
$non_existent_magic_method_ids[0]
|
||||
),
|
||||
$statements_analyzer->getSuppressedIssues()
|
||||
)) {
|
||||
// keep going
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($non_existent_class_method_ids) {
|
||||
if ($context->check_methods) {
|
||||
if ($existent_method_ids || $has_mixed_method_call) {
|
||||
@ -417,6 +435,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
* @param array<string> &$existent_method_ids
|
||||
* @param array<string> &$non_existent_class_method_ids
|
||||
* @param array<string> &$non_existent_interface_method_ids
|
||||
* @param array<string> &$non_existent_magic_method_ids
|
||||
* @return null|bool
|
||||
*/
|
||||
private static function analyzeAtomicCall(
|
||||
@ -436,6 +455,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
&$existent_method_ids,
|
||||
&$non_existent_class_method_ids,
|
||||
&$non_existent_interface_method_ids,
|
||||
&$non_existent_magic_method_ids,
|
||||
bool &$check_visibility = true
|
||||
) {
|
||||
$config = $codebase->config;
|
||||
@ -638,6 +658,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
foreach ($intersection_types as $intersection_type) {
|
||||
$i_non_existent_class_method_ids = [];
|
||||
$i_non_existent_interface_method_ids = [];
|
||||
$i_non_existent_magic_method_ids = [];
|
||||
|
||||
$intersection_return_type = null;
|
||||
|
||||
@ -658,6 +679,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$all_intersection_existent_method_ids,
|
||||
$i_non_existent_class_method_ids,
|
||||
$i_non_existent_interface_method_ids,
|
||||
$i_non_existent_magic_method_ids,
|
||||
$check_visibility
|
||||
);
|
||||
|
||||
@ -801,7 +823,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
}
|
||||
|
||||
if ($class_storage->sealed_methods) {
|
||||
$non_existent_class_method_ids[] = $method_id;
|
||||
$non_existent_magic_method_ids[] = $method_id;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
6
src/Psalm/Issue/UndefinedMagicMethod.php
Normal file
6
src/Psalm/Issue/UndefinedMagicMethod.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace Psalm\Issue;
|
||||
|
||||
class UndefinedMagicMethod extends MethodIssue
|
||||
{
|
||||
}
|
@ -591,7 +591,7 @@ class MagicMethodAnnotationTest extends TestCase
|
||||
$child = new Child();
|
||||
$child->getString();
|
||||
$child->foo();',
|
||||
'error_message' => 'UndefinedMethod - src' . DIRECTORY_SEPARATOR . 'somefile.php:13:29 - Method Child::foo does not exist',
|
||||
'error_message' => 'UndefinedMagicMethod - src' . DIRECTORY_SEPARATOR . 'somefile.php:13:29 - Magic method Child::foo does not exist',
|
||||
],
|
||||
'annotationInvalidArg' => [
|
||||
'<?php
|
||||
|
Loading…
Reference in New Issue
Block a user