diff --git a/src/Psalm/Internal/Provider/FakeFileProvider.php b/src/Psalm/Internal/Provider/FakeFileProvider.php index 7cafa391b..d2ffb9910 100644 --- a/src/Psalm/Internal/Provider/FakeFileProvider.php +++ b/src/Psalm/Internal/Provider/FakeFileProvider.php @@ -57,12 +57,13 @@ class FakeFileProvider extends FileProvider /** * @param array $file_extensions + * @param null|callable(string):bool $directory_filter * * @return list */ - public function getFilesInDir(string $dir_path, array $file_extensions): array + public function getFilesInDir(string $dir_path, array $file_extensions, callable $directory_filter = null): array { - $file_paths = parent::getFilesInDir($dir_path, $file_extensions); + $file_paths = parent::getFilesInDir($dir_path, $file_extensions, $directory_filter); foreach ($this->fake_files as $file_path => $_) { if (strpos(strtolower($file_path), strtolower($dir_path)) === 0) { diff --git a/src/Psalm/Internal/Provider/FileProvider.php b/src/Psalm/Internal/Provider/FileProvider.php index ffbfb14f9..3f319ca13 100644 --- a/src/Psalm/Internal/Provider/FileProvider.php +++ b/src/Psalm/Internal/Provider/FileProvider.php @@ -2,7 +2,9 @@ namespace Psalm\Internal\Provider; use FilesystemIterator; +use RecursiveCallbackFilterIterator; use RecursiveDirectoryIterator; +use RecursiveIterator; use RecursiveIteratorIterator; use UnexpectedValueException; @@ -14,6 +16,8 @@ use function in_array; use function is_dir; use function strtolower; +use const DIRECTORY_SEPARATOR; + class FileProvider { /** @@ -113,10 +117,11 @@ class FileProvider /** * @param array $file_extensions + * @param null|callable(string):bool $directory_filter * * @return list */ - public function getFilesInDir(string $dir_path, array $file_extensions): array + public function getFilesInDir(string $dir_path, array $file_extensions, callable $directory_filter = null): array { $file_paths = []; @@ -125,6 +130,16 @@ class FileProvider FilesystemIterator::CURRENT_AS_PATHNAME | FilesystemIterator::SKIP_DOTS ); + if ($directory_filter !== null) { + $iterator = new RecursiveCallbackFilterIterator( + $iterator, + /** @param mixed $_ */ + function (string $current, $_, RecursiveIterator $iterator) use ($directory_filter): bool { + return !$iterator->hasChildren() || $directory_filter($current . DIRECTORY_SEPARATOR); + } + ); + } + /** @var RecursiveDirectoryIterator */ $iterator = new RecursiveIteratorIterator($iterator); $iterator->rewind();