Skip to content

Commit 25be729

Browse files
authored
Add new output formatter for checkstyle (#204)
* Add new output formatter for checkstyle * Simplify progress output check for JSON and Checkstyle outputs * Add composer suggest for ext-dom
1 parent 847639a commit 25be729

6 files changed

Lines changed: 164 additions & 2 deletions

File tree

build/target-repository/composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@
1818
"symplify/coding-standard": "<12.1",
1919
"phpcsstandards/php_codesniffer": "<3.8",
2020
"friendsofphp/php-cs-fixer": "<3.46"
21+
},
22+
"suggest": {
23+
"ext-dom": "Needed to support checkstyle output format in class CheckstyleOutputFormatter"
2124
}
2225
}

src/Configuration/ConfigurationFactory.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Symplify\EasyCodingStandard\Configuration;
66

77
use Symfony\Component\Console\Input\InputInterface;
8+
use Symplify\EasyCodingStandard\Console\Output\CheckstyleOutputFormatter;
89
use Symplify\EasyCodingStandard\Console\Output\JsonOutputFormatter;
910
use Symplify\EasyCodingStandard\DependencyInjection\SimpleParameterProvider;
1011
use Symplify\EasyCodingStandard\Exception\Configuration\SourceNotFoundException;
@@ -64,8 +65,9 @@ private function canShowProgressBar(InputInterface $input): bool
6465
return false;
6566
}
6667

67-
$notJsonOutput = $input->getOption(Option::OUTPUT_FORMAT) !== JsonOutputFormatter::NAME;
68-
if (! $notJsonOutput) {
68+
$outputFormat = $input->getOption(Option::OUTPUT_FORMAT);
69+
$formatsWithoutProgressBar = [CheckstyleOutputFormatter::NAME, JsonOutputFormatter::NAME];
70+
if (in_array($outputFormat, $formatsWithoutProgressBar, true)) {
6971
return false;
7072
}
7173

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symplify\EasyCodingStandard\Console\Output;
6+
7+
use DOMDocument;
8+
use DOMElement;
9+
use RuntimeException;
10+
use Symplify\EasyCodingStandard\Console\ExitCode;
11+
use Symplify\EasyCodingStandard\Console\Style\EasyCodingStandardStyle;
12+
use Symplify\EasyCodingStandard\Contract\Console\Output\OutputFormatterInterface;
13+
use Symplify\EasyCodingStandard\ValueObject\Configuration;
14+
use Symplify\EasyCodingStandard\ValueObject\Error\ErrorAndDiffResult;
15+
16+
/**
17+
* @see \Symplify\EasyCodingStandard\Tests\Console\Output\JsonOutputFormatterTest
18+
*/
19+
final readonly class CheckstyleOutputFormatter implements OutputFormatterInterface
20+
{
21+
/**
22+
* @var string
23+
*/
24+
public const NAME = 'checkstyle';
25+
26+
public function __construct(
27+
private EasyCodingStandardStyle $easyCodingStandardStyle,
28+
private ExitCodeResolver $exitCodeResolver
29+
) {
30+
}
31+
32+
/**
33+
* @return ExitCode::*
34+
*/
35+
public function report(ErrorAndDiffResult $errorAndDiffResult, Configuration $configuration): int
36+
{
37+
$checkstyleContent = $this->createCheckstyleContent($errorAndDiffResult);
38+
$this->easyCodingStandardStyle->writeln($checkstyleContent);
39+
40+
return $this->exitCodeResolver->resolve($errorAndDiffResult, $configuration);
41+
}
42+
43+
public function getName(): string
44+
{
45+
return self::NAME;
46+
}
47+
48+
/**
49+
* @api
50+
*/
51+
public function createCheckstyleContent(ErrorAndDiffResult $errorAndDiffResult): string
52+
{
53+
if (! \extension_loaded('dom')) {
54+
throw new RuntimeException('Cannot generate report! `ext-dom` is not available!');
55+
}
56+
57+
$domDocument = new DOMDocument('1.0', 'UTF-8');
58+
59+
/** @var DOMElement $checkstyleElement */
60+
$checkstyleElement = $domDocument->appendChild($domDocument->createElement('checkstyle'));
61+
62+
foreach ($errorAndDiffResult->getFileDiffs() as $fileDiff) {
63+
/** @var DOMElement $file */
64+
$file = $checkstyleElement->appendChild($domDocument->createElement('file'));
65+
$file->setAttribute('name', $fileDiff->getRelativeFilePath());
66+
67+
foreach ($fileDiff->getAppliedCheckers() as $appliedChecker) {
68+
$errorElement = $this->createError($domDocument, $appliedChecker);
69+
$file->appendChild($errorElement);
70+
}
71+
}
72+
73+
$domDocument->formatOutput = true;
74+
75+
return (string) $domDocument->saveXML();
76+
}
77+
78+
private function createError(DOMDocument $domDocument, string $appliedChecker): DOMElement
79+
{
80+
$domElement = $domDocument->createElement('error');
81+
$domElement->setAttribute('severity', 'warning');
82+
$domElement->setAttribute('source', 'EasyCodingStandard.' . $appliedChecker);
83+
$domElement->setAttribute('message', 'Found violation(s) of type: ' . $appliedChecker);
84+
85+
return $domElement;
86+
}
87+
}

src/DependencyInjection/LazyContainerFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symplify\EasyCodingStandard\Caching\CacheFactory;
1919
use Symplify\EasyCodingStandard\Caching\ChangedFilesDetector;
2020
use Symplify\EasyCodingStandard\Config\ECSConfig;
21+
use Symplify\EasyCodingStandard\Console\Output\CheckstyleOutputFormatter;
2122
use Symplify\EasyCodingStandard\Console\Output\ConsoleOutputFormatter;
2223
use Symplify\EasyCodingStandard\Console\Output\JsonOutputFormatter;
2324
use Symplify\EasyCodingStandard\Console\Output\OutputFormatterCollector;
@@ -81,6 +82,7 @@ static function (Container $container): EasyCodingStandardStyle {
8182
});
8283

