Fixing doc type annotation sniffs to correctly ignore attributes
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/test Pipeline was successful

This commit is contained in:
Ferdinand Kuhl 2023-02-10 15:37:30 +01:00
parent ef0ac65a4f
commit 7063c47d64
12 changed files with 92 additions and 41 deletions

View file

@ -1,6 +1,6 @@
pipeline: pipeline:
code-style: code-style:
image: thecodingmachine/php:7.4-v4-cli image: thecodingmachine/php:8.1-v4-cli
commands: commands:
- "sudo -s chown -R docker:docker ." - "sudo -s chown -R docker:docker ."
- "composer config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true" - "composer config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true"

View file

@ -1,6 +1,6 @@
pipeline: pipeline:
functional-tests: functional-tests:
image: thecodingmachine/php:7.4-v4-cli image: thecodingmachine/php:8.1-v4-cli
commands: commands:
- "sudo -s chown -R docker:docker ." - "sudo -s chown -R docker:docker ."
- "composer install" - "composer install"

View file

@ -23,7 +23,8 @@
"squizlabs/php_codesniffer": "^3.6.0" "squizlabs/php_codesniffer": "^3.6.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^8.0" "phpunit/phpunit": "^8.0",
"php": ">=8.1"
}, },
"scripts": { "scripts": {
"phpunit": "php vendor/bin/phpunit", "phpunit": "php vendor/bin/phpunit",

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace DigiComp\PhpCodesniffer\DigiComp\Sniffs\Annotations; namespace DigiComp\PhpCodesniffer\DigiComp\Sniffs\Annotations;
use DigiComp\PhpCodesniffer\DigiComp\Sniffs\MemberVarUtility;
use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens; use PHP_CodeSniffer\Util\Tokens;
@ -21,21 +22,7 @@ class ReturnIsNotVoidSniff implements Sniff
$ignore = Tokens::$methodPrefixes; $ignore = Tokens::$methodPrefixes;
$ignore[\T_WHITESPACE] = \T_WHITESPACE; $ignore[\T_WHITESPACE] = \T_WHITESPACE;
for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { $commentEnd = MemberVarUtility::findCommentEndWithoutAttributes($tokens, $ignore, $stackPtr);
if (isset($ignore[$tokens[$commentEnd]['code']]) === true) {
continue;
}
if (
$tokens[$commentEnd]['code'] === \T_ATTRIBUTE_END
&& isset($tokens[$commentEnd]['attribute_opener']) === true
) {
$commentEnd = $tokens[$commentEnd]['attribute_opener'];
continue;
}
break;
}
if ($tokens[$commentEnd]['code'] === \T_COMMENT) { if ($tokens[$commentEnd]['code'] === \T_COMMENT) {
// Inline comments might just be closing comments for // Inline comments might just be closing comments for

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace DigiComp\PhpCodesniffer\DigiComp\Sniffs\Annotations; namespace DigiComp\PhpCodesniffer\DigiComp\Sniffs\Annotations;
use DigiComp\PhpCodesniffer\DigiComp\Sniffs\MemberVarUtility;
use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; use PHP_CodeSniffer\Sniffs\AbstractVariableSniff;
@ -39,18 +40,18 @@ class VarIsLastTagOnPropertySniff extends AbstractVariableSniff
} }
$tokens = $phpcsFile->getTokens(); $tokens = $phpcsFile->getTokens();
$ignore = [ $ignore = [
\T_PUBLIC, \T_PUBLIC => \T_PUBLIC,
\T_PRIVATE, \T_PRIVATE => \T_PRIVATE,
\T_PROTECTED, \T_PROTECTED => \T_PROTECTED,
\T_VAR, \T_VAR => \T_VAR,
\T_STATIC, \T_STATIC => \T_STATIC,
\T_WHITESPACE, \T_WHITESPACE => \T_WHITESPACE,
\T_STRING, \T_STRING => \T_STRING,
\T_NS_SEPARATOR, \T_NS_SEPARATOR => \T_NS_SEPARATOR,
\T_NULLABLE, \T_NULLABLE => \T_NULLABLE,
]; ];
$commentEnd = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); $commentEnd = MemberVarUtility::findCommentEndWithoutAttributes($tokens, $ignore, $stackPtr);
if ( if (
$commentEnd === false $commentEnd === false
|| ($tokens[$commentEnd]['code'] !== \T_DOC_COMMENT_CLOSE_TAG || ($tokens[$commentEnd]['code'] !== \T_DOC_COMMENT_CLOSE_TAG

View file

@ -2,6 +2,7 @@
namespace DigiComp\PhpCodesniffer\DigiComp\Sniffs\Commenting; namespace DigiComp\PhpCodesniffer\DigiComp\Sniffs\Commenting;
use DigiComp\PhpCodesniffer\DigiComp\Sniffs\MemberVarUtility;
use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Files\File;
class VariableCommentSniff extends \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\VariableCommentSniff class VariableCommentSniff extends \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\VariableCommentSniff
@ -10,18 +11,18 @@ class VariableCommentSniff extends \PHP_CodeSniffer\Standards\Squiz\Sniffs\Comme
{ {
$tokens = $phpcsFile->getTokens(); $tokens = $phpcsFile->getTokens();
$ignore = [ $ignore = [
\T_PUBLIC, \T_PUBLIC => \T_PUBLIC,
\T_PRIVATE, \T_PRIVATE => \T_PRIVATE,
\T_PROTECTED, \T_PROTECTED => \T_PROTECTED,
\T_VAR, \T_VAR => \T_VAR,
\T_STATIC, \T_STATIC => \T_STATIC,
\T_WHITESPACE, \T_WHITESPACE => \T_WHITESPACE,
\T_STRING, \T_STRING => \T_STRING,
\T_NS_SEPARATOR, \T_NS_SEPARATOR => \T_NS_SEPARATOR,
\T_NULLABLE, \T_NULLABLE => \T_NULLABLE,
]; ];
$commentEnd = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); $commentEnd = MemberVarUtility::findCommentEndWithoutAttributes($tokens, $ignore, $stackPtr);
// this error is copied from above, as it comes with a needed early return // this error is copied from above, as it comes with a needed early return
if ( if (
$commentEnd === false $commentEnd === false

View file

@ -0,0 +1,35 @@
<?php
namespace DigiComp\PhpCodesniffer\DigiComp\Sniffs;
class MemberVarUtility
{
/**
* Helps to find the end token of a comment, ignoring attributes, which might be in between
*
* @param array $tokens
* @param array $ignore
* @param int $stackPtr
*
* @return int|mixed
*/
public static function findCommentEndWithoutAttributes(array $tokens, array $ignore, int $stackPtr)
{
for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) {
if (isset($ignore[$tokens[$commentEnd]['code']]) === true) {
continue;
}
if (
$tokens[$commentEnd]['code'] === \T_ATTRIBUTE_END
&& isset($tokens[$commentEnd]['attribute_opener']) === true
) {
$commentEnd = $tokens[$commentEnd]['attribute_opener'];
continue;
}
break;
}
return $commentEnd;
}
}

View file

@ -17,7 +17,7 @@
<exclude name="DigiComp.Commenting.VariableComment.MissingVar" /> <exclude name="DigiComp.Commenting.VariableComment.MissingVar" />
</rule> </rule>
<!-- TODO: what about new PHP 7.4 code base, where property annotations may get useless? --> <!-- TODO: what about new PHP 7.4 code base, where property annotations may get useless? -->
<rule ref="DigiComp.Commenting.VariableComment.Missing"> <rule ref="DigiComp.Commenting.VariableComment.MissingVar">
<type>warning</type> <type>warning</type>
<severity>4</severity> <severity>4</severity>
</rule> </rule>

View file

@ -9,7 +9,7 @@ class VarIsLastTagOnPropertySniffTest extends TestCase
public function testErrors(): void public function testErrors(): void
{ {
$report = self::checkFile(__DIR__ . '/data/PropertyOrder.php'); $report = self::checkFile(__DIR__ . '/data/PropertyOrder.php');
self::assertSame(2, $report->getErrorCount()); self::assertSame(3, $report->getErrorCount());
} }
public function testIgnoreVarTag(): void public function testIgnoreVarTag(): void

View file

@ -2,6 +2,11 @@
namespace Inwebs\PhpCodesniffer\Sniffs\Annotations\data; namespace Inwebs\PhpCodesniffer\Sniffs\Annotations\data;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
final class OwnAttribute
{
}
class PropertyOrder class PropertyOrder
{ {
/** /**
@ -28,7 +33,7 @@ class PropertyOrder
* Text * Text
* *
* @Flow\Inject * @Flow\Inject
* @var string * @var string a very long description
* @ORM\Column(stuff={ * @ORM\Column(stuff={
* "hallo" * "hallo"
* }) * })
@ -40,4 +45,11 @@ class PropertyOrder
* @var \stdClass mega! * @var \stdClass mega!
*/ */
protected $valid; protected $valid;
/**
* @var \stdClass
* @Flow\Validate
*/
#[OwnAttribute]
protected $inValidWithAttribute;
} }

View file

@ -10,5 +10,6 @@ class VariableCommentSniffTest extends TestCase
{ {
$report = self::checkFile(__DIR__ . '/data/comments.php'); $report = self::checkFile(__DIR__ . '/data/comments.php');
self::assertCount(1, $report->getWarnings()[20][6]); self::assertCount(1, $report->getWarnings()[20][6]);
self::assertCount(2, $report->getErrors());
} }
} }

View file

@ -24,3 +24,16 @@ class C extends A {
class D extends a { class D extends a {
protected $var; protected $var;
} }
#[\Attribute(\Attribute::TARGET_PROPERTY)]
final class OwnAttribute
{
}
class E extends A {
/**
* @var A
*/
#[\OwnAttribute]
protected $myVar;
}