From 3fc105717d8091931aae4d4056fb5a468fb5bf97 Mon Sep 17 00:00:00 2001 From: Carl Kittelberger Date: Mon, 13 Jan 2020 16:52:36 +0100 Subject: [PATCH] Implement existing fix from https://github.com/felixfbecker/php-language-server/issues/462#issuecomment-546696984. --- src/FilesFinder/FileSystemFilesFinder.php | 3 +- src/FilesFinder/GlobIterator.php | 84 +++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 src/FilesFinder/GlobIterator.php diff --git a/src/FilesFinder/FileSystemFilesFinder.php b/src/FilesFinder/FileSystemFilesFinder.php index a26b5d8..44576f3 100644 --- a/src/FilesFinder/FileSystemFilesFinder.php +++ b/src/FilesFinder/FileSystemFilesFinder.php @@ -3,7 +3,6 @@ declare(strict_types = 1); namespace LanguageServer\FilesFinder; -use Webmozart\Glob\Iterator\GlobIterator; use Sabre\Event\Promise; use function Sabre\Event\coroutine; use function LanguageServer\{pathToUri, timeout}; @@ -23,7 +22,7 @@ class FileSystemFilesFinder implements FilesFinder $uris = []; foreach (new GlobIterator($glob) as $path) { // Exclude any directories that also match the glob pattern - if (!is_dir($path)) { + if (!is_dir($path) || !is_readable($path)) { $uris[] = pathToUri($path); } diff --git a/src/FilesFinder/GlobIterator.php b/src/FilesFinder/GlobIterator.php new file mode 100644 index 0000000..4362104 --- /dev/null +++ b/src/FilesFinder/GlobIterator.php @@ -0,0 +1,84 @@ + + * + * @see Glob + */ +class GlobIterator extends IteratorIterator +{ + /** + * Creates a new iterator. + * + * @param string $glob The glob pattern. + * @param int $flags A bitwise combination of the flag constants in + * {@link Glob}. + */ + public function __construct($glob, $flags = 0) + { + $basePath = Glob::getBasePath($glob, $flags); + if (!Glob::isDynamic($glob) && file_exists($glob)) { + // If the glob is a file path, return that path + $innerIterator = new ArrayIterator(array($glob)); + } elseif (is_dir($basePath)) { + // Use the system's much more efficient glob() function where we can + if ( + // glob() does not support /**/ + false === strpos($glob, '/**/') && + // glob() does not support stream wrappers + false === strpos($glob, '://') && + // glob() does not support [^...] on Windows + ('\\' !== DIRECTORY_SEPARATOR || false === strpos($glob, '[^')) + ) { + $results = glob($glob, GLOB_BRACE); + + // $results may be empty or false if $glob is invalid + if (empty($results)) { + // Parse glob and provoke errors if invalid + Glob::toRegEx($glob); + + // Otherwise return empty result set + $innerIterator = new EmptyIterator(); + } else { + $innerIterator = new ArrayIterator($results); + } + } else { + // Otherwise scan the glob's base directory for matches + $innerIterator = new GlobFilterIterator( + $glob, + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator( + $basePath, + RecursiveDirectoryIterator::CURRENT_AS_PATHNAME, + RecursiveDirectoryIterator::SKIP_DOTS + ), + RecursiveIteratorIterator::SELF_FIRST, + RecursiveIteratorIterator::CATCH_GET_CHILD + ), + GlobFilterIterator::FILTER_VALUE, + $flags + ); + } + } else { + // If the glob's base directory does not exist, return nothing + $innerIterator = new EmptyIterator(); + } + + parent::__construct($innerIterator); + } +}