Skip to content

Commit

Permalink
feature #6267 NoUnneededImportAliasFixer - Introduction (SpacePossum)
Browse files Browse the repository at this point in the history
This PR was merged into the master branch.

Discussion
----------

NoUnneededImportAliasFixer - Introduction

replaces #4498

Commits
-------

8ea666d NoUnneededImportAliasFixer - Introduction
  • Loading branch information
SpacePossum committed Feb 5, 2022
2 parents 13f0d2a + 8ea666d commit 248a56b
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 1 deletion.
7 changes: 7 additions & 0 deletions doc/list.rst
Expand Up @@ -1586,6 +1586,13 @@ List of Available Rules
Part of rule sets `@PHP80Migration:risky <./ruleSets/PHP80MigrationRisky.rst>`_ `@PhpCsFixer:risky <./ruleSets/PhpCsFixerRisky.rst>`_ `@Symfony:risky <./ruleSets/SymfonyRisky.rst>`_

`Source PhpCsFixer\\Fixer\\ClassNotation\\NoUnneededFinalMethodFixer <./../src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php>`_
- `no_unneeded_import_alias <./rules/import/no_unneeded_import_alias.rst>`_

Imports should not be aliased as the same name.

Part of rule sets `@PhpCsFixer <./ruleSets/PhpCsFixer.rst>`_ `@Symfony <./ruleSets/Symfony.rst>`_

`Source PhpCsFixer\\Fixer\\Import\\NoUnneededImportAliasFixer <./../src/Fixer/Import/NoUnneededImportAliasFixer.php>`_
- `no_unreachable_default_argument_value <./rules/function_notation/no_unreachable_default_argument_value.rst>`_

In function arguments there must not be arguments with default values before non-default ones.
Expand Down
1 change: 1 addition & 0 deletions doc/ruleSets/Symfony.rst
Expand Up @@ -75,6 +75,7 @@ Rules
- `no_unneeded_curly_braces <./../rules/control_structure/no_unneeded_curly_braces.rst>`_
config:
``['namespaces' => true]``
- `no_unneeded_import_alias <./../rules/import/no_unneeded_import_alias.rst>`_
- `no_unset_cast <./../rules/cast_notation/no_unset_cast.rst>`_
- `no_unused_imports <./../rules/import/no_unused_imports.rst>`_
- `no_whitespace_before_comma_in_array <./../rules/array_notation/no_whitespace_before_comma_in_array.rst>`_
Expand Down
30 changes: 30 additions & 0 deletions doc/rules/import/no_unneeded_import_alias.rst
@@ -0,0 +1,30 @@
=================================
Rule ``no_unneeded_import_alias``
=================================

Imports should not be aliased as the same name.

Examples
--------

Example #1
~~~~~~~~~~

.. code-block:: diff
--- Original
+++ New
<?php
-use A\B\Foo as Foo;
+use A\B\Foo ;
Rule sets
---------

The rule is part of the following rule sets:

@PhpCsFixer
Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_unneeded_import_alias`` rule.

@Symfony
Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_unneeded_import_alias`` rule.
3 changes: 3 additions & 0 deletions doc/rules/index.rst
Expand Up @@ -386,6 +386,9 @@ Import
- `no_leading_import_slash <./import/no_leading_import_slash.rst>`_

Remove leading slashes in ``use`` clauses.
- `no_unneeded_import_alias <./import/no_unneeded_import_alias.rst>`_

Imports should not be aliased as the same name.
- `no_unused_imports <./import/no_unused_imports.rst>`_

Unused ``use`` statements must be removed.
Expand Down
97 changes: 97 additions & 0 deletions src/Fixer/Import/NoUnneededImportAliasFixer.php
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace PhpCsFixer\Fixer\Import;

use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Tokens;

final class NoUnneededImportAliasFixer extends AbstractFixer
{
/**
* {@inheritdoc}
*/
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Imports should not be aliased as the same name.',
[new CodeSample("<?php\nuse A\\B\\Foo as Foo;\n")]
);
}

/**
* {@inheritdoc}
*/
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isAllTokenKindsFound([T_USE, T_AS]);
}

/**
* {@inheritdoc}
*
* Must run before NoSinglelineWhitespaceBeforeSemicolonsFixer.
*/
public function getPriority(): int
{
return 1;
}

