*/ public function register() { return [\T_CLASS]; } /** * Processes this test, when one of its tokens is encountered. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return void */ public function process(File $phpcsFile, $stackPtr) { $classProp = ObjectDeclarations::getClassProperties($phpcsFile, $stackPtr); if ($classProp['is_final'] === true) { $phpcsFile->recordMetric($stackPtr, self::METRIC_NAME, 'final'); return; } if ($classProp['is_abstract'] === true) { // Abstract classes can't be final. $phpcsFile->recordMetric($stackPtr, self::METRIC_NAME, 'abstract'); return; } $phpcsFile->recordMetric($stackPtr, self::METRIC_NAME, 'not abstract, not final'); $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); if ($nextNonEmpty === false) { // Live coding or parse error. return; } $snippetEnd = $nextNonEmpty; $classCloser = ''; $tokens = $phpcsFile->getTokens(); if (isset($tokens[$stackPtr]['scope_opener']) === true) { $snippetEnd = $tokens[$stackPtr]['scope_opener']; $classCloser = '}'; } $snippet = GetTokensAsString::compact($phpcsFile, $stackPtr, $snippetEnd, true); $fix = $phpcsFile->addFixableError( 'A non-abstract class should be declared as final. Found: %s%s', $stackPtr, 'NonFinalClassFound', [$snippet, $classCloser] ); if ($fix === true) { $phpcsFile->fixer->addContentBefore($stackPtr, 'final '); } } }