diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eaffcc8..71cc227 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3'] + php-versions: ['8.1', '8.2', '8.3', '8.4'] composer-flags: ['', '--prefer-lowest'] steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 6f79ab1..f55bea3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ /vendor /composer.lock /phpunit.xml -/.phpunit.result.cache +/.phpunit.cache diff --git a/README.md b/README.md index 2bb443b..32281a6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.4-8892BA)](https://php.net/) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.1-8892BA)](https://php.net/) ![Run tests](https://github.com/123inkt/php-codesniffer-baseline/workflows/Run%20checks/badge.svg) # PHP_Codesniffer baseline diff --git a/composer.json b/composer.json index 046b101..b258807 100644 --- a/composer.json +++ b/composer.json @@ -13,22 +13,26 @@ "lock": false }, "require": { - "php": ">=7.4", - "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=8.1", + "composer-plugin-api": "^2.0", "squizlabs/php_codesniffer": "^3.6" }, "require-dev": { "composer/composer": "^2.0", "mikey179/vfsstream": "1.6.12", "phpmd/phpmd": "^2.15", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpstan/extension-installer": "^1.1", - "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/extension-installer": "^1.4", + "phpunit/phpunit": "^10.5 || ^11.5", "roave/security-advisories": "dev-latest" }, "scripts": { + "baseline": ["@baseline:phpcs", "@baseline:phpmd", "@baseline:phpstan", "@baseline:phpcqc"], + "baseline:phpcs": "phpcs --report=\\\\DR\\\\CodeSnifferBaseline\\\\Reports\\\\Baseline --report-file=phpcs.baseline.xml --basepath=.", + "baseline:phpmd": "@check:phpmd --generate-baseline", + "baseline:phpstan": "phpstan --generate-baseline", "run:plugin": "DR\\CodeSnifferBaseline\\Plugin\\Plugin::run", "check": ["@check:phpstan", "@check:phpmd", "@check:phpcs"], "check:phpstan": "phpstan analyse", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7854d22..e91356e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,24 +1,28 @@ tests/Unit - + - src + src - + diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php index 8275463..cb03bbe 100644 --- a/src/Baseline/BaselineSetFactory.php +++ b/src/Baseline/BaselineSetFactory.php @@ -10,7 +10,6 @@ class BaselineSetFactory /** * Read the baseline violations from the given filename path. * @throws RuntimeException - * @SuppressWarnings(PHPMD.ErrorControlOperator) - handled by the RuntimeException */ public static function fromFile(string $fileName): ?BaselineSet { diff --git a/src/Plugin/Plugin.php b/src/Plugin/Plugin.php index 7e4e2f3..8803d6b 100644 --- a/src/Plugin/Plugin.php +++ b/src/Plugin/Plugin.php @@ -15,7 +15,7 @@ class Plugin implements PluginInterface, EventSubscriberInterface { private ?IOInterface $stream = null; - private string $codeSnifferFilePath; + private string $codeSnifferFilePath; public function __construct(?string $codeSnifferFilePath = null) { @@ -48,9 +48,6 @@ public function uninstall(Composer $composer, IOInterface $stream): void // not necessary } - /** - * @SuppressWarnings(PHPMD.ErrorControlOperator) - handled by the === false check - */ public function onPostInstall(): void { if ($this->stream === null) { diff --git a/tests/Unit/Baseline/BaselineSetFactoryTest.php b/tests/Unit/Baseline/BaselineSetFactoryTest.php index d0ac100..e847cff 100644 --- a/tests/Unit/Baseline/BaselineSetFactoryTest.php +++ b/tests/Unit/Baseline/BaselineSetFactoryTest.php @@ -4,17 +4,13 @@ namespace DR\CodeSnifferBaseline\Tests\Unit\Baseline; use DR\CodeSnifferBaseline\Baseline\BaselineSetFactory; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use RuntimeException; -/** - * @coversDefaultClass \DR\CodeSnifferBaseline\Baseline\BaselineSetFactory - */ +#[CoversClass(BaselineSetFactory::class)] class BaselineSetFactoryTest extends TestCase { - /** - * @covers ::fromFile - */ public function testFromFileShouldSucceed(): void { $filename = __DIR__ . '/TestFiles/baseline.xml'; @@ -23,9 +19,6 @@ public function testFromFileShouldSucceed(): void static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test/src/foo/bar', 'foobar')); } - /** - * @covers ::fromFile - */ public function testFromFileShouldSucceedWithBackAndForwardSlashes(): void { $filename = __DIR__ . '/TestFiles/baseline.xml'; @@ -35,17 +28,11 @@ public function testFromFileShouldSucceedWithBackAndForwardSlashes(): void static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test\\src\\foo/bar', 'foobar')); } - /** - * @covers ::fromFile - */ public function testFromFileShouldReturnNullIfAbsent(): void { static::assertNull(BaselineSetFactory::fromFile('foobar.xml')); } - /** - * @covers ::fromFile - */ public function testFromFileShouldThrowExceptionForOnInvalidXML(): void { $this->expectException(RuntimeException::class); @@ -53,9 +40,6 @@ public function testFromFileShouldThrowExceptionForOnInvalidXML(): void BaselineSetFactory::fromFile(__DIR__ . '/TestFiles/invalid-baseline.xml'); } - /** - * @covers ::fromFile - */ public function testFromFileViolationMissingSniffShouldThrowException(): void { $this->expectException(RuntimeException::class); @@ -63,9 +47,6 @@ public function testFromFileViolationMissingSniffShouldThrowException(): void BaselineSetFactory::fromFile(__DIR__ . '/TestFiles/missing-sniff-baseline.xml'); } - /** - * @covers ::fromFile - */ public function testFromFileViolationMissingSignatureShouldThrowException(): void { $this->expectException(RuntimeException::class); @@ -73,9 +54,6 @@ public function testFromFileViolationMissingSignatureShouldThrowException(): voi BaselineSetFactory::fromFile(__DIR__ . '/TestFiles/missing-signature-baseline.xml'); } - /** - * @covers ::fromFile - */ public function testFromFileViolationMissingFileShouldThrowException(): void { $this->expectException(RuntimeException::class); diff --git a/tests/Unit/Baseline/BaselineSetTest.php b/tests/Unit/Baseline/BaselineSetTest.php index 2b7ca40..fc773df 100644 --- a/tests/Unit/Baseline/BaselineSetTest.php +++ b/tests/Unit/Baseline/BaselineSetTest.php @@ -3,21 +3,17 @@ namespace DR\CodeSnifferBaseline\Tests\Unit\Baseline; +use PHPUnit\Framework\Attributes\CoversClass; use DR\CodeSnifferBaseline\Baseline\BaselineSet; use DR\CodeSnifferBaseline\Baseline\ViolationBaseline; use PHPUnit\Framework\TestCase; /** * Test the logic of the baseline set - * @coversDefaultClass \DR\CodeSnifferBaseline\Baseline\BaselineSet */ +#[CoversClass(BaselineSet::class)] class BaselineSetTest extends TestCase { - /** - * @covers ::addEntry - * @covers ::contains - * - */ public function testSetContainsEntry(): void { $set = new BaselineSet(); @@ -26,10 +22,6 @@ public function testSetContainsEntry(): void static::assertTrue($set->contains('sniff', 'foobar', 'signature')); } - /** - * @covers ::addEntry - * @covers ::contains - */ public function testShouldFindEntryForIdenticalRules(): void { $set = new BaselineSet(); @@ -42,10 +34,6 @@ public function testShouldFindEntryForIdenticalRules(): void static::assertFalse($set->contains('sniff', 'foo', 'signB')); } - /** - * @covers ::addEntry - * @covers ::contains - */ public function testShouldNotFindEntryForNonExistingRule(): void { $set = new BaselineSet(); diff --git a/tests/Unit/Baseline/ViolationBaselineTest.php b/tests/Unit/Baseline/ViolationBaselineTest.php index edf95b5..ef4bee0 100644 --- a/tests/Unit/Baseline/ViolationBaselineTest.php +++ b/tests/Unit/Baseline/ViolationBaselineTest.php @@ -3,19 +3,13 @@ namespace DR\CodeSnifferBaseline\Tests\Unit\Baseline; +use PHPUnit\Framework\Attributes\CoversClass; use DR\CodeSnifferBaseline\Baseline\ViolationBaseline; use PHPUnit\Framework\TestCase; -/** - * @coversDefaultClass \DR\CodeSnifferBaseline\Baseline\ViolationBaseline - */ +#[CoversClass(ViolationBaseline::class)] class ViolationBaselineTest extends TestCase { - /** - * @covers ::__construct - * @covers ::getSniffName - * @covers ::getSignature - */ public function testAccessors(): void { $violation = new ViolationBaseline('sniff', 'foobar', 'signature'); @@ -25,8 +19,6 @@ public function testAccessors(): void /** * Test the give file matches the baseline correctly - * @covers ::__construct - * @covers ::matches */ public function testMatches(): void { diff --git a/tests/Unit/Plugin/BaselineHandlerTest.php b/tests/Unit/Plugin/BaselineHandlerTest.php index d3a4bf3..db49240 100644 --- a/tests/Unit/Plugin/BaselineHandlerTest.php +++ b/tests/Unit/Plugin/BaselineHandlerTest.php @@ -3,28 +3,20 @@ namespace DR\CodeSnifferBaseline\Tests\Unit\Plugin; +use PHPUnit\Framework\Attributes\CoversClass; use DR\CodeSnifferBaseline\Baseline\BaselineSet; use DR\CodeSnifferBaseline\Plugin\BaselineHandler; use PHPUnit\Framework\TestCase; -/** - * @coversDefaultClass \DR\CodeSnifferBaseline\Plugin\BaselineHandler - * @covers ::__construct - */ +#[CoversClass(BaselineHandler::class)] class BaselineHandlerTest extends TestCase { - /** - * @covers ::isSuppressed - */ public function testIsSuppressedNoBaselineShouldBeFalse(): void { $handler = new BaselineHandler(null); static::assertFalse($handler->isSuppressed([], 1, 'foobar', '/path/')); } - /** - * @covers ::isSuppressed - */ public function testIsSuppressedWithBaseline(): void { $baseline = $this->createMock(BaselineSet::class); diff --git a/tests/Unit/Plugin/PluginTest.php b/tests/Unit/Plugin/PluginTest.php index ef291e0..bc4ff5a 100644 --- a/tests/Unit/Plugin/PluginTest.php +++ b/tests/Unit/Plugin/PluginTest.php @@ -11,20 +11,16 @@ use DR\CodeSnifferBaseline\Plugin\Plugin; use Exception; use org\bovigo\vfs\vfsStream; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use RuntimeException; -/** - * @coversDefaultClass \DR\CodeSnifferBaseline\Plugin\Plugin - * @covers ::__construct - */ +#[CoversClass(Plugin::class)] class PluginTest extends TestCase { - /** @var Composer|MockObject */ - private Composer $composer; - /** @var IOInterface|MockObject */ - private IOInterface $stream; + private Composer&MockObject $composer; + private IOInterface&MockObject $stream; protected function setUp(): void { @@ -32,9 +28,6 @@ protected function setUp(): void $this->stream = $this->createMock(IOInterface::class); } - /** - * @covers ::getSubscribedEvents - */ public function testGetSubscribedEvents(): void { $expected = [ @@ -45,10 +38,6 @@ public function testGetSubscribedEvents(): void static::assertSame($expected, Plugin::getSubscribedEvents()); } - /** - * @covers ::activate - * @covers ::onPostInstall - */ public function testOnPostInstallWithoutExistingFile(): void { $this->stream->expects(static::once())->method('error')->with(static::stringContains('failed to find')); @@ -58,15 +47,20 @@ public function testOnPostInstallWithoutExistingFile(): void $plugin->onPostInstall(); } - /** - * @covers ::activate - * @covers ::onPostInstall - */ public function testOnPostInstallAlreadyContainsInjection(): void { - $this->stream->expects(static::exactly(2)) + $matcher = static::exactly(2); + $this->stream->expects($matcher) ->method('info') - ->withConsecutive([static::stringContains('read')], [static::stringContains('is already modified')]); + ->willReturnCallback(function (...$parameters) use ($matcher) { + static::assertIsString($parameters[0]); + if ($matcher->numberOfInvocations() === 1) { + static::assertStringContainsString('read', $parameters[0]); + } + if ($matcher->numberOfInvocations() === 2) { + static::assertStringContainsString('is already modified', $parameters[0]); + } + }); $file = vfsStream::setup()->url() . '/File.php'; file_put_contents($file, 'foobar \\' . BaselineHandler::class . 'foobar'); @@ -77,15 +71,17 @@ public function testOnPostInstallAlreadyContainsInjection(): void $plugin->onPostInstall(); } - /** - * @covers ::activate - * @covers ::onPostInstall - */ public function testOnPostInstallShouldErrorWhenMessageCountCantBeFound(): void { - $this->stream->expects(static::once()) + $matcher = static::once(); + $this->stream->expects($matcher) ->method('error') - ->withConsecutive([static::stringContains('unable to find `$messageCount++;`')]); + ->willReturnCallback(function (...$parameters) use ($matcher) { + static::assertIsString($parameters[0]); + if ($matcher->numberOfInvocations() === 1) { + static::assertStringContainsString('unable to find `$messageCount++;`', $parameters[0]); + } + }); $file = vfsStream::setup()->url() . '/File.php'; file_put_contents($file, 'foobar '); @@ -95,15 +91,20 @@ public function testOnPostInstallShouldErrorWhenMessageCountCantBeFound(): void $plugin->onPostInstall(); } - /** - * @covers ::activate - * @covers ::onPostInstall - */ public function testOnPostInstallShouldInjectCode(): void { - $this->stream->expects(static::exactly(2)) + $matcher = static::exactly(2); + $this->stream->expects($matcher) ->method('info') - ->withConsecutive([static::stringContains('read')], [static::stringContains('saved to:')]); + ->willReturnCallback(function (...$parameters) use ($matcher) { + static::assertIsString($parameters[0]); + if ($matcher->numberOfInvocations() === 1) { + static::assertStringContainsString('read', $parameters[0]); + } + if ($matcher->numberOfInvocations() === 2) { + static::assertStringContainsString('saved to:', $parameters[0]); + } + }); $file = vfsStream::setup()->url() . '/File.php'; file_put_contents($file, 'foobar $messageCount++; foobar'); @@ -116,7 +117,6 @@ public function testOnPostInstallShouldInjectCode(): void } /** - * @covers ::run * @throws Exception */ public function testRun(): void diff --git a/tests/Unit/Reports/BaselineTest.php b/tests/Unit/Reports/BaselineTest.php index d3a70d4..05b30e9 100644 --- a/tests/Unit/Reports/BaselineTest.php +++ b/tests/Unit/Reports/BaselineTest.php @@ -7,34 +7,26 @@ use DR\CodeSnifferBaseline\Util\CodeSignature; use PHP_CodeSniffer\Config; use PHP_CodeSniffer\Files\File; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -/** - * @coversDefaultClass \DR\CodeSnifferBaseline\Reports\Baseline - */ +#[CoversClass(Baseline::class)] class BaselineTest extends TestCase { - /** @var File|MockObject */ - private File $file; + private File&MockObject $file; protected function setUp(): void { $this->file = $this->createMock(File::class); } - /** - * @covers ::generateFileReport - */ public function testGenerateFileReportEmptyShouldReturnFalse(): void { $report = new Baseline(); static::assertFalse($report->generateFileReport(['errors' => 0, 'warnings' => 0, 'filename' => 'foo', 'messages' => []], $this->file)); } - /** - * @covers ::generateFileReport - */ public function testGenerateFileReportShouldPrintReport(): void { $reportData = [ @@ -60,9 +52,6 @@ public function testGenerateFileReportShouldPrintReport(): void static::assertSame('' . PHP_EOL, $result); } - /** - * @covers ::generate - */ public function testGenerate(): void { $expected = "" . PHP_EOL; diff --git a/tests/Unit/Util/CodeSignatureTest.php b/tests/Unit/Util/CodeSignatureTest.php index 737f626..91269dd 100644 --- a/tests/Unit/Util/CodeSignatureTest.php +++ b/tests/Unit/Util/CodeSignatureTest.php @@ -3,18 +3,15 @@ namespace DR\CodeSnifferBaseline\Tests\Unit\Util; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use DR\CodeSnifferBaseline\Util\CodeSignature; use PHPUnit\Framework\TestCase; -/** - * @coversDefaultClass \DR\CodeSnifferBaseline\Util\CodeSignature - */ +#[CoversClass(CodeSignature::class)] class CodeSignatureTest extends TestCase { - /** - * @covers ::createSignature - * @dataProvider dataProvider - */ + #[DataProvider('dataProvider')] public function testCreateSignature(int $lineNr, string $expected): void { $tokens = [ @@ -51,7 +48,7 @@ public function testCreateSignature(int $lineNr, string $expected): void /** * @return array> */ - public function dataProvider(): array + public static function dataProvider(): array { return [ 'first line of file' => [ diff --git a/tests/Unit/Util/DirectoryUtilTest.php b/tests/Unit/Util/DirectoryUtilTest.php index 965de7a..3f52fbb 100644 --- a/tests/Unit/Util/DirectoryUtilTest.php +++ b/tests/Unit/Util/DirectoryUtilTest.php @@ -3,17 +3,13 @@ namespace DR\CodeSnifferBaseline\Tests\Unit\Util; +use PHPUnit\Framework\Attributes\CoversClass; use DR\CodeSnifferBaseline\Util\DirectoryUtil; use PHPUnit\Framework\TestCase; -/** - * @coversDefaultClass \DR\CodeSnifferBaseline\Util\DirectoryUtil - */ +#[CoversClass(DirectoryUtil::class)] class DirectoryUtilTest extends TestCase { - /** - * @covers ::getVendorDir - */ public function testGetVendorDir(): void { $directory = DirectoryUtil::getVendorDir(); @@ -21,9 +17,6 @@ public function testGetVendorDir(): void static::assertSame(dirname(__DIR__, 3) . '/vendor/', $directory); } - /** - * @covers ::getProjectRoot - */ public function testGetProjectRoot(): void { $directory = DirectoryUtil::getProjectRoot();