refactor: susun semula struktur folder — Laravel source ke src/
This commit is contained in:
691
vendor/phpunit/php-code-coverage/src/CodeCoverage.php
vendored
Normal file
691
vendor/phpunit/php-code-coverage/src/CodeCoverage.php
vendored
Normal file
@@ -0,0 +1,691 @@
|
||||
<?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;
|
||||
|
||||
use function array_diff;
|
||||
use function array_diff_key;
|
||||
use function array_flip;
|
||||
use function array_keys;
|
||||
use function array_merge;
|
||||
use function array_unique;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function is_file;
|
||||
use function sort;
|
||||
use ReflectionClass;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedCodeCoverageData;
|
||||
use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData;
|
||||
use SebastianBergmann\CodeCoverage\Driver\Driver;
|
||||
use SebastianBergmann\CodeCoverage\Node\Builder;
|
||||
use SebastianBergmann\CodeCoverage\Node\Directory;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\CachingSourceAnalyser;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\ParsingSourceAnalyser;
|
||||
use SebastianBergmann\CodeCoverage\Test\Target\MapBuilder;
|
||||
use SebastianBergmann\CodeCoverage\Test\Target\Mapper;
|
||||
use SebastianBergmann\CodeCoverage\Test\Target\TargetCollection;
|
||||
use SebastianBergmann\CodeCoverage\Test\Target\TargetCollectionValidator;
|
||||
use SebastianBergmann\CodeCoverage\Test\Target\ValidationResult;
|
||||
use SebastianBergmann\CodeCoverage\Test\TestSize\TestSize;
|
||||
use SebastianBergmann\CodeCoverage\Test\TestStatus\TestStatus;
|
||||
|
||||
/**
|
||||
* Provides collection functionality for PHP code coverage information.
|
||||
*
|
||||
* @phpstan-type TestType array{size: string, status: string, time: float}
|
||||
* @phpstan-type TargetedLines array<non-empty-string, list<positive-int>>
|
||||
*/
|
||||
final class CodeCoverage
|
||||
{
|
||||
private const string UNCOVERED_FILES = 'UNCOVERED_FILES';
|
||||
private readonly Driver $driver;
|
||||
private readonly Filter $filter;
|
||||
private ?FileAnalyser $analyser = null;
|
||||
private ?Mapper $targetMapper = null;
|
||||
private ?string $cacheDirectory = null;
|
||||
private bool $checkForUnintentionallyCoveredCode = false;
|
||||
private bool $collectBranchAndPathCoverage = false;
|
||||
private bool $includeUncoveredFiles = true;
|
||||
private bool $ignoreDeprecatedCode = false;
|
||||
private bool $useAnnotationsForIgnoringCode = true;
|
||||
|
||||
/**
|
||||
* @var list<class-string>
|
||||
*/
|
||||
private array $parentClassesExcludedFromUnintentionallyCoveredCodeCheck = [];
|
||||
private ?string $currentId = null;
|
||||
private ?TestSize $currentSize = null;
|
||||
private ProcessedCodeCoverageData $data;
|
||||
|
||||
/**
|
||||
* @var array<string, TestType>
|
||||
*/
|
||||
private array $tests = [];
|
||||
private ?Directory $cachedReport = null;
|
||||
|
||||
public function __construct(Driver $driver, Filter $filter)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
$this->filter = $filter;
|
||||
$this->data = new ProcessedCodeCoverageData;
|
||||
}
|
||||
|
||||
public function __serialize(): array
|
||||
{
|
||||
$prefix = "\x00" . self::class . "\x00";
|
||||
|
||||
return [
|
||||
// Configuration
|
||||
$prefix . 'cacheDirectory' => $this->cacheDirectory,
|
||||
$prefix . 'checkForUnintentionallyCoveredCode' => $this->checkForUnintentionallyCoveredCode,
|
||||
$prefix . 'includeUncoveredFiles' => $this->includeUncoveredFiles,
|
||||
$prefix . 'ignoreDeprecatedCode' => $this->ignoreDeprecatedCode,
|
||||
$prefix . 'parentClassesExcludedFromUnintentionallyCoveredCodeCheck' => $this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck,
|
||||
$prefix . 'useAnnotationsForIgnoringCode' => $this->useAnnotationsForIgnoringCode,
|
||||
$prefix . 'filter' => $this->filter,
|
||||
|
||||
// Data
|
||||
$prefix . 'data' => $this->data,
|
||||
$prefix . 'tests' => $this->tests,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code coverage information as a graph of node objects.
|
||||
*/
|
||||
public function getReport(): Directory
|
||||
{
|
||||
if ($this->cachedReport === null) {
|
||||
$this->cachedReport = (new Builder($this->analyser()))->build($this);
|
||||
}
|
||||
|
||||
return $this->cachedReport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears collected code coverage data.
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->currentId = null;
|
||||
$this->currentSize = null;
|
||||
$this->data = new ProcessedCodeCoverageData;
|
||||
$this->tests = [];
|
||||
$this->cachedReport = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function clearCache(): void
|
||||
{
|
||||
$this->cachedReport = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filter object used.
|
||||
*/
|
||||
public function filter(): Filter
|
||||
{
|
||||
return $this->filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collected code coverage data.
|
||||
*/
|
||||
public function getData(bool $raw = false): ProcessedCodeCoverageData
|
||||
{
|
||||
if (!$raw) {
|
||||
if ($this->includeUncoveredFiles) {
|
||||
$this->addUncoveredFilesFromFilter();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the coverage data.
|
||||
*/
|
||||
public function setData(ProcessedCodeCoverageData $data): void
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, TestType>
|
||||
*/
|
||||
public function getTests(): array
|
||||
{
|
||||
return $this->tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, TestType> $tests
|
||||
*/
|
||||
public function setTests(array $tests): void
|
||||
{
|
||||
$this->tests = $tests;
|
||||
}
|
||||
|
||||
public function start(string $id, ?TestSize $size = null, bool $clear = false): void
|
||||
{
|
||||
if ($clear) {
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
$this->currentId = $id;
|
||||
$this->currentSize = $size;
|
||||
|
||||
$this->driver->start();
|
||||
|
||||
$this->cachedReport = null;
|
||||
}
|
||||
|
||||
public function stop(bool $append = true, ?TestStatus $status = null, null|false|TargetCollection $covers = null, ?TargetCollection $uses = null, float $time = 0.0): RawCodeCoverageData
|
||||
{
|
||||
$data = $this->driver->stop();
|
||||
|
||||
$this->append($data, null, $append, $status, $covers, $uses, $time);
|
||||
|
||||
$this->currentId = null;
|
||||
$this->currentSize = null;
|
||||
$this->cachedReport = null;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
* @throws TestIdMissingException
|
||||
* @throws UnintentionallyCoveredCodeException
|
||||
*/
|
||||
public function append(RawCodeCoverageData $rawData, ?string $id = null, bool $append = true, ?TestStatus $status = null, null|false|TargetCollection $covers = null, ?TargetCollection $uses = null, float $time = 0.0): void
|
||||
{
|
||||
if ($id === null) {
|
||||
$id = $this->currentId;
|
||||
}
|
||||
|
||||
if ($id === null) {
|
||||
throw new TestIdMissingException;
|
||||
}
|
||||
|
||||
if ($status === null) {
|
||||
$status = TestStatus::unknown();
|
||||
}
|
||||
|
||||
if ($covers === null) {
|
||||
$covers = TargetCollection::fromArray([]);
|
||||
}
|
||||
|
||||
if ($uses === null) {
|
||||
$uses = TargetCollection::fromArray([]);
|
||||
}
|
||||
|
||||
$size = $this->currentSize;
|
||||
|
||||
if ($size === null) {
|
||||
$size = TestSize::unknown();
|
||||
}
|
||||
|
||||
$this->cachedReport = null;
|
||||
|
||||
$this->applyFilter($rawData);
|
||||
|
||||
$this->applyExecutableLinesFilter($rawData);
|
||||
|
||||
if ($this->useAnnotationsForIgnoringCode) {
|
||||
$this->applyIgnoredLinesFilter($rawData);
|
||||
}
|
||||
|
||||
$this->data->initializeUnseenData($rawData);
|
||||
|
||||
if (!$append) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($id === self::UNCOVERED_FILES) {
|
||||
return;
|
||||
}
|
||||
|
||||
$linesToBeCovered = false;
|
||||
$linesToBeUsed = [];
|
||||
|
||||
if ($covers !== false) {
|
||||
$linesToBeCovered = $this->targetMapper()->mapTargets($covers);
|
||||
}
|
||||
|
||||
if ($linesToBeCovered !== false) {
|
||||
$linesToBeUsed = $this->targetMapper()->mapTargets($uses);
|
||||
}
|
||||
|
||||
$this->applyCoversAndUsesFilter(
|
||||
$rawData,
|
||||
$linesToBeCovered,
|
||||
$linesToBeUsed,
|
||||
$size,
|
||||
);
|
||||
|
||||
if ($rawData->lineCoverage() === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->tests[$id] = [
|
||||
'size' => $size->asString(),
|
||||
'status' => $status->asString(),
|
||||
'time' => $time,
|
||||
];
|
||||
|
||||
$this->data->markCodeAsExecutedByTestCase($id, $rawData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the data from another instance.
|
||||
*/
|
||||
public function merge(self $that): void
|
||||
{
|
||||
$this->filter->includeFiles(
|
||||
$that->filter()->files(),
|
||||
);
|
||||
|
||||
$this->data->merge($that->data);
|
||||
|
||||
$this->tests = array_merge($this->tests, $that->getTests());
|
||||
|
||||
$this->cachedReport = null;
|
||||
}
|
||||
|
||||
public function enableCheckForUnintentionallyCoveredCode(): void
|
||||
{
|
||||
$this->checkForUnintentionallyCoveredCode = true;
|
||||
}
|
||||
|
||||
public function disableCheckForUnintentionallyCoveredCode(): void
|
||||
{
|
||||
$this->checkForUnintentionallyCoveredCode = false;
|
||||
}
|
||||
|
||||
public function includeUncoveredFiles(): void
|
||||
{
|
||||
$this->includeUncoveredFiles = true;
|
||||
}
|
||||
|
||||
public function excludeUncoveredFiles(): void
|
||||
{
|
||||
$this->includeUncoveredFiles = false;
|
||||
}
|
||||
|
||||
public function enableAnnotationsForIgnoringCode(): void
|
||||
{
|
||||
$this->useAnnotationsForIgnoringCode = true;
|
||||
}
|
||||
|
||||
public function disableAnnotationsForIgnoringCode(): void
|
||||
{
|
||||
$this->useAnnotationsForIgnoringCode = false;
|
||||
}
|
||||
|
||||
public function ignoreDeprecatedCode(): void
|
||||
{
|
||||
$this->ignoreDeprecatedCode = true;
|
||||
}
|
||||
|
||||
public function doNotIgnoreDeprecatedCode(): void
|
||||
{
|
||||
$this->ignoreDeprecatedCode = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-assert-if-true !null $this->cacheDirectory
|
||||
*/
|
||||
public function cachesStaticAnalysis(): bool
|
||||
{
|
||||
return $this->cacheDirectory !== null;
|
||||
}
|
||||
|
||||
public function cacheStaticAnalysis(string $directory): void
|
||||
{
|
||||
$this->cacheDirectory = $directory;
|
||||
}
|
||||
|
||||
public function doNotCacheStaticAnalysis(): void
|
||||
{
|
||||
$this->cacheDirectory = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws StaticAnalysisCacheNotConfiguredException
|
||||
*/
|
||||
public function cacheDirectory(): string
|
||||
{
|
||||
if (!$this->cachesStaticAnalysis()) {
|
||||
throw new StaticAnalysisCacheNotConfiguredException(
|
||||
'The static analysis cache is not configured',
|
||||
);
|
||||
}
|
||||
|
||||
return $this->cacheDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
*/
|
||||
public function excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(string $className): void
|
||||
{
|
||||
$this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck[] = $className;
|
||||
}
|
||||
|
||||
public function enableBranchAndPathCoverage(): void
|
||||
{
|
||||
$this->driver->enableBranchAndPathCoverage();
|
||||
|
||||
$this->collectBranchAndPathCoverage = true;
|
||||
}
|
||||
|
||||
public function disableBranchAndPathCoverage(): void
|
||||
{
|
||||
$this->driver->disableBranchAndPathCoverage();
|
||||
|
||||
$this->collectBranchAndPathCoverage = false;
|
||||
}
|
||||
|
||||
public function collectsBranchAndPathCoverage(): bool
|
||||
{
|
||||
return $this->collectBranchAndPathCoverage;
|
||||
}
|
||||
|
||||
public function validate(TargetCollection $targets): ValidationResult
|
||||
{
|
||||
return (new TargetCollectionValidator)->validate($this->targetMapper(), $targets);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function driverIsPcov(): bool
|
||||
{
|
||||
/** @phpstan-ignore isset.initializedProperty */
|
||||
return isset($this->driver) && $this->driver->isPcov();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function driverIsXdebug(): bool
|
||||
{
|
||||
/** @phpstan-ignore isset.initializedProperty */
|
||||
return isset($this->driver) && $this->driver->isXdebug();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param false|TargetedLines $linesToBeCovered
|
||||
* @param TargetedLines $linesToBeUsed
|
||||
*
|
||||
* @throws ReflectionException
|
||||
* @throws UnintentionallyCoveredCodeException
|
||||
*/
|
||||
private function applyCoversAndUsesFilter(RawCodeCoverageData $rawData, array|false $linesToBeCovered, array $linesToBeUsed, TestSize $size): void
|
||||
{
|
||||
if ($linesToBeCovered === false) {
|
||||
$rawData->clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($linesToBeCovered === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->checkForUnintentionallyCoveredCode && !$size->isMedium() && !$size->isLarge()) {
|
||||
$this->performUnintentionallyCoveredCodeCheck($rawData, $linesToBeCovered, $linesToBeUsed);
|
||||
}
|
||||
|
||||
$rawLineData = $rawData->lineCoverage();
|
||||
$filesWithNoCoverage = array_diff_key($rawLineData, $linesToBeCovered);
|
||||
|
||||
foreach (array_keys($filesWithNoCoverage) as $fileWithNoCoverage) {
|
||||
$rawData->removeCoverageDataForFile($fileWithNoCoverage);
|
||||
}
|
||||
|
||||
foreach ($linesToBeCovered as $fileToBeCovered => $includedLines) {
|
||||
$rawData->keepLineCoverageDataOnlyForLines($fileToBeCovered, $includedLines);
|
||||
$rawData->keepFunctionCoverageDataOnlyForLines($fileToBeCovered, $includedLines);
|
||||
}
|
||||
}
|
||||
|
||||
private function applyFilter(RawCodeCoverageData $data): void
|
||||
{
|
||||
if (!$this->filter->isEmpty()) {
|
||||
foreach (array_keys($data->lineCoverage()) as $filename) {
|
||||
if ($this->filter->isExcluded($filename)) {
|
||||
$data->removeCoverageDataForFile($filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data->skipEmptyLines();
|
||||
}
|
||||
|
||||
private function applyExecutableLinesFilter(RawCodeCoverageData $data): void
|
||||
{
|
||||
foreach (array_keys($data->lineCoverage()) as $filename) {
|
||||
if (!$this->filter->isFile($filename)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$linesToBranchMap = $this->analyser()->analyse($filename)->executableLines();
|
||||
|
||||
$data->keepLineCoverageDataOnlyForLines(
|
||||
$filename,
|
||||
array_keys($linesToBranchMap),
|
||||
);
|
||||
|
||||
$data->markExecutableLineByBranch(
|
||||
$filename,
|
||||
$linesToBranchMap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function applyIgnoredLinesFilter(RawCodeCoverageData $data): void
|
||||
{
|
||||
foreach (array_keys($data->lineCoverage()) as $filename) {
|
||||
if (!$this->filter->isFile($filename)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data->removeCoverageDataForLines(
|
||||
$filename,
|
||||
$this->analyser()->analyse($filename)->ignoredLines(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws UnintentionallyCoveredCodeException
|
||||
*/
|
||||
private function addUncoveredFilesFromFilter(): void
|
||||
{
|
||||
$uncoveredFiles = array_diff(
|
||||
$this->filter->files(),
|
||||
$this->data->coveredFiles(),
|
||||
);
|
||||
|
||||
foreach ($uncoveredFiles as $uncoveredFile) {
|
||||
if (is_file($uncoveredFile)) {
|
||||
$this->append(
|
||||
RawCodeCoverageData::fromUncoveredFile(
|
||||
$uncoveredFile,
|
||||
$this->analyser(),
|
||||
),
|
||||
self::UNCOVERED_FILES,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TargetedLines $linesToBeCovered
|
||||
* @param TargetedLines $linesToBeUsed
|
||||
*
|
||||
* @throws ReflectionException
|
||||
* @throws UnintentionallyCoveredCodeException
|
||||
*/
|
||||
private function performUnintentionallyCoveredCodeCheck(RawCodeCoverageData $data, array $linesToBeCovered, array $linesToBeUsed): void
|
||||
{
|
||||
$allowedLines = $this->getAllowedLines(
|
||||
$linesToBeCovered,
|
||||
$linesToBeUsed,
|
||||
);
|
||||
|
||||
$unintentionallyCoveredUnits = [];
|
||||
|
||||
foreach ($data->lineCoverage() as $file => $_data) {
|
||||
foreach ($_data as $line => $flag) {
|
||||
if ($flag === 1 && !isset($allowedLines[$file][$line])) {
|
||||
$unintentionallyCoveredUnits[] = $this->targetMapper->lookup($file, $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$unintentionallyCoveredUnits = $this->processUnintentionallyCoveredUnits($unintentionallyCoveredUnits);
|
||||
|
||||
if ($unintentionallyCoveredUnits !== []) {
|
||||
throw new UnintentionallyCoveredCodeException(
|
||||
$unintentionallyCoveredUnits,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TargetedLines $linesToBeCovered
|
||||
* @param TargetedLines $linesToBeUsed
|
||||
*
|
||||
* @return TargetedLines
|
||||
*/
|
||||
private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed): array
|
||||
{
|
||||
$allowedLines = [];
|
||||
|
||||
foreach (array_keys($linesToBeCovered) as $file) {
|
||||
if (!isset($allowedLines[$file])) {
|
||||
$allowedLines[$file] = [];
|
||||
}
|
||||
|
||||
$allowedLines[$file] = array_merge(
|
||||
$allowedLines[$file],
|
||||
$linesToBeCovered[$file],
|
||||
);
|
||||
}
|
||||
|
||||
foreach (array_keys($linesToBeUsed) as $file) {
|
||||
if (!isset($allowedLines[$file])) {
|
||||
$allowedLines[$file] = [];
|
||||
}
|
||||
|
||||
$allowedLines[$file] = array_merge(
|
||||
$allowedLines[$file],
|
||||
$linesToBeUsed[$file],
|
||||
);
|
||||
}
|
||||
|
||||
foreach (array_keys($allowedLines) as $file) {
|
||||
$allowedLines[$file] = array_flip(
|
||||
array_unique($allowedLines[$file]),
|
||||
);
|
||||
}
|
||||
|
||||
return $allowedLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $unintentionallyCoveredUnits
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
private function processUnintentionallyCoveredUnits(array $unintentionallyCoveredUnits): array
|
||||
{
|
||||
$unintentionallyCoveredUnits = array_unique($unintentionallyCoveredUnits);
|
||||
$processed = [];
|
||||
|
||||
foreach ($unintentionallyCoveredUnits as $unintentionallyCoveredUnit) {
|
||||
$tmp = explode('::', $unintentionallyCoveredUnit);
|
||||
|
||||
if (count($tmp) !== 2) {
|
||||
$processed[] = $unintentionallyCoveredUnit;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$class = new ReflectionClass($tmp[0]);
|
||||
|
||||
foreach ($this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck as $parentClass) {
|
||||
if ($class->isSubclassOf($parentClass)) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new ReflectionException(
|
||||
$e->getMessage(),
|
||||
$e->getCode(),
|
||||
$e,
|
||||
);
|
||||
}
|
||||
|
||||
$processed[] = $tmp[0];
|
||||
}
|
||||
|
||||
$processed = array_unique($processed);
|
||||
|
||||
sort($processed);
|
||||
|
||||
return $processed;
|
||||
}
|
||||
|
||||
private function targetMapper(): Mapper
|
||||
{
|
||||
if ($this->targetMapper !== null) {
|
||||
return $this->targetMapper;
|
||||
}
|
||||
|
||||
$this->targetMapper = new Mapper(
|
||||
(new MapBuilder)->build($this->filter, $this->analyser()),
|
||||
);
|
||||
|
||||
return $this->targetMapper;
|
||||
}
|
||||
|
||||
private function analyser(): FileAnalyser
|
||||
{
|
||||
if ($this->analyser !== null) {
|
||||
return $this->analyser;
|
||||
}
|
||||
|
||||
$sourceAnalyser = new ParsingSourceAnalyser;
|
||||
|
||||
if ($this->cachesStaticAnalysis()) {
|
||||
$sourceAnalyser = new CachingSourceAnalyser(
|
||||
$this->cacheDirectory,
|
||||
$sourceAnalyser,
|
||||
);
|
||||
}
|
||||
|
||||
$this->analyser = new FileAnalyser(
|
||||
$sourceAnalyser,
|
||||
$this->useAnnotationsForIgnoringCode,
|
||||
$this->ignoreDeprecatedCode,
|
||||
);
|
||||
|
||||
return $this->analyser;
|
||||
}
|
||||
}
|
||||
103
vendor/phpunit/php-code-coverage/src/Data/ProcessedBranchCoverageData.php
vendored
Normal file
103
vendor/phpunit/php-code-coverage/src/Data/ProcessedBranchCoverageData.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?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_merge;
|
||||
use function array_unique;
|
||||
use NoDiscard;
|
||||
use SebastianBergmann\CodeCoverage\Driver\XdebugDriver;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @phpstan-import-type TestIdType from ProcessedCodeCoverageData
|
||||
* @phpstan-import-type XdebugBranchCoverageType from XdebugDriver
|
||||
*/
|
||||
final class ProcessedBranchCoverageData
|
||||
{
|
||||
public readonly int $op_start;
|
||||
public readonly int $op_end;
|
||||
public readonly int $line_start;
|
||||
public readonly int $line_end;
|
||||
|
||||
/** @var list<TestIdType> */
|
||||
public array $hit;
|
||||
|
||||
/** @var array<int, int> */
|
||||
public readonly array $out;
|
||||
|
||||
/** @var array<int, int> */
|
||||
public readonly array $out_hit;
|
||||
|
||||
/**
|
||||
* @param XdebugBranchCoverageType $xdebugCoverageData
|
||||
*/
|
||||
public static function fromXdebugCoverage(array $xdebugCoverageData): self
|
||||
{
|
||||
return new self(
|
||||
$xdebugCoverageData['op_start'],
|
||||
$xdebugCoverageData['op_end'],
|
||||
$xdebugCoverageData['line_start'],
|
||||
$xdebugCoverageData['line_end'],
|
||||
[],
|
||||
$xdebugCoverageData['out'],
|
||||
$xdebugCoverageData['out_hit'],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<TestIdType> $hit
|
||||
* @param array<int, int> $out
|
||||
* @param array<int, int> $out_hit
|
||||
*/
|
||||
public function __construct(
|
||||
int $op_start,
|
||||
int $op_end,
|
||||
int $line_start,
|
||||
int $line_end,
|
||||
array $hit,
|
||||
array $out,
|
||||
array $out_hit,
|
||||
) {
|
||||
$this->out_hit = $out_hit;
|
||||
$this->out = $out;
|
||||
$this->hit = $hit;
|
||||
$this->line_end = $line_end;
|
||||
$this->line_start = $line_start;
|
||||
$this->op_end = $op_end;
|
||||
$this->op_start = $op_start;
|
||||
}
|
||||
|
||||
#[NoDiscard]
|
||||
public function merge(self $data): self
|
||||
{
|
||||
if ($data->hit === []) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return new self(
|
||||
$this->op_start,
|
||||
$this->op_end,
|
||||
$this->line_start,
|
||||
$this->line_end,
|
||||
array_unique(array_merge($this->hit, $data->hit)),
|
||||
$this->out,
|
||||
$this->out_hit,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TestIdType $testCaseId
|
||||
*/
|
||||
public function recordHit(string $testCaseId): void
|
||||
{
|
||||
$this->hit[] = $testCaseId;
|
||||
}
|
||||
}
|
||||
70
vendor/phpunit/php-code-coverage/src/Data/ProcessedClassType.php
vendored
Normal file
70
vendor/phpunit/php-code-coverage/src/Data/ProcessedClassType.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class ProcessedClassType
|
||||
{
|
||||
public readonly string $className;
|
||||
public readonly string $namespace;
|
||||
|
||||
/**
|
||||
* @var array<string, ProcessedMethodType>
|
||||
*/
|
||||
public array $methods;
|
||||
public readonly int $startLine;
|
||||
public int $executableLines;
|
||||
public int $executedLines;
|
||||
public int $executableBranches;
|
||||
public int $executedBranches;
|
||||
public int $executablePaths;
|
||||
public int $executedPaths;
|
||||
public int $ccn;
|
||||
public float|int $coverage;
|
||||
public int|string $crap;
|
||||
public readonly string $link;
|
||||
|
||||
public function __construct(
|
||||
string $className,
|
||||
string $namespace,
|
||||
/**
|
||||
* @var array<string, ProcessedMethodType>
|
||||
*/
|
||||
array $methods,
|
||||
int $startLine,
|
||||
int $executableLines,
|
||||
int $executedLines,
|
||||
int $executableBranches,
|
||||
int $executedBranches,
|
||||
int $executablePaths,
|
||||
int $executedPaths,
|
||||
int $ccn,
|
||||
float|int $coverage,
|
||||
int|string $crap,
|
||||
string $link,
|
||||
) {
|
||||
$this->className = $className;
|
||||
$this->namespace = $namespace;
|
||||
$this->methods = $methods;
|
||||
$this->startLine = $startLine;
|
||||
$this->executableLines = $executableLines;
|
||||
$this->executedLines = $executedLines;
|
||||
$this->executableBranches = $executableBranches;
|
||||
$this->executedBranches = $executedBranches;
|
||||
$this->executablePaths = $executablePaths;
|
||||
$this->executedPaths = $executedPaths;
|
||||
$this->ccn = $ccn;
|
||||
$this->coverage = $coverage;
|
||||
$this->crap = $crap;
|
||||
$this->link = $link;
|
||||
}
|
||||
}
|
||||
265
vendor/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php
vendored
Normal file
265
vendor/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
<?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_key_exists;
|
||||
use function array_keys;
|
||||
use function array_merge;
|
||||
use function array_unique;
|
||||
use function count;
|
||||
use function is_array;
|
||||
use function ksort;
|
||||
use SebastianBergmann\CodeCoverage\Driver\Driver;
|
||||
use SebastianBergmann\CodeCoverage\Driver\XdebugDriver;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @phpstan-import-type XdebugFunctionCoverageType from XdebugDriver
|
||||
*
|
||||
* @phpstan-type TestIdType string
|
||||
* @phpstan-type FunctionCoverageType array<string, array<string, ProcessedFunctionCoverageData>>
|
||||
* @phpstan-type LineCoverageType array<string, array<int, null|list<TestIdType>>>
|
||||
*/
|
||||
final class ProcessedCodeCoverageData
|
||||
{
|
||||
/**
|
||||
* Line coverage data.
|
||||
* An array of filenames, each having an array of linenumbers, each executable line having an array of testcase ids.
|
||||
*
|
||||
* @var LineCoverageType
|
||||
*/
|
||||
private array $lineCoverage = [];
|
||||
|
||||
/**
|
||||
* Function coverage data.
|
||||
* Maintains base format of raw data (@see https://xdebug.org/docs/code_coverage), but each 'hit' entry is an array
|
||||
* of testcase ids.
|
||||
*
|
||||
* @var FunctionCoverageType
|
||||
*/
|
||||
private array $functionCoverage = [];
|
||||
|
||||
public function initializeUnseenData(RawCodeCoverageData $rawData): void
|
||||
{
|
||||
foreach ($rawData->lineCoverage() as $file => $lines) {
|
||||
if (!isset($this->lineCoverage[$file])) {
|
||||
$this->lineCoverage[$file] = [];
|
||||
|
||||
foreach ($lines as $k => $v) {
|
||||
$this->lineCoverage[$file][$k] = $v === Driver::LINE_NOT_EXECUTABLE ? null : [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($rawData->functionCoverage() as $file => $functions) {
|
||||
foreach ($functions as $functionName => $functionData) {
|
||||
if (isset($this->functionCoverage[$file][$functionName])) {
|
||||
$this->initPreviouslySeenFunction($file, $functionName, $functionData);
|
||||
} else {
|
||||
$this->initPreviouslyUnseenFunction($file, $functionName, $functionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function markCodeAsExecutedByTestCase(string $testCaseId, RawCodeCoverageData $executedCode): void
|
||||
{
|
||||
foreach ($executedCode->lineCoverage() as $file => $lines) {
|
||||
foreach ($lines as $k => $v) {
|
||||
if ($v === Driver::LINE_EXECUTED) {
|
||||
$this->lineCoverage[$file][$k][] = $testCaseId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($executedCode->functionCoverage() as $file => $functions) {
|
||||
foreach ($functions as $functionName => $functionData) {
|
||||
foreach ($functionData['branches'] as $branchId => $branchData) {
|
||||
if ($branchData['hit'] === Driver::BRANCH_HIT) {
|
||||
$this->functionCoverage[$file][$functionName]->recordBranchHit($branchId, $testCaseId);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($functionData['paths'] as $pathId => $pathData) {
|
||||
if ($pathData['hit'] === Driver::BRANCH_HIT) {
|
||||
$this->functionCoverage[$file][$functionName]->recordPathHit($pathId, $testCaseId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LineCoverageType $lineCoverage
|
||||
*/
|
||||
public function setLineCoverage(array $lineCoverage): void
|
||||
{
|
||||
$this->lineCoverage = $lineCoverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LineCoverageType
|
||||
*/
|
||||
public function lineCoverage(): array
|
||||
{
|
||||
ksort($this->lineCoverage);
|
||||
|
||||
return $this->lineCoverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FunctionCoverageType $functionCoverage
|
||||
*/
|
||||
public function setFunctionCoverage(array $functionCoverage): void
|
||||
{
|
||||
$this->functionCoverage = $functionCoverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FunctionCoverageType
|
||||
*/
|
||||
public function functionCoverage(): array
|
||||
{
|
||||
ksort($this->functionCoverage);
|
||||
|
||||
return $this->functionCoverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public function coveredFiles(): array
|
||||
{
|
||||
ksort($this->lineCoverage);
|
||||
|
||||
return array_keys($this->lineCoverage);
|
||||
}
|
||||
|
||||
public function renameFile(string $oldFile, string $newFile): void
|
||||
{
|
||||
$this->lineCoverage[$newFile] = $this->lineCoverage[$oldFile];
|
||||
|
||||
if (isset($this->functionCoverage[$oldFile])) {
|
||||
$this->functionCoverage[$newFile] = $this->functionCoverage[$oldFile];
|
||||
}
|
||||
|
||||
unset($this->lineCoverage[$oldFile], $this->functionCoverage[$oldFile]);
|
||||
}
|
||||
|
||||
public function merge(self $newData): void
|
||||
{
|
||||
foreach ($newData->lineCoverage as $file => $lines) {
|
||||
if (!isset($this->lineCoverage[$file])) {
|
||||
$this->lineCoverage[$file] = $lines;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// we should compare the lines if any of two contains data
|
||||
$compareLineNumbers = array_unique(
|
||||
array_merge(
|
||||
array_keys($this->lineCoverage[$file]),
|
||||
array_keys($newData->lineCoverage[$file]),
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($compareLineNumbers as $line) {
|
||||
$thatPriority = $this->priorityForLine($newData->lineCoverage[$file], $line);
|
||||
$thisPriority = $this->priorityForLine($this->lineCoverage[$file], $line);
|
||||
|
||||
if ($thatPriority > $thisPriority) {
|
||||
$this->lineCoverage[$file][$line] = $newData->lineCoverage[$file][$line];
|
||||
} elseif ($thatPriority === $thisPriority && is_array($this->lineCoverage[$file][$line])) {
|
||||
$this->lineCoverage[$file][$line] = array_unique(
|
||||
array_merge($this->lineCoverage[$file][$line], $newData->lineCoverage[$file][$line]),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($newData->functionCoverage as $file => $functions) {
|
||||
if (!isset($this->functionCoverage[$file])) {
|
||||
$this->functionCoverage[$file] = $functions;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($functions as $functionName => $functionData) {
|
||||
if (isset($this->functionCoverage[$file][$functionName])) {
|
||||
$this->initPreviouslySeenFunction($file, $functionName, $functionData);
|
||||
} else {
|
||||
$this->initPreviouslyUnseenFunction($file, $functionName, $functionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the priority for a line.
|
||||
*
|
||||
* 1 = the line is not set
|
||||
* 2 = the line has not been tested
|
||||
* 3 = the line is dead code
|
||||
* 4 = the line has been tested
|
||||
*
|
||||
* During a merge, a higher number is better.
|
||||
*
|
||||
* @return 1|2|3|4
|
||||
*/
|
||||
private function priorityForLine(array $data, int $line): int
|
||||
{
|
||||
if (!array_key_exists($line, $data)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (is_array($data[$line]) && count($data[$line]) === 0) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if ($data[$line] === null) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a function we have never seen before, copy all data over and simply init the 'hit' array.
|
||||
*
|
||||
* @param ProcessedFunctionCoverageData|XdebugFunctionCoverageType $functionData
|
||||
*/
|
||||
private function initPreviouslyUnseenFunction(string $file, string $functionName, array|ProcessedFunctionCoverageData $functionData): void
|
||||
{
|
||||
if (is_array($functionData)) {
|
||||
$functionData = ProcessedFunctionCoverageData::fromXdebugCoverage($functionData);
|
||||
}
|
||||
|
||||
$this->functionCoverage[$file][$functionName] = $functionData;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a function we have seen before, only copy over and init the 'hit' array for any unseen branches and paths.
|
||||
* Techniques such as mocking and where the contents of a file are different vary during tests (e.g. compiling
|
||||
* containers) mean that the functions inside a file cannot be relied upon to be static.
|
||||
*
|
||||
* @param ProcessedFunctionCoverageData|XdebugFunctionCoverageType $functionData
|
||||
*/
|
||||
private function initPreviouslySeenFunction(string $file, string $functionName, array|ProcessedFunctionCoverageData $functionData): void
|
||||
{
|
||||
if (is_array($functionData)) {
|
||||
$functionData = ProcessedFunctionCoverageData::fromXdebugCoverage($functionData);
|
||||
}
|
||||
|
||||
$this->functionCoverage[$file][$functionName] = $this->functionCoverage[$file][$functionName]->merge(
|
||||
$functionData,
|
||||
);
|
||||
}
|
||||
}
|
||||
119
vendor/phpunit/php-code-coverage/src/Data/ProcessedFunctionCoverageData.php
vendored
Normal file
119
vendor/phpunit/php-code-coverage/src/Data/ProcessedFunctionCoverageData.php
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
<?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 NoDiscard;
|
||||
use SebastianBergmann\CodeCoverage\Driver\XdebugDriver;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @phpstan-import-type TestIdType from ProcessedCodeCoverageData
|
||||
* @phpstan-import-type XdebugFunctionCoverageType from XdebugDriver
|
||||
*/
|
||||
final readonly class ProcessedFunctionCoverageData
|
||||
{
|
||||
/** @var array<int, ProcessedBranchCoverageData> */
|
||||
public array $branches;
|
||||
|
||||
/** @var array<int, ProcessedPathCoverageData> */
|
||||
public array $paths;
|
||||
|
||||
/**
|
||||
* @param XdebugFunctionCoverageType $xdebugCoverageData
|
||||
*/
|
||||
public static function fromXdebugCoverage(array $xdebugCoverageData): self
|
||||
{
|
||||
$branches = [];
|
||||
|
||||
foreach ($xdebugCoverageData['branches'] as $branchId => $branch) {
|
||||
$branches[$branchId] = ProcessedBranchCoverageData::fromXdebugCoverage($branch);
|
||||
}
|
||||
$paths = [];
|
||||
|
||||
foreach ($xdebugCoverageData['paths'] as $pathId => $path) {
|
||||
$paths[$pathId] = ProcessedPathCoverageData::fromXdebugCoverage($path);
|
||||
}
|
||||
|
||||
return new self(
|
||||
$branches,
|
||||
$paths,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, ProcessedBranchCoverageData> $branches
|
||||
* @param array<int, ProcessedPathCoverageData> $paths
|
||||
*/
|
||||
public function __construct(
|
||||
array $branches,
|
||||
array $paths,
|
||||
) {
|
||||
$this->paths = $paths;
|
||||
$this->branches = $branches;
|
||||
}
|
||||
|
||||
#[NoDiscard]
|
||||
public function merge(self $data): self
|
||||
{
|
||||
$branches = null;
|
||||
|
||||
if ($data->branches !== $this->branches) {
|
||||
$branches = $this->branches;
|
||||
|
||||
foreach ($data->branches as $branchId => $branch) {
|
||||
if (!isset($branches[$branchId])) {
|
||||
$branches[$branchId] = $branch;
|
||||
} else {
|
||||
$branches[$branchId] = $branches[$branchId]->merge($branch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$paths = null;
|
||||
|
||||
if ($data->paths !== $this->paths) {
|
||||
$paths = $this->paths;
|
||||
|
||||
foreach ($data->paths as $pathId => $path) {
|
||||
if (!isset($paths[$pathId])) {
|
||||
$paths[$pathId] = $path;
|
||||
} else {
|
||||
$paths[$pathId] = $paths[$pathId]->merge($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($branches === null && $paths === null) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return new self(
|
||||
$branches ?? $this->branches,
|
||||
$paths ?? $this->paths,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TestIdType $testCaseId
|
||||
*/
|
||||
public function recordBranchHit(int $branchId, string $testCaseId): void
|
||||
{
|
||||
$this->branches[$branchId]->recordHit($testCaseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TestIdType $testCaseId
|
||||
*/
|
||||
public function recordPathHit(int $pathId, string $testCaseId): void
|
||||
{
|
||||
$this->paths[$pathId]->recordHit($testCaseId);
|
||||
}
|
||||
}
|
||||
66
vendor/phpunit/php-code-coverage/src/Data/ProcessedFunctionType.php
vendored
Normal file
66
vendor/phpunit/php-code-coverage/src/Data/ProcessedFunctionType.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class ProcessedFunctionType
|
||||
{
|
||||
public readonly string $functionName;
|
||||
public readonly string $namespace;
|
||||
public readonly string $signature;
|
||||
public readonly int $startLine;
|
||||
public readonly int $endLine;
|
||||
public int $executableLines;
|
||||
public int $executedLines;
|
||||
public int $executableBranches;
|
||||
public int $executedBranches;
|
||||
public int $executablePaths;
|
||||
public int $executedPaths;
|
||||
public int $ccn;
|
||||
public float|int $coverage;
|
||||
public int|string $crap;
|
||||
public readonly string $link;
|
||||
|
||||
public function __construct(
|
||||
string $functionName,
|
||||
string $namespace,
|
||||
string $signature,
|
||||
int $startLine,
|
||||
int $endLine,
|
||||
int $executableLines,
|
||||
int $executedLines,
|
||||
int $executableBranches,
|
||||
int $executedBranches,
|
||||
int $executablePaths,
|
||||
int $executedPaths,
|
||||
int $ccn,
|
||||
float|int $coverage,
|
||||
int|string $crap,
|
||||
string $link,
|
||||
) {
|
||||
$this->link = $link;
|
||||
$this->crap = $crap;
|
||||
$this->coverage = $coverage;
|
||||
$this->ccn = $ccn;
|
||||
$this->executedPaths = $executedPaths;
|
||||
$this->executablePaths = $executablePaths;
|
||||
$this->executedBranches = $executedBranches;
|
||||
$this->executableBranches = $executableBranches;
|
||||
$this->executedLines = $executedLines;
|
||||
$this->executableLines = $executableLines;
|
||||
$this->endLine = $endLine;
|
||||
$this->startLine = $startLine;
|
||||
$this->signature = $signature;
|
||||
$this->namespace = $namespace;
|
||||
$this->functionName = $functionName;
|
||||
}
|
||||
}
|
||||
66
vendor/phpunit/php-code-coverage/src/Data/ProcessedMethodType.php
vendored
Normal file
66
vendor/phpunit/php-code-coverage/src/Data/ProcessedMethodType.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class ProcessedMethodType
|
||||
{
|
||||
public readonly string $methodName;
|
||||
public readonly string $visibility;
|
||||
public readonly string $signature;
|
||||
public readonly int $startLine;
|
||||
public readonly int $endLine;
|
||||
public int $executableLines;
|
||||
public int $executedLines;
|
||||
public int $executableBranches;
|
||||
public int $executedBranches;
|
||||
public int $executablePaths;
|
||||
public int $executedPaths;
|
||||
public int $ccn;
|
||||
public float|int $coverage;
|
||||
public int|string $crap;
|
||||
public readonly string $link;
|
||||
|
||||
public function __construct(
|
||||
string $methodName,
|
||||
string $visibility,
|
||||
string $signature,
|
||||
int $startLine,
|
||||
int $endLine,
|
||||
int $executableLines,
|
||||
int $executedLines,
|
||||
int $executableBranches,
|
||||
int $executedBranches,
|
||||
int $executablePaths,
|
||||
int $executedPaths,
|
||||
int $ccn,
|
||||
float|int $coverage,
|
||||
int|string $crap,
|
||||
string $link,
|
||||
) {
|
||||
$this->link = $link;
|
||||
$this->crap = $crap;
|
||||
$this->coverage = $coverage;
|
||||
$this->ccn = $ccn;
|
||||
$this->executedPaths = $executedPaths;
|
||||
$this->executablePaths = $executablePaths;
|
||||
$this->executedBranches = $executedBranches;
|
||||
$this->executableBranches = $executableBranches;
|
||||
$this->executedLines = $executedLines;
|
||||
$this->executableLines = $executableLines;
|
||||
$this->endLine = $endLine;
|
||||
$this->startLine = $startLine;
|
||||
$this->signature = $signature;
|
||||
$this->visibility = $visibility;
|
||||
$this->methodName = $methodName;
|
||||
}
|
||||
}
|
||||
74
vendor/phpunit/php-code-coverage/src/Data/ProcessedPathCoverageData.php
vendored
Normal file
74
vendor/phpunit/php-code-coverage/src/Data/ProcessedPathCoverageData.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?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_merge;
|
||||
use function array_unique;
|
||||
use NoDiscard;
|
||||
use SebastianBergmann\CodeCoverage\Driver\XdebugDriver;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @phpstan-import-type TestIdType from ProcessedCodeCoverageData
|
||||
* @phpstan-import-type XdebugPathCoverageType from XdebugDriver
|
||||
*/
|
||||
final class ProcessedPathCoverageData
|
||||
{
|
||||
/** @var array<int, int> */
|
||||
public readonly array $path;
|
||||
|
||||
/** @var list<TestIdType> */
|
||||
public array $hit;
|
||||
|
||||
/**
|
||||
* @param XdebugPathCoverageType $xdebugCoverageData
|
||||
*/
|
||||
public static function fromXdebugCoverage(array $xdebugCoverageData): self
|
||||
{
|
||||
return new self(
|
||||
$xdebugCoverageData['path'],
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, int> $path
|
||||
* @param list<TestIdType> $hit
|
||||
*/
|
||||
public function __construct(
|
||||
array $path,
|
||||
array $hit,
|
||||
) {
|
||||
$this->hit = $hit;
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
#[NoDiscard]
|
||||
public function merge(self $data): self
|
||||
{
|
||||
if ($data->hit === []) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return new self(
|
||||
$this->path,
|
||||
array_unique(array_merge($this->hit, $data->hit)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TestIdType $testCaseId
|
||||
*/
|
||||
public function recordHit(string $testCaseId): void
|
||||
{
|
||||
$this->hit[] = $testCaseId;
|
||||
}
|
||||
}
|
||||
70
vendor/phpunit/php-code-coverage/src/Data/ProcessedTraitType.php
vendored
Normal file
70
vendor/phpunit/php-code-coverage/src/Data/ProcessedTraitType.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class ProcessedTraitType
|
||||
{
|
||||
public readonly string $traitName;
|
||||
public readonly string $namespace;
|
||||
|
||||
/**
|
||||
* @var array<string, ProcessedMethodType>
|
||||
*/
|
||||
public array $methods;
|
||||
public readonly int $startLine;
|
||||
public int $executableLines;
|
||||
public int $executedLines;
|
||||
public int $executableBranches;
|
||||
public int $executedBranches;
|
||||
public int $executablePaths;
|
||||
public int $executedPaths;
|
||||
public int $ccn;
|
||||
public float|int $coverage;
|
||||
public int|string $crap;
|
||||
public readonly string $link;
|
||||
|
||||
public function __construct(
|
||||
string $traitName,
|
||||
string $namespace,
|
||||
/**
|
||||
* @var array<string, ProcessedMethodType>
|
||||
*/
|
||||
array $methods,
|
||||
int $startLine,
|
||||
int $executableLines,
|
||||
int $executedLines,
|
||||
int $executableBranches,
|
||||
int $executedBranches,
|
||||
int $executablePaths,
|
||||
int $executedPaths,
|
||||
int $ccn,
|
||||
float|int $coverage,
|
||||
int|string $crap,
|
||||
string $link,
|
||||
) {
|
||||
$this->link = $link;
|
||||
$this->crap = $crap;
|
||||
$this->coverage = $coverage;
|
||||
$this->ccn = $ccn;
|
||||
$this->executedPaths = $executedPaths;
|
||||
$this->executablePaths = $executablePaths;
|
||||
$this->executedBranches = $executedBranches;
|
||||
$this->executableBranches = $executableBranches;
|
||||
$this->executedLines = $executedLines;
|
||||
$this->executableLines = $executableLines;
|
||||
$this->startLine = $startLine;
|
||||
$this->methods = $methods;
|
||||
$this->namespace = $namespace;
|
||||
$this->traitName = $traitName;
|
||||
}
|
||||
}
|
||||
283
vendor/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php
vendored
Normal file
283
vendor/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
<?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 array_map;
|
||||
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\Driver\XdebugDriver;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @phpstan-import-type XdebugFunctionsCoverageType from XdebugDriver
|
||||
* @phpstan-import-type XdebugCodeCoverageWithoutPathCoverageType from XdebugDriver
|
||||
* @phpstan-import-type XdebugCodeCoverageWithPathCoverageType from XdebugDriver
|
||||
*/
|
||||
final class RawCodeCoverageData
|
||||
{
|
||||
/**
|
||||
* @var array<string, array<int>>
|
||||
*/
|
||||
private static array $emptyLineCache = [];
|
||||
|
||||
/**
|
||||
* @var XdebugCodeCoverageWithoutPathCoverageType
|
||||
*/
|
||||
private array $lineCoverage;
|
||||
|
||||
/**
|
||||
* @var array<string, XdebugFunctionsCoverageType>
|
||||
*/
|
||||
private array $functionCoverage;
|
||||
|
||||
/**
|
||||
* @param XdebugCodeCoverageWithoutPathCoverageType $rawCoverage
|
||||
*/
|
||||
public static function fromXdebugWithoutPathCoverage(array $rawCoverage): self
|
||||
{
|
||||
return new self($rawCoverage, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 = array_map(
|
||||
static fn (): int => Driver::LINE_NOT_EXECUTED,
|
||||
$analyser->analyse($filename)->executableLines(),
|
||||
);
|
||||
|
||||
return new self([$filename => $lineCoverage], []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param XdebugCodeCoverageWithoutPathCoverageType $lineCoverage
|
||||
* @param array<string, XdebugFunctionsCoverageType> $functionCoverage
|
||||
*/
|
||||
private function __construct(array $lineCoverage, array $functionCoverage)
|
||||
{
|
||||
$this->lineCoverage = $lineCoverage;
|
||||
$this->functionCoverage = $functionCoverage;
|
||||
}
|
||||
|
||||
public function clear(): void
|
||||
{
|
||||
$this->lineCoverage = $this->functionCoverage = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return XdebugCodeCoverageWithoutPathCoverageType
|
||||
*/
|
||||
public function lineCoverage(): array
|
||||
{
|
||||
return $this->lineCoverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 ($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
|
||||
*/
|
||||
public function skipEmptyLines(): void
|
||||
{
|
||||
foreach ($this->lineCoverage as $filename => $coverage) {
|
||||
foreach ($this->getEmptyLinesForFile($filename) as $emptyLine) {
|
||||
unset($this->lineCoverage[$filename][$emptyLine]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int>
|
||||
*/
|
||||
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];
|
||||
}
|
||||
}
|
||||
94
vendor/phpunit/php-code-coverage/src/Driver/Driver.php
vendored
Normal file
94
vendor/phpunit/php-code-coverage/src/Driver/Driver.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<?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\Driver;
|
||||
|
||||
use function sprintf;
|
||||
use SebastianBergmann\CodeCoverage\BranchAndPathCoverageNotSupportedException;
|
||||
use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
abstract class Driver
|
||||
{
|
||||
/**
|
||||
* @see http://xdebug.org/docs/code_coverage
|
||||
*/
|
||||
public const int LINE_NOT_EXECUTABLE = -2;
|
||||
|
||||
/**
|
||||
* @see http://xdebug.org/docs/code_coverage
|
||||
*/
|
||||
public const int LINE_NOT_EXECUTED = -1;
|
||||
|
||||
/**
|
||||
* @see http://xdebug.org/docs/code_coverage
|
||||
*/
|
||||
public const int LINE_EXECUTED = 1;
|
||||
|
||||
/**
|
||||
* @see http://xdebug.org/docs/code_coverage
|
||||
*/
|
||||
public const int BRANCH_NOT_HIT = 0;
|
||||
|
||||
/**
|
||||
* @see http://xdebug.org/docs/code_coverage
|
||||
*/
|
||||
public const int BRANCH_HIT = 1;
|
||||
private bool $collectBranchAndPathCoverage = false;
|
||||
|
||||
public function canCollectBranchAndPathCoverage(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function collectsBranchAndPathCoverage(): bool
|
||||
{
|
||||
return $this->collectBranchAndPathCoverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws BranchAndPathCoverageNotSupportedException
|
||||
*/
|
||||
public function enableBranchAndPathCoverage(): void
|
||||
{
|
||||
if (!$this->canCollectBranchAndPathCoverage()) {
|
||||
throw new BranchAndPathCoverageNotSupportedException(
|
||||
sprintf(
|
||||
'%s does not support branch and path coverage',
|
||||
$this->nameAndVersion(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$this->collectBranchAndPathCoverage = true;
|
||||
}
|
||||
|
||||
public function disableBranchAndPathCoverage(): void
|
||||
{
|
||||
$this->collectBranchAndPathCoverage = false;
|
||||
}
|
||||
|
||||
public function isPcov(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isXdebug(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
abstract public function nameAndVersion(): string;
|
||||
|
||||
abstract public function start(): void;
|
||||
|
||||
abstract public function stop(): RawCodeCoverageData;
|
||||
}
|
||||
90
vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php
vendored
Normal file
90
vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?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\Driver;
|
||||
|
||||
use const pcov\inclusive;
|
||||
use function array_intersect;
|
||||
use function extension_loaded;
|
||||
use function pcov\clear;
|
||||
use function pcov\collect;
|
||||
use function pcov\start;
|
||||
use function pcov\stop;
|
||||
use function pcov\waiting;
|
||||
use function phpversion;
|
||||
use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData;
|
||||
use SebastianBergmann\CodeCoverage\Filter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class PcovDriver extends Driver
|
||||
{
|
||||
private readonly Filter $filter;
|
||||
|
||||
/**
|
||||
* @throws PcovNotAvailableException
|
||||
*/
|
||||
public function __construct(Filter $filter)
|
||||
{
|
||||
$this->ensurePcovIsAvailable();
|
||||
|
||||
$this->filter = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function start(): void
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
public function stop(): RawCodeCoverageData
|
||||
{
|
||||
stop();
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
$filesToCollectCoverageFor = waiting();
|
||||
$collected = [];
|
||||
|
||||
if ($filesToCollectCoverageFor !== []) {
|
||||
if (!$this->filter->isEmpty()) {
|
||||
$filesToCollectCoverageFor = array_intersect($filesToCollectCoverageFor, $this->filter->files());
|
||||
}
|
||||
|
||||
$collected = collect(inclusive, $filesToCollectCoverageFor);
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
return RawCodeCoverageData::fromXdebugWithoutPathCoverage($collected);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
public function nameAndVersion(): string
|
||||
{
|
||||
return 'PCOV ' . phpversion('pcov');
|
||||
}
|
||||
|
||||
public function isPcov(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws PcovNotAvailableException
|
||||
*/
|
||||
private function ensurePcovIsAvailable(): void
|
||||
{
|
||||
if (!extension_loaded('pcov')) {
|
||||
throw new PcovNotAvailableException;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
vendor/phpunit/php-code-coverage/src/Driver/Selector.php
vendored
Normal file
59
vendor/phpunit/php-code-coverage/src/Driver/Selector.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?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\Driver;
|
||||
|
||||
use SebastianBergmann\CodeCoverage\Filter;
|
||||
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException;
|
||||
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
|
||||
use SebastianBergmann\Environment\Runtime;
|
||||
|
||||
final class Selector
|
||||
{
|
||||
/**
|
||||
* @throws NoCodeCoverageDriverAvailableException
|
||||
* @throws PcovNotAvailableException
|
||||
* @throws XdebugNotAvailableException
|
||||
* @throws XdebugNotEnabledException
|
||||
* @throws XdebugVersionNotSupportedException
|
||||
*/
|
||||
public function forLineCoverage(Filter $filter): Driver
|
||||
{
|
||||
$runtime = new Runtime;
|
||||
|
||||
if ($runtime->hasPCOV()) {
|
||||
return new PcovDriver($filter);
|
||||
}
|
||||
|
||||
if ($runtime->hasXdebug()) {
|
||||
return new XdebugDriver($filter);
|
||||
}
|
||||
|
||||
throw new NoCodeCoverageDriverAvailableException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NoCodeCoverageDriverWithPathCoverageSupportAvailableException
|
||||
* @throws XdebugNotAvailableException
|
||||
* @throws XdebugNotEnabledException
|
||||
* @throws XdebugVersionNotSupportedException
|
||||
*/
|
||||
public function forLineAndPathCoverage(Filter $filter): Driver
|
||||
{
|
||||
if ((new Runtime)->hasXdebug()) {
|
||||
$driver = new XdebugDriver($filter);
|
||||
|
||||
$driver->enableBranchAndPathCoverage();
|
||||
|
||||
return $driver;
|
||||
}
|
||||
|
||||
throw new NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
|
||||
}
|
||||
}
|
||||
140
vendor/phpunit/php-code-coverage/src/Driver/XdebugDriver.php
vendored
Normal file
140
vendor/phpunit/php-code-coverage/src/Driver/XdebugDriver.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?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\Driver;
|
||||
|
||||
use const XDEBUG_CC_BRANCH_CHECK;
|
||||
use const XDEBUG_CC_DEAD_CODE;
|
||||
use const XDEBUG_CC_UNUSED;
|
||||
use const XDEBUG_FILTER_CODE_COVERAGE;
|
||||
use const XDEBUG_PATH_INCLUDE;
|
||||
use function extension_loaded;
|
||||
use function in_array;
|
||||
use function phpversion;
|
||||
use function version_compare;
|
||||
use function xdebug_get_code_coverage;
|
||||
use function xdebug_info;
|
||||
use function xdebug_set_filter;
|
||||
use function xdebug_start_code_coverage;
|
||||
use function xdebug_stop_code_coverage;
|
||||
use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData;
|
||||
use SebastianBergmann\CodeCoverage\Filter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @see https://xdebug.org/docs/code_coverage#xdebug_get_code_coverage
|
||||
*
|
||||
* @phpstan-type XdebugLinesCoverageType array<int, int>
|
||||
* @phpstan-type XdebugBranchCoverageType array{
|
||||
* op_start: int,
|
||||
* op_end: int,
|
||||
* line_start: int,
|
||||
* line_end: int,
|
||||
* hit: int,
|
||||
* out: array<int, int>,
|
||||
* out_hit: array<int, int>,
|
||||
* }
|
||||
* @phpstan-type XdebugPathCoverageType array{
|
||||
* path: array<int, int>,
|
||||
* hit: int,
|
||||
* }
|
||||
* @phpstan-type XdebugFunctionCoverageType array{
|
||||
* branches: array<int, XdebugBranchCoverageType>,
|
||||
* paths: array<int, XdebugPathCoverageType>,
|
||||
* }
|
||||
* @phpstan-type XdebugFunctionsCoverageType array<string, XdebugFunctionCoverageType>
|
||||
* @phpstan-type XdebugPathAndBranchesCoverageType array{
|
||||
* lines: XdebugLinesCoverageType,
|
||||
* functions: XdebugFunctionsCoverageType,
|
||||
* }
|
||||
* @phpstan-type XdebugCodeCoverageWithoutPathCoverageType array<string, XdebugLinesCoverageType>
|
||||
* @phpstan-type XdebugCodeCoverageWithPathCoverageType array<string, XdebugPathAndBranchesCoverageType>
|
||||
*/
|
||||
final class XdebugDriver extends Driver
|
||||
{
|
||||
/**
|
||||
* @throws XdebugNotAvailableException
|
||||
* @throws XdebugNotEnabledException
|
||||
* @throws XdebugVersionNotSupportedException
|
||||
*/
|
||||
public function __construct(Filter $filter)
|
||||
{
|
||||
$this->ensureXdebugIsAvailable();
|
||||
|
||||
if (!$filter->isEmpty()) {
|
||||
xdebug_set_filter(
|
||||
XDEBUG_FILTER_CODE_COVERAGE,
|
||||
XDEBUG_PATH_INCLUDE,
|
||||
$filter->files(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function canCollectBranchAndPathCoverage(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function start(): void
|
||||
{
|
||||
$flags = XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE;
|
||||
|
||||
if ($this->collectsBranchAndPathCoverage()) {
|
||||
$flags |= XDEBUG_CC_BRANCH_CHECK;
|
||||
}
|
||||
|
||||
xdebug_start_code_coverage($flags);
|
||||
}
|
||||
|
||||
public function stop(): RawCodeCoverageData
|
||||
{
|
||||
$data = xdebug_get_code_coverage();
|
||||
|
||||
xdebug_stop_code_coverage();
|
||||
|
||||
if ($this->collectsBranchAndPathCoverage()) {
|
||||
/* @var XdebugCodeCoverageWithPathCoverageType $data */
|
||||
return RawCodeCoverageData::fromXdebugWithPathCoverage($data);
|
||||
}
|
||||
|
||||
/* @var XdebugCodeCoverageWithoutPathCoverageType $data */
|
||||
return RawCodeCoverageData::fromXdebugWithoutPathCoverage($data);
|
||||
}
|
||||
|
||||
public function nameAndVersion(): string
|
||||
{
|
||||
return 'Xdebug ' . phpversion('xdebug');
|
||||
}
|
||||
|
||||
public function isXdebug(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws XdebugNotAvailableException
|
||||
* @throws XdebugNotEnabledException
|
||||
* @throws XdebugVersionNotSupportedException
|
||||
*/
|
||||
private function ensureXdebugIsAvailable(): void
|
||||
{
|
||||
if (!extension_loaded('xdebug')) {
|
||||
throw new XdebugNotAvailableException;
|
||||
}
|
||||
|
||||
if (!version_compare(phpversion('xdebug'), '3.1', '>=')) {
|
||||
throw new XdebugVersionNotSupportedException(phpversion('xdebug'));
|
||||
}
|
||||
|
||||
if (!in_array('coverage', xdebug_info('mode'), true)) {
|
||||
throw new XdebugNotEnabledException;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php
vendored
Normal file
16
vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class BranchAndPathCoverageNotSupportedException extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
17
vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php
vendored
Normal file
17
vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?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\Util;
|
||||
|
||||
use RuntimeException;
|
||||
use SebastianBergmann\CodeCoverage\Exception;
|
||||
|
||||
final class DirectoryCouldNotBeCreatedException extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
16
vendor/phpunit/php-code-coverage/src/Exception/Exception.php
vendored
Normal file
16
vendor/phpunit/php-code-coverage/src/Exception/Exception.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface Exception extends Throwable
|
||||
{
|
||||
}
|
||||
16
vendor/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php
vendored
Normal file
16
vendor/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class FileCouldNotBeWrittenException extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
14
vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php
vendored
Normal file
14
vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?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;
|
||||
|
||||
final class InvalidArgumentException extends \InvalidArgumentException implements Exception
|
||||
{
|
||||
}
|
||||
27
vendor/phpunit/php-code-coverage/src/Exception/InvalidCodeCoverageTargetException.php
vendored
Normal file
27
vendor/phpunit/php-code-coverage/src/Exception/InvalidCodeCoverageTargetException.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?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\Test\Target;
|
||||
|
||||
use function sprintf;
|
||||
use RuntimeException;
|
||||
use SebastianBergmann\CodeCoverage\Exception;
|
||||
|
||||
final class InvalidCodeCoverageTargetException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct(Target $target)
|
||||
{
|
||||
parent::__construct(
|
||||
sprintf(
|
||||
'%s is not a valid target for code coverage',
|
||||
$target->description(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
20
vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php
vendored
Normal file
20
vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class NoCodeCoverageDriverAvailableException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('No code coverage driver available');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class NoCodeCoverageDriverWithPathCoverageSupportAvailableException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('No code coverage driver with path coverage support available');
|
||||
}
|
||||
}
|
||||
16
vendor/phpunit/php-code-coverage/src/Exception/ParserException.php
vendored
Normal file
16
vendor/phpunit/php-code-coverage/src/Exception/ParserException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class ParserException extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
21
vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php
vendored
Normal file
21
vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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;
|
||||
|
||||
use function sprintf;
|
||||
use RuntimeException;
|
||||
|
||||
final class PathExistsButIsNotDirectoryException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct(string $path)
|
||||
{
|
||||
parent::__construct(sprintf('"%s" exists but is not a directory', $path));
|
||||
}
|
||||
}
|
||||
21
vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php
vendored
Normal file
21
vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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\Driver;
|
||||
|
||||
use RuntimeException;
|
||||
use SebastianBergmann\CodeCoverage\Exception;
|
||||
|
||||
final class PcovNotAvailableException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('The PCOV extension is not available');
|
||||
}
|
||||
}
|
||||
16
vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php
vendored
Normal file
16
vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class ReflectionException extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
20
vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php
vendored
Normal file
20
vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class ReportAlreadyFinalizedException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('The code coverage report has already been finalized');
|
||||
}
|
||||
}
|
||||
16
vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php
vendored
Normal file
16
vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class StaticAnalysisCacheNotConfiguredException extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
20
vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php
vendored
Normal file
20
vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class TestIdMissingException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('Test ID is missing');
|
||||
}
|
||||
}
|
||||
50
vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php
vendored
Normal file
50
vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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;
|
||||
|
||||
use function rtrim;
|
||||
use RuntimeException;
|
||||
|
||||
final class UnintentionallyCoveredCodeException extends RuntimeException implements Exception
|
||||
{
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private readonly array $unintentionallyCoveredUnits;
|
||||
|
||||
/**
|
||||
* @param list<string> $unintentionallyCoveredUnits
|
||||
*/
|
||||
public function __construct(array $unintentionallyCoveredUnits)
|
||||
{
|
||||
$this->unintentionallyCoveredUnits = $unintentionallyCoveredUnits;
|
||||
|
||||
parent::__construct($this->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getUnintentionallyCoveredUnits(): array
|
||||
{
|
||||
return $this->unintentionallyCoveredUnits;
|
||||
}
|
||||
|
||||
private function toString(): string
|
||||
{
|
||||
$message = '';
|
||||
|
||||
foreach ($this->unintentionallyCoveredUnits as $unit) {
|
||||
$message .= '- ' . $unit . "\n";
|
||||
}
|
||||
|
||||
return rtrim($message);
|
||||
}
|
||||
}
|
||||
21
vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php
vendored
Normal file
21
vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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;
|
||||
|
||||
use function sprintf;
|
||||
use RuntimeException;
|
||||
|
||||
final class WriteOperationFailedException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct(string $path)
|
||||
{
|
||||
parent::__construct(sprintf('Cannot write to "%s"', $path));
|
||||
}
|
||||
}
|
||||
21
vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php
vendored
Normal file
21
vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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\Driver;
|
||||
|
||||
use RuntimeException;
|
||||
use SebastianBergmann\CodeCoverage\Exception;
|
||||
|
||||
final class XdebugNotAvailableException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('The Xdebug extension is not available');
|
||||
}
|
||||
}
|
||||
21
vendor/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php
vendored
Normal file
21
vendor/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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\Driver;
|
||||
|
||||
use RuntimeException;
|
||||
use SebastianBergmann\CodeCoverage\Exception;
|
||||
|
||||
final class XdebugNotEnabledException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('XDEBUG_MODE=coverage (environment variable) or xdebug.mode=coverage (PHP configuration setting) has to be set');
|
||||
}
|
||||
}
|
||||
30
vendor/phpunit/php-code-coverage/src/Exception/XdebugVersionNotSupportedException.php
vendored
Normal file
30
vendor/phpunit/php-code-coverage/src/Exception/XdebugVersionNotSupportedException.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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\Driver;
|
||||
|
||||
use function sprintf;
|
||||
use RuntimeException;
|
||||
use SebastianBergmann\CodeCoverage\Exception;
|
||||
|
||||
final class XdebugVersionNotSupportedException extends RuntimeException implements Exception
|
||||
{
|
||||
/**
|
||||
* @param non-empty-string $version
|
||||
*/
|
||||
public function __construct(string $version)
|
||||
{
|
||||
parent::__construct(
|
||||
sprintf(
|
||||
'Version %s of the Xdebug extension is not supported',
|
||||
$version,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
16
vendor/phpunit/php-code-coverage/src/Exception/XmlException.php
vendored
Normal file
16
vendor/phpunit/php-code-coverage/src/Exception/XmlException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class XmlException extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
93
vendor/phpunit/php-code-coverage/src/Filter.php
vendored
Normal file
93
vendor/phpunit/php-code-coverage/src/Filter.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?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;
|
||||
|
||||
use function array_keys;
|
||||
use function is_file;
|
||||
use function realpath;
|
||||
use function str_contains;
|
||||
use function str_starts_with;
|
||||
|
||||
final class Filter
|
||||
{
|
||||
/**
|
||||
* @var array<string,true>
|
||||
*/
|
||||
private array $files = [];
|
||||
|
||||
/**
|
||||
* @var array<string,bool>
|
||||
*/
|
||||
private array $isFileCache = [];
|
||||
|
||||
/**
|
||||
* @param list<string> $filenames
|
||||
*/
|
||||
public function includeFiles(array $filenames): void
|
||||
{
|
||||
foreach ($filenames as $filename) {
|
||||
$this->includeFile($filename);
|
||||
}
|
||||
}
|
||||
|
||||
public function includeFile(string $filename): void
|
||||
{
|
||||
$filename = realpath($filename);
|
||||
|
||||
if (!$filename) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->files[$filename] = true;
|
||||
}
|
||||
|
||||
public function isFile(string $filename): bool
|
||||
{
|
||||
if (isset($this->isFileCache[$filename])) {
|
||||
return $this->isFileCache[$filename];
|
||||
}
|
||||
|
||||
if ($filename === '-' ||
|
||||
str_starts_with($filename, 'vfs://') ||
|
||||
str_contains($filename, 'xdebug://debug-eval') ||
|
||||
str_contains($filename, 'eval()\'d code') ||
|
||||
str_contains($filename, 'runtime-created function') ||
|
||||
str_contains($filename, 'runkit created function') ||
|
||||
str_contains($filename, 'assert code') ||
|
||||
str_contains($filename, 'regexp code') ||
|
||||
str_contains($filename, 'Standard input code')) {
|
||||
$isFile = false;
|
||||
} else {
|
||||
$isFile = is_file($filename);
|
||||
}
|
||||
|
||||
$this->isFileCache[$filename] = $isFile;
|
||||
|
||||
return $isFile;
|
||||
}
|
||||
|
||||
public function isExcluded(string $filename): bool
|
||||
{
|
||||
return !isset($this->files[$filename]) || !$this->isFile($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function files(): array
|
||||
{
|
||||
return array_keys($this->files);
|
||||
}
|
||||
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return $this->files === [];
|
||||
}
|
||||
}
|
||||
274
vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php
vendored
Normal file
274
vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
<?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\Node;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use function array_merge;
|
||||
use function str_ends_with;
|
||||
use function str_replace;
|
||||
use function substr;
|
||||
use Countable;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedClassType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedFunctionType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedTraitType;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\LinesOfCode;
|
||||
use SebastianBergmann\CodeCoverage\Util\Percentage;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
abstract class AbstractNode implements Countable
|
||||
{
|
||||
private readonly string $name;
|
||||
private string $pathAsString;
|
||||
|
||||
/**
|
||||
* @var non-empty-list<self>
|
||||
*/
|
||||
private array $pathAsArray;
|
||||
private readonly ?AbstractNode $parent;
|
||||
private string $id;
|
||||
|
||||
public function __construct(string $name, ?self $parent = null)
|
||||
{
|
||||
if (str_ends_with($name, DIRECTORY_SEPARATOR)) {
|
||||
$name = substr($name, 0, -1);
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->parent = $parent;
|
||||
|
||||
$this->processId();
|
||||
$this->processPath();
|
||||
}
|
||||
|
||||
public function name(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function id(): string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function pathAsString(): string
|
||||
{
|
||||
return $this->pathAsString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-list<self>
|
||||
*/
|
||||
public function pathAsArray(): array
|
||||
{
|
||||
return $this->pathAsArray;
|
||||
}
|
||||
|
||||
public function parent(): ?self
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function percentageOfTestedClasses(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfTestedClasses(),
|
||||
$this->numberOfClasses(),
|
||||
);
|
||||
}
|
||||
|
||||
public function percentageOfTestedTraits(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfTestedTraits(),
|
||||
$this->numberOfTraits(),
|
||||
);
|
||||
}
|
||||
|
||||
public function percentageOfTestedClassesAndTraits(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfTestedClassesAndTraits(),
|
||||
$this->numberOfClassesAndTraits(),
|
||||
);
|
||||
}
|
||||
|
||||
public function percentageOfTestedFunctions(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfTestedFunctions(),
|
||||
$this->numberOfFunctions(),
|
||||
);
|
||||
}
|
||||
|
||||
public function percentageOfTestedMethods(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfTestedMethods(),
|
||||
$this->numberOfMethods(),
|
||||
);
|
||||
}
|
||||
|
||||
public function percentageOfTestedFunctionsAndMethods(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfTestedFunctionsAndMethods(),
|
||||
$this->numberOfFunctionsAndMethods(),
|
||||
);
|
||||
}
|
||||
|
||||
public function percentageOfExecutedLines(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfExecutedLines(),
|
||||
$this->numberOfExecutableLines(),
|
||||
);
|
||||
}
|
||||
|
||||
public function percentageOfExecutedBranches(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfExecutedBranches(),
|
||||
$this->numberOfExecutableBranches(),
|
||||
);
|
||||
}
|
||||
|
||||
public function percentageOfExecutedPaths(): Percentage
|
||||
{
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$this->numberOfExecutedPaths(),
|
||||
$this->numberOfExecutablePaths(),
|
||||
);
|
||||
}
|
||||
|
||||
public function numberOfClassesAndTraits(): int
|
||||
{
|
||||
return $this->numberOfClasses() + $this->numberOfTraits();
|
||||
}
|
||||
|
||||
public function numberOfTestedClassesAndTraits(): int
|
||||
{
|
||||
return $this->numberOfTestedClasses() + $this->numberOfTestedTraits();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedClassType|ProcessedTraitType>
|
||||
*/
|
||||
public function classesAndTraits(): array
|
||||
{
|
||||
return array_merge($this->classes(), $this->traits());
|
||||
}
|
||||
|
||||
public function numberOfFunctionsAndMethods(): int
|
||||
{
|
||||
return $this->numberOfFunctions() + $this->numberOfMethods();
|
||||
}
|
||||
|
||||
public function numberOfTestedFunctionsAndMethods(): int
|
||||
{
|
||||
return $this->numberOfTestedFunctions() + $this->numberOfTestedMethods();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-negative-int
|
||||
*/
|
||||
public function cyclomaticComplexity(): int
|
||||
{
|
||||
$ccn = 0;
|
||||
|
||||
foreach ($this->classesAndTraits() as $classLike) {
|
||||
$ccn += $classLike->ccn;
|
||||
}
|
||||
|
||||
foreach ($this->functions() as $function) {
|
||||
$ccn += $function->ccn;
|
||||
}
|
||||
|
||||
return $ccn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedClassType>
|
||||
*/
|
||||
abstract public function classes(): array;
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedTraitType>
|
||||
*/
|
||||
abstract public function traits(): array;
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedFunctionType>
|
||||
*/
|
||||
abstract public function functions(): array;
|
||||
|
||||
abstract public function linesOfCode(): LinesOfCode;
|
||||
|
||||
abstract public function numberOfExecutableLines(): int;
|
||||
|
||||
abstract public function numberOfExecutedLines(): int;
|
||||
|
||||
abstract public function numberOfExecutableBranches(): int;
|
||||
|
||||
abstract public function numberOfExecutedBranches(): int;
|
||||
|
||||
abstract public function numberOfExecutablePaths(): int;
|
||||
|
||||
abstract public function numberOfExecutedPaths(): int;
|
||||
|
||||
abstract public function numberOfClasses(): int;
|
||||
|
||||
abstract public function numberOfTestedClasses(): int;
|
||||
|
||||
abstract public function numberOfTraits(): int;
|
||||
|
||||
abstract public function numberOfTestedTraits(): int;
|
||||
|
||||
abstract public function numberOfMethods(): int;
|
||||
|
||||
abstract public function numberOfTestedMethods(): int;
|
||||
|
||||
abstract public function numberOfFunctions(): int;
|
||||
|
||||
abstract public function numberOfTestedFunctions(): int;
|
||||
|
||||
private function processId(): void
|
||||
{
|
||||
if ($this->parent === null) {
|
||||
$this->id = 'index';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$parentId = $this->parent->id();
|
||||
|
||||
if ($parentId === 'index') {
|
||||
$this->id = str_replace(':', '_', $this->name);
|
||||
} else {
|
||||
$this->id = $parentId . '/' . $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
private function processPath(): void
|
||||
{
|
||||
if ($this->parent === null) {
|
||||
$this->pathAsArray = [$this];
|
||||
$this->pathAsString = $this->name;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->pathAsArray = $this->parent->pathAsArray();
|
||||
$this->pathAsString = $this->parent->pathAsString() . DIRECTORY_SEPARATOR . $this->name;
|
||||
|
||||
$this->pathAsArray[] = $this;
|
||||
}
|
||||
}
|
||||
279
vendor/phpunit/php-code-coverage/src/Node/Builder.php
vendored
Normal file
279
vendor/phpunit/php-code-coverage/src/Node/Builder.php
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
<?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\Node;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use function array_shift;
|
||||
use function basename;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function is_file;
|
||||
use function sha1_file;
|
||||
use function str_ends_with;
|
||||
use function str_replace;
|
||||
use function str_starts_with;
|
||||
use function substr;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedCodeCoverageData;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @phpstan-import-type TestType from CodeCoverage
|
||||
*/
|
||||
final readonly class Builder
|
||||
{
|
||||
private FileAnalyser $analyser;
|
||||
|
||||
public function __construct(FileAnalyser $analyser)
|
||||
{
|
||||
$this->analyser = $analyser;
|
||||
}
|
||||
|
||||
public function build(CodeCoverage $coverage): Directory
|
||||
{
|
||||
$data = clone $coverage->getData(); // clone because path munging is destructive to the original data
|
||||
$commonPath = $this->reducePaths($data);
|
||||
$root = new Directory(
|
||||
$commonPath,
|
||||
null,
|
||||
);
|
||||
|
||||
$this->addItems(
|
||||
$root,
|
||||
$this->buildDirectoryStructure($data),
|
||||
$coverage->getTests(),
|
||||
);
|
||||
|
||||
return $root;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, TestType> $tests
|
||||
*/
|
||||
private function addItems(Directory $root, array $items, array $tests): void
|
||||
{
|
||||
foreach ($items as $key => $value) {
|
||||
$key = (string) $key;
|
||||
|
||||
if (str_ends_with($key, '/f')) {
|
||||
$key = substr($key, 0, -2);
|
||||
$filename = $root->pathAsString() . DIRECTORY_SEPARATOR . $key;
|
||||
|
||||
if (is_file($filename)) {
|
||||
$analysisResult = $this->analyser->analyse($filename);
|
||||
|
||||
$root->addFile(
|
||||
new File(
|
||||
$key,
|
||||
$root,
|
||||
sha1_file($filename),
|
||||
$value['lineCoverage'],
|
||||
$value['functionCoverage'],
|
||||
$tests,
|
||||
$analysisResult->classes(),
|
||||
$analysisResult->traits(),
|
||||
$analysisResult->functions(),
|
||||
$analysisResult->linesOfCode(),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$child = $root->addDirectory($key);
|
||||
|
||||
$this->addItems($child, $value, $tests);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an array representation of the directory structure.
|
||||
*
|
||||
* For instance,
|
||||
*
|
||||
* <code>
|
||||
* Array
|
||||
* (
|
||||
* [Money.php] => Array
|
||||
* (
|
||||
* ...
|
||||
* )
|
||||
*
|
||||
* [MoneyBag.php] => Array
|
||||
* (
|
||||
* ...
|
||||
* )
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* is transformed into
|
||||
*
|
||||
* <code>
|
||||
* Array
|
||||
* (
|
||||
* [.] => Array
|
||||
* (
|
||||
* [Money.php] => Array
|
||||
* (
|
||||
* ...
|
||||
* )
|
||||
*
|
||||
* [MoneyBag.php] => Array
|
||||
* (
|
||||
* ...
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @return array<string, array<string, array{lineCoverage: array<int, int>, functionCoverage: array<string, array<int, int>>}>>
|
||||
*/
|
||||
private function buildDirectoryStructure(ProcessedCodeCoverageData $data): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$lineCoverage = $data->lineCoverage();
|
||||
$functionCoverage = $data->functionCoverage();
|
||||
|
||||
foreach ($data->coveredFiles() as $originalPath) {
|
||||
$path = explode(DIRECTORY_SEPARATOR, $originalPath);
|
||||
$pointer = &$result;
|
||||
$max = count($path);
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
$type = '';
|
||||
|
||||
if ($i === ($max - 1)) {
|
||||
$type = '/f';
|
||||
}
|
||||
|
||||
$pointer = &$pointer[$path[$i] . $type];
|
||||
}
|
||||
|
||||
$pointer = [
|
||||
'lineCoverage' => $lineCoverage[$originalPath] ?? [],
|
||||
'functionCoverage' => $functionCoverage[$originalPath] ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the paths by cutting the longest common start path.
|
||||
*
|
||||
* For instance,
|
||||
*
|
||||
* <code>
|
||||
* Array
|
||||
* (
|
||||
* [/home/sb/Money/Money.php] => Array
|
||||
* (
|
||||
* ...
|
||||
* )
|
||||
*
|
||||
* [/home/sb/Money/MoneyBag.php] => Array
|
||||
* (
|
||||
* ...
|
||||
* )
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* is reduced to
|
||||
*
|
||||
* <code>
|
||||
* Array
|
||||
* (
|
||||
* [Money.php] => Array
|
||||
* (
|
||||
* ...
|
||||
* )
|
||||
*
|
||||
* [MoneyBag.php] => Array
|
||||
* (
|
||||
* ...
|
||||
* )
|
||||
* )
|
||||
* </code>
|
||||
*/
|
||||
private function reducePaths(ProcessedCodeCoverageData $coverage): string
|
||||
{
|
||||
$coveredFiles = $coverage->coveredFiles();
|
||||
|
||||
if ($coveredFiles === []) {
|
||||
return '.';
|
||||
}
|
||||
|
||||
$commonPath = '';
|
||||
$paths = $coveredFiles;
|
||||
|
||||
if (count($paths) === 1) {
|
||||
$commonPath = dirname($paths[0]) . DIRECTORY_SEPARATOR;
|
||||
$coverage->renameFile($paths[0], basename($paths[0]));
|
||||
|
||||
return $commonPath;
|
||||
}
|
||||
|
||||
$max = count($paths);
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
// strip phar:// prefixes
|
||||
if (str_starts_with($paths[$i], 'phar://')) {
|
||||
$paths[$i] = substr($paths[$i], 7);
|
||||
$paths[$i] = str_replace('/', DIRECTORY_SEPARATOR, $paths[$i]);
|
||||
}
|
||||
|
||||
$paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]);
|
||||
|
||||
if ($paths[$i][0] === '') {
|
||||
$paths[$i][0] = DIRECTORY_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
$done = false;
|
||||
$max = count($paths);
|
||||
|
||||
while (!$done) {
|
||||
for ($i = 0; $i < $max - 1; $i++) {
|
||||
if (!isset($paths[$i][0]) ||
|
||||
!isset($paths[$i + 1][0]) ||
|
||||
$paths[$i][0] !== $paths[$i + 1][0]) {
|
||||
$done = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$done) {
|
||||
$commonPath .= $paths[0][0];
|
||||
|
||||
if ($paths[0][0] !== DIRECTORY_SEPARATOR) {
|
||||
$commonPath .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
array_shift($paths[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$original = $coveredFiles;
|
||||
$max = count($original);
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
$coverage->renameFile($original[$i], implode(DIRECTORY_SEPARATOR, $paths[$i]));
|
||||
}
|
||||
|
||||
return substr($commonPath, 0, -1);
|
||||
}
|
||||
}
|
||||
43
vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php
vendored
Normal file
43
vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?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\Node;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class CrapIndex
|
||||
{
|
||||
private int $cyclomaticComplexity;
|
||||
private float $codeCoverage;
|
||||
|
||||
public function __construct(int $cyclomaticComplexity, float $codeCoverage)
|
||||
{
|
||||
$this->cyclomaticComplexity = $cyclomaticComplexity;
|
||||
$this->codeCoverage = $codeCoverage;
|
||||
}
|
||||
|
||||
public function asString(): string
|
||||
{
|
||||
if ($this->codeCoverage === 0.0) {
|
||||
return (string) ($this->cyclomaticComplexity ** 2 + $this->cyclomaticComplexity);
|
||||
}
|
||||
|
||||
if ($this->codeCoverage >= 95) {
|
||||
return (string) $this->cyclomaticComplexity;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'%01.2F',
|
||||
$this->cyclomaticComplexity ** 2 * (1 - $this->codeCoverage / 100) ** 3 + $this->cyclomaticComplexity,
|
||||
);
|
||||
}
|
||||
}
|
||||
403
vendor/phpunit/php-code-coverage/src/Node/Directory.php
vendored
Normal file
403
vendor/phpunit/php-code-coverage/src/Node/Directory.php
vendored
Normal file
@@ -0,0 +1,403 @@
|
||||
<?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\Node;
|
||||
|
||||
use function array_merge;
|
||||
use function assert;
|
||||
use function count;
|
||||
use IteratorAggregate;
|
||||
use RecursiveIteratorIterator;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedClassType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedFunctionType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedTraitType;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\LinesOfCode;
|
||||
|
||||
/**
|
||||
* @template-implements IteratorAggregate<int, AbstractNode>
|
||||
*
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Directory extends AbstractNode implements IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var list<Directory|File>
|
||||
*/
|
||||
private array $children = [];
|
||||
|
||||
/**
|
||||
* @var list<Directory>
|
||||
*/
|
||||
private array $directories = [];
|
||||
|
||||
/**
|
||||
* @var list<File>
|
||||
*/
|
||||
private array $files = [];
|
||||
|
||||
/**
|
||||
* @var ?array<string, ProcessedClassType>
|
||||
*/
|
||||
private ?array $classes = null;
|
||||
|
||||
/**
|
||||
* @var ?array<string, ProcessedTraitType>
|
||||
*/
|
||||
private ?array $traits = null;
|
||||
|
||||
/**
|
||||
* @var ?array<string, ProcessedFunctionType>
|
||||
*/
|
||||
private ?array $functions = null;
|
||||
private ?LinesOfCode $linesOfCode = null;
|
||||
private int $numFiles = -1;
|
||||
private int $numExecutableLines = -1;
|
||||
private int $numExecutedLines = -1;
|
||||
private int $numExecutableBranches = -1;
|
||||
private int $numExecutedBranches = -1;
|
||||
private int $numExecutablePaths = -1;
|
||||
private int $numExecutedPaths = -1;
|
||||
private int $numClasses = -1;
|
||||
private int $numTestedClasses = -1;
|
||||
private int $numTraits = -1;
|
||||
private int $numTestedTraits = -1;
|
||||
private int $numMethods = -1;
|
||||
private int $numTestedMethods = -1;
|
||||
private int $numFunctions = -1;
|
||||
private int $numTestedFunctions = -1;
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
if ($this->numFiles === -1) {
|
||||
$this->numFiles = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numFiles += count($child);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RecursiveIteratorIterator<Iterator<AbstractNode>>
|
||||
*/
|
||||
public function getIterator(): RecursiveIteratorIterator
|
||||
{
|
||||
return new RecursiveIteratorIterator(
|
||||
new Iterator($this),
|
||||
RecursiveIteratorIterator::SELF_FIRST,
|
||||
);
|
||||
}
|
||||
|
||||
public function addDirectory(string $name): self
|
||||
{
|
||||
$directory = new self($name, $this);
|
||||
|
||||
assert($directory instanceof self);
|
||||
|
||||
$this->children[] = $directory;
|
||||
$this->directories[] = &$this->children[count($this->children) - 1];
|
||||
|
||||
return $directory;
|
||||
}
|
||||
|
||||
public function addFile(File $file): void
|
||||
{
|
||||
$this->children[] = $file;
|
||||
$this->files[] = &$this->children[count($this->children) - 1];
|
||||
|
||||
$this->numExecutableLines = -1;
|
||||
$this->numExecutedLines = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<Directory>
|
||||
*/
|
||||
public function directories(): array
|
||||
{
|
||||
return $this->directories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<File>
|
||||
*/
|
||||
public function files(): array
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<Directory|File>
|
||||
*/
|
||||
public function children(): array
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedClassType>
|
||||
*/
|
||||
public function classes(): array
|
||||
{
|
||||
if ($this->classes === null) {
|
||||
$this->classes = [];
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->classes = array_merge(
|
||||
$this->classes,
|
||||
$child->classes(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedTraitType>
|
||||
*/
|
||||
public function traits(): array
|
||||
{
|
||||
if ($this->traits === null) {
|
||||
$this->traits = [];
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->traits = array_merge(
|
||||
$this->traits,
|
||||
$child->traits(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->traits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedFunctionType>
|
||||
*/
|
||||
public function functions(): array
|
||||
{
|
||||
if ($this->functions === null) {
|
||||
$this->functions = [];
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->functions = array_merge(
|
||||
$this->functions,
|
||||
$child->functions(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->functions;
|
||||
}
|
||||
|
||||
public function linesOfCode(): LinesOfCode
|
||||
{
|
||||
if ($this->linesOfCode === null) {
|
||||
$linesOfCode = 0;
|
||||
$commentLinesOfCode = 0;
|
||||
$nonCommentLinesOfCode = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$childLinesOfCode = $child->linesOfCode();
|
||||
|
||||
$linesOfCode += $childLinesOfCode->linesOfCode();
|
||||
$commentLinesOfCode += $childLinesOfCode->commentLinesOfCode();
|
||||
$nonCommentLinesOfCode += $childLinesOfCode->nonCommentLinesOfCode();
|
||||
}
|
||||
|
||||
$this->linesOfCode = new LinesOfCode($linesOfCode, $commentLinesOfCode, $nonCommentLinesOfCode);
|
||||
}
|
||||
|
||||
return $this->linesOfCode;
|
||||
}
|
||||
|
||||
public function numberOfExecutableLines(): int
|
||||
{
|
||||
if ($this->numExecutableLines === -1) {
|
||||
$this->numExecutableLines = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numExecutableLines += $child->numberOfExecutableLines();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numExecutableLines;
|
||||
}
|
||||
|
||||
public function numberOfExecutedLines(): int
|
||||
{
|
||||
if ($this->numExecutedLines === -1) {
|
||||
$this->numExecutedLines = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numExecutedLines += $child->numberOfExecutedLines();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numExecutedLines;
|
||||
}
|
||||
|
||||
public function numberOfExecutableBranches(): int
|
||||
{
|
||||
if ($this->numExecutableBranches === -1) {
|
||||
$this->numExecutableBranches = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numExecutableBranches += $child->numberOfExecutableBranches();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numExecutableBranches;
|
||||
}
|
||||
|
||||
public function numberOfExecutedBranches(): int
|
||||
{
|
||||
if ($this->numExecutedBranches === -1) {
|
||||
$this->numExecutedBranches = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numExecutedBranches += $child->numberOfExecutedBranches();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numExecutedBranches;
|
||||
}
|
||||
|
||||
public function numberOfExecutablePaths(): int
|
||||
{
|
||||
if ($this->numExecutablePaths === -1) {
|
||||
$this->numExecutablePaths = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numExecutablePaths += $child->numberOfExecutablePaths();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numExecutablePaths;
|
||||
}
|
||||
|
||||
public function numberOfExecutedPaths(): int
|
||||
{
|
||||
if ($this->numExecutedPaths === -1) {
|
||||
$this->numExecutedPaths = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numExecutedPaths += $child->numberOfExecutedPaths();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numExecutedPaths;
|
||||
}
|
||||
|
||||
public function numberOfClasses(): int
|
||||
{
|
||||
if ($this->numClasses === -1) {
|
||||
$this->numClasses = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numClasses += $child->numberOfClasses();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numClasses;
|
||||
}
|
||||
|
||||
public function numberOfTestedClasses(): int
|
||||
{
|
||||
if ($this->numTestedClasses === -1) {
|
||||
$this->numTestedClasses = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numTestedClasses += $child->numberOfTestedClasses();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numTestedClasses;
|
||||
}
|
||||
|
||||
public function numberOfTraits(): int
|
||||
{
|
||||
if ($this->numTraits === -1) {
|
||||
$this->numTraits = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numTraits += $child->numberOfTraits();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numTraits;
|
||||
}
|
||||
|
||||
public function numberOfTestedTraits(): int
|
||||
{
|
||||
if ($this->numTestedTraits === -1) {
|
||||
$this->numTestedTraits = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numTestedTraits += $child->numberOfTestedTraits();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numTestedTraits;
|
||||
}
|
||||
|
||||
public function numberOfMethods(): int
|
||||
{
|
||||
if ($this->numMethods === -1) {
|
||||
$this->numMethods = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numMethods += $child->numberOfMethods();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numMethods;
|
||||
}
|
||||
|
||||
public function numberOfTestedMethods(): int
|
||||
{
|
||||
if ($this->numTestedMethods === -1) {
|
||||
$this->numTestedMethods = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numTestedMethods += $child->numberOfTestedMethods();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numTestedMethods;
|
||||
}
|
||||
|
||||
public function numberOfFunctions(): int
|
||||
{
|
||||
if ($this->numFunctions === -1) {
|
||||
$this->numFunctions = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numFunctions += $child->numberOfFunctions();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numFunctions;
|
||||
}
|
||||
|
||||
public function numberOfTestedFunctions(): int
|
||||
{
|
||||
if ($this->numTestedFunctions === -1) {
|
||||
$this->numTestedFunctions = 0;
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$this->numTestedFunctions += $child->numberOfTestedFunctions();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numTestedFunctions;
|
||||
}
|
||||
}
|
||||
656
vendor/phpunit/php-code-coverage/src/Node/File.php
vendored
Normal file
656
vendor/phpunit/php-code-coverage/src/Node/File.php
vendored
Normal file
@@ -0,0 +1,656 @@
|
||||
<?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\Node;
|
||||
|
||||
use function array_filter;
|
||||
use function count;
|
||||
use function range;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedBranchCoverageData;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedClassType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedFunctionType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedMethodType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedPathCoverageData;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedTraitType;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\AnalysisResult;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\Class_;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\Function_;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\LinesOfCode;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\Method;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\Trait_;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @phpstan-import-type TestType from CodeCoverage
|
||||
* @phpstan-import-type LinesType from AnalysisResult
|
||||
*/
|
||||
final class File extends AbstractNode
|
||||
{
|
||||
/**
|
||||
* @var non-empty-string
|
||||
*/
|
||||
private string $sha1;
|
||||
|
||||
/**
|
||||
* @var array<int, ?list<non-empty-string>>
|
||||
*/
|
||||
private array $lineCoverageData;
|
||||
private array $functionCoverageData;
|
||||
|
||||
/**
|
||||
* @var array<string, TestType>
|
||||
*/
|
||||
private readonly array $testData;
|
||||
private int $numExecutableLines = 0;
|
||||
private int $numExecutedLines = 0;
|
||||
private int $numExecutableBranches = 0;
|
||||
private int $numExecutedBranches = 0;
|
||||
private int $numExecutablePaths = 0;
|
||||
private int $numExecutedPaths = 0;
|
||||
|
||||
/**
|
||||
* @var array<string, ProcessedClassType>
|
||||
*/
|
||||
private array $classes = [];
|
||||
|
||||
/**
|
||||
* @var array<string, ProcessedTraitType>
|
||||
*/
|
||||
private array $traits = [];
|
||||
|
||||
/**
|
||||
* @var array<string, ProcessedFunctionType>
|
||||
*/
|
||||
private array $functions = [];
|
||||
private readonly LinesOfCode $linesOfCode;
|
||||
private ?int $numClasses = null;
|
||||
private int $numTestedClasses = 0;
|
||||
private ?int $numTraits = null;
|
||||
private int $numTestedTraits = 0;
|
||||
private ?int $numMethods = null;
|
||||
private ?int $numTestedMethods = null;
|
||||
private ?int $numTestedFunctions = null;
|
||||
|
||||
/**
|
||||
* @var array<int, array|array{0: Class_, 1: string}|array{0: Function_|ProcessedFunctionType|ProcessedMethodType}|array{0: Trait_, 1: string}>
|
||||
*/
|
||||
private array $codeUnitsByLine = [];
|
||||
|
||||
/**
|
||||
* @param non-empty-string $sha1
|
||||
* @param array<int, ?list<non-empty-string>> $lineCoverageData
|
||||
* @param array<string, TestType> $testData
|
||||
* @param array<string, Class_> $classes
|
||||
* @param array<string, Trait_> $traits
|
||||
* @param array<string, Function_> $functions
|
||||
*/
|
||||
public function __construct(string $name, AbstractNode $parent, string $sha1, array $lineCoverageData, array $functionCoverageData, array $testData, array $classes, array $traits, array $functions, LinesOfCode $linesOfCode)
|
||||
{
|
||||
parent::__construct($name, $parent);
|
||||
|
||||
$this->sha1 = $sha1;
|
||||
$this->lineCoverageData = $lineCoverageData;
|
||||
$this->functionCoverageData = $functionCoverageData;
|
||||
$this->testData = $testData;
|
||||
$this->linesOfCode = $linesOfCode;
|
||||
|
||||
$this->calculateStatistics($classes, $traits, $functions);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function sha1(): string
|
||||
{
|
||||
return $this->sha1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, ?list<non-empty-string>>
|
||||
*/
|
||||
public function lineCoverageData(): array
|
||||
{
|
||||
return $this->lineCoverageData;
|
||||
}
|
||||
|
||||
public function functionCoverageData(): array
|
||||
{
|
||||
return $this->functionCoverageData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, TestType>
|
||||
*/
|
||||
public function testData(): array
|
||||
{
|
||||
return $this->testData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedClassType>
|
||||
*/
|
||||
public function classes(): array
|
||||
{
|
||||
return $this->classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedTraitType>
|
||||
*/
|
||||
public function traits(): array
|
||||
{
|
||||
return $this->traits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, ProcessedFunctionType>
|
||||
*/
|
||||
public function functions(): array
|
||||
{
|
||||
return $this->functions;
|
||||
}
|
||||
|
||||
public function linesOfCode(): LinesOfCode
|
||||
{
|
||||
return $this->linesOfCode;
|
||||
}
|
||||
|
||||
public function numberOfExecutableLines(): int
|
||||
{
|
||||
return $this->numExecutableLines;
|
||||
}
|
||||
|
||||
public function numberOfExecutedLines(): int
|
||||
{
|
||||
return $this->numExecutedLines;
|
||||
}
|
||||
|
||||
public function numberOfExecutableBranches(): int
|
||||
{
|
||||
return $this->numExecutableBranches;
|
||||
}
|
||||
|
||||
public function numberOfExecutedBranches(): int
|
||||
{
|
||||
return $this->numExecutedBranches;
|
||||
}
|
||||
|
||||
public function numberOfExecutablePaths(): int
|
||||
{
|
||||
return $this->numExecutablePaths;
|
||||
}
|
||||
|
||||
public function numberOfExecutedPaths(): int
|
||||
{
|
||||
return $this->numExecutedPaths;
|
||||
}
|
||||
|
||||
public function numberOfClasses(): int
|
||||
{
|
||||
if ($this->numClasses === null) {
|
||||
$this->numClasses = 0;
|
||||
|
||||
foreach ($this->classes as $class) {
|
||||
foreach ($class->methods as $method) {
|
||||
if ($method->executableLines > 0) {
|
||||
$this->numClasses++;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numClasses;
|
||||
}
|
||||
|
||||
public function numberOfTestedClasses(): int
|
||||
{
|
||||
return $this->numTestedClasses;
|
||||
}
|
||||
|
||||
public function numberOfTraits(): int
|
||||
{
|
||||
if ($this->numTraits === null) {
|
||||
$this->numTraits = 0;
|
||||
|
||||
foreach ($this->traits as $trait) {
|
||||
foreach ($trait->methods as $method) {
|
||||
if ($method->executableLines > 0) {
|
||||
$this->numTraits++;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numTraits;
|
||||
}
|
||||
|
||||
public function numberOfTestedTraits(): int
|
||||
{
|
||||
return $this->numTestedTraits;
|
||||
}
|
||||
|
||||
public function numberOfMethods(): int
|
||||
{
|
||||
if ($this->numMethods === null) {
|
||||
$this->numMethods = 0;
|
||||
|
||||
foreach ($this->classes as $class) {
|
||||
foreach ($class->methods as $method) {
|
||||
if ($method->executableLines > 0) {
|
||||
$this->numMethods++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->traits as $trait) {
|
||||
foreach ($trait->methods as $method) {
|
||||
if ($method->executableLines > 0) {
|
||||
$this->numMethods++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numMethods;
|
||||
}
|
||||
|
||||
public function numberOfTestedMethods(): int
|
||||
{
|
||||
if ($this->numTestedMethods === null) {
|
||||
$this->numTestedMethods = 0;
|
||||
|
||||
foreach ($this->classes as $class) {
|
||||
foreach ($class->methods as $method) {
|
||||
if ($method->executableLines > 0 &&
|
||||
$method->coverage === 100) {
|
||||
$this->numTestedMethods++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->traits as $trait) {
|
||||
foreach ($trait->methods as $method) {
|
||||
if ($method->executableLines > 0 &&
|
||||
$method->coverage === 100) {
|
||||
$this->numTestedMethods++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numTestedMethods;
|
||||
}
|
||||
|
||||
public function numberOfFunctions(): int
|
||||
{
|
||||
return count($this->functions);
|
||||
}
|
||||
|
||||
public function numberOfTestedFunctions(): int
|
||||
{
|
||||
if ($this->numTestedFunctions === null) {
|
||||
$this->numTestedFunctions = 0;
|
||||
|
||||
foreach ($this->functions as $function) {
|
||||
if ($function->executableLines > 0 &&
|
||||
$function->coverage === 100) {
|
||||
$this->numTestedFunctions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->numTestedFunctions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, Class_> $classes
|
||||
* @param array<string, Trait_> $traits
|
||||
* @param array<string, Function_> $functions
|
||||
*/
|
||||
private function calculateStatistics(array $classes, array $traits, array $functions): void
|
||||
{
|
||||
foreach (range(1, $this->linesOfCode->linesOfCode()) as $lineNumber) {
|
||||
$this->codeUnitsByLine[$lineNumber] = [];
|
||||
}
|
||||
|
||||
$this->processClasses($classes);
|
||||
$this->processTraits($traits);
|
||||
$this->processFunctions($functions);
|
||||
|
||||
foreach (range(1, $this->linesOfCode->linesOfCode()) as $lineNumber) {
|
||||
if (isset($this->lineCoverageData[$lineNumber])) {
|
||||
foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) {
|
||||
$codeUnit->executableLines++;
|
||||
}
|
||||
|
||||
unset($codeUnit);
|
||||
|
||||
$this->numExecutableLines++;
|
||||
|
||||
if (count($this->lineCoverageData[$lineNumber]) > 0) {
|
||||
foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) {
|
||||
$codeUnit->executedLines++;
|
||||
}
|
||||
|
||||
unset($codeUnit);
|
||||
|
||||
$this->numExecutedLines++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->traits as &$trait) {
|
||||
foreach ($trait->methods as &$method) {
|
||||
$methodLineCoverage = $method->executableLines > 0 ? ($method->executedLines / $method->executableLines) * 100 : 100;
|
||||
$methodBranchCoverage = $method->executableBranches > 0 ? ($method->executedBranches / $method->executableBranches) * 100 : 0;
|
||||
$methodPathCoverage = $method->executablePaths > 0 ? ($method->executedPaths / $method->executablePaths) * 100 : 0;
|
||||
|
||||
$method->coverage = $methodBranchCoverage > 0 ? $methodBranchCoverage : $methodLineCoverage;
|
||||
$method->crap = (new CrapIndex($method->ccn, $methodPathCoverage > 0 ? $methodPathCoverage : $methodLineCoverage))->asString();
|
||||
|
||||
$trait->ccn += $method->ccn;
|
||||
}
|
||||
|
||||
unset($method);
|
||||
|
||||
$traitBranchCoverage = $trait->executableBranches > 0 ? ($trait->executedBranches / $trait->executableBranches) * 100 : 0;
|
||||
$traitLineCoverage = $trait->executableLines > 0 ? ($trait->executedLines / $trait->executableLines) * 100 : 100;
|
||||
$traitPathCoverage = $trait->executablePaths > 0 ? ($trait->executedPaths / $trait->executablePaths) * 100 : 0;
|
||||
|
||||
$trait->coverage = $traitBranchCoverage > 0 ? $traitBranchCoverage : $traitLineCoverage;
|
||||
$trait->crap = (new CrapIndex($trait->ccn, $traitPathCoverage > 0 ? $traitPathCoverage : $traitLineCoverage))->asString();
|
||||
|
||||
if ($trait->executableLines > 0 && $trait->coverage === 100) {
|
||||
$this->numTestedTraits++;
|
||||
}
|
||||
}
|
||||
|
||||
unset($trait);
|
||||
|
||||
foreach ($this->classes as &$class) {
|
||||
foreach ($class->methods as &$method) {
|
||||
$methodLineCoverage = $method->executableLines > 0 ? ($method->executedLines / $method->executableLines) * 100 : 100;
|
||||
$methodBranchCoverage = $method->executableBranches > 0 ? ($method->executedBranches / $method->executableBranches) * 100 : 0;
|
||||
$methodPathCoverage = $method->executablePaths > 0 ? ($method->executedPaths / $method->executablePaths) * 100 : 0;
|
||||
|
||||
$method->coverage = $methodBranchCoverage > 0 ? $methodBranchCoverage : $methodLineCoverage;
|
||||
$method->crap = (new CrapIndex($method->ccn, $methodPathCoverage > 0 ? $methodPathCoverage : $methodLineCoverage))->asString();
|
||||
|
||||
$class->ccn += $method->ccn;
|
||||
}
|
||||
|
||||
unset($method);
|
||||
|
||||
$classLineCoverage = $class->executableLines > 0 ? ($class->executedLines / $class->executableLines) * 100 : 100;
|
||||
$classBranchCoverage = $class->executableBranches > 0 ? ($class->executedBranches / $class->executableBranches) * 100 : 0;
|
||||
$classPathCoverage = $class->executablePaths > 0 ? ($class->executedPaths / $class->executablePaths) * 100 : 0;
|
||||
|
||||
$class->coverage = $classBranchCoverage > 0 ? $classBranchCoverage : $classLineCoverage;
|
||||
$class->crap = (new CrapIndex($class->ccn, $classPathCoverage > 0 ? $classPathCoverage : $classLineCoverage))->asString();
|
||||
|
||||
if ($class->executableLines > 0 && $class->coverage === 100) {
|
||||
$this->numTestedClasses++;
|
||||
}
|
||||
}
|
||||
|
||||
unset($class);
|
||||
|
||||
foreach ($this->functions as &$function) {
|
||||
$functionLineCoverage = $function->executableLines > 0 ? ($function->executedLines / $function->executableLines) * 100 : 100;
|
||||
$functionBranchCoverage = $function->executableBranches > 0 ? ($function->executedBranches / $function->executableBranches) * 100 : 0;
|
||||
$functionPathCoverage = $function->executablePaths > 0 ? ($function->executedPaths / $function->executablePaths) * 100 : 0;
|
||||
|
||||
$function->coverage = $functionBranchCoverage > 0 ? $functionBranchCoverage : $functionLineCoverage;
|
||||
$function->crap = (new CrapIndex($function->ccn, $functionPathCoverage > 0 ? $functionPathCoverage : $functionLineCoverage))->asString();
|
||||
|
||||
if ($function->coverage === 100) {
|
||||
$this->numTestedFunctions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, Class_> $classes
|
||||
*/
|
||||
private function processClasses(array $classes): void
|
||||
{
|
||||
$link = $this->id() . '.html#';
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
$this->classes[$className] = new ProcessedClassType(
|
||||
$className,
|
||||
$class->namespace(),
|
||||
[],
|
||||
$class->startLine(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$link . $class->startLine(),
|
||||
);
|
||||
|
||||
foreach ($class->methods() as $methodName => $method) {
|
||||
$methodData = $this->newMethod($className, $method, $link);
|
||||
$this->classes[$className]->methods[$methodName] = $methodData;
|
||||
|
||||
$this->classes[$className]->executableBranches += $methodData->executableBranches;
|
||||
$this->classes[$className]->executedBranches += $methodData->executedBranches;
|
||||
$this->classes[$className]->executablePaths += $methodData->executablePaths;
|
||||
$this->classes[$className]->executedPaths += $methodData->executedPaths;
|
||||
|
||||
$this->numExecutableBranches += $methodData->executableBranches;
|
||||
$this->numExecutedBranches += $methodData->executedBranches;
|
||||
$this->numExecutablePaths += $methodData->executablePaths;
|
||||
$this->numExecutedPaths += $methodData->executedPaths;
|
||||
|
||||
foreach (range($method->startLine(), $method->endLine()) as $lineNumber) {
|
||||
$this->codeUnitsByLine[$lineNumber] = [
|
||||
&$this->classes[$className],
|
||||
&$this->classes[$className]->methods[$methodName],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, Trait_> $traits
|
||||
*/
|
||||
private function processTraits(array $traits): void
|
||||
{
|
||||
$link = $this->id() . '.html#';
|
||||
|
||||
foreach ($traits as $traitName => $trait) {
|
||||
$this->traits[$traitName] = new ProcessedTraitType(
|
||||
$traitName,
|
||||
$trait->namespace(),
|
||||
[],
|
||||
$trait->startLine(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$link . $trait->startLine(),
|
||||
);
|
||||
|
||||
foreach ($trait->methods() as $methodName => $method) {
|
||||
$methodData = $this->newMethod($traitName, $method, $link);
|
||||
$this->traits[$traitName]->methods[$methodName] = $methodData;
|
||||
|
||||
$this->traits[$traitName]->executableBranches += $methodData->executableBranches;
|
||||
$this->traits[$traitName]->executedBranches += $methodData->executedBranches;
|
||||
$this->traits[$traitName]->executablePaths += $methodData->executablePaths;
|
||||
$this->traits[$traitName]->executedPaths += $methodData->executedPaths;
|
||||
|
||||
$this->numExecutableBranches += $methodData->executableBranches;
|
||||
$this->numExecutedBranches += $methodData->executedBranches;
|
||||
$this->numExecutablePaths += $methodData->executablePaths;
|
||||
$this->numExecutedPaths += $methodData->executedPaths;
|
||||
|
||||
foreach (range($method->startLine(), $method->endLine()) as $lineNumber) {
|
||||
$this->codeUnitsByLine[$lineNumber] = [
|
||||
&$this->traits[$traitName],
|
||||
&$this->traits[$traitName]->methods[$methodName],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, Function_> $functions
|
||||
*/
|
||||
private function processFunctions(array $functions): void
|
||||
{
|
||||
$link = $this->id() . '.html#';
|
||||
|
||||
foreach ($functions as $functionName => $function) {
|
||||
$this->functions[$functionName] = new ProcessedFunctionType(
|
||||
$functionName,
|
||||
$function->namespace(),
|
||||
$function->signature(),
|
||||
$function->startLine(),
|
||||
$function->endLine(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$function->cyclomaticComplexity(),
|
||||
0,
|
||||
0,
|
||||
$link . $function->startLine(),
|
||||
);
|
||||
|
||||
foreach (range($function->startLine(), $function->endLine()) as $lineNumber) {
|
||||
$this->codeUnitsByLine[$lineNumber] = [&$this->functions[$functionName]];
|
||||
}
|
||||
|
||||
if (isset($this->functionCoverageData[$functionName])) {
|
||||
$this->functions[$functionName]->executableBranches = count(
|
||||
$this->functionCoverageData[$functionName]->branches,
|
||||
);
|
||||
|
||||
$this->functions[$functionName]->executedBranches = count(
|
||||
array_filter(
|
||||
$this->functionCoverageData[$functionName]->branches,
|
||||
static function (ProcessedBranchCoverageData $branch)
|
||||
{
|
||||
return (bool) $branch->hit;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($this->functionCoverageData[$functionName])) {
|
||||
$this->functions[$functionName]->executablePaths = count(
|
||||
$this->functionCoverageData[$functionName]->paths,
|
||||
);
|
||||
|
||||
$this->functions[$functionName]->executedPaths = count(
|
||||
array_filter(
|
||||
$this->functionCoverageData[$functionName]->paths,
|
||||
static function (ProcessedPathCoverageData $path)
|
||||
{
|
||||
return (bool) $path->hit;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$this->numExecutableBranches += $this->functions[$functionName]->executableBranches;
|
||||
$this->numExecutedBranches += $this->functions[$functionName]->executedBranches;
|
||||
$this->numExecutablePaths += $this->functions[$functionName]->executablePaths;
|
||||
$this->numExecutedPaths += $this->functions[$functionName]->executedPaths;
|
||||
}
|
||||
}
|
||||
|
||||
private function newMethod(string $className, Method $method, string $link): ProcessedMethodType
|
||||
{
|
||||
$key = $className . '->' . $method->name();
|
||||
|
||||
$executableBranches = 0;
|
||||
$executedBranches = 0;
|
||||
|
||||
if (isset($this->functionCoverageData[$key])) {
|
||||
$executableBranches = count(
|
||||
$this->functionCoverageData[$key]->branches,
|
||||
);
|
||||
|
||||
$executedBranches = count(
|
||||
array_filter(
|
||||
$this->functionCoverageData[$key]->branches,
|
||||
static function (ProcessedBranchCoverageData $branch)
|
||||
{
|
||||
return (bool) $branch->hit;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$executablePaths = 0;
|
||||
$executedPaths = 0;
|
||||
|
||||
if (isset($this->functionCoverageData[$key])) {
|
||||
$executablePaths = count(
|
||||
$this->functionCoverageData[$key]->paths,
|
||||
);
|
||||
|
||||
$executedPaths = count(
|
||||
array_filter(
|
||||
$this->functionCoverageData[$key]->paths,
|
||||
static function (ProcessedPathCoverageData $path)
|
||||
{
|
||||
return (bool) $path->hit;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return new ProcessedMethodType(
|
||||
$method->name(),
|
||||
$method->visibility()->value,
|
||||
$method->signature(),
|
||||
$method->startLine(),
|
||||
$method->endLine(),
|
||||
0,
|
||||
0,
|
||||
$executableBranches,
|
||||
$executedBranches,
|
||||
$executablePaths,
|
||||
$executedPaths,
|
||||
$method->cyclomaticComplexity(),
|
||||
0,
|
||||
0,
|
||||
$link . $method->startLine(),
|
||||
);
|
||||
}
|
||||
}
|
||||
71
vendor/phpunit/php-code-coverage/src/Node/Iterator.php
vendored
Normal file
71
vendor/phpunit/php-code-coverage/src/Node/Iterator.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?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\Node;
|
||||
|
||||
use function assert;
|
||||
use function count;
|
||||
use RecursiveIterator;
|
||||
|
||||
/**
|
||||
* @template-implements RecursiveIterator<int, AbstractNode>
|
||||
*
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Iterator implements RecursiveIterator
|
||||
{
|
||||
private int $position;
|
||||
|
||||
/**
|
||||
* @var list<AbstractNode>
|
||||
*/
|
||||
private readonly array $nodes;
|
||||
|
||||
public function __construct(Directory $node)
|
||||
{
|
||||
$this->nodes = $node->children();
|
||||
}
|
||||
|
||||
public function rewind(): void
|
||||
{
|
||||
$this->position = 0;
|
||||
}
|
||||
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->position < count($this->nodes);
|
||||
}
|
||||
|
||||
public function key(): int
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function current(): ?AbstractNode
|
||||
{
|
||||
return $this->valid() ? $this->nodes[$this->position] : null;
|
||||
}
|
||||
|
||||
public function next(): void
|
||||
{
|
||||
$this->position++;
|
||||
}
|
||||
|
||||
public function getChildren(): self
|
||||
{
|
||||
assert($this->nodes[$this->position] instanceof Directory);
|
||||
|
||||
return new self($this->nodes[$this->position]);
|
||||
}
|
||||
|
||||
public function hasChildren(): bool
|
||||
{
|
||||
return $this->nodes[$this->position] instanceof Directory;
|
||||
}
|
||||
}
|
||||
227
vendor/phpunit/php-code-coverage/src/Report/Clover.php
vendored
Normal file
227
vendor/phpunit/php-code-coverage/src/Report/Clover.php
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
<?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\Report;
|
||||
|
||||
use function count;
|
||||
use function is_string;
|
||||
use function ksort;
|
||||
use function max;
|
||||
use function range;
|
||||
use function time;
|
||||
use DOMDocument;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Node\File;
|
||||
use SebastianBergmann\CodeCoverage\Util\Filesystem;
|
||||
use SebastianBergmann\CodeCoverage\Util\Xml;
|
||||
use SebastianBergmann\CodeCoverage\WriteOperationFailedException;
|
||||
|
||||
final class Clover
|
||||
{
|
||||
/**
|
||||
* @param null|non-empty-string $target
|
||||
* @param null|non-empty-string $name
|
||||
*
|
||||
* @throws WriteOperationFailedException
|
||||
*/
|
||||
public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string
|
||||
{
|
||||
$time = (string) time();
|
||||
|
||||
$xmlDocument = new DOMDocument('1.0', 'UTF-8');
|
||||
|
||||
$xmlCoverage = $xmlDocument->createElement('coverage');
|
||||
$xmlCoverage->setAttribute('generated', $time);
|
||||
$xmlDocument->appendChild($xmlCoverage);
|
||||
|
||||
$xmlProject = $xmlDocument->createElement('project');
|
||||
$xmlProject->setAttribute('timestamp', $time);
|
||||
|
||||
if (is_string($name)) {
|
||||
$xmlProject->setAttribute('name', $name);
|
||||
}
|
||||
|
||||
$xmlCoverage->appendChild($xmlProject);
|
||||
|
||||
$packages = [];
|
||||
$report = $coverage->getReport();
|
||||
|
||||
foreach ($report as $item) {
|
||||
if (!$item instanceof File) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* @var File $item */
|
||||
|
||||
$xmlFile = $xmlDocument->createElement('file');
|
||||
$xmlFile->setAttribute('name', $item->pathAsString());
|
||||
|
||||
$classes = $item->classesAndTraits();
|
||||
$coverageData = $item->lineCoverageData();
|
||||
$lines = [];
|
||||
$namespace = 'global';
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
$classStatements = 0;
|
||||
$coveredClassStatements = 0;
|
||||
$coveredMethods = 0;
|
||||
$classMethods = 0;
|
||||
|
||||
// Assumption: one namespace per file
|
||||
if ($class->namespace !== '') {
|
||||
$namespace = $class->namespace;
|
||||
}
|
||||
|
||||
foreach ($class->methods as $methodName => $method) {
|
||||
/** @phpstan-ignore equal.notAllowed */
|
||||
if ($method->executableLines == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classMethods++;
|
||||
$classStatements += $method->executableLines;
|
||||
$coveredClassStatements += $method->executedLines;
|
||||
|
||||
/** @phpstan-ignore equal.notAllowed */
|
||||
if ($method->coverage == 100) {
|
||||
$coveredMethods++;
|
||||
}
|
||||
|
||||
$methodCount = 0;
|
||||
|
||||
foreach (range($method->startLine, $method->endLine) as $line) {
|
||||
if (isset($coverageData[$line])) {
|
||||
$methodCount = max($methodCount, count($coverageData[$line]));
|
||||
}
|
||||
}
|
||||
|
||||
$lines[$method->startLine] = [
|
||||
'ccn' => $method->ccn,
|
||||
'count' => $methodCount,
|
||||
'crap' => $method->crap,
|
||||
'type' => 'method',
|
||||
'visibility' => $method->visibility,
|
||||
'name' => $methodName,
|
||||
];
|
||||
}
|
||||
|
||||
$xmlClass = $xmlDocument->createElement('class');
|
||||
$xmlClass->setAttribute('name', $className);
|
||||
$xmlClass->setAttribute('namespace', $namespace);
|
||||
|
||||
$xmlFile->appendChild($xmlClass);
|
||||
|
||||
$xmlMetrics = $xmlDocument->createElement('metrics');
|
||||
$xmlMetrics->setAttribute('complexity', (string) $class->ccn);
|
||||
$xmlMetrics->setAttribute('methods', (string) $classMethods);
|
||||
$xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods);
|
||||
$xmlMetrics->setAttribute('conditionals', (string) $class->executableBranches);
|
||||
$xmlMetrics->setAttribute('coveredconditionals', (string) $class->executedBranches);
|
||||
$xmlMetrics->setAttribute('statements', (string) $classStatements);
|
||||
$xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements);
|
||||
$xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class->executableBranches));
|
||||
$xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class->executedBranches));
|
||||
$xmlClass->appendChild($xmlMetrics);
|
||||
}
|
||||
|
||||
foreach ($coverageData as $line => $data) {
|
||||
if ($data === null || isset($lines[$line])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$lines[$line] = [
|
||||
'count' => count($data), 'type' => 'stmt',
|
||||
];
|
||||
}
|
||||
|
||||
ksort($lines);
|
||||
|
||||
foreach ($lines as $line => $data) {
|
||||
$xmlLine = $xmlDocument->createElement('line');
|
||||
$xmlLine->setAttribute('num', (string) $line);
|
||||
$xmlLine->setAttribute('type', $data['type']);
|
||||
|
||||
if (isset($data['name'])) {
|
||||
$xmlLine->setAttribute('name', $data['name']);
|
||||
}
|
||||
|
||||
if (isset($data['visibility'])) {
|
||||
$xmlLine->setAttribute('visibility', $data['visibility']);
|
||||
}
|
||||
|
||||
if (isset($data['ccn'])) {
|
||||
$xmlLine->setAttribute('complexity', (string) $data['ccn']);
|
||||
}
|
||||
|
||||
if (isset($data['crap'])) {
|
||||
$xmlLine->setAttribute('crap', (string) $data['crap']);
|
||||
}
|
||||
|
||||
$xmlLine->setAttribute('count', (string) $data['count']);
|
||||
$xmlFile->appendChild($xmlLine);
|
||||
}
|
||||
|
||||
$linesOfCode = $item->linesOfCode();
|
||||
|
||||
$xmlMetrics = $xmlDocument->createElement('metrics');
|
||||
$xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode());
|
||||
$xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode());
|
||||
$xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits());
|
||||
$xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods());
|
||||
$xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods());
|
||||
$xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches());
|
||||
$xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches());
|
||||
$xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines());
|
||||
$xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines());
|
||||
$xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches()));
|
||||
$xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches()));
|
||||
$xmlFile->appendChild($xmlMetrics);
|
||||
|
||||
if ($namespace === 'global') {
|
||||
$xmlProject->appendChild($xmlFile);
|
||||
} else {
|
||||
if (!isset($packages[$namespace])) {
|
||||
$packages[$namespace] = $xmlDocument->createElement(
|
||||
'package',
|
||||
);
|
||||
|
||||
$packages[$namespace]->setAttribute('name', $namespace);
|
||||
$xmlProject->appendChild($packages[$namespace]);
|
||||
}
|
||||
|
||||
$packages[$namespace]->appendChild($xmlFile);
|
||||
}
|
||||
}
|
||||
|
||||
$linesOfCode = $report->linesOfCode();
|
||||
|
||||
$xmlMetrics = $xmlDocument->createElement('metrics');
|
||||
$xmlMetrics->setAttribute('files', (string) count($report));
|
||||
$xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode());
|
||||
$xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode());
|
||||
$xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits());
|
||||
$xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods());
|
||||
$xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods());
|
||||
$xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches());
|
||||
$xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches());
|
||||
$xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines());
|
||||
$xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines());
|
||||
$xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches()));
|
||||
$xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches()));
|
||||
$xmlProject->appendChild($xmlMetrics);
|
||||
|
||||
$buffer = Xml::asString($xmlDocument);
|
||||
|
||||
if ($target !== null) {
|
||||
Filesystem::write($target, $buffer);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
}
|
||||
299
vendor/phpunit/php-code-coverage/src/Report/Cobertura.php
vendored
Normal file
299
vendor/phpunit/php-code-coverage/src/Report/Cobertura.php
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
<?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\Report;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use function basename;
|
||||
use function count;
|
||||
use function preg_match;
|
||||
use function range;
|
||||
use function str_replace;
|
||||
use function time;
|
||||
use DOMImplementation;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Node\File;
|
||||
use SebastianBergmann\CodeCoverage\Util\Filesystem;
|
||||
use SebastianBergmann\CodeCoverage\Util\Xml;
|
||||
use SebastianBergmann\CodeCoverage\WriteOperationFailedException;
|
||||
|
||||
final class Cobertura
|
||||
{
|
||||
/**
|
||||
* @param null|non-empty-string $target
|
||||
*
|
||||
* @throws WriteOperationFailedException
|
||||
*/
|
||||
public function process(CodeCoverage $coverage, ?string $target = null): string
|
||||
{
|
||||
$time = (string) time();
|
||||
|
||||
$report = $coverage->getReport();
|
||||
|
||||
$implementation = new DOMImplementation;
|
||||
|
||||
$documentType = $implementation->createDocumentType(
|
||||
'coverage',
|
||||
'',
|
||||
'http://cobertura.sourceforge.net/xml/coverage-04.dtd',
|
||||
);
|
||||
|
||||
$document = $implementation->createDocument('', '', $documentType);
|
||||
$document->xmlVersion = '1.0';
|
||||
$document->encoding = 'UTF-8';
|
||||
|
||||
$coverageElement = $document->createElement('coverage');
|
||||
|
||||
$linesValid = $report->numberOfExecutableLines();
|
||||
$linesCovered = $report->numberOfExecutedLines();
|
||||
$lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid);
|
||||
$coverageElement->setAttribute('line-rate', (string) $lineRate);
|
||||
|
||||
$branchesValid = $report->numberOfExecutableBranches();
|
||||
$branchesCovered = $report->numberOfExecutedBranches();
|
||||
$branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
|
||||
$coverageElement->setAttribute('branch-rate', (string) $branchRate);
|
||||
|
||||
$coverageElement->setAttribute('lines-covered', (string) $report->numberOfExecutedLines());
|
||||
$coverageElement->setAttribute('lines-valid', (string) $report->numberOfExecutableLines());
|
||||
$coverageElement->setAttribute('branches-covered', (string) $report->numberOfExecutedBranches());
|
||||
$coverageElement->setAttribute('branches-valid', (string) $report->numberOfExecutableBranches());
|
||||
$coverageElement->setAttribute('complexity', '');
|
||||
$coverageElement->setAttribute('version', '0.4');
|
||||
$coverageElement->setAttribute('timestamp', $time);
|
||||
|
||||
$document->appendChild($coverageElement);
|
||||
|
||||
$sourcesElement = $document->createElement('sources');
|
||||
$coverageElement->appendChild($sourcesElement);
|
||||
|
||||
$sourceElement = $document->createElement('source', $report->pathAsString());
|
||||
$sourcesElement->appendChild($sourceElement);
|
||||
|
||||
$packagesElement = $document->createElement('packages');
|
||||
$coverageElement->appendChild($packagesElement);
|
||||
|
||||
$complexity = 0;
|
||||
|
||||
foreach ($report as $item) {
|
||||
if (!$item instanceof File) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$packageElement = $document->createElement('package');
|
||||
$packageComplexity = 0;
|
||||
|
||||
$packageElement->setAttribute('name', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString()));
|
||||
|
||||
$linesValid = $item->numberOfExecutableLines();
|
||||
$linesCovered = $item->numberOfExecutedLines();
|
||||
$lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid);
|
||||
|
||||
$packageElement->setAttribute('line-rate', (string) $lineRate);
|
||||
|
||||
$branchesValid = $item->numberOfExecutableBranches();
|
||||
$branchesCovered = $item->numberOfExecutedBranches();
|
||||
$branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
|
||||
|
||||
$packageElement->setAttribute('branch-rate', (string) $branchRate);
|
||||
|
||||
$packageElement->setAttribute('complexity', '');
|
||||
$packagesElement->appendChild($packageElement);
|
||||
|
||||
$classesElement = $document->createElement('classes');
|
||||
|
||||
$packageElement->appendChild($classesElement);
|
||||
|
||||
$classes = $item->classesAndTraits();
|
||||
$coverageData = $item->lineCoverageData();
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
$complexity += $class->ccn;
|
||||
$packageComplexity += $class->ccn;
|
||||
|
||||
$linesValid = $class->executableLines;
|
||||
$linesCovered = $class->executedLines;
|
||||
$lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid);
|
||||
|
||||
$branchesValid = $class->executableBranches;
|
||||
$branchesCovered = $class->executedBranches;
|
||||
$branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
|
||||
|
||||
$classElement = $document->createElement('class');
|
||||
|
||||
$classElement->setAttribute('name', $className);
|
||||
$classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString()));
|
||||
$classElement->setAttribute('line-rate', (string) $lineRate);
|
||||
$classElement->setAttribute('branch-rate', (string) $branchRate);
|
||||
$classElement->setAttribute('complexity', (string) $class->ccn);
|
||||
|
||||
$classesElement->appendChild($classElement);
|
||||
|
||||
$methodsElement = $document->createElement('methods');
|
||||
|
||||
$classElement->appendChild($methodsElement);
|
||||
|
||||
$classLinesElement = $document->createElement('lines');
|
||||
|
||||
$classElement->appendChild($classLinesElement);
|
||||
|
||||
foreach ($class->methods as $methodName => $method) {
|
||||
if ($method->executableLines === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
preg_match("/\((.*?)\)/", $method->signature, $signature);
|
||||
|
||||
$linesValid = $method->executableLines;
|
||||
$linesCovered = $method->executedLines;
|
||||
$lineRate = $linesCovered / $linesValid;
|
||||
|
||||
$branchesValid = $method->executableBranches;
|
||||
$branchesCovered = $method->executedBranches;
|
||||
$branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
|
||||
|
||||
$methodElement = $document->createElement('method');
|
||||
|
||||
$methodElement->setAttribute('name', $methodName);
|
||||
$methodElement->setAttribute('signature', $signature[1]);
|
||||
$methodElement->setAttribute('line-rate', (string) $lineRate);
|
||||
$methodElement->setAttribute('branch-rate', (string) $branchRate);
|
||||
$methodElement->setAttribute('complexity', (string) $method->ccn);
|
||||
|
||||
$methodLinesElement = $document->createElement('lines');
|
||||
|
||||
$methodElement->appendChild($methodLinesElement);
|
||||
|
||||
foreach (range($method->startLine, $method->endLine) as $line) {
|
||||
if (!isset($coverageData[$line])) {
|
||||
continue;
|
||||
}
|
||||
$methodLineElement = $document->createElement('line');
|
||||
|
||||
$methodLineElement->setAttribute('number', (string) $line);
|
||||
$methodLineElement->setAttribute('hits', (string) count($coverageData[$line]));
|
||||
|
||||
$methodLinesElement->appendChild($methodLineElement);
|
||||
|
||||
$classLineElement = $methodLineElement->cloneNode();
|
||||
|
||||
$classLinesElement->appendChild($classLineElement);
|
||||
}
|
||||
|
||||
$methodsElement->appendChild($methodElement);
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->numberOfFunctions() === 0) {
|
||||
$packageElement->setAttribute('complexity', (string) $packageComplexity);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$functionsComplexity = 0;
|
||||
$functionsLinesValid = 0;
|
||||
$functionsLinesCovered = 0;
|
||||
$functionsBranchesValid = 0;
|
||||
$functionsBranchesCovered = 0;
|
||||
|
||||
$classElement = $document->createElement('class');
|
||||
$classElement->setAttribute('name', basename($item->pathAsString()));
|
||||
$classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString()));
|
||||
|
||||
$methodsElement = $document->createElement('methods');
|
||||
|
||||
$classElement->appendChild($methodsElement);
|
||||
|
||||
$classLinesElement = $document->createElement('lines');
|
||||
|
||||
$classElement->appendChild($classLinesElement);
|
||||
|
||||
$functions = $item->functions();
|
||||
|
||||
foreach ($functions as $functionName => $function) {
|
||||
if ($function->executableLines === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$complexity += $function->ccn;
|
||||
$packageComplexity += $function->ccn;
|
||||
$functionsComplexity += $function->ccn;
|
||||
|
||||
$linesValid = $function->executableLines;
|
||||
$linesCovered = $function->executedLines;
|
||||
$lineRate = $linesCovered / $linesValid;
|
||||
|
||||
$functionsLinesValid += $linesValid;
|
||||
$functionsLinesCovered += $linesCovered;
|
||||
|
||||
$branchesValid = $function->executableBranches;
|
||||
$branchesCovered = $function->executedBranches;
|
||||
$branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid);
|
||||
|
||||
$functionsBranchesValid += $branchesValid;
|
||||
$functionsBranchesCovered += $branchesValid;
|
||||
|
||||
$methodElement = $document->createElement('method');
|
||||
|
||||
$methodElement->setAttribute('name', $functionName);
|
||||
$methodElement->setAttribute('signature', $function->signature);
|
||||
$methodElement->setAttribute('line-rate', (string) $lineRate);
|
||||
$methodElement->setAttribute('branch-rate', (string) $branchRate);
|
||||
$methodElement->setAttribute('complexity', (string) $function->ccn);
|
||||
|
||||
$methodLinesElement = $document->createElement('lines');
|
||||
|
||||
$methodElement->appendChild($methodLinesElement);
|
||||
|
||||
foreach (range($function->startLine, $function->endLine) as $line) {
|
||||
if (!isset($coverageData[$line])) {
|
||||
continue;
|
||||
}
|
||||
$methodLineElement = $document->createElement('line');
|
||||
|
||||
$methodLineElement->setAttribute('number', (string) $line);
|
||||
$methodLineElement->setAttribute('hits', (string) count($coverageData[$line]));
|
||||
|
||||
$methodLinesElement->appendChild($methodLineElement);
|
||||
|
||||
$classLineElement = $methodLineElement->cloneNode();
|
||||
|
||||
$classLinesElement->appendChild($classLineElement);
|
||||
}
|
||||
|
||||
$methodsElement->appendChild($methodElement);
|
||||
}
|
||||
|
||||
$packageElement->setAttribute('complexity', (string) $packageComplexity);
|
||||
|
||||
if ($functionsLinesValid === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$lineRate = $functionsLinesCovered / $functionsLinesValid;
|
||||
$branchRate = $functionsBranchesValid === 0 ? 0 : ($functionsBranchesCovered / $functionsBranchesValid);
|
||||
|
||||
$classElement->setAttribute('line-rate', (string) $lineRate);
|
||||
$classElement->setAttribute('branch-rate', (string) $branchRate);
|
||||
$classElement->setAttribute('complexity', (string) $functionsComplexity);
|
||||
|
||||
$classesElement->appendChild($classElement);
|
||||
}
|
||||
|
||||
$coverageElement->setAttribute('complexity', (string) $complexity);
|
||||
|
||||
$buffer = Xml::asString($document);
|
||||
|
||||
if ($target !== null) {
|
||||
Filesystem::write($target, $buffer);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
}
|
||||
147
vendor/phpunit/php-code-coverage/src/Report/Crap4j.php
vendored
Normal file
147
vendor/phpunit/php-code-coverage/src/Report/Crap4j.php
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
<?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\Report;
|
||||
|
||||
use function date;
|
||||
use function htmlspecialchars;
|
||||
use function is_string;
|
||||
use function round;
|
||||
use DOMDocument;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Node\File;
|
||||
use SebastianBergmann\CodeCoverage\Util\Filesystem;
|
||||
use SebastianBergmann\CodeCoverage\Util\Xml;
|
||||
use SebastianBergmann\CodeCoverage\WriteOperationFailedException;
|
||||
|
||||
final readonly class Crap4j
|
||||
{
|
||||
private int $threshold;
|
||||
|
||||
public function __construct(int $threshold = 30)
|
||||
{
|
||||
$this->threshold = $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|non-empty-string $target
|
||||
* @param null|non-empty-string $name
|
||||
*
|
||||
* @throws WriteOperationFailedException
|
||||
*/
|
||||
public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string
|
||||
{
|
||||
$document = new DOMDocument('1.0', 'UTF-8');
|
||||
|
||||
$root = $document->createElement('crap_result');
|
||||
$document->appendChild($root);
|
||||
|
||||
$project = $document->createElement('project', is_string($name) ? $name : '');
|
||||
$root->appendChild($project);
|
||||
$root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s')));
|
||||
|
||||
$stats = $document->createElement('stats');
|
||||
$methodsNode = $document->createElement('methods');
|
||||
|
||||
$report = $coverage->getReport();
|
||||
unset($coverage);
|
||||
|
||||
$fullMethodCount = 0;
|
||||
$fullCrapMethodCount = 0;
|
||||
$fullCrapLoad = 0;
|
||||
$fullCrap = 0;
|
||||
|
||||
foreach ($report as $item) {
|
||||
$namespace = 'global';
|
||||
|
||||
if (!$item instanceof File) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$file = $document->createElement('file');
|
||||
$file->setAttribute('name', $item->pathAsString());
|
||||
|
||||
$classes = $item->classesAndTraits();
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
foreach ($class->methods as $methodName => $method) {
|
||||
$crapLoad = $this->crapLoad((float) $method->crap, $method->ccn, $method->coverage);
|
||||
|
||||
$fullCrap += $method->crap;
|
||||
$fullCrapLoad += $crapLoad;
|
||||
$fullMethodCount++;
|
||||
|
||||
if ($method->crap >= $this->threshold) {
|
||||
$fullCrapMethodCount++;
|
||||
}
|
||||
|
||||
$methodNode = $document->createElement('method');
|
||||
|
||||
if ($class->namespace !== '') {
|
||||
$namespace = $class->namespace;
|
||||
}
|
||||
|
||||
$methodNode->appendChild($document->createElement('package', $namespace));
|
||||
$methodNode->appendChild($document->createElement('className', $className));
|
||||
$methodNode->appendChild($document->createElement('methodName', $methodName));
|
||||
$methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method->signature)));
|
||||
$methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method->signature)));
|
||||
$methodNode->appendChild($document->createElement('crap', (string) $this->roundValue((float) $method->crap)));
|
||||
$methodNode->appendChild($document->createElement('complexity', (string) $method->ccn));
|
||||
$methodNode->appendChild($document->createElement('coverage', (string) $this->roundValue($method->coverage)));
|
||||
$methodNode->appendChild($document->createElement('crapLoad', (string) round($crapLoad)));
|
||||
|
||||
$methodsNode->appendChild($methodNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stats->appendChild($document->createElement('name', 'Method Crap Stats'));
|
||||
$stats->appendChild($document->createElement('methodCount', (string) $fullMethodCount));
|
||||
$stats->appendChild($document->createElement('crapMethodCount', (string) $fullCrapMethodCount));
|
||||
$stats->appendChild($document->createElement('crapLoad', (string) round($fullCrapLoad)));
|
||||
$stats->appendChild($document->createElement('totalCrap', (string) $fullCrap));
|
||||
|
||||
$crapMethodPercent = 0;
|
||||
|
||||
if ($fullMethodCount > 0) {
|
||||
$crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount);
|
||||
}
|
||||
|
||||
$stats->appendChild($document->createElement('crapMethodPercent', (string) $crapMethodPercent));
|
||||
|
||||
$root->appendChild($stats);
|
||||
$root->appendChild($methodsNode);
|
||||
|
||||
$buffer = Xml::asString($document);
|
||||
|
||||
if ($target !== null) {
|
||||
Filesystem::write($target, $buffer);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
private function crapLoad(float $crapValue, int $cyclomaticComplexity, float $coveragePercent): float
|
||||
{
|
||||
$crapLoad = 0;
|
||||
|
||||
if ($crapValue >= $this->threshold) {
|
||||
$crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100);
|
||||
$crapLoad += $cyclomaticComplexity / $this->threshold;
|
||||
}
|
||||
|
||||
return $crapLoad;
|
||||
}
|
||||
|
||||
private function roundValue(float $value): float
|
||||
{
|
||||
return round($value, 2);
|
||||
}
|
||||
}
|
||||
66
vendor/phpunit/php-code-coverage/src/Report/Html/Colors.php
vendored
Normal file
66
vendor/phpunit/php-code-coverage/src/Report/Html/Colors.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?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\Report\Html;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*/
|
||||
final readonly class Colors
|
||||
{
|
||||
private string $successLow;
|
||||
private string $successMedium;
|
||||
private string $successHigh;
|
||||
private string $warning;
|
||||
private string $danger;
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return new self('#dff0d8', '#c3e3b5', '#99cb84', '#fcf8e3', '#f2dede');
|
||||
}
|
||||
|
||||
public static function from(string $successLow, string $successMedium, string $successHigh, string $warning, string $danger): self
|
||||
{
|
||||
return new self($successLow, $successMedium, $successHigh, $warning, $danger);
|
||||
}
|
||||
|
||||
private function __construct(string $successLow, string $successMedium, string $successHigh, string $warning, string $danger)
|
||||
{
|
||||
$this->successLow = $successLow;
|
||||
$this->successMedium = $successMedium;
|
||||
$this->successHigh = $successHigh;
|
||||
$this->warning = $warning;
|
||||
$this->danger = $danger;
|
||||
}
|
||||
|
||||
public function successLow(): string
|
||||
{
|
||||
return $this->successLow;
|
||||
}
|
||||
|
||||
public function successMedium(): string
|
||||
{
|
||||
return $this->successMedium;
|
||||
}
|
||||
|
||||
public function successHigh(): string
|
||||
{
|
||||
return $this->successHigh;
|
||||
}
|
||||
|
||||
public function warning(): string
|
||||
{
|
||||
return $this->warning;
|
||||
}
|
||||
|
||||
public function danger(): string
|
||||
{
|
||||
return $this->danger;
|
||||
}
|
||||
}
|
||||
50
vendor/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php
vendored
Normal file
50
vendor/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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\Report\Html;
|
||||
|
||||
use function is_file;
|
||||
use SebastianBergmann\CodeCoverage\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*/
|
||||
final readonly class CustomCssFile
|
||||
{
|
||||
private string $path;
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return new self(__DIR__ . '/Renderer/Template/css/custom.css');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function from(string $path): self
|
||||
{
|
||||
if (!is_file($path)) {
|
||||
throw new InvalidArgumentException(
|
||||
'$path does not exist',
|
||||
);
|
||||
}
|
||||
|
||||
return new self($path);
|
||||
}
|
||||
|
||||
private function __construct(string $path)
|
||||
{
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
public function path(): string
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
}
|
||||
154
vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php
vendored
Normal file
154
vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
<?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\Report\Html;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use function copy;
|
||||
use function date;
|
||||
use function dirname;
|
||||
use function str_ends_with;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException;
|
||||
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
|
||||
use SebastianBergmann\CodeCoverage\Report\Thresholds;
|
||||
use SebastianBergmann\CodeCoverage\Util\Filesystem;
|
||||
use SebastianBergmann\Template\Exception;
|
||||
use SebastianBergmann\Template\Template;
|
||||
|
||||
final readonly class Facade
|
||||
{
|
||||
private string $templatePath;
|
||||
private string $generator;
|
||||
private Colors $colors;
|
||||
private Thresholds $thresholds;
|
||||
private CustomCssFile $customCssFile;
|
||||
|
||||
public function __construct(string $generator = '', ?Colors $colors = null, ?Thresholds $thresholds = null, ?CustomCssFile $customCssFile = null)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
$this->colors = $colors ?? Colors::default();
|
||||
$this->thresholds = $thresholds ?? Thresholds::default();
|
||||
$this->customCssFile = $customCssFile ?? CustomCssFile::default();
|
||||
$this->templatePath = __DIR__ . '/Renderer/Template/';
|
||||
}
|
||||
|
||||
public function process(CodeCoverage $coverage, string $target): void
|
||||
{
|
||||
$target = $this->directory($target);
|
||||
$report = $coverage->getReport();
|
||||
$date = date('D M j G:i:s T Y');
|
||||
$hasBranchCoverage = $coverage->getData(true)->functionCoverage() !== [];
|
||||
|
||||
$dashboard = new Dashboard(
|
||||
$this->templatePath,
|
||||
$this->generator,
|
||||
$date,
|
||||
$this->thresholds,
|
||||
$hasBranchCoverage,
|
||||
);
|
||||
|
||||
$directory = new Directory(
|
||||
$this->templatePath,
|
||||
$this->generator,
|
||||
$date,
|
||||
$this->thresholds,
|
||||
$hasBranchCoverage,
|
||||
);
|
||||
|
||||
$file = new File(
|
||||
$this->templatePath,
|
||||
$this->generator,
|
||||
$date,
|
||||
$this->thresholds,
|
||||
$hasBranchCoverage,
|
||||
);
|
||||
|
||||
$directory->render($report, $target . 'index.html');
|
||||
$dashboard->render($report, $target . 'dashboard.html');
|
||||
|
||||
foreach ($report as $node) {
|
||||
$id = $node->id();
|
||||
|
||||
if ($node instanceof DirectoryNode) {
|
||||
Filesystem::createDirectory($target . $id);
|
||||
|
||||
$directory->render($node, $target . $id . '/index.html');
|
||||
$dashboard->render($node, $target . $id . '/dashboard.html');
|
||||
} else {
|
||||
$dir = dirname($target . $id);
|
||||
|
||||
Filesystem::createDirectory($dir);
|
||||
|
||||
$file->render($node, $target . $id);
|
||||
}
|
||||
}
|
||||
|
||||
$this->copyFiles($target);
|
||||
$this->renderCss($target);
|
||||
}
|
||||
|
||||
private function copyFiles(string $target): void
|
||||
{
|
||||
$dir = $this->directory($target . '_css');
|
||||
|
||||
copy($this->templatePath . 'css/billboard.min.css', $dir . 'billboard.min.css');
|
||||
copy($this->templatePath . 'css/bootstrap.min.css', $dir . 'bootstrap.min.css');
|
||||
copy($this->customCssFile->path(), $dir . 'custom.css');
|
||||
copy($this->templatePath . 'css/octicons.css', $dir . 'octicons.css');
|
||||
|
||||
$dir = $this->directory($target . '_icons');
|
||||
copy($this->templatePath . 'icons/file-code.svg', $dir . 'file-code.svg');
|
||||
copy($this->templatePath . 'icons/file-directory.svg', $dir . 'file-directory.svg');
|
||||
|
||||
$dir = $this->directory($target . '_js');
|
||||
copy($this->templatePath . 'js/billboard.pkgd.min.js', $dir . 'billboard.pkgd.min.js');
|
||||
copy($this->templatePath . 'js/bootstrap.bundle.min.js', $dir . 'bootstrap.bundle.min.js');
|
||||
copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js');
|
||||
copy($this->templatePath . 'js/file.js', $dir . 'file.js');
|
||||
}
|
||||
|
||||
private function renderCss(string $target): void
|
||||
{
|
||||
$template = new Template($this->templatePath . 'css/style.css', '{{', '}}');
|
||||
|
||||
$template->setVar(
|
||||
[
|
||||
'success-low' => $this->colors->successLow(),
|
||||
'success-medium' => $this->colors->successMedium(),
|
||||
'success-high' => $this->colors->successHigh(),
|
||||
'warning' => $this->colors->warning(),
|
||||
'danger' => $this->colors->danger(),
|
||||
],
|
||||
);
|
||||
|
||||
try {
|
||||
$template->renderTo($this->directory($target . '_css') . 'style.css');
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
throw new FileCouldNotBeWrittenException(
|
||||
$e->getMessage(),
|
||||
$e->getCode(),
|
||||
$e,
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
private function directory(string $directory): string
|
||||
{
|
||||
if (!str_ends_with($directory, DIRECTORY_SEPARATOR)) {
|
||||
$directory .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
Filesystem::createDirectory($directory);
|
||||
|
||||
return $directory;
|
||||
}
|
||||
}
|
||||
289
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php
vendored
Normal file
289
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
<?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\Report\Html;
|
||||
|
||||
use function array_pop;
|
||||
use function count;
|
||||
use function sprintf;
|
||||
use function str_repeat;
|
||||
use function substr_count;
|
||||
use SebastianBergmann\CodeCoverage\Node\AbstractNode;
|
||||
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
|
||||
use SebastianBergmann\CodeCoverage\Node\File as FileNode;
|
||||
use SebastianBergmann\CodeCoverage\Report\Thresholds;
|
||||
use SebastianBergmann\CodeCoverage\Version;
|
||||
use SebastianBergmann\Environment\Runtime;
|
||||
use SebastianBergmann\Template\Template;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
abstract class Renderer
|
||||
{
|
||||
protected string $templatePath;
|
||||
protected string $generator;
|
||||
protected string $date;
|
||||
protected Thresholds $thresholds;
|
||||
protected bool $hasBranchCoverage;
|
||||
protected string $version;
|
||||
|
||||
public function __construct(string $templatePath, string $generator, string $date, Thresholds $thresholds, bool $hasBranchCoverage)
|
||||
{
|
||||
$this->templatePath = $templatePath;
|
||||
$this->generator = $generator;
|
||||
$this->date = $date;
|
||||
$this->thresholds = $thresholds;
|
||||
$this->version = Version::id();
|
||||
$this->hasBranchCoverage = $hasBranchCoverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<non-empty-string, float|int|string> $data
|
||||
*/
|
||||
protected function renderItemTemplate(Template $template, array $data): string
|
||||
{
|
||||
$numSeparator = ' / ';
|
||||
|
||||
if (isset($data['numClasses']) && $data['numClasses'] > 0) {
|
||||
$classesLevel = $this->colorLevel($data['testedClassesPercent']);
|
||||
|
||||
$classesNumber = $data['numTestedClasses'] . $numSeparator .
|
||||
$data['numClasses'];
|
||||
|
||||
$classesBar = $this->coverageBar(
|
||||
$data['testedClassesPercent'],
|
||||
);
|
||||
} else {
|
||||
$classesLevel = '';
|
||||
$classesNumber = '0' . $numSeparator . '0';
|
||||
$classesBar = '';
|
||||
$data['testedClassesPercentAsString'] = 'n/a';
|
||||
}
|
||||
|
||||
if ($data['numMethods'] > 0) {
|
||||
$methodsLevel = $this->colorLevel($data['testedMethodsPercent']);
|
||||
|
||||
$methodsNumber = $data['numTestedMethods'] . $numSeparator .
|
||||
$data['numMethods'];
|
||||
|
||||
$methodsBar = $this->coverageBar(
|
||||
$data['testedMethodsPercent'],
|
||||
);
|
||||
} else {
|
||||
$methodsLevel = '';
|
||||
$methodsNumber = '0' . $numSeparator . '0';
|
||||
$methodsBar = '';
|
||||
$data['testedMethodsPercentAsString'] = 'n/a';
|
||||
}
|
||||
|
||||
if ($data['numExecutableLines'] > 0) {
|
||||
$linesLevel = $this->colorLevel($data['linesExecutedPercent']);
|
||||
|
||||
$linesNumber = $data['numExecutedLines'] . $numSeparator .
|
||||
$data['numExecutableLines'];
|
||||
|
||||
$linesBar = $this->coverageBar(
|
||||
$data['linesExecutedPercent'],
|
||||
);
|
||||
} else {
|
||||
$linesLevel = '';
|
||||
$linesNumber = '0' . $numSeparator . '0';
|
||||
$linesBar = '';
|
||||
$data['linesExecutedPercentAsString'] = 'n/a';
|
||||
}
|
||||
|
||||
if ($data['numExecutablePaths'] > 0) {
|
||||
$pathsLevel = $this->colorLevel($data['pathsExecutedPercent']);
|
||||
|
||||
$pathsNumber = $data['numExecutedPaths'] . $numSeparator .
|
||||
$data['numExecutablePaths'];
|
||||
|
||||
$pathsBar = $this->coverageBar(
|
||||
$data['pathsExecutedPercent'],
|
||||
);
|
||||
} else {
|
||||
$pathsLevel = '';
|
||||
$pathsNumber = '0' . $numSeparator . '0';
|
||||
$pathsBar = '';
|
||||
$data['pathsExecutedPercentAsString'] = 'n/a';
|
||||
}
|
||||
|
||||
if ($data['numExecutableBranches'] > 0) {
|
||||
$branchesLevel = $this->colorLevel($data['branchesExecutedPercent']);
|
||||
|
||||
$branchesNumber = $data['numExecutedBranches'] . $numSeparator .
|
||||
$data['numExecutableBranches'];
|
||||
|
||||
$branchesBar = $this->coverageBar(
|
||||
$data['branchesExecutedPercent'],
|
||||
);
|
||||
} else {
|
||||
$branchesLevel = '';
|
||||
$branchesNumber = '0' . $numSeparator . '0';
|
||||
$branchesBar = '';
|
||||
$data['branchesExecutedPercentAsString'] = 'n/a';
|
||||
}
|
||||
|
||||
$template->setVar(
|
||||
[
|
||||
'icon' => $data['icon'] ?? '',
|
||||
'crap' => $data['crap'] ?? '',
|
||||
'name' => $data['name'],
|
||||
'lines_bar' => $linesBar,
|
||||
'lines_executed_percent' => $data['linesExecutedPercentAsString'],
|
||||
'lines_level' => $linesLevel,
|
||||
'lines_number' => $linesNumber,
|
||||
'paths_bar' => $pathsBar,
|
||||
'paths_executed_percent' => $data['pathsExecutedPercentAsString'],
|
||||
'paths_level' => $pathsLevel,
|
||||
'paths_number' => $pathsNumber,
|
||||
'branches_bar' => $branchesBar,
|
||||
'branches_executed_percent' => $data['branchesExecutedPercentAsString'],
|
||||
'branches_level' => $branchesLevel,
|
||||
'branches_number' => $branchesNumber,
|
||||
'methods_bar' => $methodsBar,
|
||||
'methods_tested_percent' => $data['testedMethodsPercentAsString'],
|
||||
'methods_level' => $methodsLevel,
|
||||
'methods_number' => $methodsNumber,
|
||||
'classes_bar' => $classesBar,
|
||||
'classes_tested_percent' => $data['testedClassesPercentAsString'] ?? '',
|
||||
'classes_level' => $classesLevel,
|
||||
'classes_number' => $classesNumber,
|
||||
],
|
||||
);
|
||||
|
||||
return $template->render();
|
||||
}
|
||||
|
||||
protected function setCommonTemplateVariables(Template $template, AbstractNode $node): void
|
||||
{
|
||||
$template->setVar(
|
||||
[
|
||||
'id' => $node->id(),
|
||||
'full_path' => $node->pathAsString(),
|
||||
'path_to_root' => $this->pathToRoot($node),
|
||||
'breadcrumbs' => $this->breadcrumbs($node),
|
||||
'date' => $this->date,
|
||||
'version' => $this->version,
|
||||
'runtime' => $this->runtimeString(),
|
||||
'generator' => $this->generator,
|
||||
'low_upper_bound' => (string) $this->thresholds->lowUpperBound(),
|
||||
'high_lower_bound' => (string) $this->thresholds->highLowerBound(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
protected function breadcrumbs(AbstractNode $node): string
|
||||
{
|
||||
$breadcrumbs = '';
|
||||
$path = $node->pathAsArray();
|
||||
$pathToRoot = [];
|
||||
$max = count($path);
|
||||
|
||||
if ($node instanceof FileNode) {
|
||||
$max--;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
$pathToRoot[] = str_repeat('../', $i);
|
||||
}
|
||||
|
||||
foreach ($path as $step) {
|
||||
if ($step !== $node) {
|
||||
$breadcrumbs .= $this->inactiveBreadcrumb(
|
||||
$step,
|
||||
array_pop($pathToRoot),
|
||||
);
|
||||
} else {
|
||||
$breadcrumbs .= $this->activeBreadcrumb($step);
|
||||
}
|
||||
}
|
||||
|
||||
return $breadcrumbs;
|
||||
}
|
||||
|
||||
protected function activeBreadcrumb(AbstractNode $node): string
|
||||
{
|
||||
$buffer = sprintf(
|
||||
' <li class="breadcrumb-item active">%s</li>' . "\n",
|
||||
$node->name(),
|
||||
);
|
||||
|
||||
if ($node instanceof DirectoryNode) {
|
||||
$buffer .= ' <li class="breadcrumb-item">(<a href="dashboard.html">Dashboard</a>)</li>' . "\n";
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
protected function inactiveBreadcrumb(AbstractNode $node, string $pathToRoot): string
|
||||
{
|
||||
return sprintf(
|
||||
' <li class="breadcrumb-item"><a href="%sindex.html">%s</a></li>' . "\n",
|
||||
$pathToRoot,
|
||||
$node->name(),
|
||||
);
|
||||
}
|
||||
|
||||
protected function pathToRoot(AbstractNode $node): string
|
||||
{
|
||||
$id = $node->id();
|
||||
$depth = substr_count($id, '/');
|
||||
|
||||
if ($id !== 'index' &&
|
||||
$node instanceof DirectoryNode) {
|
||||
$depth++;
|
||||
}
|
||||
|
||||
return str_repeat('../', $depth);
|
||||
}
|
||||
|
||||
protected function coverageBar(float $percent): string
|
||||
{
|
||||
$level = $this->colorLevel($percent);
|
||||
|
||||
$templateName = $this->templatePath . ($this->hasBranchCoverage ? 'coverage_bar_branch.html' : 'coverage_bar.html');
|
||||
$template = new Template(
|
||||
$templateName,
|
||||
'{{',
|
||||
'}}',
|
||||
);
|
||||
|
||||
$template->setVar(['level' => $level, 'percent' => sprintf('%.2F', $percent)]);
|
||||
|
||||
return $template->render();
|
||||
}
|
||||
|
||||
protected function colorLevel(float $percent): string
|
||||
{
|
||||
if ($percent <= $this->thresholds->lowUpperBound()) {
|
||||
return 'danger';
|
||||
}
|
||||
|
||||
if ($percent > $this->thresholds->lowUpperBound() &&
|
||||
$percent < $this->thresholds->highLowerBound()) {
|
||||
return 'warning';
|
||||
}
|
||||
|
||||
return 'success';
|
||||
}
|
||||
|
||||
private function runtimeString(): string
|
||||
{
|
||||
$runtime = new Runtime;
|
||||
|
||||
return sprintf(
|
||||
'<a href="%s" target="_top">%s %s</a>',
|
||||
$runtime->getVendorUrl(),
|
||||
$runtime->getName(),
|
||||
$runtime->getVersion(),
|
||||
);
|
||||
}
|
||||
}
|
||||
330
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php
vendored
Normal file
330
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
<?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\Report\Html;
|
||||
|
||||
use function array_values;
|
||||
use function asort;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function floor;
|
||||
use function json_encode;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function uasort;
|
||||
use function usort;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedClassType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedMethodType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedTraitType;
|
||||
use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException;
|
||||
use SebastianBergmann\CodeCoverage\Node\AbstractNode;
|
||||
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
|
||||
use SebastianBergmann\Template\Exception;
|
||||
use SebastianBergmann\Template\Template;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Dashboard extends Renderer
|
||||
{
|
||||
public function render(DirectoryNode $node, string $file): void
|
||||
{
|
||||
$classes = $node->classesAndTraits();
|
||||
$templateName = $this->templatePath . ($this->hasBranchCoverage ? 'dashboard_branch.html' : 'dashboard.html');
|
||||
$template = new Template(
|
||||
$templateName,
|
||||
'{{',
|
||||
'}}',
|
||||
);
|
||||
|
||||
$this->setCommonTemplateVariables($template, $node);
|
||||
|
||||
$baseLink = $node->id() . '/';
|
||||
$complexity = $this->complexity($classes, $baseLink);
|
||||
$coverageDistribution = $this->coverageDistribution($classes);
|
||||
$insufficientCoverage = $this->insufficientCoverage($classes, $baseLink);
|
||||
$projectRisks = $this->projectRisks($classes, $baseLink);
|
||||
|
||||
$template->setVar(
|
||||
[
|
||||
'insufficient_coverage_classes' => $insufficientCoverage['class'],
|
||||
'insufficient_coverage_methods' => $insufficientCoverage['method'],
|
||||
'project_risks_classes' => $projectRisks['class'],
|
||||
'project_risks_methods' => $projectRisks['method'],
|
||||
'complexity_class' => $complexity['class'],
|
||||
'complexity_method' => $complexity['method'],
|
||||
'class_coverage_distribution' => $coverageDistribution['class'],
|
||||
'method_coverage_distribution' => $coverageDistribution['method'],
|
||||
],
|
||||
);
|
||||
|
||||
try {
|
||||
$template->renderTo($file);
|
||||
} catch (Exception $e) {
|
||||
throw new FileCouldNotBeWrittenException(
|
||||
$e->getMessage(),
|
||||
$e->getCode(),
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function activeBreadcrumb(AbstractNode $node): string
|
||||
{
|
||||
return sprintf(
|
||||
' <li class="breadcrumb-item"><a href="index.html">%s</a></li>' . "\n" .
|
||||
' <li class="breadcrumb-item active">(Dashboard)</li>' . "\n",
|
||||
$node->name(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ProcessedClassType|ProcessedTraitType> $classes
|
||||
*
|
||||
* @return array{class: non-empty-string, method: non-empty-string}
|
||||
*/
|
||||
private function complexity(array $classes, string $baseLink): array
|
||||
{
|
||||
$result = ['class' => [], 'method' => []];
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
foreach ($class->methods as $methodName => $method) {
|
||||
if ($className !== '*') {
|
||||
$methodName = $className . '::' . $methodName;
|
||||
}
|
||||
|
||||
$result['method'][] = [
|
||||
$method->coverage,
|
||||
$method->ccn,
|
||||
str_replace($baseLink, '', $method->link),
|
||||
$methodName,
|
||||
$method->crap,
|
||||
];
|
||||
}
|
||||
|
||||
$result['class'][] = [
|
||||
$class->coverage,
|
||||
$class->ccn,
|
||||
str_replace($baseLink, '', $class->link),
|
||||
$className,
|
||||
$class->crap,
|
||||
];
|
||||
}
|
||||
|
||||
usort($result['class'], static fn (mixed $a, mixed $b) => ($a[0] <=> $b[0]));
|
||||
usort($result['method'], static fn (mixed $a, mixed $b) => ($a[0] <=> $b[0]));
|
||||
|
||||
$class = json_encode($result['class']);
|
||||
|
||||
assert($class !== false);
|
||||
|
||||
$method = json_encode($result['method']);
|
||||
|
||||
assert($method !== false);
|
||||
|
||||
return ['class' => $class, 'method' => $method];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ProcessedClassType|ProcessedTraitType> $classes
|
||||
*
|
||||
* @return array{class: non-empty-string, method: non-empty-string}
|
||||
*/
|
||||
private function coverageDistribution(array $classes): array
|
||||
{
|
||||
$result = [
|
||||
'class' => [
|
||||
'0%' => 0,
|
||||
'0-10%' => 0,
|
||||
'10-20%' => 0,
|
||||
'20-30%' => 0,
|
||||
'30-40%' => 0,
|
||||
'40-50%' => 0,
|
||||
'50-60%' => 0,
|
||||
'60-70%' => 0,
|
||||
'70-80%' => 0,
|
||||
'80-90%' => 0,
|
||||
'90-100%' => 0,
|
||||
'100%' => 0,
|
||||
],
|
||||
'method' => [
|
||||
'0%' => 0,
|
||||
'0-10%' => 0,
|
||||
'10-20%' => 0,
|
||||
'20-30%' => 0,
|
||||
'30-40%' => 0,
|
||||
'40-50%' => 0,
|
||||
'50-60%' => 0,
|
||||
'60-70%' => 0,
|
||||
'70-80%' => 0,
|
||||
'80-90%' => 0,
|
||||
'90-100%' => 0,
|
||||
'100%' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($classes as $class) {
|
||||
foreach ($class->methods as $method) {
|
||||
if ($method->coverage === 0) {
|
||||
$result['method']['0%']++;
|
||||
} elseif ($method->coverage === 100) {
|
||||
$result['method']['100%']++;
|
||||
} else {
|
||||
$key = floor($method->coverage / 10) * 10;
|
||||
$key = $key . '-' . ($key + 10) . '%';
|
||||
$result['method'][$key]++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($class->coverage === 0) {
|
||||
$result['class']['0%']++;
|
||||
} elseif ($class->coverage === 100) {
|
||||
$result['class']['100%']++;
|
||||
} else {
|
||||
$key = floor($class->coverage / 10) * 10;
|
||||
$key = $key . '-' . ($key + 10) . '%';
|
||||
$result['class'][$key]++;
|
||||
}
|
||||
}
|
||||
|
||||
$class = json_encode(array_values($result['class']));
|
||||
|
||||
assert($class !== false);
|
||||
|
||||
$method = json_encode(array_values($result['method']));
|
||||
|
||||
assert($method !== false);
|
||||
|
||||
return ['class' => $class, 'method' => $method];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ProcessedClassType|ProcessedTraitType> $classes
|
||||
*
|
||||
* @return array{class: string, method: string}
|
||||
*/
|
||||
private function insufficientCoverage(array $classes, string $baseLink): array
|
||||
{
|
||||
$leastTestedClasses = [];
|
||||
$leastTestedMethods = [];
|
||||
$result = ['class' => '', 'method' => ''];
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
foreach ($class->methods as $methodName => $method) {
|
||||
if ($method->coverage < $this->thresholds->highLowerBound()) {
|
||||
$key = $methodName;
|
||||
|
||||
if ($className !== '*') {
|
||||
$key = $className . '::' . $methodName;
|
||||
}
|
||||
|
||||
$leastTestedMethods[$key] = $method->coverage;
|
||||
}
|
||||
}
|
||||
|
||||
if ($class->coverage < $this->thresholds->highLowerBound()) {
|
||||
$leastTestedClasses[$className] = $class->coverage;
|
||||
}
|
||||
}
|
||||
|
||||
asort($leastTestedClasses);
|
||||
asort($leastTestedMethods);
|
||||
|
||||
foreach ($leastTestedClasses as $className => $coverage) {
|
||||
$result['class'] .= sprintf(
|
||||
' <tr><td><a href="%s">%s</a></td><td class="text-right">%d%%</td></tr>' . "\n",
|
||||
str_replace($baseLink, '', $classes[$className]->link),
|
||||
$className,
|
||||
$coverage,
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($leastTestedMethods as $methodName => $coverage) {
|
||||
[$class, $method] = explode('::', $methodName);
|
||||
|
||||
$result['method'] .= sprintf(
|
||||
' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d%%</td></tr>' . "\n",
|
||||
str_replace($baseLink, '', $classes[$class]->methods[$method]->link),
|
||||
$methodName,
|
||||
$method,
|
||||
$coverage,
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ProcessedClassType|ProcessedTraitType> $classes
|
||||
*
|
||||
* @return array{class: string, method: string}
|
||||
*/
|
||||
private function projectRisks(array $classes, string $baseLink): array
|
||||
{
|
||||
$classRisks = [];
|
||||
$methodRisks = [];
|
||||
$result = ['class' => '', 'method' => ''];
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
foreach ($class->methods as $methodName => $method) {
|
||||
if ($method->coverage < $this->thresholds->highLowerBound() && $method->ccn > 1) {
|
||||
$key = $methodName;
|
||||
|
||||
if ($className !== '*') {
|
||||
$key = $className . '::' . $methodName;
|
||||
}
|
||||
|
||||
$methodRisks[$key] = $method;
|
||||
}
|
||||
}
|
||||
|
||||
if ($class->coverage < $this->thresholds->highLowerBound() &&
|
||||
$class->ccn > count($class->methods)) {
|
||||
$classRisks[$className] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
uasort($classRisks, static function (ProcessedClassType|ProcessedTraitType $a, ProcessedClassType|ProcessedTraitType $b)
|
||||
{
|
||||
return ((int) ($a->crap) <=> (int) ($b->crap)) * -1;
|
||||
});
|
||||
uasort($methodRisks, static function (ProcessedMethodType $a, ProcessedMethodType $b)
|
||||
{
|
||||
return ((int) ($a->crap) <=> (int) ($b->crap)) * -1;
|
||||
});
|
||||
|
||||
foreach ($classRisks as $className => $class) {
|
||||
$result['class'] .= sprintf(
|
||||
' <tr><td><a href="%s">%s</a></td><td class="text-right">%.1f%%</td><td class="text-right">%d</td><td class="text-right">%d</td></tr>' . "\n",
|
||||
str_replace($baseLink, '', $classes[$className]->link),
|
||||
$className,
|
||||
$class->coverage,
|
||||
$class->ccn,
|
||||
$class->crap,
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($methodRisks as $methodName => $methodVals) {
|
||||
[$class, $method] = explode('::', $methodName);
|
||||
|
||||
$result['method'] .= sprintf(
|
||||
' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%.1f%%</td><td class="text-right">%d</td><td class="text-right">%d</td></tr>' . "\n",
|
||||
str_replace($baseLink, '', $classes[$class]->methods[$method]->link),
|
||||
$methodName,
|
||||
$method,
|
||||
$methodVals->coverage,
|
||||
$methodVals->ccn,
|
||||
$methodVals->crap,
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
123
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php
vendored
Normal file
123
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
<?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\Report\Html;
|
||||
|
||||
use function count;
|
||||
use function sprintf;
|
||||
use function str_repeat;
|
||||
use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException;
|
||||
use SebastianBergmann\CodeCoverage\Node\AbstractNode as Node;
|
||||
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
|
||||
use SebastianBergmann\Template\Exception;
|
||||
use SebastianBergmann\Template\Template;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Directory extends Renderer
|
||||
{
|
||||
public function render(DirectoryNode $node, string $file): void
|
||||
{
|
||||
$templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_branch.html' : 'directory.html');
|
||||
$template = new Template($templateName, '{{', '}}');
|
||||
|
||||
$this->setCommonTemplateVariables($template, $node);
|
||||
|
||||
$items = $this->renderItem($node, true);
|
||||
|
||||
foreach ($node->directories() as $item) {
|
||||
$items .= $this->renderItem($item);
|
||||
}
|
||||
|
||||
foreach ($node->files() as $item) {
|
||||
$items .= $this->renderItem($item);
|
||||
}
|
||||
|
||||
$template->setVar(
|
||||
[
|
||||
'id' => $node->id(),
|
||||
'items' => $items,
|
||||
],
|
||||
);
|
||||
|
||||
try {
|
||||
$template->renderTo($file);
|
||||
} catch (Exception $e) {
|
||||
throw new FileCouldNotBeWrittenException(
|
||||
$e->getMessage(),
|
||||
$e->getCode(),
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderItem(Node $node, bool $total = false): string
|
||||
{
|
||||
$data = [
|
||||
'numClasses' => $node->numberOfClassesAndTraits(),
|
||||
'numTestedClasses' => $node->numberOfTestedClassesAndTraits(),
|
||||
'numMethods' => $node->numberOfFunctionsAndMethods(),
|
||||
'numTestedMethods' => $node->numberOfTestedFunctionsAndMethods(),
|
||||
'linesExecutedPercent' => $node->percentageOfExecutedLines()->asFloat(),
|
||||
'linesExecutedPercentAsString' => $node->percentageOfExecutedLines()->asString(),
|
||||
'numExecutedLines' => $node->numberOfExecutedLines(),
|
||||
'numExecutableLines' => $node->numberOfExecutableLines(),
|
||||
'branchesExecutedPercent' => $node->percentageOfExecutedBranches()->asFloat(),
|
||||
'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(),
|
||||
'numExecutedBranches' => $node->numberOfExecutedBranches(),
|
||||
'numExecutableBranches' => $node->numberOfExecutableBranches(),
|
||||
'pathsExecutedPercent' => $node->percentageOfExecutedPaths()->asFloat(),
|
||||
'pathsExecutedPercentAsString' => $node->percentageOfExecutedPaths()->asString(),
|
||||
'numExecutedPaths' => $node->numberOfExecutedPaths(),
|
||||
'numExecutablePaths' => $node->numberOfExecutablePaths(),
|
||||
'testedMethodsPercent' => $node->percentageOfTestedFunctionsAndMethods()->asFloat(),
|
||||
'testedMethodsPercentAsString' => $node->percentageOfTestedFunctionsAndMethods()->asString(),
|
||||
'testedClassesPercent' => $node->percentageOfTestedClassesAndTraits()->asFloat(),
|
||||
'testedClassesPercentAsString' => $node->percentageOfTestedClassesAndTraits()->asString(),
|
||||
];
|
||||
|
||||
if ($total) {
|
||||
$data['name'] = 'Total';
|
||||
} else {
|
||||
$up = str_repeat('../', count($node->pathAsArray()) - 2);
|
||||
$data['icon'] = sprintf('<img src="%s_icons/file-code.svg" class="octicon" />', $up);
|
||||
|
||||
if ($node instanceof DirectoryNode) {
|
||||
$data['name'] = sprintf(
|
||||
'<a href="%s/index.html">%s</a>',
|
||||
$node->name(),
|
||||
$node->name(),
|
||||
);
|
||||
$data['icon'] = sprintf('<img src="%s_icons/file-directory.svg" class="octicon" />', $up);
|
||||
} elseif ($this->hasBranchCoverage) {
|
||||
$data['name'] = sprintf(
|
||||
'%s <a class="small" href="%s.html">[line]</a> <a class="small" href="%s_branch.html">[branch]</a> <a class="small" href="%s_path.html">[path]</a>',
|
||||
$node->name(),
|
||||
$node->name(),
|
||||
$node->name(),
|
||||
$node->name(),
|
||||
);
|
||||
} else {
|
||||
$data['name'] = sprintf(
|
||||
'<a href="%s.html">%s</a>',
|
||||
$node->name(),
|
||||
$node->name(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_item_branch.html' : 'directory_item.html');
|
||||
|
||||
return $this->renderItemTemplate(
|
||||
new Template($templateName, '{{', '}}'),
|
||||
$data,
|
||||
);
|
||||
}
|
||||
}
|
||||
1162
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php
vendored
Normal file
1162
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist
vendored
Normal file
9
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<hr/>
|
||||
<h4>Branches</h4>
|
||||
<p>
|
||||
Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not
|
||||
necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once.
|
||||
Please also be aware that some branches may be implicit rather than explicit, e.g. an <code>if</code> statement
|
||||
<i>always</i> has an <code>else</code> as part of its logical flow even if you didn't write one.
|
||||
</p>
|
||||
{{branches}}
|
||||
5
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist
vendored
Normal file
5
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-{{level}}" role="progressbar" aria-valuenow="{{percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{percent}}%">
|
||||
<span class="visually-hidden">{{percent}}% covered ({{level}})</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,5 @@
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-{{level}}" role="progressbar" aria-valuenow="{{percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{percent}}%">
|
||||
<span class="visually-hidden">{{percent}}% covered ({{level}})</span>
|
||||
</div>
|
||||
</div>
|
||||
10
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/billboard.min.css
vendored
Normal file
10
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/billboard.min.css
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/*!
|
||||
* Copyright (c) 2017 ~ present NAVER Corp.
|
||||
* billboard.js project is licensed under the MIT license
|
||||
*
|
||||
* billboard.js, JavaScript chart library
|
||||
* https://naver.github.io/billboard.js/
|
||||
*
|
||||
* @version 3.15.1
|
||||
*/
|
||||
.bb svg{font:10px sans-serif;-webkit-tap-highlight-color:rgba(0,0,0,0)}.bb path,.bb line{fill:none;stroke:#000}.bb text,.bb .bb-button{-webkit-user-select:none;-moz-user-select:none;user-select:none}.bb-legend-item-tile,.bb-xgrid-focus,.bb-ygrid-focus,.bb-ygrid{shape-rendering:crispEdges}.bb-chart-arcs .bb-needle,.bb-chart-arc .bb-gauge-value{fill:#000}.bb-chart-arc path{stroke:#fff}.bb-chart-arc rect{stroke:#fff;stroke-width:1}.bb-chart-arc text{fill:#fff;font-size:13px}.bb-chart-funnels path{stroke-width:0}.bb-chart-funnels+.bb-chart-texts text{font-size:13px;fill:#fff}.bb-axis{shape-rendering:crispEdges}.bb-axis .bb-axis-x-tooltip,.bb-axis .bb-axis-y-tooltip,.bb-axis .bb-axis-y2-tooltip{font-size:1em;fill:#fff;white-space:nowrap}.bb-grid{pointer-events:none}.bb-grid line{stroke:#aaa}.bb-grid text{fill:#aaa}.bb-xgrid,.bb-ygrid{stroke-dasharray:3 3}.bb-text.bb-empty{fill:gray;font-size:2em}.bb-line{stroke-width:1px}.bb-circle._expanded_{stroke-width:1px;stroke:#fff}.bb-selected-circle{fill:#fff;stroke-width:2px}.bb-bar{stroke-width:0}.bb-bar._expanded_{fill-opacity:.75}.bb-candlestick{stroke-width:1px}.bb-candlestick._expanded_{fill-opacity:.75}.bb-target.bb-focused,.bb-circles.bb-focused{opacity:1}.bb-target.bb-focused path.bb-line,.bb-target.bb-focused path.bb-step,.bb-circles.bb-focused path.bb-line,.bb-circles.bb-focused path.bb-step{stroke-width:2px}.bb-target.bb-defocused,.bb-circles.bb-defocused{opacity:.3!important}.bb-target.bb-defocused .text-overlapping,.bb-circles.bb-defocused .text-overlapping{opacity:.05!important}.bb-region{fill:#4682b4}.bb-region rect{fill-opacity:.1}.bb-zoom-brush,.bb-brush .extent{fill-opacity:.1}.bb-legend-item{font-size:12px;user-select:none}.bb-legend-item-hidden{opacity:.15}.bb-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.bb-title{font:14px sans-serif}.bb-chart-treemaps rect{stroke:#fff;stroke-width:1px}.bb-tooltip-container{z-index:10;user-select:none}.bb-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;opacity:.9;box-shadow:7px 7px 12px -9px #777;white-space:nowrap}.bb-tooltip tr{border:1px solid #CCC}.bb-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#fff}.bb-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.bb-tooltip td>span,.bb-tooltip td>svg{display:inline-block;width:10px;height:10px;margin-right:6px}.bb-tooltip.value{text-align:right}.bb-area{stroke-width:0;opacity:.2}.bb-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}text.bb-chart-arcs-gauge-title{dominant-baseline:middle;font-size:2.7em}.bb-chart-arcs .bb-chart-arcs-background{fill:#e0e0e0;stroke:#fff}.bb-chart-arcs .bb-chart-arcs-gauge-unit{fill:#000;font-size:16px}.bb-chart-arcs .bb-chart-arcs-gauge-max,.bb-chart-arcs .bb-chart-arcs-gauge-min{fill:#777}.bb-chart-arcs .bb-levels circle{fill:none;stroke:#848282;stroke-width:.5px}.bb-chart-arcs .bb-levels text{fill:#848282}.bb-chart-radars .bb-levels polygon{fill:none;stroke:#848282;stroke-width:.5px}.bb-chart-radars .bb-levels text{fill:#848282}.bb-chart-radars .bb-axis line{stroke:#848282;stroke-width:.5px}.bb-chart-radars .bb-axis text{font-size:1.15em;cursor:default}.bb-chart-radars .bb-shapes polygon{fill-opacity:.2;stroke-width:1px}.bb-button{position:absolute;top:10px;right:10px}.bb-button .bb-zoom-reset{font-size:11px;border:solid 1px #ccc;background-color:#fff;padding:5px;border-radius:5px;cursor:pointer}
|
||||
6
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css
vendored
Normal file
6
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
0
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css
vendored
Normal file
0
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css
vendored
Normal file
5
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css
vendored
Normal file
5
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.octicon {
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
fill: currentColor;
|
||||
}
|
||||
274
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css
vendored
Normal file
274
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
|
||||
:root {
|
||||
/* Implementing an auto-selection of dark/light theme via: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark */
|
||||
color-scheme: light dark;
|
||||
|
||||
/* PHPUnit light/dark colors */
|
||||
--phpunit-breadcrumbs: light-dark(var(--bs-gray-200), var(--bs-gray-800));
|
||||
--phpunit-success-bar: light-dark(#28a745 ,#1f8135);
|
||||
--phpunit-success-high: light-dark(#99cb84, #3d5c4e);
|
||||
--phpunit-success-medium: light-dark(#c3e3b5,#3c6051);
|
||||
--phpunit-success-low: light-dark(#dff0d8, #2d4431);
|
||||
--phpunit-warning: light-dark(#fcf8e3, #3e3408);
|
||||
--phpunit-warning-bar: light-dark(#ffc107 ,#c19406);
|
||||
--phpunit-danger: light-dark(#f2dede, #42221e);
|
||||
--phpunit-danger-bar: light-dark(#dc3545, #a62633);
|
||||
|
||||
/* Bootstrap v5.3 default colors (light, dark) */
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-body-bg: light-dark(#fff, #212529);
|
||||
--bs-body-color-rgb: light-dark(33, 37, 41, 222, 226, 230);
|
||||
--bs-body-color: light-dark(#212529, #dee2e6);
|
||||
--bs-border-color-translucent: light-dark(rgba(0, 0, 0, 0.175), rgba(255, 255, 255, 0.15));
|
||||
--bs-border-color: light-dark(#dee2e6, #495057);
|
||||
--bs-code-color: light-dark(#d63384, #e685b5);
|
||||
--bs-danger-bg-subtle: light-dark(#f8d7da, #2c0b0e);
|
||||
--bs-danger-border-subtle: light-dark(#f1aeb5, #842029);
|
||||
--bs-danger-text-emphasis: light-dark(#58151c, #ea868f);
|
||||
--bs-dark-bg-subtle: light-dark(#ced4da, #1a1d20);
|
||||
--bs-dark-border-subtle: light-dark(#adb5bd, #343a40);
|
||||
--bs-dark-text-emphasis: light-dark(#495057, #dee2e6);
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-emphasis-color: light-dark(#000, #fff);
|
||||
--bs-form-invalid-border-color: light-dark(#dc3545, #ea868f);
|
||||
--bs-form-invalid-color: light-dark(#dc3545, #ea868f);
|
||||
--bs-form-valid-border-color: light-dark(#198754, #75b798);
|
||||
--bs-form-valid-color: light-dark(#198754, #75b798);
|
||||
--bs-highlight-bg: light-dark(#fff3cd, #664d03);
|
||||
--bs-highlight-color: light-dark(#212529, #dee2e6);
|
||||
--bs-info-bg-subtle: light-dark(#cff4fc, #032830);
|
||||
--bs-info-border-subtle: light-dark(#9eeaf9, #087990);
|
||||
--bs-info-text-emphasis: light-dark(#055160, #6edff6);
|
||||
--bs-light-bg-subtle: light-dark(#fcfcfd, #343a40);
|
||||
--bs-light-border-subtle: light-dark(#e9ecef, #495057);
|
||||
--bs-light-text-emphasis: light-dark(#495057, #f8f9fa);
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-color: light-dark(#0d6efd, #6ea8fe);
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-link-hover-color: light-dark(#0a58ca, #8bb9fe);
|
||||
--bs-primary-bg-subtle: light-dark(#cfe2ff, #031633);
|
||||
--bs-primary-border-subtle: light-dark(#9ec5fe, #084298);
|
||||
--bs-primary-text-emphasis: light-dark(#052c65, #6ea8fe);
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-secondary-bg-subtle: light-dark(#e2e3e5, #161719);
|
||||
--bs-secondary-bg: light-dark(#e9ecef, #343a40);
|
||||
--bs-secondary-border-subtle: light-dark(#c4c8cb, #41464b);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-color: light-dark(rgba(33, 37, 41, 0.75), rgba(222, 226, 230, 0.75));
|
||||
--bs-secondary-text-emphasis: light-dark(#2b2f32, #a7acb1);
|
||||
--bs-success-bg-subtle: light-dark(#d1e7dd, #051b11);
|
||||
--bs-success-border-subtle: light-dark(#a3cfbb, #0f5132);
|
||||
--bs-success-text-emphasis: light-dark(#0a3622, #75b798);
|
||||
--bs-tertiary-bg-rgb: light-dark(248, 249, 250, 43, 48, 53);
|
||||
--bs-tertiary-bg: light-dark(#f8f9fa, #2b3035);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-color: light-dark(rgba(33, 37, 41, 0.5), rgba(222, 226, 230, 0.5));
|
||||
--bs-warning-bg-subtle: light-dark(#fff3cd, #332701);
|
||||
--bs-warning-border-subtle: light-dark(#ffe69c, #997404);
|
||||
--bs-warning-text-emphasis: light-dark(#664d03, #ffda6a);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
}
|
||||
|
||||
/* Invert icon's colors on dark mode to improve readability */
|
||||
img.octicon { filter: invert(1); }
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
font-kerning: normal;
|
||||
text-rendering: optimizeLegibility;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
nav .breadcrumb {
|
||||
border-radius: var(--bs-border-radius);
|
||||
background-color: var(--phpunit-breadcrumbs);
|
||||
padding: .75rem 1rem;
|
||||
}
|
||||
|
||||
.popover {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.popover-body {
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.octicon {
|
||||
margin-right:.25em;
|
||||
vertical-align: baseline;
|
||||
width: 0.75em;
|
||||
}
|
||||
|
||||
.table-bordered>thead>tr>td {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.table tbody>tr>td, .table thead>tr>td {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.table-condensed tbody>tr>td {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.table .progress {
|
||||
margin-bottom: inherit;
|
||||
}
|
||||
|
||||
.table-borderless th, .table-borderless td {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.table tbody tr.covered-by-large-tests, .table tbody tr.covered-by-large-tests td, li.covered-by-large-tests, tr.success, tr.success td, td.success, li.success, span.success {
|
||||
background-color: var(--phpunit-success-low);
|
||||
}
|
||||
|
||||
.table tbody tr.covered-by-medium-tests, .table tbody tr.covered-by-medium-tests td, li.covered-by-medium-tests {
|
||||
background-color: var(--phpunit-success-medium);
|
||||
}
|
||||
|
||||
.table tbody tr.covered-by-small-tests, .table tbody tr.covered-by-small-tests td, li.covered-by-small-tests {
|
||||
background-color: var(--phpunit-success-high);
|
||||
}
|
||||
|
||||
.table tbody tr.warning, .table tbody tr.warning td, .table tbody td.warning, li.warning, span.warning {
|
||||
background-color: var(--phpunit-warning);
|
||||
}
|
||||
|
||||
.table tbody tr.danger, .table tbody tr.danger td, .table tbody td.danger, li.danger, span.danger {
|
||||
background-color: var(--phpunit-danger);
|
||||
}
|
||||
|
||||
.table tbody td.info {
|
||||
background-color: rgb(from var(--bs-info) r g b / 0.25);
|
||||
}
|
||||
|
||||
td.big {
|
||||
vertical-align: middle;
|
||||
width: 117px;
|
||||
}
|
||||
|
||||
td.small {
|
||||
}
|
||||
|
||||
td.codeLine {
|
||||
font-family: "Source Code Pro", var(--bs-font-monospace);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
td span.comment {
|
||||
color: var(--bs-secondary-color);
|
||||
}
|
||||
|
||||
td span.default {
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
|
||||
td span.html {
|
||||
color: var(--bs-secondary-color);
|
||||
}
|
||||
|
||||
td span.keyword {
|
||||
color: var(--bs-body-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre span.string {
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
|
||||
span.success, span.warning, span.danger {
|
||||
margin-right: 2px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#toplink {
|
||||
position: fixed;
|
||||
left: 5px;
|
||||
bottom: 5px;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
svg text {
|
||||
font-family: var(--bs-font-sans-serif);
|
||||
font-size: 11px;
|
||||
color: var(--bs-gray);
|
||||
fill: var(--bs-gray);
|
||||
}
|
||||
|
||||
.scrollbox {
|
||||
height:245px;
|
||||
overflow-x:scroll;
|
||||
overflow-y:scroll;
|
||||
}
|
||||
|
||||
table + .structure-heading {
|
||||
border-top: 1px solid var(--bs-gray-200);
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
|
||||
table#code td:first-of-type {
|
||||
padding-left: .75em;
|
||||
padding-right: .75em;
|
||||
}
|
||||
|
||||
table#code td:first-of-type a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.legend {
|
||||
font-weight: bold;
|
||||
margin-right: 2px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.covered-by-small-tests {
|
||||
background-color: var(--phpunit-success-high);
|
||||
}
|
||||
|
||||
.covered-by-medium-tests {
|
||||
background-color: var(--phpunit-success-medium);
|
||||
}
|
||||
|
||||
.covered-by-large-tests {
|
||||
background-color: var(--phpunit-success-low);
|
||||
}
|
||||
|
||||
.not-covered {
|
||||
background-color: var(--phpunit-danger);
|
||||
}
|
||||
|
||||
.not-coverable {
|
||||
background-color: var(--phpunit-warning);
|
||||
}
|
||||
|
||||
.progress-bar.bg-success {
|
||||
background-color: var(--phpunit-success-bar) !important;
|
||||
}
|
||||
|
||||
.progress-bar.bg-warning {
|
||||
background-color: var(--phpunit-warning-bar) !important;
|
||||
}
|
||||
|
||||
.progress-bar.bg-danger {
|
||||
background-color: var(--phpunit-danger-bar) !important;
|
||||
}
|
||||
299
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist
vendored
Normal file
299
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Dashboard for {{full_path}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="{{path_to_root}}_css/bootstrap.min.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/billboard.min.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/style.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
{{breadcrumbs}}
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Classes</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3>Coverage Distribution</h3>
|
||||
<div id="classesCoverageDistribution" style="height: 300px;">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3>Complexity</h3>
|
||||
<div id="classComplexity" style="height: 300px;">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3 style="margin-top: 2rem;">Insufficient Coverage</h3>
|
||||
<div class="scrollbox">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Class</th>
|
||||
<th class="text-right">Coverage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{insufficient_coverage_classes}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3 style="margin-top: 2rem;">Project Risks</h3>
|
||||
<div class="scrollbox">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Class</th>
|
||||
<th class="text-right">Coverage</th>
|
||||
<th class="text-right">Complexity</th>
|
||||
<th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{project_risks_classes}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2 style="margin-top: 3rem;">Methods</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3>Coverage Distribution</h3>
|
||||
<div id="methodsCoverageDistribution" style="height: 300px;">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3>Complexity</h3>
|
||||
<div id="methodComplexity" style="height: 300px;">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3 style="margin-top: 2rem;">Insufficient Coverage</h3>
|
||||
<div class="scrollbox">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th class="text-right">Coverage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{insufficient_coverage_methods}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3 style="margin-top: 2rem;">Project Risks</h3>
|
||||
<div class="scrollbox">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th class="text-right">Coverage</th>
|
||||
<th class="text-right">Complexity</th>
|
||||
<th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{project_risks_methods}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<hr/>
|
||||
<p>
|
||||
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="{{path_to_root}}_js/billboard.pkgd.min.js?v={{version}}" type="text/javascript"></script>
|
||||
<script type="application/json" id="complexity_class">{{complexity_class}}</script>
|
||||
<script type="application/json" id="complexity_method">{{complexity_method}}</script>
|
||||
<script type="text/javascript" defer>
|
||||
const barLabels = [
|
||||
'0%',
|
||||
'0-10%',
|
||||
'10-20%',
|
||||
'20-30%',
|
||||
'30-40%',
|
||||
'40-50%',
|
||||
'50-60%',
|
||||
'60-70%',
|
||||
'70-80%',
|
||||
'80-90%',
|
||||
'90-100%',
|
||||
'100%'
|
||||
];
|
||||
const barConfig = (name, fullName, values) => ({
|
||||
axis: {
|
||||
x: {
|
||||
type: "category",
|
||||
categories: barLabels,
|
||||
},
|
||||
y: {
|
||||
label: {
|
||||
text: `#${name}`,
|
||||
position: 'outer-top',
|
||||
},
|
||||
},
|
||||
},
|
||||
bindto: `#${name}CoverageDistribution`,
|
||||
data: {
|
||||
columns: [
|
||||
[fullName].concat(values),
|
||||
],
|
||||
colors: {
|
||||
[fullName]: "rgba(69, 114, 167, 0.75)",
|
||||
},
|
||||
type: "bar",
|
||||
},
|
||||
bar: {
|
||||
width: {
|
||||
ratio: 0.9,
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
focus: {
|
||||
show: false,
|
||||
},
|
||||
x: {
|
||||
show: true,
|
||||
},
|
||||
y: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
tooltip: {
|
||||
contents: function (data) {
|
||||
return `<table class="bb-tooltip"><tbody>
|
||||
<tr><th colspan="2">Coverage ${barLabels[data[0].x]}</th></tr>
|
||||
<tr><td class="value">${data[0].value} ${name}</td></tr>
|
||||
</tbody></table>`;
|
||||
},
|
||||
grouped: false,
|
||||
},
|
||||
});
|
||||
bb.generate(
|
||||
barConfig('classes', "Class Coverage", {{class_coverage_distribution}})
|
||||
);
|
||||
bb.generate(
|
||||
barConfig('methods', "Method Coverage", {{method_coverage_distribution}})
|
||||
);
|
||||
|
||||
const scatterConfig = (name, complexityData) => ({
|
||||
axis: {
|
||||
x: {
|
||||
label: {
|
||||
text: 'Code Coverage (in percent)',
|
||||
position: 'outer-right',
|
||||
},
|
||||
tick: {
|
||||
values: [0, 20, 40, 60, 80, 100],
|
||||
},
|
||||
},
|
||||
y: {
|
||||
label: {
|
||||
text: 'Cyclomatic Complexity',
|
||||
position: 'outer-top',
|
||||
},
|
||||
min: 0,
|
||||
padding: {
|
||||
bottom: 0,
|
||||
top: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
bindto: `#${name}Complexity`,
|
||||
data: {
|
||||
columns: [
|
||||
["complexity_x"].concat(complexityData.map(d => d[0])),
|
||||
["complexity"].concat(complexityData.map(d => d[1])),
|
||||
],
|
||||
onclick: function(data, element) {
|
||||
window.location = complexityData[data.index][2];
|
||||
},
|
||||
type: "scatter",
|
||||
xs: {
|
||||
"complexity": "complexity_x",
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
focus: {
|
||||
show: true,
|
||||
y: true,
|
||||
},
|
||||
x: {
|
||||
show: true,
|
||||
},
|
||||
y: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
tooltip: {
|
||||
contents: function (data) {
|
||||
const coverage = Math.round(data[0].x);
|
||||
const complexity = data[0].value;
|
||||
const targetName = complexityData[data[0].index][3];
|
||||
const crap = complexityData[data[0].index][4];
|
||||
return `<table class="bb-tooltip"><tbody>
|
||||
<tr><th colspan="2">${targetName}</th></tr>
|
||||
<tr class="bb-tooltip-name-complexity"><td>Coverage</td><td class="name">${coverage}%</td></tr>
|
||||
<tr class="bb-tooltip-name-complexity"><td>Complexity</td><td class="value">${complexity}</td></tr>
|
||||
<tr class="bb-tooltip-name-complexity"><td>Crap</td><td class="value">${crap}</td></tr>
|
||||
</tbody></table>`;
|
||||
},
|
||||
grouped: false,
|
||||
},
|
||||
});
|
||||
const classComplexityData = JSON.parse(document.getElementById('complexity_class').textContent);
|
||||
bb.generate(
|
||||
scatterConfig("class", classComplexityData)
|
||||
);
|
||||
const methodComplexityData = JSON.parse(document.getElementById('complexity_method').textContent);
|
||||
bb.generate(
|
||||
scatterConfig("method", methodComplexityData),
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
293
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist
vendored
Normal file
293
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Dashboard for {{full_path}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="{{path_to_root}}_css/bootstrap.min.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/billboard.min.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/style.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
{{breadcrumbs}}
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Classes</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3>Coverage Distribution</h3>
|
||||
<div id="classesCoverageDistribution" style="height: 300px;">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3>Complexity</h3>
|
||||
<div id="classComplexity" style="height: 300px;">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3 style="margin-top: 2rem;">Insufficient Coverage</h3>
|
||||
<div class="scrollbox">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Class</th>
|
||||
<th class="text-right">Coverage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{insufficient_coverage_classes}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3 style="margin-top: 2rem;">Project Risks</h3>
|
||||
<div class="scrollbox">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Class</th>
|
||||
<th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{project_risks_classes}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2 style="margin-top: 3rem;">Methods</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3>Coverage Distribution</h3>
|
||||
<div id="methodsCoverageDistribution" style="height: 300px;">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3>Complexity</h3>
|
||||
<div id="methodComplexity" style="height: 300px;">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3 style="margin-top: 2rem;">Insufficient Coverage</h3>
|
||||
<div class="scrollbox">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th class="text-right">Coverage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{insufficient_coverage_methods}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3 style="margin-top: 2rem;">Project Risks</h3>
|
||||
<div class="scrollbox">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th class="text-right"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{project_risks_methods}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<hr/>
|
||||
<p>
|
||||
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="_js/billboard.pkgd.min.js?v={{version}}" type="text/javascript"></script>
|
||||
<script type="application/json" id="complexity_class">{{complexity_class}}</script>
|
||||
<script type="application/json" id="complexity_method">{{complexity_method}}</script>
|
||||
<script type="text/javascript" defer>
|
||||
const barLabels = [
|
||||
'0%',
|
||||
'0-10%',
|
||||
'10-20%',
|
||||
'20-30%',
|
||||
'30-40%',
|
||||
'40-50%',
|
||||
'50-60%',
|
||||
'60-70%',
|
||||
'70-80%',
|
||||
'80-90%',
|
||||
'90-100%',
|
||||
'100%'
|
||||
];
|
||||
const barConfig = (name, fullName, values) => ({
|
||||
axis: {
|
||||
x: {
|
||||
type: "category",
|
||||
categories: barLabels,
|
||||
},
|
||||
y: {
|
||||
label: {
|
||||
text: `#${name}`,
|
||||
position: 'outer-top',
|
||||
},
|
||||
},
|
||||
},
|
||||
bindto: `#${name}CoverageDistribution`,
|
||||
data: {
|
||||
columns: [
|
||||
[fullName].concat(values),
|
||||
],
|
||||
colors: {
|
||||
[fullName]: "rgba(69, 114, 167, 0.75)",
|
||||
},
|
||||
type: "bar",
|
||||
},
|
||||
bar: {
|
||||
width: {
|
||||
ratio: 0.9,
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
focus: {
|
||||
show: false,
|
||||
},
|
||||
x: {
|
||||
show: true,
|
||||
},
|
||||
y: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
tooltip: {
|
||||
contents: function (data) {
|
||||
return `<table class="bb-tooltip"><tbody>
|
||||
<tr><th colspan="2">Coverage ${barLabels[data[0].x]}</th></tr>
|
||||
<tr><td class="value">${data[0].value} ${name}</td></tr>
|
||||
</tbody></table>`;
|
||||
},
|
||||
grouped: false,
|
||||
},
|
||||
});
|
||||
bb.generate(
|
||||
barConfig('classes', "Class Coverage", {{class_coverage_distribution}})
|
||||
);
|
||||
bb.generate(
|
||||
barConfig('methods', "Method Coverage", {{method_coverage_distribution}})
|
||||
);
|
||||
|
||||
const scatterConfig = (name, complexityData) => ({
|
||||
axis: {
|
||||
x: {
|
||||
label: {
|
||||
text: 'Code Coverage (in percent)',
|
||||
position: 'outer-right',
|
||||
},
|
||||
tick: {
|
||||
values: [0, 20, 40, 60, 80, 100],
|
||||
},
|
||||
},
|
||||
y: {
|
||||
label: {
|
||||
text: 'Cyclomatic Complexity',
|
||||
position: 'outer-top',
|
||||
},
|
||||
min: 0,
|
||||
padding: {
|
||||
bottom: 0,
|
||||
top: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
bindto: `#${name}Complexity`,
|
||||
data: {
|
||||
columns: [
|
||||
["complexity_x"].concat(complexityData.map(d => d[0])),
|
||||
["complexity"].concat(complexityData.map(d => d[1])),
|
||||
],
|
||||
onclick: function(data, element) {
|
||||
window.location = complexityData[data.index][2];
|
||||
},
|
||||
type: "scatter",
|
||||
xs: {
|
||||
"complexity": "complexity_x",
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
focus: {
|
||||
show: true,
|
||||
y: true,
|
||||
},
|
||||
x: {
|
||||
show: true,
|
||||
},
|
||||
y: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
tooltip: {
|
||||
contents: function (data) {
|
||||
const coverage = Math.round(data[0].x);
|
||||
const complexity = data[0].value;
|
||||
const targetName = complexityData[data[0].index][3];
|
||||
return `<table class="bb-tooltip"><tbody>
|
||||
<tr><th colspan="2">${targetName}</th></tr>
|
||||
<tr class="bb-tooltip-name-complexity"><td>Coverage</td><td class="name">${coverage}%</td></tr>
|
||||
<tr class="bb-tooltip-name-complexity"><td>Complexity</td><td class="value">${complexity}</td></tr>
|
||||
</tbody></table>`;
|
||||
},
|
||||
grouped: false,
|
||||
},
|
||||
});
|
||||
const classComplexityData = JSON.parse(document.getElementById('complexity_class').textContent);
|
||||
bb.generate(
|
||||
scatterConfig("class", classComplexityData)
|
||||
);
|
||||
const methodComplexityData = JSON.parse(document.getElementById('complexity_method').textContent);
|
||||
bb.generate(
|
||||
scatterConfig("method", methodComplexityData),
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
60
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist
vendored
Normal file
60
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Code Coverage for {{full_path}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="{{path_to_root}}_css/bootstrap.min.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/octicons.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/style.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
{{breadcrumbs}}
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container-fluid">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="9"><div align="center"><strong>Code Coverage</strong></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="3"><div align="center"><strong>Lines</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Functions and Methods</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{items}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<footer>
|
||||
<hr/>
|
||||
<h4>Legend</h4>
|
||||
<p>
|
||||
<span class="danger"><strong>Low</strong>: 0% to {{low_upper_bound}}%</span>
|
||||
<span class="warning"><strong>Medium</strong>: {{low_upper_bound}}% to {{high_lower_bound}}%</span>
|
||||
<span class="success"><strong>High</strong>: {{high_lower_bound}}% to 100%</span>
|
||||
</p>
|
||||
<p>
|
||||
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
62
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist
vendored
Normal file
62
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Code Coverage for {{full_path}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="{{path_to_root}}_css/bootstrap.min.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/octicons.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/style.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
{{breadcrumbs}}
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container-fluid">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="15"><div align="center"><strong>Code Coverage</strong></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="3"><div align="center"><strong>Lines</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Branches</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Paths</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Functions and Methods</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{items}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<footer>
|
||||
<hr/>
|
||||
<h4>Legend</h4>
|
||||
<p>
|
||||
<span class="danger"><strong>Low</strong>: 0% to {{low_upper_bound}}%</span>
|
||||
<span class="warning"><strong>Medium</strong>: {{low_upper_bound}}% to {{high_lower_bound}}%</span>
|
||||
<span class="success"><strong>High</strong>: {{high_lower_bound}}% to 100%</span>
|
||||
</p>
|
||||
<p>
|
||||
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
13
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist
vendored
Normal file
13
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<tr>
|
||||
<td class="{{lines_level}}">{{icon}}{{name}}</td>
|
||||
<td class="{{lines_level}} big">{{lines_bar}}</td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
|
||||
<td class="{{methods_level}} big">{{methods_bar}}</td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
|
||||
<td class="{{classes_level}} big">{{classes_bar}}</td>
|
||||
<td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
|
||||
<td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
|
||||
</tr>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<tr>
|
||||
<td class="{{lines_level}}">{{icon}}{{name}}</td>
|
||||
<td class="{{lines_level}} big">{{lines_bar}}</td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
|
||||
<td class="{{branches_level}} big">{{branches_bar}}</td>
|
||||
<td class="{{branches_level}} small"><div align="right">{{branches_executed_percent}}</div></td>
|
||||
<td class="{{branches_level}} small"><div align="right">{{branches_number}}</div></td>
|
||||
<td class="{{paths_level}} big">{{paths_bar}}</td>
|
||||
<td class="{{paths_level}} small"><div align="right">{{paths_executed_percent}}</div></td>
|
||||
<td class="{{paths_level}} small"><div align="right">{{paths_number}}</div></td>
|
||||
<td class="{{methods_level}} big">{{methods_bar}}</td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
|
||||
<td class="{{classes_level}} big">{{classes_bar}}</td>
|
||||
<td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
|
||||
<td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
|
||||
</tr>
|
||||
|
||||
64
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist
vendored
Normal file
64
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Code Coverage for {{full_path}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="{{path_to_root}}_css/bootstrap.min.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/octicons.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/style.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
{{breadcrumbs}}
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container-fluid">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="10"><div align="center"><strong>Code Coverage</strong></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="3"><div align="center"><strong>Lines</strong></div></td>
|
||||
<td colspan="4"><div align="center"><strong>Functions and Methods</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{items}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{lines}}
|
||||
{{structure}}
|
||||
<footer>
|
||||
<hr/>
|
||||
<h4>Legend</h4>
|
||||
{{legend}}
|
||||
<p>
|
||||
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
|
||||
</p>
|
||||
<a title="Back to the top" id="toplink" href="#">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M12 11L6 5l-6 6h12z"/></svg>
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="{{path_to_root}}_js/jquery.min.js?v={{version}}" type="text/javascript"></script>
|
||||
<script src="{{path_to_root}}_js/bootstrap.bundle.min.js?v={{version}}" type="text/javascript"></script>
|
||||
<script src="{{path_to_root}}_js/file.js?v={{version}}" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
66
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist
vendored
Normal file
66
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Code Coverage for {{full_path}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="{{path_to_root}}_css/bootstrap.min.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/octicons.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/style.css?v={{version}}" rel="stylesheet" type="text/css">
|
||||
<link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
{{breadcrumbs}}
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container-fluid">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="16"><div align="center"><strong>Code Coverage</strong></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="3"><div align="center"><strong>Lines</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Branches</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Paths</strong></div></td>
|
||||
<td colspan="4"><div align="center"><strong>Functions and Methods</strong></div></td>
|
||||
<td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{items}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{lines}}
|
||||
{{structure}}
|
||||
<footer>
|
||||
<hr/>
|
||||
<h4>Legend</h4>
|
||||
{{legend}}
|
||||
<p>
|
||||
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
|
||||
</p>
|
||||
<a title="Back to the top" id="toplink" href="#">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M12 11L6 5l-6 6h12z"/></svg>
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="{{path_to_root}}_js/jquery.min.js?v={{version}}" type="text/javascript"></script>
|
||||
<script src="{{path_to_root}}_js/bootstrap.bundle.min.js?v={{version}}" type="text/javascript"></script>
|
||||
<script src="{{path_to_root}}_js/file.js?v={{version}}" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
14
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist
vendored
Normal file
14
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<tr>
|
||||
<td class="{{lines_level}}">{{name}}</td>
|
||||
<td class="{{lines_level}} big">{{lines_bar}}</td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
|
||||
<td class="{{methods_level}} big">{{methods_bar}}</td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
|
||||
<td class="{{methods_level}} small">{{crap}}</td>
|
||||
<td class="{{classes_level}} big">{{classes_bar}}</td>
|
||||
<td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
|
||||
<td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
|
||||
</tr>
|
||||
|
||||
20
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist
vendored
Normal file
20
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<tr>
|
||||
<td class="{{lines_level}}">{{name}}</td>
|
||||
<td class="{{lines_level}} big">{{lines_bar}}</td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
|
||||
<td class="{{branches_level}} big">{{branches_bar}}</td>
|
||||
<td class="{{branches_level}} small"><div align="right">{{branches_executed_percent}}</div></td>
|
||||
<td class="{{branches_level}} small"><div align="right">{{branches_number}}</div></td>
|
||||
<td class="{{paths_level}} big">{{paths_bar}}</td>
|
||||
<td class="{{paths_level}} small"><div align="right">{{paths_executed_percent}}</div></td>
|
||||
<td class="{{paths_level}} small"><div align="right">{{paths_number}}</div></td>
|
||||
<td class="{{methods_level}} big">{{methods_bar}}</td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
|
||||
<td class="{{methods_level}} small">{{crap}}</td>
|
||||
<td class="{{classes_level}} big">{{classes_bar}}</td>
|
||||
<td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td>
|
||||
<td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td>
|
||||
</tr>
|
||||
|
||||
1
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg
vendored
Normal file
1
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M8.5 1H1c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h10c.55 0 1-.45 1-1V4.5L8.5 1zM11 14H1V2h7l3 3v9zM5 6.98L3.5 8.5 5 10l-.5 1L2 8.5 4.5 6l.5.98zM7.5 6L10 8.5 7.5 11l-.5-.98L8.5 8.5 7 7l.5-1z"/></svg>
|
||||
|
After Width: | Height: | Size: 304 B |
1
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg
vendored
Normal file
1
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M13 4H7V3c0-.66-.31-1-1-1H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zM6 4H1V3h5v1z"/></svg>
|
||||
|
After Width: | Height: | Size: 234 B |
57
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/billboard.pkgd.min.js
vendored
Normal file
57
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/billboard.pkgd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
53
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js
vendored
Normal file
53
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
$(function () {
|
||||
var $window = $(window)
|
||||
, $top_link = $('#toplink')
|
||||
, $body = $('body, html')
|
||||
, offset = $('#code').offset().top;
|
||||
|
||||
$top_link.hide().click(function (event) {
|
||||
event.preventDefault();
|
||||
$body.animate({scrollTop: 0}, 800);
|
||||
});
|
||||
|
||||
$window.scroll(function () {
|
||||
if ($window.scrollTop() > offset) {
|
||||
$top_link.fadeIn();
|
||||
} else {
|
||||
$top_link.fadeOut();
|
||||
}
|
||||
});
|
||||
|
||||
var $popovers = $('.popin > :first-child');
|
||||
$('.popin').on({
|
||||
'click.popover': function (event) {
|
||||
event.stopPropagation();
|
||||
|
||||
var $container = $(this).children().first();
|
||||
|
||||
//Close all other popovers:
|
||||
$popovers.each(function () {
|
||||
var $current = $(this);
|
||||
if (!$current.is($container)) {
|
||||
$current.popover('hide');
|
||||
}
|
||||
});
|
||||
|
||||
// Toggle this popover:
|
||||
$container.popover('toggle');
|
||||
},
|
||||
});
|
||||
|
||||
//Hide all popovers on outside click:
|
||||
$(document).click(function (event) {
|
||||
if ($(event.target).closest($('.popover')).length === 0) {
|
||||
$popovers.popover('hide');
|
||||
}
|
||||
});
|
||||
|
||||
//Hide all popovers on escape:
|
||||
$(document).keyup(function (event) {
|
||||
if (event.key === 'Escape') {
|
||||
$popovers.popover('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
2
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js
vendored
Normal file
2
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist
vendored
Normal file
1
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<tr class="{{class}} d-flex"><td {{popover}} class="col-1 text-end"><a id="{{lineNumber}}" href="#{{lineNumber}}">{{lineNumber}}</a></td><td class="col-11 codeLine">{{lineContent}}</td></tr>
|
||||
5
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist
vendored
Normal file
5
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<table id="code" class="table table-borderless table-condensed">
|
||||
<tbody>
|
||||
{{lines}}
|
||||
</tbody>
|
||||
</table>
|
||||
12
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist
vendored
Normal file
12
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<tr>
|
||||
<td class="{{lines_level}}">{{name}}</td>
|
||||
<td class="{{lines_level}} big">{{lines_bar}}</td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
|
||||
<td class="{{methods_level}} big">{{methods_bar}}</td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
|
||||
<td class="{{methods_level}} small">{{crap}}</td>
|
||||
<td class="{{methods_level}}" colspan="3"></td>
|
||||
</tr>
|
||||
|
||||
18
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist
vendored
Normal file
18
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<tr>
|
||||
<td class="{{lines_level}}">{{name}}</td>
|
||||
<td class="{{lines_level}} big">{{lines_bar}}</td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td>
|
||||
<td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td>
|
||||
<td class="{{branches_level}} big">{{branches_bar}}</td>
|
||||
<td class="{{branches_level}} small"><div align="right">{{branches_executed_percent}}</div></td>
|
||||
<td class="{{branches_level}} small"><div align="right">{{branches_number}}</div></td>
|
||||
<td class="{{paths_level}} big">{{paths_bar}}</td>
|
||||
<td class="{{paths_level}} small"><div align="right">{{paths_executed_percent}}</div></td>
|
||||
<td class="{{paths_level}} small"><div align="right">{{paths_number}}</div></td>
|
||||
<td class="{{methods_level}} big">{{methods_bar}}</td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td>
|
||||
<td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td>
|
||||
<td class="{{methods_level}} small">{{crap}}</td>
|
||||
<td class="{{methods_level}}" colspan="3"></td>
|
||||
</tr>
|
||||
|
||||
9
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist
vendored
Normal file
9
vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<hr/>
|
||||
<h4>Paths</h4>
|
||||
<p>
|
||||
Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not
|
||||
necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once.
|
||||
Please also be aware that some paths may include implicit rather than explicit branches, e.g. an <code>if</code> statement
|
||||
<i>always</i> has an <code>else</code> as part of its logical flow even if you didn't write one.
|
||||
</p>
|
||||
{{paths}}
|
||||
249
vendor/phpunit/php-code-coverage/src/Report/OpenClover.php
vendored
Normal file
249
vendor/phpunit/php-code-coverage/src/Report/OpenClover.php
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
<?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\Report;
|
||||
|
||||
use function assert;
|
||||
use function basename;
|
||||
use function count;
|
||||
use function is_string;
|
||||
use function ksort;
|
||||
use function max;
|
||||
use function range;
|
||||
use function str_replace;
|
||||
use function time;
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Node\File;
|
||||
use SebastianBergmann\CodeCoverage\Util\Filesystem;
|
||||
use SebastianBergmann\CodeCoverage\Util\Xml;
|
||||
use SebastianBergmann\CodeCoverage\Version;
|
||||
use SebastianBergmann\CodeCoverage\WriteOperationFailedException;
|
||||
|
||||
final class OpenClover
|
||||
{
|
||||
/**
|
||||
* @throws WriteOperationFailedException
|
||||
*/
|
||||
public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string
|
||||
{
|
||||
$time = (string) time();
|
||||
|
||||
$xmlDocument = new DOMDocument('1.0', 'UTF-8');
|
||||
$xmlDocument->formatOutput = true;
|
||||
|
||||
$xmlCoverage = $xmlDocument->createElement('coverage');
|
||||
$xmlCoverage->setAttribute('clover', Version::id());
|
||||
$xmlCoverage->setAttribute('generated', $time);
|
||||
$xmlDocument->appendChild($xmlCoverage);
|
||||
|
||||
$xmlProject = $xmlDocument->createElement('project');
|
||||
$xmlProject->setAttribute('timestamp', $time);
|
||||
|
||||
if (is_string($name)) {
|
||||
$xmlProject->setAttribute('name', $name);
|
||||
}
|
||||
|
||||
$xmlCoverage->appendChild($xmlProject);
|
||||
|
||||
/** @var array<non-empty-string, DOMElement> $packages */
|
||||
$packages = [];
|
||||
$report = $coverage->getReport();
|
||||
|
||||
foreach ($report as $item) {
|
||||
if (!$item instanceof File) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$xmlFile = $xmlDocument->createElement('file');
|
||||
$xmlFile->setAttribute('name', basename($item->pathAsString()));
|
||||
$xmlFile->setAttribute('path', $item->pathAsString());
|
||||
|
||||
$classes = $item->classesAndTraits();
|
||||
$coverageData = $item->lineCoverageData();
|
||||
$lines = [];
|
||||
$namespace = 'global';
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
$classStatements = 0;
|
||||
$coveredClassStatements = 0;
|
||||
$coveredMethods = 0;
|
||||
$classMethods = 0;
|
||||
|
||||
// Assumption: one namespace per file
|
||||
if ($class->namespace !== '') {
|
||||
$namespace = $class->namespace;
|
||||
}
|
||||
|
||||
foreach ($class->methods as $methodName => $method) {
|
||||
/** @phpstan-ignore equal.notAllowed */
|
||||
if ($method->executableLines == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classMethods++;
|
||||
$classStatements += $method->executableLines;
|
||||
$coveredClassStatements += $method->executedLines;
|
||||
|
||||
/** @phpstan-ignore equal.notAllowed */
|
||||
if ($method->coverage == 100) {
|
||||
$coveredMethods++;
|
||||
}
|
||||
|
||||
$methodCount = 0;
|
||||
|
||||
foreach (range($method->startLine, $method->endLine) as $line) {
|
||||
if (isset($coverageData[$line])) {
|
||||
$methodCount = max($methodCount, count($coverageData[$line]));
|
||||
}
|
||||
}
|
||||
|
||||
$lines[$method->startLine] = [
|
||||
'ccn' => $method->ccn,
|
||||
'count' => $methodCount,
|
||||
'type' => 'method',
|
||||
'signature' => $method->signature,
|
||||
'visibility' => $method->visibility,
|
||||
];
|
||||
}
|
||||
|
||||
$xmlClass = $xmlDocument->createElement('class');
|
||||
$xmlClass->setAttribute('name', str_replace($class->namespace . '\\', '', $className));
|
||||
|
||||
$xmlFile->appendChild($xmlClass);
|
||||
|
||||
$xmlMetrics = $xmlDocument->createElement('metrics');
|
||||
$xmlMetrics->setAttribute('complexity', (string) $class->ccn);
|
||||
$xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class->executableBranches));
|
||||
$xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class->executedBranches));
|
||||
$xmlMetrics->setAttribute('conditionals', (string) $class->executableBranches);
|
||||
$xmlMetrics->setAttribute('coveredconditionals', (string) $class->executedBranches);
|
||||
$xmlMetrics->setAttribute('statements', (string) $classStatements);
|
||||
$xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements);
|
||||
$xmlMetrics->setAttribute('methods', (string) $classMethods);
|
||||
$xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods);
|
||||
$xmlClass->insertBefore($xmlMetrics, $xmlClass->firstChild);
|
||||
}
|
||||
|
||||
foreach ($coverageData as $line => $data) {
|
||||
if ($data === null || isset($lines[$line])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$lines[$line] = [
|
||||
'count' => count($data),
|
||||
'type' => 'stmt',
|
||||
];
|
||||
}
|
||||
|
||||
ksort($lines);
|
||||
|
||||
foreach ($lines as $line => $data) {
|
||||
$xmlLine = $xmlDocument->createElement('line');
|
||||
$xmlLine->setAttribute('num', (string) $line);
|
||||
$xmlLine->setAttribute('type', $data['type']);
|
||||
|
||||
if (isset($data['ccn'])) {
|
||||
$xmlLine->setAttribute('complexity', (string) $data['ccn']);
|
||||
}
|
||||
|
||||
$xmlLine->setAttribute('count', (string) $data['count']);
|
||||
|
||||
if (isset($data['signature'])) {
|
||||
$xmlLine->setAttribute('signature', $data['signature']);
|
||||
}
|
||||
|
||||
if (isset($data['visibility'])) {
|
||||
$xmlLine->setAttribute('visibility', $data['visibility']);
|
||||
}
|
||||
|
||||
$xmlFile->appendChild($xmlLine);
|
||||
}
|
||||
|
||||
$linesOfCode = $item->linesOfCode();
|
||||
|
||||
$xmlMetrics = $xmlDocument->createElement('metrics');
|
||||
$xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode());
|
||||
$xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode());
|
||||
$xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits());
|
||||
$xmlMetrics->setAttribute('complexity', (string) $item->cyclomaticComplexity());
|
||||
$xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches()));
|
||||
$xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches()));
|
||||
$xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches());
|
||||
$xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches());
|
||||
$xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines());
|
||||
$xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines());
|
||||
$xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods());
|
||||
$xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods());
|
||||
$xmlFile->insertBefore($xmlMetrics, $xmlFile->firstChild);
|
||||
|
||||
if (!isset($packages[$namespace])) {
|
||||
$packages[$namespace] = $xmlDocument->createElement('package');
|
||||
$packages[$namespace]->setAttribute('name', $namespace);
|
||||
|
||||
$xmlPackageMetrics = $xmlDocument->createElement('metrics');
|
||||
$xmlPackageMetrics->setAttribute('complexity', '0');
|
||||
$xmlPackageMetrics->setAttribute('elements', '0');
|
||||
$xmlPackageMetrics->setAttribute('coveredelements', '0');
|
||||
$xmlPackageMetrics->setAttribute('conditionals', '0');
|
||||
$xmlPackageMetrics->setAttribute('coveredconditionals', '0');
|
||||
$xmlPackageMetrics->setAttribute('statements', '0');
|
||||
$xmlPackageMetrics->setAttribute('coveredstatements', '0');
|
||||
$xmlPackageMetrics->setAttribute('methods', '0');
|
||||
$xmlPackageMetrics->setAttribute('coveredmethods', '0');
|
||||
$packages[$namespace]->appendChild($xmlPackageMetrics);
|
||||
|
||||
$xmlProject->appendChild($packages[$namespace]);
|
||||
}
|
||||
|
||||
$xmlPackageMetrics = $packages[$namespace]->firstChild;
|
||||
|
||||
assert($xmlPackageMetrics instanceof DOMElement);
|
||||
|
||||
$xmlPackageMetrics->setAttribute('complexity', (string) ((int) $xmlPackageMetrics->getAttribute('complexity') + $item->cyclomaticComplexity()));
|
||||
$xmlPackageMetrics->setAttribute('elements', (string) ((int) $xmlPackageMetrics->getAttribute('elements') + $item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches()));
|
||||
$xmlPackageMetrics->setAttribute('coveredelements', (string) ((int) $xmlPackageMetrics->getAttribute('coveredelements') + $item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches()));
|
||||
$xmlPackageMetrics->setAttribute('conditionals', (string) ((int) $xmlPackageMetrics->getAttribute('conditionals') + $item->numberOfExecutableBranches()));
|
||||
$xmlPackageMetrics->setAttribute('coveredconditionals', (string) ((int) $xmlPackageMetrics->getAttribute('coveredconditionals') + $item->numberOfExecutedBranches()));
|
||||
$xmlPackageMetrics->setAttribute('statements', (string) ((int) $xmlPackageMetrics->getAttribute('statements') + $item->numberOfExecutableLines()));
|
||||
$xmlPackageMetrics->setAttribute('coveredstatements', (string) ((int) $xmlPackageMetrics->getAttribute('coveredstatements') + $item->numberOfExecutedLines()));
|
||||
$xmlPackageMetrics->setAttribute('methods', (string) ((int) $xmlPackageMetrics->getAttribute('methods') + $item->numberOfMethods()));
|
||||
$xmlPackageMetrics->setAttribute('coveredmethods', (string) ((int) $xmlPackageMetrics->getAttribute('coveredmethods') + $item->numberOfTestedMethods()));
|
||||
|
||||
$packages[$namespace]->appendChild($xmlFile);
|
||||
}
|
||||
|
||||
$linesOfCode = $report->linesOfCode();
|
||||
|
||||
$xmlMetrics = $xmlDocument->createElement('metrics');
|
||||
$xmlMetrics->setAttribute('files', (string) count($report));
|
||||
$xmlMetrics->setAttribute('loc', (string) $linesOfCode->linesOfCode());
|
||||
$xmlMetrics->setAttribute('ncloc', (string) $linesOfCode->nonCommentLinesOfCode());
|
||||
$xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits());
|
||||
$xmlMetrics->setAttribute('complexity', (string) $report->cyclomaticComplexity());
|
||||
$xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches()));
|
||||
$xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches()));
|
||||
$xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches());
|
||||
$xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches());
|
||||
$xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines());
|
||||
$xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines());
|
||||
$xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods());
|
||||
$xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods());
|
||||
$xmlProject->insertBefore($xmlMetrics, $xmlProject->firstChild);
|
||||
|
||||
$buffer = Xml::asString($xmlDocument);
|
||||
|
||||
if ($target !== null) {
|
||||
Filesystem::write($target, $buffer);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
}
|
||||
38
vendor/phpunit/php-code-coverage/src/Report/PHP.php
vendored
Normal file
38
vendor/phpunit/php-code-coverage/src/Report/PHP.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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\Report;
|
||||
|
||||
use const PHP_EOL;
|
||||
use function serialize;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Util\Filesystem;
|
||||
use SebastianBergmann\CodeCoverage\WriteOperationFailedException;
|
||||
|
||||
final class PHP
|
||||
{
|
||||
/**
|
||||
* @param null|non-empty-string $target
|
||||
*
|
||||
* @throws WriteOperationFailedException
|
||||
*/
|
||||
public function process(CodeCoverage $coverage, ?string $target = null): string
|
||||
{
|
||||
$coverage->clearCache();
|
||||
|
||||
$buffer = "<?php
|
||||
return \unserialize(<<<'END_OF_COVERAGE_SERIALIZATION'" . PHP_EOL . serialize($coverage) . PHP_EOL . 'END_OF_COVERAGE_SERIALIZATION' . PHP_EOL . ');';
|
||||
|
||||
if ($target !== null) {
|
||||
Filesystem::write($target, $buffer);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
}
|
||||
299
vendor/phpunit/php-code-coverage/src/Report/Text.php
vendored
Normal file
299
vendor/phpunit/php-code-coverage/src/Report/Text.php
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
<?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\Report;
|
||||
|
||||
use const PHP_EOL;
|
||||
use function array_map;
|
||||
use function date;
|
||||
use function ksort;
|
||||
use function max;
|
||||
use function sprintf;
|
||||
use function str_pad;
|
||||
use function strlen;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Node\File;
|
||||
use SebastianBergmann\CodeCoverage\Util\Percentage;
|
||||
|
||||
final class Text
|
||||
{
|
||||
private const string COLOR_GREEN = "\x1b[30;42m";
|
||||
private const string COLOR_YELLOW = "\x1b[30;43m";
|
||||
private const string COLOR_RED = "\x1b[37;41m";
|
||||
private const string COLOR_HEADER = "\x1b[1;37;40m";
|
||||
private const string COLOR_RESET = "\x1b[0m";
|
||||
private readonly Thresholds $thresholds;
|
||||
private readonly bool $showUncoveredFiles;
|
||||
private readonly bool $showOnlySummary;
|
||||
|
||||
public function __construct(Thresholds $thresholds, bool $showUncoveredFiles = false, bool $showOnlySummary = false)
|
||||
{
|
||||
$this->thresholds = $thresholds;
|
||||
$this->showUncoveredFiles = $showUncoveredFiles;
|
||||
$this->showOnlySummary = $showOnlySummary;
|
||||
}
|
||||
|
||||
public function process(CodeCoverage $coverage, bool $showColors = false): string
|
||||
{
|
||||
$hasBranchCoverage = $coverage->getData(true)->functionCoverage() !== [];
|
||||
|
||||
$output = PHP_EOL . PHP_EOL;
|
||||
$report = $coverage->getReport();
|
||||
|
||||
$colors = [
|
||||
'header' => '',
|
||||
'classes' => '',
|
||||
'methods' => '',
|
||||
'lines' => '',
|
||||
'branches' => '',
|
||||
'paths' => '',
|
||||
'reset' => '',
|
||||
];
|
||||
|
||||
if ($showColors) {
|
||||
$colors['classes'] = $this->coverageColor(
|
||||
$report->numberOfTestedClassesAndTraits(),
|
||||
$report->numberOfClassesAndTraits(),
|
||||
);
|
||||
|
||||
$colors['methods'] = $this->coverageColor(
|
||||
$report->numberOfTestedMethods(),
|
||||
$report->numberOfMethods(),
|
||||
);
|
||||
|
||||
$colors['lines'] = $this->coverageColor(
|
||||
$report->numberOfExecutedLines(),
|
||||
$report->numberOfExecutableLines(),
|
||||
);
|
||||
|
||||
$colors['branches'] = $this->coverageColor(
|
||||
$report->numberOfExecutedBranches(),
|
||||
$report->numberOfExecutableBranches(),
|
||||
);
|
||||
|
||||
$colors['paths'] = $this->coverageColor(
|
||||
$report->numberOfExecutedPaths(),
|
||||
$report->numberOfExecutablePaths(),
|
||||
);
|
||||
|
||||
$colors['reset'] = self::COLOR_RESET;
|
||||
$colors['header'] = self::COLOR_HEADER;
|
||||
}
|
||||
|
||||
$classes = sprintf(
|
||||
' Classes: %6s (%d/%d)',
|
||||
Percentage::fromFractionAndTotal(
|
||||
$report->numberOfTestedClassesAndTraits(),
|
||||
$report->numberOfClassesAndTraits(),
|
||||
)->asString(),
|
||||
$report->numberOfTestedClassesAndTraits(),
|
||||
$report->numberOfClassesAndTraits(),
|
||||
);
|
||||
|
||||
$methods = sprintf(
|
||||
' Methods: %6s (%d/%d)',
|
||||
Percentage::fromFractionAndTotal(
|
||||
$report->numberOfTestedMethods(),
|
||||
$report->numberOfMethods(),
|
||||
)->asString(),
|
||||
$report->numberOfTestedMethods(),
|
||||
$report->numberOfMethods(),
|
||||
);
|
||||
|
||||
$paths = '';
|
||||
$branches = '';
|
||||
|
||||
if ($hasBranchCoverage) {
|
||||
$paths = sprintf(
|
||||
' Paths: %6s (%d/%d)',
|
||||
Percentage::fromFractionAndTotal(
|
||||
$report->numberOfExecutedPaths(),
|
||||
$report->numberOfExecutablePaths(),
|
||||
)->asString(),
|
||||
$report->numberOfExecutedPaths(),
|
||||
$report->numberOfExecutablePaths(),
|
||||
);
|
||||
|
||||
$branches = sprintf(
|
||||
' Branches: %6s (%d/%d)',
|
||||
Percentage::fromFractionAndTotal(
|
||||
$report->numberOfExecutedBranches(),
|
||||
$report->numberOfExecutableBranches(),
|
||||
)->asString(),
|
||||
$report->numberOfExecutedBranches(),
|
||||
$report->numberOfExecutableBranches(),
|
||||
);
|
||||
}
|
||||
|
||||
$lines = sprintf(
|
||||
' Lines: %6s (%d/%d)',
|
||||
Percentage::fromFractionAndTotal(
|
||||
$report->numberOfExecutedLines(),
|
||||
$report->numberOfExecutableLines(),
|
||||
)->asString(),
|
||||
$report->numberOfExecutedLines(),
|
||||
$report->numberOfExecutableLines(),
|
||||
);
|
||||
|
||||
$padding = max(array_map('strlen', [$classes, $methods, $lines]));
|
||||
|
||||
if ($this->showOnlySummary) {
|
||||
$title = 'Code Coverage Report Summary:';
|
||||
$padding = max($padding, strlen($title));
|
||||
|
||||
$output .= $this->format($colors['header'], $padding, $title);
|
||||
} else {
|
||||
$date = date(' Y-m-d H:i:s');
|
||||
$title = 'Code Coverage Report:';
|
||||
|
||||
$output .= $this->format($colors['header'], $padding, $title);
|
||||
$output .= $this->format($colors['header'], $padding, $date);
|
||||
$output .= $this->format($colors['header'], $padding, '');
|
||||
$output .= $this->format($colors['header'], $padding, ' Summary:');
|
||||
}
|
||||
|
||||
$output .= $this->format($colors['classes'], $padding, $classes);
|
||||
$output .= $this->format($colors['methods'], $padding, $methods);
|
||||
|
||||
if ($hasBranchCoverage) {
|
||||
$output .= $this->format($colors['paths'], $padding, $paths);
|
||||
$output .= $this->format($colors['branches'], $padding, $branches);
|
||||
}
|
||||
$output .= $this->format($colors['lines'], $padding, $lines);
|
||||
|
||||
if ($this->showOnlySummary) {
|
||||
return $output . PHP_EOL;
|
||||
}
|
||||
|
||||
$classCoverage = [];
|
||||
|
||||
foreach ($report as $item) {
|
||||
if (!$item instanceof File) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classes = $item->classesAndTraits();
|
||||
|
||||
foreach ($classes as $className => $class) {
|
||||
$classExecutableLines = 0;
|
||||
$classExecutedLines = 0;
|
||||
$classExecutableBranches = 0;
|
||||
$classExecutedBranches = 0;
|
||||
$classExecutablePaths = 0;
|
||||
$classExecutedPaths = 0;
|
||||
$coveredMethods = 0;
|
||||
$classMethods = 0;
|
||||
|
||||
foreach ($class->methods as $method) {
|
||||
/** @phpstan-ignore equal.notAllowed */
|
||||
if ($method->executableLines == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classMethods++;
|
||||
$classExecutableLines += $method->executableLines;
|
||||
$classExecutedLines += $method->executedLines;
|
||||
$classExecutableBranches += $method->executableBranches;
|
||||
$classExecutedBranches += $method->executedBranches;
|
||||
$classExecutablePaths += $method->executablePaths;
|
||||
$classExecutedPaths += $method->executedPaths;
|
||||
|
||||
/** @phpstan-ignore equal.notAllowed */
|
||||
if ($method->coverage == 100) {
|
||||
$coveredMethods++;
|
||||
}
|
||||
}
|
||||
|
||||
$classCoverage[$className] = [
|
||||
'namespace' => $class->namespace,
|
||||
'className' => $className,
|
||||
'methodsCovered' => $coveredMethods,
|
||||
'methodCount' => $classMethods,
|
||||
'statementsCovered' => $classExecutedLines,
|
||||
'statementCount' => $classExecutableLines,
|
||||
'branchesCovered' => $classExecutedBranches,
|
||||
'branchesCount' => $classExecutableBranches,
|
||||
'pathsCovered' => $classExecutedPaths,
|
||||
'pathsCount' => $classExecutablePaths,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
ksort($classCoverage);
|
||||
|
||||
$methodColor = '';
|
||||
$pathsColor = '';
|
||||
$branchesColor = '';
|
||||
$linesColor = '';
|
||||
$resetColor = '';
|
||||
|
||||
foreach ($classCoverage as $fullQualifiedPath => $classInfo) {
|
||||
/** @phpstan-ignore notEqual.notAllowed */
|
||||
if ($this->showUncoveredFiles || $classInfo['statementsCovered'] != 0) {
|
||||
if ($showColors) {
|
||||
$methodColor = $this->coverageColor($classInfo['methodsCovered'], $classInfo['methodCount']);
|
||||
$pathsColor = $this->coverageColor($classInfo['pathsCovered'], $classInfo['pathsCount']);
|
||||
$branchesColor = $this->coverageColor($classInfo['branchesCovered'], $classInfo['branchesCount']);
|
||||
$linesColor = $this->coverageColor($classInfo['statementsCovered'], $classInfo['statementCount']);
|
||||
$resetColor = $colors['reset'];
|
||||
}
|
||||
|
||||
$output .= PHP_EOL . $fullQualifiedPath . PHP_EOL
|
||||
. ' ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' ';
|
||||
|
||||
if ($hasBranchCoverage) {
|
||||
$output .= ' ' . $pathsColor . 'Paths: ' . $this->printCoverageCounts($classInfo['pathsCovered'], $classInfo['pathsCount'], 3) . $resetColor . ' '
|
||||
. ' ' . $branchesColor . 'Branches: ' . $this->printCoverageCounts($classInfo['branchesCovered'], $classInfo['branchesCount'], 3) . $resetColor . ' ';
|
||||
}
|
||||
$output .= ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor;
|
||||
}
|
||||
}
|
||||
|
||||
return $output . PHP_EOL;
|
||||
}
|
||||
|
||||
private function coverageColor(int $numberOfCoveredElements, int $totalNumberOfElements): string
|
||||
{
|
||||
$coverage = Percentage::fromFractionAndTotal(
|
||||
$numberOfCoveredElements,
|
||||
$totalNumberOfElements,
|
||||
);
|
||||
|
||||
if ($coverage->asFloat() >= $this->thresholds->highLowerBound()) {
|
||||
return self::COLOR_GREEN;
|
||||
}
|
||||
|
||||
if ($coverage->asFloat() > $this->thresholds->lowUpperBound()) {
|
||||
return self::COLOR_YELLOW;
|
||||
}
|
||||
|
||||
return self::COLOR_RED;
|
||||
}
|
||||
|
||||
private function printCoverageCounts(int $numberOfCoveredElements, int $totalNumberOfElements, int $precision): string
|
||||
{
|
||||
$format = '%' . $precision . 's';
|
||||
|
||||
return Percentage::fromFractionAndTotal(
|
||||
$numberOfCoveredElements,
|
||||
$totalNumberOfElements,
|
||||
)->asFixedWidthString() .
|
||||
' (' . sprintf($format, $numberOfCoveredElements) . '/' .
|
||||
sprintf($format, $totalNumberOfElements) . ')';
|
||||
}
|
||||
|
||||
private function format(string $color, int $padding, false|string $string): string
|
||||
{
|
||||
if ($color === '') {
|
||||
return (string) $string . PHP_EOL;
|
||||
}
|
||||
|
||||
return $color . str_pad((string) $string, $padding) . self::COLOR_RESET . PHP_EOL;
|
||||
}
|
||||
}
|
||||
56
vendor/phpunit/php-code-coverage/src/Report/Thresholds.php
vendored
Normal file
56
vendor/phpunit/php-code-coverage/src/Report/Thresholds.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?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\Report;
|
||||
|
||||
use SebastianBergmann\CodeCoverage\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*/
|
||||
final readonly class Thresholds
|
||||
{
|
||||
private int $lowUpperBound;
|
||||
private int $highLowerBound;
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return new self(50, 90);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function from(int $lowUpperBound, int $highLowerBound): self
|
||||
{
|
||||
if ($lowUpperBound > $highLowerBound) {
|
||||
throw new InvalidArgumentException(
|
||||
'$lowUpperBound must not be larger than $highLowerBound',
|
||||
);
|
||||
}
|
||||
|
||||
return new self($lowUpperBound, $highLowerBound);
|
||||
}
|
||||
|
||||
private function __construct(int $lowUpperBound, int $highLowerBound)
|
||||
{
|
||||
$this->lowUpperBound = $lowUpperBound;
|
||||
$this->highLowerBound = $highLowerBound;
|
||||
}
|
||||
|
||||
public function lowUpperBound(): int
|
||||
{
|
||||
return $this->lowUpperBound;
|
||||
}
|
||||
|
||||
public function highLowerBound(): int
|
||||
{
|
||||
return $this->highLowerBound;
|
||||
}
|
||||
}
|
||||
48
vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php
vendored
Normal file
48
vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use SebastianBergmann\Environment\Runtime;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class BuildInformation
|
||||
{
|
||||
public function __construct(
|
||||
XMLWriter $xmlWriter,
|
||||
Runtime $runtime,
|
||||
DateTimeImmutable $buildDate,
|
||||
string $phpUnitVersion,
|
||||
string $coverageVersion,
|
||||
string $driverExtensionName,
|
||||
string $driverExtensionVersion,
|
||||
) {
|
||||
$xmlWriter->startElement('build');
|
||||
$xmlWriter->writeAttribute('time', $buildDate->format('D M j G:i:s T Y'));
|
||||
$xmlWriter->writeAttribute('phpunit', $phpUnitVersion);
|
||||
$xmlWriter->writeAttribute('coverage', $coverageVersion);
|
||||
|
||||
$xmlWriter->startElement('runtime');
|
||||
$xmlWriter->writeAttribute('name', $runtime->getName());
|
||||
$xmlWriter->writeAttribute('version', $runtime->getVersion());
|
||||
$xmlWriter->writeAttribute('url', $runtime->getVendorUrl());
|
||||
$xmlWriter->endElement();
|
||||
|
||||
$xmlWriter->startElement('driver');
|
||||
$xmlWriter->writeAttribute('name', $driverExtensionName);
|
||||
$xmlWriter->writeAttribute('version', $driverExtensionVersion);
|
||||
$xmlWriter->endElement();
|
||||
|
||||
$xmlWriter->endElement();
|
||||
}
|
||||
}
|
||||
43
vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php
vendored
Normal file
43
vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Coverage
|
||||
{
|
||||
private readonly XMLWriter $xmlWriter;
|
||||
private readonly string $line;
|
||||
|
||||
public function __construct(
|
||||
XMLWriter $xmlWriter,
|
||||
string $line
|
||||
) {
|
||||
$this->xmlWriter = $xmlWriter;
|
||||
$this->line = $line;
|
||||
}
|
||||
|
||||
public function finalize(array $tests): void
|
||||
{
|
||||
$writer = $this->xmlWriter;
|
||||
$writer->startElement('line');
|
||||
$writer->writeAttribute('nr', $this->line);
|
||||
|
||||
foreach ($tests as $test) {
|
||||
$writer->startElement('covered');
|
||||
$writer->writeAttribute('by', $test);
|
||||
$writer->endElement();
|
||||
}
|
||||
$writer->endElement();
|
||||
}
|
||||
}
|
||||
17
vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php
vendored
Normal file
17
vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Directory extends Node
|
||||
{
|
||||
}
|
||||
350
vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php
vendored
Normal file
350
vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function file_get_contents;
|
||||
use function is_array;
|
||||
use function is_dir;
|
||||
use function is_file;
|
||||
use function is_writable;
|
||||
use function phpversion;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use DateTimeImmutable;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedClassType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedFunctionType;
|
||||
use SebastianBergmann\CodeCoverage\Data\ProcessedTraitType;
|
||||
use SebastianBergmann\CodeCoverage\Node\AbstractNode;
|
||||
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
|
||||
use SebastianBergmann\CodeCoverage\Node\File as FileNode;
|
||||
use SebastianBergmann\CodeCoverage\PathExistsButIsNotDirectoryException;
|
||||
use SebastianBergmann\CodeCoverage\Util\Filesystem;
|
||||
use SebastianBergmann\CodeCoverage\Version;
|
||||
use SebastianBergmann\CodeCoverage\WriteOperationFailedException;
|
||||
use SebastianBergmann\CodeCoverage\XmlException;
|
||||
use SebastianBergmann\Environment\Runtime;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @phpstan-import-type TestType from CodeCoverage
|
||||
*/
|
||||
final class Facade
|
||||
{
|
||||
public const string XML_NAMESPACE = 'https://schema.phpunit.de/coverage/1.0';
|
||||
private string $target;
|
||||
private Project $project;
|
||||
private readonly string $phpUnitVersion;
|
||||
private readonly bool $includeSource;
|
||||
|
||||
public function __construct(string $version, bool $includeSource = true)
|
||||
{
|
||||
$this->phpUnitVersion = $version;
|
||||
$this->includeSource = $includeSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws XmlException
|
||||
*/
|
||||
public function process(CodeCoverage $coverage, string $target): void
|
||||
{
|
||||
if (substr($target, -1, 1) !== DIRECTORY_SEPARATOR) {
|
||||
$target .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
$this->target = $target;
|
||||
$this->initTargetDirectory($target);
|
||||
|
||||
$report = $coverage->getReport();
|
||||
|
||||
$writer = new XMLWriter;
|
||||
$writer->openUri($this->targetFilePath('index'));
|
||||
$writer->setIndent(true);
|
||||
$writer->setIndentString(' ');
|
||||
$this->project = new Project(
|
||||
$writer,
|
||||
$coverage->getReport()->name(),
|
||||
);
|
||||
|
||||
$this->setBuildInformation($coverage);
|
||||
|
||||
$this->project->startProject();
|
||||
$this->processTests($coverage->getTests());
|
||||
$this->processDirectory($report, $this->project);
|
||||
$this->project->finalize();
|
||||
}
|
||||
|
||||
private function setBuildInformation(CodeCoverage $coverage): void
|
||||
{
|
||||
if ($coverage->driverIsPcov()) {
|
||||
$driverExtensionName = 'pcov';
|
||||
$driverExtensionVersion = phpversion('pcov');
|
||||
} elseif ($coverage->driverIsXdebug()) {
|
||||
$driverExtensionName = 'xdebug';
|
||||
$driverExtensionVersion = phpversion('xdebug');
|
||||
} else {
|
||||
// @codeCoverageIgnoreStart
|
||||
$driverExtensionName = 'unknown';
|
||||
$driverExtensionVersion = 'unknown';
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
$this->project->buildInformation(
|
||||
new Runtime,
|
||||
new DateTimeImmutable,
|
||||
$this->phpUnitVersion,
|
||||
Version::id(),
|
||||
$driverExtensionName,
|
||||
$driverExtensionVersion,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws PathExistsButIsNotDirectoryException
|
||||
* @throws WriteOperationFailedException
|
||||
*/
|
||||
private function initTargetDirectory(string $directory): void
|
||||
{
|
||||
if (is_file($directory)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!is_dir($directory)) {
|
||||
throw new PathExistsButIsNotDirectoryException($directory);
|
||||
}
|
||||
|
||||
if (!is_writable($directory)) {
|
||||
throw new WriteOperationFailedException($directory);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
Filesystem::createDirectory($directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws XmlException
|
||||
*/
|
||||
private function processDirectory(DirectoryNode $directory, Node $context): void
|
||||
{
|
||||
$directoryName = $directory->name();
|
||||
|
||||
if ($this->project->projectSourceDirectory() === $directoryName) {
|
||||
$directoryName = '/';
|
||||
}
|
||||
|
||||
$writer = $this->project->getWriter();
|
||||
$writer->startElement('directory');
|
||||
$writer->writeAttribute('name', $directoryName);
|
||||
$directoryObject = $context->addDirectory();
|
||||
|
||||
$this->setTotals($directory, $directoryObject->totals());
|
||||
|
||||
foreach ($directory->directories() as $node) {
|
||||
$this->processDirectory($node, $directoryObject);
|
||||
}
|
||||
|
||||
foreach ($directory->files() as $node) {
|
||||
$this->processFile($node, $directoryObject);
|
||||
}
|
||||
$writer->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws XmlException
|
||||
*/
|
||||
private function processFile(FileNode $file, Directory $context): void
|
||||
{
|
||||
$context->getWriter()->startElement('file');
|
||||
$context->getWriter()->writeAttribute('name', $file->name());
|
||||
$context->getWriter()->writeAttribute('href', $file->id() . '.xml');
|
||||
$context->getWriter()->writeAttribute('hash', $file->sha1());
|
||||
|
||||
$fileObject = $context->addFile();
|
||||
|
||||
$this->setTotals($file, $fileObject->totals());
|
||||
|
||||
$context->getWriter()->endElement();
|
||||
|
||||
$path = substr(
|
||||
$file->pathAsString(),
|
||||
strlen($this->project->projectSourceDirectory()),
|
||||
);
|
||||
|
||||
$writer = new XMLWriter;
|
||||
$writer->openUri($this->targetFilePath($file->id()));
|
||||
$writer->setIndent(true);
|
||||
$writer->setIndentString(' ');
|
||||
$fileReport = new Report($writer, $path, $file->sha1());
|
||||
|
||||
$this->setTotals($file, $fileReport->totals());
|
||||
|
||||
foreach ($file->classesAndTraits() as $unit) {
|
||||
$this->processUnit($unit, $fileReport);
|
||||
}
|
||||
|
||||
foreach ($file->functions() as $function) {
|
||||
$this->processFunction($function, $fileReport);
|
||||
}
|
||||
|
||||
$fileReport->getWriter()->startElement('coverage');
|
||||
|
||||
foreach ($file->lineCoverageData() as $line => $tests) {
|
||||
if (!is_array($tests) || count($tests) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$coverage = $fileReport->lineCoverage((string) $line);
|
||||
$coverage->finalize($tests);
|
||||
}
|
||||
$fileReport->getWriter()->endElement();
|
||||
|
||||
if ($this->includeSource) {
|
||||
$fileReport->source()->setSourceCode(
|
||||
file_get_contents($file->pathAsString()),
|
||||
);
|
||||
}
|
||||
|
||||
$fileReport->finalize();
|
||||
}
|
||||
|
||||
private function processUnit(ProcessedClassType|ProcessedTraitType $unit, Report $report): void
|
||||
{
|
||||
if ($unit instanceof ProcessedClassType) {
|
||||
$report->getWriter()->startElement('class');
|
||||
|
||||
$unitObject = $report->classObject(
|
||||
$unit->className,
|
||||
$unit->namespace,
|
||||
$unit->startLine,
|
||||
$unit->executableLines,
|
||||
$unit->executedLines,
|
||||
(float) $unit->crap,
|
||||
);
|
||||
} else {
|
||||
$report->getWriter()->startElement('trait');
|
||||
|
||||
$unitObject = $report->traitObject(
|
||||
$unit->traitName,
|
||||
$unit->namespace,
|
||||
$unit->startLine,
|
||||
$unit->executableLines,
|
||||
$unit->executedLines,
|
||||
(float) $unit->crap,
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($unit->methods as $method) {
|
||||
$report->getWriter()->startElement('method');
|
||||
|
||||
$unitObject->addMethod(
|
||||
$method->methodName,
|
||||
$method->signature,
|
||||
(string) $method->startLine,
|
||||
(string) $method->endLine,
|
||||
(string) $method->executableLines,
|
||||
(string) $method->executedLines,
|
||||
(string) $method->coverage,
|
||||
$method->crap,
|
||||
);
|
||||
|
||||
$report->getWriter()->endElement();
|
||||
}
|
||||
|
||||
$report->getWriter()->endElement();
|
||||
}
|
||||
|
||||
private function processFunction(ProcessedFunctionType $function, Report $report): void
|
||||
{
|
||||
$report->getWriter()->startElement('function');
|
||||
|
||||
$report->functionObject(
|
||||
$function->functionName,
|
||||
$function->signature,
|
||||
(string) $function->startLine,
|
||||
null,
|
||||
(string) $function->executableLines,
|
||||
(string) $function->executedLines,
|
||||
(string) $function->coverage,
|
||||
$function->crap,
|
||||
);
|
||||
|
||||
$report->getWriter()->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, TestType> $tests
|
||||
*/
|
||||
private function processTests(array $tests): void
|
||||
{
|
||||
$this->project->getWriter()->startElement('tests');
|
||||
|
||||
$testsObject = $this->project->tests();
|
||||
|
||||
foreach ($tests as $test => $result) {
|
||||
$testsObject->addTest($test, $result);
|
||||
}
|
||||
|
||||
$this->project->getWriter()->endElement();
|
||||
}
|
||||
|
||||
private function setTotals(AbstractNode $node, Totals $totals): void
|
||||
{
|
||||
$totals->getWriter()->startElement('totals');
|
||||
|
||||
$loc = $node->linesOfCode();
|
||||
|
||||
$totals->setNumLines(
|
||||
$loc->linesOfCode(),
|
||||
$loc->commentLinesOfCode(),
|
||||
$loc->nonCommentLinesOfCode(),
|
||||
$node->numberOfExecutableLines(),
|
||||
$node->numberOfExecutedLines(),
|
||||
);
|
||||
|
||||
$totals->setNumMethods(
|
||||
$node->numberOfMethods(),
|
||||
$node->numberOfTestedMethods(),
|
||||
);
|
||||
|
||||
$totals->setNumFunctions(
|
||||
$node->numberOfFunctions(),
|
||||
$node->numberOfTestedFunctions(),
|
||||
);
|
||||
|
||||
$totals->setNumClasses(
|
||||
$node->numberOfClasses(),
|
||||
$node->numberOfTestedClasses(),
|
||||
);
|
||||
|
||||
$totals->setNumTraits(
|
||||
$node->numberOfTraits(),
|
||||
$node->numberOfTestedTraits(),
|
||||
);
|
||||
|
||||
$totals->getWriter()->endElement();
|
||||
}
|
||||
|
||||
private function targetDirectory(): string
|
||||
{
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
private function targetFilePath(string $name): string
|
||||
{
|
||||
$filename = sprintf('%s/%s.xml', $this->targetDirectory(), $name);
|
||||
|
||||
$this->initTargetDirectory(dirname($filename));
|
||||
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
40
vendor/phpunit/php-code-coverage/src/Report/Xml/File.php
vendored
Normal file
40
vendor/phpunit/php-code-coverage/src/Report/Xml/File.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
class File
|
||||
{
|
||||
protected XMLWriter $xmlWriter;
|
||||
|
||||
public function __construct(XMLWriter $xmlWriter)
|
||||
{
|
||||
$this->xmlWriter = $xmlWriter;
|
||||
}
|
||||
|
||||
public function getWriter(): XMLWriter
|
||||
{
|
||||
return $this->xmlWriter;
|
||||
}
|
||||
|
||||
public function totals(): Totals
|
||||
{
|
||||
return new Totals($this->xmlWriter);
|
||||
}
|
||||
|
||||
public function lineCoverage(string $line): Coverage
|
||||
{
|
||||
return new Coverage($this->xmlWriter, $line);
|
||||
}
|
||||
}
|
||||
49
vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php
vendored
Normal file
49
vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class Method
|
||||
{
|
||||
private XMLWriter $xmlWriter;
|
||||
|
||||
public function __construct(
|
||||
XMLWriter $xmlWriter,
|
||||
string $name,
|
||||
string $signature,
|
||||
string $start,
|
||||
?string $end,
|
||||
string $executable,
|
||||
string $executed,
|
||||
string $coverage,
|
||||
string $crap
|
||||
) {
|
||||
$this->xmlWriter = $xmlWriter;
|
||||
|
||||
$this->xmlWriter->writeAttribute('name', $name);
|
||||
$this->xmlWriter->writeAttribute('signature', $signature);
|
||||
|
||||
$this->xmlWriter->writeAttribute('start', $start);
|
||||
|
||||
if ($end !== null) {
|
||||
$this->xmlWriter->writeAttribute('end', $end);
|
||||
}
|
||||
|
||||
$this->xmlWriter->writeAttribute('crap', $crap);
|
||||
|
||||
$this->xmlWriter->writeAttribute('executable', $executable);
|
||||
$this->xmlWriter->writeAttribute('executed', $executed);
|
||||
$this->xmlWriter->writeAttribute('coverage', $coverage);
|
||||
}
|
||||
}
|
||||
45
vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php
vendored
Normal file
45
vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
abstract class Node
|
||||
{
|
||||
protected readonly XMLWriter $xmlWriter;
|
||||
|
||||
public function __construct(XMLWriter $xmlWriter)
|
||||
{
|
||||
$this->xmlWriter = $xmlWriter;
|
||||
}
|
||||
|
||||
public function totals(): Totals
|
||||
{
|
||||
return new Totals($this->xmlWriter);
|
||||
}
|
||||
|
||||
public function addDirectory(): Directory
|
||||
{
|
||||
return new Directory($this->xmlWriter);
|
||||
}
|
||||
|
||||
public function addFile(): File
|
||||
{
|
||||
return new File($this->xmlWriter);
|
||||
}
|
||||
|
||||
public function getWriter(): XMLWriter
|
||||
{
|
||||
return $this->xmlWriter;
|
||||
}
|
||||
}
|
||||
81
vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php
vendored
Normal file
81
vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use SebastianBergmann\Environment\Runtime;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Project extends Node
|
||||
{
|
||||
private readonly string $directory;
|
||||
|
||||
public function __construct(XMLWriter $xmlWriter, string $directory)
|
||||
{
|
||||
$this->directory = $directory;
|
||||
|
||||
parent::__construct($xmlWriter);
|
||||
|
||||
$this->xmlWriter->startDocument();
|
||||
|
||||
$this->xmlWriter->startElement('phpunit');
|
||||
$this->xmlWriter->writeAttribute('xmlns', Facade::XML_NAMESPACE);
|
||||
}
|
||||
|
||||
public function projectSourceDirectory(): string
|
||||
{
|
||||
return $this->directory;
|
||||
}
|
||||
|
||||
public function buildInformation(
|
||||
Runtime $runtime,
|
||||
DateTimeImmutable $buildDate,
|
||||
string $phpUnitVersion,
|
||||
string $coverageVersion,
|
||||
string $driverExtensionName,
|
||||
string $driverExtensionVersion,
|
||||
): void {
|
||||
new BuildInformation(
|
||||
$this->xmlWriter,
|
||||
$runtime,
|
||||
$buildDate,
|
||||
$phpUnitVersion,
|
||||
$coverageVersion,
|
||||
$driverExtensionName,
|
||||
$driverExtensionVersion,
|
||||
);
|
||||
}
|
||||
|
||||
public function tests(): Tests
|
||||
{
|
||||
return new Tests($this->xmlWriter);
|
||||
}
|
||||
|
||||
public function getWriter(): XMLWriter
|
||||
{
|
||||
return $this->xmlWriter;
|
||||
}
|
||||
|
||||
public function startProject(): void
|
||||
{
|
||||
$this->xmlWriter->startElement('project');
|
||||
$this->xmlWriter->writeAttribute('source', $this->directory);
|
||||
}
|
||||
|
||||
public function finalize(): void
|
||||
{
|
||||
$this->xmlWriter->endElement();
|
||||
$this->xmlWriter->endDocument();
|
||||
$this->xmlWriter->flush();
|
||||
}
|
||||
}
|
||||
108
vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php
vendored
Normal file
108
vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use function basename;
|
||||
use function dirname;
|
||||
use DOMDocument;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Report extends File
|
||||
{
|
||||
private readonly string $name;
|
||||
private readonly string $sha1;
|
||||
|
||||
public function __construct(XMLWriter $xmlWriter, string $name, string $sha1)
|
||||
{
|
||||
/*
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><file /></phpunit>');
|
||||
|
||||
$contextNode = $dom->getElementsByTagNameNS(
|
||||
Facade::XML_NAMESPACE,
|
||||
'file',
|
||||
)->item(0);
|
||||
*/
|
||||
parent::__construct($xmlWriter);
|
||||
|
||||
$this->name = $name;
|
||||
$this->sha1 = $sha1;
|
||||
|
||||
$xmlWriter->startDocument();
|
||||
$xmlWriter->startElement('phpunit');
|
||||
$xmlWriter->writeAttribute('xmlns', Facade::XML_NAMESPACE);
|
||||
$xmlWriter->startElement('file');
|
||||
$xmlWriter->writeAttribute('name', basename($this->name));
|
||||
$xmlWriter->writeAttribute('path', dirname($this->name));
|
||||
$xmlWriter->writeAttribute('hash', $this->sha1);
|
||||
}
|
||||
|
||||
public function finalize(): void
|
||||
{
|
||||
$this->xmlWriter->endElement();
|
||||
$this->xmlWriter->endElement();
|
||||
|
||||
$this->xmlWriter->endDocument();
|
||||
$this->xmlWriter->flush();
|
||||
}
|
||||
|
||||
public function functionObject(
|
||||
string $name,
|
||||
string $signature,
|
||||
string $start,
|
||||
?string $end,
|
||||
string $executable,
|
||||
string $executed,
|
||||
string $coverage,
|
||||
string $crap
|
||||
): void {
|
||||
new Method(
|
||||
$this->xmlWriter,
|
||||
$name,
|
||||
$signature,
|
||||
$start,
|
||||
$end,
|
||||
$executable,
|
||||
$executed,
|
||||
$coverage,
|
||||
$crap,
|
||||
);
|
||||
}
|
||||
|
||||
public function classObject(
|
||||
string $name,
|
||||
string $namespace,
|
||||
int $start,
|
||||
int $executable,
|
||||
int $executed,
|
||||
float $crap
|
||||
): Unit {
|
||||
return new Unit($this->xmlWriter, $name, $namespace, $start, $executable, $executed, $crap);
|
||||
}
|
||||
|
||||
public function traitObject(
|
||||
string $name,
|
||||
string $namespace,
|
||||
int $start,
|
||||
int $executable,
|
||||
int $executed,
|
||||
float $crap
|
||||
): Unit {
|
||||
return new Unit($this->xmlWriter, $name, $namespace, $start, $executable, $executed, $crap);
|
||||
}
|
||||
|
||||
public function source(): Source
|
||||
{
|
||||
return new Source($this->xmlWriter);
|
||||
}
|
||||
}
|
||||
34
vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php
vendored
Normal file
34
vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use TheSeer\Tokenizer\NamespaceUri;
|
||||
use TheSeer\Tokenizer\Tokenizer;
|
||||
use TheSeer\Tokenizer\XMLSerializer;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class Source
|
||||
{
|
||||
private XMLWriter $xmlWriter;
|
||||
|
||||
public function __construct(XMLWriter $xmlWriter)
|
||||
{
|
||||
$this->xmlWriter = $xmlWriter;
|
||||
}
|
||||
|
||||
public function setSourceCode(string $source): void
|
||||
{
|
||||
$tokens = (new Tokenizer)->parse($source);
|
||||
(new XMLSerializer(new NamespaceUri(Facade::XML_NAMESPACE)))->appendToWriter($this->xmlWriter, $tokens);
|
||||
}
|
||||
}
|
||||
44
vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php
vendored
Normal file
44
vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use function sprintf;
|
||||
use SebastianBergmann\CodeCoverage\CodeCoverage;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @phpstan-import-type TestType from CodeCoverage
|
||||
*/
|
||||
final readonly class Tests
|
||||
{
|
||||
private readonly XMLWriter $xmlWriter;
|
||||
|
||||
public function __construct(XMLWriter $xmlWriter)
|
||||
{
|
||||
$this->xmlWriter = $xmlWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TestType $result
|
||||
*/
|
||||
public function addTest(string $test, array $result): void
|
||||
{
|
||||
$this->xmlWriter->startElement('test');
|
||||
|
||||
$this->xmlWriter->writeAttribute('name', $test);
|
||||
$this->xmlWriter->writeAttribute('size', $result['size']);
|
||||
$this->xmlWriter->writeAttribute('status', $result['status']);
|
||||
$this->xmlWriter->writeAttribute('time', sprintf('%F', $result['time']));
|
||||
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
}
|
||||
95
vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php
vendored
Normal file
95
vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use function sprintf;
|
||||
use SebastianBergmann\CodeCoverage\Util\Percentage;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class Totals
|
||||
{
|
||||
private XMLWriter $xmlWriter;
|
||||
|
||||
public function __construct(XMLWriter $xmlWriter)
|
||||
{
|
||||
$this->xmlWriter = $xmlWriter;
|
||||
}
|
||||
|
||||
public function setNumLines(int $loc, int $cloc, int $ncloc, int $executable, int $executed): void
|
||||
{
|
||||
$this->xmlWriter->startElement('lines');
|
||||
$this->xmlWriter->writeAttribute('total', (string) $loc);
|
||||
$this->xmlWriter->writeAttribute('comments', (string) $cloc);
|
||||
$this->xmlWriter->writeAttribute('code', (string) $ncloc);
|
||||
$this->xmlWriter->writeAttribute('executable', (string) $executable);
|
||||
$this->xmlWriter->writeAttribute('executed', (string) $executed);
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'percent',
|
||||
$executable === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($executed, $executable)->asFloat()),
|
||||
);
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function setNumClasses(int $count, int $tested): void
|
||||
{
|
||||
$this->xmlWriter->startElement('classes');
|
||||
$this->xmlWriter->writeAttribute('count', (string) $count);
|
||||
$this->xmlWriter->writeAttribute('tested', (string) $tested);
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'percent',
|
||||
$count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()),
|
||||
);
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function setNumTraits(int $count, int $tested): void
|
||||
{
|
||||
$this->xmlWriter->startElement('traits');
|
||||
$this->xmlWriter->writeAttribute('count', (string) $count);
|
||||
$this->xmlWriter->writeAttribute('tested', (string) $tested);
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'percent',
|
||||
$count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()),
|
||||
);
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function setNumMethods(int $count, int $tested): void
|
||||
{
|
||||
$this->xmlWriter->startElement('methods');
|
||||
$this->xmlWriter->writeAttribute('count', (string) $count);
|
||||
$this->xmlWriter->writeAttribute('tested', (string) $tested);
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'percent',
|
||||
$count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()),
|
||||
);
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function setNumFunctions(int $count, int $tested): void
|
||||
{
|
||||
$this->xmlWriter->startElement('functions');
|
||||
$this->xmlWriter->writeAttribute('count', (string) $count);
|
||||
$this->xmlWriter->writeAttribute('tested', (string) $tested);
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'percent',
|
||||
$count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()),
|
||||
);
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function getWriter(): XMLWriter
|
||||
{
|
||||
return $this->xmlWriter;
|
||||
}
|
||||
}
|
||||
65
vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php
vendored
Normal file
65
vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?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\Report\Xml;
|
||||
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class Unit
|
||||
{
|
||||
private XMLWriter $xmlWriter;
|
||||
|
||||
public function __construct(
|
||||
XMLWriter $xmlWriter,
|
||||
string $name,
|
||||
string $namespace,
|
||||
int $start,
|
||||
int $executable,
|
||||
int $executed,
|
||||
float $crap
|
||||
) {
|
||||
$this->xmlWriter = $xmlWriter;
|
||||
|
||||
$this->xmlWriter->writeAttribute('name', $name);
|
||||
$this->xmlWriter->writeAttribute('start', (string) $start);
|
||||
$this->xmlWriter->writeAttribute('executable', (string) $executable);
|
||||
$this->xmlWriter->writeAttribute('executed', (string) $executed);
|
||||
$this->xmlWriter->writeAttribute('crap', (string) $crap);
|
||||
|
||||
$this->xmlWriter->startElement('namespace');
|
||||
$this->xmlWriter->writeAttribute('name', $namespace);
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function addMethod(
|
||||
string $name,
|
||||
string $signature,
|
||||
string $start,
|
||||
?string $end,
|
||||
string $executable,
|
||||
string $executed,
|
||||
string $coverage,
|
||||
string $crap
|
||||
): void {
|
||||
new Method(
|
||||
$this->xmlWriter,
|
||||
$name,
|
||||
$signature,
|
||||
$start,
|
||||
$end,
|
||||
$executable,
|
||||
$executed,
|
||||
$coverage,
|
||||
$crap,
|
||||
);
|
||||
}
|
||||
}
|
||||
44
vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php
vendored
Normal file
44
vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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\StaticAnalysis;
|
||||
|
||||
use function file_get_contents;
|
||||
use SebastianBergmann\CodeCoverage\Filter;
|
||||
|
||||
/**
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class CacheWarmer
|
||||
{
|
||||
/**
|
||||
* @return array{cacheHits: non-negative-int, cacheMisses: non-negative-int}
|
||||
*/
|
||||
public function warmCache(string $cacheDirectory, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode, Filter $filter): array
|
||||
{
|
||||
$analyser = new CachingSourceAnalyser(
|
||||
$cacheDirectory,
|
||||
new ParsingSourceAnalyser,
|
||||
);
|
||||
|
||||
foreach ($filter->files() as $file) {
|
||||
$analyser->analyse(
|
||||
$file,
|
||||
file_get_contents($file),
|
||||
$useAnnotationsForIgnoringCode,
|
||||
$ignoreDeprecatedCode,
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'cacheHits' => $analyser->cacheHits(),
|
||||
'cacheMisses' => $analyser->cacheMisses(),
|
||||
];
|
||||
}
|
||||
}
|
||||
154
vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingSourceAnalyser.php
vendored
Normal file
154
vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingSourceAnalyser.php
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
<?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\StaticAnalysis;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function hash;
|
||||
use function implode;
|
||||
use function is_file;
|
||||
use function serialize;
|
||||
use function unserialize;
|
||||
use SebastianBergmann\CodeCoverage\Util\Filesystem;
|
||||
use SebastianBergmann\CodeCoverage\Version;
|
||||
|
||||
/**
|
||||
* @internal This interface is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class CachingSourceAnalyser implements SourceAnalyser
|
||||
{
|
||||
/**
|
||||
* @var non-empty-string
|
||||
*/
|
||||
private readonly string $directory;
|
||||
private readonly SourceAnalyser $sourceAnalyser;
|
||||
|
||||
/**
|
||||
* @var non-negative-int
|
||||
*/
|
||||
private int $cacheHits = 0;
|
||||
|
||||
/**
|
||||
* @var non-negative-int
|
||||
*/
|
||||
private int $cacheMisses = 0;
|
||||
|
||||
public function __construct(string $directory, SourceAnalyser $sourceAnalyser)
|
||||
{
|
||||
Filesystem::createDirectory($directory);
|
||||
|
||||
$this->directory = $directory;
|
||||
$this->sourceAnalyser = $sourceAnalyser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param non-empty-string $sourceCodeFile
|
||||
*/
|
||||
public function analyse(string $sourceCodeFile, string $sourceCode, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode): AnalysisResult
|
||||
{
|
||||
$cacheFile = $this->cacheFile(
|
||||
$sourceCode,
|
||||
$useAnnotationsForIgnoringCode,
|
||||
$ignoreDeprecatedCode,
|
||||
);
|
||||
|
||||
$cachedAnalysisResult = $this->read($cacheFile);
|
||||
|
||||
if ($cachedAnalysisResult !== false) {
|
||||
$this->cacheHits++;
|
||||
|
||||
return $cachedAnalysisResult;
|
||||
}
|
||||
|
||||
$this->cacheMisses++;
|
||||
|
||||
$analysisResult = $this->sourceAnalyser->analyse(
|
||||
$sourceCodeFile,
|
||||
$sourceCode,
|
||||
$useAnnotationsForIgnoringCode,
|
||||
$ignoreDeprecatedCode,
|
||||
);
|
||||
|
||||
$this->write($cacheFile, $analysisResult);
|
||||
|
||||
return $analysisResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-negative-int
|
||||
*/
|
||||
public function cacheHits(): int
|
||||
{
|
||||
return $this->cacheHits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-negative-int
|
||||
*/
|
||||
public function cacheMisses(): int
|
||||
{
|
||||
return $this->cacheMisses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param non-empty-string $cacheFile
|
||||
*/
|
||||
private function read(string $cacheFile): AnalysisResult|false
|
||||
{
|
||||
if (!is_file($cacheFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return unserialize(
|
||||
file_get_contents($cacheFile),
|
||||
[
|
||||
'allowed_classes' => [
|
||||
AnalysisResult::class,
|
||||
Class_::class,
|
||||
Function_::class,
|
||||
Interface_::class,
|
||||
LinesOfCode::class,
|
||||
Method::class,
|
||||
Trait_::class,
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param non-empty-string $cacheFile
|
||||
*/
|
||||
private function write(string $cacheFile, AnalysisResult $result): void
|
||||
{
|
||||
file_put_contents(
|
||||
$cacheFile,
|
||||
serialize($result),
|
||||
);
|
||||
}
|
||||
|
||||
private function cacheFile(string $source, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode): string
|
||||
{
|
||||
$cacheKey = hash(
|
||||
'sha256',
|
||||
implode(
|
||||
"\0",
|
||||
[
|
||||
$source,
|
||||
Version::id(),
|
||||
$useAnnotationsForIgnoringCode,
|
||||
$ignoreDeprecatedCode,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
return $this->directory . DIRECTORY_SEPARATOR . $cacheKey;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user