Skip to content

Commit

Permalink
feat(PhpUnit) - add php 8.0 compatibility part 3
Browse files Browse the repository at this point in the history
- Update CodeHelper add support ReflectionUnionType return type
- Update Mockery add support ReflectionUnionType return type
  • Loading branch information
temafey committed Apr 28, 2021
1 parent 2e68470 commit 0c5b82b
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 16 deletions.
15 changes: 12 additions & 3 deletions src/Generator/DataProviderGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ public function addDataProviderMethod(ReflectionClass $reflectionClass, Reflecti
private function getFakeDataForMethodReturnType(ReflectionMethod $method): ?array
{
$typeIsArray = false;
$type = $this->getReturnFromAnnotation($method, false, true);
$type = $this->getReturnFromReflectionMethodAnnotation($method, false, true);

if (null === $type) {
$type = $this->getMethodReturnType($method);
Expand Down Expand Up @@ -710,13 +710,22 @@ private function getFakeData(ReflectionParameter $parameter): array
{
$type = $parameter->getType();

if (null !== $type) {
if (
class_exists('ReflectionUnionType') &&
$type instanceof \ReflectionUnionType
) {
// use only first return type
// @TODO return all return types
$type = $type->getTypes();
$type = array_shift($type);
}
if ($type instanceof \ReflectionNamedType) {
$type = $type->getName();
}

if (null === $type) {
try {
$type = $this->getReturnFromAnnotation($parameter->getDeclaringFunction());
$type = $this->getReturnFromReflectionMethodAnnotation($parameter->getDeclaringFunction());
} catch (ReturnTypeNotFoundException $e) {
if ($this->returnTypeNotFoundThrowable) {
throw $e;
Expand Down
1 change: 1 addition & 0 deletions src/Generator/DataTypeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ interface DataTypeInterface
public const TYPE_THIS = '$this';
public const TYPE_SELF = 'self';
public const TYPE_STATIC = 'static';
public const TYPE_OBJECT = 'object';
public const TYPE_ = '';
}
13 changes: 7 additions & 6 deletions src/Generator/Helper/CodeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ trait CodeHelper
protected $namespaces = [];

/**
* Find and return method return type from annotation.
* Parse and return method return type from DocCOmment of ReflectionMethod object.
*
* @param ReflectionMethod $refMethod
* @param bool $strictMode
Expand All @@ -38,13 +38,13 @@ trait CodeHelper
*
* @throws ReturnTypeNotFoundException
*/
protected function getReturnFromAnnotation(
protected function getReturnFromReflectionMethodAnnotation(
ReflectionMethod $refMethod,
bool $strictMode = true,
bool $returnOrigin = false
): ?string {
$return = [];
$docComment = $refMethod->getDocComment();
$return = [];

if ($docComment) {
preg_match_all('/@return (.*)$/Um', $docComment, $return);
Expand Down Expand Up @@ -534,19 +534,20 @@ protected function getMethodReturnType(ReflectionMethod $reflectionMethod): stri

if (
class_exists('ReflectionUnionType') &&
$returnType instanceof \ReflectionUnionType
$className instanceof \ReflectionUnionType
) {
// use only first return type
// @TODO return all return types
$returnType = array_shift($returnType->getTypes());
$returnTypes = $returnType->getTypes();
$returnType = array_shift($returnTypes);
}
if ($returnType instanceof \ReflectionNamedType) {
$returnType = $returnType->getName();
}
}

if (!$returnType || $returnType === 'array') {
$returnType = $this->getReturnFromAnnotation($reflectionMethod, false, true);
$returnType = $this->getReturnFromReflectionMethodAnnotation($reflectionMethod, false, true);

if (null === $returnType) {
$returnType = DataTypeInterface::TYPE_MIXED;
Expand Down
18 changes: 14 additions & 4 deletions src/Generator/Mock/Mockery.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,12 @@ public function generateMockCode(

if (
class_exists('ReflectionUnionType') &&
$returnType instanceof \ReflectionUnionType
$className instanceof \ReflectionUnionType
) {
// use only first return type
// @TODO return all return types
$returnType = array_shift($returnType->getTypes());
$returnTypes = $returnType->getTypes();
$returnType = array_shift($returnTypes);
}
if ($returnType instanceof \ReflectionNamedType) {
$returnType = $returnType->getName();
Expand All @@ -130,14 +131,18 @@ class_exists('ReflectionUnionType') &&

if (!$returnType) {
try {
$returnType = $this->getReturnFromAnnotation($refMethod);
$returnType = $this->getReturnFromReflectionMethodAnnotation($refMethod);
} catch (ReturnTypeNotFoundException $e) {
if ($this->returnTypeNotFoundThrowable) {
throw $e;
}
$returnType = DataTypeInterface::TYPE_MIXED;
}
}
if (strpos($returnType, '<')) {
//@TODO build mock after analyze <> structure.
$returnType = preg_replace("/\<[^)]+\>/",'', $returnType);
}

$mockMethod = 'if (array_key_exists(\'' . $refMethodName . '\', $mockTimes)) {
$mockMethod = $mock
Expand Down Expand Up @@ -176,7 +181,7 @@ class_exists('ReflectionUnionType') &&
break;

case DataTypeInterface::TYPE_ARRAY:
$returnType = $this->getReturnFromAnnotation($refMethod, false, true);
$returnType = $this->getReturnFromReflectionMethodAnnotation($refMethod, false, true);

if (null === $returnType || $returnType === 'mixed[]') {
$returnType = DataTypeInterface::TYPE_ARRAY;
Expand Down Expand Up @@ -233,6 +238,11 @@ class_exists('ReflectionUnionType') &&

break;

case DataTypeInterface::TYPE_OBJECT:
$mockMethod .= '$mockMethod->andReturn(new class {});';

break;

default:
if (
in_array($returnType, $extendedClasses, true) ||
Expand Down
2 changes: 1 addition & 1 deletion src/Generator/Mock/PhpUnit.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public function generateMockCode(

if (!$returnType) {
try {
$returnType = $this->getReturnFromAnnotation($refMethod);
$returnType = $this->getReturnFromReflectionMethodAnnotation($refMethod);
} catch (ReturnTypeNotFoundException $e) {
if ($this->returnTypeNotFoundThrowable) {
throw $e;
Expand Down
37 changes: 35 additions & 2 deletions src/Generator/TestGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,21 @@ protected function processMethodDocComment(ReflectionClass $reflectionClass, Ref
$argumentInitialize = '$' . $param->getName() . ' = ';

if (null !== $param->getType()) {
$annotationParams[$i] = $param->getType()->getName();
$returnType = $param->getType();

if (
class_exists('ReflectionUnionType') &&
$returnType instanceof \ReflectionUnionType
) {
// use only first return type
// @TODO return all return types
$returnTypes = $returnType->getTypes();
$returnType = array_shift($returnTypes);
}
if ($returnType instanceof \ReflectionNamedType) {
$returnType = $returnType->getName();
}
$annotationParams[$i] = $returnType;
} elseif (isset($annotationParams[$i])) {
$annotationParam = $this->findAndReturnClassNameFromUseStatement($annotationParams[$i], $reflectionClass);

Expand Down Expand Up @@ -768,10 +782,16 @@ protected function processMethodDocComment(ReflectionClass $reflectionClass, Ref
break;

case DataTypeInterface::TYPE_CLOSURE:
case DataTypeInterface::TYPE_CALLABLE:
$argumentInitialize .= 'function () { return true; }';

break;

case DataTypeInterface::TYPE_OBJECT:
$argumentInitialize .= 'new class {}';

break;

default:
if (
false === $excludeConstructor &&
Expand All @@ -788,7 +808,20 @@ protected function processMethodDocComment(ReflectionClass $reflectionClass, Ref
}

if (!$excludeConstructor && $param->getType()) {
$className = (string) $param->getType() ?: $annotationParams[$i];
$className = $param->getType() ?: $this->getReturnFromReflectionMethodAnnotation($reflectionMethod);

if (
class_exists('ReflectionUnionType') &&
$className instanceof \ReflectionUnionType
) {
// use only first return type
// @TODO return all return types
$className = $className->getTypes();
$className = array_shift($className);
}
if ($className instanceof \ReflectionNamedType) {
$className = $className->getName();
}

if (null === $className) {
throw new InvalidClassnameException(sprintf('Class name could not be null.'));
Expand Down

0 comments on commit 0c5b82b

Please sign in to comment.