1
0
Fork 0

Add globWorkspace helper

pull/136/head
Felix Becker 2016-11-03 11:52:51 +01:00
parent 0060045a1e
commit b9aeea2523
3 changed files with 37 additions and 60 deletions

View File

@ -18,6 +18,8 @@ use function Sabre\Event\coroutine;
use Exception;
use Throwable;
use Generator;
use Webmozart\Glob\Iterator\GlobIterator;
use Webmozart\PathUril\Path;
class LanguageServer extends AdvancedJsonRpc\Dispatcher
{
@ -182,32 +184,15 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
private function indexProject()
{
return coroutine(function () {
if ($this->clientCapabilities->xglobProvider) {
$textDocuments = yield $this->client->workspace->xglob('**/*.php');
$uris = array_map(function ($textDocument) {
return $textDocument->uri;
}, $textDocuments);
} else {
$uris = array_map(function ($path) {
return pathToUri($path);
}, findFilesRecursive($this->rootPath, '/^.+\.php$/i'));
}
$textDocuments = yield $this->globWorkspace('**/*.php');
$count = count($uris);
$startTime = microtime(true);
foreach ($uris as $i => $uri) {
foreach ($textDocuments as $i => $textDocument) {
// Give LS to the chance to handle requests while indexing
Loop\tick();
try {
$shortName = substr(uriToPath($uri), strlen($this->rootPath) + 1);
} catch (Exception $e) {
$shortName = $uri;
}
$this->client->window->logMessage(MessageType::INFO, "Parsing file $i/$count: $shortName.");
$this->client->window->logMessage(MessageType::INFO, "Parsing file $i/$count: {$textDocument->uri}");
try {
$this->project->loadDocument($uri);
} catch (Exception $e) {
@ -220,4 +205,36 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
$this->client->window->logMessage(MessageType::INFO, "All PHP files parsed in $duration seconds. $mem MiB allocated.");
});
}
/**
* Returns all files matching a glob pattern.
* If the client does not support workspace/xglob, it falls back to globbing the file system directly.
*
* @param string $pattern
* @return Promise <TextDocumentIdentifier[]>
*/
private function globWorkspace(string $pattern): Promise
{
if ($this->clientCapabilities->xglobProvider) {
// Use xglob request
return $this->client->workspace->xglob($pattern);
} else {
// Use the file system
$promise = new Promise;
$textDocuments = [];
$pattern = Path::makeAbsolute($pattern, $this->rootPath);
$iterator = new GlobIterator($pattern);
$next = function () use ($iterator, &$textDocuments, $promise, &$next) {
if (!$iterator->valid()) {
$promise->resolve($textDocuments);
return;
}
$textDocuments[] = new TextDocumentIdentifier(pathToUri($iterator->current()));
$iterator->next();
Loop\setTimeout($next, 0);
};
Loop\setTimeout($next, 0);
return $promise;
}
}
}

View File

@ -5,25 +5,6 @@ namespace LanguageServer;
use InvalidArgumentException;
/**
* Recursively Searches files with matching filename, starting at $path.
*
* @param string $path
* @param string $pattern
* @return array
*/
function findFilesRecursive(string $path, string $pattern): array
{
$dir = new \RecursiveDirectoryIterator($path);
$ite = new \RecursiveIteratorIterator($dir);
$files = new \RegexIterator($ite, $pattern, \RegexIterator::GET_MATCH);
$fileList = [];
foreach ($files as $file) {
$fileList = array_merge($fileList, $file);
}
return $fileList;
}
/**
* Transforms an absolute file path into a URI as used by the language server protocol.
*

View File

@ -1,21 +0,0 @@
<?php
declare(strict_types = 1);
namespace LanguageServer\Tests\Utils;
use PHPUnit\Framework\TestCase;
class RecursiveFileSearchTest extends TestCase
{
public function testFilesAreFound()
{
$path = realpath(__DIR__ . '/../../fixtures/recursive');
$files = \LanguageServer\findFilesRecursive($path, '/.+\.txt/');
sort($files);
$this->assertEquals([
$path . DIRECTORY_SEPARATOR . 'a.txt',
$path . DIRECTORY_SEPARATOR . 'search' . DIRECTORY_SEPARATOR . 'b.txt',
$path . DIRECTORY_SEPARATOR . 'search' . DIRECTORY_SEPARATOR . 'here' . DIRECTORY_SEPARATOR . 'c.txt',
], $files);
}
}