aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/installation/server.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/installation/server.ts')
-rw-r--r--editors/code/src/installation/server.ts124
1 files changed, 124 insertions, 0 deletions
diff --git a/editors/code/src/installation/server.ts b/editors/code/src/installation/server.ts
new file mode 100644
index 000000000..80cb719e3
--- /dev/null
+++ b/editors/code/src/installation/server.ts
@@ -0,0 +1,124 @@
1import * as vscode from "vscode";
2import * as path from "path";
3import { strict as assert } from "assert";
4import { promises as dns } from "dns";
5import { spawnSync } from "child_process";
6
7import { BinarySource } from "./interfaces";
8import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info";
9import { downloadArtifact } from "./download_artifact";
10
11export async function ensureServerBinary(source: null | BinarySource): Promise<null | string> {
12 if (!source) {
13 vscode.window.showErrorMessage(
14 "Unfortunately we don't ship binaries for your platform yet. " +
15 "You need to manually clone rust-analyzer repository and " +
16 "run `cargo xtask install --server` to build the language server from sources. " +
17 "If you feel that your platform should be supported, please create an issue " +
18 "about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we " +
19 "will consider it."
20 );
21 return null;
22 }
23
24 switch (source.type) {
25 case BinarySource.Type.ExplicitPath: {
26 if (isBinaryAvailable(source.path)) {
27 return source.path;
28 }
29
30 vscode.window.showErrorMessage(
31 `Unable to run ${source.path} binary. ` +
32 `To use the pre-built language server, set "rust-analyzer.raLspServerPath" ` +
33 "value to `null` or remove it from the settings to use it by default."
34 );
35 return null;
36 }
37 case BinarySource.Type.GithubRelease: {
38 const prebuiltBinaryPath = path.join(source.dir, source.file);
39
40 const installedVersion: null | string = getServerVersion(source.storage);
41 const requiredVersion: string = source.version;
42
43 console.log("Installed version:", installedVersion, "required:", requiredVersion);
44
45 if (isBinaryAvailable(prebuiltBinaryPath) && installedVersion == requiredVersion) {
46 // FIXME: check for new releases and notify the user to update if possible
47 return prebuiltBinaryPath;
48 }
49
50 const userResponse = await vscode.window.showInformationMessage(
51 `Language server version ${source.version} for rust-analyzer is not installed. ` +
52 "Do you want to download it now?",
53 "Download now", "Cancel"
54 );
55 if (userResponse !== "Download now") return null;
56
57 if (!await downloadServer(source)) return null;
58
59 return prebuiltBinaryPath;
60 }
61 }
62}
63
64async function downloadServer(source: BinarySource.GithubRelease): Promise<boolean> {
65 try {
66 const releaseInfo = (await fetchArtifactReleaseInfo(source.repo, source.file, source.version))!;
67
68 await downloadArtifact(releaseInfo, source.file, source.dir, "language server");
69 await setServerVersion(source.storage, releaseInfo.releaseName);
70 } catch (err) {
71 vscode.window.showErrorMessage(
72 `Failed to download language server from ${source.repo.name} ` +
73 `GitHub repository: ${err.message}`
74 );
75
76 console.error(err);
77
78 dns.resolve('example.com').then(
79 addrs => console.log("DNS resolution for example.com was successful", addrs),
80 err => {
81 console.error(
82 "DNS resolution for example.com failed, " +
83 "there might be an issue with Internet availability"
84 );
85 console.error(err);
86 }
87 );
88 return false;
89 }
90
91 if (!isBinaryAvailable(path.join(source.dir, source.file))) assert(false,
92 `Downloaded language server binary is not functional.` +
93 `Downloaded from: ${JSON.stringify(source, null, 4)}`
94 );
95
96 vscode.window.showInformationMessage(
97 "Rust analyzer language server was successfully installed 🦀"
98 );
99
100 return true;
101}
102
103function isBinaryAvailable(binaryPath: string): boolean {
104 const res = spawnSync(binaryPath, ["--version"]);
105
106 // ACHTUNG! `res` type declaration is inherently wrong, see
107 // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/42221
108
109 console.log("Checked binary availablity via --version", res);
110 console.log(binaryPath, "--version output:", res.output?.map(String));
111
112 return res.status === 0;
113}
114
115function getServerVersion(storage: vscode.Memento): null | string {
116 const version = storage.get<null | string>("server-version", null);
117 console.log("Get server-version:", version);
118 return version;
119}
120
121async function setServerVersion(storage: vscode.Memento, version: string): Promise<void> {
122 console.log("Set server-version:", version);
123 await storage.update("server-version", version.toString());
124}