private function fixSemicolonAfterCurlyBraceClose(Tokens $tokens, $index, $curlyCloseIndex)
    {
        static $beforeCurlyOpeningKinds = null;
        if (null === $beforeCurlyOpeningKinds) {
            $beforeCurlyOpeningKinds = [T_ELSE, T_FINALLY, T_NAMESPACE, T_OPEN_TAG];
        }

        $curlyOpeningIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $curlyCloseIndex);
        $beforeCurlyOpening = $tokens->getPrevMeaningfulToken($curlyOpeningIndex);
        if ($tokens[$beforeCurlyOpening]->isGivenKind($beforeCurlyOpeningKinds) || $tokens[$beforeCurlyOpening]->equalsAny([';', '{', '}'])) {
            $tokens->clearTokenAndMergeSurroundingWhitespace($index);

            return;
        }

        // check for namespaces and class, interface and trait definitions
        if ($tokens[$beforeCurlyOpening]->isGivenKind(T_STRING)) {
            $classyTest = $tokens->getPrevMeaningfulToken($beforeCurlyOpening);
            while ($tokens[$classyTest]->equals(',') || $tokens[$classyTest]->isGivenKind([T_STRING, T_NS_SEPARATOR, T_EXTENDS, T_IMPLEMENTS])) {
                $classyTest = $tokens->getPrevMeaningfulToken($classyTest);
            }

            $tokensAnalyzer = new TokensAnalyzer($tokens);

            if (
                $tokens[$classyTest]->isGivenKind(T_NAMESPACE) ||
                ($tokens[$classyTest]->isClassy() && !$tokensAnalyzer->isAnonymousClass($classyTest))
            ) {
                $tokens->clearTokenAndMergeSurroundingWhitespace($index);
            }

            return;
        }

        // early return check, below only control structures with conditions are fixed
        if (!$tokens[$beforeCurlyOpening]->equals(')')) {
            return;
        }

        $openingBrace = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $beforeCurlyOpening);
        $beforeOpeningBrace = $tokens->getPrevMeaningfulToken($openingBrace);

        if ($tokens[$beforeOpeningBrace]->isGivenKind([T_IF, T_ELSEIF, T_FOR, T_FOREACH, T_WHILE, T_SWITCH, T_CATCH, T_DECLARE])) {
            $tokens->clearTokenAndMergeSurroundingWhitespace($index);

            return;
        }

        // check for function definition
        if ($tokens[$beforeOpeningBrace]->isGivenKind(T_STRING)) {
            $beforeString = $tokens->getPrevMeaningfulToken($beforeOpeningBrace);
            if ($tokens[$beforeString]->isGivenKind(T_FUNCTION)) {
                $tokens->clearTokenAndMergeSurroundingWhitespace($index); // implicit return
            }
        }
    }
private function fixSemicolonAfterCurlyBraceClose(Tokens $tokens, $index, $curlyCloseIndex)
    {
        static $beforeCurlyOpeningKinds = null;
        if (null === $beforeCurlyOpeningKinds) {
            $beforeCurlyOpeningKinds = [T_ELSE, T_FINALLY, T_NAMESPACE, T_OPEN_TAG];
        }

        $curlyOpeningIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $curlyCloseIndex);
        $beforeCurlyOpening = $tokens->getPrevMeaningfulToken($curlyOpeningIndex);
        if ($tokens[$beforeCurlyOpening]->isGivenKind($beforeCurlyOpeningKinds) || $tokens[$beforeCurlyOpening]->equalsAny([';', '{', '}'])) {
            $tokens->clearTokenAndMergeSurroundingWhitespace($index);

            return;
        }

        // check for namespaces and class, interface and trait definitions
        if ($tokens[$beforeCurlyOpening]->isGivenKind(T_STRING)) {
            $classyTest = $tokens->getPrevMeaningfulToken($beforeCurlyOpening);
            while ($tokens[$classyTest]->equals(',') || $tokens[$classyTest]->isGivenKind([T_STRING, T_NS_SEPARATOR, T_EXTENDS, T_IMPLEMENTS])) {
                $classyTest = $tokens->getPrevMeaningfulToken($classyTest);
            }

            $tokensAnalyzer = new TokensAnalyzer($tokens);

            if (
                $tokens[$classyTest]->isGivenKind(T_NAMESPACE) ||
                ($tokens[$classyTest]->isClassy() && !$tokensAnalyzer->isAnonymousClass($classyTest))
            ) {
                $tokens->clearTokenAndMergeSurroundingWhitespace($index);
            }

            return;
        }

        // early return check, below only control structures with conditions are fixed
        if (!$tokens[$beforeCurlyOpening]->equals(')')) {
            return;
        }

        $openingBrace = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $beforeCurlyOpening);
        $beforeOpeningBrace = $tokens->getPrevMeaningfulToken($openingBrace);

        if ($tokens[$beforeOpeningBrace]->isGivenKind([T_IF, T_ELSEIF, T_FOR, T_FOREACH, T_WHILE, T_SWITCH, T_CATCH, T_DECLARE])) {
            $tokens->clearTokenAndMergeSurroundingWhitespace($index);

            return;
        }

        // check for function definition
        if ($tokens[$beforeOpeningBrace]->isGivenKind(T_STRING)) {
            $beforeString = $tokens->getPrevMeaningfulToken($beforeOpeningBrace);
            if ($tokens[$beforeString]->isGivenKind(T_FUNCTION)) {
                $tokens->clearTokenAndMergeSurroundingWhitespace($index); // implicit return
            }
        }
    }
