|
6 | 6 | use PhpParser\Node\Expr\MethodCall;
|
7 | 7 | use PhpParser\PrettyPrinter\Standard;
|
8 | 8 | use PHPStan\Analyser\Scope;
|
| 9 | +use PHPStan\Rules\IdentifierRuleError; |
9 | 10 | use PHPStan\Rules\Rule;
|
10 | 11 | use PHPStan\Rules\RuleErrorBuilder;
|
| 12 | +use PHPStan\Symfony\AutowireLoaderServiceMapFactory; |
| 13 | +use PHPStan\Symfony\DefaultServiceMap; |
11 | 14 | use PHPStan\Symfony\ServiceMap;
|
12 | 15 | use PHPStan\Type\ObjectType;
|
13 | 16 | use PHPStan\Type\Symfony\Helper;
|
@@ -66,19 +69,56 @@ public function processNode(Node $node, Scope $scope): array
|
66 | 69 | }
|
67 | 70 |
|
68 | 71 | $serviceId = $this->serviceMap::getServiceIdFromNode($node->getArgs()[0]->value, $scope);
|
69 |
| - if ($serviceId !== null) { |
70 |
| - $service = $this->serviceMap->getService($serviceId); |
71 |
| - $serviceIdType = $scope->getType($node->getArgs()[0]->value); |
72 |
| - if ($service === null && !$scope->getType(Helper::createMarkerNode($node->var, $serviceIdType, $this->printer))->equals($serviceIdType)) { |
| 72 | + if ($serviceId === null) { |
| 73 | + return []; |
| 74 | + } |
| 75 | + |
| 76 | + $isContainerInterfaceType = $isContainerType->yes() || $isPsrContainerType->yes(); |
| 77 | + if ($isContainerInterfaceType) { |
| 78 | + $autowireLoaderResult = $this->getAutowireLoaderResult($node, $scope, $serviceId); |
| 79 | + |
| 80 | + if ($autowireLoaderResult !== null) { |
| 81 | + return $autowireLoaderResult; |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + $service = $this->serviceMap->getService($serviceId); |
| 86 | + $serviceIdType = $scope->getType($node->getArgs()[0]->value); |
| 87 | + if ($service === null && !$scope->getType(Helper::createMarkerNode($node->var, $serviceIdType, $this->printer))->equals($serviceIdType)) { |
| 88 | + return [ |
| 89 | + RuleErrorBuilder::message(sprintf('Service "%s" is not registered in the container.', $serviceId)) |
| 90 | + ->identifier('symfonyContainer.serviceNotFound') |
| 91 | + ->build(), |
| 92 | + ]; |
| 93 | + } |
| 94 | + |
| 95 | + return []; |
| 96 | + } |
| 97 | + |
| 98 | + /** |
| 99 | + * @return list<IdentifierRuleError>|null |
| 100 | + */ |
| 101 | + private function getAutowireLoaderResult(Node $node, Scope $scope, string $serviceId): ?array |
| 102 | + { |
| 103 | + $autowireLocatorServiceMapFactory = new AutowireLoaderServiceMapFactory($node, $scope); |
| 104 | + $autowireLocatorServiceMap = $autowireLocatorServiceMapFactory->create(); |
| 105 | + |
| 106 | + // Our container has a valid AutowireLoader attribute, else we would get a FakeServiceMap. |
| 107 | + if ($autowireLocatorServiceMap instanceof DefaultServiceMap) { |
| 108 | + $autowireLocatorService = $autowireLocatorServiceMap->getService($serviceId); |
| 109 | + |
| 110 | + if ($autowireLocatorService === null) { |
73 | 111 | return [
|
74 |
| - RuleErrorBuilder::message(sprintf('Service "%s" is not registered in the container.', $serviceId)) |
75 |
| - ->identifier('symfonyContainer.serviceNotFound') |
| 112 | + RuleErrorBuilder::message(sprintf('Service "%s" is not registered in the AutowireLocator.', $serviceId)) |
| 113 | + ->identifier('symfonyContainer.undefinedService') |
76 | 114 | ->build(),
|
77 | 115 | ];
|
78 | 116 | }
|
| 117 | + |
| 118 | + return []; |
79 | 119 | }
|
80 | 120 |
|
81 |
| - return []; |
| 121 | + return null; |
82 | 122 | }
|
83 | 123 |
|
84 | 124 | }
|
0 commit comments