diff --git a/composer-require-checker.json b/composer-require-checker.json index 3e87a142..7878977e 100644 --- a/composer-require-checker.json +++ b/composer-require-checker.json @@ -8,7 +8,6 @@ "Symfony\\Bridge\\Twig\\TokenParser\\TransTokenParser", "Symfony\\UX\\TwigComponent\\Twig\\ComponentTokenParser", "Symfony\\UX\\TwigComponent\\Twig\\PropsTokenParser", - "Twig\\Extra\\Cache\\TokenParser\\CacheTokenParser", - "\\SimpleXMLElement" + "Twig\\Extra\\Cache\\TokenParser\\CacheTokenParser" ] } diff --git a/src/Report/Reporter/CheckstyleReporter.php b/src/Report/Reporter/CheckstyleReporter.php index 880b8dd8..f37f1219 100644 --- a/src/Report/Reporter/CheckstyleReporter.php +++ b/src/Report/Reporter/CheckstyleReporter.php @@ -8,35 +8,52 @@ use TwigCsFixer\Report\Report; use TwigCsFixer\Report\SniffViolation; -/** - * Human-readable output with context. - */ final class CheckstyleReporter implements ReporterInterface { public const NAME = 'checkstyle'; public function display(OutputInterface $output, Report $report, ?string $level = null): void { - $checkstyle = new \SimpleXMLElement(''); + $text = ''."\n"; + + $text .= ''."\n"; foreach ($report->getFiles() as $file) { $fileMessages = $report->getMessages($file, $level); - if (\count($fileMessages) > 0) { - /** @var \SimpleXMLElement $fileNode */ - $fileNode = $checkstyle->addChild('file'); - $fileNode->addAttribute('name', $file); - - foreach ($fileMessages as $message) { - /** @var \SimpleXMLElement $violation */ - $violation = $fileNode->addChild('violation'); - $violation->addAttribute('column', (string) $message->getLinePosition()); - $violation->addAttribute('severity', strtolower(SniffViolation::getLevelAsString($message->getLevel()))); - $violation->addAttribute('message', $message->getMessage()); - $violation->addAttribute('source', $message->getSniffName() ?? ''); + if (0 === \count($fileMessages)) { + continue; + } + + $text .= ' '."\n"; + foreach ($fileMessages as $message) { + $line = (string) $message->getLine(); + $linePosition = (string) $message->getLinePosition(); + $sniffName = $message->getSniffName(); + + $text .= ' getLevel())).'"'; + $text .= ' message="'.$this->xmlEncode($message->getMessage()).'"'; + if (null !== $sniffName) { + $text .= ' source="'.$sniffName.'"'; + } + $text .= '/>'."\n"; } + $text .= ' '."\n"; } - $output->writeln((string) $checkstyle->asXML()); + $text .= ''."\n"; + + $output->writeln($text); + } + + private function xmlEncode(string $data): string + { + return htmlspecialchars($data, \ENT_XML1 | \ENT_QUOTES); } } diff --git a/tests/Command/TwigCsFixerCommandTest.php b/tests/Command/TwigCsFixerCommandTest.php index 02c3981b..e8945577 100644 --- a/tests/Command/TwigCsFixerCommandTest.php +++ b/tests/Command/TwigCsFixerCommandTest.php @@ -116,7 +116,7 @@ public function testExecuteWithReportOption(): void $commandTester = new CommandTester($command); $commandTester->execute([ - 'paths' => [$this->getTmpPath(__DIR__.'/Fixtures/file.twig')], + 'paths' => [$this->getTmpPath(__DIR__.'/Fixtures')], '--no-cache' => true, // To avoid cache output '--report' => 'null', ]); diff --git a/tests/Report/Formatter/CheckstyleReporterTest.php b/tests/Report/Formatter/CheckstyleReporterTest.php new file mode 100644 index 00000000..1198030a --- /dev/null +++ b/tests/Report/Formatter/CheckstyleReporterTest.php @@ -0,0 +1,82 @@ +addMessage($violation0); + $violation1 = new SniffViolation(SniffViolation::LEVEL_WARNING, 'Warning', $file, 2, 22, 'WarningSniff'); + $report->addMessage($violation1); + $violation2 = new SniffViolation(SniffViolation::LEVEL_ERROR, 'Error', $file, 3, 33, 'ErrorSniff'); + $report->addMessage($violation2); + $violation3 = new SniffViolation(SniffViolation::LEVEL_FATAL, 'Fatal', $file); + $report->addMessage($violation3); + + $output = new BufferedOutput(OutputInterface::VERBOSITY_NORMAL, true); + $textFormatter->display($output, $report, $level); + + $text = $output->fetch(); + static::assertStringContainsString($expected, $text); + } + + /** + * @return iterable + */ + public static function displayDataProvider(): iterable + { + yield [ + sprintf( + << + + + + + + + + + EOD, + __DIR__ + ), + null, + ]; + + yield [ + sprintf( + << + + + + + + + EOD, + __DIR__ + ), + Report::MESSAGE_TYPE_ERROR, + ]; + } +} diff --git a/tests/Report/ReporterFactoryTest.php b/tests/Report/ReporterFactoryTest.php index d01c0bef..289e5dba 100644 --- a/tests/Report/ReporterFactoryTest.php +++ b/tests/Report/ReporterFactoryTest.php @@ -5,6 +5,7 @@ namespace TwigCsFixer\Tests\Report; use PHPUnit\Framework\TestCase; +use TwigCsFixer\Report\Reporter\CheckstyleReporter; use TwigCsFixer\Report\Reporter\NullReporter; use TwigCsFixer\Report\Reporter\TextReporter; use TwigCsFixer\Report\ReporterFactory; @@ -18,6 +19,7 @@ public function testGetReporter(): void static::assertInstanceOf(TextReporter::class, $reporterFactory->getReporter()); static::assertInstanceOf(TextReporter::class, $reporterFactory->getReporter(TextReporter::NAME)); static::assertInstanceOf(NullReporter::class, $reporterFactory->getReporter(NullReporter::NAME)); + static::assertInstanceOf(CheckstyleReporter::class, $reporterFactory->getReporter(CheckstyleReporter::NAME)); } public function testGetMessageForAnotherFile(): void