Skip to content

Commit

Permalink
Fix static magic method pureness not being inherited from traits
Browse files Browse the repository at this point in the history
vimeo#10385 broke this by propagating pseudo static methods from traits to using classes.
`AtomicStaticCallAnalyzer` was then not capable of dealing with this, because now these static pseudo methods actually exist.

I don't actually like this solution. To me it'd seem more appropriate to propagate trait methods directly to the using class in `Populator::inheritMethodsFromParent()`.
But among the related properties of `ClassLikeStorage` (`::$appearing_method_ids`, `::$potential_declaring_method_ids`, `::$overridden_method_ids` and `::$declaring_method_ids`) I got very confused as to how the whole structure is supposed to work and where / whether a method should be added.
  • Loading branch information
tscni committed Nov 29, 2023
1 parent 982f95c commit db97963
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -547,10 +547,11 @@ private static function handleNamedCall(
|| ($found_method_and_class_storage
&& ($config->use_phpdoc_method_without_magic_or_parent || $class_storage->parent_class))
) {
$callstatic_id = new MethodIdentifier(
$fq_class_name,
'__callstatic',
);
$callstatic_id = $class_storage->declaring_method_ids['__callstatic']
?? new MethodIdentifier(
$fq_class_name,
'__callstatic',
);

if ($codebase->methods->methodExists(
$callstatic_id,
Expand Down
75 changes: 75 additions & 0 deletions tests/PureAnnotationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,81 @@ function gimmeFoo(): MyEnum
return MyEnum::FOO();
}',
],
'pureThroughCallStaticInTrait' => [
'code' => '<?php
/**
* @method static static foo()
*/
trait TestTrait {
/** @psalm-pure */
public static function __callStatic(string $name, array $params): static
{
throw new BadMethodCallException("not implemented");
}
}
class Test {
use TestTrait;
}
/** @psalm-pure */
function gimmeFoo(): Test
{
return Test::foo();
}',
],
'pureThroughCallStaticInNestedTrait' => [
'code' => '<?php
/**
* @method static static foo()
*/
trait InnerTestTrait {
/** @psalm-pure */
public static function __callStatic(string $name, array $params): static
{
throw new BadMethodCallException("not implemented");
}
}
trait TestTrait {
use InnerTestTrait;
}
class Test {
use TestTrait;
}
/** @psalm-pure */
function gimmeFoo(): Test
{
return Test::foo();
}',
],
'pureThroughAliasedCallStaticInTrait' => [
'code' => '<?php
/**
* @method static static foo()
*/
trait TestTrait {
/** @psalm-pure */
public static function toBeCallStatic(string $name, array $params): static
{
throw new BadMethodCallException("not implemented");
}
}
class Test {
use TestTrait {
TestTrait::toBeCallStatic as __callStatic;
}
}
/** @psalm-pure */
function gimmeFoo(): Test
{
return Test::foo();
}',
],
'dontCrashWhileCheckingPurityOnCallStaticInATrait' => [
'code' => '<?php
/**
Expand Down

0 comments on commit db97963

Please sign in to comment.