PHP-CS-Fixer camelCaseな変数名をsnake_caseに変換するcustom-fixers

PHP-CS-Fixerを使って、camelCaseな変数名をsnake_caseに変換するcustom-fixersです。 protected な変数は対象外にしています。

<?php

namespace App\Fixers;

use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use SplFileInfo;

class SnakeCaseVariableFixer extends AbstractFixer
{
    /**
     * https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/d208496b85c57217e76502b55e2228f3bfe7452b/src/FixerFactory.php#L131
     */
    public function getName(): string
    {
        return 'App/snake_case_variable';
    }

    public function getDefinition(): FixerDefinition
    {
        return new FixerDefinition(
            'Variable names should be in snake_case.',
            [
                new CodeSample('<?php $camelCase = "example";'),
            ]
        );
    }

    public function isCandidate(Tokens $tokens): bool
    {
        return $tokens->isAllTokenKindsFound([T_VARIABLE]);
    }

    public function applyFix(SplFileInfo $file, Tokens $tokens): void
    {
        foreach ($tokens as $index => $token) {
            if ($token->isGivenKind(T_VARIABLE)) {
                 /**
                 * This section processes the exclusion of protected variables.
                 * When the variable is protected, it will be preceded by 'protected' and a space, 
                 * both of which are tokens. Thus, we check the token value at $index - 2 to identify
                 * if it is 'protected' and skip processing if so.
                 */
                if ($index > 2) {
                    $previousToken = $tokens[$index - 2];
                    if ($previousToken->isGivenKind(T_PROTECTED)) {
                        continue;
                    }
                }

                $variable_name = $token->getContent();
                $snake_case_name = $this->convertToSnakeCase($variable_name);
                if ($variable_name !== $snake_case_name) {
                    $tokens[$index] = new Token([T_VARIABLE, $snake_case_name]);
                }
            }
        }
    }

    private function convertToSnakeCase($string): string
    {
        return '$'.strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', substr($string, 1)));
    }
}