Skip to content

Commit

Permalink
Add new output formatter for checkstyle (#204)
Browse files Browse the repository at this point in the history
* Add new output formatter for checkstyle

* Simplify progress output check for JSON and Checkstyle outputs

* Add composer suggest for ext-dom
  • Loading branch information
M-arcus committed May 21, 2024
1 parent 847639a commit 25be729
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 2 deletions.
3 changes: 3 additions & 0 deletions build/target-repository/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
"symplify/coding-standard": "<12.1",
"phpcsstandards/php_codesniffer": "<3.8",
"friendsofphp/php-cs-fixer": "<3.46"
},
"suggest": {
"ext-dom": "Needed to support checkstyle output format in class CheckstyleOutputFormatter"
}
}
6 changes: 4 additions & 2 deletions src/Configuration/ConfigurationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Symplify\EasyCodingStandard\Configuration;

use Symfony\Component\Console\Input\InputInterface;
use Symplify\EasyCodingStandard\Console\Output\CheckstyleOutputFormatter;
use Symplify\EasyCodingStandard\Console\Output\JsonOutputFormatter;
use Symplify\EasyCodingStandard\DependencyInjection\SimpleParameterProvider;
use Symplify\EasyCodingStandard\Exception\Configuration\SourceNotFoundException;
Expand Down Expand Up @@ -64,8 +65,9 @@ private function canShowProgressBar(InputInterface $input): bool
return false;
}

$notJsonOutput = $input->getOption(Option::OUTPUT_FORMAT) !== JsonOutputFormatter::NAME;
if (! $notJsonOutput) {
$outputFormat = $input->getOption(Option::OUTPUT_FORMAT);
$formatsWithoutProgressBar = [CheckstyleOutputFormatter::NAME, JsonOutputFormatter::NAME];
if (in_array($outputFormat, $formatsWithoutProgressBar, true)) {
return false;
}

Expand Down
87 changes: 87 additions & 0 deletions src/Console/Output/CheckstyleOutputFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

namespace Symplify\EasyCodingStandard\Console\Output;

use DOMDocument;
use DOMElement;
use RuntimeException;
use Symplify\EasyCodingStandard\Console\ExitCode;
use Symplify\EasyCodingStandard\Console\Style\EasyCodingStandardStyle;
use Symplify\EasyCodingStandard\Contract\Console\Output\OutputFormatterInterface;
use Symplify\EasyCodingStandard\ValueObject\Configuration;
use Symplify\EasyCodingStandard\ValueObject\Error\ErrorAndDiffResult;

/**
* @see \Symplify\EasyCodingStandard\Tests\Console\Output\JsonOutputFormatterTest
*/
final readonly class CheckstyleOutputFormatter implements OutputFormatterInterface
{
/**
* @var string
*/
public const NAME = 'checkstyle';

public function __construct(
private EasyCodingStandardStyle $easyCodingStandardStyle,
private ExitCodeResolver $exitCodeResolver
) {
}

/**
* @return ExitCode::*
*/
public function report(ErrorAndDiffResult $errorAndDiffResult, Configuration $configuration): int
{
$checkstyleContent = $this->createCheckstyleContent($errorAndDiffResult);
$this->easyCodingStandardStyle->writeln($checkstyleContent);

return $this->exitCodeResolver->resolve($errorAndDiffResult, $configuration);
}

public function getName(): string
{
return self::NAME;
}

/**
* @api
*/
public function createCheckstyleContent(ErrorAndDiffResult $errorAndDiffResult): string
{
if (! \extension_loaded('dom')) {
throw new RuntimeException('Cannot generate report! `ext-dom` is not available!');
}

$domDocument = new DOMDocument('1.0', 'UTF-8');

/** @var DOMElement $checkstyleElement */
$checkstyleElement = $domDocument->appendChild($domDocument->createElement('checkstyle'));

foreach ($errorAndDiffResult->getFileDiffs() as $fileDiff) {
/** @var DOMElement $file */
$file = $checkstyleElement->appendChild($domDocument->createElement('file'));
$file->setAttribute('name', $fileDiff->getRelativeFilePath());

foreach ($fileDiff->getAppliedCheckers() as $appliedChecker) {
$errorElement = $this->createError($domDocument, $appliedChecker);
$file->appendChild($errorElement);
}
}

$domDocument->formatOutput = true;

return (string) $domDocument->saveXML();
}

private function createError(DOMDocument $domDocument, string $appliedChecker): DOMElement
{
$domElement = $domDocument->createElement('error');
$domElement->setAttribute('severity', 'warning');
$domElement->setAttribute('source', 'EasyCodingStandard.' . $appliedChecker);
$domElement->setAttribute('message', 'Found violation(s) of type: ' . $appliedChecker);

return $domElement;
}
}
2 changes: 2 additions & 0 deletions src/DependencyInjection/LazyContainerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Symplify\EasyCodingStandard\Caching\CacheFactory;
use Symplify\EasyCodingStandard\Caching\ChangedFilesDetector;
use Symplify\EasyCodingStandard\Config\ECSConfig;
use Symplify\EasyCodingStandard\Console\Output\CheckstyleOutputFormatter;
use Symplify\EasyCodingStandard\Console\Output\ConsoleOutputFormatter;
use Symplify\EasyCodingStandard\Console\Output\JsonOutputFormatter;
use Symplify\EasyCodingStandard\Console\Output\OutputFormatterCollector;
Expand Down Expand Up @@ -81,6 +82,7 @@ static function (Container $container): EasyCodingStandardStyle {
});

