mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 00:07:26 +00:00
589 lines
14 KiB
PHP
589 lines
14 KiB
PHP
<?php
|
|
namespace JakubOnderka\PhpParallelLint;
|
|
|
|
interface Output
|
|
{
|
|
public function __construct(IWriter $writer);
|
|
|
|
public function ok();
|
|
|
|
public function skip();
|
|
|
|
public function error();
|
|
|
|
public function fail();
|
|
|
|
public function setTotalFileCount($count);
|
|
|
|
public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null);
|
|
|
|
public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails);
|
|
}
|
|
|
|
class JsonOutput implements Output
|
|
{
|
|
/** @var IWriter */
|
|
protected $writer;
|
|
|
|
/** @var int */
|
|
protected $phpVersion;
|
|
|
|
/** @var int */
|
|
protected $parallelJobs;
|
|
|
|
/** @var string */
|
|
protected $hhvmVersion;
|
|
|
|
/**
|
|
* @param IWriter $writer
|
|
*/
|
|
public function __construct(IWriter $writer)
|
|
{
|
|
$this->writer = $writer;
|
|
}
|
|
|
|
public function ok()
|
|
{
|
|
|
|
}
|
|
|
|
public function skip()
|
|
{
|
|
|
|
}
|
|
|
|
public function error()
|
|
{
|
|
|
|
}
|
|
|
|
public function fail()
|
|
{
|
|
|
|
}
|
|
|
|
public function setTotalFileCount($count)
|
|
{
|
|
|
|
}
|
|
|
|
public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null)
|
|
{
|
|
$this->phpVersion = $phpVersion;
|
|
$this->parallelJobs = $parallelJobs;
|
|
$this->hhvmVersion = $hhvmVersion;
|
|
}
|
|
|
|
public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
|
|
{
|
|
echo json_encode(array(
|
|
'phpVersion' => $this->phpVersion,
|
|
'hhvmVersion' => $this->hhvmVersion,
|
|
'parallelJobs' => $this->parallelJobs,
|
|
'results' => $result,
|
|
));
|
|
}
|
|
}
|
|
|
|
class GitLabOutput implements Output
|
|
{
|
|
/** @var IWriter */
|
|
protected $writer;
|
|
|
|
/**
|
|
* @param IWriter $writer
|
|
*/
|
|
public function __construct(IWriter $writer)
|
|
{
|
|
$this->writer = $writer;
|
|
}
|
|
|
|
public function ok()
|
|
{
|
|
|
|
}
|
|
|
|
public function skip()
|
|
{
|
|
|
|
}
|
|
|
|
public function error()
|
|
{
|
|
|
|
}
|
|
|
|
public function fail()
|
|
{
|
|
|
|
}
|
|
|
|
public function setTotalFileCount($count)
|
|
{
|
|
|
|
}
|
|
|
|
public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null)
|
|
{
|
|
|
|
}
|
|
|
|
public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
|
|
{
|
|
$errors = array();
|
|
foreach ($result->getErrors() as $error) {
|
|
$message = $error->getMessage();
|
|
$line = 1;
|
|
if ($error instanceof SyntaxError) {
|
|
$line = $error->getLine();
|
|
}
|
|
$filePath = $error->getFilePath();
|
|
$result = array(
|
|
'type' => 'issue',
|
|
'check_name' => 'Parse error',
|
|
'description' => $message,
|
|
'categories' => 'Style',
|
|
'fingerprint' => md5($filePath . $message . $line),
|
|
'severity' => 'minor',
|
|
'location' => array(
|
|
'path' => $filePath,
|
|
'lines' => array(
|
|
'begin' => $line,
|
|
),
|
|
),
|
|
);
|
|
array_push($errors, $result);
|
|
}
|
|
|
|
$string = json_encode($errors) . PHP_EOL;
|
|
$this->writer->write($string);
|
|
}
|
|
}
|
|
|
|
class TextOutput implements Output
|
|
{
|
|
const TYPE_DEFAULT = 'default',
|
|
TYPE_SKIP = 'skip',
|
|
TYPE_ERROR = 'error',
|
|
TYPE_FAIL = 'fail',
|
|
TYPE_OK = 'ok';
|
|
|
|
/** @var int */
|
|
public $filesPerLine = 60;
|
|
|
|
/** @var bool */
|
|
public $showProgress = true;
|
|
|
|
/** @var int */
|
|
protected $checkedFiles;
|
|
|
|
/** @var int */
|
|
protected $totalFileCount;
|
|
|
|
/** @var IWriter */
|
|
protected $writer;
|
|
|
|
/**
|
|
* @param IWriter $writer
|
|
*/
|
|
public function __construct(IWriter $writer)
|
|
{
|
|
$this->writer = $writer;
|
|
}
|
|
|
|
public function ok()
|
|
{
|
|
$this->writeMark(self::TYPE_OK);
|
|
}
|
|
|
|
public function skip()
|
|
{
|
|
$this->writeMark(self::TYPE_SKIP);
|
|
}
|
|
|
|
public function error()
|
|
{
|
|
$this->writeMark(self::TYPE_ERROR);
|
|
}
|
|
|
|
public function fail()
|
|
{
|
|
$this->writeMark(self::TYPE_FAIL);
|
|
}
|
|
|
|
/**
|
|
* @param string $string
|
|
* @param string $type
|
|
*/
|
|
public function write($string, $type = self::TYPE_DEFAULT)
|
|
{
|
|
$this->writer->write($string);
|
|
}
|
|
|
|
/**
|
|
* @param string|null $line
|
|
* @param string $type
|
|
*/
|
|
public function writeLine($line = null, $type = self::TYPE_DEFAULT)
|
|
{
|
|
$this->write($line, $type);
|
|
$this->writeNewLine();
|
|
}
|
|
|
|
/**
|
|
* @param int $count
|
|
*/
|
|
public function writeNewLine($count = 1)
|
|
{
|
|
$this->write(str_repeat(PHP_EOL, $count));
|
|
}
|
|
|
|
/**
|
|
* @param int $count
|
|
*/
|
|
public function setTotalFileCount($count)
|
|
{
|
|
$this->totalFileCount = $count;
|
|
}
|
|
|
|
/**
|
|
* @param int $phpVersion
|
|
* @param int $parallelJobs
|
|
* @param string $hhvmVersion
|
|
*/
|
|
public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null)
|
|
{
|
|
$this->write("PHP {$this->phpVersionIdToString($phpVersion)} | ");
|
|
|
|
if ($hhvmVersion) {
|
|
$this->write("HHVM $hhvmVersion | ");
|
|
}
|
|
|
|
if ($parallelJobs === 1) {
|
|
$this->writeLine("1 job");
|
|
} else {
|
|
$this->writeLine("{$parallelJobs} parallel jobs");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Result $result
|
|
* @param ErrorFormatter $errorFormatter
|
|
* @param bool $ignoreFails
|
|
*/
|
|
public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
|
|
{
|
|
if ($this->showProgress) {
|
|
if ($this->checkedFiles % $this->filesPerLine !== 0) {
|
|
$rest = $this->filesPerLine - ($this->checkedFiles % $this->filesPerLine);
|
|
$this->write(str_repeat(' ', $rest));
|
|
$this->writePercent();
|
|
}
|
|
|
|
$this->writeNewLine(2);
|
|
}
|
|
|
|
$testTime = round($result->getTestTime(), 1);
|
|
$message = "Checked {$result->getCheckedFilesCount()} files in $testTime ";
|
|
$message .= $testTime == 1 ? 'second' : 'seconds';
|
|
|
|
if ($result->getSkippedFilesCount() > 0) {
|
|
$message .= ", skipped {$result->getSkippedFilesCount()} ";
|
|
$message .= ($result->getSkippedFilesCount() === 1 ? 'file' : 'files');
|
|
}
|
|
|
|
$this->writeLine($message);
|
|
|
|
if (!$result->hasSyntaxError()) {
|
|
$message = "No syntax error found";
|
|
} else {
|
|
$message = "Syntax error found in {$result->getFilesWithSyntaxErrorCount()} ";
|
|
$message .= ($result->getFilesWithSyntaxErrorCount() === 1 ? 'file' : 'files');
|
|
}
|
|
|
|
if ($result->hasFilesWithFail()) {
|
|
$message .= ", failed to check {$result->getFilesWithFailCount()} ";
|
|
$message .= ($result->getFilesWithFailCount() === 1 ? 'file' : 'files');
|
|
|
|
if ($ignoreFails) {
|
|
$message .= ' (ignored)';
|
|
}
|
|
}
|
|
|
|
$hasError = $ignoreFails ? $result->hasSyntaxError() : $result->hasError();
|
|
$this->writeLine($message, $hasError ? self::TYPE_ERROR : self::TYPE_OK);
|
|
|
|
if ($result->hasError()) {
|
|
$this->writeNewLine();
|
|
foreach ($result->getErrors() as $error) {
|
|
$this->writeLine(str_repeat('-', 60));
|
|
$this->writeLine($errorFormatter->format($error));
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function writeMark($type)
|
|
{
|
|
++$this->checkedFiles;
|
|
|
|
if ($this->showProgress) {
|
|
if ($type === self::TYPE_OK) {
|
|
$this->writer->write('.');
|
|
|
|
} else if ($type === self::TYPE_SKIP) {
|
|
$this->write('S', self::TYPE_SKIP);
|
|
|
|
} else if ($type === self::TYPE_ERROR) {
|
|
$this->write('X', self::TYPE_ERROR);
|
|
|
|
} else if ($type === self::TYPE_FAIL) {
|
|
$this->writer->write('-');
|
|
}
|
|
|
|
if ($this->checkedFiles % $this->filesPerLine === 0) {
|
|
$this->writePercent();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function writePercent()
|
|
{
|
|
$percent = floor($this->checkedFiles / $this->totalFileCount * 100);
|
|
$current = $this->stringWidth($this->checkedFiles, strlen($this->totalFileCount));
|
|
$this->writeLine(" $current/$this->totalFileCount ($percent %)");
|
|
}
|
|
|
|
/**
|
|
* @param string $input
|
|
* @param int $width
|
|
* @return string
|
|
*/
|
|
protected function stringWidth($input, $width = 3)
|
|
{
|
|
$multiplier = $width - strlen($input);
|
|
return str_repeat(' ', $multiplier > 0 ? $multiplier : 0) . $input;
|
|
}
|
|
|
|
/**
|
|
* @param int $phpVersionId
|
|
* @return string
|
|
*/
|
|
protected function phpVersionIdToString($phpVersionId)
|
|
{
|
|
$releaseVersion = (int) substr($phpVersionId, -2, 2);
|
|
$minorVersion = (int) substr($phpVersionId, -4, 2);
|
|
$majorVersion = (int) substr($phpVersionId, 0, strlen($phpVersionId) - 4);
|
|
|
|
return "$majorVersion.$minorVersion.$releaseVersion";
|
|
}
|
|
}
|
|
|
|
class CheckstyleOutput implements Output
|
|
{
|
|
private $writer;
|
|
|
|
public function __construct(IWriter $writer)
|
|
{
|
|
$this->writer = $writer;
|
|
}
|
|
|
|
public function ok()
|
|
{
|
|
}
|
|
|
|
public function skip()
|
|
{
|
|
}
|
|
|
|
public function error()
|
|
{
|
|
}
|
|
|
|
public function fail()
|
|
{
|
|
}
|
|
|
|
public function setTotalFileCount($count)
|
|
{
|
|
}
|
|
|
|
public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null)
|
|
{
|
|
$this->writer->write('<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL);
|
|
}
|
|
|
|
public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
|
|
{
|
|
$this->writer->write('<checkstyle>' . PHP_EOL);
|
|
$errors = array();
|
|
|
|
foreach ($result->getErrors() as $error) {
|
|
$message = $error->getMessage();
|
|
if ($error instanceof SyntaxError) {
|
|
$line = $error->getLine();
|
|
$source = "Syntax Error";
|
|
} else {
|
|
$line = 1;
|
|
$source = "Linter Error";
|
|
}
|
|
|
|
$errors[$error->getShortFilePath()][] = array(
|
|
'message' => $message,
|
|
'line' => $line,
|
|
'source' => $source
|
|
);
|
|
}
|
|
|
|
foreach ($errors as $file => $fileErrors) {
|
|
$this->writer->write(sprintf(' <file name="%s">', $file) . PHP_EOL);
|
|
foreach ($fileErrors as $fileError) {
|
|
$this->writer->write(
|
|
sprintf(
|
|
' <error line="%d" severity="ERROR" message="%s" source="%s" />',
|
|
$fileError['line'],
|
|
$fileError['message'],
|
|
$fileError['source']
|
|
) .
|
|
PHP_EOL
|
|
);
|
|
}
|
|
$this->writer->write(' </file>' . PHP_EOL);
|
|
}
|
|
|
|
$this->writer->write('</checkstyle>' . PHP_EOL);
|
|
}
|
|
}
|
|
|
|
class TextOutputColored extends TextOutput
|
|
{
|
|
/** @var \JakubOnderka\PhpConsoleColor\ConsoleColor */
|
|
private $colors;
|
|
|
|
public function __construct(IWriter $writer, $colors = Settings::AUTODETECT)
|
|
{
|
|
parent::__construct($writer);
|
|
|
|
if (class_exists('\JakubOnderka\PhpConsoleColor\ConsoleColor')) {
|
|
$this->colors = new \JakubOnderka\PhpConsoleColor\ConsoleColor();
|
|
$this->colors->setForceStyle($colors === Settings::FORCED);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $string
|
|
* @param string $type
|
|
* @throws \JakubOnderka\PhpConsoleColor\InvalidStyleException
|
|
*/
|
|
public function write($string, $type = self::TYPE_DEFAULT)
|
|
{
|
|
if (!$this->colors instanceof \JakubOnderka\PhpConsoleColor\ConsoleColor) {
|
|
parent::write($string, $type);
|
|
} else {
|
|
switch ($type) {
|
|
case self::TYPE_OK:
|
|
parent::write($this->colors->apply('bg_green', $string));
|
|
break;
|
|
|
|
case self::TYPE_SKIP:
|
|
parent::write($this->colors->apply('bg_yellow', $string));
|
|
break;
|
|
|
|
case self::TYPE_ERROR:
|
|
parent::write($this->colors->apply('bg_red', $string));
|
|
break;
|
|
|
|
default:
|
|
parent::write($string);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
interface IWriter
|
|
{
|
|
/**
|
|
* @param string $string
|
|
*/
|
|
public function write($string);
|
|
}
|
|
|
|
class NullWriter implements IWriter
|
|
{
|
|
/**
|
|
* @param string $string
|
|
*/
|
|
public function write($string)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
class ConsoleWriter implements IWriter
|
|
{
|
|
/**
|
|
* @param string $string
|
|
*/
|
|
public function write($string)
|
|
{
|
|
echo $string;
|
|
}
|
|
}
|
|
|
|
class FileWriter implements IWriter
|
|
{
|
|
/** @var string */
|
|
protected $logFile;
|
|
|
|
/** @var string */
|
|
protected $buffer;
|
|
|
|
public function __construct($logFile)
|
|
{
|
|
$this->logFile = $logFile;
|
|
}
|
|
|
|
public function write($string)
|
|
{
|
|
$this->buffer .= $string;
|
|
}
|
|
|
|
public function __destruct()
|
|
{
|
|
file_put_contents($this->logFile, $this->buffer);
|
|
}
|
|
}
|
|
|
|
class MultipleWriter implements IWriter
|
|
{
|
|
/** @var IWriter[] */
|
|
protected $writers;
|
|
|
|
/**
|
|
* @param IWriter[] $writers
|
|
*/
|
|
public function __construct(array $writers)
|
|
{
|
|
foreach ($writers as $writer) {
|
|
$this->addWriter($writer);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param IWriter $writer
|
|
*/
|
|
public function addWriter(IWriter $writer)
|
|
{
|
|
$this->writers[] = $writer;
|
|
}
|
|
|
|
/**
|
|
* @param $string
|
|
*/
|
|
public function write($string)
|
|
{
|
|
foreach ($this->writers as $writer) {
|
|
$writer->write($string);
|
|
}
|
|
}
|
|
}
|