Skip to content

Commit 4c48973

Browse files
authored
[container] get service by name with PHP const (#204)
1 parent 72911c5 commit 4c48973

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

src/Handler/ContainerHandler.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace Psalm\SymfonyPsalmPlugin\Handler;
44

5+
use function constant;
56
use PhpParser\Node\Expr\ClassConstFetch;
7+
use PhpParser\Node\Identifier;
68
use PhpParser\Node\Scalar\String_;
79
use Psalm\CodeLocation;
810
use Psalm\IssueBuffer;
@@ -73,10 +75,28 @@ public static function afterMethodCallAnalysis(AfterMethodCallAnalysisEvent $eve
7375
return;
7476
}
7577

76-
if ($expr->args[0]->value instanceof String_) {
77-
$serviceId = $expr->args[0]->value->value;
78-
} elseif ($expr->args[0]->value instanceof ClassConstFetch) {
79-
$serviceId = (string) $expr->args[0]->value->class->getAttribute('resolvedName');
78+
$idArgument = $expr->args[0]->value;
79+
80+
if ($idArgument instanceof String_) {
81+
$serviceId = $idArgument->value;
82+
} elseif ($idArgument instanceof ClassConstFetch) {
83+
$className = (string) $idArgument->class->getAttribute('resolvedName');
84+
if ('self' === $className) {
85+
$className = $event->getStatementsSource()->getSource()->getFQCLN();
86+
}
87+
if (!$idArgument->name instanceof Identifier || !$className) {
88+
return;
89+
}
90+
91+
if ('class' === $idArgument->name->name) {
92+
$serviceId = $className;
93+
} else {
94+
try {
95+
$serviceId = constant($className.'::'.$idArgument->name->name);
96+
} catch (\Exception $e) {
97+
return;
98+
}
99+
}
80100
} else {
81101
return;
82102
}

tests/acceptance/acceptance/ServiceSubscriber.feature

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,19 @@ Feature: Service Subscriber
5757
| Trace | $service2: Psalm\SymfonyPsalmPlugin\Tests\Fixture\DummyPrivateService |
5858
| Trace | $service3: Psalm\SymfonyPsalmPlugin\Tests\Fixture\DummyPrivateService |
5959
And I see no other errors
60+
61+
Scenario: Asserting psalm recognizes return type of services fetched name by PHP constants.
62+
Given I have the following code
63+
"""
64+
public function __invoke()
65+
{
66+
/** @psalm-trace $service1 */
67+
$service1 = $this->container->get(\Psalm\SymfonyPsalmPlugin\Tests\Fixture\DummyPrivateService::CUSTOM_SERVICE_NAME);
68+
}
69+
}
70+
"""
71+
When I run Psalm
72+
Then I see these errors
73+
| Type | Message |
74+
| Trace | $service1: Psalm\SymfonyPsalmPlugin\Tests\Fixture\DummyPrivateService |
75+
And I see no other errors

tests/fixture/DummyPrivateService.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
class DummyPrivateService
66
{
7+
const CUSTOM_SERVICE_NAME = 'dummy_service_with_locator';
8+
79
public function foo(): string
810
{
911
return 'foo';

0 commit comments

Comments
 (0)