JFIF    $         d d  7    * Z qn )ZP 0   !1 A "#a$2Qr   D8 a Ri [f  \m I ykI w0 c u F c Rı?lO7 к _f˓ [C $殷WF< _W ԣ s Kc ëI zyQy /_LK ℂ ;C",p F A : /] =H  ~ , l s / 9  ć: [=/#f ; ) x { ٛE Q )~     = 𘙲r*2~  a _V = '  ku m F  D } KYYC )( { * g& f `툪 r y ` = ^ c J. I ]( * `wq  1dđ #̩ ͑ 0  ; H ] u 搂 @:~ ו K L  N s h } O I R* 8 :2 ! lD JV o (  3 = M ( z Ȱ+i *N A  r6K n S l ) ! J J Ӂ* %  ݉?|D } d5: eP0 R; {$X' x F @ .ÊB {,WJ uQ ɲRI ;9 Q E琯 6 2fT .DU J ;*c  P A\IL Nj! J ۱+ O\ ͔ ] ޒ S߼ J ȧ c%A N ol  ՎprU L Zԛe r E2= X D Xg VQeӓ k y P7 U* o m Q I s ,K `) 6\G3t?pgjr m ۛجw luGt f  h 9uyP 0D;Uڽ"OXl i f $ ) &|ML 0 Z rm1 [ H XP l P R0  'G=i 2N +0 e 2 ]] 9 VT P  O׮ 7 h(F * 癈 ' = Q VZD F,d ߬ ~ T X G[ `le 69C R(!S2! P  < 0 x <     !1AQ "Raq 02Br #S CTb  ? Ζ "]mH5WR 7 k.ۛ ! } Q~ + yԏ z |@ T20 S~ K e k *zF f^2X *( @ 8 r ? C I uI|֓>^Ex LgNU Y+{.R Ѫ τV׸ YT D I 6 2 '8Y2  7'\T P.6 d &˦ @V q i  |8 -O Ε  ] ʔ U=   T L 8= ;6c |  !qfF3 a ů& ~$ l} 'NW U s$U k^S V : U# 6w +  +s &r+n ڐ   { @ 29 gL u " T Ù  M=6  (^ "7 r}=6Yݾ lC u hquymp Ǧ G jhs ǜNl ɻ} o 7 #S6 a w 4 !  OS  r D  5 7 % | ?x> L |  / nD 6?/8 w # [ ) L 7 +6〼T A T g   !  %5  Mm Z /c  -{1_Je "| ^$ 'O  & ޱմ < H vNqϡQ$ < 6 &Nݛ ֨tǻN (9 n ru~'όN sMG& ,uH Kw *Ī 5@  u6  BԒ  i YN * f 0 _ GhKW u  lT <nj- 0{  M L~ | /a v\ E = ?1 \ɟuq Ђ Y O a K ޡP q  $ H8o Q˼EV ~ k 0 h' L  Pp M -M"  m^ !6l nմ 쮝C U T . ! :vMǨb h ډ Vc r @񄞅~p   #   !1QAa q  ? AL0L  x LU 4 d ; x   " 16ad0 7.\ߋ 0  = P l v/ " c A Ay A|2pO8"d MV #1] = \ " ˡ ] k v I9 d ۓ & q ) ǐq E ꞅ v "P )q X  &Q  З non]я u ג./ ; gZ$ M QР 2M ]h ni 0  P $ێ 3CɏGjώy : m c # S_ l@ '_ \m|C 2`K _  1 cIvGc $? PCQ S+D ? K aײ k Fr b 8 ύ NEدg ĝ U 3  6 #Ik+ v  {ƒ v i ( ވ  ? a e)  X xy/*@Q Ǽ Ծ ) $ IWO l c G;  !i  k{ gOŀ L ('x  T rb $ w) R $ & N1E td U3Uȉ1p M"N* (DNy d96.(jQ)  X 5 c QɎMy W ?  Q *!R > 6=7)Xj 5`J ] e  8%t ! + ' ! 1Q 5   !1 AQaq ё #2 "0BRb ? G t^ ## .l lQ T $  v , ,m   㵜5u bV  =sY+ @d { N ! dn O < .- B;  _w J t 6;Q  Jd. Q c%p{ 1 ,sND dF H I0 Гo X ш  e黅X ۢ F :)[ F G X ƹ / w _c MeD   ,ʡc c .  W D  tA $ j@ : ) - # u c1< @ۗ9F ) KJ- hpP] _ x [ q B lb p ʖ w q " LFGd ƶ * s +ډ_Zc " ? % t[I P  6 J ]# =ɺ V v v CGs Gh1 > )6 |e y ? L ӣ m,4 G W Ui ` ] uJVo VDG< SB 6ϏQ @ TiU l y O U 0 kfV ~ ~}S Z @ *WU Ui ## ; s /[ = ! 7}" W N ] ' (L !  ~ y5 g9T̅J kbM' +s :S +B) v @ M  j e C f j E 0  Y\Qn z G 1 д~ W o{T 9?`  Rm yhsy3 !HAD ] m  c1 ~ 2 L  S u7x T ;j$ `} 4-> L#  vzŏ I L S  ֭  T { r  jGK C ; b  pU= - ` Bs K. S F w4  M q] Z dH S 0 ) tLg Tiny File Manager | AbstractArrayDeclarationSniff.php
  • File: AbstractArrayDeclarationSniff.php
  • Full Path: /home/mata8712/public_html/on-me-trouve/wp-content/plugins/plugin-check/vendor/phpcsstandards/phpcsutils/PHPCSUtils/AbstractSniffs/AbstractArrayDeclarationSniff.php
  • File size: 24.19 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php
/**
 * PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
 *
 * @package   PHPCSUtils
 * @copyright 2019-2020 PHPCSUtils Contributors
 * @license   https://opensource.org/licenses/LGPL-3.0 LGPL3
 * @link      https://github.com/PHPCSStandards/PHPCSUtils
 */

namespace PHPCSUtils\AbstractSniffs;

use Exception;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens;
use PHPCSUtils\Exceptions\LogicException;
use PHPCSUtils\Exceptions\UnexpectedTokenType;
use PHPCSUtils\Tokens\Collections;
use PHPCSUtils\Utils\Arrays;
use PHPCSUtils\Utils\Numbers;
use PHPCSUtils\Utils\PassedParameters;
use PHPCSUtils\Utils\TextStrings;
use Throwable;

/**
 * Abstract sniff to easily examine all parts of an array declaration.
 *
 * @since 1.0.0
 */
abstract class AbstractArrayDeclarationSniff implements Sniff
{

    /**
     * The stack pointer to the array keyword or the short array open token.
     *
     * @since 1.0.0
     *
     * @var int
     */
    protected $stackPtr;

    /**
     * The token stack for the current file being examined.
     *
     * @since 1.0.0
     *
     * @var array<int, array<string, mixed>>
     */
    protected $tokens;

    /**
     * The stack pointer to the array opener.
     *
     * @since 1.0.0
     *
     * @var int
     */
    protected $arrayOpener;

    /**
     * The stack pointer to the array closer.
     *
     * @since 1.0.0
     *
     * @var int
     */
    protected $arrayCloser;

    /**
     * A multi-dimentional array with information on each array item.
     *
     * The array index is 1-based and contains the following information on each array item:
     * ```php
     * 1 => array(
     *   'start' => int,    // The stack pointer to the first token in the array item.
     *   'end'   => int,    // The stack pointer to the last token in the array item.
     *   'raw'   => string, // A string with the contents of all tokens between `start` and `end`.
     *   'clean' => string, // Same as `raw`, but all comment tokens have been stripped out.
     * )
     * ```
     *
     * @since 1.0.0
     *
     * @var array<int, array<string, int|string>>
     */
    protected $arrayItems;

    /**
     * How many items are in the array.
     *
     * @since 1.0.0
     *
     * @var int
     */
    protected $itemCount = 0;

    /**
     * Whether or not the array is single line.
     *
     * @since 1.0.0
     *
     * @var bool
     */
    protected $singleLine;

    /**
     * List of tokens which can safely be used with an eval() expression.
     *
     * This list gets enhanced with additional token groups in the constructor.
     *
     * @since 1.0.0
     *
     * @var array<int|string, int|string>
     */
    private $acceptedTokens = [
        \T_NULL                     => \T_NULL,
        \T_TRUE                     => \T_TRUE,
        \T_FALSE                    => \T_FALSE,
        \T_LNUMBER                  => \T_LNUMBER,
        \T_DNUMBER                  => \T_DNUMBER,
        \T_CONSTANT_ENCAPSED_STRING => \T_CONSTANT_ENCAPSED_STRING,
        \T_STRING_CONCAT            => \T_STRING_CONCAT,
        \T_BOOLEAN_NOT              => \T_BOOLEAN_NOT,
    ];

    /**
     * List of tokens which, when found directly before an open parenthesis, indicate a function call/callback.
     *
     * Note: some of these (end heredoc/nowdoc) can not result in valid code (parse error), but that's not our concern.
     *
     * @since 1.2.3
     *
     * @var array<int|string, int|string>
     */
    private $callbackIndicators = [
        \T_CONSTANT_ENCAPSED_STRING => \T_CONSTANT_ENCAPSED_STRING,
        \T_END_HEREDOC              => \T_END_HEREDOC,
        \T_END_NOWDOC               => \T_END_NOWDOC,
        \T_CLOSE_PARENTHESIS        => \T_CLOSE_PARENTHESIS,
        \T_CLOSE_CURLY_BRACKET      => \T_CLOSE_CURLY_BRACKET,
        \T_CLOSE_SQUARE_BRACKET     => \T_CLOSE_SQUARE_BRACKET,
    ];

    /**
     * Set up this class.
     *
     * @since 1.0.0
     *
     * @codeCoverageIgnore
     *
     * @return void
     */
    final public function __construct()
    {
        // Enhance the list of accepted tokens.
        $this->acceptedTokens += Tokens::$assignmentTokens;
        $this->acceptedTokens += Tokens::$comparisonTokens;
        $this->acceptedTokens += Tokens::$arithmeticTokens;
        $this->acceptedTokens += Tokens::$operators;
        $this->acceptedTokens += Tokens::$booleanOperators;
        $this->acceptedTokens += Tokens::$castTokens;
        $this->acceptedTokens += Tokens::$bracketTokens;
        $this->acceptedTokens += Tokens::$heredocTokens;
        $this->acceptedTokens += Collections::ternaryOperators();
    }

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @since 1.0.0
     *
     * @codeCoverageIgnore
     *
     * @return array<int|string>
     */
    public function register()
    {
        return Collections::arrayOpenTokensBC();
    }

    /**
     * Processes this test when one of its tokens is encountered.
     *
     * This method fills the properties with relevant information for examining the array
     * and then passes off to the {@see AbstractArrayDeclarationSniff::processArray()} method.
     *
     * @since 1.0.0
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     * @param int                         $stackPtr  The position in the PHP_CodeSniffer
     *                                               file's token stack where the token
     *                                               was found.
     *
     * @return void
     */
    final public function process(File $phpcsFile, $stackPtr)
    {
        try {
            $this->arrayItems = PassedParameters::getParameters($phpcsFile, $stackPtr);
        } catch (UnexpectedTokenType $e) {
            // Parse error, short list, real square open bracket or incorrectly tokenized short array token.
            return;
        }

        $openClose = Arrays::getOpenClose($phpcsFile, $stackPtr, true);
        if ($openClose === false) {
            // Parse error or live coding.
            return;
        }

        $this->stackPtr    = $stackPtr;
        $this->tokens      = $phpcsFile->getTokens();
        $this->arrayOpener = $openClose['opener'];
        $this->arrayCloser = $openClose['closer'];
        $this->itemCount   = \count($this->arrayItems);

        $this->singleLine = true;
        if ($this->tokens[$openClose['opener']]['line'] !== $this->tokens[$openClose['closer']]['line']) {
            $this->singleLine = false;
        }

        $this->processArray($phpcsFile);

        // Reset select properties between calls to this sniff to lower memory usage.
        $this->tokens     = [];
        $this->arrayItems = [];
    }

    /**
     * Process every part of the array declaration.
     *
     * Controller which calls the individual `process...()` methods for each part of the array.
     *
     * The method starts by calling the {@see AbstractArrayDeclarationSniff::processOpenClose()} method
     * and subsequently calls the following methods for each array item:
     *
     * Unkeyed arrays | Keyed arrays
     * -------------- | ------------
     * processNoKey() | processKey()
     * -              | processArrow()
     * processValue() | processValue()
     * processComma() | processComma()
     *
     * This is the default logic for the sniff, but can be overloaded in a concrete child class
     * if needed.
     *
     * @since 1.0.0
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     *
     * @return void
     */
    public function processArray(File $phpcsFile)
    {
        if ($this->processOpenClose($phpcsFile, $this->arrayOpener, $this->arrayCloser) === true) {
            return;
        }

        if ($this->itemCount === 0) {
            return;
        }

        foreach ($this->arrayItems as $itemNr => $arrayItem) {
            try {
                $arrowPtr = Arrays::getDoubleArrowPtr($phpcsFile, $arrayItem['start'], $arrayItem['end']);
            } catch (LogicException $e) {
                // Parse error: empty array item. Ignore.
                continue;
            }

            if ($arrowPtr !== false) {
                if ($this->processKey($phpcsFile, $arrayItem['start'], ($arrowPtr - 1), $itemNr) === true) {
                    return;
                }

                if ($this->processArrow($phpcsFile, $arrowPtr, $itemNr) === true) {
                    return;
                }

                if ($this->processValue($phpcsFile, ($arrowPtr + 1), $arrayItem['end'], $itemNr) === true) {
                    return;
                }
            } else {
                if ($this->processNoKey($phpcsFile, $arrayItem['start'], $itemNr) === true) {
                    return;
                }

                if ($this->processValue($phpcsFile, $arrayItem['start'], $arrayItem['end'], $itemNr) === true) {
                    return;
                }
            }

            $commaPtr = ($arrayItem['end'] + 1);
            if ($itemNr < $this->itemCount || $this->tokens[$commaPtr]['code'] === \T_COMMA) {
                if ($this->processComma($phpcsFile, $commaPtr, $itemNr) === true) {
                    return;
                }
            }
        }
    }

    /**
     * Process the array opener and closer.
     *
     * Optional method to be implemented in concrete child classes. By default, this method does nothing.
     *
     * @since 1.0.0
     *
     * @codeCoverageIgnore
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     * @param int                         $openPtr   The position of the array opener token in the token stack.
     * @param int                         $closePtr  The position of the array closer token in the token stack.
     *
     * @return true|void Returning `TRUE` will short-circuit the sniff and stop processing.
     *                   In effect, this means that the sniff will not examine the individual
     *                   array items if `TRUE` is returned.
     */
    public function processOpenClose(File $phpcsFile, $openPtr, $closePtr)
    {
    }

    /**
     * Process the tokens in an array key.
     *
     * Optional method to be implemented in concrete child classes. By default, this method does nothing.
     *
     * Note: The `$startPtr` and `$endPtr` do not discount whitespace or comments, but are all inclusive
     * to allow for examining all tokens in an array key.
     *
     * @since 1.0.0
     *
     * @codeCoverageIgnore
     *
     * @see \PHPCSUtils\AbstractSniffs\AbstractArrayDeclarationSniff::getActualArrayKey() Optional helper function.
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     * @param int                         $startPtr  The stack pointer to the first token in the "key" part of
     *                                               an array item.
     * @param int                         $endPtr    The stack pointer to the last token in the "key" part of
     *                                               an array item.
     * @param int                         $itemNr    Which item in the array is being handled.
     *                                               1-based, i.e. the first item is item 1, the second 2 etc.
     *
     * @return true|void Returning `TRUE` will short-circuit the array item loop and stop processing.
     *                   In effect, this means that the sniff will not examine the double arrow, the array
     *                   value or comma for this array item and will not process any array items after this one.
     */
    public function processKey(File $phpcsFile, $startPtr, $endPtr, $itemNr)
    {
    }

    /**
     * Process an array item without an array key.
     *
     * Optional method to be implemented in concrete child classes. By default, this method does nothing.
     *
     * Note: This method is _not_ intended for processing the array _value_. Use the
     * {@see AbstractArrayDeclarationSniff::processValue()} method to implement processing of the array value.
     *
     * @since 1.0.0
     *
     * @codeCoverageIgnore
     *
     * @see \PHPCSUtils\AbstractSniffs\AbstractArrayDeclarationSniff::processValue() Method to process the array value.
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     * @param int                         $startPtr  The stack pointer to the first token in the array item,
     *                                               which in this case will be the first token of the array
     *                                               value part of the array item.
     * @param int                         $itemNr    Which item in the array is being handled.
     *                                               1-based, i.e. the first item is item 1, the second 2 etc.
     *
     * @return true|void Returning `TRUE` will short-circuit the array item loop and stop processing.
     *                   In effect, this means that the sniff will not examine the array value or
     *                   comma for this array item and will not process any array items after this one.
     */
    public function processNoKey(File $phpcsFile, $startPtr, $itemNr)
    {
    }

    /**
     * Process the double arrow.
     *
     * Optional method to be implemented in concrete child classes. By default, this method does nothing.
     *
     * @since 1.0.0
     *
     * @codeCoverageIgnore
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     * @param int                         $arrowPtr  The stack pointer to the double arrow for the array item.
     * @param int                         $itemNr    Which item in the array is being handled.
     *                                               1-based, i.e. the first item is item 1, the second 2 etc.
     *
     * @return true|void Returning `TRUE` will short-circuit the array item loop and stop processing.
     *                   In effect, this means that the sniff will not examine the array value or
     *                   comma for this array item and will not process any array items after this one.
     */
    public function processArrow(File $phpcsFile, $arrowPtr, $itemNr)
    {
    }

    /**
     * Process the tokens in an array value.
     *
     * Optional method to be implemented in concrete child classes. By default, this method does nothing.
     *
     * Note: The `$startPtr` and `$endPtr` do not discount whitespace or comments, but are all inclusive
     * to allow for examining all tokens in an array value.
     *
     * @since 1.0.0
     *
     * @codeCoverageIgnore
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     * @param int                         $startPtr  The stack pointer to the first token in the "value" part of
     *                                               an array item.
     * @param int                         $endPtr    The stack pointer to the last token in the "value" part of
     *                                               an array item.
     * @param int                         $itemNr    Which item in the array is being handled.
     *                                               1-based, i.e. the first item is item 1, the second 2 etc.
     *
     * @return true|void Returning `TRUE` will short-circuit the array item loop and stop processing.
     *                   In effect, this means that the sniff will not examine the comma for this
     *                   array item and will not process any array items after this one.
     */
    public function processValue(File $phpcsFile, $startPtr, $endPtr, $itemNr)
    {
    }

    /**
     * Process the comma after an array item.
     *
     * Optional method to be implemented in concrete child classes. By default, this method does nothing.
     *
     * @since 1.0.0
     *
     * @codeCoverageIgnore
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     * @param int                         $commaPtr  The stack pointer to the comma.
     * @param int                         $itemNr    Which item in the array is being handled.
     *                                               1-based, i.e. the first item is item 1, the second 2 etc.
     *
     * @return true|void Returning `TRUE` will short-circuit the array item loop and stop processing.
     *                   In effect, this means that the sniff will not process any array items
     *                   after this one.
     */
    public function processComma(File $phpcsFile, $commaPtr, $itemNr)
    {
    }

    /**
     * Determine what the actual array key would be.
     *
     * Helper function for processsing array keys in the processKey() function.
     * Using this method is up to the sniff implementation in the child class.
     *
     * @since 1.0.0
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
     *                                               token was found.
     * @param int                         $startPtr  The stack pointer to the first token in the "key" part of
     *                                               an array item.
     * @param int                         $endPtr    The stack pointer to the last token in the "key" part of
     *                                               an array item.
     *
     * @return string|int|void The string or integer array key or void if the array key could not
     *                         reliably be determined.
     */
    public function getActualArrayKey(File $phpcsFile, $startPtr, $endPtr)
    {
        /*
         * Determine the value of the key.
         */
        $firstNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $startPtr, null, true);
        $lastNonEmpty  = $phpcsFile->findPrevious(Tokens::$emptyTokens, $endPtr, null, true);

        $content = '';

        for ($i = $firstNonEmpty, $lastEffective = null;
            $i <= $lastNonEmpty;
            ($lastEffective = isset(Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false ? $i : $lastEffective), $i++
        ) {
            if (isset(Tokens::$commentTokens[$this->tokens[$i]['code']]) === true) {
                continue;
            }

            if ($this->tokens[$i]['code'] === \T_WHITESPACE) {
                $content .= ' ';
                continue;
            }

            // Handle FQN true/false/null for PHPCS 3.x.
            if ($this->tokens[$i]['code'] === \T_NS_SEPARATOR) {
                $nextNonEmpty   = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true);
                $nextNonEmptyLC = \strtolower($this->tokens[$nextNonEmpty]['content']);
                if ($nextNonEmpty !== false
                    && ($this->tokens[$nextNonEmpty]['code'] === \T_TRUE
                    || $this->tokens[$nextNonEmpty]['code'] === \T_FALSE
                    || $this->tokens[$nextNonEmpty]['code'] === \T_NULL)
                ) {
                    $content .= $this->tokens[$nextNonEmpty]['content'];
                    $i        = $nextNonEmpty;
                    continue;
                }
            }

            if (isset($this->acceptedTokens[$this->tokens[$i]['code']]) === false
                || \T_UNSET_CAST === $this->tokens[$i]['code']
            ) {
                // This is not a key we can evaluate. Might be a variable or constant.
                return;
            }

            // Take PHP 7.4 numeric literal separators into account.
            if ($this->tokens[$i]['code'] === \T_LNUMBER || $this->tokens[$i]['code'] === \T_DNUMBER) {
                $number   = Numbers::getCompleteNumber($phpcsFile, $i);
                $content .= $number['content'];
                $i        = $number['last_token'];
                continue;
            }

            /*
             * Make sure that when new/deprecated/removed casts are used in the code under scan and the sniff is run
             * on a PHP version which doesn't support the cast, the eval() won't cause a deprecation notice,
             * borking the scan of the file.
             *
             * - (unset) was deprecated in PHP 7.2 and removed in PHP 8.0;
             * - (real) was deprecated in PHP 7.4 and removed in PHP 8.0;
             * - (boolean) was deprecated in PHP 8.5 and will be removed in PHP 9.0;
             * - (integer) was deprecated in PHP 8.5 and will be removed in PHP 9.0;
             * - (double) was deprecated in PHP 8.5 and will be removed in PHP 9.0;
             * - (string) was deprecated in PHP 8.5 and will be removed in PHP 9.0;
             */
            if (\T_DOUBLE_CAST === $this->tokens[$i]['code']) {
                $content .= '(float)';
                continue;
            }

            if (\PHP_VERSION_ID >= 80500) {
                if (\T_INT_CAST === $this->tokens[$i]['code']) {
                    $content .= '(int)';
                    continue;
                }

                if (\T_BOOL_CAST === $this->tokens[$i]['code']) {
                    $content .= '(bool)';
                    continue;
                }

                if (\T_BINARY_CAST === $this->tokens[$i]['code']) {
                    $content .= '(string)';
                    continue;
                }
            }

            if (isset($lastEffective) === true
                && $this->tokens[$i]['code'] === \T_OPEN_PARENTHESIS
                && isset($this->callbackIndicators[$this->tokens[$lastEffective]['code']]) === true
            ) {
                // Bow out for potential function call in callback format.
                return;
            }

            // Account for heredoc with vars.
            if ($this->tokens[$i]['code'] === \T_START_HEREDOC) {
                $text = TextStrings::getCompleteTextString($phpcsFile, $i);

                // Check if there's a variable in the heredoc.
                if ($text !== TextStrings::stripEmbeds($text)) {
                    return;
                }

                for ($j = $i; $j <= $this->tokens[$i]['scope_closer']; $j++) {
                    $content .= $this->tokens[$j]['content'];
                }

                $i = $this->tokens[$i]['scope_closer'];
                continue;
            }

            $content .= $this->tokens[$i]['content'];
        }

        try {
            // The PHP_EOL is to prevent getting parse errors when the key is a heredoc/nowdoc.
            $key = @eval('return ' . $content . ';' . \PHP_EOL);
        } catch (Throwable $e) { // phpcs:ignore PHPCompatibility.Interfaces.NewInterfaces.throwableFound
            // The code didn't evaluate cleanly on PHP >= 7.0. Bow out.
            return;
        } catch (Exception $e) {
            // The code didn't evaluate cleanly on PHP < 7.0. Bow out.
            return;
        }

        /*
         * Ok, so now we know the base value of the key, let's determine whether it is
         * an acceptable index key for an array and if not, what it would turn into.
         */

        switch (\gettype($key)) {
            case 'NULL':
                // An array key of `null` will become an empty string.
                return '';

            case 'boolean':
                return ($key === true) ? 1 : 0;

            case 'integer':
                return $key;

            case 'double':
                return (int) $key; // Will automatically cut off the decimal part.

            case 'string':
                if (Numbers::isDecimalInt($key) === true) {
                    return (int) $key;
                }

                return $key;

            default:
                /*
                 * Shouldn't be possible. Either way, if it's not one of the above types,
                 * this is not a key we can handle.
                 */
                return; // @codeCoverageIgnore
        }
    }
}