aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/config.ts
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-03-19 08:06:48 +0000
committerGitHub <[email protected]>2020-03-19 08:06:48 +0000
commitaca3c3086ee99f5770a60970e20af640c895d42a (patch)
tree2f0b3233cc4728436ba5e47a6e91e7df33585d43 /editors/code/src/config.ts
parent55336722b3662cbdcc9e1b92a3e27ed0442d2452 (diff)
parentfb6e655de8a44c65275ad45a27bf5bd684670ba0 (diff)
Merge #3629
3629: Alternative aproach to plugin auto update r=matklad a=matklad This is very much WIP (as in, I haven't run this once), but I like the result so far. cc @Veetaha The primary focus here on simplification: * local simplification of data structures and control-flow: using union of strings instead of an enum, using unwrapped GitHub API responses * global simplification of control flow: all logic is now in `main.ts`, implemented as linear functions without abstractions. This is stateful side-effective code, so arguments from [Carmack](http://number-none.com/blow/john_carmack_on_inlined_code.html) very much apply. We need all user interractions, all mutations, and all network requests to happen in a single file. * as a side-effect of condensing everything to functions, we can get rid of various enums. The enums were basically a reified control flow: ``` enum E { A, B } fn foo() -> E { if cond { E::A } else { E::B } } fn bar(e: E) { match e { E::A => do_a(), E::B => do_b(), } } ==>> fn all() { if cond { do_a() } else { do_b() } } ``` * simplification of model: we don't need to reinstall on settings update, we can just ask the user to reload, we don't need to handle nightly=>stable fallback, we can ask the user to reinstall extension, (todo) we don't need to parse out the date from the version, we can use build id for nightly and for stable we can write the info directly into package.json. Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'editors/code/src/config.ts')
-rw-r--r--editors/code/src/config.ts103
1 files changed, 7 insertions, 96 deletions
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index b45b14bef..28698ab8e 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -1,9 +1,5 @@
1import * as os from "os";
2import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
3import { ArtifactSource } from "./installation/interfaces"; 2import { log } from "./util";
4import { log, vscodeReloadWindow } from "./util";
5
6const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG;
7 3
8export interface InlayHintOptions { 4export interface InlayHintOptions {
9 typeHints: boolean; 5 typeHints: boolean;
@@ -25,10 +21,7 @@ export interface CargoFeatures {
25 loadOutDirsFromCheck: boolean; 21 loadOutDirsFromCheck: boolean;
26} 22}
27 23
28export const enum UpdatesChannel { 24export type UpdatesChannel = "stable" | "nightly";
29 Stable = "stable",
30 Nightly = "nightly"
31}
32 25
33export const NIGHTLY_TAG = "nightly"; 26export const NIGHTLY_TAG = "nightly";
34export class Config { 27export class Config {
@@ -41,6 +34,7 @@ export class Config {
41 "cargo-watch", 34 "cargo-watch",
42 "highlighting.semanticTokens", 35 "highlighting.semanticTokens",
43 "inlayHints", 36 "inlayHints",
37 "updates.channel",
44 ] 38 ]
45 .map(opt => `${this.rootSection}.${opt}`); 39 .map(opt => `${this.rootSection}.${opt}`);
46 40
@@ -94,100 +88,17 @@ export class Config {
94 ); 88 );
95 89
96 if (userResponse === "Reload now") { 90 if (userResponse === "Reload now") {
97 await vscodeReloadWindow(); 91 await vscode.commands.executeCommand("workbench.action.reloadWindow");
98 } 92 }
99 } 93 }
100 94
101 private static replaceTildeWithHomeDir(path: string) { 95 get globalStoragePath(): string { return this.ctx.globalStoragePath; }
102 if (path.startsWith("~/")) {
103 return os.homedir() + path.slice("~".length);
104 }
105 return path;
106 }
107
108 /**
109 * Name of the binary artifact for `rust-analyzer` that is published for
110 * `platform` on GitHub releases. (It is also stored under the same name when
111 * downloaded by the extension).
112 */
113 get prebuiltServerFileName(): null | string {
114 // See possible `arch` values here:
115 // https://nodejs.org/api/process.html#process_process_arch
116
117 switch (process.platform) {
118
119 case "linux": {
120 switch (process.arch) {
121 case "arm":
122 case "arm64": return null;
123
124 default: return "rust-analyzer-linux";
125 }
126 }
127
128 case "darwin": return "rust-analyzer-mac";
129 case "win32": return "rust-analyzer-windows.exe";
130
131 // Users on these platforms yet need to manually build from sources
132 case "aix":
133 case "android":
134 case "freebsd":
135 case "openbsd":
136 case "sunos":
137 case "cygwin":
138 case "netbsd": return null;
139 // The list of platforms is exhaustive (see `NodeJS.Platform` type definition)
140 }
141 }
142
143 get installedExtensionUpdateChannel(): UpdatesChannel {
144 return this.extensionReleaseTag === NIGHTLY_TAG
145 ? UpdatesChannel.Nightly
146 : UpdatesChannel.Stable;
147 }
148
149 get serverSource(): null | ArtifactSource {
150 const serverPath = RA_LSP_DEBUG ?? this.serverPath;
151
152 if (serverPath) {
153 return {
154 type: ArtifactSource.Type.ExplicitPath,
155 path: Config.replaceTildeWithHomeDir(serverPath)
156 };
157 }
158
159 const prebuiltBinaryName = this.prebuiltServerFileName;
160
161 if (!prebuiltBinaryName) return null;
162
163 return this.createGithubReleaseSource(
164 prebuiltBinaryName,
165 this.extensionReleaseTag
166 );
167 }
168
169 private createGithubReleaseSource(file: string, tag: string): ArtifactSource.GithubRelease {
170 return {
171 type: ArtifactSource.Type.GithubRelease,
172 file,
173 tag,
174 dir: this.ctx.globalStoragePath,
175 repo: {
176 name: "rust-analyzer",
177 owner: "rust-analyzer",
178 }
179 };
180 }
181
182 get nightlyVsixSource(): ArtifactSource.GithubRelease {
183 return this.createGithubReleaseSource("rust-analyzer.vsix", NIGHTLY_TAG);
184 }
185 96
186 // We don't do runtime config validation here for simplicity. More on stackoverflow: 97 // We don't do runtime config validation here for simplicity. More on stackoverflow:
187 // https://stackoverflow.com/questions/60135780/what-is-the-best-way-to-type-check-the-configuration-for-vscode-extension 98 // https://stackoverflow.com/questions/60135780/what-is-the-best-way-to-type-check-the-configuration-for-vscode-extension
188 99
189 private get serverPath() { return this.cfg.get("serverPath") as null | string; } 100 get serverPath() { return this.cfg.get("serverPath") as null | string; }
190 get updatesChannel() { return this.cfg.get("updates.channel") as UpdatesChannel; } 101 get channel() { return this.cfg.get<"stable" | "nightly">("updates.channel")!; }
191 get askBeforeDownload() { return this.cfg.get("updates.askBeforeDownload") as boolean; } 102 get askBeforeDownload() { return this.cfg.get("updates.askBeforeDownload") as boolean; }
192 get highlightingSemanticTokens() { return this.cfg.get("highlighting.semanticTokens") as boolean; } 103 get highlightingSemanticTokens() { return this.cfg.get("highlighting.semanticTokens") as boolean; }
193 get highlightingOn() { return this.cfg.get("highlightingOn") as boolean; } 104 get highlightingOn() { return this.cfg.get("highlightingOn") as boolean; }