Skip to content

Commit aa38695

Browse files
committed
@mixin above classes with __callStatic() creates static methods
1 parent acb9d70 commit aa38695

File tree

4 files changed

+149
-1
lines changed

4 files changed

+149
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Reflection\Mixin;
4+
5+
use PHPStan\Reflection\ClassMemberReflection;
6+
use PHPStan\Reflection\ClassReflection;
7+
use PHPStan\Reflection\MethodReflection;
8+
use PHPStan\TrinaryLogic;
9+
use PHPStan\Type\Type;
10+
11+
class MixinMethodReflection implements MethodReflection
12+
{
13+
14+
private MethodReflection $reflection;
15+
16+
private bool $static;
17+
18+
public function __construct(MethodReflection $reflection, bool $static)
19+
{
20+
$this->reflection = $reflection;
21+
$this->static = $static;
22+
}
23+
24+
public function getDeclaringClass(): ClassReflection
25+
{
26+
return $this->reflection->getDeclaringClass();
27+
}
28+
29+
public function isStatic(): bool
30+
{
31+
return $this->static;
32+
}
33+
34+
public function isPrivate(): bool
35+
{
36+
return $this->reflection->isPrivate();
37+
}
38+
39+
public function isPublic(): bool
40+
{
41+
return $this->reflection->isPublic();
42+
}
43+
44+
public function getDocComment(): ?string
45+
{
46+
return $this->reflection->getDocComment();
47+
}
48+
49+
public function getName(): string
50+
{
51+
return $this->reflection->getName();
52+
}
53+
54+
public function getPrototype(): ClassMemberReflection
55+
{
56+
return $this->reflection->getPrototype();
57+
}
58+
59+
public function getVariants(): array
60+
{
61+
return $this->reflection->getVariants();
62+
}
63+
64+
public function isDeprecated(): TrinaryLogic
65+
{
66+
return $this->reflection->isDeprecated();
67+
}
68+
69+
public function getDeprecatedDescription(): ?string
70+
{
71+
return $this->reflection->getDeprecatedDescription();
72+
}
73+
74+
public function isFinal(): TrinaryLogic
75+
{
76+
return $this->reflection->isFinal();
77+
}
78+
79+
public function isInternal(): TrinaryLogic
80+
{
81+
return $this->reflection->isInternal();
82+
}
83+
84+
public function getThrowType(): ?Type
85+
{
86+
return $this->reflection->getThrowType();
87+
}
88+
89+
public function hasSideEffects(): TrinaryLogic
90+
{
91+
return $this->reflection->hasSideEffects();
92+
}
93+
94+
}

src/Reflection/Mixin/MixinMethodsClassReflectionExtension.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,17 @@ private function findMethod(ClassReflection $classReflection, string $methodName
4949
continue;
5050
}
5151

52-
return $type->getMethod($methodName, new OutOfClassScope());
52+
$method = $type->getMethod($methodName, new OutOfClassScope());
53+
$static = $method->isStatic();
54+
if (
55+
!$static
56+
&& $classReflection->hasNativeMethod('__callStatic')
57+
&& !$classReflection->hasNativeMethod('__call')
58+
) {
59+
$static = true;
60+
}
61+
62+
return new MixinMethodReflection($method, $static);
5363
}
5464

5565
foreach ($classReflection->getParents() as $parentClass) {

tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php

+11
Original file line numberDiff line numberDiff line change
@@ -362,4 +362,15 @@ public function testBug3448(): void
362362
]);
363363
}
364364

365+
public function testBug3641(): void
366+
{
367+
$this->checkThisOnly = false;
368+
$this->analyse([__DIR__ . '/data/bug-3641.php'], [
369+
[
370+
'Static method Bug3641\Foo::bar() invoked with 1 parameter, 0 required.',
371+
32,
372+
],
373+
]);
374+
}
375+
365376
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Bug3641;
4+
5+
class Foo
6+
{
7+
public function bar(): int
8+
{
9+
return 5;
10+
}
11+
}
12+
13+
/**
14+
* @mixin Foo
15+
*/
16+
class Bar
17+
{
18+
/**
19+
* @param mixed[] $args
20+
* @return mixed
21+
*/
22+
public static function __callStatic(string $method, $args)
23+
{
24+
$instance = new Foo;
25+
26+
return $instance->$method(...$args);
27+
}
28+
}
29+
30+
function (): void {
31+
Bar::bar();
32+
Bar::bar(1);
33+
};

0 commit comments

Comments
 (0)