Skip to content

Commit 39e629c

Browse files
committed
尝试由客户端处理多个工作区
1 parent 6fec0dd commit 39e629c

3 files changed

Lines changed: 202 additions & 39 deletions

File tree

client/out/extension.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/out/languageserver.js

Lines changed: 88 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/src/languageserver.ts

Lines changed: 113 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
11
import * as path from 'path';
22
import * as os from 'os';
33
import * as fs from 'fs';
4-
import { workspace, ExtensionContext, env } from 'vscode';
5-
6-
let patch = require("./patch");
7-
4+
import {
5+
workspace as Workspace,
6+
ExtensionContext,
7+
env as Env,
8+
commands as Commands,
9+
TextDocument,
10+
WorkspaceFolder,
11+
Uri
12+
} from 'vscode';
813
import {
914
LanguageClient,
1015
LanguageClientOptions,
1116
ServerOptions,
17+
DocumentSelector,
1218
} from 'vscode-languageclient/node';
13-
import { commands } from 'vscode';
1419

15-
let client: LanguageClient;
20+
let patch = require("./patch");
21+
22+
let defaultClient: LanguageClient;
23+
let clients: Map<string, LanguageClient> = new Map();
1624

1725
function registerCustomCommands(context: ExtensionContext) {
18-
context.subscriptions.push(commands.registerCommand('lua.config', (data) => {
19-
let config = workspace.getConfiguration()
26+
context.subscriptions.push(Commands.registerCommand('lua.config', (data) => {
27+
let config = Workspace.getConfiguration()
2028
if (data.action == 'add') {
2129
let value: any[] = config.get(data.key);
2230
value.push(data.value);
@@ -30,24 +38,53 @@ function registerCustomCommands(context: ExtensionContext) {
3038
}))
3139
}
3240

33-
export function activate(context: ExtensionContext) {
34-
let language = env.language;
41+
let _sortedWorkspaceFolders: string[] | undefined;
42+
function sortedWorkspaceFolders(): string[] {
43+
if (_sortedWorkspaceFolders === void 0) {
44+
_sortedWorkspaceFolders = Workspace.workspaceFolders ? Workspace.workspaceFolders.map(folder => {
45+
let result = folder.uri.toString();
46+
if (result.charAt(result.length - 1) !== '/') {
47+
result = result + '/';
48+
}
49+
return result;
50+
}).sort(
51+
(a, b) => {
52+
return a.length - b.length;
53+
}
54+
) : [];
55+
}
56+
return _sortedWorkspaceFolders;
57+
}
58+
Workspace.onDidChangeWorkspaceFolders(() => _sortedWorkspaceFolders = undefined);
3559

60+
function getOuterMostWorkspaceFolder(folder: WorkspaceFolder): WorkspaceFolder {
61+
let sorted = sortedWorkspaceFolders();
62+
for (let element of sorted) {
63+
let uri = folder.uri.toString();
64+
if (uri.charAt(uri.length - 1) !== '/') {
65+
uri = uri + '/';
66+
}
67+
if (uri.startsWith(element)) {
68+
return Workspace.getWorkspaceFolder(Uri.parse(element))!;
69+
}
70+
}
71+
return folder;
72+
}
73+
74+
function start(context: ExtensionContext, documentSelector: DocumentSelector, folder: WorkspaceFolder): LanguageClient {
75+
let language = Env.language;
3676
// Options to control the language client
3777
let clientOptions: LanguageClientOptions = {
3878
// Register the server for plain text documents
39-
documentSelector: [{ scheme: 'file', language: 'lua' }],
40-
synchronize: {
41-
// Notify the server about file changes to '.clientrc files contained in the workspace
42-
fileEvents: workspace.createFileSystemWatcher('**/.clientrc')
43-
}
79+
documentSelector: documentSelector,
80+
workspaceFolder: folder,
4481
};
4582

46-
let beta: boolean = workspace.getConfiguration().get("Lua.zzzzzz.cat");
83+
let beta: boolean = Workspace.getConfiguration().get("Lua.zzzzzz.cat");
4784
//let beta: boolean = false;
48-
let develop: boolean = workspace.getConfiguration().get("Lua.develop.enable");
49-
let debuggerPort: number = workspace.getConfiguration().get("Lua.develop.debuggerPort");
50-
let debuggerWait: boolean = workspace.getConfiguration().get("Lua.develop.debuggerWait");
85+
let develop: boolean = Workspace.getConfiguration().get("Lua.develop.enable");
86+
let debuggerPort: number = Workspace.getConfiguration().get("Lua.develop.debuggerPort");
87+
let debuggerWait: boolean = Workspace.getConfiguration().get("Lua.develop.debuggerWait");
5188
let command: string;
5289
let platform: string = os.platform();
5390
switch (platform) {
@@ -98,24 +135,76 @@ export function activate(context: ExtensionContext) {
98135
]
99136
};
100137

101-
client = new LanguageClient(
138+
let client = new LanguageClient(
102139
'Lua',
103140
'Lua',
104141
serverOptions,
105142
clientOptions
106143
);
107144

108145
client.registerProposedFeatures();
109-
registerCustomCommands(context);
110146

111147
patch.patch(client);
112148

113149
client.start();
150+
151+
return client;
152+
}
153+
154+
export function activate(context: ExtensionContext) {
155+
registerCustomCommands(context);
156+
function didOpenTextDocument(document: TextDocument): void {
157+
// We are only interested in language mode text
158+
if (document.languageId !== 'lua' || (document.uri.scheme !== 'file' && document.uri.scheme !== 'untitled')) {
159+
return;
160+
}
161+
162+
let uri = document.uri;
163+
// Untitled files go to a default client.
164+
if (uri.scheme === 'untitled' && !defaultClient) {
165+
defaultClient = start(context, [
166+
{ scheme: 'untitled', language: 'lua' }
167+
], null);
168+
return;
169+
}
170+
171+
let folder = Workspace.getWorkspaceFolder(uri);
172+
// Files outside a folder can't be handled. This might depend on the language.
173+
// Single file languages like JSON might handle files outside the workspace folders.
174+
if (!folder) {
175+
return;
176+
}
177+
// If we have nested workspace folders we only start a server on the outer most workspace folder.
178+
folder = getOuterMostWorkspaceFolder(folder);
179+
180+
if (!clients.has(folder.uri.toString())) {
181+
let client = start(context, [
182+
{ scheme: 'file', language: 'lua', pattern: `${folder.uri.fsPath}/**/*` }
183+
], folder);
184+
clients.set(folder.uri.toString(), client);
185+
}
186+
}
187+
188+
Workspace.onDidOpenTextDocument(didOpenTextDocument);
189+
Workspace.textDocuments.forEach(didOpenTextDocument);
190+
Workspace.onDidChangeWorkspaceFolders((event) => {
191+
for (let folder of event.removed) {
192+
let client = clients.get(folder.uri.toString());
193+
if (client) {
194+
clients.delete(folder.uri.toString());
195+
client.stop();
196+
}
197+
}
198+
});
114199
}
115200

116201
export function deactivate(): Thenable<void> | undefined {
117-
if (!client) {
118-
return undefined;
202+
let promises: Thenable<void>[] = [];
203+
if (defaultClient) {
204+
promises.push(defaultClient.stop());
205+
}
206+
for (let client of clients.values()) {
207+
promises.push(client.stop());
119208
}
120-
return client.stop();
209+
return Promise.all(promises).then(() => undefined);
121210
}

0 commit comments

Comments
 (0)