Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update PHPstan to 0.12 #77

Merged
merged 3 commits into from
Nov 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"ext-pdo": "*",
"doctrine/coding-standard": "^6.0",
"phpbench/phpbench": "^0.13",
"phpstan/phpstan-phpunit": "^0.11",
"phpstan/phpstan-shim": "^0.11",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^7.0"
},
"autoload": {
Expand Down
721 changes: 538 additions & 183 deletions composer.lock

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ parameters:
- tests

ignoreErrors:
-
message: '#::__construct\(\) does not call parent constructor from#'
path: '*/tests/DoctrineTest/InstantiatorTestAsset/*.php'

# dynamic properties confuse static analysis
-
message: '#Access to an undefined property object::\$foo\.#'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use InvalidArgumentException as BaseInvalidArgumentException;
use ReflectionClass;
use const PHP_VERSION_ID;
use function interface_exists;
use function sprintf;
use function trait_exists;
Expand All @@ -20,13 +19,17 @@ public static function fromNonExistingClass(string $className) : self
return new self(sprintf('The provided type "%s" is an interface, and can not be instantiated', $className));
}

if (PHP_VERSION_ID >= 50400 && trait_exists($className)) {
if (trait_exists($className)) {
return new self(sprintf('The provided type "%s" is a trait, and can not be instantiated', $className));
}

return new self(sprintf('The provided class "%s" does not exist', $className));
}

