Buckets:
ktongue/docker_container / SGAE /vendor /phpunit /php-code-coverage /src /Data /RawCodeCoverageData.php
| declare(strict_types=1); | |
| /* | |
| * This file is part of phpunit/php-code-coverage. | |
| * | |
| * (c) Sebastian Bergmann <sebastian@phpunit.de> | |
| * | |
| * For the full copyright and license information, please view the LICENSE | |
| * file that was distributed with this source code. | |
| */ | |
| namespace SebastianBergmann\CodeCoverage\Data; | |
| use function array_diff; | |
| use function array_diff_key; | |
| use function array_flip; | |
| use function array_intersect; | |
| use function array_intersect_key; | |
| use function count; | |
| use function explode; | |
| use function file_get_contents; | |
| use function in_array; | |
| use function is_file; | |
| use function preg_replace; | |
| use function range; | |
| use function str_ends_with; | |
| use function str_starts_with; | |
| use function trim; | |
| use SebastianBergmann\CodeCoverage\Driver\Driver; | |
| use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; | |
| /** | |
| * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage | |
| * | |
| * @psalm-import-type XdebugFunctionsCoverageType from \SebastianBergmann\CodeCoverage\Driver\XdebugDriver | |
| * @psalm-import-type XdebugCodeCoverageWithoutPathCoverageType from \SebastianBergmann\CodeCoverage\Driver\XdebugDriver | |
| * @psalm-import-type XdebugCodeCoverageWithPathCoverageType from \SebastianBergmann\CodeCoverage\Driver\XdebugDriver | |
| */ | |
| final class RawCodeCoverageData | |
| { | |
| /** | |
| * @var array<string, array<int>> | |
| */ | |
| private static array $emptyLineCache = []; | |
| /** | |
| * @psalm-var XdebugCodeCoverageWithoutPathCoverageType | |
| */ | |
| private array $lineCoverage; | |
| /** | |
| * @psalm-var array<string, XdebugFunctionsCoverageType> | |
| */ | |
| private array $functionCoverage; | |
| /** | |
| * @psalm-param XdebugCodeCoverageWithoutPathCoverageType $rawCoverage | |
| */ | |
| public static function fromXdebugWithoutPathCoverage(array $rawCoverage): self | |
| { | |
| return new self($rawCoverage, []); | |
| } | |
| /** | |
| * @psalm-param XdebugCodeCoverageWithPathCoverageType $rawCoverage | |
| */ | |
| public static function fromXdebugWithPathCoverage(array $rawCoverage): self | |
| { | |
| $lineCoverage = []; | |
| $functionCoverage = []; | |
| foreach ($rawCoverage as $file => $fileCoverageData) { | |
| // Xdebug annotates the function name of traits, strip that off | |
| foreach ($fileCoverageData['functions'] as $existingKey => $data) { | |
| if (str_ends_with($existingKey, '}') && !str_starts_with($existingKey, '{')) { // don't want to catch {main} | |
| $newKey = preg_replace('/\{.*}$/', '', $existingKey); | |
| $fileCoverageData['functions'][$newKey] = $data; | |
| unset($fileCoverageData['functions'][$existingKey]); | |
| } | |
| } | |
| $lineCoverage[$file] = $fileCoverageData['lines']; | |
| $functionCoverage[$file] = $fileCoverageData['functions']; | |
| } | |
| return new self($lineCoverage, $functionCoverage); | |
| } | |
| public static function fromUncoveredFile(string $filename, FileAnalyser $analyser): self | |
| { | |
| $lineCoverage = []; | |
| foreach ($analyser->executableLinesIn($filename) as $line => $branch) { | |
| $lineCoverage[$line] = Driver::LINE_NOT_EXECUTED; | |
| } | |
| return new self([$filename => $lineCoverage], []); | |
| } | |
| /** | |
| * @psalm-param XdebugCodeCoverageWithoutPathCoverageType $lineCoverage | |
| * @psalm-param array<string, XdebugFunctionsCoverageType> $functionCoverage | |
| */ | |
| private function __construct(array $lineCoverage, array $functionCoverage) | |
| { | |
| $this->lineCoverage = $lineCoverage; | |
| $this->functionCoverage = $functionCoverage; | |
| $this->skipEmptyLines(); | |
| } | |
| public function clear(): void | |
| { | |
| $this->lineCoverage = $this->functionCoverage = []; | |
| } | |
| /** | |
| * @psalm-return XdebugCodeCoverageWithoutPathCoverageType | |
| */ | |
| public function lineCoverage(): array | |
| { | |
| return $this->lineCoverage; | |
| } | |
| /** | |
| * @psalm-return array<string, XdebugFunctionsCoverageType> | |
| */ | |
| public function functionCoverage(): array | |
| { | |
| return $this->functionCoverage; | |
| } | |
| public function removeCoverageDataForFile(string $filename): void | |
| { | |
| unset($this->lineCoverage[$filename], $this->functionCoverage[$filename]); | |
| } | |
| /** | |
| * @param int[] $lines | |
| */ | |
| public function keepLineCoverageDataOnlyForLines(string $filename, array $lines): void | |
| { | |
| if (!isset($this->lineCoverage[$filename])) { | |
| return; | |
| } | |
| $this->lineCoverage[$filename] = array_intersect_key( | |
| $this->lineCoverage[$filename], | |
| array_flip($lines), | |
| ); | |
| } | |
| /** | |
| * @param int[] $linesToBranchMap | |
| */ | |
| public function markExecutableLineByBranch(string $filename, array $linesToBranchMap): void | |
| { | |
| if (!isset($this->lineCoverage[$filename])) { | |
| return; | |
| } | |
| $linesByBranch = []; | |
| foreach ($linesToBranchMap as $line => $branch) { | |
| $linesByBranch[$branch][] = $line; | |
| } | |
| foreach ($this->lineCoverage[$filename] as $line => $lineStatus) { | |
| if (!isset($linesToBranchMap[$line])) { | |
| continue; | |
| } | |
| $branch = $linesToBranchMap[$line]; | |
| if (!isset($linesByBranch[$branch])) { | |
| continue; | |
| } | |
| foreach ($linesByBranch[$branch] as $lineInBranch) { | |
| $this->lineCoverage[$filename][$lineInBranch] = $lineStatus; | |
| } | |
| if (Driver::LINE_EXECUTED === $lineStatus) { | |
| unset($linesByBranch[$branch]); | |
| } | |
| } | |
| } | |
| /** | |
| * @param int[] $lines | |
| */ | |
| public function keepFunctionCoverageDataOnlyForLines(string $filename, array $lines): void | |
| { | |
| if (!isset($this->functionCoverage[$filename])) { | |
| return; | |
| } | |
| foreach ($this->functionCoverage[$filename] as $functionName => $functionData) { | |
| foreach ($functionData['branches'] as $branchId => $branch) { | |
| if (count(array_diff(range($branch['line_start'], $branch['line_end']), $lines)) > 0) { | |
| unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]); | |
| foreach ($functionData['paths'] as $pathId => $path) { | |
| if (in_array($branchId, $path['path'], true)) { | |
| unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * @param int[] $lines | |
| */ | |
| public function removeCoverageDataForLines(string $filename, array $lines): void | |
| { | |
| if (empty($lines)) { | |
| return; | |
| } | |
| if (!isset($this->lineCoverage[$filename])) { | |
| return; | |
| } | |
| $this->lineCoverage[$filename] = array_diff_key( | |
| $this->lineCoverage[$filename], | |
| array_flip($lines), | |
| ); | |
| if (isset($this->functionCoverage[$filename])) { | |
| foreach ($this->functionCoverage[$filename] as $functionName => $functionData) { | |
| foreach ($functionData['branches'] as $branchId => $branch) { | |
| if (count(array_intersect($lines, range($branch['line_start'], $branch['line_end']))) > 0) { | |
| unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]); | |
| foreach ($functionData['paths'] as $pathId => $path) { | |
| if (in_array($branchId, $path['path'], true)) { | |
| unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * At the end of a file, the PHP interpreter always sees an implicit return. Where this occurs in a file that has | |
| * e.g. a class definition, that line cannot be invoked from a test and results in confusing coverage. This engine | |
| * implementation detail therefore needs to be masked which is done here by simply ensuring that all empty lines | |
| * are skipped over for coverage purposes. | |
| * | |
| * @see https://github.com/sebastianbergmann/php-code-coverage/issues/799 | |
| */ | |
| private function skipEmptyLines(): void | |
| { | |
| foreach ($this->lineCoverage as $filename => $coverage) { | |
| foreach ($this->getEmptyLinesForFile($filename) as $emptyLine) { | |
| unset($this->lineCoverage[$filename][$emptyLine]); | |
| } | |
| } | |
| } | |
| private function getEmptyLinesForFile(string $filename): array | |
| { | |
| if (!isset(self::$emptyLineCache[$filename])) { | |
| self::$emptyLineCache[$filename] = []; | |
| if (is_file($filename)) { | |
| $sourceLines = explode("\n", file_get_contents($filename)); | |
| foreach ($sourceLines as $line => $source) { | |
| if (trim($source) === '') { | |
| self::$emptyLineCache[$filename][] = ($line + 1); | |
| } | |
| } | |
| } | |
| } | |
| return self::$emptyLineCache[$filename]; | |
| } | |
| } | |
Xet Storage Details
- Size:
- 9.3 kB
- Xet hash:
- 87887cf1cf35e851a0aadb9297043831ad1b38f6457d5bc48abb88156511eb15
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.