src/Fixer/Import/OrderedImportsFixer.php
private function getNewOrder(array $uses, Tokens $tokens)
    {
        $indexes = [];
        $originalIndexes = [];
        $lineEnding = $this->whitespacesConfig->getLineEnding();

        for ($i = \count($uses) - 1; $i >= 0; --$i) {
            $index = $uses[$i];

            $startIndex = $tokens->getTokenNotOfKindSibling($index + 1, 1, [[T_WHITESPACE]]);
            $endIndex = $tokens->getNextTokenOfKind($startIndex, [';', [T_CLOSE_TAG]]);
            $previous = $tokens->getPrevMeaningfulToken($endIndex);

            $group = $tokens[$previous]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_CLOSE);
            if ($tokens[$startIndex]->isGivenKind(CT::T_CONST_IMPORT)) {
                $type = self::IMPORT_TYPE_CONST;
                $index = $tokens->getNextNonWhitespace($startIndex);
            } elseif ($tokens[$startIndex]->isGivenKind(CT::T_FUNCTION_IMPORT)) {
                $type = self::IMPORT_TYPE_FUNCTION;
                $index = $tokens->getNextNonWhitespace($startIndex);
            } else {
                $type = self::IMPORT_TYPE_CLASS;
                $index = $startIndex;
            }

            $namespaceTokens = [];

            while ($index <= $endIndex) {
                $token = $tokens[$index];

                if ($index === $endIndex || (!$group && $token->equals(','))) {
                    if ($group && self::SORT_NONE !== $this->configuration['sort_algorithm']) {
                        // if group import, sort the items within the group definition

                        // figure out where the list of namespace parts within the group def. starts
                        $namespaceTokensCount = \count($namespaceTokens) - 1;
                        $namespace = '';
                        for ($k = 0; $k < $namespaceTokensCount; ++$k) {
                            if ($namespaceTokens[$k]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_OPEN)) {
                                $namespace .= '{';

                                break;
                            }

                            $namespace .= $namespaceTokens[$k]->getContent();
                        }

                        // fetch all parts, split up in an array of strings, move comments to the end
                        $parts = [];
                        $firstIndent = '';
                        $separator = ', ';
                        $lastIndent = '';

                        for ($k1 = $k + 1; $k1 < $namespaceTokensCount; ++$k1) {
                            $comment = '';
                            $namespacePart = '';
                            for ($k2 = $k1;; ++$k2) {
                                if ($namespaceTokens[$k2]->equalsAny([',', [CT::T_GROUP_IMPORT_BRACE_CLOSE]])) {
                                    break;
                                }

                                if ($namespaceTokens[$k2]->isComment()) {
                                    $comment .= $namespaceTokens[$k2]->getContent();

                                    continue;
                                }

                                // if there is any line ending inside the group import, it should be indented properly
                                if (
                                    '' === $firstIndent &&
                                    $namespaceTokens[$k2]->isWhitespace() &&
                                    false !== strpos($namespaceTokens[$k2]->getContent(), $lineEnding)
                                ) {
                                    $lastIndent = $lineEnding;
                                    $firstIndent = $lineEnding.$this->whitespacesConfig->getIndent();
                                    $separator = ','.$firstIndent;
                                }

                                $namespacePart .= $namespaceTokens[$k2]->getContent();
                            }

                            $namespacePart = trim($namespacePart);
                            $comment = trim($comment);
                            if ('' !== $comment) {
                                $namespacePart .= ' '.$comment;
                            }

                            $parts[] = $namespacePart;

                            $k1 = $k2;
                        }

                        $sortedParts = $parts;
                        sort($parts);

                        // check if the order needs to be updated, otherwise don't touch as we might change valid CS (to other valid CS).
                        if ($sortedParts === $parts) {
                            $namespace = Tokens::fromArray($namespaceTokens)->generateCode();
                        } else {
                            $namespace .= $firstIndent.implode($separator, $parts).$lastIndent.'}';
                        }
                    } else {
                        $namespace = Tokens::fromArray($namespaceTokens)->generateCode();
                    }

                    $indexes[$startIndex] = [
                        'namespace' => $namespace,
                        'startIndex' => $startIndex,
                        'endIndex' => $index - 1,
                        'importType' => $type,
                        'group' => $group,
                    ];

                    $originalIndexes[] = $startIndex;

                    if ($index === $endIndex) {
                        break;
                    }

                    $namespaceTokens = [];
                    $nextPartIndex = $tokens->getTokenNotOfKindSibling($index, 1, [[','], [T_WHITESPACE]]);
                    $startIndex = $nextPartIndex;
                    $index = $nextPartIndex;

                    continue;
                }

                $namespaceTokens[] = $token;
                ++$index;
            }
        }

        // Is sort types provided, sorting by groups and each group by algorithm
        if (null !== $this->configuration['imports_order']) {
            // Grouping indexes by import type.
            $groupedByTypes = [];
            foreach ($indexes as $startIndex => $item) {
                $groupedByTypes[$item['importType']][$startIndex] = $item;
            }

            // Sorting each group by algorithm.
            foreach ($groupedByTypes as $type => $indexes) {
                $groupedByTypes[$type] = $this->sortByAlgorithm($indexes);
            }

            // Ordering groups
            $sortedGroups = [];
            foreach ($this->configuration['imports_order'] as $type) {
                if (isset($groupedByTypes[$type]) && !empty($groupedByTypes[$type])) {
                    foreach ($groupedByTypes[$type] as $startIndex => $item) {
                        $sortedGroups[$startIndex] = $item;
                    }
                }
            }
            $indexes = $sortedGroups;
        } else {
            // Sorting only by algorithm
            $indexes = $this->sortByAlgorithm($indexes);
        }

        $index = -1;
        $usesOrder = [];

        // Loop trough the index but use original index order
        foreach ($indexes as $v) {
            $usesOrder[$originalIndexes[++$index]] = $v;
        }

        return $usesOrder;
    }
