Skip to content

Commit a193b3d

Browse files
collect extends also for interfaces
1 parent 92bfae0 commit a193b3d

File tree

9 files changed

+112
-82
lines changed

9 files changed

+112
-82
lines changed

src/Analyzer/ClassDescription.php

+21-25
Original file line numberDiff line numberDiff line change
@@ -6,54 +6,47 @@
66

77
class ClassDescription
88
{
9-
/** @var FullyQualifiedClassName */
10-
private $FQCN;
9+
private FullyQualifiedClassName $FQCN;
1110

1211
/** @var list<ClassDependency> */
13-
private $dependencies;
12+
private array $dependencies;
1413

1514
/** @var list<FullyQualifiedClassName> */
16-
private $interfaces;
15+
private array $interfaces;
1716

18-
/** @var ?FullyQualifiedClassName */
19-
private $extends;
17+
/** @var list<FullyQualifiedClassName> */
18+
private array $extends;
2019

21-
/** @var bool */
22-
private $final;
20+
/** @var list<string> */
21+
private array $docBlock;
2322

24-
/** @var bool */
25-
private $readonly;
23+
/** @var list<FullyQualifiedClassName> */
24+
private array $attributes;
2625

27-
/** @var bool */
28-
private $abstract;
26+
private bool $final;
2927

30-
/** @var bool */
31-
private $interface;
28+
private bool $readonly;
3229

33-
/** @var bool */
34-
private $trait;
30+
private bool $abstract;
3531

36-
/** @var bool */
37-
private $enum;
32+
private bool $interface;
3833

39-
/** @var list<string> */
40-
private $docBlock;
34+
private bool $trait;
4135

42-
/** @var list<FullyQualifiedClassName> */
43-
private $attributes;
36+
private bool $enum;
4437

4538
/**
4639
* @param list<ClassDependency> $dependencies
4740
* @param list<FullyQualifiedClassName> $interfaces
48-
* @param ?FullyQualifiedClassName $extends
41+
* @param list<FullyQualifiedClassName> $extends
4942
* @param list<FullyQualifiedClassName> $attributes
5043
* @param list<string> $docBlock
5144
*/
5245
public function __construct(
5346
FullyQualifiedClassName $FQCN,
5447
array $dependencies,
5548
array $interfaces,
56-
?FullyQualifiedClassName $extends,
49+
array $extends,
5750
bool $final,
5851
bool $readonly,
5952
bool $abstract,
@@ -127,7 +120,10 @@ public function getInterfaces(): array
127120
return $this->interfaces;
128121
}
129122

130-
public function getExtends(): ?FullyQualifiedClassName
123+
/**
124+
* @return list<FullyQualifiedClassName>
125+
*/
126+
public function getExtends(): array
131127
{
132128
return $this->extends;
133129
}

src/Analyzer/ClassDescriptionBuilder.php

+16-23
Original file line numberDiff line numberDiff line change
@@ -8,47 +8,40 @@
88
class ClassDescriptionBuilder
99
{
1010
/** @var list<ClassDependency> */
11-
private $classDependencies = [];
11+
private array $classDependencies = [];
1212

13-
/** @var ?FullyQualifiedClassName */
14-
private $FQCN;
13+
private ?FullyQualifiedClassName $FQCN = null;
1514

1615
/** @var list<FullyQualifiedClassName> */
17-
private $interfaces = [];
16+
private array $interfaces = [];
1817

19-
/** @var ?FullyQualifiedClassName */
20-
private $extend;
18+
/** @var list<FullyQualifiedClassName> */
19+
private array $extend = [];
2120

22-
/** @var bool */
23-
private $final = false;
21+
private bool $final = false;
2422

25-
/** @var bool */
26-
private $readonly = false;
23+
private bool $readonly = false;
2724

28-
/** @var bool */
29-
private $abstract = false;
25+
private bool $abstract = false;
3026

3127
/** @var list<string> */
32-
private $docBlock = [];
28+
private array $docBlock = [];
3329

3430
/** @var list<FullyQualifiedClassName> */
35-
private $attributes = [];
31+
private array $attributes = [];
3632

37-
/** @var bool */
38-
private $interface = false;
33+
private bool $interface = false;
3934

40-
/** @var bool */
41-
private $trait = false;
35+
private bool $trait = false;
4236

43-
/** @var bool */
44-
private $enum = false;
37+
private bool $enum = false;
4538

4639
public function clear(): void
4740
{
4841
$this->FQCN = null;
4942
$this->classDependencies = [];
5043
$this->interfaces = [];
51-
$this->extend = null;
44+
$this->extend = [];
5245
$this->final = false;
5346
$this->readonly = false;
5447
$this->abstract = false;
@@ -81,10 +74,10 @@ public function addDependency(ClassDependency $cd): self
8174
return $this;
8275
}
8376

84-
public function setExtends(string $FQCN, int $line): self
77+
public function addExtends(string $FQCN, int $line): self
8578
{
8679
$this->addDependency(new ClassDependency($FQCN, $line));
87-
$this->extend = FullyQualifiedClassName::fromString($FQCN);
80+
$this->extend[] = FullyQualifiedClassName::fromString($FQCN);
8881

8982
return $this;
9083
}

src/Analyzer/FileVisitor.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function enterNode(Node $node): void
3535

3636
if (!$node->isAnonymous() && null !== $node->extends) {
3737
$this->classDescriptionBuilder
38-
->setExtends($node->extends->toString(), $node->getLine());
38+
->addExtends($node->extends->toString(), $node->getLine());
3939
}
4040

4141
if ($node->isFinal()) {
@@ -182,6 +182,11 @@ public function enterNode(Node $node): void
182182

183183
$this->classDescriptionBuilder->setClassName($node->namespacedName->toCodeString());
184184
$this->classDescriptionBuilder->setInterface(true);
185+
186+
foreach ($node->extends as $interface) {
187+
$this->classDescriptionBuilder
188+
->addExtends($interface->toString(), $interface->getLine());
189+
}
185190
}
186191

187192
if ($node instanceof Node\Stmt\Trait_) {

src/Expression/ForClasses/Extend.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
class Extend implements Expression
1515
{
1616
/** @var string[] */
17-
private $classNames;
17+
private array $classNames;
1818

1919
public function __construct(string ...$classNames)
2020
{
@@ -34,8 +34,10 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
3434

3535
/** @var string $className */
3636
foreach ($this->classNames as $className) {
37-
if (null !== $extends && $extends->matches($className)) {
38-
return;
37+
foreach ($extends as $extend) {
38+
if ($extend->matches($className)) {
39+
return;
40+
}
3941
}
4042
}
4143

src/Expression/ForClasses/NotExtend.php

+10-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
class NotExtend implements Expression
1515
{
1616
/** @var string[] */
17-
private $classNames;
17+
private array $classNames;
1818

1919
public function __construct(string ...$classNames)
2020
{
@@ -34,15 +34,15 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str
3434

3535
/** @var string $className */
3636
foreach ($this->classNames as $className) {
37-
if (null !== $extends && $extends->matches($className)) {
38-
$violation = Violation::create(
39-
$theClass->getFQCN(),
40-
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
41-
);
42-
43-
$violations->add($violation);
44-
45-
return;
37+
foreach ($extends as $extend) {
38+
if ($extend->matches($className)) {
39+
$violation = Violation::create(
40+
$theClass->getFQCN(),
41+
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
42+
);
43+
44+
$violations->add($violation);
45+
}
4646
}
4747
}
4848
}

tests/Unit/Analyzer/FileVisitorTest.php

+45-11
Original file line numberDiff line numberDiff line change
@@ -106,27 +106,27 @@ class Cat implements AnInterface
106106
public function test_it_should_parse_extends_class(): void
107107
{
108108
$code = <<< 'EOF'
109-
<?php
109+
<?php
110110
111-
namespace Root\Animals;
111+
namespace Root\Animals;
112112
113-
class Animal
114-
{
115-
}
113+
class Animal
114+
{
115+
}
116116
117-
class Cat extends Animal
118-
{
117+
class Cat extends Animal
118+
{
119119
120-
}
121-
EOF;
120+
}
121+
EOF;
122122

123123
/** @var FileParser $fp */
124124
$fp = FileParserFactory::createFileParser(TargetPhpVersion::create('7.4'));
125125
$fp->parse($code, 'relativePathName');
126126

127127
$cd = $fp->getClassDescriptions()[1];
128128

129-
$this->assertEquals('Root\Animals\Animal', $cd->getExtends()->toString());
129+
$this->assertEquals('Root\Animals\Animal', $cd->getExtends()[0]->toString());
130130
}
131131

132132
public function test_it_should_not_parse_extends_from_insider_anonymousclass(): void
@@ -155,7 +155,7 @@ public function methodWithAnonymous(): void
155155

156156
$cd = $fp->getClassDescriptions()[1];
157157

158-
$this->assertEquals('Root\Animals\Animal', $cd->getExtends()->toString());
158+
$this->assertEquals('Root\Animals\Animal', $cd->getExtends()[0]->toString());
159159
}
160160

161161
public function test_should_depends_on_these_namespaces(): void
@@ -882,6 +882,40 @@ public function getBookList(): QueryBuilder;
882882
$this->assertCount(1, $violations);
883883
}
884884

885+
public function test_it_parse_interface_extends(): void
886+
{
887+
$code = <<< 'EOF'
888+
<?php
889+
namespace MyProject\AppBundle\Application;
890+
891+
interface FooAble
892+
{
893+
public function foo();
894+
}
895+
+
896+
interface BarAble
897+
{
898+
public function bar();
899+
}
900+
901+
902+
interface ForBarAble extends FooAble, BarAble
903+
{
904+
public function foobar();
905+
}
906+
EOF;
907+
908+
/** @var FileParser $fp */
909+
$fp = FileParserFactory::createFileParser(TargetPhpVersion::create('8.1'));
910+
$fp->parse($code, 'relativePathName');
911+
912+
$cd = $fp->getClassDescriptions();
913+
914+
$this->assertCount(3, $cd);
915+
$this->assertEquals('MyProject\AppBundle\Application\FooAble', $cd[2]->getExtends()[0]->toString());
916+
$this->assertEquals('MyProject\AppBundle\Application\BarAble', $cd[2]->getExtends()[1]->toString());
917+
}
918+
885919
public function test_it_handles_return_types(): void
886920
{
887921
$code = <<< 'EOF'

tests/Unit/Expressions/ForClasses/ExtendTest.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function test_it_should_return_no_violation_on_success(): void
1717

1818
$classDescription = (new ClassDescriptionBuilder())
1919
->setClassName('My\Class')
20-
->setExtends('My\BaseClass', 10)
20+
->addExtends('My\BaseClass', 10)
2121
->build();
2222

2323
$violations = new Violations();
@@ -32,7 +32,7 @@ public function test_it_should_work_with_wildcards(): void
3232

3333
$classDescription = (new ClassDescriptionBuilder())
3434
->setClassName('My\Class')
35-
->setExtends('My\B14Class', 10)
35+
->addExtends('My\B14Class', 10)
3636
->build();
3737

3838
$violations = new Violations();
@@ -47,7 +47,7 @@ public function test_it_should_return_violation_error_when_argument_is_a_regex()
4747

4848
$classDescription = (new ClassDescriptionBuilder())
4949
->setClassName('My\Class')
50-
->setExtends('My\BaseClass', 10)
50+
->addExtends('My\BaseClass', 10)
5151
->build();
5252

5353
$violations = new Violations();
@@ -61,7 +61,7 @@ public function test_it_should_return_violation_error_when_class_not_extend(): v
6161

6262
$classDescription = (new ClassDescriptionBuilder())
6363
->setClassName('HappyIsland')
64-
->setExtends('My\AnotherClass', 10)
64+
->addExtends('My\AnotherClass', 10)
6565
->build();
6666

6767
$violations = new Violations();
@@ -95,7 +95,7 @@ public function test_it_should_accept_multiple_extends(): void
9595

9696
$classDescription = (new ClassDescriptionBuilder())
9797
->setClassName('My\Class')
98-
->setExtends('My\SecondExtend', 10)
98+
->addExtends('My\SecondExtend', 10)
9999
->build();
100100

101101
$violations = new Violations();

tests/Unit/Expressions/ForClasses/NotExtendTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function test_it_should_return_violation_error(): void
1717

1818
$classDescription = (new ClassDescriptionBuilder())
1919
->setClassName('HappyIsland')
20-
->setExtends('My\BaseClass', 1)
20+
->addExtends('My\BaseClass', 1)
2121
->build();
2222

2323
$because = 'we want to add this rule for our software';
@@ -36,7 +36,7 @@ public function test_it_should_not_return_violation_error_if_extends_another_cla
3636

3737
$classDescription = (new ClassDescriptionBuilder())
3838
->setClassName('HappyIsland')
39-
->setExtends('My\AnotherClass', 1)
39+
->addExtends('My\AnotherClass', 1)
4040
->build();
4141

4242
$because = 'we want to add this rule for our software';
@@ -53,7 +53,7 @@ public function test_it_should_return_violation_error_for_multiple_extends(): vo
5353

5454
$classDescription = (new ClassDescriptionBuilder())
5555
->setClassName('HappyIsland')
56-
->setExtends('My\SecondExtend', 1)
56+
->addExtends('My\SecondExtend', 1)
5757
->build();
5858

5959
$because = 'we want to add this rule for our software';

0 commit comments

Comments
 (0)