Skip to content

Commit

Permalink
Closes #14
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Oct 6, 2020
1 parent 98aaa5f commit 2167139
Show file tree
Hide file tree
Showing 10 changed files with 344 additions and 36 deletions.
47 changes: 12 additions & 35 deletions .psalm/baseline.xml
Original file line number Diff line number Diff line change
@@ -1,48 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="3.11.4@58e1d8e68e5098bf4fbfdfb420c38d563f882549">
<file src="src/CallableType.php">
<MixedArgument occurrences="7">
<code>$type-&gt;value()</code>
<code>$type-&gt;value()</code>
<code>$object</code>
<code>$methodName</code>
<code>$type-&gt;value()</code>
<code>$type-&gt;value()</code>
<code>$type-&gt;value()</code>
</MixedArgument>
<MixedArrayAccess occurrences="8">
<code>$type-&gt;value()[0]</code>
<code>$type-&gt;value()[1]</code>
<code>$object</code>
<code>$methodName</code>
<code>$type-&gt;value()[0]</code>
<code>$type-&gt;value()[1]</code>
<code>$className</code>
<code>$methodName</code>
</MixedArrayAccess>
<MixedAssignment occurrences="2">
<code>[$object, $methodName]</code>
<code>[$className, $methodName]</code>
</MixedAssignment>
</file>
<files psalm-version="3.16@d03e5ef057d6adc656c0ff7e166c50b73b4f48f3">
<file src="src/ReflectionMapper.php">
<MixedArgument occurrences="2">
<code>$returnType instanceof ReflectionNamedType || $returnType instanceof ReflectionUnionType</code>
<code>$type-&gt;getName()</code>
<InvalidCast occurrences="1">
<code>$returnType</code>
</InvalidCast>
<MixedArgument occurrences="1">
<code>$returnType instanceof ReflectionUnionType</code>
</MixedArgument>
<MixedAssignment occurrences="1">
<code>$type</code>
</MixedAssignment>
<MixedMethodCall occurrences="2">
<code>getName</code>
<code>getName</code>
</MixedMethodCall>
<RedundantConditionGivenDocblockType occurrences="1">
<code>assert($returnType instanceof ReflectionUnionType)</code>
</RedundantConditionGivenDocblockType>
<TypeDoesNotContainType occurrences="1">
<code>assert($returnType instanceof ReflectionNamedType || $returnType instanceof ReflectionUnionType)</code>
</TypeDoesNotContainType>
<UndefinedClass occurrences="2">
<code>ReflectionUnionType</code>
<UndefinedClass occurrences="3">
<code>$returnType</code>
<code>ReflectionUnionType</code>
<code>ReflectionUnionType</code>
</UndefinedClass>
</file>
<file src="src/SimpleType.php">
Expand Down
7 changes: 7 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.

## [2.3.0] - 2020-MM-DD

### Added

* [#14](https://github.com/sebastianbergmann/type/issues/14): Support for `static` return type that is introduced in PHP 8

## [2.2.2] - 2020-09-28

### Changed
Expand Down Expand Up @@ -77,6 +83,7 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt

* Initial release based on [code contributed by Michel Hartmann to PHPUnit](https://github.com/sebastianbergmann/phpunit/pull/3673)

[2.3.0]: https://github.com/sebastianbergmann/type/compare/2.2.2...master
[2.2.2]: https://github.com/sebastianbergmann/type/compare/2.2.1...2.2.2
[2.2.1]: https://github.com/sebastianbergmann/type/compare/2.2.0...2.2.1
[2.2.0]: https://github.com/sebastianbergmann/type/compare/2.1.1...2.2.0
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
"dev-master": "2.3-dev"
}
}
}
17 changes: 17 additions & 0 deletions src/ReflectionMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ public function fromMethodReturnType(ReflectionMethod $method): Type
);
}

if ($returnType->getName() === 'static') {
return new StaticType(
TypeName::fromReflection($method->getDeclaringClass()),
$returnType->allowsNull()
);
}

if ($returnType->getName() === 'mixed') {
return new MixedType;
}
Expand Down Expand Up @@ -71,6 +78,16 @@ public function fromMethodReturnType(ReflectionMethod $method): Type

$types = [];

/* @see Workaround for https://github.com/sebastianbergmann/type/issues/14 */
foreach (explode('|', (string) $returnType) as $type) {
if ($type === 'static') {
$types[] = new StaticType(
TypeName::fromReflection($method->getDeclaringClass()),
false
);
}
}

