diff options
Diffstat (limited to 'editors/code')
-rw-r--r-- | editors/code/src/config.ts | 111 |
1 files changed, 96 insertions, 15 deletions
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 6db073bec..e2b0f6f84 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -23,22 +23,36 @@ export interface CargoFeatures { | |||
23 | allFeatures: boolean; | 23 | allFeatures: boolean; |
24 | features: string[]; | 24 | features: string[]; |
25 | } | 25 | } |
26 | |||
27 | export const enum UpdatesChannel { | ||
28 | Stable = "stable", | ||
29 | Nightly = "nightly" | ||
30 | } | ||
31 | |||
32 | export const NIGHTLY_TAG = "nightly"; | ||
26 | export class Config { | 33 | export class Config { |
27 | private static readonly rootSection = "rust-analyzer"; | 34 | readonly extensionId = "matklad.rust-analyzer"; |
28 | private static readonly requiresReloadOpts = [ | 35 | |
36 | private readonly rootSection = "rust-analyzer"; | ||
37 | private readonly requiresReloadOpts = [ | ||
29 | "cargoFeatures", | 38 | "cargoFeatures", |
30 | "cargo-watch", | 39 | "cargo-watch", |
31 | "highlighting.semanticTokens", | 40 | "highlighting.semanticTokens", |
32 | "inlayHints", | 41 | "inlayHints", |
33 | ] | 42 | ] |
34 | .map(opt => `${Config.rootSection}.${opt}`); | 43 | .map(opt => `${this.rootSection}.${opt}`); |
35 | 44 | ||
36 | private static readonly extensionVersion: string = (() => { | 45 | /** |
46 | * Either `nightly` or `YYYY-MM-DD` (i.e. `stable` release) | ||
47 | */ | ||
48 | private readonly extensionVersion: string = (() => { | ||
37 | const packageJsonVersion = vscode | 49 | const packageJsonVersion = vscode |
38 | .extensions | 50 | .extensions |
39 | .getExtension("matklad.rust-analyzer")! | 51 | .getExtension(this.extensionId)! |
40 | .packageJSON | 52 | .packageJSON |
41 | .version as string; // n.n.YYYYMMDD | 53 | .version as string; |
54 | |||
55 | if (packageJsonVersion.endsWith(NIGHTLY_TAG)) return NIGHTLY_TAG; | ||
42 | 56 | ||
43 | const realVersionRegexp = /^\d+\.\d+\.(\d{4})(\d{2})(\d{2})/; | 57 | const realVersionRegexp = /^\d+\.\d+\.(\d{4})(\d{2})(\d{2})/; |
44 | const [, yyyy, mm, dd] = packageJsonVersion.match(realVersionRegexp)!; | 58 | const [, yyyy, mm, dd] = packageJsonVersion.match(realVersionRegexp)!; |
@@ -54,7 +68,7 @@ export class Config { | |||
54 | } | 68 | } |
55 | 69 | ||
56 | private refreshConfig() { | 70 | private refreshConfig() { |
57 | this.cfg = vscode.workspace.getConfiguration(Config.rootSection); | 71 | this.cfg = vscode.workspace.getConfiguration(this.rootSection); |
58 | const enableLogging = this.cfg.get("trace.extension") as boolean; | 72 | const enableLogging = this.cfg.get("trace.extension") as boolean; |
59 | log.setEnabled(enableLogging); | 73 | log.setEnabled(enableLogging); |
60 | log.debug("Using configuration:", this.cfg); | 74 | log.debug("Using configuration:", this.cfg); |
@@ -63,7 +77,7 @@ export class Config { | |||
63 | private async onConfigChange(event: vscode.ConfigurationChangeEvent) { | 77 | private async onConfigChange(event: vscode.ConfigurationChangeEvent) { |
64 | this.refreshConfig(); | 78 | this.refreshConfig(); |
65 | 79 | ||
66 | const requiresReloadOpt = Config.requiresReloadOpts.find( | 80 | const requiresReloadOpt = this.requiresReloadOpts.find( |
67 | opt => event.affectsConfiguration(opt) | 81 | opt => event.affectsConfiguration(opt) |
68 | ); | 82 | ); |
69 | 83 | ||
@@ -121,8 +135,16 @@ export class Config { | |||
121 | } | 135 | } |
122 | } | 136 | } |
123 | 137 | ||
138 | get installedExtensionUpdateChannel() { | ||
139 | if (this.serverPath !== null) return null; | ||
140 | |||
141 | return this.extensionVersion === NIGHTLY_TAG | ||
142 | ? UpdatesChannel.Nightly | ||
143 | : UpdatesChannel.Stable; | ||
144 | } | ||
145 | |||
124 | get serverSource(): null | ArtifactSource { | 146 | get serverSource(): null | ArtifactSource { |
125 | const serverPath = RA_LSP_DEBUG ?? this.cfg.get<null | string>("serverPath"); | 147 | const serverPath = RA_LSP_DEBUG ?? this.serverPath; |
126 | 148 | ||
127 | if (serverPath) { | 149 | if (serverPath) { |
128 | return { | 150 | return { |
@@ -135,23 +157,47 @@ export class Config { | |||
135 | 157 | ||
136 | if (!prebuiltBinaryName) return null; | 158 | if (!prebuiltBinaryName) return null; |
137 | 159 | ||
160 | return this.createGithubReleaseSource( | ||
161 | prebuiltBinaryName, | ||
162 | this.extensionVersion | ||
163 | ); | ||
164 | } | ||
165 | |||
166 | private createGithubReleaseSource(file: string, tag: string): ArtifactSource.GithubRelease { | ||
138 | return { | 167 | return { |
139 | type: ArtifactSource.Type.GithubRelease, | 168 | type: ArtifactSource.Type.GithubRelease, |
169 | file, | ||
170 | tag, | ||
140 | dir: this.ctx.globalStoragePath, | 171 | dir: this.ctx.globalStoragePath, |
141 | file: prebuiltBinaryName, | ||
142 | storage: this.ctx.globalState, | ||
143 | tag: Config.extensionVersion, | ||
144 | askBeforeDownload: this.cfg.get("updates.askBeforeDownload") as boolean, | ||
145 | repo: { | 172 | repo: { |
146 | name: "rust-analyzer", | 173 | name: "rust-analyzer", |
147 | owner: "rust-analyzer", | 174 | owner: "rust-analyzer" |
148 | } | 175 | } |
149 | }; | 176 | } |
150 | } | 177 | } |
151 | 178 | ||
179 | get nightlyVsixSource(): ArtifactSource.GithubRelease { | ||
180 | return this.createGithubReleaseSource("rust-analyzer.vsix", NIGHTLY_TAG); | ||
181 | } | ||
182 | |||
183 | readonly installedNightlyExtensionReleaseDate = new DateStorage( | ||
184 | "rust-analyzer-installed-nightly-extension-release-date", | ||
185 | this.ctx.globalState | ||
186 | ); | ||
187 | readonly serverReleaseDate = new DateStorage( | ||
188 | "rust-analyzer-server-release-date", | ||
189 | this.ctx.globalState | ||
190 | ); | ||
191 | readonly serverReleaseTag = new StringStorage( | ||
192 | "rust-analyzer-release-tag", this.ctx.globalState | ||
193 | ); | ||
194 | |||
152 | // We don't do runtime config validation here for simplicity. More on stackoverflow: | 195 | // We don't do runtime config validation here for simplicity. More on stackoverflow: |
153 | // https://stackoverflow.com/questions/60135780/what-is-the-best-way-to-type-check-the-configuration-for-vscode-extension | 196 | // https://stackoverflow.com/questions/60135780/what-is-the-best-way-to-type-check-the-configuration-for-vscode-extension |
154 | 197 | ||
198 | private get serverPath() { return this.cfg.get("serverPath") as null | string; } | ||
199 | get updatesChannel() { return this.cfg.get("updates.channel") as UpdatesChannel; } | ||
200 | get askBeforeDownload() { return this.cfg.get("updates.askBeforeDownload") as boolean; } | ||
155 | get highlightingSemanticTokens() { return this.cfg.get("highlighting.semanticTokens") as boolean; } | 201 | get highlightingSemanticTokens() { return this.cfg.get("highlighting.semanticTokens") as boolean; } |
156 | get highlightingOn() { return this.cfg.get("highlightingOn") as boolean; } | 202 | get highlightingOn() { return this.cfg.get("highlightingOn") as boolean; } |
157 | get rainbowHighlightingOn() { return this.cfg.get("rainbowHighlightingOn") as boolean; } | 203 | get rainbowHighlightingOn() { return this.cfg.get("rainbowHighlightingOn") as boolean; } |
@@ -189,3 +235,38 @@ export class Config { | |||
189 | // for internal use | 235 | // for internal use |
190 | get withSysroot() { return this.cfg.get("withSysroot", true) as boolean; } | 236 | get withSysroot() { return this.cfg.get("withSysroot", true) as boolean; } |
191 | } | 237 | } |
238 | |||
239 | export class StringStorage { | ||
240 | constructor( | ||
241 | private readonly key: string, | ||
242 | private readonly storage: vscode.Memento | ||
243 | ) {} | ||
244 | |||
245 | get(): null | string { | ||
246 | const tag = this.storage.get(this.key, null); | ||
247 | log.debug(this.key, "==", tag); | ||
248 | return tag; | ||
249 | } | ||
250 | async set(tag: string) { | ||
251 | log.debug(this.key, "=", tag); | ||
252 | await this.storage.update(this.key, tag); | ||
253 | } | ||
254 | } | ||
255 | export class DateStorage { | ||
256 | |||
257 | constructor( | ||
258 | private readonly key: string, | ||
259 | private readonly storage: vscode.Memento | ||
260 | ) {} | ||
261 | |||
262 | get(): null | Date { | ||
263 | const date = this.storage.get(this.key, null); | ||
264 | log.debug(this.key, "==", date); | ||
265 | return date ? new Date(date) : null; | ||
266 | } | ||
267 | |||
268 | async set(date: null | Date) { | ||
269 | log.debug(this.key, "=", date); | ||
270 | await this.storage.update(this.key, date); | ||
271 | } | ||
272 | } | ||