/**
* {@inheritdoc}
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
for ($index = \count($tokens) - 1; 0 <= $index; --$index) {
if (!$tokens[$index]->isGivenKind(T_AS)) {
continue;
}

$aliasIndex = $tokens->getNextMeaningfulToken($index);

if (!$tokens[$aliasIndex]->isGivenKind(T_STRING)) {
continue;
}

$importIndex = $tokens->getPrevMeaningfulToken($index);

if (!$tokens[$importIndex]->isGivenKind(T_STRING)) {
continue;
}

if ($tokens[$importIndex]->getContent() !== $tokens[$aliasIndex]->getContent()) {
continue;
}

do {
$importIndex = $tokens->getPrevMeaningfulToken($importIndex);
} while ($tokens[$importIndex]->isGivenKind([T_NS_SEPARATOR, T_STRING, T_AS]) || $tokens[$importIndex]->equals(','));

if ($tokens[$importIndex]->isGivenKind([CT::T_FUNCTION_IMPORT, CT::T_CONST_IMPORT])) {
$importIndex = $tokens->getPrevMeaningfulToken($importIndex);
}

if (!$tokens[$importIndex]->isGivenKind([T_USE, CT::T_GROUP_IMPORT_BRACE_OPEN])) {
continue;
}

$tokens->clearTokenAndMergeSurroundingWhitespace($aliasIndex);
$tokens->clearTokenAndMergeSurroundingWhitespace($index);
}
}
}
2 changes: 1 addition & 1 deletion src/Fixer/Import/SingleImportPerStatementFixer.php
Expand Up @@ -144,7 +144,7 @@ private function getGroupStatements(Tokens $tokens, string $groupPrefix, int $gr
if ($token->isWhitespace()) {
$j = $tokens->getNextMeaningfulToken($i);

if ($tokens[$j]->equals([T_AS])) {
if ($tokens[$j]->isGivenKind(T_AS)) {
$statement .= ' as ';
$i += 2;
} elseif ($tokens[$j]->isGivenKind(CT::T_FUNCTION_IMPORT)) {
Expand Down
1 change: 1 addition & 0 deletions src/RuleSet/Sets/SymfonySet.php
Expand Up @@ -118,6 +118,7 @@ public function getRules(): array
'no_unneeded_curly_braces' => [
'namespaces' => true,
],
'no_unneeded_import_alias' => true,
'no_unset_cast' => true,
'no_unused_imports' => true,
'no_whitespace_before_comma_in_array' => true,
Expand Down
3 changes: 3 additions & 0 deletions tests/AutoReview/FixerFactoryTest.php
Expand Up @@ -553,6 +553,9 @@ private static function getFixersPriorityGraph(): array
'return_assignment',
'simplified_if_return',
],
'no_unneeded_import_alias' => [
'no_singleline_whitespace_before_semicolons',
],
'no_unset_cast' => [
'binary_operator_spaces',
],
Expand Down
109 changes: 109 additions & 0 deletions tests/Fixer/Import/NoUnneededImportAliasFixerTest.php
@@ -0,0 +1,109 @@
<?php

declare(strict_types=1);

/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace PhpCsFixer\Tests\Fixer\Import;

use PhpCsFixer\Tests\Test\AbstractFixerTestCase;

/**
* @internal
*
* @covers \PhpCsFixer\Fixer\Import\NoUnneededImportAliasFixer
*/
final class NoUnneededImportAliasFixerTest extends AbstractFixerTestCase
{
/**
* @dataProvider provideFixCases
*/
public function testFix(string $expected, ?string $input = null): void
{
$this->doTest($expected, $input);
}

public function provideFixCases(): iterable
{
yield [
'<?php use some\ns\{ClassA, ClassB, ClassC };',
'<?php use some\ns\{ClassA, ClassB, ClassC as ClassC};',
];

yield [
'<?php
use A\B\C , D\E\F as G;
use const X\Y\Z as Z1, U\V\W ;
use function U\V\W\FX , U\V\W\FY ;
',
'<?php
use A\B\C as C, D\E\F as G;
use const X\Y\Z as Z1, U\V\W as W;
use function U\V\W\FX as FX, U\V\W\FY as FY;
',
];

yield [
'<?php
use F ;
use X as x;
use const CA ;
use function FW ;
',
'<?php
use F as F;
use X as x;
use const CA as CA;
use function FW as FW;
',
];

yield [
'<?php
use /* 1 */\F ;
use const \CA/* 2 */ /* 3 */;
use /* 4 */ function/* 5 */ \FW /* 6 */ /* 7 */ ;
',
'<?php
use /* 1 */\F as F;
use const \CA/* 2 */ as CA/* 3 */;
use /* 4 */ function/* 5 */ \FW /* 6 */ as /* 7 */ FW;
',
];

yield [
'<?php
use \F\B\C ;
use const \X\Y\CA ;
use function \U\V\FW ;
',
'<?php
use \F\B\C as C;
use const \X\Y\CA as CA;
use function \U\V\FW as FW;
',
];

yield [
'<?php use A\B ?> X <?php use C\D; use E\F ?>',
'<?php use A\B as B ?> X <?php use C\D; use E\F as F ?>',
];

yield [
'<?php use A\B ?>',
'<?php use A\B as B ?>',
];

yield [
'<?php foreach ($a as $a) {}',
];
}
}
@@ -0,0 +1,17 @@
--TEST--
Integration of fixers: no_unneeded_import_alias,no_singleline_whitespace_before_semicolons.
--RULESET--
{"no_unneeded_import_alias": true, "no_singleline_whitespace_before_semicolons": true}
--EXPECT--
<?php

use function U\V\W\FY;

FY();

--INPUT--
<?php

use function U\V\W\FY as FY;

FY();

0 comments on commit 248a56b

Please sign in to comment.