Skip to content

Commit

Permalink
Implement CodeCoverage::validate(TargetCollection)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Dec 7, 2024
1 parent 873416b commit 02adea8
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/CodeCoverage.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
use SebastianBergmann\CodeCoverage\StaticAnalysis\CachingFileAnalyser;
use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser;
use SebastianBergmann\CodeCoverage\StaticAnalysis\ParsingFileAnalyser;
use SebastianBergmann\CodeCoverage\Test\Target\MapBuilder;
use SebastianBergmann\CodeCoverage\Test\Target\Mapper;
use SebastianBergmann\CodeCoverage\Test\Target\TargetCollection;
use SebastianBergmann\CodeCoverage\Test\Target\ValidationResult;
use SebastianBergmann\CodeCoverage\Test\TestSize\TestSize;
use SebastianBergmann\CodeCoverage\Test\TestStatus\TestStatus;
use SebastianBergmann\CodeUnitReverseLookup\Wizard;
Expand All @@ -47,6 +51,7 @@ final class CodeCoverage
private readonly Driver $driver;
private readonly Filter $filter;
private readonly Wizard $wizard;
private ?Mapper $targetMapper = null;
private bool $checkForUnintentionallyCoveredCode = false;
private bool $ignoreDeprecatedCode = false;
private ?string $currentId = null;
Expand Down Expand Up @@ -348,6 +353,11 @@ public function detectsDeadCode(): bool
return $this->driver->detectsDeadCode();
}

public function validate(TargetCollection $targets): ValidationResult
{
return $targets->validate($this->targetMapper());
}

/**
* @throws ReflectionException
* @throws UnintentionallyCoveredCodeException
Expand Down Expand Up @@ -566,6 +576,19 @@ private function processUnintentionallyCoveredUnits(array $unintentionallyCovere
return $processed;
}

private function targetMapper(): Mapper
{
if ($this->targetMapper !== null) {
return $this->targetMapper;
}

$this->targetMapper = new Mapper(
(new MapBuilder)->build($this->filter, $this->analyser()),
);

return $this->targetMapper;
}

private function analyser(): FileAnalyser
{
if ($this->analyser !== null) {
Expand Down
20 changes: 20 additions & 0 deletions src/Target/TargetCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace SebastianBergmann\CodeCoverage\Test\Target;

use function count;
use function implode;
use Countable;
use IteratorAggregate;

Expand Down Expand Up @@ -67,4 +68,23 @@ public function getIterator(): TargetCollectionIterator
{
return new TargetCollectionIterator($this);
}

public function validate(Mapper $mapper): ValidationResult
{
$errors = [];

foreach ($this->targets as $target) {
try {
$mapper->mapTarget($target);
} catch (InvalidCodeCoverageTargetException $e) {
$errors[] = $e->getMessage();
}
}

if ($errors === []) {
return ValidationResult::success();
}

return ValidationResult::failure(implode("\n", $errors));
}
}
46 changes: 46 additions & 0 deletions src/Target/ValidationFailure.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?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\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;
}
}
51 changes: 51 additions & 0 deletions src/Target/ValidationResult.php
Original file line number Diff line number Diff line change
@@ -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\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);
}

protected function __construct()
{
}

/**
* @phpstan-assert-if-true ValidationSuccess $this
*/
public function isSuccess(): bool
{
return false;
}

/**
* @phpstan-assert-if-true ValidationFailure $this
*/
public function isFailure(): bool
{
return false;
}
}
23 changes: 23 additions & 0 deletions src/Target/ValidationSuccess.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?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\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;
}
}
36 changes: 36 additions & 0 deletions tests/tests/Target/ValidationResultTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?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\Test\Target;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Small;
use PHPUnit\Framework\TestCase;

#[CoversClass(ValidationResult::class)]
#[CoversClass(ValidationSuccess::class)]
#[CoversClass(ValidationFailure::class)]
#[Small]
final class ValidationResultTest extends TestCase
{
public function testCanBeSuccess(): void
{
$this->assertTrue(ValidationResult::success()->isSuccess());
$this->assertFalse(ValidationResult::success()->isFailure());
}

public function testCanBeFailure(): void
{
$message = 'message';

$this->assertTrue(ValidationResult::failure($message)->isFailure());
$this->assertFalse(ValidationResult::failure($message)->isSuccess());
$this->assertSame($message, ValidationResult::failure($message)->message());
}
}

0 comments on commit 02adea8

Please sign in to comment.