Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lookyman/dfa3a46b6685b8e63e92b72a32b849ee to your computer and use it in GitHub Desktop.
Save lookyman/dfa3a46b6685b8e63e92b72a32b849ee to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace PHPStan\Type\PHPUnit;
use Nette\PhpGenerator\ClassType;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPUnit\Framework\TestCase;
class TestCaseCreateMockDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
{
public static function getClass(): string
{
return TestCase::class;
}
public function isMethodSupported(MethodReflection $methodReflection): bool
{
return $methodReflection->getName() === 'createMock';
}
public function getTypeFromMethodCall(
MethodReflection $methodReflection,
MethodCall $methodCall,
Scope $scope
): Type {
$class = (string) $methodCall->args[0]->value->class;
if ($class === 'static') {
return $methodReflection->getReturnType();
} elseif ($class === 'self') {
$class = $scope->getClass();
}
$rc = new \ReflectionClass($class);
if ($rc->isFinal() || $rc->isTrait()) {
return $methodReflection->getReturnType();
}
$proxy = 'proxyClass___' . md5($class);
$this->generateProxy($rc, $proxy);
return new ObjectType($proxy, false);
}
private function generateProxy(\ReflectionClass $rc, string $name)
{
$class = new ClassType($name);
$class->setAbstract();
$class->addImplement(\PHPUnit_Framework_MockObject_MockObject::class);
$rc->isInterface() ? $class->addImplement($rc->getName()) : $class->setExtends($rc->getName());
if (!class_exists($name)) {
eval((string) $class);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment