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
+68
View File
@@ -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();
}
}
@@ -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()]),
);
}
}
+101
View File
@@ -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;
}
}
+83
View File
@@ -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();
}
}
+125
View File
@@ -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));
}
}
+68
View File
@@ -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;
}
}