private function findFunction(Tokens $tokens, $name, $startIndex, $endIndex)
    {
        $function = $tokens->findSequence([
            [T_FUNCTION],
            [T_STRING, $name],
            '(',
        ], $startIndex, $endIndex, false);

        if (null === $function) {
            return null;
        }

        // keep only the indexes
        $function = array_keys($function);

        // find previous block, saving method modifiers for later use
        $possibleModifiers = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_ABSTRACT, T_FINAL];
        $modifiers = [];

        $prevBlock = $tokens->getPrevMeaningfulToken($function[0]);
        while (null !== $prevBlock && $tokens[$prevBlock]->isGivenKind($possibleModifiers)) {
            $modifiers[$tokens[$prevBlock]->getId()] = $prevBlock;
            $prevBlock = $tokens->getPrevMeaningfulToken($prevBlock);
        }

        if (isset($modifiers[T_ABSTRACT])) {
            // abstract methods have no body
            $bodyStart = null;
            $funcEnd = $tokens->getNextTokenOfKind($function[2], [';']);
        } else {
            // find method body start and the end of the function definition
            $bodyStart = $tokens->getNextTokenOfKind($function[2], ['{']);
            $funcEnd = null !== $bodyStart ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $bodyStart) : null;
        }

        return [
            'nameIndex' => $function[1],
            'startIndex' => $prevBlock + 1,
            'endIndex' => $funcEnd,
            'bodyIndex' => $bodyStart,
            'modifiers' => $modifiers,
        ];
    }