private function getNewOrder(array $uses, Tokens $tokens)
    {
        $indexes = [];
        $originalIndexes = [];
        $lineEnding = $this->whitespacesConfig->getLineEnding();

        for ($i = \count($uses) - 1; $i >= 0; --$i) {
            $index = $uses[$i];

            $startIndex = $tokens->getTokenNotOfKindSibling($index + 1, 1, [[T_WHITESPACE]]);
            $endIndex = $tokens->getNextTokenOfKind($startIndex, [';', [T_CLOSE_TAG]]);
            $previous = $tokens->getPrevMeaningfulToken($endIndex);

            $group = $tokens[$previous]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_CLOSE);
            if ($tokens[$startIndex]->isGivenKind(CT::T_CONST_IMPORT)) {
                $type = self::IMPORT_TYPE_CONST;
                $index = $tokens->getNextNonWhitespace($startIndex);
            } elseif ($tokens[$startIndex]->isGivenKind(CT::T_FUNCTION_IMPORT)) {
                $type = self::IMPORT_TYPE_FUNCTION;
                $index = $tokens->getNextNonWhitespace($startIndex);
            } else {
                $type = self::IMPORT_TYPE_CLASS;
                $index = $startIndex;
            }

            $namespaceTokens = [];

            while ($index <= $endIndex) {
                $token = $tokens[$index];

                if ($index === $endIndex || (!$group && $token->equals(','))) {
                    if ($group && self::SORT_NONE !== $this->configuration['sort_algorithm']) {
                        // if group import, sort the items within the group definition

                        // figure out where the list of namespace parts within the group def. starts
                        $namespaceTokensCount = \count($namespaceTokens) - 1;
                        $namespace = '';
                        for ($k = 0; $k < $namespaceTokensCount; ++$k) {
                            if ($namespaceTokens[$k]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_OPEN)) {
                                $namespace .= '{';

                                break;
                            }

                            $namespace .= $namespaceTokens[$k]->getContent();
                        }

                        // fetch all parts, split up in an array of strings, move comments to the end
                        $parts = [];
                        $firstIndent = '';
                        $separator = ', ';
                        $lastIndent = '';

                        for ($k1 = $k + 1; $k1 < $namespaceTokensCount; ++$k1) {
                            $comment = '';
                            $namespacePart = '';
                            for ($k2 = $k1;; ++$k2) {
                                if ($namespaceTokens[$k2]->equalsAny([',', [CT::T_GROUP_IMPORT_BRACE_CLOSE]])) {
                                    break;
                                }

                                if ($namespaceTokens[$k2]->isComment()) {
                                    $comment .= $namespaceTokens[$k2]->getContent();

                                    continue;
                                }

                                // if there is any line ending inside the group import, it should be indented properly
                                if (
                                    '' === $firstIndent &&
                                    $namespaceTokens[$k2]->isWhitespace() &&
                                    false !== strpos($namespaceTokens[$k2]->getContent(), $lineEnding)
                                ) {
                                    $lastIndent = $lineEnding;
                                    $firstIndent = $lineEnding.$this->whitespacesConfig->getIndent();
                                    $separator = ','.$firstIndent;
                                }

                                $namespacePart .= $namespaceTokens[$k2]->getContent();
                            }

                            $namespacePart = trim($namespacePart);
                            $comment = trim($comment);
                            if ('' !== $comment) {
                                $namespacePart .= ' '.$comment;
                            }

                            $parts[] = $namespacePart;

                            $k1 = $k2;
                        }

                        $sortedParts = $parts;
                        sort($parts);

                        // check if the order needs to be updated, otherwise don't touch as we might change valid CS (to other valid CS).
                        if ($sortedParts === $parts) {
                            $namespace = Tokens::fromArray($namespaceTokens)->generateCode();
                        } else {
                            $namespace .= $firstIndent.implode($separator, $parts).$lastIndent.'}';
                        }
                    } else {
                        $namespace = Tokens::fromArray($namespaceTokens)->generateCode();
                    }

                    $indexes[$startIndex] = [
                        'namespace' => $namespace,
                        'startIndex' => $startIndex,
                        'endIndex' => $index - 1,
                        'importType' => $type,
                        'group' => $group,
                    ];

                    $originalIndexes[] = $startIndex;

                    if ($index === $endIndex) {
                        break;
                    }

                    $namespaceTokens = [];
                    $nextPartIndex = $tokens->getTokenNotOfKindSibling($index, 1, [[','], [T_WHITESPACE]]);
                    $startIndex = $nextPartIndex;
                    $index = $nextPartIndex;

                    continue;
                }

                $namespaceTokens[] = $token;
                ++$index;
            }
        }

        // Is sort types provided, sorting by groups and each group by algorithm
        if (null !== $this->configuration['imports_order']) {
            // Grouping indexes by import type.
            $groupedByTypes = [];
            foreach ($indexes as $startIndex => $item) {
                $groupedByTypes[$item['importType']][$startIndex] = $item;
            }

            // Sorting each group by algorithm.
            foreach ($groupedByTypes as $type => $indexes) {
                $groupedByTypes[$type] = $this->sortByAlgorithm($indexes);
            }

            // Ordering groups
            $sortedGroups = [];
            foreach ($this->configuration['imports_order'] as $type) {
                if (isset($groupedByTypes[$type]) && !empty($groupedByTypes[$type])) {
                    foreach ($groupedByTypes[$type] as $startIndex => $item) {
                        $sortedGroups[$startIndex] = $item;
                    }
                }
            }
            $indexes = $sortedGroups;
        } else {
            // Sorting only by algorithm
            $indexes = $this->sortByAlgorithm($indexes);
        }

        $index = -1;
        $usesOrder = [];

        // Loop trough the index but use original index order
        foreach ($indexes as $v) {
            $usesOrder[$originalIndexes[++$index]] = $v;
        }

        return $usesOrder;
    }
