From 39531205afa3de1dbc4e890b0d5d0ded7d890e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Cobucci?= Date: Mon, 23 Jul 2018 21:10:56 +0200 Subject: [PATCH] Allow using prophecy in test attributes as well --- composer.json | 2 +- composer.lock | 85 ++++++++++++------------ src/PhpDoc/TypeNodeResolverExtension.php | 61 +++++++++++++++++ src/extension.neon | 5 ++ tests/Test/BaseModelTest.php | 27 +++++++- 5 files changed, 137 insertions(+), 43 deletions(-) create mode 100644 src/PhpDoc/TypeNodeResolverExtension.php diff --git a/composer.json b/composer.json index d7c1ca6..d54b0b6 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "php": "^7.1", "phpspec/prophecy": "^1.7", "phpunit/phpunit": "^6.0||^7.0", - "phpstan/phpstan": "^0.10" + "phpstan/phpstan": "^0.10.3@dev" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 1c1ecd7..b567551 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2c47897f3a4d64f34b2a7c65c46e213a", + "content-hash": "bead517f54a3419d24974bfc76bfdf5a", "packages": [ { "name": "composer/xdebug-handler", @@ -682,16 +682,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.0.2", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12" + "reference": "bd088dc940a418f09cda079a9b5c7c478890fb8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/35b8caf75e791ba1b2d24fec1552168d72692b12", - "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bd088dc940a418f09cda079a9b5c7c478890fb8d", + "reference": "bd088dc940a418f09cda079a9b5c7c478890fb8d", "shasum": "" }, "require": { @@ -729,7 +729,7 @@ "parser", "php" ], - "time": "2018-06-03T11:33:10+00:00" + "time": "2018-07-15T17:25:16+00:00" }, { "name": "ocramius/package-versions", @@ -782,22 +782,22 @@ }, { "name": "phar-io/manifest", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", - "phar-io/version": "^1.0.1", + "phar-io/version": "^2.0", "php": "^5.6 || ^7.0" }, "type": "library", @@ -833,20 +833,20 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05T18:14:27+00:00" + "time": "2018-07-08T19:23:20+00:00" }, { "name": "phar-io/version", - "version": "1.0.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", "shasum": "" }, "require": { @@ -880,7 +880,7 @@ } ], "description": "Library for handling version information and constraints", - "time": "2017-03-05T17:38:23+00:00" + "time": "2018-07-08T19:19:57+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -1145,16 +1145,16 @@ }, { "name": "phpstan/phpstan", - "version": "0.10.1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "3179cf27542e9e47acb548150e7ca21ca5ab92d6" + "reference": "7b23c31226eec8bd1f3f732a841221ddea7a60ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3179cf27542e9e47acb548150e7ca21ca5ab92d6", - "reference": "3179cf27542e9e47acb548150e7ca21ca5ab92d6", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/7b23c31226eec8bd1f3f732a841221ddea7a60ee", + "reference": "7b23c31226eec8bd1f3f732a841221ddea7a60ee", "shasum": "" }, "require": { @@ -1179,6 +1179,7 @@ "ext-mysqli": "*", "ext-zip": "*", "jakub-onderka/php-parallel-lint": "^1.0", + "localheinz/composer-normalize": "~0.8.0", "phing/phing": "^2.16.0", "phpstan/phpstan-deprecation-rules": "^0.10.2", "phpstan/phpstan-php-parser": "^0.10", @@ -1209,7 +1210,7 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", - "time": "2018-07-01T18:22:12+00:00" + "time": "2018-07-26T16:42:55+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1462,16 +1463,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.2.6", + "version": "7.2.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "400a3836ee549ae6f665323ac3f21e27eac7155f" + "reference": "8e878aff7917ef66e702e03d1359b16eee254e2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/400a3836ee549ae6f665323ac3f21e27eac7155f", - "reference": "400a3836ee549ae6f665323ac3f21e27eac7155f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e878aff7917ef66e702e03d1359b16eee254e2c", + "reference": "8e878aff7917ef66e702e03d1359b16eee254e2c", "shasum": "" }, "require": { @@ -1482,8 +1483,8 @@ "ext-mbstring": "*", "ext-xml": "*", "myclabs/deep-copy": "^1.7", - "phar-io/manifest": "^1.0.1", - "phar-io/version": "^1.0", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", "php": "^7.1", "phpspec/prophecy": "^1.7", "phpunit/php-code-coverage": "^6.0.7", @@ -1542,7 +1543,7 @@ "testing", "xunit" ], - "time": "2018-06-21T13:13:39+00:00" + "time": "2018-07-15T05:20:50+00:00" }, { "name": "psr/log", @@ -1638,16 +1639,16 @@ }, { "name": "sebastian/comparator", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "591a30922f54656695e59b1f39501aec513403da" + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/591a30922f54656695e59b1f39501aec513403da", - "reference": "591a30922f54656695e59b1f39501aec513403da", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", "shasum": "" }, "require": { @@ -1698,7 +1699,7 @@ "compare", "equality" ], - "time": "2018-06-14T15:05:28+00:00" + "time": "2018-07-12T15:12:46+00:00" }, { "name": "sebastian/diff", @@ -2156,16 +2157,16 @@ }, { "name": "symfony/console", - "version": "v4.1.1", + "version": "v4.1.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "70591cda56b4b47c55776ac78e157c4bb6c8b43f" + "reference": "5c31f6a97c1c240707f6d786e7e59bfacdbc0219" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/70591cda56b4b47c55776ac78e157c4bb6c8b43f", - "reference": "70591cda56b4b47c55776ac78e157c4bb6c8b43f", + "url": "https://api.github.com/repos/symfony/console/zipball/5c31f6a97c1c240707f6d786e7e59bfacdbc0219", + "reference": "5c31f6a97c1c240707f6d786e7e59bfacdbc0219", "shasum": "" }, "require": { @@ -2220,11 +2221,11 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-05-31T10:17:53+00:00" + "time": "2018-07-16T14:05:40+00:00" }, { "name": "symfony/finder", - "version": "v4.1.1", + "version": "v4.1.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -2424,7 +2425,9 @@ "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "phpstan/phpstan": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/PhpDoc/TypeNodeResolverExtension.php b/src/PhpDoc/TypeNodeResolverExtension.php new file mode 100644 index 0000000..121b920 --- /dev/null +++ b/src/PhpDoc/TypeNodeResolverExtension.php @@ -0,0 +1,61 @@ +typeNodeResolver = $typeNodeResolver; + } + + public function getCacheKey(): string + { + return 'prophecy-v1'; + } + + public function resolve(TypeNode $typeNode, NameScope $nameScope): ?Type + { + if (!$typeNode instanceof UnionTypeNode) { + return null; + } + + if (count($typeNode->types) === 2) { + $objectProphecyType = null; + $prophesizedType = null; + foreach ($typeNode->types as $innerType) { + $type = $this->typeNodeResolver->resolve($innerType, $nameScope); + if ($type instanceof TypeWithClassName) { + if ($type->getClassName() === ObjectProphecy::class) { + $objectProphecyType = $type; + } else { + $prophesizedType = $type; + } + } else { + break; + } + } + + if ($objectProphecyType !== null && $prophesizedType !== null) { + return new ObjectProphecyType($prophesizedType->getClassName()); + } + } + + return null; + } + +} diff --git a/src/extension.neon b/src/extension.neon index 41166e9..3ff05b2 100644 --- a/src/extension.neon +++ b/src/extension.neon @@ -17,3 +17,8 @@ services: class: JanGregor\Prophecy\Reflection\ProphecyMethodsClassReflectionExtension tags: - phpstan.broker.methodsClassReflectionExtension + + - + class: JanGregor\Prophecy\PhpDoc\TypeNodeResolverExtension + tags: + - phpstan.phpDoc.typeNodeResolverExtension diff --git a/tests/Test/BaseModelTest.php b/tests/Test/BaseModelTest.php index bc9a804..0cd03cf 100644 --- a/tests/Test/BaseModelTest.php +++ b/tests/Test/BaseModelTest.php @@ -2,12 +2,18 @@ namespace Tests\Test; -use Tests\Model\BaseModel; use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Prophecy\Prophecy\ObjectProphecy; +use Tests\Model\BaseModel; class BaseModelTest extends TestCase { + /** + * @var BaseModel|ObjectProphecy + */ + private $subject; + public function testBasicProperty() { $word = 'bar'; @@ -29,4 +35,23 @@ public function testWithProphecy() $this->assertEquals('bar', $subject->reveal()->getFoo()); $this->assertEquals(5, $subject->reveal()->doubleTheNumber(2)); } + + /** + * @before + */ + public function createSubject(): void + { + $this->subject = $this->prophesize(BaseModel::class); + } + + public function testProphesizedAttributesShouldAlsoWork(): void + { + $this->subject->getFoo()->willReturn('bar'); + $this->subject->doubleTheNumber(Argument::is(2))->willReturn(5); + + $subject = $this->subject->reveal(); + + $this->assertEquals('bar', $subject->getFoo()); + $this->assertEquals(5, $subject->doubleTheNumber(2)); + } }