feat: multi-root support (WIP)
parent
c74076d84f
commit
8741e287ad
|
@ -9,7 +9,8 @@ use LanguageServer\Protocol\{
|
||||||
TextDocumentSyncKind,
|
TextDocumentSyncKind,
|
||||||
Message,
|
Message,
|
||||||
InitializeResult,
|
InitializeResult,
|
||||||
CompletionOptions
|
CompletionOptions,
|
||||||
|
WorkspaceFolder
|
||||||
};
|
};
|
||||||
use LanguageServer\FilesFinder\{FilesFinder, ClientFilesFinder, FileSystemFilesFinder};
|
use LanguageServer\FilesFinder\{FilesFinder, ClientFilesFinder, FileSystemFilesFinder};
|
||||||
use LanguageServer\ContentRetriever\{ContentRetriever, ClientContentRetriever, FileSystemContentRetriever};
|
use LanguageServer\ContentRetriever\{ContentRetriever, ClientContentRetriever, FileSystemContentRetriever};
|
||||||
|
@ -161,12 +162,26 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
||||||
*
|
*
|
||||||
* @param ClientCapabilities $capabilities The capabilities provided by the client (editor)
|
* @param ClientCapabilities $capabilities The capabilities provided by the client (editor)
|
||||||
* @param string|null $rootPath The rootPath of the workspace. Is null if no folder is open.
|
* @param string|null $rootPath The rootPath of the workspace. Is null if no folder is open.
|
||||||
|
* @param string|null $rootUri TThe rootUri of the workspace. Is null if no folder is open. If both `rootPath` and `rootUri` are set `rootUri` wins.
|
||||||
|
* @param WorkspaceFolder[]|null $workspaceFolders The actual configured workspace folders.
|
||||||
* @param int|null $processId The process Id of the parent process that started the server. Is null if the process has not been started by another process. If the parent process is not alive then the server should exit (see exit notification) its process.
|
* @param int|null $processId The process Id of the parent process that started the server. Is null if the process has not been started by another process. If the parent process is not alive then the server should exit (see exit notification) its process.
|
||||||
* @return Promise <InitializeResult>
|
* @return Promise <InitializeResult>
|
||||||
*/
|
*/
|
||||||
public function initialize(ClientCapabilities $capabilities, string $rootPath = null, int $processId = null): Promise
|
public function initialize(ClientCapabilities $capabilities, string $rootPath = null, string $rootUri = null, array $workspaceFolders = null, int $processId = null): Promise
|
||||||
{
|
{
|
||||||
return coroutine(function () use ($capabilities, $rootPath, $processId) {
|
return coroutine(function () use ($capabilities, $rootPath, $rootUri, $workspaceFolders, $processId) {
|
||||||
|
|
||||||
|
/** @var string[] */
|
||||||
|
$rootPaths = [];
|
||||||
|
if ($workspaceFolders !== null) {
|
||||||
|
foreach ($workspaceFolders as $workspaceFolder) {
|
||||||
|
$rootPaths[] = uriToPath($workspaceFolder->uri);
|
||||||
|
}
|
||||||
|
} else if ($rootUri !== null) {
|
||||||
|
$rootPaths[] = uriToPath($rootUri);
|
||||||
|
} else if ($rootPath !== null) {
|
||||||
|
$rootPaths[] = $rootPath;
|
||||||
|
}
|
||||||
|
|
||||||
if ($capabilities->xfilesProvider) {
|
if ($capabilities->xfilesProvider) {
|
||||||
$this->filesFinder = new ClientFilesFinder($this->client);
|
$this->filesFinder = new ClientFilesFinder($this->client);
|
||||||
|
@ -199,23 +214,23 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
||||||
yield $this->beforeIndex($rootPath);
|
yield $this->beforeIndex($rootPath);
|
||||||
|
|
||||||
// Find composer.json
|
// Find composer.json
|
||||||
if ($this->composerJson === null) {
|
if ($this->composerJsons === null) {
|
||||||
$composerJsonFiles = yield $this->filesFinder->find(Path::makeAbsolute('**/composer.json', $rootPath));
|
$this->composerJsons = yield array_map(function (string $rootPath) {
|
||||||
sortUrisLevelOrder($composerJsonFiles);
|
$composerJsonFiles = yield $this->filesFinder->find(Path::makeAbsolute('**/composer.json', $rootPath));
|
||||||
|
foreach ($composerJsonFiles as $composerJsonFile) {
|
||||||
if (!empty($composerJsonFiles)) {
|
$this->composerJsons[$composerJsonFile] = json_decode(yield $this->contentRetriever->retrieve($composerJsonFile));
|
||||||
$this->composerJson = json_decode(yield $this->contentRetriever->retrieve($composerJsonFiles[0]));
|
}
|
||||||
}
|
}, $rootPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find composer.lock
|
// Find composer.lock
|
||||||
if ($this->composerLock === null) {
|
if ($this->composerLocks === null) {
|
||||||
$composerLockFiles = yield $this->filesFinder->find(Path::makeAbsolute('**/composer.lock', $rootPath));
|
$this->composerLocks = yield array_map(function (string $rootPath) {
|
||||||
sortUrisLevelOrder($composerLockFiles);
|
$composerLockFiles = yield $this->filesFinder->find(Path::makeAbsolute('**/composer.lock', $rootPath));
|
||||||
|
foreach ($composerLockFiles as $composerLockFile) {
|
||||||
if (!empty($composerLockFiles)) {
|
$this->composerLocks[$composerLockFile] = json_decode(yield $this->contentRetriever->retrieve($composerLockFile));
|
||||||
$this->composerLock = json_decode(yield $this->contentRetriever->retrieve($composerLockFiles[0]));
|
}
|
||||||
}
|
}, $rootPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
$cache = $capabilities->xcacheProvider ? new ClientCache($this->client) : new FileSystemCache;
|
$cache = $capabilities->xcacheProvider ? new ClientCache($this->client) : new FileSystemCache;
|
||||||
|
@ -229,8 +244,8 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
||||||
$dependenciesIndex,
|
$dependenciesIndex,
|
||||||
$sourceIndex,
|
$sourceIndex,
|
||||||
$this->documentLoader,
|
$this->documentLoader,
|
||||||
$this->composerLock,
|
$this->composerLocks,
|
||||||
$this->composerJson
|
$this->composerJsons
|
||||||
);
|
);
|
||||||
$indexer->index()->otherwise('\\LanguageServer\\crash');
|
$indexer->index()->otherwise('\\LanguageServer\\crash');
|
||||||
}
|
}
|
||||||
|
@ -242,8 +257,8 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
||||||
$this->definitionResolver,
|
$this->definitionResolver,
|
||||||
$this->client,
|
$this->client,
|
||||||
$this->globalIndex,
|
$this->globalIndex,
|
||||||
$this->composerJson,
|
$this->composerJsons,
|
||||||
$this->composerLock
|
$this->composerLocks
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ($this->workspace === null) {
|
if ($this->workspace === null) {
|
||||||
|
@ -252,9 +267,9 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
||||||
$this->projectIndex,
|
$this->projectIndex,
|
||||||
$dependenciesIndex,
|
$dependenciesIndex,
|
||||||
$sourceIndex,
|
$sourceIndex,
|
||||||
$this->composerLock,
|
$this->composerLocks,
|
||||||
$this->documentLoader,
|
$this->documentLoader,
|
||||||
$this->composerJson
|
$this->composerJsons
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LanguageServer\Protocol;
|
||||||
|
|
||||||
|
class WorkspaceFolder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The associated URI for this workspace folder.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $uri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the workspace folder. Defaults to the uri's basename.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $name;
|
||||||
|
}
|
Loading…
Reference in New Issue