Skip to content

Commit

Permalink
Commenting/CoversTag: flag deprecated @Covers tag formats
Browse files Browse the repository at this point in the history
PHPUnit 9.0 (soft) deprecated the use of `ClassName<*>` type `@covers` annotations. Support for these type of annotation has been removed completely in PHPUnit 10.0.0.

This commit adds a new _warning_ to the sniff, which will detect the use of these deprecated formats and flag them.

The choice for _warning_ vs _error_ is deliberate. The Yoast repos, for now, do not use PHPUnit 10.x yet, so for now, a warning is sufficient.
Once the repos would be upgraded to start using PHPUnit 10.x, this sniff should be updated and the `warning` changed to an `error`.

Includes tests.
Includes a new section in the XML docs about this new warning.

Refs:
* sebastianbergmann/phpunit 3630 (PHPUnit 9.0 deprecation).
* sebastianbergmann/phpunit 3631 (PHPUnit 10.0 removal).
  • Loading branch information
jrfnl committed Nov 4, 2023
1 parent 6e668b7 commit cd94f23
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 43 deletions.
35 changes: 35 additions & 0 deletions Yoast/Docs/Commenting/CoversTagStandard.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,41 @@ class Some_Test extends TestCase {
* @covers ::globalFunction</em>
*/
function test_something() {}
}
]]>
</code>
</code_comparison>
<standard>
<![CDATA[
The use of @covers ClassName::<[!](public|protected|private)> tags is deprecated since PHPUnit 9.0 and support has been removed in PHPUnit 10.0.
These type of annotations should not be used.
]]>
</standard>
<code_comparison>
<code title="Valid: A @covers tag referencing a function or a method.">
<![CDATA[
class Some_Test extends TestCase {
/**
* Testing...
*
* @covers <em>::globalFunction</em>
* @covers <em>\ClassName::methodName</em>
*/
function test_something() {}
}
]]>
</code>
<code title="Invalid: A @covers tag using one of the deprecated/removed function group formats.">
<![CDATA[
class Some_Test extends TestCase {
/**
* Testing...
*
* @covers <em>\ClassName::<public></em>
* @covers <em>\ClassName::<!protected></em>
* @covers <em>\ClassName<extended></em>
*/
function test_something() {}
}
]]>
</code>
Expand Down
33 changes: 32 additions & 1 deletion Yoast/Sniffs/Commenting/CoversTagSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
* - each @covers tag has an annotation;
* - there are no duplicate @covers tags;
* - there are no duplicate @coversNothing tags;
* - a method does not have both a @covers as well as a @coversNothing tag.
* - a method does not have both a @covers as well as a @coversNothing tag;
* - deprecated @covers tag formats are flagged. (since 3.0.0)
*
* @since 1.3.0
*/
Expand All @@ -26,6 +27,26 @@ final class CoversTagSniff implements Sniff {
*/
private const VALID_CONTENT_REGEX = '(?:\\\\?(?:(?<OOName>[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\\\\)*(?P>OOName)(?:<extended>|::<[!]?(?:public|protected|private)>|::(?<functionName>(?!public$|protected$|private$)(?P>OOName)))?|::(?P>functionName)|::<[!]?(?:public|protected|private)>|\\\\?(?:(?P>OOName)\\\\)+(?P>functionName))';

/**
* Regex to check for deprecated `@covers ClassName<extended>` tag format.
*
* @link https://github.com/sebastianbergmann/phpunit/issues/3630 PHPUnit 9.0 deprecation.
* @link https://github.com/sebastianbergmann/phpunit/issues/3631 PHPUnit 10.0 removal.
*
* @var string
*/
private const DEPRECATED_FORMAT_EXTENDED = '`^(?:\\\\)?(?:(?<OOName>[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\\\\)*(?P>OOName)<extended>$`';

/**
* Regex to check for deprecated `@covers *::<[!]public|protected|private>` tag format.
*
* @link https://github.com/sebastianbergmann/phpunit/issues/3630 PHPUnit 9.0 deprecation.
* @link https://github.com/sebastianbergmann/phpunit/issues/3631 PHPUnit 10.0 removal.
*
* @var string
*/
private const DEPRECATED_FORMAT_VISIBILITY = '`::<[!]?(?:public|protected|private)>$`';

/**
* Base error message.
*
Expand Down Expand Up @@ -95,6 +116,16 @@ public function process( File $phpcsFile, $stackPtr ) {
$annotation = $tokens[ $next ]['content'];
$coversTags[ "$tag-$next" ] = $annotation;

// Check for deprecated/removed @covers formats.
if ( \preg_match( self::DEPRECATED_FORMAT_EXTENDED, $annotation ) === 1
|| \preg_match( self::DEPRECATED_FORMAT_VISIBILITY, $annotation ) === 1
) {
$warning = 'Use of the "ClassName<*>" type values for @covers annotations has been deprecated in PHPUnit 9.0';
$warning .= ' and support has been removed in PHPUnit 10.0. Found: %s';
$data = [ $annotation ];
$phpcsFile->addWarning( $warning, $next, 'RemovedFormat', $data );
}

if ( \preg_match( '`^' . self::VALID_CONTENT_REGEX . '$`', $annotation ) === 1 ) {
continue;
}
Expand Down
36 changes: 18 additions & 18 deletions Yoast/Tests/Commenting/CoversTagUnitTest.inc
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
<?php

class ClassNameTest {

/**
* Docblock.
*
* Correct:
* @covers ::global_function
* @covers Name\Space\function_name
* @covers \Name\Space\function_name
* @covers Class_Name
* @covers Class_Name<extended>
* @covers Class_Name::<public>
* @covers Class_Name::<protected>
* @covers Class_Name::<private>
* @covers Class_Name::<!public>
* @covers Class_Name::<!protected>
* @covers Class_Name::<!private>
* @covers Name\Space\Class_Name
* @covers \Name\Space\Class_Name
* @covers Name\Space\Class_Name::<public>
* @covers Name\Space\Class_Name::<protected>
* @covers Name\Space\Class_Name::<private>
* @covers Name\Space\Class_Name::<!public>
* @covers Name\Space\Class_Name::<!protected>
* @covers Name\Space\Class_Name::<!private>
* @covers Class_Name::method_name
* @covers \Class_name::method_name
* @covers Name\Space\Class_Name::method_name
Expand All @@ -42,8 +26,24 @@ class ClassNameTest {
public function testCoversTag() {}

/**
* Docblock.
*
* @covers Class_Name<extended>
* @covers Class_Name::<public>
* @covers Class_Name::<protected>
* @covers Class_Name::<private>
* @covers Class_Name::<!public>
* @covers Class_Name::<!protected>
* @covers Class_Name::<!private>
* @covers \Name\Space\Class_Name<extended>
* @covers \Name\Space\Class_Name::<public>
* @covers Name\Space\Class_Name::<protected>
* @covers Name\Space\Class_Name::<private>
* @covers \Name\Space\Class_Name::<!public>
* @covers Name\Space\Class_Name::<!protected>
* @covers \Name\Space\Class_Name::<!private>
*/
public function testDeprecatedRemovedTagTypes() {}

/**
* @covers ::global_functionA && ::other_functionA
* @covers ::global_functionB & ::other_functionB
* @covers ::global_functionC|::other_functionC
Expand Down
36 changes: 18 additions & 18 deletions Yoast/Tests/Commenting/CoversTagUnitTest.inc.fixed
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
<?php

class ClassNameTest {

/**
* Docblock.
*
* Correct:
* @covers ::global_function
* @covers Name\Space\function_name
* @covers \Name\Space\function_name
* @covers Class_Name
* @covers Class_Name<extended>
* @covers Class_Name::<public>
* @covers Class_Name::<protected>
* @covers Class_Name::<private>
* @covers Class_Name::<!public>
* @covers Class_Name::<!protected>
* @covers Class_Name::<!private>
* @covers Name\Space\Class_Name
* @covers \Name\Space\Class_Name
* @covers Name\Space\Class_Name::<public>
* @covers Name\Space\Class_Name::<protected>
* @covers Name\Space\Class_Name::<private>
* @covers Name\Space\Class_Name::<!public>
* @covers Name\Space\Class_Name::<!protected>
* @covers Name\Space\Class_Name::<!private>
* @covers Class_Name::method_name
* @covers \Class_name::method_name
* @covers Name\Space\Class_Name::method_name
Expand All @@ -42,8 +26,24 @@ class ClassNameTest {
public function testCoversTag() {}

/**
* Docblock.
*
* @covers Class_Name<extended>
* @covers Class_Name::<public>
* @covers Class_Name::<protected>
* @covers Class_Name::<private>
* @covers Class_Name::<!public>
* @covers Class_Name::<!protected>
* @covers Class_Name::<!private>
* @covers \Name\Space\Class_Name<extended>
* @covers \Name\Space\Class_Name::<public>
* @covers Name\Space\Class_Name::<protected>
* @covers Name\Space\Class_Name::<private>
* @covers \Name\Space\Class_Name::<!public>
* @covers Name\Space\Class_Name::<!protected>
* @covers \Name\Space\Class_Name::<!private>
*/
public function testDeprecatedRemovedTagTypes() {}

/**
* @covers ::global_functionA
* @covers ::other_functionA
* @covers ::global_functionB
Expand Down
33 changes: 27 additions & 6 deletions Yoast/Tests/Commenting/CoversTagUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ final class CoversTagUnitTest extends AbstractSniffUnitTest {
*/
public function getErrorList(): array {
return [
36 => 1,
37 => 1,
38 => 1,
39 => 1,
40 => 1,
20 => 1,
21 => 1,
22 => 1,
23 => 1,
24 => 1,
47 => 1,
48 => 1,
49 => 1,
Expand Down Expand Up @@ -58,6 +58,27 @@ public function getErrorList(): array {
* @return array<int, int> Key is the line number, value is the number of expected warnings.
*/
public function getWarningList(): array {
return [];
return [
29 => 1,
30 => 1,
31 => 1,
32 => 1,
33 => 1,
34 => 1,
35 => 1,
36 => 1,
37 => 1,
38 => 1,
39 => 1,
40 => 1,
41 => 1,
42 => 1,
190 => 1,
191 => 1,
192 => 1,
193 => 1,
194 => 1,
195 => 1,
];
}
}

0 comments on commit cd94f23

Please sign in to comment.