Skip to content

Commit 42af3cd

Browse files
authored
Merge pull request #829 from Nyholm/json-formatter
Add support for JsonFormatter
2 parents d0ba4f1 + 7e92f54 commit 42af3cd

File tree

6 files changed

+332
-2
lines changed

6 files changed

+332
-2
lines changed

Resources/errors.schema.json

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://github.com/Roave/BackwardCompatibilityCheck/tree/8.10.x/Resources/errors.schema.json",
4+
"title": "Backward Compatibility Errors",
5+
"description": "A list of errors",
6+
"required": [
7+
"errors"
8+
],
9+
"additionalProperties": false,
10+
"properties": {
11+
"errors": {
12+
"type": "array",
13+
"items": {
14+
"$ref": "#/definitions/Error"
15+
}
16+
}
17+
},
18+
"definitions": {
19+
"Error": {
20+
"type": "object",
21+
"additionalProperties": false,
22+
"properties": {
23+
"description": {
24+
"type": "string"
25+
},
26+
"path": {
27+
"anyOf": [
28+
{
29+
"type": "null"
30+
},
31+
{
32+
"type": "string"
33+
}
34+
]
35+
},
36+
"line": {
37+
"anyOf": [
38+
{
39+
"type": "integer"
40+
},
41+
{
42+
"type": "null"
43+
}
44+
]
45+
},
46+
"column": {
47+
"anyOf": [
48+
{
49+
"type": "integer"
50+
},
51+
{
52+
"type": "null"
53+
}
54+
]
55+
}
56+
},
57+
"required": [
58+
"column",
59+
"description",
60+
"line",
61+
"path"
62+
],
63+
"title": "Error"
64+
}
65+
}
66+
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
],
2525
"require-dev": {
2626
"doctrine/coding-standard": "^12.0.0",
27+
"estahn/phpunit-json-assertions": "^4.0",
2728
"php-standard-library/psalm-plugin": "^2.3.0",
2829
"phpunit/phpunit": "^9.6.19",
2930
"psalm/plugin-phpunit": "^0.19.0",

composer.lock

Lines changed: 128 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Command/AssertBackwardsCompatible.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Roave\BackwardCompatibility\CompareApi;
1414
use Roave\BackwardCompatibility\Factory\ComposerInstallationReflectorFactory;
1515
use Roave\BackwardCompatibility\Formatter\GithubActionsFormatter;
16+
use Roave\BackwardCompatibility\Formatter\JsonFormatter;
1617
use Roave\BackwardCompatibility\Formatter\JunitFormatter;
1718
use Roave\BackwardCompatibility\Formatter\MarkdownPipedToSymfonyConsoleFormatter;
1819
use Roave\BackwardCompatibility\Formatter\SymfonyConsoleTextFormatter;
@@ -154,6 +155,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
154155
'console' => new SymfonyConsoleTextFormatter($stdErr),
155156
'markdown' => new MarkdownPipedToSymfonyConsoleFormatter($output),
156157
'github-actions' => new GithubActionsFormatter($output, $toPath),
158+
'json' => new JsonFormatter($output, $toPath),
157159
'junit' => new JunitFormatter($output, $toPath),
158160
];
159161

