1
0
Fork 0

Add FilesFinder

pull/209/head
Felix Becker 2016-12-06 16:56:53 +01:00
parent ebd1cc6133
commit 164c4589e4
4 changed files with 111 additions and 32 deletions

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types = 1);
namespace LanguageServer\ContentRetriever;
use LanguageServer\LanguageClient;
use Sabre\Event\Promise;
/**
* Retrieves file content from the client through a textDocument/xcontent request
*/
class ClientFilesFinder implements FilesFinder
{
/**
* @var LanguageClient
*/
private $client;
/**
* @param LanguageClient $client
*/
public function __construct(LanguageClient $client)
{
$this->client = $client;
}
/**
* Returns all files in the workspace that match a glob.
* If the client does not support workspace/files, it falls back to searching the file system directly.
*
* @param string $glob
* @return Promise <string[]> The URIs
*/
private function find(string $glob): Promise
{
return $this->client->workspace->xfiles()->then(function (array $textDocuments) {
$uris = [];
foreach ($textDocuments as $textDocument) {
$path = Uri\parse($textDocument->uri)['path'];
if (Glob::match($path, $pattern)) {
$uris[] = $textDocument->uri;
}
}
return $uris;
});
}
}

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types = 1);
namespace LanguageServer\FilesFinder;
use Sabre\Event\Promise;
use function LanguageServer\{uriToPath, timeout};
use Webmozart\Glob\Iterator\GlobIterator;
class FileSystemFindFinder implements FilesFinder
{
/**
* Returns all files in the workspace that match a glob.
* If the client does not support workspace/files, it falls back to searching the file system directly.
*
* @param string $glob
* @return Promise <string[]>
*/
public function find(string $glob): Promise
{
return coroutine(function () use ($glob) {
$uris = [];
foreach (new GlobIterator($pattern) as $path) {
$uris[] = pathToUri($path);
yield timeout();
}
return $uris;
});
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types = 1);
namespace LanguageServer\ContentRetriever;
use Sabre\Event\Promise;
/**
* Interface for retrieving the content of a text document
*/
interface FilesFinder
{
/**
* Returns all files in the workspace that match a glob.
* If the client does not support workspace/files, it falls back to searching the file system directly.
*
* @param string $glob
* @return Promise <string[]>
*/
public function find(string $glob): Promise;
}

View File

@ -14,13 +14,12 @@ use LanguageServer\Protocol\{
TextDocumentIdentifier, TextDocumentIdentifier,
CompletionOptions CompletionOptions
}; };
use LanguageServer\FilesFinder\{FilesFinder, ClientFilesFinder, FileSystemFilesFinder};
use AdvancedJsonRpc; use AdvancedJsonRpc;
use Sabre\Event\{Loop, Promise}; use Sabre\Event\{Loop, Promise};
use function Sabre\Event\coroutine; use function Sabre\Event\coroutine;
use Exception; use Exception;
use Throwable; use Throwable;
use Webmozart\Glob\Iterator\GlobIterator;
use Webmozart\Glob\Glob;
use Webmozart\PathUtil\Path; use Webmozart\PathUtil\Path;
use Sabre\Uri; use Sabre\Uri;
@ -62,6 +61,11 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
private $rootPath; private $rootPath;
private $project; private $project;
/**
* @var FilesFinder
*/
private $filesFinder;
public function __construct(ProtocolReader $reader, ProtocolWriter $writer) public function __construct(ProtocolReader $reader, ProtocolWriter $writer)
{ {
parent::__construct($this, '/'); parent::__construct($this, '/');
@ -107,6 +111,11 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
}); });
$this->protocolWriter = $writer; $this->protocolWriter = $writer;
$this->client = new LanguageClient($reader, $writer); $this->client = new LanguageClient($reader, $writer);
if ($this->clientCapabilities->xfilesProvider) {
$this->filesFinder = new ClientFilesFinder($this->client);
} else {
$this->filesFinder = new FileSystemFilesFinder;
}
} }
/** /**
@ -183,7 +192,8 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
private function indexProject(): Promise private function indexProject(): Promise
{ {
return coroutine(function () { return coroutine(function () {
$textDocuments = yield $this->findPhpFiles(); $pattern = Path::makeAbsolute('**/*.php', $this->rootPath);
$textDocuments = yield $this->filesFinder->find($pattern);
$count = count($textDocuments); $count = count($textDocuments);
$startTime = microtime(true); $startTime = microtime(true);
@ -219,33 +229,4 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
}); });
} }
/**
* Returns all PHP files in the workspace.
* If the client does not support workspace/files, it falls back to searching the file system directly.
*
* @return Promise <TextDocumentIdentifier[]>
*/
private function findPhpFiles(): Promise
{
return coroutine(function () {
$textDocuments = [];
$pattern = Path::makeAbsolute('**/*.php', $this->rootPath);
if ($this->clientCapabilities->xfilesProvider) {
// Use xfiles request
foreach (yield $this->client->workspace->xfiles() as $textDocument) {
$path = Uri\parse($textDocument->uri)['path'];
if (Glob::match($path, $pattern)) {
$textDocuments[] = $textDocument;
}
}
} else {
// Use the file system
foreach (new GlobIterator($pattern) as $path) {
$textDocuments[] = new TextDocumentIdentifier(pathToUri($path));
yield timeout();
}
}
return $textDocuments;
});
}
} }