Skip to content

Commit 9b2d935

Browse files
authored
Skip private ctors only when those have zero params (#159)
1 parent f37593e commit 9b2d935

File tree

4 files changed

+18
-5
lines changed

4 files changed

+18
-5
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ parameters:
328328

329329
#### Private constructors:
330330
- Those are never reported as dead as those are often used to deny class instantiation
331+
- This applies only to constructors without any parameters
331332

332333
#### Interface methods:
333334
- If you never call interface method over the interface, but only over its implementors, it gets reported as dead

src/Collector/ClassDefinitionCollector.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
use ShipMonk\PHPStan\DeadCode\Enum\Visibility;
2020
use function array_fill_keys;
2121
use function array_map;
22+
use function count;
2223

2324
/**
2425
* @implements Collector<ClassLike, array{
2526
* kind: string,
2627
* name: string,
2728
* constants: array<string, array{line: int}>,
28-
* methods: array<string, array{line: int, abstract: bool, visibility: int-mask-of<Visibility::*>}>,
29+
* methods: array<string, array{line: int, params: int, abstract: bool, visibility: int-mask-of<Visibility::*>}>,
2930
* parents: array<string, null>,
3031
* traits: array<string, array{excluded?: list<string>, aliases?: array<string, string>}>,
3132
* interfaces: array<string, null>,
@@ -52,7 +53,7 @@ public function getNodeType(): string
5253
* kind: string,
5354
* name: string,
5455
* constants: array<string, array{line: int}>,
55-
* methods: array<string, array{line: int, abstract: bool, visibility: int-mask-of<Visibility::*>}>,
56+
* methods: array<string, array{line: int, params: int, abstract: bool, visibility: int-mask-of<Visibility::*>}>,
5657
* parents: array<string, null>,
5758
* traits: array<string, array{excluded?: list<string>, aliases?: array<string, string>}>,
5859
* interfaces: array<string, null>,
@@ -76,6 +77,7 @@ public function processNode(
7677
foreach ($node->getMethods() as $method) {
7778
$methods[$method->name->toString()] = [
7879
'line' => $method->getStartLine(),
80+
'params' => count($method->params),
7981
'abstract' => $method->isAbstract() || $node instanceof Interface_,
8082
'visibility' => $method->flags & (Visibility::PUBLIC | Visibility::PROTECTED | Visibility::PRIVATE),
8183
];

src/Rule/DeadCodeRule.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class DeadCodeRule implements Rule, DiagnoseExtension
7676
* name: string,
7777
* file: string,
7878
* constants: array<string, array{line: int}>,
79-
* methods: array<string, array{line: int, abstract: bool, visibility: int-mask-of<Visibility::*>}>,
79+
* methods: array<string, array{line: int, params: int, abstract: bool, visibility: int-mask-of<Visibility::*>}>,
8080
* parents: array<string, null>,
8181
* traits: array<string, array{excluded?: list<string>, aliases?: array<string, string>}>,
8282
* interfaces: array<string, null>
@@ -692,6 +692,7 @@ private function isNeverReportedAsDead(BlackMember $blackMember): bool
692692
}
693693

694694
$kind = $this->typeDefinitions[$typeName]['kind'] ?? null;
695+
$params = $this->typeDefinitions[$typeName]['methods'][$memberName]['params'] ?? 0;
695696
$abstract = $this->typeDefinitions[$typeName]['methods'][$memberName]['abstract'] ?? false;
696697
$visibility = $this->typeDefinitions[$typeName]['methods'][$memberName]['visibility'] ?? 0;
697698

@@ -701,8 +702,8 @@ private function isNeverReportedAsDead(BlackMember $blackMember): bool
701702
return true;
702703
}
703704

704-
if ($memberName === '__construct' && ($visibility & Visibility::PRIVATE) !== 0) {
705-
// private constructors are often used to deny instantiation
705+
if ($memberName === '__construct' && ($visibility & Visibility::PRIVATE) !== 0 && $params === 0) {
706+
// private constructors with zero parameters are often used to deny instantiation
706707
return true;
707708
}
708709

tests/Rule/data/methods/ctor-denied.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,12 @@ private function __construct()
99
}
1010
}
1111

12+
class NotUtility
13+
{
14+
private function __construct(private int $foo) // error: Unused CtorDenied\NotUtility::__construct
15+
{
16+
17+
}
18+
19+
}
20+

0 commit comments

Comments
 (0)