mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-29 11:33:33 +01:00
Add 'exclude_paths' option to exclude files or directories [closes #609]
This commit is contained in:
parent
8efe81b6fd
commit
5817e17234
@ -64,6 +64,15 @@ parameters:
|
||||
- '%kernel.project_dir%/vendor/project-without-composer'
|
||||
```
|
||||
|
||||
You can also exclude files or directories - use regex or [fnmatch](http://php.net/manual/en/function.fnmatch.php):
|
||||
|
||||
```yaml
|
||||
# rector.yml
|
||||
parameters:
|
||||
exclude_paths:
|
||||
- '*/src/*/Tests/*'
|
||||
```
|
||||
|
||||
## How to Reconstruct your Code
|
||||
|
||||
### A. Prepared Sets
|
||||
|
@ -41,6 +41,7 @@ parameters:
|
||||
- '#Access to an undefined property PhpParser\\Node\\Expr\\Error\|PhpParser\\Node\\Expr\\Variable::\$name#'
|
||||
|
||||
# SplFileInfo::getRealPath() false positive
|
||||
- '#Parameter \#1 \$pattern of function fnmatch expects string, string\|false given#'
|
||||
- '#Parameter \#1 \$file of function file_put_contents expects string, string\|false given#'
|
||||
- '#Parameter \#1 \$filePath of method Rector\\Parser\\Parser::parseFile\(\) expects string, string\|false given#'
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Rector\FileSystem;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use Rector\Exception\FileSystem\DirectoryNotFoundException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
@ -13,6 +14,19 @@ final class FilesFinder
|
||||
*/
|
||||
private $fileInfosBySourceAndSuffixes = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $excludePaths = [];
|
||||
|
||||
/**
|
||||
* @param string[] $excludePaths
|
||||
*/
|
||||
public function __construct(array $excludePaths)
|
||||
{
|
||||
$this->excludePaths = $excludePaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $source
|
||||
* @param string[] $suffixes
|
||||
@ -61,7 +75,14 @@ final class FilesFinder
|
||||
->exclude(['examples', 'Examples', 'stubs', 'Stubs', 'fixtures', 'Fixtures', 'polyfill', 'Polyfill'])
|
||||
->notName('*polyfill*');
|
||||
|
||||
return iterator_to_array($finder->getIterator());
|
||||
$splFileInfos = iterator_to_array($finder->getIterator());
|
||||
if (! $this->excludePaths) {
|
||||
return $splFileInfos;
|
||||
}
|
||||
|
||||
// to overcome magic behavior: https://github.com/symfony/symfony/pull/26396/files
|
||||
/** @var SplFileInfo[] $splFileInfos */
|
||||
return $this->filterOutFilesByPatterns($splFileInfos, $this->excludePaths);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,4 +108,30 @@ final class FilesFinder
|
||||
|
||||
return '#\.(' . $suffixesPattern . ')$#';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SplFileInfo[] $splFileInfos
|
||||
* @param string[] $patternsToExclude
|
||||
* @return SplFileInfo[]
|
||||
*/
|
||||
private function filterOutFilesByPatterns(array $splFileInfos, array $patternsToExclude): array
|
||||
{
|
||||
$filteredFiles = [];
|
||||
|
||||
foreach ($splFileInfos as $relativePath => $splFileInfo) {
|
||||
foreach ($patternsToExclude as $patternToExclude) {
|
||||
if (Strings::match($splFileInfo->getRealPath(), $patternToExclude)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fnmatch($splFileInfo->getRealPath(), $patternToExclude)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filteredFiles[$relativePath] = $splFileInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredFiles;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ imports:
|
||||
- { resource: 'external-services.yml' }
|
||||
|
||||
parameters:
|
||||
excluded_paths: []
|
||||
exclude_paths: []
|
||||
autoload_directories: []
|
||||
autoload_files: []
|
||||
|
29
tests/AbstractConfigurableContainerAwareTestCase.php
Normal file
29
tests/AbstractConfigurableContainerAwareTestCase.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Rector\DependencyInjection\ContainerFactory;
|
||||
|
||||
abstract class AbstractConfigurableContainerAwareTestCase extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructs a test case with the given name.
|
||||
*
|
||||
* @param mixed[] $data
|
||||
*/
|
||||
public function __construct(?string $name = null, array $data = [], string $dataName = '')
|
||||
{
|
||||
$this->container = (new ContainerFactory())->createWithConfig($this->provideConfig());
|
||||
|
||||
parent::__construct($name, $data, $dataName);
|
||||
}
|
||||
|
||||
abstract protected function provideConfig(): string;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\FileSystem\FilesFinder\ExcludePaths;
|
||||
|
||||
use Rector\FileSystem\FilesFinder;
|
||||
use Rector\Tests\AbstractConfigurableContainerAwareTestCase;
|
||||
|
||||
final class ExcludePathsTest extends AbstractConfigurableContainerAwareTestCase
|
||||
{
|
||||
/**
|
||||
* @var FilesFinder
|
||||
*/
|
||||
private $filesFinder;
|
||||
|
||||
public function testShouldFail(): void
|
||||
{
|
||||
$this->filesFinder = $this->container->get(FilesFinder::class);
|
||||
$splFileInfos = $this->filesFinder->findInDirectoriesAndFiles([__DIR__ . '/Source'], ['php']);
|
||||
|
||||
$this->assertCount(1, $splFileInfos);
|
||||
}
|
||||
|
||||
protected function provideConfig(): string
|
||||
{
|
||||
return __DIR__ . '/config/config-with-excluded-paths.yml';
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Configuration\ExcludePaths\ShouldBeExcludedSource;
|
||||
|
||||
final class FileWithMissingClass extends ThisClassIsNotHere
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Configuration\ExcludePaths\Source;
|
||||
|
||||
final class ThisShouldBeHere
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
parameters:
|
||||
excluded_paths:
|
||||
- '*/ShouldBeExcluded/*'
|
Loading…
x
Reference in New Issue
Block a user