Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 51521f4

Browse files
Improve
1 parent fe51050 commit 51521f4

File tree

5 files changed

+95
-12
lines changed

5 files changed

+95
-12
lines changed

‎extension.neon‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ services:
5151
class: PHPStan\Type\PHPUnit\MockForIntersectionDynamicReturnTypeExtension
5252
tags:
5353
- phpstan.broker.dynamicMethodReturnTypeExtension
54+
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
5455
-
5556
class: PHPStan\Rules\PHPUnit\CoversHelper
5657
-

‎src/Type/PHPUnit/MockForIntersectionDynamicReturnTypeExtension.php‎

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,23 @@
22

33
namespace PHPStan\Type\PHPUnit;
44

5+
use PhpParser\Node\Arg;
56
use PhpParser\Node\Expr\MethodCall;
7+
use PhpParser\Node\Expr\StaticCall;
68
use PHPStan\Analyser\Scope;
79
use PHPStan\Reflection\MethodReflection;
810
use PHPStan\Type\DynamicMethodReturnTypeExtension;
11+
use PHPStan\Type\DynamicStaticMethodReturnTypeExtension;
912
use PHPStan\Type\ObjectType;
1013
use PHPStan\Type\Type;
1114
use PHPStan\Type\TypeCombinator;
1215
use PHPUnit\Framework\MockObject\MockObject;
1316
use PHPUnit\Framework\MockObject\Stub;
1417
use PHPUnit\Framework\TestCase;
1518
use function count;
16-
use function in_array;
19+
use function strtolower;
1720

18-
class MockForIntersectionDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
21+
class MockForIntersectionDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension, DynamicStaticMethodReturnTypeExtension
1922
{
2023

2124
public function getClass(): string
@@ -25,19 +28,29 @@ public function getClass(): string
2528

2629
public function isMethodSupported(MethodReflection $methodReflection): bool
2730
{
28-
return in_array(
29-
$methodReflection->getName(),
30-
[
31-
'createMockForIntersectionOfInterfaces',
32-
'createStubForIntersectionOfInterfaces',
33-
],
34-
true,
35-
);
31+
return strtolower($methodReflection->getName()) === 'createmockforintersectionofinterfaces';
32+
}
33+
34+
public function isStaticMethodSupported(MethodReflection $methodReflection): bool
35+
{
36+
return strtolower($methodReflection->getName()) === 'createstubforintersectionofinterfaces';
37+
}
38+
39+
public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): ?Type
40+
{
41+
return $this->getTypeFromCall($methodReflection, $methodCall->getArgs(), $scope);
3642
}
3743

3844
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type
3945
{
40-
$args = $methodCall->getArgs();
46+
return $this->getTypeFromCall($methodReflection, $methodCall->getArgs(), $scope);
47+
}
48+
49+
/**
50+
* @param array<Arg> $args
51+
*/
52+
private function getTypeFromCall(MethodReflection $methodReflection, array $args, Scope $scope): ?Type
53+
{
4154
if (!isset($args[0])) {
4255
return null;
4356
}

‎tests/Rules/PHPUnit/data/mock-method-call.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function testMockForIntersection()
5151

5252
public function testStubForIntersection()
5353
{
54-
$stub = $this->createStubForIntersectionOfInterfaces([FooInterface::class, BarInterface::class]);
54+
$stub = static::createStubForIntersectionOfInterfaces([FooInterface::class, BarInterface::class]);
5555
$stub->method('fooMethod');
5656
$stub->method('barMethod');
5757
$stub->method('bazMethod');
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\PHPUnit;
4+
5+
use PHPStan\Testing\TypeInferenceTestCase;
6+
use PHPUnit\Framework\Attributes\DataProvider;
7+
use PHPUnit\Framework\TestCase;
8+
use function method_exists;
9+
10+
class MockForIntersectionDynamicReturnTypeExtensionTest extends TypeInferenceTestCase
11+
{
12+
13+
/** @return mixed[] */
14+
public static function dataFileAsserts(): iterable
15+
{
16+
if (method_exists(TestCase::class, 'createMockForIntersectionOfInterfaces')) { // @phpstan-ignore-line
17+
yield from self::gatherAssertTypes(__DIR__ . '/data/mock-for-intersection.php');
18+
}
19+
20+
return [];
21+
}
22+
23+
/**
24+
* @dataProvider dataFileAsserts
25+
* @param mixed ...$args
26+
*/
27+
#[DataProvider('dataFileAsserts')]
28+
public function testFileAsserts(
29+
string $assertType,
30+
string $file,
31+
...$args
32+
): void
33+
{
34+
$this->assertFileAsserts($assertType, $file, ...$args);
35+
}
36+
37+
public static function getAdditionalConfigFiles(): array
38+
{
39+
return [__DIR__ . '/../../../extension.neon'];
40+
}
41+
42+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace MockForIntersection;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class Foo extends TestCase
10+
{
11+
12+
public function inheritedAssertMethodsNarrowType(?string $s): void
13+
{
14+
assertType(
15+
'MockForIntersection\BarInterface&MockForIntersection\FooInterface&PHPUnit\Framework\MockObject\MockObject',
16+
$this->createMockForIntersectionOfInterfaces([FooInterface::class, BarInterface::class]),
17+
);
18+
assertType(
19+
'MockForIntersection\BarInterface&MockForIntersection\FooInterface&PHPUnit\Framework\MockObject\Stub',
20+
self::createStubForIntersectionOfInterfaces([FooInterface::class, BarInterface::class]),
21+
);
22+
}
23+
24+
}
25+
26+
interface FooInterface {}
27+
interface BarInterface {}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /