mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
Fix trait method aliasing
This commit is contained in:
parent
cb15f48406
commit
49c4dd8a5d
@ -275,13 +275,26 @@ class MethodCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
|
||||
}
|
||||
}
|
||||
|
||||
if ($var_id === '$this' &&
|
||||
$context->self &&
|
||||
$fq_class_name !== $context->self &&
|
||||
$codebase->methodExists($context->self . '::' . $method_name_lc)
|
||||
$source_source = $statements_checker->getSource();
|
||||
|
||||
/**
|
||||
* @var \Psalm\Checker\ClassLikeChecker|null
|
||||
*/
|
||||
$classlike_source = $source_source->getSource();
|
||||
$classlike_source_fqcln = $classlike_source ? $classlike_source->getFQCLN() : null;
|
||||
|
||||
if ($var_id === '$this' && $context->self && $classlike_source_fqcln) {
|
||||
if ($fq_class_name !== $context->self
|
||||
&& $codebase->methodExists($context->self . '::' . $method_name_lc)
|
||||
) {
|
||||
$method_id = $context->self . '::' . $method_name_lc;
|
||||
$fq_class_name = $context->self;
|
||||
} elseif ($classlike_source instanceof \Psalm\Checker\TraitChecker
|
||||
&& $codebase->methodExists($classlike_source_fqcln . '::' . $method_name_lc)
|
||||
) {
|
||||
$method_id = $classlike_source_fqcln . '::' . $method_name_lc;
|
||||
$fq_class_name = $classlike_source_fqcln;
|
||||
}
|
||||
}
|
||||
|
||||
if ($intersection_types && !$codebase->methodExists($method_id)) {
|
||||
|
@ -460,15 +460,16 @@ class Populator
|
||||
|
||||
// register where they appear (can never be in a trait)
|
||||
foreach ($parent_storage->appearing_method_ids as $method_name => $appearing_method_id) {
|
||||
$aliased_method_names = [$method_name];
|
||||
|
||||
if ($parent_storage->is_trait
|
||||
&& $storage->trait_alias_map
|
||||
&& isset($storage->trait_alias_map[$method_name])
|
||||
) {
|
||||
$aliased_method_name = $storage->trait_alias_map[$method_name];
|
||||
} else {
|
||||
$aliased_method_name = $method_name;
|
||||
$aliased_method_names[] = $storage->trait_alias_map[$method_name];
|
||||
}
|
||||
|
||||
foreach ($aliased_method_names as $aliased_method_name) {
|
||||
if (isset($storage->appearing_method_ids[$aliased_method_name])) {
|
||||
continue;
|
||||
}
|
||||
@ -478,6 +479,7 @@ class Populator
|
||||
$storage->appearing_method_ids[$aliased_method_name] =
|
||||
$parent_storage->is_trait ? $implemented_method_id : $appearing_method_id;
|
||||
}
|
||||
}
|
||||
|
||||
// register where they're declared
|
||||
foreach ($parent_storage->inheritable_method_ids as $method_name => $declaring_method_id) {
|
||||
@ -485,15 +487,16 @@ class Populator
|
||||
$storage->overridden_method_ids[$method_name][] = $declaring_method_id;
|
||||
}
|
||||
|
||||
$aliased_method_names = [$method_name];
|
||||
|
||||
if ($parent_storage->is_trait
|
||||
&& $storage->trait_alias_map
|
||||
&& isset($storage->trait_alias_map[$method_name])
|
||||
) {
|
||||
$aliased_method_name = $storage->trait_alias_map[$method_name];
|
||||
} else {
|
||||
$aliased_method_name = $method_name;
|
||||
$aliased_method_names[] = $storage->trait_alias_map[$method_name];
|
||||
}
|
||||
|
||||
foreach ($aliased_method_names as $aliased_method_name) {
|
||||
if (isset($storage->declaring_method_ids[$aliased_method_name])) {
|
||||
list($implementing_fq_class_name, $implementing_method_name) = explode(
|
||||
'::',
|
||||
@ -511,6 +514,7 @@ class Populator
|
||||
$storage->inheritable_method_ids[$aliased_method_name] = $declaring_method_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassLikeStorage $storage
|
||||
|
@ -450,6 +450,54 @@ class TraitTest extends TestCase
|
||||
}
|
||||
}',
|
||||
],
|
||||
'aliasedMethodInternalCallNoReplacement' => [
|
||||
'<?php
|
||||
trait T {
|
||||
public function foo() : int {
|
||||
return $this->bar();
|
||||
}
|
||||
|
||||
public function bar() : int {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
use T {
|
||||
bar as bat;
|
||||
}
|
||||
|
||||
public function baz() : int {
|
||||
return $this->bar();
|
||||
}
|
||||
}',
|
||||
],
|
||||
'aliasedMethodInternalCallWithLocalDefinition' => [
|
||||
'<?php
|
||||
trait T {
|
||||
public function foo() : int {
|
||||
return $this->bar();
|
||||
}
|
||||
|
||||
public function bar() : int {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
use T {
|
||||
bar as bat;
|
||||
}
|
||||
|
||||
public function bar() : string {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
public function baz() : string {
|
||||
return $this->bar();
|
||||
}
|
||||
}',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user