foreach ($returnType->getTypes() as $type) {
assert($type instanceof ReflectionNamedType);

Expand Down
60 changes: 60 additions & 0 deletions src/StaticType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/type.
*
* (c) Sebastian Bergmann <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Type;

final class StaticType extends Type
{
/**
* @var TypeName
*/
private $className;

/**
* @var bool
*/
private $allowsNull;

public function __construct(TypeName $className, bool $allowsNull)
{
$this->className = $className;
$this->allowsNull = $allowsNull;
}

public function isAssignable(Type $other): bool
{
if ($this->allowsNull && $other instanceof NullType) {
return true;
}

if (!$other instanceof ObjectType) {
return false;
}

if (0 === strcasecmp($this->className->qualifiedName(), $other->className()->qualifiedName())) {
return true;
}

if (is_subclass_of($other->className()->qualifiedName(), $this->className->qualifiedName(), true)) {
return true;
}

return false;
}

public function name(): string
{
return 'static';
}

public function allowsNull(): bool
{
return $this->allowsNull;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/type.
*
* (c) Sebastian Bergmann <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Type\TestFixture;

class ChildClassThatExtendsClassWithMethodThatHasStaticReturnType extends ParentClassWithMethodThatHasStaticReturnType
{
}
25 changes: 25 additions & 0 deletions tests/_fixture/ClassWithMethodsThatHaveStaticReturnTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/type.
*
* (c) Sebastian Bergmann <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Type\TestFixture;

class ClassWithMethodsThatHaveStaticReturnTypes
{
public function returnsStatic(): static
{
}

public function returnsNullableStatic(): ?static
{
}

public function returnsUnionWithStatic(): static|\stdClass
{
}
}
17 changes: 17 additions & 0 deletions tests/_fixture/ParentClassWithMethodThatHasStaticReturnType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/type.
*
* (c) Sebastian Bergmann <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Type\TestFixture;

class ParentClassWithMethodThatHasStaticReturnType
{
public function m(): static
{
}
}
37 changes: 37 additions & 0 deletions tests/unit/ReflectionMapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use SebastianBergmann\Type\TestFixture\ChildClassWithoutParentClass;
use SebastianBergmann\Type\TestFixture\ClassWithMethodsThatDeclareReturnTypes;
use SebastianBergmann\Type\TestFixture\ClassWithMethodsThatDeclareUnionReturnTypes;
use SebastianBergmann\Type\TestFixture\ClassWithMethodsThatHaveStaticReturnTypes;
use SebastianBergmann\Type\TestFixture\ParentClass;

/**
Expand All @@ -29,6 +30,7 @@
* @uses \SebastianBergmann\Type\VoidType
* @uses \SebastianBergmann\Type\UnionType
* @uses \SebastianBergmann\Type\MixedType
* @uses \SebastianBergmann\Type\StaticType
*/
final class ReflectionMapperTest extends TestCase
{
Expand Down Expand Up @@ -73,6 +75,41 @@ public function testMapsFromMethodMixedReturnType(): void
$this->assertSame('mixed', $type->name());
}

/**
* @requires PHP >= 8.0
*/
public function testMapsFromMethodStaticReturnType(): void
{
$type = (new ReflectionMapper)->fromMethodReturnType(new ReflectionMethod(ClassWithMethodsThatHaveStaticReturnTypes::class, 'returnsStatic'));

$this->assertInstanceOf(StaticType::class, $type);
$this->assertSame('static', $type->asString());
$this->assertFalse($type->allowsNull());
}

/**
* @requires PHP >= 8.0
*/
public function testMapsFromMethodNullableStaticReturnType(): void
{
$type = (new ReflectionMapper)->fromMethodReturnType(new ReflectionMethod(ClassWithMethodsThatHaveStaticReturnTypes::class, 'returnsNullableStatic'));

$this->assertInstanceOf(StaticType::class, $type);
$this->assertSame('?static', $type->asString());
$this->assertTrue($type->allowsNull());
}

/**
* @requires PHP >= 8.0
*/
public function testMapsFromMethodUnionWithStaticReturnType(): void
{
$type = (new ReflectionMapper)->fromMethodReturnType(new ReflectionMethod(ClassWithMethodsThatHaveStaticReturnTypes::class, 'returnsUnionWithStatic'));

$this->assertInstanceOf(UnionType::class, $type);
$this->assertSame('static|stdClass', $type->name());
}

/**
* @requires PHP < 7.4
*/
Expand Down
Loading

0 comments on commit 2167139

Please sign in to comment.