<?php

declare(strict_types=1);

namespace Sabberworm\CSS\Tests\Unit\PhpStan;

use PHPStan\Analyser\IgnoreErrorExtension;
use PHPStan\Testing\RuleTestCase;
use PHPStan\Rules\Classes\ImpossibleInstanceOfRule;
use PHPStan\Rules\Rule;

/**
 * This covers `instanceof.alwaysTrue` error handling in the `IgnoreBooleanAlways` PHPStan extension class.
 * `RuleTestCase` allows only one `Rule` class, so separate `TestCase`s are needed for errors generated by other rules.
 * Note that the base class covers testing the suppression of the warning, and is included via `extends`.
 * This class covers the non-suppression of warnings in other contexts, which requires detailing the expected warnings.
 *
 * @covers \Sabberworm\CSS\PhpStan\IgnoreBooleanAlways
 */
final class IgnoreBooleanAlwaysImpossibleInstanceofTest extends IgnoreBooleanAlwaysTestBase
{
    /**
     * @return ImpossibleInstanceOfRule
     */
    protected function getRule(): Rule
    {
        // If the class is renamed or removed in the next major release of PHPStan, we'll deal with it then.
        // @phpstan-ignore phpstanApi.classConstant
        return self::getContainer()->getByType(ImpossibleInstanceOfRule::class);
    }

    /**
     * @test
     */
    public function warningIsRetainedForInstanceofNotInAssert(): void
    {
        // Skip the test in PHP/PHPStan configurations that don't have the required components.
        // It is good enough to test for those that do.
        if (!\interface_exists(IgnoreErrorExtension::class)) {
            self::markTestSkipped('This is testing the testers, and only needs to run whenever possible.');
        }

        // Second argument is array of expected warnings.
        $this->analyse(
            [self::FIXTURES_DIR . 'alwaystrue-instanceof-notinassert.php'],
            [
                [
                    'Instanceof between Exception and Exception will always evaluate to true.',
                    6,
                ],
            ]
        );
    }
}
