1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/**
* If we wanted to run or use another language server from our extension, this is how we would do it.
*/
import * as path from "path";
import { workspace, ExtensionContext, extensions } from "vscode";
import {
DefinitionParams,
LanguageClient,
LanguageClientOptions,
ServerOptions,
StateChangeEvent,
TransportKind,
State,
} from "vscode-languageclient/node";
import { getExtensionUri } from "../util/vscode";
let client: LanguageClient;
export async function startLanguageClient(context: ExtensionContext) {
let pythonLS = startPythonLanguageServer(context);
pythonLS.start();
}
export async function makeRequest(method: string, param: any): Promise<any> {
if (!client) {
return;
} else if (client.state === State.Starting) {
return new Promise((resolve, reject) => {
let stateListener = client.onDidChangeState((e: StateChangeEvent) => {
if (e.newState === State.Running) {
stateListener.dispose();
resolve(client.sendRequest(method, param));
} else if (e.newState === State.Stopped) {
stateListener.dispose();
reject(new Error("Language server stopped unexpectedly"));
}
});
});
} else {
return client.sendRequest(method, param);
}
}
export function deactivate(): Thenable<void> | undefined {
if (!client) {
return undefined;
}
return client.stop();
}
function startPythonLanguageServer(context: ExtensionContext): LanguageClient {
let extensionPath = getExtensionUri().fsPath;
const command = `cd ${path.join(
extensionPath,
"scripts"
)} && source env/bin/activate.fish && python -m pyls`;
const serverOptions: ServerOptions = {
command: command,
args: ["-vv"],
};
const clientOptions: LanguageClientOptions = {
documentSelector: ["python"],
synchronize: {
configurationSection: "pyls",
},
};
return new LanguageClient(command, serverOptions, clientOptions);
}
async function startPylance(context: ExtensionContext) {
let pylance = extensions.getExtension("ms-python.vscode-pylance");
await pylance?.activate();
if (!pylance) {
return;
}
let { path: lsPath } = await pylance.exports.languageServerFolder();
// The server is implemented in node
let serverModule = context.asAbsolutePath(lsPath);
// The debug options for the server
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] };
// If the extension is launched in debug mode then the debug server options are used
// Otherwise the run options are used
let serverOptions: ServerOptions = {
run: { module: serverModule, transport: TransportKind.ipc },
debug: {
module: serverModule,
transport: TransportKind.ipc,
options: debugOptions,
},
};
// Options to control the language client
let clientOptions: LanguageClientOptions = {
// Register the server for plain text documents
documentSelector: [{ scheme: "file", language: "python" }],
synchronize: {
// Notify the server about file changes to '.clientrc files contained in the workspace
fileEvents: workspace.createFileSystemWatcher("**/.clientrc"),
},
};
// Create the language client and start the client.
client = new LanguageClient(
"languageServerExample",
"Language Server Example",
serverOptions,
clientOptions
);
return client;
}
|