Skip to content
Permalink
Browse files

Add more specific UndefinedMagicMethod issue

  • Loading branch information
muglug committed Jan 6, 2020
1 parent 8e786a1 commit 083fbc55e1f67c4eff6ccc6eb8569ebad3eb5528
@@ -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\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 @@ public static function analyze(

$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 @@ public static function analyze(
$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 @@ public static function analyze(
}
}

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 @@ public static function analyze(
* @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 @@ private static function analyzeAtomicCall(
&$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 @@ private static function analyzeAtomicCall(
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 @@ private static function analyzeAtomicCall(
$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 @@ private static function analyzeAtomicCall(
}

if ($class_storage->sealed_methods) {
$non_existent_class_method_ids[] = $method_id;
$non_existent_magic_method_ids[] = $method_id;
return true;
}
}
@@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;

class UndefinedMagicMethod extends MethodIssue
{
}
@@ -591,7 +591,7 @@ class Child extends ParentClass {}
$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

0 comments on commit 083fbc5

Please sign in to comment.
You can’t perform that action at this time.