Skip to content

Commit e27a765

Browse files
committed
Revert "Provide the same functionality in simpler way with stubs"
This reverts commit 846a5fa.
1 parent 783a04d commit e27a765

7 files changed

+188
-121
lines changed

Diff for: extension.neon

+8-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ parameters:
55
- markTestIncomplete
66
- markTestSkipped
77
stubFiles:
8-
- stubs/MockBuilder.stub
98
- stubs/MockObject.stub
10-
- stubs/TestCase.stub
119

1210
services:
1311
-
@@ -26,6 +24,14 @@ services:
2624
class: PHPStan\Type\PHPUnit\Assert\AssertStaticMethodTypeSpecifyingExtension
2725
tags:
2826
- phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension
27+
-
28+
class: PHPStan\Type\PHPUnit\CreateMockDynamicReturnTypeExtension
29+
tags:
30+
- phpstan.broker.dynamicMethodReturnTypeExtension
31+
-
32+
class: PHPStan\Type\PHPUnit\GetMockBuilderDynamicReturnTypeExtension
33+
tags:
34+
- phpstan.broker.dynamicMethodReturnTypeExtension
2935
-
3036
class: PHPStan\Type\PHPUnit\MockBuilderDynamicReturnTypeExtension
3137
tags:
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\PHPUnit;
4+
5+
use PhpParser\Node\Expr\MethodCall;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Reflection\MethodReflection;
8+
use PHPStan\Reflection\ParametersAcceptorSelector;
9+
use PHPStan\Type\Constant\ConstantStringType;
10+
use PHPStan\Type\ObjectType;
11+
use PHPStan\Type\Type;
12+
use PHPStan\Type\TypeCombinator;
13+
14+
class CreateMockDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMethodReturnTypeExtension
15+
{
16+
17+
/** @var int[] */
18+
private $methods = [
19+
'createMock' => 0,
20+
'createConfiguredMock' => 0,
21+
'createPartialMock' => 0,
22+
'createTestProxy' => 0,
23+
'getMockForAbstractClass' => 0,
24+
'getMockFromWsdl' => 1,
25+
];
26+
27+
public function getClass(): string
28+
{
29+
return 'PHPUnit\Framework\TestCase';
30+
}
31+
32+
public function isMethodSupported(MethodReflection $methodReflection): bool
33+
{
34+
return array_key_exists($methodReflection->getName(), $this->methods);
35+
}
36+
37+
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
38+
{
39+
$argumentIndex = $this->methods[$methodReflection->getName()];
40+
$parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
41+
if (!isset($methodCall->args[$argumentIndex])) {
42+
return $parametersAcceptor->getReturnType();
43+
}
44+
$argType = $scope->getType($methodCall->args[$argumentIndex]->value);
45+
if (!$argType instanceof ConstantStringType) {
46+
return $parametersAcceptor->getReturnType();
47+
}
48+
49+
$class = $argType->getValue();
50+
51+
return TypeCombinator::intersect(
52+
new ObjectType($class),
53+
$parametersAcceptor->getReturnType()
54+
);
55+
}
56+
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\PHPUnit;
4+
5+
use PhpParser\Node\Expr\MethodCall;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Reflection\MethodReflection;
8+
use PHPStan\Reflection\ParametersAcceptorSelector;
9+
use PHPStan\Type\Constant\ConstantStringType;
10+
use PHPStan\Type\Type;
11+
use PHPStan\Type\TypeWithClassName;
12+
13+
class GetMockBuilderDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMethodReturnTypeExtension
14+
{
15+
16+
public function getClass(): string
17+
{
18+
return 'PHPUnit\Framework\TestCase';
19+
}
20+
21+
public function isMethodSupported(MethodReflection $methodReflection): bool
22+
{
23+
return $methodReflection->getName() === 'getMockBuilder';
24+
}
25+
26+
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
27+
{
28+
$parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
29+
$mockBuilderType = $parametersAcceptor->getReturnType();
30+
if (count($methodCall->args) === 0) {
31+
return $mockBuilderType;
32+
}
33+
$argType = $scope->getType($methodCall->args[0]->value);
34+
if (!$argType instanceof ConstantStringType) {
35+
return $mockBuilderType;
36+
}
37+
38+
$class = $argType->getValue();
39+
40+
if (!$mockBuilderType instanceof TypeWithClassName) {
41+
throw new \PHPStan\ShouldNotHappenException();
42+
}
43+
44+
return new MockBuilderType($mockBuilderType, $class);
45+
}
46+
47+
}

Diff for: src/Type/PHPUnit/MockBuilderDynamicReturnTypeExtension.php

+43-10
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,67 @@
44

55
use PhpParser\Node\Expr\MethodCall;
66
use PHPStan\Analyser\Scope;
7+
use PHPStan\Broker\Broker;
78
use PHPStan\Reflection\MethodReflection;
9+
use PHPStan\Reflection\ParametersAcceptorSelector;
10+
use PHPStan\Type\ObjectType;
811
use PHPStan\Type\Type;
9-
use PHPUnit\Framework\MockObject\MockBuilder;
12+
use PHPStan\Type\TypeCombinator;
13+
use PHPStan\Type\TypeWithClassName;
1014

11-
class MockBuilderDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMethodReturnTypeExtension
15+
class MockBuilderDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMethodReturnTypeExtension, \PHPStan\Reflection\BrokerAwareExtension
1216
{
1317

18+
/** @var \PHPStan\Broker\Broker */
19+
private $broker;
20+
21+
public function setBroker(Broker $broker): void
22+
{
23+
$this->broker = $broker;
24+
}
25+
1426
public function getClass(): string
1527
{
16-
return MockBuilder::class;
28+
$testCase = $this->broker->getClass('PHPUnit\Framework\TestCase');
29+
$mockBuilderType = ParametersAcceptorSelector::selectSingle(
30+
$testCase->getNativeMethod('getMockBuilder')->getVariants()
31+
)->getReturnType();
32+
if (!$mockBuilderType instanceof TypeWithClassName) {
33+
throw new \PHPStan\ShouldNotHappenException();
34+
}
35+
36+
return $mockBuilderType->getClassName();
1737
}
1838

1939
public function isMethodSupported(MethodReflection $methodReflection): bool
2040
{
21-
return !in_array(
41+
return true;
42+
}
43+
44+
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
45+
{
46+
$calledOnType = $scope->getType($methodCall->var);
47+
if (!in_array(
2248
$methodReflection->getName(),
2349
[
2450
'getMock',
2551
'getMockForAbstractClass',
26-
'getMockForTrait',
2752
],
2853
true
29-
);
30-
}
54+
)) {
55+
return $calledOnType;
56+
}
3157

32-
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
33-
{
34-
return $scope->getType($methodCall->var);
58+
$parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
59+
60+
if (!$calledOnType instanceof MockBuilderType) {
61+
return $parametersAcceptor->getReturnType();
62+
}
63+
64+
return TypeCombinator::intersect(
65+
new ObjectType($calledOnType->getMockedClass()),
66+
$parametersAcceptor->getReturnType()
67+
);
3568
}
3669

3770
}

Diff for: src/Type/PHPUnit/MockBuilderType.php

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\PHPUnit;
4+
5+
use PHPStan\Type\TypeWithClassName;
6+
use PHPStan\Type\VerbosityLevel;
7+
8+
class MockBuilderType extends \PHPStan\Type\ObjectType
9+
{
10+
11+
/** @var string */
12+
private $mockedClass;
13+
14+
public function __construct(
15+
TypeWithClassName $mockBuilderType,
16+
string $mockedClass
17+
)
18+
{
19+
parent::__construct($mockBuilderType->getClassName());
20+
$this->mockedClass = $mockedClass;
21+
}
22+
23+
public function getMockedClass(): string
24+
{
25+
return $this->mockedClass;
26+
}
27+
28+
public function describe(VerbosityLevel $level): string
29+
{
30+
return sprintf('%s<%s>', parent::describe($level), $this->mockedClass);
31+
}
32+
33+
}

Diff for: stubs/MockBuilder.stub

-29
This file was deleted.

Diff for: stubs/TestCase.stub

-80
This file was deleted.

0 commit comments

Comments
 (0)