private function fixSemicolonAfterCurlyBraceClose ( Tokens $ tokens , $ index , $ curlyCloseIndex ) { static $ beforeCurlyOpeningKinds = null ; if ( null === $ beforeCurlyOpeningKinds ) { $ beforeCurlyOpeningKinds = [ T_ELSE , T_FINALLY , T_NAMESPACE , T_OPEN_TAG ] ; } $ curlyOpeningIndex = $ tokens -> findBlockStart ( Tokens :: BLOCK_TYPE_CURLY_BRACE , $ curlyCloseIndex ) ; $ beforeCurlyOpening = $ tokens -> getPrevMeaningfulToken ( $ curlyOpeningIndex ) ; if ( $ tokens [ $ beforeCurlyOpening ] -> isGivenKind ( $ beforeCurlyOpeningKinds ) || $ tokens [ $ beforeCurlyOpening ] -> equalsAny ( [ ';' , '{' , '}' ] ) ) { $ tokens -> clearTokenAndMergeSurroundingWhitespace ( $ index ) ; return ; } // check for namespaces and class, interface and trait definitions if ( $ tokens [ $ beforeCurlyOpening ] -> isGivenKind ( T_STRING ) ) { $ classyTest = $ tokens -> getPrevMeaningfulToken ( $ beforeCurlyOpening ) ; while ( $ tokens [ $ classyTest ] -> equals ( ',' ) || $ tokens [ $ classyTest ] -> isGivenKind ( [ T_STRING , T_NS_SEPARATOR , T_EXTENDS , T_IMPLEMENTS ] ) ) { $ classyTest = $ tokens -> getPrevMeaningfulToken ( $ classyTest ) ; } $ tokensAnalyzer = new TokensAnalyzer ( $ tokens ) ; if ( $ tokens [ $ classyTest ] -> isGivenKind ( T_NAMESPACE ) || ( $ tokens [ $ classyTest ] -> isClassy ( ) && ! $ tokensAnalyzer -> isAnonymousClass ( $ classyTest ) ) ) { $ tokens -> clearTokenAndMergeSurroundingWhitespace ( $ index ) ; } return ; } // early return check, below only control structures with conditions are fixed if ( ! $ tokens [ $ beforeCurlyOpening ] -> equals ( ')' ) ) { return ; } $ openingBrace = $ tokens -> findBlockStart ( Tokens :: BLOCK_TYPE_PARENTHESIS_BRACE , $ beforeCurlyOpening ) ; $ beforeOpeningBrace = $ tokens -> getPrevMeaningfulToken ( $ openingBrace ) ; if ( $ tokens [ $ beforeOpeningBrace ] -> isGivenKind ( [ T_IF , T_ELSEIF , T_FOR , T_FOREACH , T_WHILE , T_SWITCH , T_CATCH , T_DECLARE ] ) ) { $ tokens -> clearTokenAndMergeSurroundingWhitespace ( $ index ) ; return ; } // check for function definition if ( $ tokens [ $ beforeOpeningBrace ] -> isGivenKind ( T_STRING ) ) { $ beforeString = $ tokens -> getPrevMeaningfulToken ( $ beforeOpeningBrace ) ; if ( $ tokens [ $ beforeString ] -> isGivenKind ( T_FUNCTION ) ) { $ tokens -> clearTokenAndMergeSurroundingWhitespace ( $ index ) ; // implicit return } } }
Fix semicolon after closing curly brace if needed.

Test for the following cases
- just '{' '}' block (following open tag or ';')
- if, else, elseif
- interface, trait, class (but not anonymous)
- catch, finally (but not try)
- for, foreach, while (but not 'do - while')
- switch
- function (declaration, but not lambda)
- declare (with '{' '}')
- namespace (with '{' '}')

@param Tokens $tokens
@param int    $index           Semicolon index
@param int    $curlyCloseIndex
Fix semicolon after closing curly brace if needed .