diff --git a/composer.json b/composer.json index 62a9217..2afb468 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,8 @@ "symfony/debug": "^3.1", "netresearch/jsonmapper": "^1.0", "webmozart/path-util": "^2.3", - "webmozart/glob": "^4.1" + "webmozart/glob": "^4.1", + "sabre/uri": "^2.0" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/src/Client/Workspace.php b/src/Client/Workspace.php index 8e277e5..901e386 100644 --- a/src/Client/Workspace.php +++ b/src/Client/Workspace.php @@ -30,16 +30,16 @@ class Workspace } /** - * Returns a list of all files in the workspace that match any of the given glob patterns + * Returns a list of all files in a directory * - * @param string[] $patterns Glob patterns - * @return Promise Array of documents that match the glob patterns + * @param string $base The base directory (defaults to the workspace) + * @return Promise Array of documents */ - public function xglob(array $patterns): Promise + public function xfiles(string $base = null): Promise { return $this->handler->request( - 'workspace/xglob', - ['patterns' => $patterns] + 'workspace/xfiles', + ['base' => $base] )->then(function (array $textDocuments) { return $this->mapper->mapArray($textDocuments, [], TextDocumentIdentifier::class); }); diff --git a/src/LanguageServer.php b/src/LanguageServer.php index a6789b9..959aa33 100644 --- a/src/LanguageServer.php +++ b/src/LanguageServer.php @@ -20,7 +20,9 @@ use Exception; use RuntimeException; use Throwable; use Webmozart\Glob\Iterator\GlobIterator; +use Webmozart\Glob\Glob; use Webmozart\PathUtil\Path; +use Sabre\Uri; class LanguageServer extends AdvancedJsonRpc\Dispatcher { @@ -215,19 +217,24 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher private function findPhpFiles(): Promise { return coroutine(function () { + $textDocuments = []; + $pattern = Path::makeAbsolute('**/*.php', $this->rootPath); if ($this->clientCapabilities->xfilesProvider) { // Use xfiles request - return yield $this->client->workspace->xfiles($patterns); + 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 - $textDocuments = []; - $pattern = Path::makeAbsolute('**/*.php', $this->rootPath); foreach (new GlobIterator($pattern) as $path) { $textDocuments[] = new TextDocumentIdentifier(pathToUri($path)); yield timeout(); } - return $textDocuments; } + return $textDocuments; }); } } diff --git a/tests/LanguageServerTest.php b/tests/LanguageServerTest.php index fcab0c3..1690a5e 100644 --- a/tests/LanguageServerTest.php +++ b/tests/LanguageServerTest.php @@ -5,7 +5,8 @@ namespace LanguageServer\Tests; use PHPUnit\Framework\TestCase; use LanguageServer\LanguageServer; -use LanguageServer\Protocol\{Message, ClientCapabilities, TextDocumentSyncKind, MessageType, Content}; +use LanguageServer\Protocol\{ + Message, ClientCapabilities, TextDocumentSyncKind, MessageType, TextDocumentItem, TextDocumentIdentifier}; use AdvancedJsonRpc; use Webmozart\Glob\Glob; use Webmozart\PathUtil\Path; @@ -71,31 +72,32 @@ class LanguageServerTest extends TestCase $promise->wait(); } - public function testIndexingWithGlobAndContentRequests() + public function testIndexingWithFilesAndContentRequests() { $promise = new Promise; - $globCalled = false; + $filesCalled = false; $contentCalled = false; $rootPath = realpath(__DIR__ . '/../fixtures'); $input = new MockProtocolStream; $output = new MockProtocolStream; - $output->on('message', function (Message $msg) use ($promise, $input, $rootPath, &$globCalled, &$contentCalled) { + $output->on('message', function (Message $msg) use ($promise, $input, $rootPath, &$filesCalled, &$contentCalled) { if ($msg->body->method === 'textDocument/xcontent') { // Document content requested $contentCalled = true; - $input->write(new Message(new AdvancedJsonRpc\SuccessResponse( - $msg->body->id, - new Content(file_get_contents($msg->body->params->textDocument->uri)) - ))); - } else if ($msg->body->method === 'workspace/xglob') { + $textDocumentItem = new TextDocumentItem; + $textDocumentItem->uri = $msg->body->params->textDocument->uri; + $textDocumentItem->version = 1; + $textDocumentItem->languageId = 'php'; + $textDocumentItem->text = file_get_contents($msg->body->params->textDocument->uri); + $input->write(new Message(new AdvancedJsonRpc\SuccessResponse($msg->body->id, $textDocumentItem))); + } else if ($msg->body->method === 'workspace/xfiles') { // Glob requested - $globCalled = true; - $files = array_map( - '\\LanguageServer\\pathToUri', - array_merge(...array_map(function (string $pattern) use ($rootPath) { - return Glob::glob(Path::makeAbsolute($pattern, $rootPath)); - }, $msg->body->params->patterns)) - ); + $filesCalled = true; + $pattern = Path::makeAbsolute('**/*.php', $msg->body->params->base ?? $rootPath); + $files = []; + foreach (Glob::glob($pattern) as $path) { + $files[] = new TextDocumentIdentifier(pathToUri($path)); + } $input->write(new Message(new AdvancedJsonRpc\SuccessResponse($msg->body->id, $files))); } else if ($msg->body->method === 'window/logMessage') { // Message logged @@ -112,11 +114,11 @@ class LanguageServerTest extends TestCase }); $server = new LanguageServer($input, $output); $capabilities = new ClientCapabilities; - $capabilities->xglobProvider = true; + $capabilities->xfilesProvider = true; $capabilities->xcontentProvider = true; $server->initialize(getmypid(), $capabilities, $rootPath); $promise->wait(); - $this->assertTrue($globCalled); + $this->assertTrue($filesCalled); $this->assertTrue($contentCalled); } }