Skip to content

Commit 18887de

Browse files
committed
Merge branch 'tomasfejfar-tf-sf4'
2 parents efe5f29 + 710cc63 commit 18887de

10 files changed

+117
-9
lines changed

composer.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@
3838
"phpstan/phpstan-strict-rules": "^0.12",
3939
"slevomat/coding-standard": "^4.5.2",
4040
"phpstan/phpstan-phpunit": "^0.12",
41-
"symfony/framework-bundle": "^3.0 || ^4.0",
41+
"symfony/framework-bundle": "^4.0",
4242
"squizlabs/php_codesniffer": "^3.3.2",
43-
"symfony/serializer": "^3.0 || ^4.0",
43+
"symfony/serializer": "^4.0",
4444
"symfony/messenger": "^4.2",
45-
"symfony/console": "^3.0 || ^4.0",
46-
"symfony/http-foundation": "^3.0 || ^4.0"
45+
"symfony/console": "^4.0",
46+
"symfony/http-foundation": "^4.0"
4747
},
4848
"conflict": {
4949
"symfony/framework-bundle": "<3.0"

extension.neon

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ services:
2828
-
2929
factory: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Symfony\Component\DependencyInjection\ContainerInterface, %symfony.constant_hassers%)
3030
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]
31+
-
32+
factory: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Psr\Container\ContainerInterface, %symfony.constant_hassers%)
33+
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]
3134
-
3235
factory: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Symfony\Bundle\FrameworkBundle\Controller\Controller, %symfony.constant_hassers%)
3336
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]
@@ -39,6 +42,9 @@ services:
3942
-
4043
factory: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Symfony\Component\DependencyInjection\ContainerInterface)
4144
tags: [phpstan.typeSpecifier.methodTypeSpecifyingExtension]
45+
-
46+
factory: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Psr\Container\ContainerInterface)
47+
tags: [phpstan.typeSpecifier.methodTypeSpecifyingExtension]
4248
-
4349
factory: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Symfony\Bundle\FrameworkBundle\Controller\Controller)
4450
tags: [phpstan.typeSpecifier.methodTypeSpecifyingExtension]

