Skip to content

Commit 74e7ddf

Browse files
authored
Symfony: skip services not instantiated by the DIC (#348)
1 parent e10651d commit 74e7ddf

4 files changed

Lines changed: 60 additions & 0 deletions

File tree

src/Provider/SymfonyUsageProvider.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,11 @@ private function fillDicClasses(string $containerXmlPath): void
11431143
foreach ($xml->services->service as $serviceDefinition) {
11441144
/** @var SimpleXMLElement $serviceAttributes */
11451145
$serviceAttributes = $serviceDefinition->attributes();
1146+
1147+
if ($this->isServiceNotInstantiatedByContainer($serviceDefinition, $serviceAttributes)) {
1148+
continue;
1149+
}
1150+
11461151
$class = isset($serviceAttributes->class) ? (string) $serviceAttributes->class : null;
11471152
$constructor = isset($serviceAttributes->constructor) ? (string) $serviceAttributes->constructor : '__construct';
11481153

@@ -1191,6 +1196,32 @@ private function fillDicClasses(string $containerXmlPath): void
11911196
}
11921197
}
11931198

1199+
private function isServiceNotInstantiatedByContainer(
1200+
SimpleXMLElement $serviceDefinition,
1201+
SimpleXMLElement $serviceAttributes,
1202+
): bool
1203+
{
1204+
if (isset($serviceAttributes->abstract) && (string) $serviceAttributes->abstract === 'true') {
1205+
return true;
1206+
}
1207+
1208+
if (isset($serviceAttributes->synthetic) && (string) $serviceAttributes->synthetic === 'true') {
1209+
return true;
1210+
}
1211+
1212+
foreach ($serviceDefinition->tag ?? [] as $tagDefinition) {
1213+
/** @var SimpleXMLElement $tagAttributes */
1214+
$tagAttributes = $tagDefinition->attributes();
1215+
$tagName = $tagAttributes->name !== null ? (string) $tagAttributes->name : null;
1216+
1217+
if ($tagName === 'container.error' || $tagName === 'container.excluded') {
1218+
return true;
1219+
}
1220+
}
1221+
1222+
return false;
1223+
}
1224+
11941225
/**
11951226
* @return array<string, string>
11961227
*/

tests/Provider/SymfonyUsageProviderTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public function testExplicitContainerXmlPaths(): void
5050
self::assertArrayHasKey('Symfony\DicClass1', $dicCalls);
5151
self::assertArrayHasKey('__construct', $dicCalls['Symfony\DicClass1']);
5252
self::assertArrayHasKey('calledViaDic', $dicCalls['Symfony\DicClass1']);
53+
54+
self::assertArrayNotHasKey('Symfony\DicErroredService', $dicCalls);
55+
self::assertArrayNotHasKey('Symfony\DicExcludedService', $dicCalls);
56+
self::assertArrayNotHasKey('Symfony\DicSyntheticService', $dicCalls);
57+
self::assertArrayNotHasKey('Symfony\DicAbstractService', $dicCalls);
5358
}
5459

5560
public function testExplicitContainerXmlPathsTakesPrecedenceOverContainer(): void

tests/Rule/data/providers/symfony.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,22 @@ class DicClass4 {
160160
public function __construct() {}
161161
}
162162

163+
class DicErroredService {
164+
public function __construct(string $name) {} // error: Unused Symfony\DicErroredService::__construct
165+
}
166+
167+
class DicExcludedService {
168+
public function __construct() {} // error: Unused Symfony\DicExcludedService::__construct
169+
}
170+
171+
class DicSyntheticService {
172+
public function __construct() {} // error: Unused Symfony\DicSyntheticService::__construct
173+
}
174+
175+
class DicAbstractService {
176+
public function __construct() {} // error: Unused Symfony\DicAbstractService::__construct
177+
}
178+
163179
class Sftp {
164180
const RETRY_LIMIT = 3; // used in yaml via !php/const
165181
}

tests/Rule/data/providers/symfony/services.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,13 @@
2424
<service id="Symfony\TaggedServiceB" class="Symfony\TaggedServiceB" public="true" autowire="true" autoconfigure="true">
2525
<tag name="app.tagged_handler"/>
2626
</service>
27+
<service id="Symfony\DicErroredService" class="Symfony\DicErroredService" autowire="true" autoconfigure="true">
28+
<tag name="container.error" message="Cannot autowire service &quot;Symfony\DicErroredService&quot;: argument &quot;$name&quot; of method &quot;__construct()&quot; is type-hinted &quot;string&quot;, you should configure its value explicitly."/>
29+
</service>
30+
<service id="Symfony\DicExcludedService" class="Symfony\DicExcludedService" abstract="true">
31+
<tag name="container.excluded" source="because it's a Doctrine entity"/>
32+
</service>
33+
<service id="Symfony\DicSyntheticService" class="Symfony\DicSyntheticService" synthetic="true" public="true"/>
34+
<service id="Symfony\DicAbstractService" class="Symfony\DicAbstractService" abstract="true"/>
2735
</services>
2836
</container>

0 commit comments

Comments
 (0)