Skip to content

Commit 578a141

Browse files
author
Reno Reckling
committed
add phpcs enricher
It supports reading the standard phpcs output which seems to be slightly incompatible with the checkstyle output
1 parent 47999e0 commit 578a141

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

bootstrap/enrichers.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
->implementedByClass('TheSeer\\phpDox\\Generator\\Enricher\\CheckStyle')
5151
->withConfigClass('TheSeer\\phpDox\\Generator\\Enricher\\CheckStyleConfig');
5252

53+
$phpDox->registerEnricher('phpcs', 'phpcs.xml enricher')
54+
->implementedByClass('TheSeer\\phpDox\\Generator\\Enricher\\PHPCs')
55+
->withConfigClass('TheSeer\\phpDox\\Generator\\Enricher\\PHPCsConfig');
56+
5357
$phpDox->registerEnricher('pmd', 'PHPMessDetector (pmd.xml) enricher')
5458
->implementedByClass('TheSeer\\phpDox\\Generator\\Enricher\\PHPMessDetector')
5559
->withConfigClass('TheSeer\\phpDox\\Generator\\Enricher\\PHPMessDetectorConfig');

src/autoload.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ function($class) {
129129
'theseer\\phpdox\\generator\\enricher\\gitconfig' => '/generator/enricher/git/GitConfig.php',
130130
'theseer\\phpdox\\generator\\enricher\\gitenricherexception' => '/generator/enricher/git/Git.php',
131131
'theseer\\phpdox\\generator\\enricher\\interfaceenricherinterface' => '/generator/enricher/InterfaceEnricherInterface.php',
132+
'theseer\\phpdox\\generator\\enricher\\phpcs' => '/generator/enricher/phpcs/PHPCs.php',
133+
'theseer\\phpdox\\generator\\enricher\\phpcsconfig' => '/generator/enricher/phpcs/PHPCsConfig.php',
132134
'theseer\\phpdox\\generator\\enricher\\phploc' => '/generator/enricher/phploc/PHPLoc.php',
133135
'theseer\\phpdox\\generator\\enricher\\phplocconfig' => '/generator/enricher/phploc/PHPLocConfig.php',
134136
'theseer\\phpdox\\generator\\enricher\\phpmessdetector' => '/generator/enricher/pmd/PHPMessDetector.php',
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
namespace TheSeer\phpDox\Generator\Enricher {
4+
5+
use TheSeer\fDOM\fDOMDocument;
6+
use TheSeer\fDOM\fDOMElement;
7+
use TheSeer\fDOM\fDOMException;
8+
use TheSeer\phpDox\Generator\AbstractUnitObject;
9+
use TheSeer\phpDox\Generator\ClassStartEvent;
10+
use TheSeer\phpDox\Generator\InterfaceStartEvent;
11+
use TheSeer\phpDox\Generator\TraitStartEvent;
12+
13+
class PHPCs extends AbstractEnricher implements ClassEnricherInterface, TraitEnricherInterface, InterfaceEnricherInterface {
14+
15+
private $config;
16+
private $findings = NULL;
17+
const XMLNS = 'http://xml.phpdox.net/src#';
18+
19+
public function __construct(PHPCsConfig $config) {
20+
$this->config = $config;
21+
$this->loadFindings($config->getLogFilePath());
22+
}
23+
24+
/**
25+
* @return string
26+
*/
27+
public function getName() {
28+
return 'PHPCS XML';
29+
}
30+
31+
public function enrichClass(ClassStartEvent $event) {
32+
$this->enrichUnit($event->getClass());
33+
}
34+
35+
public function enrichInterface(InterfaceStartEvent $event) {
36+
$this->enrichUnit($event->getInterface());
37+
}
38+
39+
public function enrichTrait(TraitStartEvent $event) {
40+
$this->enrichUnit($event->getTrait());
41+
}
42+
43+
private function enrichUnit(AbstractUnitObject $ctx) {
44+
$file = $ctx->getSourceFile();
45+
if (isset($this->findings[$file])) {
46+
$this->processFindings($ctx->asDom(), $this->findings[$file]);
47+
}
48+
}
49+
50+
private function loadFindings($xmlFile) {
51+
$this->findings = array();
52+
try {
53+
if (!file_exists($xmlFile)) {
54+
throw new EnricherException(
55+
sprintf('Logfile "%s" not found.', $xmlFile),
56+
EnricherException::LoadError
57+
);
58+
}
59+
$dom = new fDOMDocument();
60+
$dom->load($xmlFile);
61+
foreach($dom->query('/phpcs/file') as $file) {
62+
$this->findings[$file->getAttribute('name')] = $file->query('*');
63+
}
64+
} catch (fDOMException $e) {
65+
throw new EnricherException(
66+
'Parsing phpcs logfile failed: ' . $e->getMessage(),
67+
EnricherException::LoadError
68+
);
69+
}
70+
}
71+
72+
private function processFindings(fDOMDocument $dom, \DOMNodeList $findings) {
73+
74+
foreach($findings as $finding) {
75+
/** @var fDOMElement $finding */
76+
$line = $finding->getAttribute('line');
77+
$ref = $dom->queryOne(sprintf('//phpdox:*/*[@line = %d or (@start <= %d and @end >= %d)]', $line, $line, $line));
78+
if (!$ref) {
79+
// One src file may contain multiple classes/traits/interfaces, so the
80+
// finding might not apply to the current object since findings are based on filenames
81+
// but we have individual objects - so we just ignore the finding for this context
82+
continue;
83+
}
84+
85+
$enrichment = $this->getEnrichtmentContainer($ref, 'checkstyle');
86+
$enrichFinding = $dom->createElementNS(self::XMLNS, $finding->tagName);
87+
$enrichment->appendChild($enrichFinding);
88+
foreach($finding->attributes as $attr) {
89+
if ($attr->localName == 'severity') {
90+
continue;
91+
}
92+
$enrichFinding->setAttributeNode($dom->importNode($attr, true));
93+
}
94+
$enrichFinding->setAttribute('message', $finding->nodeValue);
95+
}
96+
97+
}
98+
}
99+
100+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace TheSeer\phpDox\Generator\Enricher {
4+
5+
use TheSeer\fDOM\fDOMElement;
6+
use TheSeer\phpDox\GeneratorConfig;
7+
8+
class PHPCsConfig {
9+
10+
/**
11+
* @var GeneratorConfig
12+
*/
13+
private $generator;
14+
15+
/**
16+
* @var fDOMElement
17+
*/
18+
private $context;
19+
20+
public function __construct(GeneratorConfig $generator, fDOMElement $ctx) {
21+
$this->context = $ctx;
22+
$this->generator = $generator;
23+
}
24+
25+
public function getLogFilePath() {
26+
$basedirDefault = dirname($this->context->ownerDocument->baseURI);
27+
$path = $basedirDefault . '/build/logs';
28+
if ($this->context->parentNode->hasAttribute('base')) {
29+
$path = $this->context->parentNode->getAttribute('base');
30+
}
31+
if ($path != '') { $path .= '/'; }
32+
$file = $this->context->queryOne('cfg:file');
33+
if ($file && $file->hasAttribute('name')) {
34+
$path .= $file->getAttribute('name');
35+
} else {
36+
$path .= 'phpcs.xml';
37+
}
38+
return $path;
39+
}
40+
}
41+
42+
}

0 commit comments

Comments
 (0)