summaryrefslogtreecommitdiff
path: root/vendor/phpunit/php-code-coverage/src/Report/Xml
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/phpunit/php-code-coverage/src/Report/Xml')
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php88
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php74
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php17
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php315
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/File.php87
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php61
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php93
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php90
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php99
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php42
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php51
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php146
-rw-r--r--vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php78
13 files changed, 1241 insertions, 0 deletions
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php
new file mode 100644
index 000000000..ebdbae612
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php
@@ -0,0 +1,88 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 constant;
+use function phpversion;
+use DateTimeImmutable;
+use DOMElement;
+use SebastianBergmann\Environment\Runtime;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class BuildInformation
+{
+ /**
+ * @var DOMElement
+ */
+ private $contextNode;
+
+ public function __construct(DOMElement $contextNode)
+ {
+ $this->contextNode = $contextNode;
+ }
+
+ public function setRuntimeInformation(Runtime $runtime): void
+ {
+ $runtimeNode = $this->nodeByName('runtime');
+
+ $runtimeNode->setAttribute('name', $runtime->getName());
+ $runtimeNode->setAttribute('version', $runtime->getVersion());
+ $runtimeNode->setAttribute('url', $runtime->getVendorUrl());
+
+ $driverNode = $this->nodeByName('driver');
+
+ if ($runtime->hasPHPDBGCodeCoverage()) {
+ $driverNode->setAttribute('name', 'phpdbg');
+ $driverNode->setAttribute('version', constant('PHPDBG_VERSION'));
+ }
+
+ if ($runtime->hasXdebug()) {
+ $driverNode->setAttribute('name', 'xdebug');
+ $driverNode->setAttribute('version', phpversion('xdebug'));
+ }
+
+ if ($runtime->hasPCOV()) {
+ $driverNode->setAttribute('name', 'pcov');
+ $driverNode->setAttribute('version', phpversion('pcov'));
+ }
+ }
+
+ public function setBuildTime(DateTimeImmutable $date): void
+ {
+ $this->contextNode->setAttribute('time', $date->format('D M j G:i:s T Y'));
+ }
+
+ public function setGeneratorVersions(string $phpUnitVersion, string $coverageVersion): void
+ {
+ $this->contextNode->setAttribute('phpunit', $phpUnitVersion);
+ $this->contextNode->setAttribute('coverage', $coverageVersion);
+ }
+
+ private function nodeByName(string $name): DOMElement
+ {
+ $node = $this->contextNode->getElementsByTagNameNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ $name
+ )->item(0);
+
+ if (!$node) {
+ $node = $this->contextNode->appendChild(
+ $this->contextNode->ownerDocument->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ $name
+ )
+ );
+ }
+
+ return $node;
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php
new file mode 100644
index 000000000..215f9b932
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php
@@ -0,0 +1,74 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMElement;
+use SebastianBergmann\CodeCoverage\ReportAlreadyFinalizedException;
+use XMLWriter;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Coverage
+{
+ /**
+ * @var XMLWriter
+ */
+ private $writer;
+
+ /**
+ * @var DOMElement
+ */
+ private $contextNode;
+
+ /**
+ * @var bool
+ */
+ private $finalized = false;
+
+ public function __construct(DOMElement $context, string $line)
+ {
+ $this->contextNode = $context;
+
+ $this->writer = new XMLWriter();
+ $this->writer->openMemory();
+ $this->writer->startElementNS(null, $context->nodeName, 'https://schema.phpunit.de/coverage/1.0');
+ $this->writer->writeAttribute('nr', $line);
+ }
+
+ /**
+ * @throws ReportAlreadyFinalizedException
+ */
+ public function addTest(string $test): void
+ {
+ if ($this->finalized) {
+ throw new ReportAlreadyFinalizedException;
+ }
+
+ $this->writer->startElement('covered');
+ $this->writer->writeAttribute('by', $test);
+ $this->writer->endElement();
+ }
+
+ public function finalize(): void
+ {
+ $this->writer->endElement();
+
+ $fragment = $this->contextNode->ownerDocument->createDocumentFragment();
+ $fragment->appendXML($this->writer->outputMemory());
+
+ $this->contextNode->parentNode->replaceChild(
+ $fragment,
+ $this->contextNode
+ );
+
+ $this->finalized = true;
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php
new file mode 100644
index 000000000..b712953ab
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php
@@ -0,0 +1,17 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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
+{
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php
new file mode 100644
index 000000000..3ecc7506f
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php
@@ -0,0 +1,315 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 const PHP_EOL;
+use function count;
+use function dirname;
+use function file_get_contents;
+use function file_put_contents;
+use function is_array;
+use function is_dir;
+use function is_file;
+use function is_writable;
+use function libxml_clear_errors;
+use function libxml_get_errors;
+use function libxml_use_internal_errors;
+use function sprintf;
+use function strlen;
+use function substr;
+use DateTimeImmutable;
+use DOMDocument;
+use SebastianBergmann\CodeCoverage\CodeCoverage;
+use SebastianBergmann\CodeCoverage\Driver\PathExistsButIsNotDirectoryException;
+use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException;
+use SebastianBergmann\CodeCoverage\Node\AbstractNode;
+use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
+use SebastianBergmann\CodeCoverage\Node\File as FileNode;
+use SebastianBergmann\CodeCoverage\Util\Filesystem as DirectoryUtil;
+use SebastianBergmann\CodeCoverage\Version;
+use SebastianBergmann\CodeCoverage\XmlException;
+use SebastianBergmann\Environment\Runtime;
+
+final class Facade
+{
+ /**
+ * @var string
+ */
+ private $target;
+
+ /**
+ * @var Project
+ */
+ private $project;
+
+ /**
+ * @var string
+ */
+ private $phpUnitVersion;
+
+ public function __construct(string $version)
+ {
+ $this->phpUnitVersion = $version;
+ }
+
+ /**
+ * @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();
+
+ $this->project = new Project(
+ $coverage->getReport()->name()
+ );
+
+ $this->setBuildInformation();
+ $this->processTests($coverage->getTests());
+ $this->processDirectory($report, $this->project);
+
+ $this->saveDocument($this->project->asDom(), 'index');
+ }
+
+ private function setBuildInformation(): void
+ {
+ $buildNode = $this->project->buildInformation();
+ $buildNode->setRuntimeInformation(new Runtime);
+ $buildNode->setBuildTime(new DateTimeImmutable);
+ $buildNode->setGeneratorVersions($this->phpUnitVersion, Version::id());
+ }
+
+ /**
+ * @throws PathExistsButIsNotDirectoryException
+ * @throws WriteOperationFailedException
+ */
+ private function initTargetDirectory(string $directory): void
+ {
+ if (is_file($directory)) {
+ if (!is_dir($directory)) {
+ throw new PathExistsButIsNotDirectoryException($directory);
+ }
+
+ if (!is_writable($directory)) {
+ throw new WriteOperationFailedException($directory);
+ }
+ }
+
+ DirectoryUtil::createDirectory($directory);
+ }
+
+ /**
+ * @throws XmlException
+ */
+ private function processDirectory(DirectoryNode $directory, Node $context): void
+ {
+ $directoryName = $directory->name();
+
+ if ($this->project->projectSourceDirectory() === $directoryName) {
+ $directoryName = '/';
+ }
+
+ $directoryObject = $context->addDirectory($directoryName);
+
+ $this->setTotals($directory, $directoryObject->totals());
+
+ foreach ($directory->directories() as $node) {
+ $this->processDirectory($node, $directoryObject);
+ }
+
+ foreach ($directory->files() as $node) {
+ $this->processFile($node, $directoryObject);
+ }
+ }
+
+ /**
+ * @throws XmlException
+ */
+ private function processFile(FileNode $file, Directory $context): void
+ {
+ $fileObject = $context->addFile(
+ $file->name(),
+ $file->id() . '.xml'
+ );
+
+ $this->setTotals($file, $fileObject->totals());
+
+ $path = substr(
+ $file->pathAsString(),
+ strlen($this->project->projectSourceDirectory())
+ );
+
+ $fileReport = new Report($path);
+
+ $this->setTotals($file, $fileReport->totals());
+
+ foreach ($file->classesAndTraits() as $unit) {
+ $this->processUnit($unit, $fileReport);
+ }
+
+ foreach ($file->functions() as $function) {
+ $this->processFunction($function, $fileReport);
+ }
+
+ foreach ($file->lineCoverageData() as $line => $tests) {
+ if (!is_array($tests) || count($tests) === 0) {
+ continue;
+ }
+
+ $coverage = $fileReport->lineCoverage((string) $line);
+
+ foreach ($tests as $test) {
+ $coverage->addTest($test);
+ }
+
+ $coverage->finalize();
+ }
+
+ $fileReport->source()->setSourceCode(
+ file_get_contents($file->pathAsString())
+ );
+
+ $this->saveDocument($fileReport->asDom(), $file->id());
+ }
+
+ private function processUnit(array $unit, Report $report): void
+ {
+ if (isset($unit['className'])) {
+ $unitObject = $report->classObject($unit['className']);
+ } else {
+ $unitObject = $report->traitObject($unit['traitName']);
+ }
+
+ $unitObject->setLines(
+ $unit['startLine'],
+ $unit['executableLines'],
+ $unit['executedLines']
+ );
+
+ $unitObject->setCrap((float) $unit['crap']);
+ $unitObject->setNamespace($unit['namespace']);
+
+ foreach ($unit['methods'] as $method) {
+ $methodObject = $unitObject->addMethod($method['methodName']);
+ $methodObject->setSignature($method['signature']);
+ $methodObject->setLines((string) $method['startLine'], (string) $method['endLine']);
+ $methodObject->setCrap($method['crap']);
+ $methodObject->setTotals(
+ (string) $method['executableLines'],
+ (string) $method['executedLines'],
+ (string) $method['coverage']
+ );
+ }
+ }
+
+ private function processFunction(array $function, Report $report): void
+ {
+ $functionObject = $report->functionObject($function['functionName']);
+
+ $functionObject->setSignature($function['signature']);
+ $functionObject->setLines((string) $function['startLine']);
+ $functionObject->setCrap($function['crap']);
+ $functionObject->setTotals((string) $function['executableLines'], (string) $function['executedLines'], (string) $function['coverage']);
+ }
+
+ private function processTests(array $tests): void
+ {
+ $testsObject = $this->project->tests();
+
+ foreach ($tests as $test => $result) {
+ $testsObject->addTest($test, $result);
+ }
+ }
+
+ private function setTotals(AbstractNode $node, Totals $totals): void
+ {
+ $loc = $node->linesOfCode();
+
+ $totals->setNumLines(
+ $loc['linesOfCode'],
+ $loc['commentLinesOfCode'],
+ $loc['nonCommentLinesOfCode'],
+ $node->numberOfExecutableLines(),
+ $node->numberOfExecutedLines()
+ );
+
+ $totals->setNumClasses(
+ $node->numberOfClasses(),
+ $node->numberOfTestedClasses()
+ );
+
+ $totals->setNumTraits(
+ $node->numberOfTraits(),
+ $node->numberOfTestedTraits()
+ );
+
+ $totals->setNumMethods(
+ $node->numberOfMethods(),
+ $node->numberOfTestedMethods()
+ );
+
+ $totals->setNumFunctions(
+ $node->numberOfFunctions(),
+ $node->numberOfTestedFunctions()
+ );
+ }
+
+ private function targetDirectory(): string
+ {
+ return $this->target;
+ }
+
+ /**
+ * @throws XmlException
+ */
+ private function saveDocument(DOMDocument $document, string $name): void
+ {
+ $filename = sprintf('%s/%s.xml', $this->targetDirectory(), $name);
+
+ $document->formatOutput = true;
+ $document->preserveWhiteSpace = false;
+ $this->initTargetDirectory(dirname($filename));
+
+ file_put_contents($filename, $this->documentAsString($document));
+ }
+
+ /**
+ * @throws XmlException
+ *
+ * @see https://bugs.php.net/bug.php?id=79191
+ */
+ private function documentAsString(DOMDocument $document): string
+ {
+ $xmlErrorHandling = libxml_use_internal_errors(true);
+ $xml = $document->saveXML();
+
+ if ($xml === false) {
+ $message = 'Unable to generate the XML';
+
+ foreach (libxml_get_errors() as $error) {
+ $message .= PHP_EOL . $error->message;
+ }
+
+ throw new XmlException($message);
+ }
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($xmlErrorHandling);
+
+ return $xml;
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php
new file mode 100644
index 000000000..245c5cee6
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php
@@ -0,0 +1,87 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMDocument;
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+class File
+{
+ /**
+ * @var DOMDocument
+ */
+ private $dom;
+
+ /**
+ * @var DOMElement
+ */
+ private $contextNode;
+
+ public function __construct(DOMElement $context)
+ {
+ $this->dom = $context->ownerDocument;
+ $this->contextNode = $context;
+ }
+
+ public function totals(): Totals
+ {
+ $totalsContainer = $this->contextNode->firstChild;
+
+ if (!$totalsContainer) {
+ $totalsContainer = $this->contextNode->appendChild(
+ $this->dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'totals'
+ )
+ );
+ }
+
+ return new Totals($totalsContainer);
+ }
+
+ public function lineCoverage(string $line): Coverage
+ {
+ $coverage = $this->contextNode->getElementsByTagNameNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'coverage'
+ )->item(0);
+
+ if (!$coverage) {
+ $coverage = $this->contextNode->appendChild(
+ $this->dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'coverage'
+ )
+ );
+ }
+
+ $lineNode = $coverage->appendChild(
+ $this->dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'line'
+ )
+ );
+
+ return new Coverage($lineNode, $line);
+ }
+
+ protected function contextNode(): DOMElement
+ {
+ return $this->contextNode;
+ }
+
+ protected function dom(): DOMDocument
+ {
+ return $this->dom;
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php
new file mode 100644
index 000000000..7e3009997
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Method
+{
+ /**
+ * @var DOMElement
+ */
+ private $contextNode;
+
+ public function __construct(DOMElement $context, string $name)
+ {
+ $this->contextNode = $context;
+
+ $this->setName($name);
+ }
+
+ public function setSignature(string $signature): void
+ {
+ $this->contextNode->setAttribute('signature', $signature);
+ }
+
+ public function setLines(string $start, ?string $end = null): void
+ {
+ $this->contextNode->setAttribute('start', $start);
+
+ if ($end !== null) {
+ $this->contextNode->setAttribute('end', $end);
+ }
+ }
+
+ public function setTotals(string $executable, string $executed, string $coverage): void
+ {
+ $this->contextNode->setAttribute('executable', $executable);
+ $this->contextNode->setAttribute('executed', $executed);
+ $this->contextNode->setAttribute('coverage', $coverage);
+ }
+
+ public function setCrap(string $crap): void
+ {
+ $this->contextNode->setAttribute('crap', $crap);
+ }
+
+ private function setName(string $name): void
+ {
+ $this->contextNode->setAttribute('name', $name);
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php
new file mode 100644
index 000000000..159923093
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php
@@ -0,0 +1,93 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMDocument;
+use DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+abstract class Node
+{
+ /**
+ * @var DOMDocument
+ */
+ private $dom;
+
+ /**
+ * @var DOMElement
+ */
+ private $contextNode;
+
+ public function __construct(DOMElement $context)
+ {
+ $this->setContextNode($context);
+ }
+
+ public function dom(): DOMDocument
+ {
+ return $this->dom;
+ }
+
+ public function totals(): Totals
+ {
+ $totalsContainer = $this->contextNode()->firstChild;
+
+ if (!$totalsContainer) {
+ $totalsContainer = $this->contextNode()->appendChild(
+ $this->dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'totals'
+ )
+ );
+ }
+
+ return new Totals($totalsContainer);
+ }
+
+ public function addDirectory(string $name): Directory
+ {
+ $dirNode = $this->dom()->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'directory'
+ );
+
+ $dirNode->setAttribute('name', $name);
+ $this->contextNode()->appendChild($dirNode);
+
+ return new Directory($dirNode);
+ }
+
+ public function addFile(string $name, string $href): File
+ {
+ $fileNode = $this->dom()->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'file'
+ );
+
+ $fileNode->setAttribute('name', $name);
+ $fileNode->setAttribute('href', $href);
+ $this->contextNode()->appendChild($fileNode);
+
+ return new File($fileNode);
+ }
+
+ protected function setContextNode(DOMElement $context): void
+ {
+ $this->dom = $context->ownerDocument;
+ $this->contextNode = $context;
+ }
+
+ protected function contextNode(): DOMElement
+ {
+ return $this->contextNode;
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php
new file mode 100644
index 000000000..b566bce06
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php
@@ -0,0 +1,90 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMDocument;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Project extends Node
+{
+ public function __construct(string $directory)
+ {
+ $this->init();
+ $this->setProjectSourceDirectory($directory);
+ }
+
+ public function projectSourceDirectory(): string
+ {
+ return $this->contextNode()->getAttribute('source');
+ }
+
+ public function buildInformation(): BuildInformation
+ {
+ $buildNode = $this->dom()->getElementsByTagNameNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'build'
+ )->item(0);
+
+ if (!$buildNode) {
+ $buildNode = $this->dom()->documentElement->appendChild(
+ $this->dom()->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'build'
+ )
+ );
+ }
+
+ return new BuildInformation($buildNode);
+ }
+
+ public function tests(): Tests
+ {
+ $testsNode = $this->contextNode()->getElementsByTagNameNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'tests'
+ )->item(0);
+
+ if (!$testsNode) {
+ $testsNode = $this->contextNode()->appendChild(
+ $this->dom()->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'tests'
+ )
+ );
+ }
+
+ return new Tests($testsNode);
+ }
+
+ public function asDom(): DOMDocument
+ {
+ return $this->dom();
+ }
+
+ private function init(): void
+ {
+ $dom = new DOMDocument;
+ $dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><build/><project/></phpunit>');
+
+ $this->setContextNode(
+ $dom->getElementsByTagNameNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'project'
+ )->item(0)
+ );
+ }
+
+ private function setProjectSourceDirectory(string $name): void
+ {
+ $this->contextNode()->setAttribute('source', $name);
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php
new file mode 100644
index 000000000..b53b08c00
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php
@@ -0,0 +1,99 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Report extends File
+{
+ public function __construct(string $name)
+ {
+ $dom = new DOMDocument();
+ $dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><file /></phpunit>');
+
+ $contextNode = $dom->getElementsByTagNameNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'file'
+ )->item(0);
+
+ parent::__construct($contextNode);
+
+ $this->setName($name);
+ }
+
+ public function asDom(): DOMDocument
+ {
+ return $this->dom();
+ }
+
+ public function functionObject($name): Method
+ {
+ $node = $this->contextNode()->appendChild(
+ $this->dom()->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'function'
+ )
+ );
+
+ return new Method($node, $name);
+ }
+
+ public function classObject($name): Unit
+ {
+ return $this->unitObject('class', $name);
+ }
+
+ public function traitObject($name): Unit
+ {
+ return $this->unitObject('trait', $name);
+ }
+
+ public function source(): Source
+ {
+ $source = $this->contextNode()->getElementsByTagNameNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'source'
+ )->item(0);
+
+ if (!$source) {
+ $source = $this->contextNode()->appendChild(
+ $this->dom()->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'source'
+ )
+ );
+ }
+
+ return new Source($source);
+ }
+
+ private function setName(string $name): void
+ {
+ $this->contextNode()->setAttribute('name', basename($name));
+ $this->contextNode()->setAttribute('path', dirname($name));
+ }
+
+ private function unitObject(string $tagName, $name): Unit
+ {
+ $node = $this->contextNode()->appendChild(
+ $this->dom()->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ $tagName
+ )
+ );
+
+ return new Unit($node, $name);
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php
new file mode 100644
index 000000000..8fd20f58f
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php
@@ -0,0 +1,42 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMElement;
+use TheSeer\Tokenizer\NamespaceUri;
+use TheSeer\Tokenizer\Tokenizer;
+use TheSeer\Tokenizer\XMLSerializer;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Source
+{
+ /** @var DOMElement */
+ private $context;
+
+ public function __construct(DOMElement $context)
+ {
+ $this->context = $context;
+ }
+
+ public function setSourceCode(string $source): void
+ {
+ $context = $this->context;
+
+ $tokens = (new Tokenizer())->parse($source);
+ $srcDom = (new XMLSerializer(new NamespaceUri($context->namespaceURI)))->toDom($tokens);
+
+ $context->parentNode->replaceChild(
+ $context->ownerDocument->importNode($srcDom->documentElement, true),
+ $context
+ );
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php
new file mode 100644
index 000000000..c2e56268c
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php
@@ -0,0 +1,51 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Tests
+{
+ private $contextNode;
+
+ private $codeMap = [
+ -1 => 'UNKNOWN', // PHPUnit_Runner_BaseTestRunner::STATUS_UNKNOWN
+ 0 => 'PASSED', // PHPUnit_Runner_BaseTestRunner::STATUS_PASSED
+ 1 => 'SKIPPED', // PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED
+ 2 => 'INCOMPLETE', // PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE
+ 3 => 'FAILURE', // PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE
+ 4 => 'ERROR', // PHPUnit_Runner_BaseTestRunner::STATUS_ERROR
+ 5 => 'RISKY', // PHPUnit_Runner_BaseTestRunner::STATUS_RISKY
+ 6 => 'WARNING', // PHPUnit_Runner_BaseTestRunner::STATUS_WARNING
+ ];
+
+ public function __construct(DOMElement $context)
+ {
+ $this->contextNode = $context;
+ }
+
+ public function addTest(string $test, array $result): void
+ {
+ $node = $this->contextNode->appendChild(
+ $this->contextNode->ownerDocument->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'test'
+ )
+ );
+
+ $node->setAttribute('name', $test);
+ $node->setAttribute('size', $result['size']);
+ $node->setAttribute('result', (string) $result['status']);
+ $node->setAttribute('status', $this->codeMap[(int) $result['status']]);
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php
new file mode 100644
index 000000000..370813188
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php
@@ -0,0 +1,146 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMElement;
+use DOMNode;
+use SebastianBergmann\CodeCoverage\Util\Percentage;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Totals
+{
+ /**
+ * @var DOMNode
+ */
+ private $container;
+
+ /**
+ * @var DOMElement
+ */
+ private $linesNode;
+
+ /**
+ * @var DOMElement
+ */
+ private $methodsNode;
+
+ /**
+ * @var DOMElement
+ */
+ private $functionsNode;
+
+ /**
+ * @var DOMElement
+ */
+ private $classesNode;
+
+ /**
+ * @var DOMElement
+ */
+ private $traitsNode;
+
+ public function __construct(DOMElement $container)
+ {
+ $this->container = $container;
+ $dom = $container->ownerDocument;
+
+ $this->linesNode = $dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'lines'
+ );
+
+ $this->methodsNode = $dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'methods'
+ );
+
+ $this->functionsNode = $dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'functions'
+ );
+
+ $this->classesNode = $dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'classes'
+ );
+
+ $this->traitsNode = $dom->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'traits'
+ );
+
+ $container->appendChild($this->linesNode);
+ $container->appendChild($this->methodsNode);
+ $container->appendChild($this->functionsNode);
+ $container->appendChild($this->classesNode);
+ $container->appendChild($this->traitsNode);
+ }
+
+ public function container(): DOMNode
+ {
+ return $this->container;
+ }
+
+ public function setNumLines(int $loc, int $cloc, int $ncloc, int $executable, int $executed): void
+ {
+ $this->linesNode->setAttribute('total', (string) $loc);
+ $this->linesNode->setAttribute('comments', (string) $cloc);
+ $this->linesNode->setAttribute('code', (string) $ncloc);
+ $this->linesNode->setAttribute('executable', (string) $executable);
+ $this->linesNode->setAttribute('executed', (string) $executed);
+ $this->linesNode->setAttribute(
+ 'percent',
+ $executable === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($executed, $executable)->asFloat())
+ );
+ }
+
+ public function setNumClasses(int $count, int $tested): void
+ {
+ $this->classesNode->setAttribute('count', (string) $count);
+ $this->classesNode->setAttribute('tested', (string) $tested);
+ $this->classesNode->setAttribute(
+ 'percent',
+ $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat())
+ );
+ }
+
+ public function setNumTraits(int $count, int $tested): void
+ {
+ $this->traitsNode->setAttribute('count', (string) $count);
+ $this->traitsNode->setAttribute('tested', (string) $tested);
+ $this->traitsNode->setAttribute(
+ 'percent',
+ $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat())
+ );
+ }
+
+ public function setNumMethods(int $count, int $tested): void
+ {
+ $this->methodsNode->setAttribute('count', (string) $count);
+ $this->methodsNode->setAttribute('tested', (string) $tested);
+ $this->methodsNode->setAttribute(
+ 'percent',
+ $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat())
+ );
+ }
+
+ public function setNumFunctions(int $count, int $tested): void
+ {
+ $this->functionsNode->setAttribute('count', (string) $count);
+ $this->functionsNode->setAttribute('tested', (string) $tested);
+ $this->functionsNode->setAttribute(
+ 'percent',
+ $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat())
+ );
+ }
+}
diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php
new file mode 100644
index 000000000..d84dc481f
--- /dev/null
+++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php
@@ -0,0 +1,78 @@
+<?php declare(strict_types=1);
+/*
+ * This file is part of phpunit/php-code-coverage.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * 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 DOMElement;
+
+/**
+ * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
+ */
+final class Unit
+{
+ /**
+ * @var DOMElement
+ */
+ private $contextNode;
+
+ public function __construct(DOMElement $context, string $name)
+ {
+ $this->contextNode = $context;
+
+ $this->setName($name);
+ }
+
+ public function setLines(int $start, int $executable, int $executed): void
+ {
+ $this->contextNode->setAttribute('start', (string) $start);
+ $this->contextNode->setAttribute('executable', (string) $executable);
+ $this->contextNode->setAttribute('executed', (string) $executed);
+ }
+
+ public function setCrap(float $crap): void
+ {
+ $this->contextNode->setAttribute('crap', (string) $crap);
+ }
+
+ public function setNamespace(string $namespace): void
+ {
+ $node = $this->contextNode->getElementsByTagNameNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'namespace'
+ )->item(0);
+
+ if (!$node) {
+ $node = $this->contextNode->appendChild(
+ $this->contextNode->ownerDocument->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'namespace'
+ )
+ );
+ }
+
+ $node->setAttribute('name', $namespace);
+ }
+
+ public function addMethod(string $name): Method
+ {
+ $node = $this->contextNode->appendChild(
+ $this->contextNode->ownerDocument->createElementNS(
+ 'https://schema.phpunit.de/coverage/1.0',
+ 'method'
+ )
+ );
+
+ return new Method($node, $name);
+ }
+
+ private function setName(string $name): void
+ {
+ $this->contextNode->setAttribute('name', $name);
+ }
+}