@@ -162,6 +164,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
162164
Type\literal_scalar('console'),
163165
Type\literal_scalar('markdown'),
164166
Type\literal_scalar('github-actions'),
167+
Type\literal_scalar('json'),
165168
Type\literal_scalar('junit'),
166169
))->coerce((array) $input->getOption('format')) as $format
167170
) {

src/Formatter/JsonFormatter.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Roave\BackwardCompatibility\Formatter;
6+
7+
use Psl\Str;
8+
use Roave\BackwardCompatibility\Changes;
9+
use Roave\BackwardCompatibility\Git\CheckedOutRepository;
10+
use Symfony\Component\Console\Output\OutputInterface;
11+
12+
use function json_encode;
13+
14+
/** @internal */
15+
final class JsonFormatter implements OutputFormatter
16+
{
17+
public function __construct(
18+
private readonly OutputInterface $output,
19+
private CheckedOutRepository $basePath,
20+
) {
21+
}
22+
23+
public function write(Changes $changes): void
24+
{
25+
$basePath = $this->basePath->__toString() . '/';
26+
$result = [];
27+
28+
foreach ($changes as $change) {
29+
$result[] = [
30+
'description' => $change->description,
31+
'path' => $change->file === null ? null : Str\replace($change->file, $basePath, ''),
32+
'line' => $change->line,
33+
'column' => $change->column,
34+
];
35+
}
36+
37+
$this->output->writeln(json_encode(['errors' => $result]));
38+
}
39+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RoaveTest\BackwardCompatibility\Formatter;
6+
7+
use EnricoStahn\JsonAssert\AssertClass as JsonAssert;
8+
use PHPUnit\Framework\TestCase;
9+
use Psl\Env;
10+
use Psl\Filesystem;
11+
use ReflectionException;
12+
use Roave\BackwardCompatibility\Change;
13+
use Roave\BackwardCompatibility\Changes;
14+
use Roave\BackwardCompatibility\Formatter\JsonFormatter;
15+
use Roave\BackwardCompatibility\Git\CheckedOutRepository;
16+
use stdClass;
17+
use Symfony\Component\Console\Output\BufferedOutput;
18+
19+
use function dirname;
20+
use function json_decode;
21+
22+
use const JSON_THROW_ON_ERROR;
23+
24+
/** @covers \Roave\BackwardCompatibility\Formatter\JsonFormatter */
25+
final class JsonFormatterTest extends TestCase
26+
{
27+
/** @throws ReflectionException */
28+
public function testWrite(): void
29+
{
30+
$output = new BufferedOutput();
31+
$temporaryLocation = Filesystem\create_temporary_file(Env\temp_dir(), 'jsonFormatter');
32+
33+
Filesystem\delete_file($temporaryLocation);
34+
Filesystem\create_directory($temporaryLocation . '/foo/bar/.git');
35+
36+
(new JsonFormatter(
37+
$output,
38+
CheckedOutRepository::fromPath($temporaryLocation . '/foo/bar'),
39+
))->write(Changes::fromList(
40+
Change::removed('foo', true),
41+
Change::added('bar', false),
42+
Change::changed('baz', false)
43+
->onFile('baz-file.php'),
44+
Change::changed('tab', false)
45+
->onFile('tab-file.php')
46+
->onLine(5),
47+
Change::changed('taz', false)
48+
->onFile('taz-file.php')
49+
->onLine(6)
50+
->onColumn(15),
51+
Change::changed('tar', false)
52+
->onFile('tar-file.php')
53+
->onLine(-1)
54+
->onColumn(-1),
55+
Change::changed('file-in-checked-out-dir', false)
56+
->onFile($temporaryLocation . '/foo/bar/subpath/file-in-checked-out-dir.php')
57+
->onLine(10)
58+
->onColumn(20),
59+
));
60+
61+
Filesystem\delete_directory($temporaryLocation, true);
62+
63+
$expected = [
64+
'errors' => [
65+
['description' => 'foo', 'path' => null, 'line' => null, 'column' => null],
66+
['description' => 'bar', 'path' => null, 'line' => null, 'column' => null],
67+
['description' => 'baz', 'path' => 'baz-file.php', 'line' => null, 'column' => null],
68+
['description' => 'tab', 'path' => 'tab-file.php', 'line' => 5, 'column' => null],
69+
['description' => 'taz', 'path' => 'taz-file.php', 'line' => 6, 'column' => 15],
70+
['description' => 'tar', 'path' => 'tar-file.php', 'line' => -1, 'column' => -1],
71+
['description' => 'file-in-checked-out-dir', 'path' => 'subpath/file-in-checked-out-dir.php', 'line' => 10, 'column' => 20],
72+
],
73+
];
74+
75+
$json = $output->fetch();
76+
self::assertJson($json);
77+
78+
$data = json_decode($json, true);
79+
self::assertIsArray($data);
80+
self::assertEquals($expected, $data);
81+
82+
$content = json_decode($json, flags: JSON_THROW_ON_ERROR);
83+
self::assertInstanceOf(stdClass::class, $content);
84+
JsonAssert::assertJsonMatchesSchema($content, dirname(__DIR__, 3) . '/Resources/errors.schema.json');
85+
86+
self::assertJsonStringEqualsJsonString(
87+
<<<'OUTPUT'
88+
{"errors":[{"description":"foo","path":null,"line":null,"column":null},{"description":"bar","path":null,"line":null,"column":null},{"description":"baz","path":"baz-file.php","line":null,"column":null},{"description":"tab","path":"tab-file.php","line":5,"column":null},{"description":"taz","path":"taz-file.php","line":6,"column":15},{"description":"tar","path":"tar-file.php","line":-1,"column":-1},{"description":"file-in-checked-out-dir","path":"subpath\/file-in-checked-out-dir.php","line":10,"column":20}]}
89+
90+
OUTPUT
91+
,
92+
$json,
93+
);
94+
}
95+
}

0 commit comments

Comments
 (0)