Fixing doc type annotation sniffs to correctly ignore attributes
This commit is contained in:
parent
ef0ac65a4f
commit
7063c47d64
12 changed files with 92 additions and 41 deletions
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
35
src/DigiComp/Sniffs/MemberVarUtility.php
Normal file
35
src/DigiComp/Sniffs/MemberVarUtility.php
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue