Skip to content

Commit 51b5765

Browse files
authored
Improve no single interface (#136)
1 parent 883c98d commit 51b5765

File tree

8 files changed

+64
-20
lines changed

8 files changed

+64
-20
lines changed

config/code-complexity-rules.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ services:
1313
class: Symplify\PHPStanRules\Collector\ImplementedInterfaceCollector
1414
tags:
1515
- phpstan.collector
16+
17+
-
18+
class: Symplify\PHPStanRules\Collector\InterfaceOfAbstractClassCollector
19+
tags:
20+
- phpstan.collector

config/services/services.neon

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
services:
2-
- PhpParser\NodeFinder
3-
42
- Symplify\PHPStanRules\NodeTraverser\SimpleCallableNodeTraverser
53
- Symplify\PHPStanRules\PhpDocParser\PhpDocNodeTraverser
64
- Symplify\PHPStanRules\Reflection\ReflectionParser
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symplify\PHPStanRules\Collector;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Stmt\Class_;
9+
use PHPStan\Analyser\Scope;
10+
use PHPStan\Collectors\Collector;
11+
12+
final class InterfaceOfAbstractClassCollector implements Collector
13+
{
14+
public function getNodeType(): string
15+
{
16+
return Class_::class;
17+
}
18+
19+
/**
20+
* @param Class_ $node
21+
* @return string[]|null
22+
*/
23+
public function processNode(Node $node, Scope $scope): ?array
24+
{
25+
if (! $node->isAbstract()) {
26+
return null;
27+
}
28+
29+
$interfaceNames = [];
30+
31+
foreach ($node->implements as $implement) {
32+
$interfaceNames[] = $implement->toString();
33+
}
34+
35+
return $interfaceNames;
36+
}
37+
}

src/NodeFinder/TypeAwareNodeFinder.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
*/
1313
final class TypeAwareNodeFinder
1414
{
15-
public function __construct(
16-
private readonly NodeFinder $nodeFinder
17-
) {
15+
private readonly NodeFinder $nodeFinder;
16+
17+
public function __construct()
18+
{
19+
$this->nodeFinder = new NodeFinder();
1820
}
1921

2022
/**

src/Rules/ForbiddenMultipleClassLikeInOneFileRule.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ final class ForbiddenMultipleClassLikeInOneFileRule implements Rule, DocumentedR
2525
*/
2626
public const ERROR_MESSAGE = 'Multiple class/interface/trait is not allowed in single file';
2727

28+
private readonly NodeFinder $nodeFinder;
29+
2830
public function __construct(
29-
private readonly NodeFinder $nodeFinder
3031
) {
32+
$this->nodeFinder = new NodeFinder();
3133
}
3234

3335
/**

src/Rules/NoSingleInterfaceImplementerRule.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PHPStan\Rules\RuleErrorBuilder;
1414
use Symplify\PHPStanRules\Collector\ImplementedInterfaceCollector;
1515
use Symplify\PHPStanRules\Collector\InterfaceCollector;
16+
use Symplify\PHPStanRules\Collector\InterfaceOfAbstractClassCollector;
1617
use Symplify\RuleDocGenerator\Contract\DocumentedRuleInterface;
1718
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
1819
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@@ -45,10 +46,14 @@ public function processNode(Node $node, Scope $scope): array
4546
{
4647
$implementedInterfaces = Arrays::flatten($node->get(ImplementedInterfaceCollector::class));
4748
$interfaces = Arrays::flatten($node->get(InterfaceCollector::class));
49+
$interfacesOfAbstractClass = Arrays::flatten($node->get(InterfaceOfAbstractClassCollector::class));
4850

4951
$onceUsedInterfaces = $this->resolveOnceUsedInterfaces($implementedInterfaces);
50-
5152
$onceImplementedInterfaces = array_intersect($onceUsedInterfaces, $interfaces);
53+
54+
// remove the abstract class implemented, as required transitionally
55+
$onceImplementedInterfaces = array_diff($onceImplementedInterfaces, $interfacesOfAbstractClass);
56+
5257
if ($onceImplementedInterfaces === []) {
5358
return [];
5459
}

tests/Rules/NoSingleInterfaceImplementerRule/NoSingleInterfaceImplementerRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PHPUnit\Framework\Attributes\DataProvider;
1111
use Symplify\PHPStanRules\Collector\ImplementedInterfaceCollector;
1212
use Symplify\PHPStanRules\Collector\InterfaceCollector;
13+
use Symplify\PHPStanRules\Collector\InterfaceOfAbstractClassCollector;
1314
use Symplify\PHPStanRules\Rules\NoSingleInterfaceImplementerRule;
1415
use Symplify\PHPStanRules\Tests\Rules\NoSingleInterfaceImplementerRule\Fixture\SimpleInterface;
1516

@@ -33,6 +34,9 @@ public static function provideData(): Iterator
3334
yield [[__DIR__ . '/Fixture/SimpleInterface.php'], []];
3435
yield [[__DIR__ . '/Fixture/AllowAbstract.php', __DIR__ . '/Fixture/SimpleInterface.php'], []];
3536

37+
// already counted in abstract class
38+
yield [[__DIR__ . '/Fixture/AllowAbstract.php', __DIR__ . '/Fixture/SimpleInterface.php', __DIR__ . '/Fixture/ImplementsSimpleInterface.php'], []];
39+
3640
yield [
3741
[
3842
__DIR__ . '/Fixture/SimpleInterface.php',
@@ -58,6 +62,7 @@ protected function getCollectors(): array
5862
return [
5963
self::getContainer()->getByType(ImplementedInterfaceCollector::class),
6064
self::getContainer()->getByType(InterfaceCollector::class),
65+
self::getContainer()->getByType(InterfaceOfAbstractClassCollector::class),
6166
];
6267
}
6368

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,3 @@
1-
rules:
2-
- Symplify\PHPStanRules\Rules\NoSingleInterfaceImplementerRule
3-
4-
services:
5-
-
6-
class: Symplify\PHPStanRules\Collector\InterfaceCollector
7-
tags:
8-
- phpstan.collector
9-
10-
-
11-
class: Symplify\PHPStanRules\Collector\ImplementedInterfaceCollector
12-
tags:
13-
- phpstan.collector
1+
includes:
2+
- ../../../../config/code-complexity-rules.neon
3+
- ../../../../config/services/services.neon

0 commit comments

Comments
 (0)