Skip to content

Commit

Permalink
Add new option for auto importing names (#764)
Browse files Browse the repository at this point in the history
* Add new option for auto importing names

- In order to apply the Option::AUTO_IMPORT_NAMES only on those files which are really changed by a rector we introduce this new option

* [ci-review] Rector Rectify

* Update packages/PostRector/Rector/NameImportingPostRector.php

Co-authored-by: Abdul Malik Ikhsan <samsonasik@gmail.com>

* [ci-review] Rector Rectify

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Abdul Malik Ikhsan <samsonasik@gmail.com>
  • Loading branch information
3 people committed Sep 16, 2021
1 parent e22645d commit 0315a82
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 2 deletions.
12 changes: 11 additions & 1 deletion build/target-repository/docs/auto_import_names.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Auto Import Names

Rector works with all class names as fully qualified by default, so it know the exact types. In most coding standard, that's not desired behavior, because short version with `use` statement is preferred:
Rector works with all class names as fully qualified by default, so it knows the exact types. In most coding standard, that's not desired behavior, because short version with `use` statement is preferred:

```diff
-$object = new \App\Some\Namespace\SomeClass();
Expand Down Expand Up @@ -48,6 +48,16 @@ Do you want to keep those?
$parameters->set(Option::IMPORT_SHORT_CLASSES, false);
```

<br>

If you have set Option::AUTO_IMPORT_NAMES to true, rector is applying this to every analyzed file, even if no real change by a rector was applied to the file.
The reason is that a so-called post rector is responsible for this, namely the NameImportingPostRector.
If you like to apply the Option::AUTO_IMPORT_NAMES only for real changed files, you can configure this.

```php
$parameters->set(Option::APPLY_AUTO_IMPORT_NAMES_ON_CHANGED_FILES_ONLY, true);
```

## How to Remove Unused Imports?

To remove imports, use [ECS](github.com/symplify/easy-coding-standard) with [`NoUnusedImportsFixer`](https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/2.18/doc/rules/import/no_unused_imports.rst) rule:
Expand Down
20 changes: 19 additions & 1 deletion packages/PostRector/Rector/NameImportingPostRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,28 @@ public function enterNode(Node $node): ?Node
return null;
}

$file = $this->currentFileProvider->getFile();

if ($node instanceof Name) {
$file = $this->currentFileProvider->getFile();
if (! $file instanceof File) {
return null;
}

if (! $this->shouldApply($file)) {
return null;
}

return $this->processNodeName($node, $file);
}

if (! $this->parameterProvider->provideBoolParameter(Option::IMPORT_DOC_BLOCKS)) {
return null;
}

if ($file instanceof File && ! $this->shouldApply($file)) {
return null;
}

$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
$this->docBlockNameImporter->importNames($phpDocInfo->getPhpDocNode(), $node);

Expand Down Expand Up @@ -128,4 +137,13 @@ private function shouldImportName(Name $name, File $file, array $currentUses): b

return $this->reflectionProvider->hasFunction(new Name($name->getLast()), null);
}

private function shouldApply(File $file): bool
{
if (! $this->parameterProvider->provideBoolParameter(Option::APPLY_AUTO_IMPORT_NAMES_ON_CHANGED_FILES_ONLY)) {
return true;
}

return $file->hasContentChanged();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

/**
* @see \Rector\PostRector\Rector\NameImportingPostRector
*/
final class AutoImportNamesOnlyOnChangedFilesTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}

/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/FixtureNameImportingOnChangedFiles');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/import_only_on_changed_files_config.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector\FixtureNameImportingOnChangedFiles;

class AutoImportNamesOnChangedFile
{
/**
* @var \Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source\NormalParamClass
*/
private $some;

public function __construct(\Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source\NormalParamClass $some)
{
$this->some = $some;
}
}
?>
-----
<?php

namespace Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector\FixtureNameImportingOnChangedFiles;

use Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source\NormalReturnClass;
class AutoImportNamesOnChangedFile
{
/**
* @var NormalReturnClass
*/
private $some;

public function __construct(NormalReturnClass $some)
{
$this->some = $some;
}
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector\FixtureNameImportingOnChangedFiles;

class SkipAutoImportNameNoChange
{
/**
* @var \SomeAnother\AnotherClass
*/
public $some;

public function __construct(\SomeAnother\AnotherClass $some)
{
$this->some = $some;
}
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

use Rector\Core\Configuration\Option;
use Rector\Renaming\Rector\Name\RenameClassRector;

use Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source\NormalParamClass;
use Rector\Tests\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source\NormalReturnClass;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
$parameters->set(Option::IMPORT_DOC_BLOCKS, true);
$parameters->set(Option::APPLY_AUTO_IMPORT_NAMES_ON_CHANGED_FILES_ONLY, true);

$services = $containerConfigurator->services();

$services->set(RenameClassRector::class)
->call('configure', [[
RenameClassRector::OLD_TO_NEW_CLASSES => [
NormalParamClass::class => NormalReturnClass::class,
],
]]);
};
5 changes: 5 additions & 0 deletions src/Configuration/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,9 @@ final class Option
* @var string
*/
public const OUTPUT_FORMAT_SHORT = 'o';

/**
* @var string
*/
public const APPLY_AUTO_IMPORT_NAMES_ON_CHANGED_FILES_ONLY = 'apply_auto_import_names_on_changed_files_only';
}
5 changes: 5 additions & 0 deletions src/ValueObject/Application/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ public function changeFileContent(string $newFileContent): void
$this->hasChanged = true;
}

public function hasContentChanged(): bool
{
return $this->fileContent !== $this->originalFileContent;
}

public function getOriginalFileContent(): string
{
return $this->originalFileContent;
Expand Down

0 comments on commit 0315a82

Please sign in to comment.