src/Rules/Symfony/ContainerInterfacePrivateServiceRule.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@ public function processNode(Node $node, Scope $scope): array
6161
$isControllerType = (new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\Controller'))->isSuperTypeOf($argType);
6262
$isAbstractControllerType = (new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\AbstractController'))->isSuperTypeOf($argType);
6363
$isContainerType = (new ObjectType('Symfony\Component\DependencyInjection\ContainerInterface'))->isSuperTypeOf($argType);
64-
if (!$isControllerType->yes() && !$isAbstractControllerType->yes() && !$isContainerType->yes()) {
64+
$isPsrContainerType = (new ObjectType('Psr\Container\ContainerInterface'))->isSuperTypeOf($argType);
65+
if (
66+
!$isControllerType->yes()
67+
&& !$isAbstractControllerType->yes()
68+
&& !$isContainerType->yes()
69+
&& !$isPsrContainerType->yes()
70+
) {
6571
return [];
6672
}
6773

src/Rules/Symfony/ContainerInterfaceUnknownServiceRule.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ public function processNode(Node $node, Scope $scope): array
5858
$isControllerType = (new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\Controller'))->isSuperTypeOf($argType);
5959
$isAbstractControllerType = (new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\AbstractController'))->isSuperTypeOf($argType);
6060
$isContainerType = (new ObjectType('Symfony\Component\DependencyInjection\ContainerInterface'))->isSuperTypeOf($argType);
61-
if (!$isControllerType->yes() && !$isAbstractControllerType->yes() && !$isContainerType->yes()) {
61+
$isPsrContainerType = (new ObjectType('Psr\Container\ContainerInterface'))->isSuperTypeOf($argType);
62+
if (
63+
!$isControllerType->yes()
64+
&& !$isAbstractControllerType->yes()
65+
&& !$isContainerType->yes()
66+
&& !$isPsrContainerType->yes()
67+
) {
6268
return [];
6369
}
6470

tests/Rules/Symfony/ContainerInterfacePrivateServiceRuleFakeTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ public function testGetPrivateService(): void
2727
);
2828
}
2929

30+
public function testGetPrivateServiceInAbstractController(): void
31+
{
32+
$this->analyse(
33+
[
34+
__DIR__ . '/ExampleAbstractController.php',
35+
],
36+
[]
37+
);
38+
}
39+
3040
public function testGetPrivateServiceInLegacyServiceSubscriber(): void
3141
{
3242
if (!interface_exists('Symfony\\Component\\DependencyInjection\\ServiceSubscriberInterface')) {

tests/Rules/Symfony/ContainerInterfaceUnknownServiceRuleFakeTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,14 @@ public function testGetPrivateService(): void
4040
);
4141
}
4242

43+
public function testGetPrivateServiceInAbstractController(): void
44+
{
45+
$this->analyse(
46+
[
47+
__DIR__ . '/ExampleAbstractController.php',
48+
],
49+
[]
50+
);
51+
}
52+
4353
}

tests/Rules/Symfony/ContainerInterfaceUnknownServiceRuleTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\Symfony\XmlServiceMapFactory;
88
use PHPStan\Testing\RuleTestCase;
99
use PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension;
10+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1011
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
1112

1213
/**
@@ -27,6 +28,7 @@ protected function getMethodTypeSpecifyingExtensions(): array
2728
{
2829
return [
2930
new ServiceTypeSpecifyingExtension(Controller::class, new Standard()),
31+
new ServiceTypeSpecifyingExtension(AbstractController::class, new Standard()),
3032
];
3133
}
3234

@@ -45,4 +47,19 @@ public function testGetPrivateService(): void
4547
);
4648
}
4749

50+
public function testGetPrivateServiceInAbstractController(): void
51+
{
52+
$this->analyse(
53+
[
54+
__DIR__ . '/ExampleAbstractController.php',
55+
],
56+
[
57+
[
58+
'Service "unknown" is not registered in the container.',
59+
24,
60+
],
61+
]
62+
);
63+
}
64+
4865
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Symfony;
4+
5+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
6+
7+
final class ExampleAbstractController extends AbstractController
8+
{
9+
10+
public function privateService(): void
11+
{
12+
$this->get('private');
13+
}
14+
15+
public function privateServiceInTestContainer(): void
16+
{
17+
/** @var \Symfony\Bundle\FrameworkBundle\Test\TestContainer $container */
18+
$container = doFoo();
19+
$container->get('private');
20+
}
21+
22+
public function unknownService(): void
23+
{
24+
$this->get('unknown');
25+
}
26+
27+
public function unknownGuardedServiceInsideContext(): void
28+
{
29+
if ($this->has('unknown')) { // phpcs:ignore
30+
$this->get('unknown');
31+
}
32+
}
33+
34+
public function unknownGuardedServiceOutsideOfContext(): void
35+
{
36+
if (!$this->has('unknown')) {
37+
return;
38+
}
39+
$this->get('unknown');
40+
}
41+
42+
}

tests/Symfony/NeonTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ public function testExtensionNeon(): void
3030
], $parameters['symfony']);
3131

3232
self::assertCount(6, $container->getServicesByTag('phpstan.rules.rule'));
33-
self::assertCount(15, $container->getServicesByTag('phpstan.broker.dynamicMethodReturnTypeExtension'));
34-
self::assertCount(6, $container->getServicesByTag('phpstan.typeSpecifier.methodTypeSpecifyingExtension'));
33+
self::assertCount(16, $container->getServicesByTag('phpstan.broker.dynamicMethodReturnTypeExtension'));
34+
self::assertCount(7, $container->getServicesByTag('phpstan.typeSpecifier.methodTypeSpecifyingExtension'));
3535
self::assertInstanceOf(ServiceMap::class, $container->getByType(ServiceMap::class));
3636
}
3737

tests/Type/Symfony/RequestTypeSpecifyingExtensionTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
use PHPStan\Rules\Rule;
66
use PHPStan\Testing\RuleTestCase;
77
use PHPStan\Type\MethodTypeSpecifyingExtension;
8+
use ReflectionMethod;
9+
use Symfony\Component\HttpFoundation\Request;
810
use Symfony\Component\HttpFoundation\Session\SessionInterface;
11+
use function strpos;
912

1013
/**
1114
* @extends RuleTestCase<VariableTypeReportingRule>
@@ -28,9 +31,17 @@ protected function getMethodTypeSpecifyingExtensions(): array
2831

2932
public function testGetSession(): void
3033
{
34+
$ref = new ReflectionMethod(Request::class, 'getSession');
35+
$doc = (string) $ref->getDocComment();
36+
37+
$checkedTypeString = SessionInterface::class;
38+
if (strpos($doc, '@return SessionInterface|null') !== false) {
39+
$checkedTypeString .= '|null';
40+
}
41+
3142
$this->analyse([__DIR__ . '/request_get_session.php'], [
3243
[
33-
'Variable $session1 is: ' . SessionInterface::class . '|null',
44+
'Variable $session1 is: ' . $checkedTypeString,
3445
7,
3546
],
3647
[

0 commit comments

Comments
 (0)