// output
$ecsConfig->singleton(CheckstyleOutputFormatter::class);
$ecsConfig->singleton(ConsoleOutputFormatter::class);
$ecsConfig->singleton(JsonOutputFormatter::class);
$ecsConfig->singleton(OutputFormatterCollector::class);
Expand Down
59 changes: 59 additions & 0 deletions tests/Console/Output/CheckstyleOutputFormatterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Symplify\EasyCodingStandard\Tests\Console\Output;

use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;
use Symplify\EasyCodingStandard\Console\Formatter\ColorConsoleDiffFormatter;
use Symplify\EasyCodingStandard\Console\Output\CheckstyleOutputFormatter;
use Symplify\EasyCodingStandard\FileSystem\StaticRelativeFilePathHelper;
use Symplify\EasyCodingStandard\Testing\PHPUnit\AbstractTestCase;
use Symplify\EasyCodingStandard\ValueObject\Error\ErrorAndDiffResult;
use Symplify\EasyCodingStandard\ValueObject\Error\FileDiff;

final class CheckstyleOutputFormatterTest extends AbstractTestCase
{
private CheckstyleOutputFormatter $checkstyleOutputFormatter;

private ColorConsoleDiffFormatter $colorConsoleDiffFormatter;

protected function setUp(): void
{
parent::setUp();

$this->checkstyleOutputFormatter = $this->make(CheckstyleOutputFormatter::class);
$this->colorConsoleDiffFormatter = $this->make(ColorConsoleDiffFormatter::class);
}

public function test(): void
{
$relativeFilePath = StaticRelativeFilePathHelper::resolveFromCwd(__DIR__ . '/Source/RandomFile.php');

$fileDiffs = [];

$diff = 'some diff';
$fileDiffs[] = new FileDiff(
$relativeFilePath,
$diff,
$this->colorConsoleDiffFormatter->format($diff),
[LineLengthFixer::class]
);

$diff = 'some other diff';
$fileDiffs[] = new FileDiff(
$relativeFilePath,
$diff,
$this->colorConsoleDiffFormatter->format($diff),
[LineLengthFixer::class]
);

$errorAndDiffResult = new ErrorAndDiffResult([], $fileDiffs, []);

$checkstyleContent = $this->checkstyleOutputFormatter->createCheckstyleContent($errorAndDiffResult);
$this->assertStringMatchesFormatFile(
__DIR__ . '/Fixture/expected_checkstyle_output.xml',
$checkstyleContent . PHP_EOL
);
}
}
9 changes: 9 additions & 0 deletions tests/Console/Output/Fixture/expected_checkstyle_output.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle>
<file name="tests/Console/Output/Source/RandomFile.php">
<error severity="warning" source="EasyCodingStandard.Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer" message="Found violation(s) of type: Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer"/>
</file>
<file name="tests/Console/Output/Source/RandomFile.php">
<error severity="warning" source="EasyCodingStandard.Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer" message="Found violation(s) of type: Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer"/>
</file>
</checkstyle>

0 comments on commit 25be729

Please sign in to comment.