Skip to content

Commit 11bfb67

Browse files
committed
[#10] Adding methods to an interface should generate a MAJOR
[#17] Verification codes Point toward a custom branch of php-parser (hopefully temporarily).
1 parent d907252 commit 11bfb67

27 files changed

+689
-87
lines changed

composer.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@
1919
"support": {
2020
"issues": "https://github.com/tomzx/php-semver-checker/issues"
2121
},
22+
"repositories": [
23+
{
24+
"type": "vcs",
25+
"url": "https://github.com/tomzx/php-parser"
26+
}
27+
],
2228
"require": {
2329
"php": ">=5.4.0",
2430
"symfony/console": "2.7.*@dev",
25-
"nikic/php-parser": "~1.0.2",
31+
"nikic/php-parser": "dev-features/php-semver-checker",
2632
"phpunit/php-file-iterator": "~1.3"
2733
},
2834
"require-dev": {

src/PHPSemVerChecker/Analyzer/ClassAnalyzer.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ public function analyze(Registry $registryBefore, Registry $registryAfter)
3838
/** @var \PhpParser\Node\Stmt\Class_ $classBefore */
3939
$classAfter = $registryAfter->data['class'][$key];
4040

41-
// TODO: Verify this comparison works properly <[email protected]>
4241
// Leave non-strict comparison here
4342
if ($classBefore != $classAfter) {
44-
$analyzer = new ClassMethodAnalyzer($fileBefore, $fileAfter);
43+
$analyzer = new ClassMethodAnalyzer('class', $fileBefore, $fileAfter);
4544
$classMethodReport = $analyzer->analyze($classBefore, $classAfter);
4645
$report->merge($classMethodReport);
4746
}

src/PHPSemVerChecker/Analyzer/ClassMethodAnalyzer.php

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPSemVerChecker\Analyzer;
44

5+
use PhpParser\Node\Stmt;
56
use PhpParser\Node\Stmt\Class_;
67
use PhpParser\Node\Stmt\ClassMethod;
78
use PHPSemVerChecker\Comparator\Signature;
@@ -15,27 +16,28 @@
1516

1617
class ClassMethodAnalyzer
1718
{
18-
protected $context = 'method';
19-
19+
protected $context;
2020
protected $fileBefore;
2121
protected $fileAfter;
2222

2323
/**
2424
* @param string $fileBefore
2525
* @param string $fileAfter
2626
*/
27-
public function __construct($fileBefore = null, $fileAfter = null)
27+
public function __construct($context, $fileBefore = null, $fileAfter = null)
2828
{
29+
$this->context = $context;
2930
$this->fileBefore = $fileBefore;
3031
$this->fileAfter = $fileAfter;
3132
}
3233

33-
public function analyze(Class_ $classBefore, Class_ $classAfter)
34+
public function analyze(Stmt $contextBefore, Stmt $contextAfter)
3435
{
36+
// TODO: Verify that the given contexts match the context given in the constructor <[email protected]>
3537
$report = new Report();
3638

37-
$methodsBefore = $classBefore->getMethods();
38-
$methodsAfter = $classAfter->getMethods();
39+
$methodsBefore = $contextBefore->getMethods();
40+
$methodsAfter = $contextAfter->getMethods();
3941

4042
$methodsBeforeKeyed = [];
4143
foreach ($methodsBefore as $method) {
@@ -66,7 +68,7 @@ public function analyze(Class_ $classBefore, Class_ $classAfter)
6668
// Removed methods can either be implemented in parent classes or not exist anymore
6769
foreach ($methodsRemoved as $method) {
6870
$methodBefore = $methodsBeforeKeyed[$method];
69-
$data = new ClassMethodRemoved($this->fileBefore, $classBefore, $methodBefore);
71+
$data = new ClassMethodRemoved($this->context, $this->fileBefore, $contextBefore, $methodBefore);
7072
$report->addClassMethod($data, Level::MAJOR);
7173
}
7274

@@ -83,36 +85,29 @@ public function analyze(Class_ $classBefore, Class_ $classAfter)
8385
// Signature
8486

8587
if ( ! Signature::isSameTypehints($paramsBefore, $paramsAfter)) {
86-
$data = new ClassMethodParameterChanged($this->fileBefore, $classBefore, $methodBefore, $this->fileAfter, $classAfter, $methodAfter);
88+
$data = new ClassMethodParameterChanged($this->context, $this->fileBefore, $contextBefore, $methodBefore, $this->fileAfter, $contextAfter, $methodAfter);
8789
$report->addClassMethod($data, Level::MAJOR);
88-
continue;
8990
}
9091

9192
if ( ! Signature::isSameVariables($paramsBefore, $paramsAfter)) {
92-
$data = new ClassMethodParameterChanged($this->fileBefore, $classBefore, $methodBefore, $this->fileAfter, $classAfter, $methodAfter);
93+
$data = new ClassMethodParameterChanged($this->context, $this->fileBefore, $contextBefore, $methodBefore, $this->fileAfter, $contextAfter, $methodAfter);
9394
$report->addClassMethod($data, Level::PATCH);
94-
continue;
9595
}
9696

9797
// Different length (considering params with defaults)
9898

9999
// Difference in source code
100100
if ($methodBefore->stmts != $methodAfter->stmts) {
101-
$data = new ClassMethodImplementationChanged($this->fileBefore, $classBefore, $methodBefore, $this->fileAfter, $classAfter, $methodAfter);
101+
$data = new ClassMethodImplementationChanged($this->context, $this->fileBefore, $contextBefore, $methodBefore, $this->fileAfter, $contextAfter, $methodAfter);
102102
$report->addClassMethod($data, Level::PATCH);
103-
continue;
104103
}
105-
106-
// Unable to match an issue, but there is one...
107-
$data = new Unknown($this->fileBefore, $this->fileAfter);
108-
$report->addClassMethod($data, Level::MAJOR);
109104
}
110105
}
111106

112107
// Added methods implies MINOR BUMP
113108
foreach ($methodsAdded as $method) {
114109
$methodAfter = $methodsAfterKeyed[$method];
115-
$data = new ClassMethodAdded($this->fileAfter, $classAfter, $methodAfter);
110+
$data = new ClassMethodAdded($this->context, $this->fileAfter, $contextAfter, $methodAfter);
116111
$report->addClassMethod($data, Level::MINOR);
117112
}
118113

src/PHPSemVerChecker/Analyzer/FunctionAnalyzer.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ public function analyze(Registry $registryBefore, Registry $registryAfter)
4646
$fileAfter = $registryAfter->mapping['function'][$key];
4747
$functionAfter = $registryAfter->data['function'][$key];
4848

49-
// TODO: Verify this comparison works properly <[email protected]>
5049
// Leave non-strict comparison here
5150
if ($functionBefore != $functionAfter) {
5251
$paramsBefore = $functionBefore->params;

src/PHPSemVerChecker/Analyzer/InterfaceAnalyzer.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,21 @@ public function analyze(Registry $registryBefore, Registry $registryAfter)
3030
$report->addInterface($data, Level::MAJOR);
3131
}
3232

33-
// TODO: Verify similar interface methods <[email protected]>
33+
foreach ($toVerify as $key) {
34+
$fileBefore = $registryBefore->mapping['interface'][$key];
35+
/** @var \PhpParser\Node\Stmt\Interface_ $interfaceBefore */
36+
$interfaceBefore = $registryBefore->data['interface'][$key];
37+
$fileAfter = $registryAfter->mapping['interface'][$key];
38+
/** @var \PhpParser\Node\Stmt\Interface_ $interfaceBefore */
39+
$interfaceAfter = $registryAfter->data['interface'][$key];
40+
41+
// Leave non-strict comparison here
42+
if ($interfaceBefore != $interfaceAfter) {
43+
$analyzer = new ClassMethodAnalyzer('interface', $fileBefore, $fileAfter);
44+
$interfaceMethodReport = $analyzer->analyze($interfaceBefore, $interfaceAfter);
45+
$report->merge($interfaceMethodReport);
46+
}
47+
}
3448

3549
foreach ($added as $key) {
3650
$fileAfter = $registryAfter->mapping['interface'][$key];

src/PHPSemVerChecker/Analyzer/TraitAnalyzer.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,21 @@ public function analyze(Registry $registryBefore, Registry $registryAfter)
3030
$report->addTrait($data, Level::MAJOR);
3131
}
3232

33-
// TODO: Verify similar traits methods <[email protected]>
33+
foreach ($toVerify as $key) {
34+
$fileBefore = $registryBefore->mapping['trait'][$key];
35+
/** @var \PhpParser\Node\Stmt\Class_ $traitBefore */
36+
$traitBefore = $registryBefore->data['trait'][$key];
37+
$fileAfter = $registryAfter->mapping['trait'][$key];
38+
/** @var \PhpParser\Node\Stmt\Class_ $traitBefore */
39+
$traitAfter = $registryAfter->data['trait'][$key];
40+
41+
// Leave non-strict comparison here
42+
if ($traitBefore != $traitAfter) {
43+
$analyzer = new ClassMethodAnalyzer('trait', $fileBefore, $fileAfter);
44+
$traitMethodReport = $analyzer->analyze($traitBefore, $traitAfter);
45+
$report->merge($traitMethodReport);
46+
}
47+
}
3448

3549
foreach ($added as $key) {
3650
$fileAfter = $registryAfter->mapping['trait'][$key];

src/PHPSemVerChecker/Operation/ClassAdded.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
use PhpParser\Node\Stmt\Class_;
66

77
class ClassAdded extends Operation {
8+
/**
9+
* @var string
10+
*/
11+
protected $code = 'V014';
812
/**
913
* @var string
1014
*/
@@ -47,4 +51,4 @@ public function getTarget()
4751
}
4852
return $fqcn;
4953
}
50-
}
54+
}

src/PHPSemVerChecker/Operation/ClassMethodAdded.php

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,22 @@
22

33
namespace PHPSemVerChecker\Operation;
44

5-
use PhpParser\Node\Stmt\Class_;
5+
use PhpParser\Node\Stmt;
66
use PhpParser\Node\Stmt\ClassMethod;
77

8-
class ClassMethodAdded extends Operation {
8+
class ClassMethodAdded extends ClassMethodOperation {
9+
/**
10+
* @var array
11+
*/
12+
protected $code = [
13+
'class' => 'V015',
14+
'interface' => 'V034',
15+
'trait' => 'V047',
16+
];
17+
/**
18+
* @var string
19+
*/
20+
protected $context;
921
/**
1022
* @var string
1123
*/
@@ -15,23 +27,25 @@ class ClassMethodAdded extends Operation {
1527
*/
1628
protected $fileAfter;
1729
/**
18-
* @var \PhpParser\Node\Stmt\Class_
30+
* @var \PhpParser\Node\Stmt
1931
*/
20-
protected $classAfter;
32+
protected $contextAfter;
2133
/**
2234
* @var \PhpParser\Node\Stmt\ClassMethod
2335
*/
2436
protected $classMethod;
2537

2638
/**
39+
* @param string $context
2740
* @param string $fileAfter
28-
* @param \PhpParser\Node\Stmt\Class_ $classAfter
41+
* @param \PhpParser\Node\Stmt $contextAfter
2942
* @param \PhpParser\Node\Stmt\ClassMethod $classMethod
3043
*/
31-
public function __construct($fileAfter, Class_ $classAfter, ClassMethod $classMethod)
44+
public function __construct($context, $fileAfter, Stmt $contextAfter, ClassMethod $classMethod)
3245
{
46+
$this->context = $context;
3347
$this->fileAfter = $fileAfter;
34-
$this->classAfter = $classAfter;
48+
$this->contextAfter = $contextAfter;
3549
$this->classMethod = $classMethod;
3650
}
3751

@@ -48,10 +62,10 @@ public function getLocation()
4862
*/
4963
public function getTarget()
5064
{
51-
$fqcn = $this->classAfter->name;
52-
if ($this->classAfter->namespacedName) {
53-
$fqcn = $this->classAfter->namespacedName->toString();
65+
$fqcn = $this->contextAfter->name;
66+
if ($this->contextAfter->namespacedName) {
67+
$fqcn = $this->contextAfter->namespacedName->toString();
5468
}
5569
return $fqcn . '::' . $this->classMethod->name;
5670
}
57-
}
71+
}

src/PHPSemVerChecker/Operation/ClassMethodImplementationChanged.php

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,21 @@
22

33
namespace PHPSemVerChecker\Operation;
44

5-
use PhpParser\Node\Stmt\Class_;
5+
use PhpParser\Node\Stmt\Stmt;
66
use PhpParser\Node\Stmt\ClassMethod;
77

8-
class ClassMethodImplementationChanged extends Operation {
8+
class ClassMethodImplementationChanged extends ClassMethodOperation {
9+
/**
10+
* @var array
11+
*/
12+
protected $code = [
13+
'class' => 'V023',
14+
'trait' => 'V038',
15+
];
16+
/**
17+
* @var string
18+
*/
19+
protected $context;
920
/**
1021
* @var string
1122
*/
@@ -15,9 +26,9 @@ class ClassMethodImplementationChanged extends Operation {
1526
*/
1627
protected $fileBefore;
1728
/**
18-
* @var \PhpParser\Node\Stmt\Class_
29+
* @var \PhpParser\Node\Stmt
1930
*/
20-
protected $classBefore;
31+
protected $contextBefore;
2132
/**
2233
* @var \PhpParser\Node\Stmt\ClassMethod
2334
*/
@@ -27,29 +38,31 @@ class ClassMethodImplementationChanged extends Operation {
2738
*/
2839
protected $fileAfter;
2940
/**
30-
* @var \PhpParser\Node\Stmt\Class_
41+
* @var \PhpParser\Node\Stmt
3142
*/
32-
protected $classAfter;
43+
protected $contextAfter;
3344
/**
3445
* @var \PhpParser\Node\Stmt\ClassMethod
3546
*/
3647
protected $classMethodAfter;
3748

3849
/**
50+
* @param string $context
3951
* @param string $fileBefore
40-
* @param \PhpParser\Node\Stmt\Class_ $classBefore
52+
* @param \PhpParser\Node\Stmt $contextBefore
4153
* @param \PhpParser\Node\Stmt\ClassMethod $classMethodBefore
4254
* @param string $fileAfter
43-
* @param \PhpParser\Node\Stmt\Class_ $classAfter
55+
* @param \PhpParser\Node\Stmt $contextAfter
4456
* @param \PhpParser\Node\Stmt\ClassMethod $classMethodAfter
4557
*/
46-
public function __construct($fileBefore, Class_ $classBefore, ClassMethod $classMethodBefore, $fileAfter, Class_ $classAfter, ClassMethod $classMethodAfter)
58+
public function __construct($context, $fileBefore, \PhpParser\Node\Stmt $contextBefore, ClassMethod $classMethodBefore, $fileAfter, \PhpParser\Node\Stmt $contextAfter, ClassMethod $classMethodAfter)
4759
{
60+
$this->context = $context;
4861
$this->fileBefore = $fileBefore;
49-
$this->classBefore = $classBefore;
62+
$this->contextBefore = $contextBefore;
5063
$this->classMethodBefore = $classMethodBefore;
5164
$this->fileAfter = $fileAfter;
52-
$this->classAfter = $classAfter;
65+
$this->contextAfter = $contextAfter;
5366
$this->classMethodAfter = $classMethodAfter;
5467
}
5568

@@ -66,10 +79,10 @@ public function getLocation()
6679
*/
6780
public function getTarget()
6881
{
69-
$fqcn = $this->classAfter->name;
70-
if ($this->classAfter->namespacedName) {
71-
$fqcn = $this->classAfter->namespacedName->toString();
82+
$fqcn = $this->contextAfter->name;
83+
if ($this->contextAfter->namespacedName) {
84+
$fqcn = $this->contextAfter->namespacedName->toString();
7285
}
7386
return $fqcn . '::' . $this->classMethodBefore->name;
7487
}
75-
}
88+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace PHPSemVerChecker\Operation;
4+
5+
class ClassMethodOperation extends Operation
6+
{
7+
public function getCode()
8+
{
9+
return $this->code[$this->context];
10+
}
11+
}

0 commit comments

Comments
 (0)