Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support parallel-lint #41

Merged
merged 10 commits into from
Dec 21, 2016
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ install:
- if [ -n "$GITHUB_OAUTH_TOKEN" ]; then composer config github-oauth.github.com ${GITHUB_OAUTH_TOKEN}; fi;
- composer install --no-interaction
# test app with symfony3 components in latest php
- if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.1" ]]; then composer update && composer require sebastian/phpcpd:dev-master; fi
- if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.1" ]]; then composer update && composer require sebastian/phpcpd:dev-master && bin/suggested-tools.sh install; fi
script:
- vendor/phpunit/phpunit/phpunit
- bin/ci.sh
Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ Tool| Description
[phpmd](https://github.com/phpmd/phpmd) | Scan PHP project for messy code |
[phpmetrics](https://github.com/Halleck45/PhpMetrics) | Static analysis tool for PHP |

##### Suggested tools

Newly added tools aren't preinstalled. You have to install relevant composer packages if
you want to use.

Tool | Supported since | Description |
---- | --------------- |----------- |
[parallel-lint](https://github.com/JakubOnderka/PHP-Parallel-Lint) | `>= 1.9` | Check syntax of PHP files |

_Tip_: use [`bin/suggested-tools.sh install`](/bin/suggested-tools.sh) for installing the tools.

## Install

### Without composer
Expand Down Expand Up @@ -124,6 +135,7 @@ phpcs | [checkstyle.xml](https://edgedesigncz.github.io/phpqa/report/checkstyle.
pdepend | [pdepend-jdepend.xml](https://edgedesigncz.github.io/phpqa/report/pdepend-jdepend.xml), [pdepend-summary.xml](https://edgedesigncz.github.io/phpqa/report/pdepend-summary.xml), [pdepend-dependencies.xml](https://edgedesigncz.github.io/phpqa/report/pdepend-dependencies.xml), [pdepend-jdepend.svg](https://edgedesigncz.github.io/phpqa/report/pdepend-jdepend.svg), [pdepend-pyramid.svg](https://edgedesigncz.github.io/phpqa/report/pdepend-pyramid.svg) | ✗ |
phpmd | [phpmd.xml](https://edgedesigncz.github.io/phpqa/report/phpmd.xml) | [✓](https://github.com/phpmd/phpmd/blob/master/src/main/php/PHPMD/Renderer/TextRenderer.php#L47) |
phpmetrics | [phpmetrics.html](https://edgedesigncz.github.io/phpqa/report/phpmetrics.html), [phpmetrics.xml](https://edgedesigncz.github.io/phpqa/report/phpmetrics.xml) | [✓](https://github.com/phpmetrics/PhpMetrics#usage) |
parallel-lint | [parallel-lint.html](https://edgedesigncz.github.io/phpqa/report/parallel-lint.html) | [✓](https://github.com/JakubOnderka/PHP-Parallel-Lint#example-output) |

## Exit code

Expand All @@ -140,7 +152,7 @@ or [Circle CI](https://circleci.com/docs/manually/#overview) build should fail w
Define number of allowed errors for each tools and watch the build:

```bash
phpqa --report --tools phpcs:0,phpmd:0,phpcpd:0,phpmetrics,phploc,pdepend
phpqa --report --tools phpcs:0,phpmd:0,phpcpd:0,parallel-lint:0,phpmetrics,phploc,pdepend
```

**File mode**
Expand Down
20 changes: 20 additions & 0 deletions app/report/cli.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<h1>Parallel Lint</h1>
<pre id="cli">{{ process.getOutput() }}{{ process.getErrorOutput() }}</pre>

<style>
html, body {
margin: 0;
padding: 0;
}
pre {
background: black;
color: white;
padding: 1em;
margin: 0;
}
</style>
<script src="https://edgedesigncz.github.io/phpqa/assets/ansi_up.js" type="text/javascript"></script>
<script type="text/javascript">
var code = document.getElementById("cli");
code.innerHTML = ansi_up.ansi_to_html(code.innerHTML);
</script>
2 changes: 2 additions & 0 deletions app/report/phpqa.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ set tabs = {
<ul class="nav navbar-nav nav-tabs" role="tablist">
{% for tool in tools %}
<li{{ loop.first ? ' class=active' : '' }}><a href="#{{ tool }}">{{ tool }}</a></li>
{% if tabs[tool] %}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
&nbsp;<span class="caret"></span>&nbsp;
Expand All @@ -102,6 +103,7 @@ set tabs = {
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
<ul class="nav navbar-nav navbar-right visible-md-block visible-lg-block">
Expand Down
2 changes: 1 addition & 1 deletion bin/ci.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh

./phpqa --verbose --report --tools phpcs:0,phpmd:0,phpcpd:0,phpmetrics,phploc,pdepend
./phpqa --verbose --report --tools phpcs:0,phpmd:0,phpcpd:0,parallel-lint:0,phpmetrics,phploc,pdepend
16 changes: 16 additions & 0 deletions bin/suggested-tools.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/sh

# Usage:
# $ bin/suggested-tools.sh install
# $ bin/suggested-tools.sh remove

mode="$1"

if [ $mode = "install" ]
then
echo "Installing suggested tools"
composer require jakub-onderka/php-parallel-lint jakub-onderka/php-console-highlighter
else
echo "Removing suggested tools"
composer remove jakub-onderka/php-parallel-lint jakub-onderka/php-console-highlighter
fi
4 changes: 4 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
"squizlabs/php_codesniffer": "*",
"phpmetrics/phpmetrics": "*"
},
"suggest": {
"jakub-onderka/php-parallel-lint": "Check PHP syntax",
"jakub-onderka/php-console-highlighter": "Colored output in parallel-lint"
},
"require-dev": {
"phpunit/phpunit": "~4.8",
"hamcrest/hamcrest-php": "*"
Expand Down
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 38 additions & 9 deletions src/CodeAnalysisTasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ trait CodeAnalysisTasks
'xml' => ['phpcpd.xml'],
'errorsXPath' => '//pmd-cpd/duplication',
),
'parallel-lint' => array(
'optionSeparator' => ' ',
'internalClass' => 'JakubOnderka\PhpParallelLint\ParallelLint',
'hasOnlyConsoleOutput' => true,
),
);
/** @var Options */
private $options;
Expand All @@ -47,7 +52,14 @@ public function tools()
{
$this->yell("phpqa v" . PHPQA_VERSION);
foreach (array_keys($this->tools) as $tool) {
$this->_exec(pathToBinary("{$tool} --version"));
if ($tool == 'parallel-lint') {
$task = $this->taskExec(pathToBinary("{$tool}"))
->printed(false)
->run();
$this->getOutput()->writeln(strtok($task->getMessage(), "\n"));
} else {
$this->_exec(pathToBinary("{$tool} --version"));
}
}
}

Expand All @@ -70,7 +82,7 @@ public function ci(
'buildDir' => 'build/',
'ignoredDirs' => 'vendor',
'ignoredFiles' => '',
'tools' => 'phploc,phpcpd,phpcs,pdepend,phpmd,phpmetrics',
'tools' => 'phploc,phpcpd,phpcs,pdepend,phpmd,phpmetrics,parallel-lint',
'output' => 'file',
'config' => '',
'report' => false,
Expand Down Expand Up @@ -126,7 +138,8 @@ private function toolToExec(RunningTool $tool)
{
$binary = pathToBinary($tool);
$process = $this->taskExec($binary);
foreach ($this->{(string) $tool}($tool) as $arg => $value) {
$method = str_replace('-', '', $tool);
foreach ($this->{$method}($tool) as $arg => $value) {
if (is_int($arg)) {
$process->arg($value);
} else {
Expand Down Expand Up @@ -237,16 +250,32 @@ private function phpmetrics(RunningTool $tool)
return $args;
}

private function parallellint()
{
return array(
$this->options->ignore->parallelLint(),
$this->options->getAnalyzedDirs(' '),
);
}

private function buildHtmlReport()
{
foreach ($this->usedTools as $tool) {
$tool->htmlReport = $this->options->rawFile("{$tool}.html");
xmlToHtml(
$tool->getXmlFiles(),
$this->config->path("report.{$tool}"),
$tool->htmlReport,
['root-directory' => $this->options->getCommonRootPath()]
);
if ($tool->hasOnlyConsoleOutput) {
twigToHtml(
'cli.html.twig',
array('process' => $tool->process),
$this->options->rawFile("{$tool}.html")
);
} else {
xmlToHtml(
$tool->getXmlFiles(),
$this->config->path("report.{$tool}"),
$tool->htmlReport,
['root-directory' => $this->options->getCommonRootPath()]
);
}
}
twigToHtml(
'phpqa.html.twig',
Expand Down
5 changes: 5 additions & 0 deletions src/IgnoredPaths.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public function bergmann()
return $this->ignore(' --exclude=', ' --exclude=', '');
}

public function parallelLint()
{
return $this->ignore(' --exclude ', ' --exclude ', '');
}

private function ignore($before, $dirSeparator, $after, $fileSeparator = null)
{
if ($fileSeparator) {
Expand Down
5 changes: 4 additions & 1 deletion src/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ public function buildRunningTools(array $tools)
'allowedErrorsCount' => $this->allowedTools[$tool],
'xml' => array_key_exists('xml', $config) ? array_map([$this, 'rawFile'], $config['xml']) : []
];
$allowed[$tool] = new RunningTool($tool, $preload + $config);
$runningTool = new RunningTool($tool, $preload + $config);
if ($runningTool->isInstalled()) {
$allowed[$tool] = $runningTool;
}
}
}
return $allowed;
Expand Down
15 changes: 13 additions & 2 deletions src/RunningTool.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
class RunningTool
{
private $tool;
private $internalClass;
private $optionSeparator;

private $xmlFiles;
private $errorsXPath;
private $allowedErrorsCount;

public $htmlReport;
public $hasOnlyConsoleOutput;
/** @var \Symfony\Component\Process\Process */
public $process;

Expand All @@ -21,13 +23,22 @@ public function __construct($tool, array $toolConfig)
'optionSeparator' => '=',
'xml' => [],
'errorsXPath' => '',
'allowedErrorsCount' => null
'allowedErrorsCount' => null,
'hasOnlyConsoleOutput' => false,
'internalClass' => null,
];
$this->tool = $tool;
$this->internalClass = $config['internalClass'];
$this->optionSeparator = $config['optionSeparator'];
$this->xmlFiles = $config['xml'];
$this->errorsXPath = $config['errorsXPath'];
$this->allowedErrorsCount = $config['allowedErrorsCount'];
$this->hasOnlyConsoleOutput = $config['hasOnlyConsoleOutput'];
}

public function isInstalled()
{
return !$this->internalClass || class_exists($this->internalClass);
}

public function buildOption($arg, $value)
Expand All @@ -46,7 +57,7 @@ public function getAllowedErrorsCount()

public function analyzeResult($hasNoOutput = false)
{
if ($hasNoOutput) {
if ($hasNoOutput || $this->hasOnlyConsoleOutput) {
return $this->evaluteErrorsCount($this->process->getExitCode() ? 1 : 0);
} elseif (!$this->errorsXPath) {
return [true, ''];
Expand Down
10 changes: 9 additions & 1 deletion tests/IgnoredPathsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,15 @@ public function provideTools()
'dirs' => ' --exclude=bin --exclude=vendor',
'files' => ' --exclude=autoload.php --exclude=RoboFile.php'
)
)
),
array(
'parallelLint',
array(
'both' => ' --exclude bin --exclude vendor --exclude autoload.php --exclude RoboFile.php',
'dirs' => ' --exclude bin --exclude vendor',
'files' => ' --exclude autoload.php --exclude RoboFile.php'
)
),
);
}
}
18 changes: 13 additions & 5 deletions tests/OptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,31 @@ private function overrideOptions(array $options = array())
return new Options(array_merge($this->defaultOptions, $options));
}

public function testShouldEscapePaths()
public function testEscapePaths()
{
assertThat($this->fileOutput->getAnalyzedDirs(','), is('"./"'));
assertThat($this->fileOutput->getAnalyzedDirs(), is(['"./"']));
assertThat($this->fileOutput->toFile('file'), is('"build//file"'));
assertThat($this->fileOutput->rawFile('file'), is('build//file'));
}

public function testShouldIgnorePdependInCliOutput()
public function testIgnorePdependInCliOutput()
{
$cliOutput = $this->overrideOptions(array('output' => 'cli'));
assertThat($this->fileOutput->buildRunningTools(array('pdepend' => [])), is(nonEmptyArray()));
assertThat($cliOutput->buildRunningTools(array('pdepend' => [])), is(emptyArray()));
}

public function testIgnoreNotInstalledTool()
{
assertThat(
$this->fileOutput->buildRunningTools(array('pdepend' => ['internalClass' => 'UnknownTool\UnknownClass'])),
is(emptyArray())
);
}

/** @dataProvider provideConfig */
public function testShouldLoadDirectoryWithCustomConfig($config, $expectedConfig)
public function testLoadDirectoryWithCustomConfig($config, $expectedConfig)
{
$options = $this->overrideOptions(array('config' => $config));
assertThat($options->configDir, is($expectedConfig));
Expand All @@ -63,7 +71,7 @@ public function provideConfig()
}

/** @dataProvider provideOutputs */
public function testShouldBuildOutput(array $opts, $isSavedToFiles, $isOutputPrinted, $hasReport)
public function testBuildOutput(array $opts, $isSavedToFiles, $isOutputPrinted, $hasReport)
{
$options = $this->overrideOptions($opts);
assertThat($options->isSavedToFiles, is($isSavedToFiles));
Expand All @@ -90,7 +98,7 @@ public function provideOutputs()
}

/** @dataProvider provideExecutionMode */
public function testShouldExecute(array $opts, $isParallel)
public function testExecute(array $opts, $isParallel)
{
$options = $this->overrideOptions($opts);
assertThat($options->isParallel, is($isParallel));
Expand Down