diff --git a/src/CodeCoverage.php b/src/CodeCoverage.php index 4550e468d..539328abe 100644 --- a/src/CodeCoverage.php +++ b/src/CodeCoverage.php @@ -113,6 +113,20 @@ class CodeCoverage */ private $unintentionallyCoveredSubclassesWhitelist = []; + /** + * 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. * @@ -154,6 +168,7 @@ public function getReport() */ public function clear() { + $this->isInitialized = false; $this->currentId = null; $this->data = []; $this->tests = []; @@ -237,9 +252,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); } /** @@ -687,13 +706,7 @@ private function addUncoveredFilesFromWhitelist() continue; } - if ($this->processUncoveredFilesFromWhitelist) { - $this->processUncoveredFileFromWhitelist( - $uncoveredFile, - $data, - $uncoveredFiles - ); - } else { + if (!$this->processUncoveredFilesFromWhitelist) { $data[$uncoveredFile] = []; $lines = count(file($uncoveredFile)); @@ -707,31 +720,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] == Driver::LINE_EXECUTED) { - $fileCoverage[$key] = Driver::LINE_NOT_EXECUTED; - } - } - - $data[$file] = $fileCoverage; - } - } - } - /** * Returns the lines of a source file that should be ignored. * @@ -1074,4 +1062,45 @@ private function processUnintentionallyCoveredUnits(array $unintentionallyCovere return array_values($unintentionallyCoveredUnits); } + + /** + * 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] == Driver::LINE_EXECUTED) { + $fileCoverage[$key] = Driver::LINE_NOT_EXECUTED; + } + } + + $data[$file] = $fileCoverage; + } + + $this->append($data, 'UNCOVERED_FILES_FROM_WHITELIST'); + } + } } diff --git a/src/Driver/Driver.php b/src/Driver/Driver.php index 8d9ef5357..bdd1b9794 100644 --- a/src/Driver/Driver.php +++ b/src/Driver/Driver.php @@ -38,8 +38,10 @@ interface Driver /** * Start collection of code coverage information. + * + * @param bool $determineUnusedAndDead */ - public function start(); + public function start($determineUnusedAndDead = true); /** * Stop collection of code coverage information. diff --git a/src/Driver/HHVM.php b/src/Driver/HHVM.php index 76758cb6e..b35ea81bb 100644 --- a/src/Driver/HHVM.php +++ b/src/Driver/HHVM.php @@ -19,8 +19,10 @@ class HHVM extends Xdebug { /** * Start collection of code coverage information. + * + * @param bool $determineUnusedAndDead */ - public function start() + public function start($determineUnusedAndDead = true) { xdebug_start_code_coverage(); } diff --git a/src/Driver/PHPDBG.php b/src/Driver/PHPDBG.php index 6e1cdd943..86cc8444c 100644 --- a/src/Driver/PHPDBG.php +++ b/src/Driver/PHPDBG.php @@ -39,8 +39,10 @@ public function __construct() /** * Start collection of code coverage information. + * + * @param bool $determineUnusedAndDead */ - public function start() + public function start($determineUnusedAndDead = true) { phpdbg_start_oplog(); } diff --git a/src/Driver/Xdebug.php b/src/Driver/Xdebug.php index b47752d73..82d555507 100644 --- a/src/Driver/Xdebug.php +++ b/src/Driver/Xdebug.php @@ -19,6 +19,13 @@ */ class Xdebug implements Driver { + /** + * Cache the number of lines for each file + * + * @var array + */ + private $cacheNumLines = []; + /** * Constructor. */ @@ -38,10 +45,16 @@ public function __construct() /** * Start collection of code coverage information. + * + * @param bool $determineUnusedAndDead */ - 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(); + } } /** @@ -88,13 +101,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]; } }