Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoUnneededImportAliasFixer - Introduction #6267

Merged
merged 1 commit into from Feb 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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();