Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b8e94b1

Browse files
committed
Make container xml config option nullable
1 parent 6cac146 commit b8e94b1

13 files changed

+219
-54
lines changed

‎extension.neon‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
parameters:
22
symfony:
3+
container_xml_path: null
34
constant_hassers: true
45
console_application_loader: null
56

‎src/Rules/Symfony/ContainerInterfacePrivateServiceRule.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function processNode(Node $node, Scope $scope): array
6262
return [];
6363
}
6464

65-
$serviceId = ServiceMap::getServiceIdFromNode($node->args[0]->value, $scope);
65+
$serviceId = $this->serviceMap::getServiceIdFromNode($node->args[0]->value, $scope);
6666
if ($serviceId !== null) {
6767
$service = $this->serviceMap->getService($serviceId);
6868
if ($service !== null && !$service->isPublic()) {

‎src/Rules/Symfony/ContainerInterfaceUnknownServiceRule.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function processNode(Node $node, Scope $scope): array
5959
return [];
6060
}
6161

62-
$serviceId = ServiceMap::getServiceIdFromNode($node->args[0]->value, $scope);
62+
$serviceId = $this->serviceMap::getServiceIdFromNode($node->args[0]->value, $scope);
6363
if ($serviceId !== null) {
6464
$service = $this->serviceMap->getService($serviceId);
6565
$serviceIdType = $scope->getType($node->args[0]->value);

‎src/Symfony/DefaultServiceMap.php‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Symfony;
4+
5+
use PhpParser\Node\Expr;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Type\TypeUtils;
8+
use function count;
9+
10+
final class DefaultServiceMap implements ServiceMap
11+
{
12+
13+
/** @var \PHPStan\Symfony\ServiceDefinition[] */
14+
private $services;
15+
16+
/**
17+
* @param \PHPStan\Symfony\ServiceDefinition[] $services
18+
*/
19+
public function __construct(array $services)
20+
{
21+
$this->services = $services;
22+
}
23+
24+
/**
25+
* @return \PHPStan\Symfony\ServiceDefinition[]
26+
*/
27+
public function getServices(): array
28+
{
29+
return $this->services;
30+
}
31+
32+
public function getService(string $id): ?ServiceDefinition
33+
{
34+
return $this->services[$id] ?? null;
35+
}
36+
37+
public static function getServiceIdFromNode(Expr $node, Scope $scope): ?string
38+
{
39+
$strings = TypeUtils::getConstantStrings($scope->getType($node));
40+
return count($strings) === 1 ? $strings[0]->getValue() : null;
41+
}
42+
43+
}

‎src/Symfony/FakeServiceMap.php‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Symfony;
4+
5+
use PhpParser\Node\Expr;
6+
use PHPStan\Analyser\Scope;
7+
8+
final class FakeServiceMap implements ServiceMap
9+
{
10+
11+
/**
12+
* @return \PHPStan\Symfony\ServiceDefinition[]
13+
*/
14+
public function getServices(): array
15+
{
16+
return [];
17+
}
18+
19+
public function getService(string $id): ?ServiceDefinition
20+
{
21+
return null;
22+
}
23+
24+
public static function getServiceIdFromNode(Expr $node, Scope $scope): ?string
25+
{
26+
return null;
27+
}
28+
29+
}

‎src/Symfony/ServiceMap.php‎

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,17 @@
44

55
use PhpParser\Node\Expr;
66
use PHPStan\Analyser\Scope;
7-
use PHPStan\Type\TypeUtils;
8-
use function count;
97

10-
finalclass ServiceMap
8+
interface ServiceMap
119
{
1210

13-
/** @var \PHPStan\Symfony\ServiceDefinition[] */
14-
private $services;
15-
16-
/**
17-
* @param \PHPStan\Symfony\ServiceDefinition[] $services
18-
*/
19-
public function __construct(array $services)
20-
{
21-
$this->services = $services;
22-
}
23-
2411
/**
2512
* @return \PHPStan\Symfony\ServiceDefinition[]
2613
*/
27-
public function getServices(): array
28-
{
29-
return $this->services;
30-
}
14+
public function getServices(): array;
3115

32-
public function getService(string $id): ?ServiceDefinition
33-
{
34-
return $this->services[$id] ?? null;
35-
}
16+
public function getService(string $id): ?ServiceDefinition;
3617

37-
public static function getServiceIdFromNode(Expr $node, Scope $scope): ?string
38-
{
39-
$strings = TypeUtils::getConstantStrings($scope->getType($node));
40-
return count($strings) === 1 ? $strings[0]->getValue() : null;
41-
}
18+
public static function getServiceIdFromNode(Expr $node, Scope $scope): ?string;
4219

4320
}

‎src/Symfony/XmlServiceMapFactory.php‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,20 @@
1010
final class XmlServiceMapFactory implements ServiceMapFactory
1111
{
1212

13-
/** @var string */
13+
/** @var string|null */
1414
private $containerXml;
1515

16-
public function __construct(string $containerXml)
16+
public function __construct(?string $containerXml)
1717
{
1818
$this->containerXml = $containerXml;
1919
}
2020

2121
public function create(): ServiceMap
2222
{
23+
if ($this->containerXml === null) {
24+
return new FakeServiceMap();
25+
}
26+
2327
$fileContents = file_get_contents($this->containerXml);
2428
if ($fileContents === false) {
2529
throw new XmlContainerNotExistsException(sprintf('Container %s does not exist or cannot be parsed', $this->containerXml));
@@ -70,7 +74,7 @@ public function create(): ServiceMap
7074
);
7175
}
7276

73-
return new ServiceMap($services);
77+
return new DefaultServiceMap($services);
7478
}
7579

7680
}

‎src/Type/Symfony/ServiceDynamicReturnTypeExtension.php‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ final class ServiceDynamicReturnTypeExtension implements DynamicMethodReturnType
2424
private $constantHassers;
2525

2626
/** @var \PHPStan\Symfony\ServiceMap */
27-
private $symfonyServiceMap;
27+
private $serviceMap;
2828

2929
public function __construct(string $className, bool $constantHassers, ServiceMap $symfonyServiceMap)
3030
{
3131
$this->className = $className;
3232
$this->constantHassers = $constantHassers;
33-
$this->symfonyServiceMap = $symfonyServiceMap;
33+
$this->serviceMap = $symfonyServiceMap;
3434
}
3535

3636
public function getClass(): string
@@ -65,9 +65,9 @@ private function getGetTypeFromMethodCall(
6565
return $returnType;
6666
}
6767

68-
$serviceId = ServiceMap::getServiceIdFromNode($methodCall->args[0]->value, $scope);
68+
$serviceId = $this->serviceMap::getServiceIdFromNode($methodCall->args[0]->value, $scope);
6969
if ($serviceId !== null) {
70-
$service = $this->symfonyServiceMap->getService($serviceId);
70+
$service = $this->serviceMap->getService($serviceId);
7171
if ($service !== null && !$service->isSynthetic()) {
7272
return new ObjectType($service->getClass() ?? $serviceId);
7373
}
@@ -87,9 +87,9 @@ private function getHasTypeFromMethodCall(
8787
return $returnType;
8888
}
8989

90-
$serviceId = ServiceMap::getServiceIdFromNode($methodCall->args[0]->value, $scope);
90+
$serviceId = $this->serviceMap::getServiceIdFromNode($methodCall->args[0]->value, $scope);
9191
if ($serviceId !== null) {
92-
$service = $this->symfonyServiceMap->getService($serviceId);
92+
$service = $this->serviceMap->getService($serviceId);
9393
return new ConstantBooleanType($service !== null && $service->isPublic());
9494
}
9595

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Symfony;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Symfony\XmlServiceMapFactory;
7+
use PHPStan\Testing\RuleTestCase;
8+
9+
final class ContainerInterfacePrivateServiceRuleFakeTest extends RuleTestCase
10+
{
11+
12+
protected function getRule(): Rule
13+
{
14+
return new ContainerInterfacePrivateServiceRule((new XmlServiceMapFactory(null))->create());
15+
}
16+
17+
public function testGetPrivateService(): void
18+
{
19+
$this->analyse(
20+
[
21+
__DIR__ . '/ExampleController.php',
22+
],
23+
[]
24+
);
25+
}
26+
27+
public function testGetPrivateServiceInLegacyServiceSubscriber(): void
28+
{
29+
if (!interface_exists('Symfony\\Component\\DependencyInjection\\ServiceSubscriberInterface')) {
30+
self::markTestSkipped('The test needs Symfony\Component\DependencyInjection\ServiceSubscriberInterface class.');
31+
}
32+
33+
$this->analyse(
34+
[
35+
__DIR__ . '/ExampleLegacyServiceSubscriber.php',
36+
__DIR__ . '/ExampleLegacyServiceSubscriberFromAbstractController.php',
37+
__DIR__ . '/ExampleLegacyServiceSubscriberFromLegacyController.php',
38+
],
39+
[]
40+
);
41+
}
42+
43+
public function testGetPrivateServiceInServiceSubscriber(): void
44+
{
45+
if (!interface_exists('Symfony\Contracts\Service\ServiceSubscriberInterface')) {
46+
self::markTestSkipped('The test needs Symfony\Contracts\Service\ServiceSubscriberInterface class.');
47+
}
48+
49+
$this->analyse(
50+
[
51+
__DIR__ . '/ExampleServiceSubscriber.php',
52+
__DIR__ . '/ExampleServiceSubscriberFromAbstractController.php',
53+
__DIR__ . '/ExampleServiceSubscriberFromLegacyController.php',
54+
],
55+
[]
56+
);
57+
}
58+
59+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Symfony;
4+
5+
use PhpParser\PrettyPrinter\Standard;
6+
use PHPStan\Rules\Rule;
7+
use PHPStan\Symfony\XmlServiceMapFactory;
8+
use PHPStan\Testing\RuleTestCase;
9+
use PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension;
10+
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
11+
12+
final class ContainerInterfaceUnknownServiceRuleFakeTest extends RuleTestCase
13+
{
14+
15+
protected function getRule(): Rule
16+
{
17+
return new ContainerInterfaceUnknownServiceRule((new XmlServiceMapFactory(null))->create(), new Standard());
18+
}
19+
20+
/**
21+
* @return \PHPStan\Type\MethodTypeSpecifyingExtension[]
22+
*/
23+
protected function getMethodTypeSpecifyingExtensions(): array
24+
{
25+
return [
26+
new ServiceTypeSpecifyingExtension(Controller::class, new Standard()),
27+
];
28+
}
29+
30+
public function testGetPrivateService(): void
31+
{
32+
$this->analyse(
33+
[
34+
__DIR__ . '/ExampleController.php',
35+
],
36+
[]
37+
);
38+
}
39+
40+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /