diff --git a/src/Error/Blame.php b/src/Error/Blame.php
new file mode 100644
index 00000000..e0580638
--- /dev/null
+++ b/src/Error/Blame.php
@@ -0,0 +1,34 @@
+
+ * Specify data which should be serialized to JSON
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ * @return mixed data which can be serialized by json_encode,
+ * which is a value of any type other than a resource.
+ */
+ function jsonSerialize()
+ {
+ return array(
+ 'name' => $this->name,
+ 'email' => $this->email,
+ 'datetime' => $this->datetime,
+ 'commitHash' => $this->commitHash,
+ 'summary' => $this->summary,
+ );
+ }
+}
diff --git a/src/Error/Error.php b/src/Error/Error.php
new file mode 100644
index 00000000..5397d965
--- /dev/null
+++ b/src/Error/Error.php
@@ -0,0 +1,68 @@
+filePath = $filePath;
+ $this->message = rtrim($message);
+ }
+
+ /**
+ * @return string
+ */
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ /**
+ * @return string
+ */
+ public function getFilePath()
+ {
+ return $this->filePath;
+ }
+
+ /**
+ * @return string
+ */
+ public function getShortFilePath()
+ {
+ $cwd = getcwd();
+
+ if ($cwd === '/') {
+ // For root directory in unix, do not modify path
+ return $this->filePath;
+ }
+
+ return preg_replace('/' . preg_quote($cwd, '/') . '/', '', $this->filePath, 1);
+ }
+
+ /**
+ * (PHP 5 >= 5.4.0)
+ * Specify data which should be serialized to JSON
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ * @return mixed data which can be serialized by json_encode,
+ * which is a value of any type other than a resource.
+ */
+ public function jsonSerialize()
+ {
+ return array(
+ 'type' => 'error',
+ 'file' => $this->getFilePath(),
+ 'message' => $this->getMessage(),
+ );
+ }
+}
diff --git a/src/Error.php b/src/Error/SyntaxError.php
similarity index 60%
rename from src/Error.php
rename to src/Error/SyntaxError.php
index 9041ab1c..ba3f7e7b 100644
--- a/src/Error.php
+++ b/src/Error/SyntaxError.php
@@ -1,105 +1,5 @@
filePath = $filePath;
- $this->message = rtrim($message);
- }
-
- /**
- * @return string
- */
- public function getMessage()
- {
- return $this->message;
- }
-
- /**
- * @return string
- */
- public function getFilePath()
- {
- return $this->filePath;
- }
-
- /**
- * @return string
- */
- public function getShortFilePath()
- {
- $cwd = getcwd();
-
- if ($cwd === '/') {
- // For root directory in unix, do not modify path
- return $this->filePath;
- }
-
- return preg_replace('/' . preg_quote($cwd, '/') . '/', '', $this->filePath, 1);
- }
-
- /**
- * (PHP 5 >= 5.4.0)
- * Specify data which should be serialized to JSON
- * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by json_encode,
- * which is a value of any type other than a resource.
- */
- public function jsonSerialize()
- {
- return array(
- 'type' => 'error',
- 'file' => $this->getFilePath(),
- 'message' => $this->getMessage(),
- );
- }
-}
-
-class Blame implements \JsonSerializable
-{
- public $name;
-
- public $email;
-
- /** @var \DateTime */
- public $datetime;
-
- public $commitHash;
-
- public $summary;
-
- /**
- * (PHP 5 >= 5.4.0)
- * Specify data which should be serialized to JSON
- * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
- * @return mixed data which can be serialized by json_encode,
- * which is a value of any type other than a resource.
- */
- function jsonSerialize()
- {
- return array(
- 'name' => $this->name,
- 'email' => $this->email,
- 'datetime' => $this->datetime,
- 'commitHash' => $this->commitHash,
- 'summary' => $this->summary,
- );
- }
-
-
-}
+namespace JakubOnderka\PhpParallelLint\Error;
class SyntaxError extends Error
{
@@ -219,4 +119,4 @@ public function jsonSerialize()
'blame' => $this->blame,
);
}
-}
\ No newline at end of file
+}
diff --git a/src/ErrorFormatter.php b/src/ErrorFormatter.php
index 76b4466c..ad2542a7 100644
--- a/src/ErrorFormatter.php
+++ b/src/ErrorFormatter.php
@@ -3,6 +3,8 @@
use JakubOnderka\PhpConsoleColor\ConsoleColor;
use JakubOnderka\PhpConsoleHighlighter\Highlighter;
+use JakubOnderka\PhpParallelLint\Error\Error;
+use JakubOnderka\PhpParallelLint\Error\SyntaxError;
class ErrorFormatter
{
diff --git a/src/Manager.php b/src/Manager.php
index 0373f9b0..0802af12 100644
--- a/src/Manager.php
+++ b/src/Manager.php
@@ -1,12 +1,15 @@
output = $output;
}
/**
* @param Settings $settings
- * @return Output
+ * @return Output\Output
*/
protected function getDefaultOutput(Settings $settings)
{
- $writer = new ConsoleWriter;
+ $writer = new Output\ConsoleWriter;
switch ($settings->format) {
case Settings::FORMAT_JSON:
- return new JsonOutput($writer);
+ return new Output\JsonOutput($writer);
case Settings::FORMAT_CHECKSTYLE:
- return new CheckstyleOutput($writer);
+ return new Output\CheckstyleOutput($writer);
}
if ($settings->colors === Settings::DISABLED) {
- $output = new TextOutput($writer);
+ $output = new Output\TextOutput($writer);
} else {
- $output = new TextOutputColored($writer, $settings->colors);
+ $output = new Output\TextOutputColored($writer, $settings->colors);
}
$output->showProgress = $settings->showProgress;
@@ -166,91 +169,3 @@ protected function getFilesFromPaths(array $paths, array $extensions, array $exc
return $files;
}
}
-
-class RecursiveDirectoryFilterIterator extends \RecursiveFilterIterator
-{
- /** @var \RecursiveDirectoryIterator */
- private $iterator;
-
- /** @var array */
- private $excluded = array();
-
- /**
- * @param \RecursiveDirectoryIterator $iterator
- * @param array $excluded
- */
- public function __construct(\RecursiveDirectoryIterator $iterator, array $excluded)
- {
- parent::__construct($iterator);
- $this->iterator = $iterator;
- $this->excluded = array_map(array($this, 'getPathname'), $excluded);
- }
-
- /**
- * (PHP 5 >= 5.1.0)
- * Check whether the current element of the iterator is acceptable
- *
- * @link http://php.net/manual/en/filteriterator.accept.php
- * @return bool true if the current element is acceptable, otherwise false.
- */
- public function accept()
- {
- $current = $this->current()->getPathname();
- $current = $this->normalizeDirectorySeparator($current);
-
- if ('.' . DIRECTORY_SEPARATOR !== $current[0] . $current[1]) {
- $current = '.' . DIRECTORY_SEPARATOR . $current;
- }
-
- return !in_array($current, $this->excluded);
- }
-
- /**
- * (PHP 5 >= 5.1.0)
- * Check whether the inner iterator's current element has children
- *
- * @link http://php.net/manual/en/recursivefilteriterator.haschildren.php
- * @return bool true if the inner iterator has children, otherwise false
- */
- public function hasChildren()
- {
- return $this->iterator->hasChildren();
- }
-
- /**
- * (PHP 5 >= 5.1.0)
- * Return the inner iterator's children contained in a RecursiveFilterIterator
- *
- * @link http://php.net/manual/en/recursivefilteriterator.getchildren.php
- * @return \RecursiveFilterIterator containing the inner iterator's children.
- */
- public function getChildren()
- {
- return new self($this->iterator->getChildren(), $this->excluded);
- }
-
- /**
- * @param string $file
- * @return string
- */
- private function getPathname($file)
- {
- $file = $this->normalizeDirectorySeparator($file);
-
- if ('.' . DIRECTORY_SEPARATOR !== $file[0] . $file[1]) {
- $file = '.' . DIRECTORY_SEPARATOR . $file;
- }
-
- $directoryFile = new \SplFileInfo($file);
- return $directoryFile->getPathname();
- }
-
- /**
- * @param string $file
- * @return string
- */
- private function normalizeDirectorySeparator($file)
- {
- return str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $file);
- }
-}
diff --git a/src/Output.php b/src/Output.php
deleted file mode 100644
index c51d11b0..00000000
--- a/src/Output.php
+++ /dev/null
@@ -1,513 +0,0 @@
-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 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('' . PHP_EOL);
- }
-
- public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
- {
- $this->writer->write('' . 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) . PHP_EOL);
- foreach ($fileErrors as $fileError) {
- $this->writer->write(
- sprintf(
- ' ',
- $fileError['line'],
- $fileError['message'],
- $fileError['source']
- ) .
- PHP_EOL
- );
- }
- $this->writer->write(' ' . PHP_EOL);
- }
-
- $this->writer->write('' . 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);
- }
- }
-}
diff --git a/src/Output/CheckstyleOutput.php b/src/Output/CheckstyleOutput.php
new file mode 100644
index 00000000..346c146c
--- /dev/null
+++ b/src/Output/CheckstyleOutput.php
@@ -0,0 +1,82 @@
+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('' . PHP_EOL);
+ }
+
+ public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
+ {
+ $this->writer->write('' . 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) . PHP_EOL);
+ foreach ($fileErrors as $fileError) {
+ $this->writer->write(
+ sprintf(
+ ' ',
+ $fileError['line'],
+ $fileError['message'],
+ $fileError['source']
+ ) .
+ PHP_EOL
+ );
+ }
+ $this->writer->write(' ' . PHP_EOL);
+ }
+
+ $this->writer->write('' . PHP_EOL);
+ }
+}
diff --git a/src/Output/JsonOutput.php b/src/Output/JsonOutput.php
new file mode 100644
index 00000000..1c50edfd
--- /dev/null
+++ b/src/Output/JsonOutput.php
@@ -0,0 +1,70 @@
+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,
+ ));
+ }
+}
diff --git a/src/Output/Output.php b/src/Output/Output.php
new file mode 100644
index 00000000..8297f7aa
--- /dev/null
+++ b/src/Output/Output.php
@@ -0,0 +1,112 @@
+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);
+ }
+ }
+}
diff --git a/src/Output/TextOutput.php b/src/Output/TextOutput.php
new file mode 100644
index 00000000..489dbac8
--- /dev/null
+++ b/src/Output/TextOutput.php
@@ -0,0 +1,224 @@
+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
+ * @throws \JakubOnderka\PhpConsoleColor\InvalidStyleException
+ */
+ 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";
+ }
+}
diff --git a/src/Output/TextOutputColored.php b/src/Output/TextOutputColored.php
new file mode 100644
index 00000000..542ecb53
--- /dev/null
+++ b/src/Output/TextOutputColored.php
@@ -0,0 +1,49 @@
+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);
+ }
+ }
+ }
+}
diff --git a/src/ParallelLint.php b/src/ParallelLint.php
index fcb4cb98..1f254829 100644
--- a/src/ParallelLint.php
+++ b/src/ParallelLint.php
@@ -1,6 +1,8 @@
iterator = $iterator;
+ $this->excluded = array_map(array($this, 'getPathname'), $excluded);
+ }
+
+ /**
+ * (PHP 5 >= 5.1.0)
+ * Check whether the current element of the iterator is acceptable
+ *
+ * @link http://php.net/manual/en/filteriterator.accept.php
+ * @return bool true if the current element is acceptable, otherwise false.
+ */
+ public function accept()
+ {
+ $current = $this->current()->getPathname();
+ $current = $this->normalizeDirectorySeparator($current);
+
+ if ('.' . DIRECTORY_SEPARATOR !== $current[0] . $current[1]) {
+ $current = '.' . DIRECTORY_SEPARATOR . $current;
+ }
+
+ return !in_array($current, $this->excluded);
+ }
+
+ /**
+ * (PHP 5 >= 5.1.0)
+ * Check whether the inner iterator's current element has children
+ *
+ * @link http://php.net/manual/en/recursivefilteriterator.haschildren.php
+ * @return bool true if the inner iterator has children, otherwise false
+ */
+ public function hasChildren()
+ {
+ return $this->iterator->hasChildren();
+ }
+
+ /**
+ * (PHP 5 >= 5.1.0)
+ * Return the inner iterator's children contained in a RecursiveFilterIterator
+ *
+ * @link http://php.net/manual/en/recursivefilteriterator.getchildren.php
+ * @return \RecursiveFilterIterator containing the inner iterator's children.
+ */
+ public function getChildren()
+ {
+ return new self($this->iterator->getChildren(), $this->excluded);
+ }
+
+ /**
+ * @param string $file
+ * @return string
+ */
+ private function getPathname($file)
+ {
+ $file = $this->normalizeDirectorySeparator($file);
+
+ if ('.' . DIRECTORY_SEPARATOR !== $file[0] . $file[1]) {
+ $file = '.' . DIRECTORY_SEPARATOR . $file;
+ }
+
+ $directoryFile = new \SplFileInfo($file);
+ return $directoryFile->getPathname();
+ }
+
+ /**
+ * @param string $file
+ * @return string
+ */
+ private function normalizeDirectorySeparator($file)
+ {
+ return str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $file);
+ }
+}
diff --git a/src/Result.php b/src/Result.php
index 60043742..c1c0bff0 100644
--- a/src/Result.php
+++ b/src/Result.php
@@ -1,6 +1,9 @@
run();
\ No newline at end of file
+$testCase->run();