diff --git a/src/CodeCoverage.php b/src/CodeCoverage.php index d1ac2e9e7..55520571e 100644 --- a/src/CodeCoverage.php +++ b/src/CodeCoverage.php @@ -81,6 +81,20 @@ class PHP_CodeCoverage */ private $tests = []; + /** + * Determine if the data has been initialized or not + * + * @var bool + */ + private $isInitialized = false; + + /** + * Determine whether we need to check for dead and unused code on each test + * + * @var bool + */ + private $shouldCheckForDeadAndUnused = true; + /** * Constructor. * @@ -121,6 +135,7 @@ public function getReport() */ public function clear() { + $this->isInitialized = false; $this->currentId = null; $this->data = []; $this->tests = []; @@ -206,9 +221,13 @@ public function start($id, $clear = false) $this->clear(); } + if ($this->isInitialized === false) { + $this->initializeData(); + } + $this->currentId = $id; - $this->driver->start(); + $this->driver->start($this->shouldCheckForDeadAndUnused); } /** @@ -580,13 +599,7 @@ private function addUncoveredFilesFromWhitelist() continue; } - if ($this->processUncoveredFilesFromWhitelist) { - $this->processUncoveredFileFromWhitelist( - $uncoveredFile, - $data, - $uncoveredFiles - ); - } else { + if (!$this->processUncoveredFilesFromWhitelist) { $data[$uncoveredFile] = []; $lines = count(file($uncoveredFile)); @@ -600,31 +613,6 @@ private function addUncoveredFilesFromWhitelist() $this->append($data, 'UNCOVERED_FILES_FROM_WHITELIST'); } - /** - * @param string $uncoveredFile - * @param array $data - * @param array $uncoveredFiles - */ - private function processUncoveredFileFromWhitelist($uncoveredFile, array &$data, array $uncoveredFiles) - { - $this->driver->start(); - include_once $uncoveredFile; - $coverage = $this->driver->stop(); - - foreach ($coverage as $file => $fileCoverage) { - if (!isset($data[$file]) && - in_array($file, $uncoveredFiles)) { - foreach (array_keys($fileCoverage) as $key) { - if ($fileCoverage[$key] == PHP_CodeCoverage_Driver::LINE_EXECUTED) { - $fileCoverage[$key] = PHP_CodeCoverage_Driver::LINE_NOT_EXECUTED; - } - } - - $data[$file] = $fileCoverage; - } - } - } - /** * Returns the lines of a source file that should be ignored. * @@ -897,4 +885,45 @@ private function selectDriver() return new PHP_CodeCoverage_Driver_Xdebug; } } + + /** + * If we are processing uncovered files from whitelist, + * we can initialize the data before we start to speed up the tests + */ + protected function initializeData() + { + $this->isInitialized = true; + + if ($this->processUncoveredFilesFromWhitelist) { + + $this->shouldCheckForDeadAndUnused = false; + + $this->driver->start(true); + + foreach ($this->filter->getWhitelist() as $file) { + if ($this->filter->isFile($file)) { + include_once($file); + } + } + + $data = []; + $coverage = $this->driver->stop(); + + foreach ($coverage as $file => $fileCoverage) { + if ($this->filter->isFiltered($file)) { + continue; + } + + foreach (array_keys($fileCoverage) as $key) { + if ($fileCoverage[$key] == PHP_CodeCoverage_Driver::LINE_EXECUTED) { + $fileCoverage[$key] = PHP_CodeCoverage_Driver::LINE_NOT_EXECUTED; + } + } + + $data[$file] = $fileCoverage; + } + + $this->append($data, 'UNCOVERED_FILES_FROM_WHITELIST'); + } + } } diff --git a/src/CodeCoverage/Driver.php b/src/CodeCoverage/Driver.php index 8635acefe..4452ec02e 100644 --- a/src/CodeCoverage/Driver.php +++ b/src/CodeCoverage/Driver.php @@ -36,7 +36,7 @@ interface PHP_CodeCoverage_Driver /** * Start collection of code coverage information. */ - public function start(); + public function start($determineUnusedAndDead = true); /** * Stop collection of code coverage information. diff --git a/src/CodeCoverage/Driver/HHVM.php b/src/CodeCoverage/Driver/HHVM.php index a9d8f0cef..4250091a3 100644 --- a/src/CodeCoverage/Driver/HHVM.php +++ b/src/CodeCoverage/Driver/HHVM.php @@ -19,7 +19,7 @@ class PHP_CodeCoverage_Driver_HHVM extends PHP_CodeCoverage_Driver_Xdebug /** * Start collection of code coverage information. */ - public function start() + public function start($determineUnusedAndDead = true) { xdebug_start_code_coverage(); } diff --git a/src/CodeCoverage/Driver/PHPDBG.php b/src/CodeCoverage/Driver/PHPDBG.php index 2c39c8c80..92f78106f 100644 --- a/src/CodeCoverage/Driver/PHPDBG.php +++ b/src/CodeCoverage/Driver/PHPDBG.php @@ -37,7 +37,7 @@ public function __construct() /** * Start collection of code coverage information. */ - public function start() + public function start($determineUnusedAndDead = true) { phpdbg_start_oplog(); } diff --git a/src/CodeCoverage/Driver/Xdebug.php b/src/CodeCoverage/Driver/Xdebug.php index ed9a7035b..f8e9a9f03 100644 --- a/src/CodeCoverage/Driver/Xdebug.php +++ b/src/CodeCoverage/Driver/Xdebug.php @@ -16,6 +16,13 @@ */ class PHP_CodeCoverage_Driver_Xdebug implements PHP_CodeCoverage_Driver { + /** + * Cache the number of lines for each file + * + * @var array + */ + private $cacheNumLines = []; + /** * Constructor. */ @@ -36,9 +43,13 @@ public function __construct() /** * Start collection of code coverage information. */ - public function start() + public function start($determineUnusedAndDead = true) { - xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); + if ($determineUnusedAndDead) { + xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); + } else { + xdebug_start_code_coverage(); + } } /** @@ -85,13 +96,17 @@ private function cleanup(array $data) */ private function getNumberOfLinesInFile($file) { - $buffer = file_get_contents($file); - $lines = substr_count($buffer, "\n"); + if (!isset($this->cacheNumLines[$file])) { + $buffer = file_get_contents($file); + $lines = substr_count($buffer, "\n"); + + if (substr($buffer, -1) !== "\n") { + $lines++; + } - if (substr($buffer, -1) !== "\n") { - $lines++; + $this->cacheNumLines[$file] = $lines; } - return $lines; + return $this->cacheNumLines[$file]; } }