|
@@ -19,9 +19,14 @@ use PhpCsFixer\Tokenizer\TokensAnalyzer;
|
|
|
/**
|
|
|
* @author Sebastiaan Stok <s.stok@rollerscapes.net>
|
|
|
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
|
|
+ * @author SpacePossum
|
|
|
*/
|
|
|
final class OrderedImportsFixer extends AbstractFixer
|
|
|
{
|
|
|
+ const IMPORT_TYPE_CLASS = 1;
|
|
|
+ const IMPORT_TYPE_CONST = 2;
|
|
|
+ const IMPORT_TYPE_FUNCTION = 3;
|
|
|
+
|
|
|
/**
|
|
|
* {@inheritdoc}
|
|
|
*/
|
|
@@ -39,25 +44,25 @@ final class OrderedImportsFixer extends AbstractFixer
|
|
|
$namespacesImports = $tokensAnalyzer->getImportUseIndexes(true);
|
|
|
$usesOrder = array();
|
|
|
|
|
|
- if (!count($namespacesImports)) {
|
|
|
+ if (0 === count($namespacesImports)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ $usesOrder = array();
|
|
|
foreach ($namespacesImports as $uses) {
|
|
|
- $uses = array_reverse($uses);
|
|
|
- $usesOrder = array_replace($usesOrder, $this->getNewOrder($uses, $tokens));
|
|
|
+ $usesOrder = array_replace($usesOrder, $this->getNewOrder(array_reverse($uses), $tokens));
|
|
|
}
|
|
|
|
|
|
$usesOrder = array_reverse($usesOrder, true);
|
|
|
$mapStartToEnd = array();
|
|
|
|
|
|
foreach ($usesOrder as $use) {
|
|
|
- $mapStartToEnd[$use[1]] = $use[2];
|
|
|
+ $mapStartToEnd[$use['startIndex']] = $use['endIndex'];
|
|
|
}
|
|
|
|
|
|
// Now insert the new tokens, starting from the end
|
|
|
foreach ($usesOrder as $index => $use) {
|
|
|
- $declarationTokens = Tokens::fromCode('<?php use '.$use[0].';');
|
|
|
+ $declarationTokens = Tokens::fromCode('<?php use '.$use['namespace'].';');
|
|
|
$declarationTokens->clearRange(0, 2); // clear `<?php use `
|
|
|
$declarationTokens[count($declarationTokens) - 1]->clear(); // clear `;`
|
|
|
$declarationTokens->clearEmptyTokens();
|
|
@@ -95,14 +100,18 @@ final class OrderedImportsFixer extends AbstractFixer
|
|
|
*/
|
|
|
public static function sortingCallBack(array $first, array $second)
|
|
|
{
|
|
|
- $a = trim(preg_replace('%/\*(.*)\*/%s', '', $first[0]));
|
|
|
- $b = trim(preg_replace('%/\*(.*)\*/%s', '', $second[0]));
|
|
|
+ if ($first['importType'] !== $second['importType']) {
|
|
|
+ return $first['importType'] > $second['importType'] ? 1 : -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ $firstNamespace = trim(preg_replace('%/\*(.*)\*/%s', '', $first['namespace']));
|
|
|
+ $secondNamespace = trim(preg_replace('%/\*(.*)\*/%s', '', $second['namespace']));
|
|
|
|
|
|
// Replace backslashes by spaces before sorting for correct sort order
|
|
|
- $a = str_replace('\\', ' ', $a);
|
|
|
- $b = str_replace('\\', ' ', $b);
|
|
|
+ $firstNamespace = str_replace('\\', ' ', $firstNamespace);
|
|
|
+ $secondNamespace = str_replace('\\', ' ', $secondNamespace);
|
|
|
|
|
|
- return strcasecmp($a, $b);
|
|
|
+ return strcasecmp($firstNamespace, $secondNamespace);
|
|
|
}
|
|
|
|
|
|
private function getNewOrder(array $uses, Tokens $tokens)
|
|
@@ -113,8 +122,18 @@ final class OrderedImportsFixer extends AbstractFixer
|
|
|
$originalIndexes = array();
|
|
|
|
|
|
foreach ($uses as $index) {
|
|
|
- $endIndex = $tokens->getNextTokenOfKind($index, array(';'));
|
|
|
$startIndex = $tokens->getTokenNotOfKindSibling($index + 1, 1, array(array(T_WHITESPACE)));
|
|
|
+ $endIndex = $tokens->getNextTokenOfKind($startIndex, array(';', array(T_CLOSE_TAG)));
|
|
|
+ $previous = $tokens->getPrevMeaningfulToken($endIndex);
|
|
|
+
|
|
|
+ $group = $tokens[$previous]->equals('}');
|
|
|
+ if ($tokens[$startIndex]->isGivenKind(array(CT_CONST_IMPORT))) {
|
|
|
+ $type = self::IMPORT_TYPE_CONST;
|
|
|
+ } elseif ($tokens[$startIndex]->isGivenKind(array(CT_FUNCTION_IMPORT))) {
|
|
|
+ $type = self::IMPORT_TYPE_FUNCTION;
|
|
|
+ } else {
|
|
|
+ $type = self::IMPORT_TYPE_CLASS;
|
|
|
+ }
|
|
|
|
|
|
$namespace = '';
|
|
|
$index = $startIndex;
|
|
@@ -122,8 +141,14 @@ final class OrderedImportsFixer extends AbstractFixer
|
|
|
while ($index <= $endIndex) {
|
|
|
$token = $tokens[$index];
|
|
|
|
|
|
- if ($index === $endIndex || $token->equals(',')) {
|
|
|
- $indexes[$startIndex] = array($namespace, $startIndex, $index - 1);
|
|
|
+ if ($index === $endIndex || (!$group && $token->equals(','))) {
|
|
|
+ $indexes[$startIndex] = array(
|
|
|
+ 'namespace' => $namespace,
|
|
|
+ 'startIndex' => $startIndex,
|
|
|
+ 'endIndex' => $index - 1,
|
|
|
+ 'importType' => $type,
|
|
|
+ );
|
|
|
+
|
|
|
$originalIndexes[] = $startIndex;
|
|
|
|
|
|
if ($index === $endIndex) {
|
|
@@ -145,13 +170,12 @@ final class OrderedImportsFixer extends AbstractFixer
|
|
|
|
|
|
uasort($indexes, 'self::sortingCallBack');
|
|
|
|
|
|
- $i = -1;
|
|
|
-
|
|
|
+ $index = -1;
|
|
|
$usesOrder = array();
|
|
|
|
|
|
// Loop trough the index but use original index order
|
|
|
foreach ($indexes as $v) {
|
|
|
- $usesOrder[$originalIndexes[++$i]] = $v;
|
|
|
+ $usesOrder[$originalIndexes[++$index]] = $v;
|
|
|
}
|
|
|
|
|
|
return $usesOrder;
|