Merge branch 'feature-technical-debt-fix'
This commit is contained in:
commit
0b71d79cd8
|
@ -63,7 +63,7 @@ Plugins
|
||||||
* [PHP Unit](plugins/php_unit.md) - `php_unit`
|
* [PHP Unit](plugins/php_unit.md) - `php_unit`
|
||||||
* [Shell](plugins/shell.md) - `shell`
|
* [Shell](plugins/shell.md) - `shell`
|
||||||
* [Slack](plugins/slack_notify.md) - `slack_notify`
|
* [Slack](plugins/slack_notify.md) - `slack_notify`
|
||||||
* [Technical Debt](plugins/technical_dept.md) - `technical_debt`
|
* [Technical Debt](plugins/technical_debt.md) - `technical_debt`
|
||||||
* [Security Checker](plugins/security_checker.md) - SensioLabs Security Checker Plugin (`security_checker`).
|
* [Security Checker](plugins/security_checker.md) - SensioLabs Security Checker Plugin (`security_checker`).
|
||||||
* [XMPP](plugins/xmpp.md) - `xmpp`
|
* [XMPP](plugins/xmpp.md) - `xmpp`
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Plugin Technical Dept
|
Plugin Technical Debt
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Checks all files in your project for TODOs and other technical debt.
|
Checks all files in your project for TODOs and other technical debt.
|
|
@ -30,12 +30,6 @@ class TechnicalDebt extends Plugin implements ZeroConfigPluginInterface
|
||||||
*/
|
*/
|
||||||
protected $allowed_errors;
|
protected $allowed_errors;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string, based on the assumption the root may not hold the code to be
|
|
||||||
* tested, extends the base path
|
|
||||||
*/
|
|
||||||
protected $path;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array - paths to ignore
|
* @var array - paths to ignore
|
||||||
*/
|
*/
|
||||||
|
@ -47,13 +41,78 @@ class TechnicalDebt extends Plugin implements ZeroConfigPluginInterface
|
||||||
protected $searches;
|
protected $searches;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @var array - lines of . and X to visualize errors
|
||||||
*/
|
*/
|
||||||
|
protected $errorPerFile = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $currentLineSize = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $lineNumber = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $numberOfAnalysedFile = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public static function pluginName()
|
public static function pluginName()
|
||||||
{
|
{
|
||||||
return 'technical_debt';
|
return 'technical_debt';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the status of the file :
|
||||||
|
* . : checked no errors
|
||||||
|
* X : checked with one or more errors
|
||||||
|
*
|
||||||
|
* @param string $char
|
||||||
|
*/
|
||||||
|
protected function buildLogString($char)
|
||||||
|
{
|
||||||
|
if (isset($this->errorPerFile[$this->lineNumber])) {
|
||||||
|
$this->errorPerFile[$this->lineNumber] .= $char;
|
||||||
|
} else {
|
||||||
|
$this->errorPerFile[$this->lineNumber] = $char;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->currentLineSize++;
|
||||||
|
$this->numberOfAnalysedFile++;
|
||||||
|
|
||||||
|
if ($this->currentLineSize > 59) {
|
||||||
|
$this->currentLineSize = 0;
|
||||||
|
$this->lineNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a visual representation of file with Todo
|
||||||
|
* ...XX... 10/300 (10 %)
|
||||||
|
*
|
||||||
|
* @return string The visual representation
|
||||||
|
*/
|
||||||
|
protected function returnResult()
|
||||||
|
{
|
||||||
|
$string = '';
|
||||||
|
$fileNumber = 0;
|
||||||
|
foreach ($this->errorPerFile as $oneLine) {
|
||||||
|
$fileNumber += strlen($oneLine);
|
||||||
|
$string .= str_pad($oneLine, 60, ' ', STR_PAD_RIGHT);
|
||||||
|
$string .= str_pad($fileNumber, 4, ' ', STR_PAD_LEFT);
|
||||||
|
$string .= "/" . $this->numberOfAnalysedFile . " (" . floor($fileNumber * 100 / $this->numberOfAnalysedFile) . " %)\n";
|
||||||
|
}
|
||||||
|
$string .= "Checked {$fileNumber} files\n";
|
||||||
|
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -63,12 +122,15 @@ class TechnicalDebt extends Plugin implements ZeroConfigPluginInterface
|
||||||
|
|
||||||
$this->suffixes = ['php'];
|
$this->suffixes = ['php'];
|
||||||
$this->directory = $this->builder->buildPath;
|
$this->directory = $this->builder->buildPath;
|
||||||
$this->path = '';
|
|
||||||
$this->ignore = $this->builder->ignore;
|
$this->ignore = $this->builder->ignore;
|
||||||
$this->allowed_errors = 0;
|
$this->allowed_errors = 0;
|
||||||
$this->searches = ['TODO', 'FIXME', 'TO DO', 'FIX ME'];
|
$this->searches = ['TODO', 'FIXME', 'TO DO', 'FIX ME'];
|
||||||
|
|
||||||
if (isset($options['searches']) && is_array($options['searches'])) {
|
if (!empty($options['suffixes']) && is_array($options['suffixes'])) {
|
||||||
|
$this->suffixes = $options['suffixes'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($options['searches']) && is_array($options['searches'])) {
|
||||||
$this->searches = $options['searches'];
|
$this->searches = $options['searches'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,11 +143,12 @@ class TechnicalDebt extends Plugin implements ZeroConfigPluginInterface
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle this plugin's options.
|
* Handle this plugin's options.
|
||||||
|
*
|
||||||
* @param $options
|
* @param $options
|
||||||
*/
|
*/
|
||||||
protected function setOptions($options)
|
protected function setOptions($options)
|
||||||
{
|
{
|
||||||
foreach (array('directory', 'path', 'ignore', 'allowed_errors') as $key) {
|
foreach (['directory', 'ignore', 'allowed_errors'] as $key) {
|
||||||
if (array_key_exists($key, $options)) {
|
if (array_key_exists($key, $options)) {
|
||||||
$this->{$key} = $options[$key];
|
$this->{$key} = $options[$key];
|
||||||
}
|
}
|
||||||
|
@ -95,10 +158,11 @@ class TechnicalDebt extends Plugin implements ZeroConfigPluginInterface
|
||||||
/**
|
/**
|
||||||
* Check if this plugin can be executed.
|
* Check if this plugin can be executed.
|
||||||
*
|
*
|
||||||
* @param $stage
|
* @param string $stage
|
||||||
* @param Builder $builder
|
* @param Builder $builder
|
||||||
* @param Build $build
|
* @param Build $build
|
||||||
* @return bool
|
*
|
||||||
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function canExecute($stage, Builder $builder, Build $build)
|
public static function canExecute($stage, Builder $builder, Build $build)
|
||||||
{
|
{
|
||||||
|
@ -114,16 +178,14 @@ class TechnicalDebt extends Plugin implements ZeroConfigPluginInterface
|
||||||
*/
|
*/
|
||||||
public function execute()
|
public function execute()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$this->builder->logExecOutput(false);
|
|
||||||
|
|
||||||
$errorCount = $this->getErrorList();
|
$errorCount = $this->getErrorList();
|
||||||
|
|
||||||
$this->builder->log("Found $errorCount instances of " . implode(', ', $this->searches));
|
$this->builder->log($this->returnResult() . "Found $errorCount instances of " . implode(', ', $this->searches));
|
||||||
|
|
||||||
$this->build->storeMeta('technical_debt-warnings', $errorCount);
|
$this->build->storeMeta('technical_debt-warnings', $errorCount);
|
||||||
|
|
||||||
if ($this->allowed_errors != -1 && $errorCount > $this->allowed_errors) {
|
if ($this->allowed_errors !== -1 && $errorCount > $this->allowed_errors) {
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,65 +195,75 @@ class TechnicalDebt extends Plugin implements ZeroConfigPluginInterface
|
||||||
/**
|
/**
|
||||||
* Gets the number and list of errors returned from the search
|
* Gets the number and list of errors returned from the search
|
||||||
*
|
*
|
||||||
* @return array
|
* @return integer
|
||||||
*/
|
*/
|
||||||
public function getErrorList()
|
protected function getErrorList()
|
||||||
{
|
{
|
||||||
$dirIterator = new \RecursiveDirectoryIterator($this->directory);
|
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory));
|
||||||
$iterator = new \RecursiveIteratorIterator($dirIterator, \RecursiveIteratorIterator::SELF_FIRST);
|
|
||||||
$files = [];
|
|
||||||
|
|
||||||
$ignores = $this->ignore;
|
$this->builder->logDebug("Ignored path: ".json_encode($this->ignore, true));
|
||||||
$ignores[] = '.php-censor.yml';
|
$errorCount = 0;
|
||||||
$ignores[] = 'phpci.yml';
|
|
||||||
$ignores[] = '.phpci.yml';
|
|
||||||
|
|
||||||
|
/** @var \SplFileInfo $file */
|
||||||
foreach ($iterator as $file) {
|
foreach ($iterator as $file) {
|
||||||
$filePath = $file->getRealPath();
|
$filePath = $file->getRealPath();
|
||||||
$skipFile = false;
|
$extension = $file->getExtension();
|
||||||
foreach ($ignores as $ignore) {
|
|
||||||
if (stripos($filePath, $ignore) !== false) {
|
$ignored = false;
|
||||||
$skipFile = true;
|
foreach ($this->suffixes as $suffix) {
|
||||||
|
if ($suffix !== $extension) {
|
||||||
|
$ignored = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore hidden files, else .git, .sass_cache, etc. all get looped over
|
foreach ($this->ignore as $ignore) {
|
||||||
if (stripos($filePath, DIRECTORY_SEPARATOR . '.') !== false) {
|
if ('/' === $ignore{0}) {
|
||||||
$skipFile = true;
|
if (0 === strpos($filePath, $ignore)) {
|
||||||
|
$ignored = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$ignoreReal = $this->directory . $ignore;
|
||||||
|
if (0 === strpos($filePath, $ignoreReal)) {
|
||||||
|
$ignored = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($skipFile === false) {
|
if (!$ignored) {
|
||||||
$files[] = $file->getRealPath();
|
$handle = fopen($filePath, "r");
|
||||||
}
|
$lineNumber = 1;
|
||||||
}
|
$errorInFile = false;
|
||||||
|
while (false === feof($handle)) {
|
||||||
|
$line = fgets($handle);
|
||||||
|
|
||||||
$files = array_filter(array_unique($files));
|
foreach ($this->searches as $search) {
|
||||||
$errorCount = 0;
|
if ($technicalDeptLine = trim(strstr($line, $search))) {
|
||||||
|
$fileName = str_replace($this->directory, '', $filePath);
|
||||||
|
|
||||||
foreach ($files as $file) {
|
$this->build->reportError(
|
||||||
foreach ($this->searches as $search) {
|
$this->builder,
|
||||||
$fileContent = file_get_contents($file);
|
'technical_debt',
|
||||||
$allLines = explode(PHP_EOL, $fileContent);
|
$technicalDeptLine,
|
||||||
$beforeString = strstr($fileContent, $search, true);
|
PHPCensor\Model\BuildError::SEVERITY_LOW,
|
||||||
|
$fileName,
|
||||||
|
$lineNumber
|
||||||
|
);
|
||||||
|
|
||||||
if (false !== $beforeString) {
|
$errorInFile = true;
|
||||||
$lines = explode(PHP_EOL, $beforeString);
|
$errorCount++;
|
||||||
$lineNumber = count($lines);
|
}
|
||||||
$content = trim($allLines[$lineNumber - 1]);
|
}
|
||||||
|
$lineNumber++;
|
||||||
|
}
|
||||||
|
fclose ($handle);
|
||||||
|
|
||||||
$errorCount++;
|
if ($errorInFile === true) {
|
||||||
|
$this->buildLogString('X');
|
||||||
$fileName = str_replace($this->directory, '', $file);
|
} else {
|
||||||
|
$this->buildLogString('.');
|
||||||
$this->build->reportError(
|
|
||||||
$this->builder,
|
|
||||||
'technical_debt',
|
|
||||||
$content,
|
|
||||||
PHPCensor\Model\BuildError::SEVERITY_LOW,
|
|
||||||
$fileName,
|
|
||||||
$lineNumber
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue