From 956cb5389522feffe20718bcc88964775ebbacb3 Mon Sep 17 00:00:00 2001 From: webimpress Date: Sun, 27 Oct 2019 19:12:32 +0000 Subject: [PATCH] Feature: Classes\PropertyBeforeMethod sniff Class properties should be defined before class methods. --- .../Classes/PropertyBeforeMethodSniff.php | 92 +++++++++++++++++++ .../Classes/PropertyBeforeMethodUnitTest.inc | 59 ++++++++++++ .../PropertyBeforeMethodUnitTest.inc.fixed | 59 ++++++++++++ .../Classes/PropertyBeforeMethodUnitTest.php | 26 ++++++ 4 files changed, 236 insertions(+) create mode 100644 src/WebimpressCodingStandard/Sniffs/Classes/PropertyBeforeMethodSniff.php create mode 100644 test/Sniffs/Classes/PropertyBeforeMethodUnitTest.inc create mode 100644 test/Sniffs/Classes/PropertyBeforeMethodUnitTest.inc.fixed create mode 100644 test/Sniffs/Classes/PropertyBeforeMethodUnitTest.php diff --git a/src/WebimpressCodingStandard/Sniffs/Classes/PropertyBeforeMethodSniff.php b/src/WebimpressCodingStandard/Sniffs/Classes/PropertyBeforeMethodSniff.php new file mode 100644 index 00000000..05013621 --- /dev/null +++ b/src/WebimpressCodingStandard/Sniffs/Classes/PropertyBeforeMethodSniff.php @@ -0,0 +1,92 @@ +getTokens(); + + $scopePtr = key(array_reverse($tokens[$stackPtr]['conditions'], true)); + $scopeOpener = $tokens[$scopePtr]['scope_opener']; + + $find = $phpcsFile->findNext(T_FUNCTION, $scopeOpener + 1, $stackPtr); + if ($find) { + $error = 'Method declaration forbidden in line %d before property declaration'; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BeforeProperty', [$tokens[$find]['line']]); + if ($fix) { + $before = $phpcsFile->findPrevious( + Tokens::$emptyTokens + Tokens::$methodPrefixes, + $find - 1, + null, + true + ); + + $from = $phpcsFile->findPrevious( + Tokens::$emptyTokens + Tokens::$scopeModifiers + [ + T_VAR => T_VAR, + T_STATIC => T_STATIC, + // as of PHP 7.4 we can have defined types with properties + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_STRING => T_STRING, + T_NULLABLE => T_NULLABLE, + ], + $stackPtr - 1, + null, + true + ); + $eos = $phpcsFile->findEndOfStatement($stackPtr); + + $toMove = $phpcsFile->getTokensAsString($from + 1, $eos - $from); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($before, $toMove); + for ($i = $from + 1; $i <= $eos; ++$i) { + $phpcsFile->fixer->replaceToken($i, ''); + } + $phpcsFile->fixer->endChangeset(); + } + } + } + + /** + * @codeCoverageIgnore + * + * @param int $stackPtr + */ + protected function processVariable(File $phpcsFile, $stackPtr) : void + { + // Normal variables are not processed in this sniff. + } + + /** + * @codeCoverageIgnore + * + * @param int $stackPtr + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) : void + { + // Variables in string are not processed in this sniff. + } +} diff --git a/test/Sniffs/Classes/PropertyBeforeMethodUnitTest.inc b/test/Sniffs/Classes/PropertyBeforeMethodUnitTest.inc new file mode 100644 index 00000000..760992e4 --- /dev/null +++ b/test/Sniffs/Classes/PropertyBeforeMethodUnitTest.inc @@ -0,0 +1,59 @@ + 1, + 31 => 1, + 34 => 1, + 44 => 1, + 55 => 1, + ]; + } + + protected function getWarningList(string $testFile = '') : array + { + return []; + } +}