glastree_on_gitea
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Class_ extends Target
|
||||
{
|
||||
/**
|
||||
* @var class-string
|
||||
*/
|
||||
private string $className;
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
*/
|
||||
protected function __construct(string $className)
|
||||
{
|
||||
$this->className = $className;
|
||||
}
|
||||
|
||||
public function isClass(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string
|
||||
*/
|
||||
public function className(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
return 'classes';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function target(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function description(): string
|
||||
{
|
||||
return 'Class ' . $this->target();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class ClassesThatExtendClass extends Target
|
||||
{
|
||||
/**
|
||||
* @var class-string
|
||||
*/
|
||||
private string $className;
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
*/
|
||||
protected function __construct(string $className)
|
||||
{
|
||||
$this->className = $className;
|
||||
}
|
||||
|
||||
public function isClassesThatExtendClass(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string
|
||||
*/
|
||||
public function className(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
return 'classesThatExtendClass';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function target(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function description(): string
|
||||
{
|
||||
return 'Classes that extend class ' . $this->target();
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class ClassesThatImplementInterface extends Target
|
||||
{
|
||||
/**
|
||||
* @var class-string
|
||||
*/
|
||||
private string $interfaceName;
|
||||
|
||||
/**
|
||||
* @param class-string $interfaceName
|
||||
*/
|
||||
protected function __construct(string $interfaceName)
|
||||
{
|
||||
$this->interfaceName = $interfaceName;
|
||||
}
|
||||
|
||||
public function isClassesThatImplementInterface(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string
|
||||
*/
|
||||
public function interfaceName(): string
|
||||
{
|
||||
return $this->interfaceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
return 'classesThatImplementInterface';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function target(): string
|
||||
{
|
||||
return $this->interfaceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function description(): string
|
||||
{
|
||||
return 'Classes that implement interface ' . $this->target();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Function_ extends Target
|
||||
{
|
||||
/**
|
||||
* @var non-empty-string
|
||||
*/
|
||||
private string $functionName;
|
||||
|
||||
/**
|
||||
* @param non-empty-string $functionName
|
||||
*/
|
||||
protected function __construct(string $functionName)
|
||||
{
|
||||
$this->functionName = $functionName;
|
||||
}
|
||||
|
||||
public function isFunction(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function functionName(): string
|
||||
{
|
||||
return $this->functionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
return 'functions';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function target(): string
|
||||
{
|
||||
return $this->functionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function description(): string
|
||||
{
|
||||
return 'Function ' . $this->target();
|
||||
}
|
||||
}
|
||||
@@ -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\Test\Target;
|
||||
|
||||
use function array_keys;
|
||||
use function array_merge;
|
||||
use function array_slice;
|
||||
use function array_unique;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function range;
|
||||
use SebastianBergmann\CodeCoverage\Filter;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\Class_;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser;
|
||||
use SebastianBergmann\CodeCoverage\StaticAnalysis\Trait_;
|
||||
|
||||
/**
|
||||
* @phpstan-import-type TargetMap from Mapper
|
||||
* @phpstan-import-type TargetMapPart from Mapper
|
||||
*
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class MapBuilder
|
||||
{
|
||||
/**
|
||||
* @return TargetMap
|
||||
*/
|
||||
public function build(Filter $filter, FileAnalyser $analyser): array
|
||||
{
|
||||
/**
|
||||
* @var array<non-empty-string, Class_> $classDetails
|
||||
*/
|
||||
$classDetails = [];
|
||||
|
||||
$namespaces = [];
|
||||
$classes = [];
|
||||
$classesThatExtendClass = [];
|
||||
$classesThatImplementInterface = [];
|
||||
$traits = [];
|
||||
$methods = [];
|
||||
$functions = [];
|
||||
$reverseLookup = [];
|
||||
|
||||
foreach ($filter->files() as $file) {
|
||||
foreach ($analyser->analyse($file)->traits() as $trait) {
|
||||
if ($trait->isNamespaced()) {
|
||||
$this->processNamespace($namespaces, $trait->namespace(), $file, $trait->startLine(), $trait->endLine());
|
||||
}
|
||||
|
||||
$this->process($traits, $trait->namespacedName(), $file, $trait->startLine(), $trait->endLine());
|
||||
$this->processMethods($trait, $file, $methods, $reverseLookup);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($filter->files() as $file) {
|
||||
foreach ($analyser->analyse($file)->traits() as $trait) {
|
||||
foreach ($trait->traits() as $traitName) {
|
||||
if (!isset($traits[$traitName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->mergeLines($trait->namespacedName(), $traits[$traitName], $traits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($filter->files() as $file) {
|
||||
$analysisResult = $analyser->analyse($file);
|
||||
|
||||
foreach ($analysisResult->interfaces() as $interface) {
|
||||
$classesThatImplementInterface[$interface->namespacedName()] = [];
|
||||
}
|
||||
|
||||
foreach ($analysisResult->classes() as $class) {
|
||||
if ($class->isNamespaced()) {
|
||||
$this->processNamespace($namespaces, $class->namespace(), $file, $class->startLine(), $class->endLine());
|
||||
}
|
||||
|
||||
$this->process($classes, $class->namespacedName(), $file, $class->startLine(), $class->endLine());
|
||||
|
||||
foreach ($class->traits() as $traitName) {
|
||||
if (!isset($traits[$traitName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->mergeLines($class->namespacedName(), $traits[$traitName], $classes);
|
||||
}
|
||||
|
||||
$this->processMethods($class, $file, $methods, $reverseLookup);
|
||||
|
||||
$classesThatExtendClass[$class->namespacedName()] = [];
|
||||
$classDetails[$class->namespacedName()] = $class;
|
||||
}
|
||||
|
||||
foreach ($analysisResult->functions() as $function) {
|
||||
if ($function->isNamespaced()) {
|
||||
$this->processNamespace($namespaces, $function->namespace(), $file, $function->startLine(), $function->endLine());
|
||||
}
|
||||
|
||||
$this->process($functions, $function->namespacedName(), $file, $function->startLine(), $function->endLine());
|
||||
|
||||
foreach (range($function->startLine(), $function->endLine()) as $line) {
|
||||
$reverseLookup[$file . ':' . $line] = $function->namespacedName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($namespaces as $namespace => $files) {
|
||||
foreach (array_keys($files) as $file) {
|
||||
$namespaces[$namespace][$file] = array_unique($namespaces[$namespace][$file]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($classDetails as $class) {
|
||||
foreach ($class->interfaces() as $interfaceName) {
|
||||
if (!isset($classesThatImplementInterface[$interfaceName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->process($classesThatImplementInterface, $interfaceName, $class->file(), $class->startLine(), $class->endLine());
|
||||
}
|
||||
|
||||
foreach ($this->parentClasses($classDetails, $class) as $parentClass) {
|
||||
$this->mergeLines($class->namespacedName(), $classes[$parentClass->namespacedName()], $classes);
|
||||
|
||||
if (isset($classesThatExtendClass[$parentClass->namespacedName()])) {
|
||||
$this->process($classesThatExtendClass, $parentClass->namespacedName(), $class->file(), $class->startLine(), $class->endLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_keys($classesThatImplementInterface) as $className) {
|
||||
if ($classesThatImplementInterface[$className] !== []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($classesThatImplementInterface[$className]);
|
||||
}
|
||||
|
||||
foreach (array_keys($classesThatExtendClass) as $className) {
|
||||
if ($classesThatExtendClass[$className] !== []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($classesThatExtendClass[$className]);
|
||||
}
|
||||
|
||||
return [
|
||||
'namespaces' => $namespaces,
|
||||
'traits' => $traits,
|
||||
'classes' => $classes,
|
||||
'classesThatExtendClass' => $classesThatExtendClass,
|
||||
'classesThatImplementInterface' => $classesThatImplementInterface,
|
||||
'methods' => $methods,
|
||||
'functions' => $functions,
|
||||
'reverseLookup' => $reverseLookup,
|
||||
];
|
||||
}
|
||||
|
||||
private function mergeLines(string $targetClass, array $sourceData, array &$data): void
|
||||
{
|
||||
/**
|
||||
* In large inheritance trees we might handle a lot of data.
|
||||
* This loop needs to prevent unnecessary work whenever possible.
|
||||
*/
|
||||
foreach ($sourceData as $file => $lines) {
|
||||
if (!isset($data[$targetClass][$file])) {
|
||||
$data[$targetClass][$file] = $lines;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($data[$targetClass][$file] === $lines) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[$targetClass][$file] = array_unique(
|
||||
array_merge(
|
||||
$data[$targetClass][$file],
|
||||
$lines,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function processMethods(Class_|Trait_ $classOrTrait, string $file, array &$methods, array &$reverseLookup): void
|
||||
{
|
||||
foreach ($classOrTrait->methods() as $method) {
|
||||
$methodName = $classOrTrait->namespacedName() . '::' . $method->name();
|
||||
|
||||
$this->process($methods, $methodName, $file, $method->startLine(), $method->endLine());
|
||||
|
||||
foreach (range($method->startLine(), $method->endLine()) as $line) {
|
||||
$reverseLookup[$file . ':' . $line] = $methodName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TargetMapPart $data
|
||||
* @param non-empty-string $namespace
|
||||
* @param non-empty-string $file
|
||||
* @param positive-int $startLine
|
||||
* @param positive-int $endLine
|
||||
*
|
||||
* @param-out TargetMapPart $data
|
||||
*/
|
||||
private function processNamespace(array &$data, string $namespace, string $file, int $startLine, int $endLine): void
|
||||
{
|
||||
$parts = explode('\\', $namespace);
|
||||
|
||||
foreach (range(1, count($parts)) as $i) {
|
||||
$this->process($data, implode('\\', array_slice($parts, 0, $i)), $file, $startLine, $endLine);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TargetMapPart $data
|
||||
* @param non-empty-string $unit
|
||||
* @param non-empty-string $file
|
||||
* @param positive-int $startLine
|
||||
* @param positive-int $endLine
|
||||
*
|
||||
* @param-out TargetMapPart $data
|
||||
*/
|
||||
private function process(array &$data, string $unit, string $file, int $startLine, int $endLine): void
|
||||
{
|
||||
if (!isset($data[$unit])) {
|
||||
$data[$unit] = [];
|
||||
}
|
||||
|
||||
if (!isset($data[$unit][$file])) {
|
||||
$data[$unit][$file] = [];
|
||||
}
|
||||
|
||||
$data[$unit][$file] = array_merge(
|
||||
$data[$unit][$file],
|
||||
range($startLine, $endLine),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<non-empty-string, Class_> $classDetails
|
||||
*
|
||||
* @return array<Class_>
|
||||
*/
|
||||
private function parentClasses(array $classDetails, Class_ $class): array
|
||||
{
|
||||
if (!$class->hasParent()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!isset($classDetails[$class->parentClass()])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
[$classDetails[$class->parentClass()]],
|
||||
$this->parentClasses($classDetails, $classDetails[$class->parentClass()]),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?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 array_keys;
|
||||
use function array_merge;
|
||||
use function array_unique;
|
||||
use function strcasecmp;
|
||||
|
||||
/**
|
||||
* @phpstan-type TargetMap array{namespaces: TargetMapPart, traits: TargetMapPart, classes: TargetMapPart, classesThatExtendClass: TargetMapPart, classesThatImplementInterface: TargetMapPart, methods: TargetMapPart, functions: TargetMapPart, reverseLookup: ReverseLookup}
|
||||
* @phpstan-type TargetMapPart array<non-empty-string, array<non-empty-string, list<positive-int>>>
|
||||
* @phpstan-type ReverseLookup array<non-empty-string, non-empty-string>
|
||||
*
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class Mapper
|
||||
{
|
||||
/**
|
||||
* @var TargetMap
|
||||
*/
|
||||
private array $map;
|
||||
|
||||
/**
|
||||
* @param TargetMap $map
|
||||
*/
|
||||
public function __construct(array $map)
|
||||
{
|
||||
$this->map = $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<non-empty-string, list<positive-int>>
|
||||
*/
|
||||
public function mapTargets(TargetCollection $targets): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($targets as $target) {
|
||||
foreach ($this->mapTarget($target) as $file => $lines) {
|
||||
if (!isset($result[$file])) {
|
||||
$result[$file] = $lines;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[$file] = array_unique(array_merge($result[$file], $lines));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidCodeCoverageTargetException
|
||||
*
|
||||
* @return array<non-empty-string, list<positive-int>>
|
||||
*/
|
||||
public function mapTarget(Target $target): array
|
||||
{
|
||||
if (isset($this->map[$target->key()][$target->target()])) {
|
||||
return $this->map[$target->key()][$target->target()];
|
||||
}
|
||||
|
||||
foreach (array_keys($this->map[$target->key()]) as $key) {
|
||||
if (strcasecmp($key, $target->target()) === 0) {
|
||||
return $this->map[$target->key()][$key];
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidCodeCoverageTargetException($target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param non-empty-string $file
|
||||
* @param positive-int $line
|
||||
*
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function lookup(string $file, int $line): string
|
||||
{
|
||||
$key = $file . ':' . $line;
|
||||
|
||||
if (isset($this->map['reverseLookup'][$key])) {
|
||||
return $this->map['reverseLookup'][$key];
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Method extends Target
|
||||
{
|
||||
/**
|
||||
* @var class-string
|
||||
*/
|
||||
private string $className;
|
||||
|
||||
/**
|
||||
* @var non-empty-string
|
||||
*/
|
||||
private string $methodName;
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
* @param non-empty-string $methodName
|
||||
*/
|
||||
protected function __construct(string $className, string $methodName)
|
||||
{
|
||||
$this->className = $className;
|
||||
$this->methodName = $methodName;
|
||||
}
|
||||
|
||||
public function isMethod(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string
|
||||
*/
|
||||
public function className(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function methodName(): string
|
||||
{
|
||||
return $this->methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
return 'methods';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function target(): string
|
||||
{
|
||||
return $this->className . '::' . $this->methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function description(): string
|
||||
{
|
||||
return 'Method ' . $this->target();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Namespace_ extends Target
|
||||
{
|
||||
/**
|
||||
* @var non-empty-string
|
||||
*/
|
||||
private string $namespace;
|
||||
|
||||
/**
|
||||
* @param non-empty-string $namespace
|
||||
*/
|
||||
protected function __construct(string $namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
public function isNamespace(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function namespace(): string
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
return 'namespaces';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function target(): string
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function description(): string
|
||||
{
|
||||
return 'Namespace ' . $this->target();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
abstract class Target
|
||||
{
|
||||
/**
|
||||
* @param non-empty-string $namespace
|
||||
*/
|
||||
public static function forNamespace(string $namespace): Namespace_
|
||||
{
|
||||
return new Namespace_($namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
*/
|
||||
public static function forClass(string $className): Class_
|
||||
{
|
||||
return new Class_($className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
* @param non-empty-string $methodName
|
||||
*/
|
||||
public static function forMethod(string $className, string $methodName): Method
|
||||
{
|
||||
return new Method($className, $methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $interfaceName
|
||||
*/
|
||||
public static function forClassesThatImplementInterface(string $interfaceName): ClassesThatImplementInterface
|
||||
{
|
||||
return new ClassesThatImplementInterface($interfaceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
*/
|
||||
public static function forClassesThatExtendClass(string $className): ClassesThatExtendClass
|
||||
{
|
||||
return new ClassesThatExtendClass($className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param non-empty-string $functionName
|
||||
*/
|
||||
public static function forFunction(string $functionName): Function_
|
||||
{
|
||||
return new Function_($functionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trait-string $traitName
|
||||
*/
|
||||
public static function forTrait(string $traitName): Trait_
|
||||
{
|
||||
return new Trait_($traitName);
|
||||
}
|
||||
|
||||
public function isNamespace(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isClass(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isMethod(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isClassesThatImplementInterface(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isClassesThatExtendClass(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isFunction(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isTrait(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
abstract public function key(): string;
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
abstract public function target(): string;
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
abstract public function description(): string;
|
||||
}
|
||||
@@ -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\Test\Target;
|
||||
|
||||
use function count;
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* @template-implements IteratorAggregate<int, Target>
|
||||
*
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class TargetCollection implements Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var list<Target>
|
||||
*/
|
||||
private array $targets;
|
||||
|
||||
/**
|
||||
* @param list<Target> $targets
|
||||
*/
|
||||
public static function fromArray(array $targets): self
|
||||
{
|
||||
return new self(...$targets);
|
||||
}
|
||||
|
||||
private function __construct(Target ...$targets)
|
||||
{
|
||||
$this->targets = $targets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<Target>
|
||||
*/
|
||||
public function asArray(): array
|
||||
{
|
||||
return $this->targets;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->targets);
|
||||
}
|
||||
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return $this->count() === 0;
|
||||
}
|
||||
|
||||
public function isNotEmpty(): bool
|
||||
{
|
||||
return $this->count() > 0;
|
||||
}
|
||||
|
||||
public function getIterator(): TargetCollectionIterator
|
||||
{
|
||||
return new TargetCollectionIterator($this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?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 count;
|
||||
use Iterator;
|
||||
|
||||
/**
|
||||
* @template-implements Iterator<int, Target>
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class TargetCollectionIterator implements Iterator
|
||||
{
|
||||
/**
|
||||
* @var list<Target>
|
||||
*/
|
||||
private readonly array $targets;
|
||||
private int $position = 0;
|
||||
|
||||
public function __construct(TargetCollection $metadata)
|
||||
{
|
||||
$this->targets = $metadata->asArray();
|
||||
}
|
||||
|
||||
public function rewind(): void
|
||||
{
|
||||
$this->position = 0;
|
||||
}
|
||||
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->position < count($this->targets);
|
||||
}
|
||||
|
||||
public function key(): int
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function current(): Target
|
||||
{
|
||||
return $this->targets[$this->position];
|
||||
}
|
||||
|
||||
public function next(): void
|
||||
{
|
||||
$this->position++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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 implode;
|
||||
|
||||
/**
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*
|
||||
* @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class TargetCollectionValidator
|
||||
{
|
||||
public function validate(Mapper $mapper, TargetCollection $targets): ValidationResult
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
foreach ($targets as $target) {
|
||||
try {
|
||||
$mapper->mapTarget($target);
|
||||
} catch (InvalidCodeCoverageTargetException $e) {
|
||||
$errors[] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors === []) {
|
||||
return ValidationResult::success();
|
||||
}
|
||||
|
||||
return ValidationResult::failure(implode("\n", $errors));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final class Trait_ extends Target
|
||||
{
|
||||
/**
|
||||
* @var trait-string
|
||||
*/
|
||||
private string $traitName;
|
||||
|
||||
/**
|
||||
* @param trait-string $traitName
|
||||
*/
|
||||
protected function __construct(string $traitName)
|
||||
{
|
||||
$this->traitName = $traitName;
|
||||
}
|
||||
|
||||
public function isTrait(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return trait-string
|
||||
*/
|
||||
public function traitName(): string
|
||||
{
|
||||
return $this->traitName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
return 'traits';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function target(): string
|
||||
{
|
||||
return $this->traitName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function description(): string
|
||||
{
|
||||
return 'Trait ' . $this->target();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class ValidationFailure extends ValidationResult
|
||||
{
|
||||
/**
|
||||
* @var non-empty-string
|
||||
*/
|
||||
private string $message;
|
||||
|
||||
/**
|
||||
* @param non-empty-string $message
|
||||
*
|
||||
* @noinspection PhpMissingParentConstructorInspection
|
||||
*/
|
||||
protected function __construct(string $message)
|
||||
{
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
public function isFailure(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function message(): string
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
abstract readonly class ValidationResult
|
||||
{
|
||||
public static function success(): ValidationSuccess
|
||||
{
|
||||
return new ValidationSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param non-empty-string $message
|
||||
*/
|
||||
public static function failure(string $message): ValidationFailure
|
||||
{
|
||||
return new ValidationFailure($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-assert-if-true ValidationSuccess $this
|
||||
*/
|
||||
public function isSuccess(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-assert-if-true ValidationFailure $this
|
||||
*/
|
||||
public function isFailure(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @immutable
|
||||
*
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for phpunit/php-code-coverage
|
||||
*/
|
||||
final readonly class ValidationSuccess extends ValidationResult
|
||||
{
|
||||
public function isSuccess(): true
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user