glastree_on_gitea

This commit is contained in:
2026-05-26 08:14:29 +02:00
commit 0bed099d05
9556 changed files with 1186307 additions and 0 deletions
@@ -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();
}
}
@@ -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();
}
}
@@ -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
{
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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();
}
}
@@ -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;
}
}
@@ -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,
);
}
}