Skip to content

Commit 5b091f4

Browse files
committed
Detect interface case name changes as PATCH
1 parent 6424295 commit 5b091f4

File tree

5 files changed

+124
-13
lines changed

5 files changed

+124
-13
lines changed

docs/Ruleset.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ V077 | MINOR | Interface method parameter default added
111111
V078 | MAJOR | Interface method parameter default removed
112112
V079 | MAJOR | Interface method parameter default value changed
113113
V151 | PATCH | Interface method renamed (case only)
114+
V153 | PATCH | Interface renamed (case only)
114115

115116
# Trait
116117

src/PHPSemVerChecker/Analyzer/InterfaceAnalyzer.php

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPSemVerChecker\Operation\InterfaceAdded;
66
use PHPSemVerChecker\Operation\InterfaceRemoved;
7+
use PHPSemVerChecker\Operation\InterfaceRenamedCaseOnly;
78
use PHPSemVerChecker\Registry\Registry;
89
use PHPSemVerChecker\Report\Report;
910

@@ -14,39 +15,67 @@ public function analyze(Registry $registryBefore, Registry $registryAfter)
1415
{
1516
$report = new Report();
1617

17-
$keysBefore = array_keys($registryBefore->data['interface']);
18-
$keysAfter = array_keys($registryAfter->data['interface']);
19-
$added = array_diff($keysAfter, $keysBefore);
20-
$removed = array_diff($keysBefore, $keysAfter);
21-
$toVerify = array_intersect($keysBefore, $keysAfter);
18+
$interfacesBefore = $registryBefore->data['interface'];
19+
$interfacesAfter = $registryAfter->data['interface'];
20+
21+
$interfacesBeforeKeyed = [];
22+
$mappingsBeforeKeyed = [];
23+
foreach($interfacesBefore as $key => $interfaceBefore)
24+
{
25+
$interfacesBeforeKeyed[strtolower($interfaceBefore->name)] = $interfaceBefore;
26+
$mappingsBeforeKeyed[strtolower($interfaceBefore->name)] = $registryBefore->mapping['interface'][$key];
27+
}
28+
29+
$interfacesAfterKeyed = [];
30+
$mappingsAfterKeyed = [];
31+
foreach($interfacesAfter as $key => $interfaceAfter)
32+
{
33+
$interfacesAfterKeyed[strtolower($interfaceAfter->name)] = $interfaceAfter;
34+
$mappingsAfterKeyed[strtolower($interfaceAfter->name)] = $registryAfter->mapping['interface'][$key];
35+
}
36+
37+
38+
$interfaceNamesBefore = array_keys($interfacesBeforeKeyed);
39+
$interfaceNamesAfter = array_keys($interfacesAfterKeyed);
40+
$added = array_diff($interfaceNamesAfter, $interfaceNamesBefore);
41+
$removed = array_diff($interfaceNamesBefore, $interfaceNamesAfter);
42+
$toVerify = array_intersect($interfaceNamesBefore, $interfaceNamesAfter);
2243

2344
foreach ($removed as $key) {
24-
$fileBefore = $registryBefore->mapping['interface'][$key];
25-
$interfaceBefore = $registryBefore->data['interface'][$key];
45+
$fileBefore = $mappingsBeforeKeyed[$key];
46+
$interfaceBefore = $interfacesBeforeKeyed[$key];
2647

2748
$data = new InterfaceRemoved($fileBefore, $interfaceBefore);
2849
$report->addInterface($data);
2950
}
3051

3152
foreach ($toVerify as $key) {
32-
$fileBefore = $registryBefore->mapping['interface'][$key];
53+
$fileBefore = $mappingsBeforeKeyed[$key];
3354
/** @var \PhpParser\Node\Stmt\Interface_ $interfaceBefore */
34-
$interfaceBefore = $registryBefore->data['interface'][$key];
35-
$fileAfter = $registryAfter->mapping['interface'][$key];
55+
$interfaceBefore = $interfacesBeforeKeyed[$key];
56+
$fileAfter = $mappingsAfterKeyed[$key];
3657
/** @var \PhpParser\Node\Stmt\Interface_ $interfaceBefore */
37-
$interfaceAfter = $registryAfter->data['interface'][$key];
58+
$interfaceAfter = $interfacesAfterKeyed[$key];
3859

3960
// Leave non-strict comparison here
4061
if ($interfaceBefore != $interfaceAfter) {
62+
63+
// Check if the name of the interface has changed case.
64+
if($interfaceBefore->name !== $interfaceAfter->name)
65+
{
66+
$report->add('interface', new InterfaceRenamedCaseOnly($fileAfter, $interfaceAfter));
67+
}
68+
4169
$analyzer = new ClassMethodAnalyzer('interface', $fileBefore, $fileAfter);
4270
$interfaceMethodReport = $analyzer->analyze($interfaceBefore, $interfaceAfter);
4371
$report->merge($interfaceMethodReport);
4472
}
4573
}
4674

4775
foreach ($added as $key) {
48-
$fileAfter = $registryAfter->mapping['interface'][$key];
49-
$interfaceAfter = $registryAfter->data['interface'][$key];
76+
77+
$fileAfter = $mappingsAfterKeyed[$key];
78+
$interfaceAfter = $interfacesAfterKeyed[$key];
5079

5180
$data = new InterfaceAdded($fileAfter, $interfaceAfter);
5281
$report->addInterface($data);

src/PHPSemVerChecker/Configuration/LevelMapping.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class LevelMapping
124124
'V150' => Level::PATCH,
125125
'V151' => Level::PATCH,
126126
'V152' => Level::PATCH,
127+
'V153' => Level::PATCH,
127128
];
128129

129130
public static function getLevelForCode($code)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace PHPSemVerChecker\Operation;
4+
5+
use PhpParser\Node\Stmt\Interface_;
6+
use PHPSemVerChecker\Node\Statement\Interface_ as PInterface;
7+
8+
class InterfaceRenamedCaseOnly extends Operation {
9+
/**
10+
* @var string
11+
*/
12+
protected $code = 'V153';
13+
/**
14+
* @var string
15+
*/
16+
protected $reason = 'Interface was renamed (case only).';
17+
/**
18+
* @var string
19+
*/
20+
protected $fileAfter;
21+
/**
22+
* @var \PhpParser\Node\Stmt\Interface_
23+
*/
24+
protected $interfaceAfter;
25+
26+
/**
27+
* @param string $fileAfter
28+
* @param \PhpParser\Node\Stmt\Interface_ $interfaceAfter
29+
*/
30+
public function __construct($fileAfter, Interface_ $interfaceAfter)
31+
{
32+
$this->fileAfter = $fileAfter;
33+
$this->interfaceAfter = $interfaceAfter;
34+
}
35+
36+
/**
37+
* @return string
38+
*/
39+
public function getLocation()
40+
{
41+
return $this->fileAfter;
42+
}
43+
44+
/**
45+
* @return int
46+
*/
47+
public function getLine()
48+
{
49+
return $this->interfaceAfter->getLine();
50+
}
51+
52+
/**
53+
* @return string
54+
*/
55+
public function getTarget()
56+
{
57+
return PInterface::getFullyQualifiedName($this->interfaceAfter);
58+
}
59+
}

tests/PHPSemVerChecker/Analyzer/InterfaceAnalyzerTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,25 @@ public function testInterfaceAdded()
6262
$this->assertSame('Interface was added.', $report[$context][$expectedLevel][0]->getReason());
6363
$this->assertSame('tmp', $report[$context][$expectedLevel][0]->getTarget());
6464
}
65+
66+
public function testInterfaceRenamedCaseOnly()
67+
{
68+
$before = new Registry();
69+
$after = new Registry();
70+
71+
$interfaceBefore = new Interface_('TestInterface');
72+
$before->addInterface($interfaceBefore);
73+
74+
$interfaceAfter = new Interface_('testinterface');
75+
$after->addInterface($interfaceAfter);
76+
77+
$analyzer = new InterfaceAnalyzer();
78+
$report = $analyzer->analyze($before, $after);
79+
80+
$context = 'interface';
81+
$expectedLevel = Level::PATCH;
82+
Assert::assertDifference($report, $context, $expectedLevel);
83+
$this->assertSame('V153', $report[$context][$expectedLevel][0]->getCode());
84+
$this->assertSame('Interface was renamed (case only).', $report[$context][$expectedLevel][0]->getReason());
85+
}
6586
}

0 commit comments

Comments
 (0)