Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .phpqa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ php-cs-fixer:
phpmd:
# alternatively you can use an array to define multiple rule sets (https://phpmd.org/documentation/index.html#using-multiple-rule-sets)
standard: app/phpmd.xml
ignoreParsingErrors: true

pdepend:
# coverageReport: build/coverage-clover.xml
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ Tool | Settings | Default Value | Your value
[phpmetrics.composer](https://github.com/EdgedesignCZ/phpqa/pull/123) | phpmetrics v2 analyzes composer dependencies | `null` | Path to composer.json when the file is not included in `analyzedDirs`
[pdepend.coverageReport](https://github.com/EdgedesignCZ/phpqa/pull/124) | Load Clover style CodeCoverage report | `null` | Path to report produced by PHPUnit's `--coverage-clover` option
[phpmd.standard](http://phpmd.org/documentation/creating-a-ruleset.html) | Ruleset | [Edgedesign's standard](/app/phpmd.xml) | Path to ruleset. To specify [multiple rule sets](https://phpmd.org/documentation/index.html#using-multiple-rule-sets), you can use an array
[phpcs.ignoreParsingErrors](https://github.com/EdgedesignCZ/phpqa/issues/230) | If parsing errors affect exit code, or just violations | `true` | Boolean value
[phpcpd](https://github.com/sebastianbergmann/phpcpd/blob/de9056615da6c1230f3294384055fa7d722c38fa/src/CLI/Command.php#L136) | Minimum number of lines/tokens for copy-paste detection | 5 lines, 70 tokens |
[phpstan](https://github.com/phpstan/phpstan#configuration) | Level, config file, memory limit | Level 0, `%currentWorkingDirectory%/phpstan.neon`, memoryLimit: null | Take a look at [phpqa config in tests/.ci](/tests/.ci/) |
[phpunit.binary](https://github.com/EdgedesignCZ/phpqa/blob/4947416/.phpqa.yml#L40) | Phpunit binary | phpqa's phpunit | Path to phpunit executable in your project, typically [`vendor/bin/phpunit`](https://gitlab.com/costlocker/integrations/blob/master/basecamp/backend/.phpqa.yml#L2) |
Expand Down
12 changes: 10 additions & 2 deletions app/report/phpmd.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
.priority-3 {background: #f0ad4e;}
.priority-4 {background: #5bc0de;}
.priority-5 {background: #5bc0de;}
.alert {
margin: 1em 0;
}
</style>
<script>
var onDocumentReady = [
Expand Down Expand Up @@ -60,6 +63,12 @@
<div class="tab-content">

<div role="tabpanel" class="tab-pane active" id="overview">
<xsl:if test="count(/pmd/error) > 0">
<div class="alert alert-danger">
<strong>Errors are not analyzed in <xsl:value-of select="count(/pmd/error)" /> file(s)!</strong>
PHPMD cannot parse the file(s). Check <a href="#parsing" data-toggle="tab">Parsing Errors</a>
</div>
</xsl:if>
<table class="table table-striped">
<thead>
<tr>
Expand All @@ -75,7 +84,6 @@
<td><xsl:value-of select="$group"/></td>
<td><xsl:value-of select="count(key('error-category', $group))" /></td>
<td><xsl:value-of select="count(key('file-category', $group))" /></td>
<td></td>
</tr>
</xsl:for-each>
<tfoot>
Expand Down Expand Up @@ -201,7 +209,7 @@
<xsl:for-each select="/pmd/error">
<tr>
<td><strong data-file=""><xsl:value-of select="@filename" /></strong></td>
<td><xsl:value-of select="@msg" /></td>
<td><span data-file=""><xsl:value-of select="@msg" /></span></td>
</tr>
</xsl:for-each>
</table>
Expand Down
11 changes: 5 additions & 6 deletions src/RunningTool.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,23 @@ public function getAllowedErrorsCount()

public function analyzeResult($hasNoOutput = false)
{
$xpath = $this->errorsXPath[$this->errorsType];
$xpaths = $this->errorsXPath[$this->errorsType];

if ($hasNoOutput ||
$this->hasOutput(OutputMode::RAW_CONSOLE_OUTPUT) ||
$this->hasOutput(OutputMode::CUSTOM_OUTPUT_AND_EXIT_CODE)
) {
return $this->evaluteErrorsCount($this->process->getExitCode() ? 1 : 0);
} elseif (!$xpath) {
} elseif (!$xpaths) {
return [true, ''];
} elseif (!file_exists($this->getMainXml())) {
return [$this->areErrorsIgnored(), "XML [{$this->getMainXml()}] not found"];
}

list($isInvalidXml, $xpathOrError) = xmlXpath($this->getMainXml(), $xpath);
if ($isInvalidXml) {
return [$this->areErrorsIgnored(), $xpathOrError];
list($errorsCount, $xmlError) = xmlXpaths($this->getMainXml(), (array) $xpaths);
if ($xmlError) {
return [$this->areErrorsIgnored(), $xmlError];
}
$errorsCount = count($xpathOrError);
return $this->evaluteErrorsCount($errorsCount);
}

Expand Down
7 changes: 6 additions & 1 deletion src/Tools/Analyzer/Phpmd.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ class Phpmd extends \Edge\QA\Tools\Tool
public static $SETTINGS = array(
'optionSeparator' => ' ',
'xml' => ['phpmd.xml'],
'errorsXPath' => '//pmd/file/violation',
'errorsXPath' => [
# ignoreParsingErrors => xpath
true => '//pmd/file/violation',
false => ['//pmd/file/violation', '//pmd/error'],
],
'composer' => 'phpmd/phpmd',
);

public function __invoke()
{
$this->tool->errorsType = $this->config->value('phpmd.ignoreParsingErrors') === true;
$rulesets = $this->config->pathsOrValues('phpmd.standard');

$args = array(
Expand Down
10 changes: 7 additions & 3 deletions src/report.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,18 @@ function xmlToHtml(array $xmlDocuments, $style, $outputFile, array $params = [])
}
}

function xmlXpath($xmlFile, $xpathQuery)
function xmlXpaths($xmlFile, array $xpathQueries)
{
convertPhpErrorsToExceptions();
$matchedElements = 0;
try {
$xml = simplexml_load_file($xmlFile);
return [false, $xml->xpath($xpathQuery)];
foreach ($xpathQueries as $xpathQuery) {
$matchedElements += count($xml->xpath($xpathQuery));
}
return [$matchedElements, ''];
} catch (Exception $e) {
return [true, $e->getMessage()];
return [0, $e->getMessage()];
}
}

Expand Down
3 changes: 3 additions & 0 deletions tests/.ci/.phpqa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ phpqa:
- parallel-lint:0
- deptrac

phpmd:
ignoreParsingErrors: false

phpcs:
standard:
- PSR2
Expand Down
1 change: 1 addition & 0 deletions tests/Config/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function testLoadDefaultConfig()
assertThat($config->path('php-cs-fixer.config'), is(nullValue()));
assertThat($config->path('phpmetrics.config'), is(nullValue()));
assertThat($config->path('phpmd.standard'), is(nonEmptyString()));
assertThat($config->value('phpmd.ignoreParsingErrors'), is(true));
assertThat($config->value('phpstan.level'), identicalTo(0));
assertThat($config->value('phpstan.memoryLimit'), is(nullValue()));
assertThat($config->value('phpunit.config'), is(nullValue()));
Expand Down
1 change: 1 addition & 0 deletions tests/Error/errors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
<errors version="2.6.0">
<error severity="error">first</error>
<error severity="warning">second</error>
<warning>third</warning>
</errors>

22 changes: 22 additions & 0 deletions tests/RunningToolTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Edge\QA;

/** @SuppressWarnings(PHPMD.TooManyPublicMethods) */
class RunningToolTest extends \PHPUnit_Framework_TestCase
{
private $errorsCountInXmlFile = 2;
Expand Down Expand Up @@ -75,6 +76,27 @@ public function testRuntimeSelectionOfErrorXpath()
assertThat($tool->analyzeResult(), is([false, 1]));
}

/** @dataProvider provideMultipleXpaths */
public function testMultipleXpaths(array $xpaths, array $expectedResult)
{
$tool = new RunningTool('tool', [
'xml' => ['tests/Error/errors.xml'],
'errorsXPath' => [
null => $xpaths,
],
'allowedErrorsCount' => 3,
]);
assertThat($tool->analyzeResult(), is($expectedResult));
}

public function provideMultipleXpaths()
{
return [
'multiple elements' => [['//errors/error', '//errors/warning'], [true, 2 + 1]],
'invalid xpath' => [[null], [false, 'SimpleXMLElement::xpath(): Invalid expression']],
];
}

/** @dataProvider provideProcess */
public function testAnalyzeExitCodeInCliMode($allowedErrors, $exitCode, array $expectedResult)
{
Expand Down