Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. DisallowImplicitArrayCreationSniff.php

class DisallowImplicitArrayCreationSniff

Hierarchy

  • class \SlevomatCodingStandard\Sniffs\Arrays\DisallowImplicitArrayCreationSniff implements \PHP_CodeSniffer\Sniffs\Sniff

Expanded class hierarchy of DisallowImplicitArrayCreationSniff

File

vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowImplicitArrayCreationSniff.php, line 31

Namespace

SlevomatCodingStandard\Sniffs\Arrays
View source
class DisallowImplicitArrayCreationSniff implements Sniff {
    public const CODE_IMPLICIT_ARRAY_CREATION_USED = 'ImplicitArrayCreationUsed';
    
    /**
     * @return array<int, (int|string)>
     */
    public function register() : array {
        return [
            T_OPEN_SQUARE_BRACKET,
        ];
    }
    
    /**
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     * @param int $bracketOpenerPointer
     */
    public function process(File $phpcsFile, $bracketOpenerPointer) : void {
        $tokens = $phpcsFile->getTokens();
        $assignmentPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$bracketOpenerPointer]['bracket_closer'] + 1);
        if ($tokens[$assignmentPointer]['code'] !== T_EQUAL) {
            return;
        }
        
        /** @var int $variablePointer */
        $variablePointer = TokenHelper::findPreviousEffective($phpcsFile, $bracketOpenerPointer - 1);
        if ($tokens[$variablePointer]['code'] !== T_VARIABLE) {
            return;
        }
        if (in_array($tokens[$variablePointer]['content'], [
            '$GLOBALS',
            '$_SERVER',
            '$_REQUEST',
            '$_POST',
            '$_GET',
            '$_FILES',
            '$_ENV',
            '$_COOKIE',
            '$_SESSION',
            '$this',
        ], true)) {
            return;
        }
        $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1);
        if (in_array($tokens[$pointerBeforeVariable]['code'], [
            T_OBJECT_OPERATOR,
            T_DOUBLE_COLON,
        ], true)) {
            return;
        }
        $scopeOwnerPointer = null;
        foreach (array_reverse($tokens[$variablePointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) {
            if (!in_array($conditionTokenCode, TokenHelper::$functionTokenCodes, true)) {
                continue;
            }
            $scopeOwnerPointer = $conditionPointer;
            break;
        }
        if ($scopeOwnerPointer === null) {
            $scopeOwnerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $variablePointer - 1);
        }
        $scopeOpenerPointer = $tokens[$scopeOwnerPointer]['code'] === T_OPEN_TAG ? $scopeOwnerPointer : $tokens[$scopeOwnerPointer]['scope_opener'];
        $scopeCloserPointer = $tokens[$scopeOwnerPointer]['code'] === T_OPEN_TAG ? count($tokens) - 1 : $tokens[$scopeOwnerPointer]['scope_closer'];
        if (in_array($tokens[$scopeOwnerPointer]['code'], TokenHelper::$functionTokenCodes, true)) {
            if ($this->isParameter($phpcsFile, $scopeOwnerPointer, $variablePointer)) {
                return;
            }
            if ($tokens[$scopeOwnerPointer]['code'] === T_CLOSURE && $this->isInheritedVariable($phpcsFile, $scopeOwnerPointer, $variablePointer)) {
                return;
            }
        }
        if ($this->hasExplicitCreation($phpcsFile, $scopeOpenerPointer, $scopeCloserPointer, $variablePointer)) {
            return;
        }
        $phpcsFile->addError('Implicit array creation is disallowed.', $variablePointer, self::CODE_IMPLICIT_ARRAY_CREATION_USED);
    }
    private function isParameter(File $phpcsFile, int $functionPointer, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $variableName = $tokens[$variablePointer]['content'];
        $parameterPointer = TokenHelper::findNextContent($phpcsFile, T_VARIABLE, $variableName, $tokens[$functionPointer]['parenthesis_opener'] + 1, $tokens[$functionPointer]['parenthesis_closer']);
        return $parameterPointer !== null;
    }
    private function isInheritedVariable(File $phpcsFile, int $closurePointer, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $variableName = $tokens[$variablePointer]['content'];
        $usePointer = TokenHelper::findNext($phpcsFile, T_USE, $tokens[$closurePointer]['parenthesis_closer'] + 1, $tokens[$closurePointer]['scope_opener']);
        if ($usePointer === null) {
            return false;
        }
        $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1);
        $inheritedVariablePointer = TokenHelper::findNextContent($phpcsFile, T_VARIABLE, $variableName, $parenthesisOpenerPointer + 1, $tokens[$parenthesisOpenerPointer]['parenthesis_closer']);
        return $inheritedVariablePointer !== null;
    }
    private function hasExplicitCreation(File $phpcsFile, int $scopeOpenerPointer, int $scopeCloserPointer, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $variableName = $tokens[$variablePointer]['content'];
        for ($i = $scopeOpenerPointer + 1; $i < $variablePointer; $i++) {
            if ($tokens[$i]['code'] !== T_VARIABLE) {
                continue;
            }
            if ($tokens[$i]['content'] !== $variableName) {
                continue;
            }
            if (!ScopeHelper::isInSameScope($phpcsFile, $variablePointer, $i)) {
                continue;
            }
            $assignmentPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1);
            if ($tokens[$assignmentPointer]['code'] === T_EQUAL) {
                return true;
            }
            $staticPointer = TokenHelper::findPreviousEffective($phpcsFile, $i - 1);
            if ($tokens[$staticPointer]['code'] === T_STATIC) {
                return true;
            }
            if ($this->isCreatedInForeach($phpcsFile, $i, $scopeCloserPointer)) {
                return true;
            }
            if ($this->isCreatedInList($phpcsFile, $i, $scopeOpenerPointer)) {
                return true;
            }
            if ($this->isCreatedByReferencedParameterInFunctionCall($phpcsFile, $i, $scopeOpenerPointer)) {
                return true;
            }
            if ($this->isImportedUsingGlobalStatement($phpcsFile, $i)) {
                return true;
            }
        }
        return false;
    }
    private function isCreatedInList(File $phpcsFile, int $variablePointer, int $scopeOpenerPointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $parenthesisOpenerPointer = TokenHelper::findPrevious($phpcsFile, [
            T_OPEN_PARENTHESIS,
            T_OPEN_SHORT_ARRAY,
            T_OPEN_SQUARE_BRACKET,
        ], $variablePointer - 1, $scopeOpenerPointer);
        if ($parenthesisOpenerPointer === null) {
            return false;
        }
        if ($tokens[$parenthesisOpenerPointer]['code'] === T_OPEN_PARENTHESIS) {
            if ($tokens[$parenthesisOpenerPointer]['parenthesis_closer'] < $variablePointer) {
                return false;
            }
            $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1);
            return $tokens[$pointerBeforeParenthesisOpener]['code'] === T_LIST;
        }
        return $tokens[$parenthesisOpenerPointer]['bracket_closer'] > $variablePointer;
    }
    private function isCreatedInForeach(File $phpcsFile, int $variablePointer, int $scopeCloserPointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $parenthesisCloserPointer = TokenHelper::findNext($phpcsFile, T_CLOSE_PARENTHESIS, $variablePointer + 1, $scopeCloserPointer);
        return $parenthesisCloserPointer !== null && array_key_exists('parenthesis_owner', $tokens[$parenthesisCloserPointer]) && $tokens[$tokens[$parenthesisCloserPointer]['parenthesis_owner']]['code'] === T_FOREACH && $tokens[$parenthesisCloserPointer]['parenthesis_opener'] < $variablePointer;
    }
    private function isCreatedByReferencedParameterInFunctionCall(File $phpcsFile, int $variablePointer, int $scopeOpenerPointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $parenthesisOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_PARENTHESIS, $variablePointer - 1, $scopeOpenerPointer);
        if ($parenthesisOpenerPointer === null || $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] < $variablePointer) {
            return false;
        }
        $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1);
        return $tokens[$pointerBeforeParenthesisOpener]['code'] === T_STRING;
    }
    private function isImportedUsingGlobalStatement(File $phpcsFile, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $startOfStatement = $phpcsFile->findStartOfStatement($variablePointer, T_COMMA);
        return $tokens[$startOfStatement]['code'] === T_GLOBAL;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
DisallowImplicitArrayCreationSniff::CODE_IMPLICIT_ARRAY_CREATION_USED public constant
DisallowImplicitArrayCreationSniff::hasExplicitCreation private function
DisallowImplicitArrayCreationSniff::isCreatedByReferencedParameterInFunctionCall private function
DisallowImplicitArrayCreationSniff::isCreatedInForeach private function
DisallowImplicitArrayCreationSniff::isCreatedInList private function
DisallowImplicitArrayCreationSniff::isImportedUsingGlobalStatement private function
DisallowImplicitArrayCreationSniff::isInheritedVariable private function
DisallowImplicitArrayCreationSniff::isParameter private function
DisallowImplicitArrayCreationSniff::process public function * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
*
Overrides Sniff::process
DisallowImplicitArrayCreationSniff::register public function * Overrides Sniff::register
RSS feed
Powered by Drupal