mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
This is a new (with js-debug) option that makes debugging child processes much easier. Use it for the LSP subprocesses. Supplants https://github.com/microsoft/vscode-extension-samples/pull/704
130 lines
4.5 KiB
TypeScript
130 lines
4.5 KiB
TypeScript
/* --------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
* ------------------------------------------------------------------------------------------ */
|
|
import * as path from 'path';
|
|
import {
|
|
workspace as Workspace, window as Window, ExtensionContext, TextDocument, OutputChannel, WorkspaceFolder, Uri
|
|
} from 'vscode';
|
|
|
|
import {
|
|
LanguageClient, LanguageClientOptions, TransportKind
|
|
} from 'vscode-languageclient/node';
|
|
|
|
let defaultClient: LanguageClient;
|
|
const clients: Map<string, LanguageClient> = new Map();
|
|
|
|
let _sortedWorkspaceFolders: string[] | undefined;
|
|
function sortedWorkspaceFolders(): string[] {
|
|
if (_sortedWorkspaceFolders === void 0) {
|
|
_sortedWorkspaceFolders = Workspace.workspaceFolders ? Workspace.workspaceFolders.map(folder => {
|
|
let result = folder.uri.toString();
|
|
if (result.charAt(result.length - 1) !== '/') {
|
|
result = result + '/';
|
|
}
|
|
return result;
|
|
}).sort(
|
|
(a, b) => {
|
|
return a.length - b.length;
|
|
}
|
|
) : [];
|
|
}
|
|
return _sortedWorkspaceFolders;
|
|
}
|
|
Workspace.onDidChangeWorkspaceFolders(() => _sortedWorkspaceFolders = undefined);
|
|
|
|
function getOuterMostWorkspaceFolder(folder: WorkspaceFolder): WorkspaceFolder {
|
|
const sorted = sortedWorkspaceFolders();
|
|
for (const element of sorted) {
|
|
let uri = folder.uri.toString();
|
|
if (uri.charAt(uri.length - 1) !== '/') {
|
|
uri = uri + '/';
|
|
}
|
|
if (uri.startsWith(element)) {
|
|
return Workspace.getWorkspaceFolder(Uri.parse(element))!;
|
|
}
|
|
}
|
|
return folder;
|
|
}
|
|
|
|
export function activate(context: ExtensionContext) {
|
|
|
|
const module = context.asAbsolutePath(path.join('server', 'out', 'server.js'));
|
|
const outputChannel: OutputChannel = Window.createOutputChannel('lsp-multi-server-example');
|
|
|
|
function didOpenTextDocument(document: TextDocument): void {
|
|
// We are only interested in language mode text
|
|
if (document.languageId !== 'plaintext' || (document.uri.scheme !== 'file' && document.uri.scheme !== 'untitled')) {
|
|
return;
|
|
}
|
|
|
|
const uri = document.uri;
|
|
// Untitled files go to a default client.
|
|
if (uri.scheme === 'untitled' && !defaultClient) {
|
|
const serverOptions = {
|
|
run: { module, transport: TransportKind.ipc },
|
|
debug: { module, transport: TransportKind.ipc }
|
|
};
|
|
const clientOptions: LanguageClientOptions = {
|
|
documentSelector: [
|
|
{ scheme: 'untitled', language: 'plaintext' }
|
|
],
|
|
diagnosticCollectionName: 'lsp-multi-server-example',
|
|
outputChannel: outputChannel
|
|
};
|
|
defaultClient = new LanguageClient('lsp-multi-server-example', 'LSP Multi Server Example', serverOptions, clientOptions);
|
|
defaultClient.start();
|
|
return;
|
|
}
|
|
let folder = Workspace.getWorkspaceFolder(uri);
|
|
// Files outside a folder can't be handled. This might depend on the language.
|
|
// Single file languages like JSON might handle files outside the workspace folders.
|
|
if (!folder) {
|
|
return;
|
|
}
|
|
// If we have nested workspace folders we only start a server on the outer most workspace folder.
|
|
folder = getOuterMostWorkspaceFolder(folder);
|
|
|
|
if (!clients.has(folder.uri.toString())) {
|
|
const serverOptions = {
|
|
run: { module, transport: TransportKind.ipc },
|
|
debug: { module, transport: TransportKind.ipc }
|
|
};
|
|
const clientOptions: LanguageClientOptions = {
|
|
documentSelector: [
|
|
{ scheme: 'file', language: 'plaintext', pattern: `${folder.uri.fsPath}/**/*` }
|
|
],
|
|
diagnosticCollectionName: 'lsp-multi-server-example',
|
|
workspaceFolder: folder,
|
|
outputChannel: outputChannel
|
|
};
|
|
const client = new LanguageClient('lsp-multi-server-example', 'LSP Multi Server Example', serverOptions, clientOptions);
|
|
client.start();
|
|
clients.set(folder.uri.toString(), client);
|
|
}
|
|
}
|
|
|
|
Workspace.onDidOpenTextDocument(didOpenTextDocument);
|
|
Workspace.textDocuments.forEach(didOpenTextDocument);
|
|
Workspace.onDidChangeWorkspaceFolders((event) => {
|
|
for (const folder of event.removed) {
|
|
const client = clients.get(folder.uri.toString());
|
|
if (client) {
|
|
clients.delete(folder.uri.toString());
|
|
client.stop();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
export function deactivate(): Thenable<void> {
|
|
const promises: Thenable<void>[] = [];
|
|
if (defaultClient) {
|
|
promises.push(defaultClient.stop());
|
|
}
|
|
for (const client of clients.values()) {
|
|
promises.push(client.stop());
|
|
}
|
|
return Promise.all(promises).then(() => undefined);
|
|
}
|