private function getNewOrder ( array $ uses , Tokens $ tokens ) { $ indexes = [ ] ; $ originalIndexes = [ ] ; $ lineEnding = $ this -> whitespacesConfig -> getLineEnding ( ) ; for ( $ i = \ count ( $ uses ) - 1 ; $ i >= 0 ; -- $ i ) { $ index = $ uses [ $ i ] ; $ startIndex = $ tokens -> getTokenNotOfKindSibling ( $ index + 1 , 1 , [ [ T_WHITESPACE ] ] ) ; $ endIndex = $ tokens -> getNextTokenOfKind ( $ startIndex , [ ';' , [ T_CLOSE_TAG ] ] ) ; $ previous = $ tokens -> getPrevMeaningfulToken ( $ endIndex ) ; $ group = $ tokens [ $ previous ] -> isGivenKind ( CT :: T_GROUP_IMPORT_BRACE_CLOSE ) ; if ( $ tokens [ $ startIndex ] -> isGivenKind ( CT :: T_CONST_IMPORT ) ) { $ type = self :: IMPORT_TYPE_CONST ; $ index = $ tokens -> getNextNonWhitespace ( $ startIndex ) ; } elseif ( $ tokens [ $ startIndex ] -> isGivenKind ( CT :: T_FUNCTION_IMPORT ) ) { $ type = self :: IMPORT_TYPE_FUNCTION ; $ index = $ tokens -> getNextNonWhitespace ( $ startIndex ) ; } else { $ type = self :: IMPORT_TYPE_CLASS ; $ index = $ startIndex ; } $ namespaceTokens = [ ] ; while ( $ index <= $ endIndex ) { $ token = $ tokens [ $ index ] ; if ( $ index === $ endIndex || ( ! $ group && $ token -> equals ( ',' ) ) ) { if ( $ group && self :: SORT_NONE !== $ this -> configuration [ 'sort_algorithm' ] ) { // if group import, sort the items within the group definition // figure out where the list of namespace parts within the group def. starts $ namespaceTokensCount = \ count ( $ namespaceTokens ) - 1 ; $ namespace = '' ; for ( $ k = 0 ; $ k < $ namespaceTokensCount ; ++ $ k ) { if ( $ namespaceTokens [ $ k ] -> isGivenKind ( CT :: T_GROUP_IMPORT_BRACE_OPEN ) ) { $ namespace .= '{' ; break ; } $ namespace .= $ namespaceTokens [ $ k ] -> getContent ( ) ; } // fetch all parts, split up in an array of strings, move comments to the end $ parts = [ ] ; $ firstIndent = '' ; $ separator = ', ' ; $ lastIndent = '' ; for ( $ k1 = $ k + 1 ; $ k1 < $ namespaceTokensCount ; ++ $ k1 ) { $ comment = '' ; $ namespacePart = '' ; for ( $ k2 = $ k1 ; ; ++ $ k2 ) { if ( $ namespaceTokens [ $ k2 ] -> equalsAny ( [ ',' , [ CT :: T_GROUP_IMPORT_BRACE_CLOSE ] ] ) ) { break ; } if ( $ namespaceTokens [ $ k2 ] -> isComment ( ) ) { $ comment .= $ namespaceTokens [ $ k2 ] -> getContent ( ) ; continue ; } // if there is any line ending inside the group import, it should be indented properly if ( '' === $ firstIndent && $ namespaceTokens [ $ k2 ] -> isWhitespace ( ) && false !== strpos ( $ namespaceTokens [ $ k2 ] -> getContent ( ) , $ lineEnding ) ) { $ lastIndent = $ lineEnding ; $ firstIndent = $ lineEnding . $ this -> whitespacesConfig -> getIndent ( ) ; $ separator = ',' . $ firstIndent ; } $ namespacePart .= $ namespaceTokens [ $ k2 ] -> getContent ( ) ; } $ namespacePart = trim ( $ namespacePart ) ; $ comment = trim ( $ comment ) ; if ( '' !== $ comment ) { $ namespacePart .= ' ' . $ comment ; } $ parts [ ] = $ namespacePart ; $ k1 = $ k2 ; } $ sortedParts = $ parts ; sort ( $ parts ) ; // check if the order needs to be updated, otherwise don't touch as we might change valid CS (to other valid CS). if ( $ sortedParts === $ parts ) { $ namespace = Tokens :: fromArray ( $ namespaceTokens ) -> generateCode ( ) ; } else { $ namespace .= $ firstIndent . implode ( $ separator , $ parts ) . $ lastIndent . '}' ; } } else { $ namespace = Tokens :: fromArray ( $ namespaceTokens ) -> generateCode ( ) ; } $ indexes [ $ startIndex ] = [ 'namespace' => $ namespace , 'startIndex' => $ startIndex , 'endIndex' => $ index - 1 , 'importType' => $ type , 'group' => $ group , ] ; $ originalIndexes [ ] = $ startIndex ; if ( $ index === $ endIndex ) { break ; } $ namespaceTokens = [ ] ; $ nextPartIndex = $ tokens -> getTokenNotOfKindSibling ( $ index , 1 , [ [ ',' ] , [ T_WHITESPACE ] ] ) ; $ startIndex = $ nextPartIndex ; $ index = $ nextPartIndex ; continue ; } $ namespaceTokens [ ] = $ token ; ++ $ index ; } } // Is sort types provided, sorting by groups and each group by algorithm if ( null !== $ this -> configuration [ 'imports_order' ] ) { // Grouping indexes by import type. $ groupedByTypes = [ ] ; foreach ( $ indexes as $ startIndex => $ item ) { $ groupedByTypes [ $ item [ 'importType' ] ] [ $ startIndex ] = $ item ; } // Sorting each group by algorithm. foreach ( $ groupedByTypes as $ type => $ indexes ) { $ groupedByTypes [ $ type ] = $ this -> sortByAlgorithm ( $ indexes ) ; } // Ordering groups $ sortedGroups = [ ] ; foreach ( $ this -> configuration [ 'imports_order' ] as $ type ) { if ( isset ( $ groupedByTypes [ $ type ] ) && ! empty ( $ groupedByTypes [ $ type ] ) ) { foreach ( $ groupedByTypes [ $ type ] as $ startIndex => $ item ) { $ sortedGroups [ $ startIndex ] = $ item ; } } } $ indexes = $ sortedGroups ; } else { // Sorting only by algorithm $ indexes = $ this -> sortByAlgorithm ( $ indexes ) ; } $ index = - 1 ; $ usesOrder = [ ] ; // Loop trough the index but use original index order foreach ( $ indexes as $ v ) { $ usesOrder [ $ originalIndexes [ ++ $ index ] ] = $ v ; } return $ usesOrder ; }
@param int[]  $uses
@param Tokens $tokens

@return array
@param int [] $uses @param Tokens $tokens