* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use const PHP_SAPI; use const PHP_VERSION; use function array_diff; use function array_keys; use function array_merge; use function get_included_files; use function phpdbg_end_oplog; use function phpdbg_get_executable; use function phpdbg_start_oplog; use SebastianBergmann\CodeCoverage\RawCodeCoverageData; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class PhpdbgDriver extends Driver { /** * @throws PhpdbgNotAvailableException */ public function __construct() { if (PHP_SAPI !== 'phpdbg') { throw new PhpdbgNotAvailableException; } } public function start(): void { phpdbg_start_oplog(); } public function stop(): RawCodeCoverageData { static $fetchedLines = []; $dbgData = phpdbg_end_oplog(); if ($fetchedLines === []) { $sourceLines = phpdbg_get_executable(); } else { $newFiles = array_diff(get_included_files(), array_keys($fetchedLines)); $sourceLines = []; if ($newFiles) { $sourceLines = phpdbg_get_executable(['files' => $newFiles]); } } foreach ($sourceLines as $file => $lines) { foreach ($lines as $lineNo => $numExecuted) { $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED; } } $fetchedLines = array_merge($fetchedLines, $sourceLines); return RawCodeCoverageData::fromXdebugWithoutPathCoverage( $this->detectExecutedLines($fetchedLines, $dbgData) ); } public function nameAndVersion(): string { return 'PHPDBG ' . PHP_VERSION; } private function detectExecutedLines(array $sourceLines, array $dbgData): array { foreach ($dbgData as $file => $coveredLines) { foreach ($coveredLines as $lineNo => $numExecuted) { // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown. // make sure we only mark lines executed which are actually executable. if (isset($sourceLines[$file][$lineNo])) { $sourceLines[$file][$lineNo] = self::LINE_EXECUTED; } } } return $sourceLines; } }