Skip to content

Commit 16ca57b

Browse files
committed
Add support for collaborator properties
1 parent 9381210 commit 16ca57b

File tree

11 files changed

+446
-2
lines changed

11 files changed

+446
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* support for array return type (check if array item has correct type)
1717
* Allow to user `Propehcy` as `Collaborator` arguments
1818
* `Argument::cetera()`, `Argument::any()`
19+
* Provides correct attributes for `Collaborator`
1920
* Provides correct methods for `ObjectBehavior`:
2021
* `should*` methods
2122
* `during*` methods

composer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
},
2323
"autoload-dev": {
2424
"psr-4": {
25-
"spec\\PhpSpec\\": "spec/PhpSpec/"
25+
"spec\\PhpSpec\\": "spec/PhpSpec/",
26+
"spec\\Proget\\": "spec/Proget/",
27+
"Proget\\Tests\\": "tests/"
2628
}
2729
},
2830
"license": "MIT",
@@ -35,7 +37,7 @@
3537
"scripts": {
3638
"check-cs": "php-cs-fixer fix --dry-run --diff",
3739
"fix-cs": "php-cs-fixer fix",
38-
"tests": "phpspec run",
40+
"tests": "phpspec run --format=dot",
3941
"stan": "phpstan analyse -l max -c ./phpstan.neon ./src ./spec",
4042
"check": [
4143
"@check-cs",

extension.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ services:
1414
-
1515
class: Proget\PHPStan\PhpSpec\Reflection\ObjectBehaviorPropertiesClassReflectionExtension
1616
tags: [phpstan.broker.propertiesClassReflectionExtension]
17+
-
18+
class: Proget\PHPStan\PhpSpec\Reflection\SpoofedCollaboratorPropertiesClassReflectionExtension
19+
tags: [phpstan.broker.propertiesClassReflectionExtension]
1720
-
1821
class: Proget\PHPStan\PhpSpec\Type\ObjectBehaviorDynamicMethodReturnTypeExtension
1922
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]

spec/Proget/Tests/BarSpec.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace spec\Proget\Tests;
6+
7+
use Proget\Tests\Bar;
8+
use PhpSpec\ObjectBehavior;
9+
use Proget\Tests\Foo;
10+
11+
class BarSpec extends ObjectBehavior
12+
{
13+
public function let(Foo $foo): void
14+
{
15+
$this->beConstructedWith($foo);
16+
}
17+
18+
public function it_is_initializable()
19+
{
20+
$this->shouldHaveType(Bar::class);
21+
}
22+
23+
public function it_should_return_foo_property(Foo $foo): void
24+
{
25+
$foo->property = 'Some text';
26+
27+
$this->getFooProperty()->shouldBe('Some text');
28+
}
29+
}

spec/Proget/Tests/FooSpec.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace spec\Proget\Tests;
6+
7+
use Proget\Tests\Bar;
8+
use Proget\Tests\Baz;
9+
use Proget\Tests\Foo;
10+
use PhpSpec\ObjectBehavior;
11+
12+
class FooSpec extends ObjectBehavior
13+
{
14+
public function it_is_initializable()
15+
{
16+
$this->shouldHaveType(Foo::class);
17+
}
18+
19+
public function it_should_return_int_from_baz(Bar $bar, Baz $baz): void
20+
{
21+
$bar->baz = $baz;
22+
$baz->someInt()->willReturn(99);
23+
24+
$this->getIntFromBaz($bar)->shouldBe(99);
25+
}
26+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Proget\PHPStan\PhpSpec\Reflection;
6+
7+
use PHPStan\Reflection\ClassReflection;
8+
use PHPStan\Reflection\PropertyReflection;
9+
use PHPStan\Type\Type;
10+
use Proget\PHPStan\PhpSpec\Type\CollaboratorPropertyType;
11+
12+
final class CollaboratorPropertyReflection implements PropertyReflection
13+
{
14+
/**
15+
* @var PropertyReflection
16+
*/
17+
private $wrappedReflection;
18+
19+
public function __construct(PropertyReflection $wrappedReflection)
20+
{
21+
$this->wrappedReflection = $wrappedReflection;
22+
}
23+
24+
public function getDeclaringClass(): ClassReflection
25+
{
26+
return $this->wrappedReflection->getDeclaringClass();
27+
}
28+
29+
public function isStatic(): bool
30+
{
31+
return $this->wrappedReflection->isStatic();
32+
}
33+
34+
public function isPrivate(): bool
35+
{
36+
return $this->wrappedReflection->isPrivate();
37+
}
38+
39+
public function isPublic(): bool
40+
{
41+
return $this->wrappedReflection->isPublic();
42+
}
43+
44+
public function getType(): Type
45+
{
46+
return new CollaboratorPropertyType($this->wrappedReflection->getType());
47+
}
48+
49+
public function isReadable(): bool
50+
{
51+
return $this->wrappedReflection->isReadable();
52+
}
53+
54+
public function isWritable(): bool
55+
{
56+
return $this->wrappedReflection->isWritable();
57+
}
58+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Proget\PHPStan\PhpSpec\Reflection;
6+
7+
use PhpSpec\Wrapper\Collaborator;
8+
use PHPStan\Analyser\OutOfClassScope;
9+
use PHPStan\Broker\Broker;
10+
use PHPStan\Reflection\BrokerAwareExtension;
11+
use PHPStan\Reflection\ClassReflection;
12+
use PHPStan\Reflection\MethodReflection;
13+
use PHPStan\Reflection\PropertiesClassReflectionExtension;
14+
use PHPStan\Reflection\PropertyReflection;
15+
use Proget\PHPStan\PhpSpec\Registry\SpoofedCollaboratorRegistry;
16+
use Proget\PHPStan\PhpSpec\Wrapper\SpoofedCollaborator;
17+
18+
final class SpoofedCollaboratorPropertiesClassReflectionExtension implements PropertiesClassReflectionExtension, BrokerAwareExtension
19+
{
20+
/**
21+
* @var Broker
22+
*/
23+
private $broker;
24+
25+
public function setBroker(Broker $broker): void
26+
{
27+
$this->broker = $broker;
28+
}
29+
30+
public function hasProperty(ClassReflection $classReflection, string $propertyName): bool
31+
{
32+
return in_array(SpoofedCollaborator::class, array_map(function (ClassReflection $interface):string {
33+
return $interface->getName();
34+
}, $classReflection->getInterfaces()), true);
35+
}
36+
37+
public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection
38+
{
39+
$collaboratorClassName = (string) preg_replace('/Collaborator$/', '', SpoofedCollaboratorRegistry::getAlias($classReflection->getName()));
40+
41+
return new CollaboratorPropertyReflection($this->broker->getClass($collaboratorClassName)->getProperty($propertyName, new OutOfClassScope()));
42+
}
43+
44+
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
45+
{
46+
return in_array(SpoofedCollaborator::class, array_map(function (ClassReflection $interface):string {
47+
return $interface->getName();
48+
}, $classReflection->getInterfaces()), true);
49+
}
50+
51+
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
52+
{
53+
$collaboratorReflection = $this->broker->getClass(Collaborator::class);
54+
if ($collaboratorReflection->hasMethod($methodName)) {
55+
return $collaboratorReflection->getMethod($methodName, new OutOfClassScope());
56+
}
57+
58+
$collaboratorClassName = (string) preg_replace('/Collaborator$/', '', SpoofedCollaboratorRegistry::getAlias($classReflection->getName()));
59+
60+
return new CollaboratorMethodReflection($this->broker->getClass($collaboratorClassName)->getMethod($methodName, new OutOfClassScope()));
61+
}
62+
}

0 commit comments

Comments
 (0)