/**
* @template T of object
* @phpstan-param ReflectionClass<T> $reflectionClass
*/
public static function fromAbstractClass(ReflectionClass $reflectionClass) : self
{
return new self(sprintf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
*/
class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface
{
/**
* @template T of object
* @phpstan-param ReflectionClass<T> $reflectionClass
*/
public static function fromSerializationTriggeredException(
ReflectionClass $reflectionClass,
Exception $exception
Expand All @@ -26,6 +30,10 @@ public static function fromSerializationTriggeredException(
);
}

/**
* @template T of object
* @phpstan-param ReflectionClass<T> $reflectionClass
*/
public static function fromUncleanUnSerialization(
ReflectionClass $reflectionClass,
string $errorString,
Expand Down
39 changes: 35 additions & 4 deletions src/Doctrine/Instantiator/Instantiator.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public function instantiate($className)
* Builds the requested object and caches it in static properties for performance
*
* @return object
*
* @template T of object
* @phpstan-param class-string<T> $className
*
* @phpstan-return T
*/
private function buildAndCacheFromFactory(string $className)
{
Expand All @@ -86,6 +91,11 @@ private function buildAndCacheFromFactory(string $className)
* @throws InvalidArgumentException
* @throws UnexpectedValueException
* @throws ReflectionException
*
* @template T of object
* @phpstan-param class-string<T> $className
*
* @phpstan-return callable(): T
*/
private function buildFactory(string $className) : callable
{
Expand All @@ -112,6 +122,11 @@ private function buildFactory(string $className) : callable
/**
* @throws InvalidArgumentException
* @throws ReflectionException
*
* @template T of object
* @phpstan-param class-string<T> $className
*
* @phpstan-return ReflectionClass<T>
*/
private function getReflectionClass(string $className) : ReflectionClass
{
Expand All @@ -130,6 +145,9 @@ private function getReflectionClass(string $className) : ReflectionClass

/**
* @throws UnexpectedValueException
*
* @template T of object
* @phpstan-param ReflectionClass<T> $reflectionClass
*/
private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString) : void
{
Expand Down Expand Up @@ -158,6 +176,9 @@ private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionCl

/**
* @throws UnexpectedValueException
*
* @template T of object
* @phpstan-param ReflectionClass<T> $reflectionClass
*/
private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString) : void
{
Expand All @@ -168,13 +189,20 @@ private function attemptInstantiationViaUnSerialization(ReflectionClass $reflect
}
}

/**
* @template T of object
* @phpstan-param ReflectionClass<T> $reflectionClass
*/
private function isInstantiableViaReflection(ReflectionClass $reflectionClass) : bool
{
return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());
}

/**
* Verifies whether the given class is to be considered internal
*
* @template T of object
* @phpstan-param ReflectionClass<T> $reflectionClass
*/
private function hasInternalAncestors(ReflectionClass $reflectionClass) : bool
{
Expand All @@ -193,11 +221,14 @@ private function hasInternalAncestors(ReflectionClass $reflectionClass) : bool
* Checks if a class is cloneable
*
* Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects.
*
* @template T of object
* @phpstan-param ReflectionClass<T> $reflectionClass
*/
private function isSafeToClone(ReflectionClass $reflection) : bool
private function isSafeToClone(ReflectionClass $reflectionClass) : bool
{
return $reflection->isCloneable()
&& ! $reflection->hasMethod('__clone')
&& ! $reflection->isSubclassOf(ArrayIterator::class);
return $reflectionClass->isCloneable()
&& ! $reflectionClass->hasMethod('__clone')
&& ! $reflectionClass->isSubclassOf(ArrayIterator::class);
}
}
3 changes: 3 additions & 0 deletions src/Doctrine/Instantiator/InstantiatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ interface InstantiatorInterface
* @return object
*
* @throws ExceptionInterface
*
* @template T of object
* @phpstan-param class-string<T> $className
*/
public function instantiate($className);
}
14 changes: 12 additions & 2 deletions tests/DoctrineTest/InstantiatorTest/InstantiatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ protected function setUp() : void

/**
* @dataProvider getInstantiableClasses
* @phpstan-param class-string $className
*/
public function testCanInstantiate(string $className) : void
{
Expand All @@ -58,6 +59,7 @@ public function testCanInstantiate(string $className) : void

/**
* @dataProvider getInstantiableClasses
* @phpstan-param class-string $className
*/
public function testInstantiatesSeparateInstances(string $className) : void
{
Expand All @@ -77,6 +79,7 @@ public function testExceptionOnUnSerializationException() : void

/**
* @dataProvider getInvalidClassNames
* @phpstan-param class-string $invalidClassName
*/
public function testInstantiationFromNonExistingClass(string $invalidClassName) : void
{
Expand All @@ -91,11 +94,16 @@ public function testInstancesAreNotCloned() : void

eval('namespace ' . __NAMESPACE__ . '; class ' . $className . '{}');

$instance = $this->instantiator->instantiate(__NAMESPACE__ . '\\' . $className);
/**
* @phpstan-var class-string
*/
$classNameWithNamespace = __NAMESPACE__ . '\\' . $className;

$instance = $this->instantiator->instantiate($classNameWithNamespace);

$instance->foo = 'bar';

$instance2 = $this->instantiator->instantiate(__NAMESPACE__ . '\\' . $className);
$instance2 = $this->instantiator->instantiate($classNameWithNamespace);

self::assertObjectNotHasAttribute('foo', $instance2);
}
Expand All @@ -104,6 +112,8 @@ public function testInstancesAreNotCloned() : void
* Provides a list of instantiable classes (existing)
*
* @return string[][]
*
* @phpstan-return list<array{class-string}>
*/
public function getInstantiableClasses() : array
{
Expand Down
3 changes: 3 additions & 0 deletions tests/DoctrineTest/InstantiatorTestAsset/ArrayObjectAsset.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

/**
* Test asset that extends an internal PHP class
*
* @template TValue
* @template-extends ArrayObject<int, TValue>
*/
class ArrayObjectAsset extends ArrayObject
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

/**
* Serializable test asset that also extends an internal class
*
* @template TValue
* @template-extends ArrayObject<int, TValue>
*/
class SerializableArrayObjectAsset extends ArrayObject implements Serializable
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

use ArrayIterator;

/**
* @template TValue
* @template-extends ArrayIterator<int, TValue>
*/
final class SerializableFinalInternalChildAsset extends ArrayIterator
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

/**
* A simple asset for an abstract class
*
* @template TValue
* @template-extends ArrayObject<int, TValue>
*/
class UnserializeExceptionArrayObjectAsset extends ArrayObject
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

/**
* A simple asset for an abstract class
*
* @template TValue
* @template-extends ArrayObject<int, TValue>
*/
class WakeUpNoticesAsset extends ArrayObject
{
Expand Down