8384
// output
85+
$ecsConfig->singleton(CheckstyleOutputFormatter::class);
8486
$ecsConfig->singleton(ConsoleOutputFormatter::class);
8587
$ecsConfig->singleton(JsonOutputFormatter::class);
8688
$ecsConfig->singleton(OutputFormatterCollector::class);
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symplify\EasyCodingStandard\Tests\Console\Output;
6+
7+
use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;
8+
use Symplify\EasyCodingStandard\Console\Formatter\ColorConsoleDiffFormatter;
9+
use Symplify\EasyCodingStandard\Console\Output\CheckstyleOutputFormatter;
10+
use Symplify\EasyCodingStandard\FileSystem\StaticRelativeFilePathHelper;
11+
use Symplify\EasyCodingStandard\Testing\PHPUnit\AbstractTestCase;
12+
use Symplify\EasyCodingStandard\ValueObject\Error\ErrorAndDiffResult;
13+
use Symplify\EasyCodingStandard\ValueObject\Error\FileDiff;
14+
15+
final class CheckstyleOutputFormatterTest extends AbstractTestCase
16+
{
17+
private CheckstyleOutputFormatter $checkstyleOutputFormatter;
18+
19+
private ColorConsoleDiffFormatter $colorConsoleDiffFormatter;
20+
21+
protected function setUp(): void
22+
{
23+
parent::setUp();
24+
25+
$this->checkstyleOutputFormatter = $this->make(CheckstyleOutputFormatter::class);
26+
$this->colorConsoleDiffFormatter = $this->make(ColorConsoleDiffFormatter::class);
27+
}
28+
29+
public function test(): void
30+
{
31+
$relativeFilePath = StaticRelativeFilePathHelper::resolveFromCwd(__DIR__ . '/Source/RandomFile.php');
32+
33+
$fileDiffs = [];
34+
35+
$diff = 'some diff';
36+
$fileDiffs[] = new FileDiff(
37+
$relativeFilePath,
38+
$diff,
39+
$this->colorConsoleDiffFormatter->format($diff),
40+
[LineLengthFixer::class]
41+
);
42+
43+
$diff = 'some other diff';
44+
$fileDiffs[] = new FileDiff(
45+
$relativeFilePath,
46+
$diff,
47+
$this->colorConsoleDiffFormatter->format($diff),
48+
[LineLengthFixer::class]
49+
);
50+
51+
$errorAndDiffResult = new ErrorAndDiffResult([], $fileDiffs, []);
52+
53+
$checkstyleContent = $this->checkstyleOutputFormatter->createCheckstyleContent($errorAndDiffResult);
54+
$this->assertStringMatchesFormatFile(
55+
__DIR__ . '/Fixture/expected_checkstyle_output.xml',
56+
$checkstyleContent . PHP_EOL
57+
);
58+
}
59+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<checkstyle>
3+
<file name="tests/Console/Output/Source/RandomFile.php">
4+
<error severity="warning" source="EasyCodingStandard.Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer" message="Found violation(s) of type: Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer"/>
5+
</file>
6+
<file name="tests/Console/Output/Source/RandomFile.php">
7+
<error severity="warning" source="EasyCodingStandard.Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer" message="Found violation(s) of type: Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer"/>
8+
</file>
9+
</checkstyle>

0 commit comments

Comments
 (0)