Skip to content

Commit 2e19e12

Browse files
COMOPS-908: Updating compatibility with the BIC doc generator (#25)
1 parent 9d82c98 commit 2e19e12

File tree

9 files changed

+219
-37
lines changed

9 files changed

+219
-37
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "magento/magento-semver",
33
"description": "Magento semantic version checker",
4-
"version": "2.0.0",
4+
"version": "3.0.0",
55
"license": [
66
"OSL-3.0",
77
"AFL-3.0"

src/Analyzer/AbstractCodeAnalyzer.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,17 @@ protected function getFileName($context, $nodeName, $isBefore = true)
237237
{
238238
return $isBefore ? $this->fileBefore : $this->fileAfter;
239239
}
240+
241+
/**
242+
* Gets the AbstractCodeAnalyzers for content analysis (ex: method analyzer for classes)
243+
*
244+
* @param string $context
245+
* @param string $fileBefore
246+
* @param string $fileAfter
247+
* @return AbstractCodeAnalyzer[]
248+
*/
249+
protected function getContentAnalyzers($context, $fileBefore, $fileAfter)
250+
{
251+
return [];
252+
}
240253
}

src/Analyzer/ClassAnalyzer.php

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,7 @@ protected function reportChanged($report, $registryBefore, $registryAfter, $toVe
108108
$classAfter = $afterNameMap[$key];
109109

110110
if ($classBefore !== $classAfter) {
111-
/**
112-
* @var AnalyzerInterface[] $analyzers
113-
*/
114-
$analyzers = [
115-
new ClassMethodAnalyzer(static::CONTEXT, $fileBefore, $fileAfter, $this->dependencyGraph),
116-
new PropertyAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
117-
new ClassConstantAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
118-
new ClassMethodExceptionAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
119-
new ClassImplementsAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
120-
new ClassExtendsAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
121-
new ClassTraitAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
122-
];
111+
$analyzers = $this->getContentAnalyzers(static::CONTEXT, $fileBefore, $fileAfter);
123112

124113
foreach ($analyzers as $analyzer) {
125114
$internalReport = $analyzer->analyze($classBefore, $classAfter);
@@ -129,6 +118,27 @@ protected function reportChanged($report, $registryBefore, $registryAfter, $toVe
129118
}
130119
}
131120

121+
/**
122+
* Get the list of content analyzers
123+
*
124+
* @param string $context
125+
* @param string $fileBefore
126+
* @param string $fileAfter
127+
* @return AbstractCodeAnalyzer[]
128+
*/
129+
protected function getContentAnalyzers($context, $fileBefore, $fileAfter)
130+
{
131+
return [
132+
new ClassMethodAnalyzer($context, $fileBefore, $fileAfter, $this->dependencyGraph),
133+
new PropertyAnalyzer($context, $fileBefore, $fileAfter),
134+
new ClassConstantAnalyzer($context, $fileBefore, $fileAfter),
135+
new ClassMethodExceptionAnalyzer($context, $fileBefore, $fileAfter),
136+
new ClassImplementsAnalyzer($context, $fileBefore, $fileAfter),
137+
new ClassExtendsAnalyzer($context, $fileBefore, $fileAfter),
138+
new ClassTraitAnalyzer($context, $fileBefore, $fileAfter),
139+
];
140+
}
141+
132142
/**
133143
* Get the class node registry
134144
*

src/Analyzer/InterfaceAnalyzer.php

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,7 @@ protected function reportChanged($report, $registryBefore, $registryAfter, $toVe
118118
$interfaceAfter = $afterNameMap[$key];
119119

120120
if ($interfaceBefore !== $interfaceAfter) {
121-
/** @var AnalyzerInterface[] $analyzers */
122-
$analyzers = [
123-
new ClassMethodAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
124-
new ClassConstantAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
125-
new ClassMethodExceptionAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
126-
new InterfaceExtendsAnalyzer(static::CONTEXT, $fileBefore, $fileAfter)
127-
];
121+
$analyzers = $this->getContentAnalyzers(static::CONTEXT, $fileBefore, $fileAfter);
128122

129123
foreach ($analyzers as $analyzer) {
130124
$internalReport = $analyzer->analyze($interfaceBefore, $interfaceAfter);
@@ -133,4 +127,22 @@ protected function reportChanged($report, $registryBefore, $registryAfter, $toVe
133127
}
134128
}
135129
}
130+
131+
/**
132+
* Get the list of content analyzers
133+
*
134+
* @param string $context
135+
* @param string $fileBefore
136+
* @param string $fileAfter
137+
* @return AbstractCodeAnalyzer[]
138+
*/
139+
protected function getContentAnalyzers($context, $fileBefore, $fileAfter)
140+
{
141+
return [
142+
new ClassMethodAnalyzer($context, $fileBefore, $fileAfter),
143+
new ClassConstantAnalyzer($context, $fileBefore, $fileAfter),
144+
new ClassMethodExceptionAnalyzer($context, $fileBefore, $fileAfter),
145+
new InterfaceExtendsAnalyzer($context, $fileBefore, $fileAfter)
146+
];
147+
}
136148
}

src/Analyzer/TraitAnalyzer.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,7 @@ protected function reportChanged($report, $registryBefore, $registryAfter, $toVe
115115
if ($traitBefore !== $traitAfter) {
116116
$fileBefore = $this->getFileName($registryBefore, $traitName);
117117
$fileAfter = $this->getFileName($registryAfter, $traitName);
118-
119-
/** @var AbstractCodeAnalyzer[] $analyzers */
120-
$analyzers = [
121-
new ClassMethodAnalyzer(static::CONTEXT, $fileBefore, $fileAfter),
122-
];
118+
$analyzers = $this->getContentAnalyzers(static::CONTEXT, $fileBefore, $fileAfter);
123119

124120
foreach ($analyzers as $analyzer) {
125121
$internalReport = $analyzer->analyze($traitBefore, $traitAfter);
@@ -128,4 +124,17 @@ protected function reportChanged($report, $registryBefore, $registryAfter, $toVe
128124
}
129125
}
130126
}
127+
128+
/**
129+
* Get the list of content analyzers
130+
*
131+
* @param string $context
132+
* @param string $fileBefore
133+
* @param string $fileAfter
134+
* @return AbstractCodeAnalyzer[]
135+
*/
136+
protected function getContentAnalyzers($context, $fileBefore, $fileAfter)
137+
{
138+
return [new ClassMethodAnalyzer($context, $fileBefore, $fileAfter)];
139+
}
131140
}

src/MergedReport.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\SemanticVersionChecker;
9+
10+
use PHPSemVerChecker\Report\Report;
11+
12+
class MergedReport extends Report
13+
{
14+
/**
15+
* Merges with the given report including any non-standard contexts
16+
*
17+
* @param Report $report
18+
* @return $this
19+
*/
20+
public function merge(Report $report)
21+
{
22+
foreach ($report->differences as $context => $levels) {
23+
if (!key_exists($context, $this->differences)) {
24+
$this->differences[$context] = $levels;
25+
} else {
26+
foreach ($levels as $level => $differences) {
27+
$this->differences[$context][$level] = array_merge(
28+
$this->differences[$context][$level],
29+
$differences
30+
);
31+
}
32+
}
33+
}
34+
35+
return $this;
36+
}
37+
}

src/ReportBuilder.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ class ReportBuilder
4444

4545
/**
4646
* Define analyzer factory list for the different report types.
47-
* @var array
47+
* @var string[]
4848
*/
49-
private $analyzerList = [
49+
private $analyzerFactoryClasses = [
5050
ReportTypes::API => AnalyzerFactory::class,
5151
ReportTypes::ALL => NonApiAnalyzerFactory::class,
5252
ReportTypes::DB_SCHEMA => DbSchemaAnalyzerFactory::class,
@@ -118,6 +118,16 @@ protected function makeVersionReport()
118118
return $report;
119119
}
120120

121+
/**
122+
* Get the mapping of report type -> analyzer factory
123+
*
124+
* @return string[]
125+
*/
126+
protected function getAnalyzerFactoryClasses()
127+
{
128+
return $this->analyzerFactoryClasses;
129+
}
130+
121131
/**
122132
* Create a report based on type
123133
*
@@ -161,7 +171,7 @@ protected function buildReport()
161171
/**
162172
* @var AnalyzerFactoryInterface $factory
163173
*/
164-
foreach ($this->analyzerList as $reportType => $factory) {
174+
foreach ($this->getAnalyzerFactoryClasses() as $reportType => $factory) {
165175
/** @var AnalyzerInterface $analyzer */
166176
$analyzer = (new $factory())->create($dependencyMap);
167177
$tmpReport = $analyzer->analyze(

src/Reporter/BreakingChangeTableReporter.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,15 @@ public function __construct($apiChangeReport, $apiMembershipReport, $targetFile)
5151
*/
5252
public function output(OutputInterface $output)
5353
{
54-
$contexts = [
55-
'class',
56-
'function',
57-
'interface',
58-
'trait',
59-
'database',
60-
];
54+
$reportContexts = array_keys($this->report->getDifferences());
55+
$membershipContexts = array_keys($this->membershipReport->getDifferences());
6156

62-
foreach ($contexts as $context) {
57+
foreach ($reportContexts as $context) {
6358
$header = static::formatSectionHeader($this->targetFile, $context, 'breaking-change');
6459
$this->outputChangeReport($output, $this->report, $context, $header);
6560
}
6661

67-
foreach ($contexts as $context) {
62+
foreach ($membershipContexts as $context) {
6863
$header = static::formatSectionHeader($this->targetFile, $context, 'api-membership');
6964
$this->outputChangeReport($output, $this->membershipReport, $context, $header);
7065
}

tests/Unit/MergedReportTest.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\SemanticVersionChecker\Test\Unit;
9+
10+
use Magento\SemanticVersionChecker\InjectableReport;
11+
use Magento\SemanticVersionChecker\MergedReport;
12+
use Magento\SemanticVersionChecker\Operation\ClassConstantRemoved;
13+
use Magento\SemanticVersionChecker\Operation\ClassConstructorOptionalParameterAdded;
14+
use Magento\SemanticVersionChecker\Operation\ClassExtendsAdded;
15+
use Magento\SemanticVersionChecker\Operation\ClassImplementsAdded;
16+
use Magento\SemanticVersionChecker\Operation\ClassMethodOptionalParameterAdded;
17+
use Magento\SemanticVersionChecker\Operation\ClassTraitAdded;
18+
use Magento\SemanticVersionChecker\Operation\DropForeignKey;
19+
use Magento\SemanticVersionChecker\Operation\SystemXml\FieldAdded;
20+
use PHPSemVerChecker\Report\Report;
21+
use PHPSemVerChecker\SemanticVersioning\Level;
22+
use PHPUnit\Framework\MockObject\MockObject;
23+
use PHPUnit\Framework\TestCase;
24+
25+
class MergedReportTest extends TestCase
26+
{
27+
/**
28+
* Verify that reports are properly merged including non-standard contexts
29+
*
30+
* @return void
31+
*/
32+
public function testMergedChanges()
33+
{
34+
$diffsWithDatabase = [];
35+
$diffsWithDatabase['class'][Level::PATCH] = [$this->createMock(ClassConstructorOptionalParameterAdded::class)];
36+
$diffsWithDatabase['class'][Level::MINOR] = [
37+
$this->createMock(ClassExtendsAdded::class),
38+
$this->createMock(ClassMethodOptionalParameterAdded::class)
39+
];
40+
$diffsWithDatabase['database'][Level::MAJOR] = [$this->createMock(DropForeignKey::class)];
41+
$databaseReport = new InjectableReport($diffsWithDatabase);
42+
43+
$diffsWithXml = [];
44+
$diffsWithXml['class'][Level::MAJOR] = [$this->createMock(ClassConstantRemoved::class)];
45+
$diffsWithXml['class'][Level::MINOR] = [$this->createMock(ClassImplementsAdded::class)];
46+
$diffsWithXml['xml'][Level::MINOR] = [$this->createMock(FieldAdded::class)];
47+
$xmlReport = new InjectableReport($diffsWithXml);
48+
49+
/** @var MockObject|ClassTraitAdded $preMergeOperation */
50+
$preMergeOperation = $this->createMock(ClassTraitAdded::class);
51+
$preMergeOperation->expects($this->any())->method('getLevel')->willReturn(Level::MINOR);
52+
53+
$mergedReport = new MergedReport();
54+
$mergedReport->addClass($preMergeOperation);
55+
$mergedReport->merge($databaseReport);
56+
$mergedReport->merge($xmlReport);
57+
58+
$mergedDiffs = $mergedReport->getDifferences();
59+
$this->assertTrue(key_exists('database', $mergedDiffs));
60+
$this->assertTrue(key_exists('xml', $mergedDiffs));
61+
$this->assertTrue($this->hasAllDifferences($mergedReport, $databaseReport));
62+
$this->assertTrue($this->hasAllDifferences($mergedReport, $xmlReport));
63+
$this->assertTrue(array_search($preMergeOperation, $mergedDiffs['class'][Level::MINOR]) !== false);
64+
}
65+
66+
/**
67+
* Checks if a merged report contains all differences in another report
68+
69+
* @param Report $mergedReport
70+
* @param Report $inputReport
71+
* @return bool
72+
*/
73+
private function hasAllDifferences($mergedReport, $inputReport)
74+
{
75+
$mergedDiffs = $mergedReport->getDifferences();
76+
$inputDiffs = $inputReport->getDifferences();
77+
foreach ($inputDiffs as $context => $levels) {
78+
if (!key_exists($context, $mergedDiffs)) {
79+
return false;
80+
}
81+
$mergedLevels = $mergedDiffs[$context];
82+
foreach ($levels as $level => $operations) {
83+
if (!key_exists($level, $mergedLevels)) {
84+
return false;
85+
}
86+
$mergedOperations = $mergedLevels[$level];
87+
foreach ($operations as $operation) {
88+
if (array_search($operation, $mergedOperations) === false) {
89+
return false;
90+
}
91+
}
92+
}
93+
}
94+
return true;
95+
}
96+
}

0 commit comments

Comments
 (0)