diff --git a/.travis.yml b/.travis.yml
index cab5494a..6b88f2be 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -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
diff --git a/README.md b/README.md
index cdc51866..41b016f8 100644
--- a/README.md
+++ b/README.md
@@ -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
@@ -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
@@ -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**
diff --git a/app/report/cli.html.twig b/app/report/cli.html.twig
new file mode 100644
index 00000000..fdb77726
--- /dev/null
+++ b/app/report/cli.html.twig
@@ -0,0 +1,20 @@
+
Parallel Lint
+{{ process.getOutput() }}{{ process.getErrorOutput() }}
+
+
+
+
diff --git a/app/report/phpqa.html.twig b/app/report/phpqa.html.twig
index be37a204..ae8ded6b 100644
--- a/app/report/phpqa.html.twig
+++ b/app/report/phpqa.html.twig
@@ -88,6 +88,7 @@ set tabs = {
+ {% endif %}
{% endfor %}
diff --git a/bin/ci.sh b/bin/ci.sh
index 37618f91..fc9ca746 100755
--- a/bin/ci.sh
+++ b/bin/ci.sh
@@ -1,3 +1,3 @@
#!/bin/sh
-./phpqa --verbose --report --tools phpcs:0,phpmd:0,phpcpd:0,phpmetrics,phploc,pdepend
\ No newline at end of file
+./phpqa --verbose --report --tools phpcs:0,phpmd:0,phpcpd:0,parallel-lint:0,phpmetrics,phploc,pdepend
\ No newline at end of file
diff --git a/bin/suggested-tools.sh b/bin/suggested-tools.sh
new file mode 100755
index 00000000..ebe40766
--- /dev/null
+++ b/bin/suggested-tools.sh
@@ -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
diff --git a/composer.json b/composer.json
index 68b5987b..a2626f9b 100644
--- a/composer.json
+++ b/composer.json
@@ -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": "*"
diff --git a/composer.lock b/composer.lock
index 29352af2..69c49690 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "fcdfbbf4e73c12595d00a20f45c7a2a5",
+ "hash": "c2405fc1a7b65013c04b3a3ed3d42cb6",
"content-hash": "5065a6c361aa0f9b50fc43a84c495097",
"packages": [
{
diff --git a/src/CodeAnalysisTasks.php b/src/CodeAnalysisTasks.php
index 14f47ec1..ba36e7c2 100644
--- a/src/CodeAnalysisTasks.php
+++ b/src/CodeAnalysisTasks.php
@@ -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;
@@ -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"));
+ }
}
}
@@ -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,
@@ -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 {
@@ -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',
diff --git a/src/IgnoredPaths.php b/src/IgnoredPaths.php
index b1bb3e21..6a5fd196 100644
--- a/src/IgnoredPaths.php
+++ b/src/IgnoredPaths.php
@@ -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) {
diff --git a/src/Options.php b/src/Options.php
index f8f486c6..b2fd857a 100644
--- a/src/Options.php
+++ b/src/Options.php
@@ -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;
diff --git a/src/RunningTool.php b/src/RunningTool.php
index 0cd17a0a..db8fe61e 100644
--- a/src/RunningTool.php
+++ b/src/RunningTool.php
@@ -5,6 +5,7 @@
class RunningTool
{
private $tool;
+ private $internalClass;
private $optionSeparator;
private $xmlFiles;
@@ -12,6 +13,7 @@ class RunningTool
private $allowedErrorsCount;
public $htmlReport;
+ public $hasOnlyConsoleOutput;
/** @var \Symfony\Component\Process\Process */
public $process;
@@ -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)
@@ -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, ''];
diff --git a/tests/IgnoredPathsTest.php b/tests/IgnoredPathsTest.php
index fb7265de..c891283d 100644
--- a/tests/IgnoredPathsTest.php
+++ b/tests/IgnoredPathsTest.php
@@ -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'
+ )
+ ),
);
}
}
diff --git a/tests/OptionsTest.php b/tests/OptionsTest.php
index 97b2a0a7..ec96e7c7 100644
--- a/tests/OptionsTest.php
+++ b/tests/OptionsTest.php
@@ -32,7 +32,7 @@ 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(['"./"']));
@@ -40,15 +40,23 @@ public function testShouldEscapePaths()
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));
@@ -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));
@@ -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));