Skip to content

Commit

Permalink
Merge pull request #910 from beberlei/Php8support
Browse files Browse the repository at this point in the history
Add support for union types and mixed type in ProxyGenerator
  • Loading branch information
beberlei authored Dec 3, 2020
2 parents bd6f2f4 + e62bda5 commit 9f3e3f3
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 26 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
matrix:
php-version:
- "7.4"
- "8.0"

steps:
- name: "Checkout code"
Expand All @@ -43,3 +43,4 @@ jobs:

- name: "Run a static analysis with phpstan/phpstan"
run: "vendor/bin/phpstan analyse"
continue-on-error: true
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"require-dev": {
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^7.5.20 || ^8.0 || ^9.0",
"phpunit/phpunit": "^7.5.20 || ^8.5 || ^9.0",
"doctrine/coding-standard": "^6.0 || ^8.0",
"squizlabs/php_codesniffer": "^3.0",
"symfony/phpunit-bridge": "^4.0.5"
Expand Down
16 changes: 15 additions & 1 deletion lib/Doctrine/Common/Proxy/ProxyGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use ReflectionNamedType;
use ReflectionParameter;
use ReflectionProperty;
use ReflectionType;
use ReflectionUnionType;

use function array_combine;
use function array_diff;
Expand Down Expand Up @@ -1108,10 +1110,21 @@ private function shouldProxiedMethodReturn(ReflectionMethod $method)
* @return string
*/
private function formatType(
ReflectionNamedType $type,
ReflectionType $type,
ReflectionMethod $method,
?ReflectionParameter $parameter = null
) {
if ($type instanceof ReflectionUnionType) {
return implode('|', array_map(
function (ReflectionType $unionedType) use ($method, $parameter) {
return $this->formatType($unionedType, $method, $parameter);
},
$type->getTypes()
));
}

assert($type instanceof ReflectionNamedType);

$name = $type->getName();
$nameLower = strtolower($name);

Expand Down Expand Up @@ -1145,6 +1158,7 @@ private function formatType(
if (
$type->allowsNull()
&& ($parameter === null || ! $parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== null)
&& $name !== 'mixed'
) {
$name = '?' . $name;
}
Expand Down
8 changes: 6 additions & 2 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ parameters:
- lib/vendor/doctrine-build-common
- tests/Doctrine/Tests/Common/Proxy/InvalidReturnTypeClass.php
- tests/Doctrine/Tests/Common/Proxy/InvalidTypeHintClass.php
- tests/Doctrine/Tests/Common/Proxy/LazyLoadableObjectWithTypedProperties.php
- tests/Doctrine/Tests/Common/Proxy/MagicIssetClassWithInteger.php
- tests/Doctrine/Tests/Common/Proxy/NullableNonOptionalHintClass.php
- tests/Doctrine/Tests/Common/Proxy/Php8UnionTypes.php
- tests/Doctrine/Tests/Common/Proxy/ProxyGeneratorTest.php
- tests/Doctrine/Tests/Common/Proxy/ProxyLogicTypedPropertiesTest.php
- tests/Doctrine/Tests/Common/Proxy/SerializedClass.php
- tests/Doctrine/Tests/Common/Proxy/VariadicTypeHintClass.php
- tests/Doctrine/Tests/Common/Proxy/ProxyLogicTypedPropertiesTest.php
- tests/Doctrine/Tests/Common/Proxy/LazyLoadableObjectWithTypedProperties.php
- tests/Doctrine/Tests/Common/Proxy/generated
ignoreErrors:
- '#Access to an undefined property Doctrine\\Common\\Proxy\\Proxy::\$publicField#'
Expand Down
46 changes: 25 additions & 21 deletions tests/Doctrine/Tests/Common/Proxy/MagicIssetClassWithInteger.php
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
<?php

if (PHP_VERSION_ID < 80000) {
eval(<<<'BROKEN_CODE'
namespace Doctrine\Tests\Common\Proxy;
use BadMethodCallException;

/**
* Test asset class
*/
class MagicIssetClassWithInteger
{
/** @var string */
public $id = 'id';

/** @var string */
public $publicField = 'publicField';

/**
* @throws BadMethodCallException
* Test asset class
*/
public function __isset(string $name) : int
class MagicIssetClassWithInteger
{
if ($name === 'test') {
return 1;
}
/** @var string */
public $id = 'id';
if ($name === 'publicField' || $name === 'id') {
throw new BadMethodCallException('Should never be called for "publicField" or "id"');
}
/** @var string */
public $publicField = 'publicField';
/**
* @throws BadMethodCallException
*/
public function __isset(string $name) : int
{
if ($name === 'test') {
return 1;
}
return 0;
if ($name === 'publicField' || $name === 'id') {
throw new BadMethodCallException('Should never be called for "publicField" or "id"');
}
return 0;
}
}
BROKEN_CODE
);
}
11 changes: 11 additions & 0 deletions tests/Doctrine/Tests/Common/Proxy/Php8MixedType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Doctrine\Tests\Common\Proxy;

class Php8MixedType
{
public function foo(mixed $bar) : mixed
{
return 1;
}
}
14 changes: 14 additions & 0 deletions tests/Doctrine/Tests/Common/Proxy/Php8UnionTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Doctrine\Tests\Common\Proxy;

use stdClass;

class Php8UnionTypes
{
public string|int $foo;

public function setValue(stdClass|array $value) : bool|float
{
}
}
42 changes: 42 additions & 0 deletions tests/Doctrine/Tests/Common/Proxy/ProxyGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use function is_subclass_of;
use function substr_count;

use const PHP_VERSION_ID;

/**
* Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy
* pattern.
Expand Down Expand Up @@ -403,6 +405,46 @@ public function testFinalClassThrowsException()
$proxyGenerator->generateProxyClass($this->createClassMetadata(FinalClass::class, []));
}

/**
* @requires PHP >= 8.0.0
*/
public function testPhp8UnionTypes()
{
$className = Php8UnionTypes::class;

if ( ! class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\Php8UnionTypes', false)) {
$metadata = $this->createClassMetadata($className, ['id']);

$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy');
$this->generateAndRequire($proxyGenerator, $metadata);
}

self::assertStringContainsString(
'setValue(\stdClass|array $value): float|bool',
file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyPhp8UnionTypes.php')
);
}

/**
* @requires PHP >= 8.0.0
*/
public function testPhp8MixedType()
{
$className = Php8MixedType::class;

if ( ! class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\Php8MixedType', false)) {
$metadata = $this->createClassMetadata($className, ['id']);

$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy');
$this->generateAndRequire($proxyGenerator, $metadata);
}

self::assertStringContainsString(
'foo(mixed $bar): mixed',
file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyPhp8MixedType.php')
);
}

/**
* @param string $className
* @param mixed[] $ids
Expand Down

0 comments on commit 9f3e3f3

Please sign in to comment.