From 57a86ebb8d952b91f6d9e0b21a991bf2019a9fad Mon Sep 17 00:00:00 2001 From: Marvin Kuhl Date: Wed, 30 Nov 2022 12:25:23 +0100 Subject: [PATCH] adds sniff to find @return void --- .../Annotations/ReturnIsNotVoidSniff.php | 77 +++++++++++++++++++ src/Inwebs/ruleset.xml | 1 + .../Annotations/ReturnIsNotVoidSniffTest.php | 18 +++++ .../Sniffs/Annotations/data/VoidReturner.php | 23 ++++++ 4 files changed, 119 insertions(+) create mode 100644 src/DigiComp/Sniffs/Annotations/ReturnIsNotVoidSniff.php create mode 100644 tests/DigiComp/Sniffs/Annotations/ReturnIsNotVoidSniffTest.php create mode 100644 tests/DigiComp/Sniffs/Annotations/data/VoidReturner.php diff --git a/src/DigiComp/Sniffs/Annotations/ReturnIsNotVoidSniff.php b/src/DigiComp/Sniffs/Annotations/ReturnIsNotVoidSniff.php new file mode 100644 index 0000000..fae06b1 --- /dev/null +++ b/src/DigiComp/Sniffs/Annotations/ReturnIsNotVoidSniff.php @@ -0,0 +1,77 @@ +getTokens(); + $ignore = Tokens::$methodPrefixes; + $ignore[\T_WHITESPACE] = \T_WHITESPACE; + + 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; + } + + if ($tokens[$commentEnd]['code'] === \T_COMMENT) { + // Inline comments might just be closing comments for + // control structures or functions instead of function comments + // using the wrong comment type. If there is other code on the line, + // assume they relate to that code. + $prev = $phpcsFile->findPrevious($ignore, ($commentEnd - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) { + $commentEnd = $prev; + } + } + + if ($tokens[$commentEnd]['code'] !== \T_DOC_COMMENT_CLOSE_TAG) { + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if (($tokens[$tag]['content'] === '@return') && 'void' === $tokens[$tag + 2]['content']) { + $fix = $phpcsFile->addFixableError('Return type void must not be annotated.', $tag, 'WrongReturnType'); + if ($fix) { + $nextTokenIndex = \array_search($tag, $tokens[$commentStart]['comment_tags'], true) + 1; + if (!isset($tokens[$commentStart]['comment_tags'][$nextTokenIndex])) { + $tag -= 2; + $nextToken = $commentEnd; + } else { + $nextToken = $tokens[$commentStart]['comment_tags'][$nextTokenIndex]; + } + $phpcsFile->fixer->beginChangeset(); + for ($tokenToDelete = $tag; $tokenToDelete < $nextToken; $tokenToDelete++) { + $phpcsFile->fixer->replaceToken($tokenToDelete, ''); + } + $phpcsFile->fixer->endChangeset(); + } + } + } + } +} diff --git a/src/Inwebs/ruleset.xml b/src/Inwebs/ruleset.xml index f18982a..6a58a10 100644 --- a/src/Inwebs/ruleset.xml +++ b/src/Inwebs/ruleset.xml @@ -13,6 +13,7 @@ + error 6 diff --git a/tests/DigiComp/Sniffs/Annotations/ReturnIsNotVoidSniffTest.php b/tests/DigiComp/Sniffs/Annotations/ReturnIsNotVoidSniffTest.php new file mode 100644 index 0000000..fccd42b --- /dev/null +++ b/tests/DigiComp/Sniffs/Annotations/ReturnIsNotVoidSniffTest.php @@ -0,0 +1,18 @@ +getErrorCount()); + } +} diff --git a/tests/DigiComp/Sniffs/Annotations/data/VoidReturner.php b/tests/DigiComp/Sniffs/Annotations/data/VoidReturner.php new file mode 100644 index 0000000..256e81d --- /dev/null +++ b/tests/DigiComp/Sniffs/Annotations/data/VoidReturner.php @@ -0,0 +1,23 @@ +