From d5b4aa303731b7333b67906ff03311f5f3b6cd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 08:24:58 +0200 Subject: [PATCH 01/13] Remove server download and update checks --- editors/code/src/main.ts | 187 +-------------------------- editors/code/src/persistent_state.ts | 45 ------- 2 files changed, 2 insertions(+), 230 deletions(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index dc0a9a2f872c..06e231a9732f 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -5,9 +5,8 @@ import * as commands from './commands'; import { activateInlayHints } from './inlay_hints'; import { Ctx } from './ctx'; import { Config } from './config'; -import { log, assert, isValidExecutable, isRustDocument } from './util'; +import { log, isValidExecutable, isRustDocument } from './util'; import { PersistentState } from './persistent_state'; -import { fetchRelease, download } from './net'; import { activateTaskProvider } from './tasks'; import { setContextValue } from './util'; import { exec, spawnSync } from 'child_process'; @@ -111,10 +110,6 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) { await activate(context).catch(log.error); }); - ctx.registerCommand('updateGithubToken', ctx => async () => { - await queryForGithubToken(new PersistentState(ctx.globalState)); - }); - ctx.registerCommand('analyzerStatus', commands.analyzerStatus); ctx.registerCommand('memoryUsage', commands.memoryUsage); ctx.registerCommand('shuffleCrateGraph', commands.shuffleCrateGraph); @@ -163,95 +158,10 @@ export async function deactivate() { async function bootstrap(config: Config, state: PersistentState): Promise { await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); - - if (!config.currentExtensionIsNightly) { - await state.updateNightlyReleaseId(undefined); - } - await bootstrapExtension(config, state); const path = await bootstrapServer(config, state); return path; } -async function bootstrapExtension(config: Config, state: PersistentState): Promise { - if (config.package.releaseTag === null) return; - if (config.channel === "stable") { - if (config.currentExtensionIsNightly) { - void vscode.window.showWarningMessage( - `You are running a nightly version of rust-analyzer extension. ` + - `To switch to stable, uninstall the extension and re-install it from the marketplace` - ); - } - return; - }; - if (serverPath(config)) return; - - const now = Date.now(); - const isInitialNightlyDownload = state.nightlyReleaseId === undefined; - if (config.currentExtensionIsNightly) { - // Check if we should poll github api for the new nightly version - // if we haven't done it during the past hour - const lastCheck = state.lastCheck; - - const anHour = 60 * 60 * 1000; - const shouldCheckForNewNightly = isInitialNightlyDownload || (now - (lastCheck ?? 0)) > anHour; - - if (!shouldCheckForNewNightly) return; - } - - const latestNightlyRelease = await downloadWithRetryDialog(state, async () => { - return await fetchRelease("nightly", state.githubToken, config.proxySettings); - }).catch(async (e) => { - log.error(e); - if (isInitialNightlyDownload) { - await vscode.window.showErrorMessage(`Failed to download rust-analyzer nightly: ${e}`); - } - return; - }); - if (latestNightlyRelease === undefined) { - if (isInitialNightlyDownload) { - await vscode.window.showErrorMessage("Failed to download rust-analyzer nightly: empty release contents returned"); - } - return; - } - if (config.currentExtensionIsNightly && latestNightlyRelease.id === state.nightlyReleaseId) return; - - const userResponse = await vscode.window.showInformationMessage( - "New version of rust-analyzer (nightly) is available (requires reload).", - "Update" - ); - if (userResponse !== "Update") return; - - let arch = process.arch; - if (arch === "ia32") { - arch = "x64"; - } - let platform = process.platform as string; - if (platform === "linux" && isMusl()) { - platform = "alpine"; - } - const artifactName = `rust-analyzer-${platform}-${arch}.vsix`; - - const artifact = latestNightlyRelease.assets.find(artifact => artifact.name === artifactName); - assert(!!artifact, `Bad release: ${JSON.stringify(latestNightlyRelease)}`); - const dest = vscode.Uri.joinPath(config.globalStorageUri, "rust-analyzer.vsix"); - - await downloadWithRetryDialog(state, async () => { - await download({ - url: artifact.browser_download_url, - dest, - progressTitle: "Downloading rust-analyzer extension", - proxySettings: config.proxySettings, - }); - }); - - await vscode.commands.executeCommand("workbench.extensions.installExtension", dest); - await vscode.workspace.fs.delete(dest); - - await state.updateNightlyReleaseId(latestNightlyRelease.id); - await state.updateLastCheck(now); - await vscode.commands.executeCommand("workbench.action.reloadWindow"); -} - async function bootstrapServer(config: Config, state: PersistentState): Promise { const path = await getServer(config, state); if (!path) { @@ -356,56 +266,16 @@ async function getServer(config: Config, state: PersistentState): Promise true, () => false); - let exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false); + const exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false); if (bundledExists) { - await state.updateServerVersion(config.package.version); if (!await isNixOs()) { return bundled.fsPath; } if (!exists) { await vscode.workspace.fs.copy(bundled, dest); await patchelf(dest); - exists = true; } } - if (!exists) { - await state.updateServerVersion(undefined); - } - - if (state.serverVersion === config.package.version) return dest.fsPath; - - if (config.askBeforeDownload) { - const userResponse = await vscode.window.showInformationMessage( - `Language server version ${config.package.version} for rust-analyzer is not installed.`, - "Download now" - ); - if (userResponse !== "Download now") return dest.fsPath; - } - - const releaseTag = config.package.releaseTag; - const release = await downloadWithRetryDialog(state, async () => { - return await fetchRelease(releaseTag, state.githubToken, config.proxySettings); - }); - const artifact = release.assets.find(artifact => artifact.name === `rust-analyzer-${platform}.gz`); - assert(!!artifact, `Bad release: ${JSON.stringify(release)}`); - - await downloadWithRetryDialog(state, async () => { - await download({ - url: artifact.browser_download_url, - dest, - progressTitle: "Downloading rust-analyzer server", - gunzip: true, - mode: 0o755, - proxySettings: config.proxySettings, - }); - }); - - // Patching executable if that's NixOS. - if (await isNixOs()) { - await patchelf(dest); - } - - await state.updateServerVersion(config.package.version); return dest.fsPath; } @@ -429,59 +299,6 @@ function isMusl(): boolean { return res.stderr != null && res.stderr.indexOf("musl libc") >= 0; } -async function downloadWithRetryDialog(state: PersistentState, downloadFunc: () => Promise): Promise { - while (true) { - try { - return await downloadFunc(); - } catch (e) { - const selected = await vscode.window.showErrorMessage("Failed to download: " + e.message, {}, { - title: "Update Github Auth Token", - updateToken: true, - }, { - title: "Retry download", - retry: true, - }, { - title: "Dismiss", - }); - - if (selected?.updateToken) { - await queryForGithubToken(state); - continue; - } else if (selected?.retry) { - continue; - } - throw e; - }; - } -} - -async function queryForGithubToken(state: PersistentState): Promise { - const githubTokenOptions: vscode.InputBoxOptions = { - value: state.githubToken, - password: true, - prompt: ` - This dialog allows to store a Github authorization token. - The usage of an authorization token will increase the rate - limit on the use of Github APIs and can thereby prevent getting - throttled. - Auth tokens can be created at https://github.com/settings/tokens`, - }; - - const newToken = await vscode.window.showInputBox(githubTokenOptions); - if (newToken === undefined) { - // The user aborted the dialog => Do not update the stored token - return; - } - - if (newToken === "") { - log.info("Clearing github token"); - await state.updateGithubToken(undefined); - } else { - log.info("Storing new github token"); - await state.updateGithubToken(newToken); - } -} - function warnAboutExtensionConflicts() { const conflicting = [ ["rust-analyzer", "matklad.rust-analyzer"], diff --git a/editors/code/src/persistent_state.ts b/editors/code/src/persistent_state.ts index dd2aeecca354..f6d0a3d015f7 100644 --- a/editors/code/src/persistent_state.ts +++ b/editors/code/src/persistent_state.ts @@ -3,50 +3,5 @@ import { log } from './util'; export class PersistentState { constructor(private readonly globalState: vscode.Memento) { - const { lastCheck, nightlyReleaseId, serverVersion } = this; - log.info("PersistentState:", { lastCheck, nightlyReleaseId, serverVersion }); - } - - /** - * Used to check for *nightly* updates once an hour. - */ - get lastCheck(): number | undefined { - return this.globalState.get("lastCheck"); - } - async updateLastCheck(value: number) { - await this.globalState.update("lastCheck", value); - } - - /** - * Release id of the *nightly* extension. - * Used to check if we should update. - */ - get nightlyReleaseId(): number | undefined { - return this.globalState.get("releaseId"); - } - async updateNightlyReleaseId(value: number | undefined) { - await this.globalState.update("releaseId", value); - } - - /** - * Version of the extension that installed the server. - * Used to check if we need to update the server. - */ - get serverVersion(): string | undefined { - return this.globalState.get("serverVersion"); - } - async updateServerVersion(value: string | undefined) { - await this.globalState.update("serverVersion", value); - } - - /** - * Github authorization token. - * This is used for API requests against the Github API. - */ - get githubToken(): string | undefined { - return this.globalState.get("githubToken"); - } - async updateGithubToken(value: string | undefined) { - await this.globalState.update("githubToken", value); } } From 53c183cc13a1149f6be6c746b56455e9ae355596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 08:28:25 +0200 Subject: [PATCH 02/13] Remove network functions --- editors/code/src/net.ts | 228 ---------------------------------------- 1 file changed, 228 deletions(-) delete mode 100644 editors/code/src/net.ts diff --git a/editors/code/src/net.ts b/editors/code/src/net.ts deleted file mode 100644 index bd1bb5f8a8a8..000000000000 --- a/editors/code/src/net.ts +++ /dev/null @@ -1,228 +0,0 @@ -import fetch from "node-fetch"; -var HttpsProxyAgent = require('https-proxy-agent'); - -import * as vscode from "vscode"; -import * as stream from "stream"; -import * as crypto from "crypto"; -import * as fs from "fs"; -import * as zlib from "zlib"; -import * as util from "util"; -import * as path from "path"; -import { log, assert } from "./util"; -import * as https from "https"; -import { ProxySettings } from "./config"; - -const pipeline = util.promisify(stream.pipeline); - -const GITHUB_API_ENDPOINT_URL = "https://api.github.com"; -const OWNER = "rust-analyzer"; -const REPO = "rust-analyzer"; - -function makeHttpAgent(proxy: string | null | undefined, options?: https.AgentOptions) { - if (proxy) { - return new HttpsProxyAgent({ ...options, ...new URL(proxy) }); - } else { - return new https.Agent(options); - } -} - -export async function fetchRelease( - releaseTag: string, - githubToken: string | null | undefined, - proxySettings: ProxySettings, -): Promise { - - const apiEndpointPath = `/repos/${OWNER}/${REPO}/releases/tags/${releaseTag}`; - - const requestUrl = GITHUB_API_ENDPOINT_URL + apiEndpointPath; - - log.debug("Issuing request for released artifacts metadata to", requestUrl); - - const headers: Record = { Accept: "application/vnd.github.v3+json" }; - if (githubToken != null) { - headers.Authorization = "token " + githubToken; - } - - const response = await (() => { - if (proxySettings.proxy) { - log.debug(`Fetching release metadata via proxy: ${proxySettings.proxy}`); - } - const options: any = {}; - if (proxySettings.strictSSL) { - options["rejectUnauthorized"] = false; - } - const agent = makeHttpAgent(proxySettings.proxy, options); - return fetch(requestUrl, { headers: headers, agent: agent }); - })(); - - if (!response.ok) { - log.error("Error fetching artifact release info", { - requestUrl, - releaseTag, - response: { - headers: response.headers, - status: response.status, - body: await response.text(), - } - }); - - throw new Error( - `Got response ${response.status} when trying to fetch ` + - `release info for ${releaseTag} release` - ); - } - - // We skip runtime type checks for simplicity (here we cast from `unknown` to `GithubRelease`) - const release = await response.json() as GithubRelease; - return release; -} - -// We omit declaration of tremendous amount of fields that we are not using here -export interface GithubRelease { - name: string; - id: number; - // eslint-disable-next-line camelcase - published_at: string; - assets: Array<{ - name: string; - // eslint-disable-next-line camelcase - browser_download_url: vscode.Uri; - }>; -} - -interface DownloadOpts { - progressTitle: string; - url: vscode.Uri; - dest: vscode.Uri; - mode?: number; - gunzip?: boolean; - proxySettings: ProxySettings; -} - -export async function download(opts: DownloadOpts) { - // Put artifact into a temporary file (in the same dir for simplicity) - // to prevent partially downloaded files when user kills vscode - // This also avoids overwriting running executables - const randomHex = crypto.randomBytes(5).toString("hex"); - const rawDest = path.parse(opts.dest.fsPath); - const oldServerPath = vscode.Uri.joinPath(vscode.Uri.file(rawDest.dir), `${rawDest.name}-stale-${randomHex}${rawDest.ext}`); - const tempFilePath = vscode.Uri.joinPath(vscode.Uri.file(rawDest.dir), `${rawDest.name}${randomHex}`); - - await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - cancellable: false, - title: opts.progressTitle - }, - async (progress, _cancellationToken) => { - let lastPercentage = 0; - await downloadFile(opts.url, tempFilePath, opts.mode, !!opts.gunzip, opts.proxySettings, (readBytes, totalBytes) => { - const newPercentage = Math.round((readBytes / totalBytes) * 100); - if (newPercentage !== lastPercentage) { - progress.report({ - message: `${newPercentage.toFixed(0)}%`, - increment: newPercentage - lastPercentage - }); - - lastPercentage = newPercentage; - } - }); - } - ); - - // Try to rename a running server to avoid EPERM on Windows - // NB: this can lead to issues if a running Code instance tries to restart the server. - try { - await vscode.workspace.fs.rename(opts.dest, oldServerPath, { overwrite: true }); - log.info(`Renamed old server binary ${opts.dest.fsPath} to ${oldServerPath.fsPath}`); - } catch (err) { - const fsErr = err as vscode.FileSystemError; - - // This is supposed to return `FileNotFound` (spelled as `EntryNotFound`) - // but instead `code` is `Unknown` and `name` is `EntryNotFound (FileSystemError) (FileSystemError)`. - // https://github.com/rust-analyzer/rust-analyzer/pull/10222 - if (!fsErr.code || fsErr.code !== "EntryNotFound" && fsErr.name.indexOf("EntryNotFound") === -1) { - log.error(`Cannot rename existing server instance: ${err}"`); - } - } - try { - await vscode.workspace.fs.rename(tempFilePath, opts.dest, { overwrite: true }); - } catch (err) { - log.error(`Cannot update server binary: ${err}`); - } - - // Now try to remove any stale server binaries - const serverDir = vscode.Uri.file(rawDest.dir); - try { - const entries = await vscode.workspace.fs.readDirectory(serverDir); - for (const [entry, _] of entries) { - try { - if (entry.includes(`${rawDest.name}-stale-`)) { - const uri = vscode.Uri.joinPath(serverDir, entry); - try { - await vscode.workspace.fs.delete(uri); - log.info(`Removed old server binary ${uri.fsPath}`); - } catch (err) { - log.error(`Unable to remove old server binary ${uri.fsPath}`); - } - } - } catch (err) { - log.error(`Unable to parse ${entry}`); - } - } - } catch (err) { - log.error(`Unable to enumerate contents of ${serverDir.fsPath}`); - } -} - -async function downloadFile( - url: vscode.Uri, - destFilePath: vscode.Uri, - mode: number | undefined, - gunzip: boolean, - proxySettings: ProxySettings, - onProgress: (readBytes: number, totalBytes: number) => void -): Promise { - const urlString = url.toString(); - - const res = await (() => { - if (proxySettings.proxy) { - log.debug(`Downloading ${urlString} via proxy: ${proxySettings.proxy}`); - } - const options: any = {}; - if (proxySettings.strictSSL) { - options["rejectUnauthorized"] = false; - } - const agent = makeHttpAgent(proxySettings.proxy, options); - return fetch(urlString, { agent: agent }); - })(); - - if (!res.ok) { - log.error("Error", res.status, "while downloading file from", urlString); - log.error({ body: await res.text(), headers: res.headers }); - - throw new Error(`Got response ${res.status} when trying to download a file.`); - } - - if (!res.body) { - log.error("Empty body while downloading file from", urlString); - log.error({ headers: res.headers }); - throw new Error(`Got empty body when trying to download a file.`); - } - - const totalBytes = Number(res.headers.get('content-length')); - assert(!Number.isNaN(totalBytes), "Sanity check of content-length protocol"); - - log.debug("Downloading file of", totalBytes, "bytes size from", urlString, "to", destFilePath.fsPath); - - let readBytes = 0; - res.body.on("data", (chunk: Buffer) => { - readBytes += chunk.length; - onProgress(readBytes, totalBytes); - }); - - const destFileStream = fs.createWriteStream(destFilePath.fsPath, { mode }); - const srcStream = gunzip ? res.body.pipe(zlib.createGunzip()) : res.body; - - await pipeline(srcStream, destFileStream); -} From c68dbc16f8a68b479631bfa1c148c509caf47978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 08:31:16 +0200 Subject: [PATCH 03/13] Remove node-fetch and https-proxy-agent deps --- editors/code/package-lock.json | 115 +++------------------------------ editors/code/package.json | 2 - 2 files changed, 10 insertions(+), 107 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 8728654662c6..4aa9ac9d4301 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -11,8 +11,6 @@ "dependencies": { "d3": "^7.2.0", "d3-graphviz": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^3.0.3", "vscode-languageclient": "8.0.0-next.2" }, "devDependencies": { @@ -345,6 +343,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "dependencies": { "debug": "4" }, @@ -1274,18 +1273,11 @@ "node": ">=12" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", - "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", - "engines": { - "node": ">= 12" - } - }, "node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2059,27 +2051,6 @@ "pend": "~1.2.0" } }, - "node_modules/fetch-blob": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.3.tgz", - "integrity": "sha512-ax1Y5I9w+9+JiM+wdHkhBoxew+zG4AJ2SvAD1v1szpddUIiPERVGBxrMcB2ZqW0Y3PP8bOWYv2zqQq1Jp2kqUQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2123,17 +2094,6 @@ "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", "dev": true }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -2403,6 +2363,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -2770,7 +2731,8 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/mute-stream": { "version": "0.0.8", @@ -2814,23 +2776,6 @@ "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", "dev": true }, - "node_modules/node-fetch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.1.0.tgz", - "integrity": "sha512-QU0WbIfMUjd5+MUzQOYhenAazakV7Irh1SGkWCsRzBwvm4fAhzEUaHMJ6QLP7gWT6WO9/oH2zhKMMGMuIrDyKw==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.2", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -3866,14 +3811,6 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.3.tgz", "integrity": "sha512-VQcXnhKYxUW6OiRMhG++SzmZYMJwusXknJGd+FfdOnS1yHAo734OHyR0e2eEHDlv0/oWc8RZPgx/VKSKyondVg==" }, - "node_modules/web-streams-polyfill": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", - "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==", - "engines": { - "node": ">= 8" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4170,6 +4107,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "requires": { "debug": "4" } @@ -4874,15 +4812,11 @@ "d3-transition": "2 - 3" } }, - "data-uri-to-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", - "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" - }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -5434,14 +5368,6 @@ "pend": "~1.2.0" } }, - "fetch-blob": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.3.tgz", - "integrity": "sha512-ax1Y5I9w+9+JiM+wdHkhBoxew+zG4AJ2SvAD1v1szpddUIiPERVGBxrMcB2ZqW0Y3PP8bOWYv2zqQq1Jp2kqUQ==", - "requires": { - "web-streams-polyfill": "^3.0.3" - } - }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -5476,14 +5402,6 @@ "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", "dev": true }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "requires": { - "fetch-blob": "^3.1.2" - } - }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -5696,6 +5614,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, "requires": { "agent-base": "6", "debug": "4" @@ -5978,7 +5897,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "mute-stream": { "version": "0.0.8", @@ -6021,16 +5941,6 @@ "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", "dev": true }, - "node-fetch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.1.0.tgz", - "integrity": "sha512-QU0WbIfMUjd5+MUzQOYhenAazakV7Irh1SGkWCsRzBwvm4fAhzEUaHMJ6QLP7gWT6WO9/oH2zhKMMGMuIrDyKw==", - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.2", - "formdata-polyfill": "^4.0.10" - } - }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -6827,11 +6737,6 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.3.tgz", "integrity": "sha512-VQcXnhKYxUW6OiRMhG++SzmZYMJwusXknJGd+FfdOnS1yHAo734OHyR0e2eEHDlv0/oWc8RZPgx/VKSKyondVg==" }, - "web-streams-polyfill": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", - "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==" - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index 9ab57d7dc5f3..fc78b2830ac3 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -36,8 +36,6 @@ "test": "node ./out/tests/runTests.js" }, "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^3.0.3", "vscode-languageclient": "8.0.0-next.2", "d3": "^7.2.0", "d3-graphviz": "^4.0.0" From 650ec14e4f083316b6341dd3a52f734ec449d10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 08:32:58 +0200 Subject: [PATCH 04/13] Remove channel and ask before download prefs --- editors/code/package.json | 18 ------------------ editors/code/src/config.ts | 3 --- 2 files changed, 21 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index fc78b2830ac3..550b28e1cdb2 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -303,24 +303,6 @@ "default": true, "description": "Whether inlay hints font size should be smaller than editor's font size." }, - "rust-analyzer.updates.channel": { - "type": "string", - "enum": [ - "stable", - "nightly" - ], - "default": "stable", - "markdownEnumDescriptions": [ - "`stable` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general.", - "`nightly` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**." - ], - "markdownDescription": "Choose `nightly` updates to get the latest features and bug fixes every day. While `stable` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs." - }, - "rust-analyzer.updates.askBeforeDownload": { - "type": "boolean", - "default": false, - "description": "Whether to ask for permission before downloading any files from the Internet." - }, "rust-analyzer.server.path": { "type": [ "null", diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index cb0868db5979..0178e4bb8708 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -24,7 +24,6 @@ export class Config { "procMacro", "files", "highlighting", - "updates.channel", "lens", // works as lens.* ] .map(opt => `${this.rootSection}.${opt}`); @@ -103,8 +102,6 @@ export class Config { return this.get("server.path") ?? this.get("serverPath"); } get serverExtraEnv() { return this.get("server.extraEnv") ?? {}; } - get channel() { return this.get("updates.channel"); } - get askBeforeDownload() { return this.get("updates.askBeforeDownload"); } get traceExtension() { return this.get("trace.extension"); } get proxySettings(): ProxySettings { const proxy = vscode From f63690c058dbffcf334e3eb67a73102b30504d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 08:33:34 +0200 Subject: [PATCH 05/13] Remove proxy settings --- editors/code/src/config.ts | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 0178e4bb8708..9ed573ccf5c0 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -8,11 +8,6 @@ const NIGHTLY_TAG = "nightly"; export type RunnableEnvCfg = undefined | Record | { mask?: string; env: Record }[]; -export class ProxySettings { - proxy?: string = undefined; - strictSSL: boolean = true; -} - export class Config { readonly extensionId = "matklad.rust-analyzer"; @@ -103,18 +98,6 @@ export class Config { } get serverExtraEnv() { return this.get("server.extraEnv") ?? {}; } get traceExtension() { return this.get("trace.extension"); } - get proxySettings(): ProxySettings { - const proxy = vscode - .workspace - .getConfiguration('http') - .get("proxy")! || process.env["https_proxy"] || process.env["HTTPS_PROXY"]; - const strictSSL = vscode.workspace.getConfiguration("http").get("proxyStrictSSL") ?? true; - - return { - proxy: proxy, - strictSSL: strictSSL, - }; - } get inlayHints() { return { From e97569c998e87288fe7730e1d8bed0def6bda120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 08:44:23 +0200 Subject: [PATCH 06/13] Drop extensionUri copy --- editors/code/src/config.ts | 2 -- editors/code/src/main.ts | 14 +++++--------- editors/code/src/persistent_state.ts | 13 +++++++++++++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 9ed573ccf5c0..cdbaa67fe22c 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -30,11 +30,9 @@ export class Config { } = vscode.extensions.getExtension(this.extensionId)!.packageJSON; readonly globalStorageUri: vscode.Uri; - readonly installUri: vscode.Uri; constructor(ctx: vscode.ExtensionContext) { this.globalStorageUri = ctx.globalStorageUri; - this.installUri = ctx.extensionUri; vscode.workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, ctx.subscriptions); this.refreshLogging(); } diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 06e231a9732f..74fdc59a1ef7 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -156,14 +156,10 @@ export async function deactivate() { ctx = undefined; } -async function bootstrap(config: Config, state: PersistentState): Promise { +async function bootstrap(context: vscode.ExtensionContext, config: Config, state: PersistentState): Promise { await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); - const path = await bootstrapServer(config, state); - return path; -} -async function bootstrapServer(config: Config, state: PersistentState): Promise { - const path = await getServer(config, state); + const path = await getServer(context, config, state); if (!path) { throw new Error( "Rust Analyzer Language Server is not available. " + @@ -228,7 +224,7 @@ async function patchelf(dest: vscode.Uri): Promise { ); } -async function getServer(config: Config, state: PersistentState): Promise { +async function getServer(context: vscode.ExtensionContext, config: Config, state: PersistentState): Promise { const explicitPath = serverPath(config); if (explicitPath) { if (explicitPath.startsWith("~/")) { @@ -264,14 +260,14 @@ async function getServer(config: Config, state: PersistentState): Promise true, () => false); const exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false); if (bundledExists) { if (!await isNixOs()) { return bundled.fsPath; } - if (!exists) { + if (!exists || config.package.version !== state.serverVersion) { await vscode.workspace.fs.copy(bundled, dest); await patchelf(dest); } diff --git a/editors/code/src/persistent_state.ts b/editors/code/src/persistent_state.ts index f6d0a3d015f7..3e86ed1e3231 100644 --- a/editors/code/src/persistent_state.ts +++ b/editors/code/src/persistent_state.ts @@ -3,5 +3,18 @@ import { log } from './util'; export class PersistentState { constructor(private readonly globalState: vscode.Memento) { + const { serverVersion } = this; + log.info("PersistentState:", { serverVersion }); + } + + /** + * Version of the extension that installed the server. + * Used to check if we need to run patchelf again on NixOS. + */ + get serverVersion(): string | undefined { + return this.globalState.get("serverVersion"); + } + async updateServerVersion(value: string | undefined) { + await this.globalState.update("serverVersion", value); } } From 3835b3790ea9ddcf97e992c640324744e7e5db49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 09:49:24 +0200 Subject: [PATCH 07/13] Improve NixOS handling --- editors/code/src/main.ts | 63 ++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 74fdc59a1ef7..4628bf4b3c52 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -27,7 +27,7 @@ export async function activate(context: vscode.ExtensionContext) { async function tryActivate(context: vscode.ExtensionContext) { const config = new Config(context); const state = new PersistentState(context.globalState); - const serverPath = await bootstrap(config, state).catch(err => { + const serverPath = await bootstrap(context, config, state).catch(err => { let message = "bootstrap error. "; if (err.code === "EBUSY" || err.code === "ETXTBSY" || err.code === "EPERM") { @@ -157,8 +157,6 @@ export async function deactivate() { } async function bootstrap(context: vscode.ExtensionContext, config: Config, state: PersistentState): Promise { - await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); - const path = await getServer(context, config, state); if (!path) { throw new Error( @@ -244,35 +242,42 @@ async function getServer(context: vscode.ExtensionContext, config: Config, state "arm64 darwin": "aarch64-apple-darwin", }; let platform = platforms[`${process.arch} ${process.platform}`]; - if (platform === undefined) { - await vscode.window.showErrorMessage( - "Unfortunately we don't ship binaries for your platform yet. " + - "You need to manually clone rust-analyzer repository and " + - "run `cargo xtask install --server` to build the language server from sources. " + - "If you feel that your platform should be supported, please create an issue " + - "about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we " + - "will consider it." - ); - return undefined; - } - if (platform === "x86_64-unknown-linux-gnu" && isMusl()) { - platform = "x86_64-unknown-linux-musl"; - } - const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : ""; - const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer-${platform}${ext}`); - const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`); - const bundledExists = await vscode.workspace.fs.stat(bundled).then(() => true, () => false); - const exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false); - if (bundledExists) { - if (!await isNixOs()) { - return bundled.fsPath; + if (platform) { + if (platform === "x86_64-unknown-linux-gnu" && isMusl()) { + platform = "x86_64-unknown-linux-musl"; } - if (!exists || config.package.version !== state.serverVersion) { - await vscode.workspace.fs.copy(bundled, dest); - await patchelf(dest); + const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : ""; + const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`); + const bundledExists = await vscode.workspace.fs.stat(bundled).then(() => true, () => false); + if (bundledExists) { + let server = bundled; + if (await isNixOs()) { + await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); + const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer-${platform}${ext}`); + let exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false); + if (exists && config.package.version !== state.serverVersion) { + await vscode.workspace.fs.delete(dest); + exists = false; + } + if (!exists) { + await vscode.workspace.fs.copy(bundled, dest); + await patchelf(dest); + server = dest; + } + } + await state.updateServerVersion(config.package.version); + return server.fsPath; } } - return dest.fsPath; + await vscode.window.showErrorMessage( + "Unfortunately we don't ship binaries for your platform yet. " + + "You need to manually clone rust-analyzer repository and " + + "run `cargo xtask install --server` to build the language server from sources. " + + "If you feel that your platform should be supported, please create an issue " + + "about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we " + + "will consider it." + ); + return undefined; } function serverPath(config: Config): string | null { From 8b304a72f6a85a1463225d73041a28b234ca26e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 09:50:09 +0200 Subject: [PATCH 08/13] Remove ETXTBUSY check, we don't overwrite binaries --- editors/code/src/main.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 4628bf4b3c52..3652a613cf2d 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -30,11 +30,6 @@ async function tryActivate(context: vscode.ExtensionContext) { const serverPath = await bootstrap(context, config, state).catch(err => { let message = "bootstrap error. "; - if (err.code === "EBUSY" || err.code === "ETXTBSY" || err.code === "EPERM") { - message += "Other vscode windows might be using rust-analyzer, "; - message += "you should close them and reload this window to retry. "; - } - message += 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). '; message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }'; From f55cca4d3b895aa59a31f2470ae13b0cd9838dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 09:55:39 +0200 Subject: [PATCH 09/13] Update privacy note --- PRIVACY.md | 2 +- docs/user/manual.adoc | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/PRIVACY.md b/PRIVACY.md index 718fbed12069..89e252be731d 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1 +1 @@ -See the [Privacy](https://rust-analyzer.github.io/manual.html#security) section of the user manual. +See the [Privacy](https://rust-analyzer.github.io/manual.html#privacy) section of the user manual. diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 1335f8df7c01..13165e8d3f0f 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc @@ -653,10 +653,12 @@ Here is a **non-exhaustive** list of ways to make rust-analyzer execute arbitrar The LSP server performs no network access in itself, but runs `cargo metadata` which will update or download the crate registry and the source code of the project dependencies. If enabled (the default), build scripts and procedural macros can do anything. -The Code extension automatically connects to GitHub to download updated LSP binaries and, if the nightly channel is selected, to perform update checks using the GitHub API. For `rust-analyzer` developers, using `cargo xtask release` uses the same API to put together the release notes. +The Code extension does not access the network. Any other editor plugins are not under the control of the `rust-analyzer` developers. For any privacy concerns, you should check with their respective developers. +For `rust-analyzer` developers, `cargo xtask release` uses the GitHub API to put together the release notes. + == Features include::./generated_features.adoc[] From c0d0ceefb29111732cacf39dbb57fe9f3ce25ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 13:04:27 +0200 Subject: [PATCH 10/13] Don't check for platform details --- editors/code/src/main.ts | 64 ++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 42 deletions(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 3652a613cf2d..3145326bc1cd 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -9,7 +9,7 @@ import { log, isValidExecutable, isRustDocument } from './util'; import { PersistentState } from './persistent_state'; import { activateTaskProvider } from './tasks'; import { setContextValue } from './util'; -import { exec, spawnSync } from 'child_process'; +import { exec } from 'child_process'; let ctx: Ctx | undefined; @@ -227,43 +227,30 @@ async function getServer(context: vscode.ExtensionContext, config: Config, state }; if (config.package.releaseTag === null) return "rust-analyzer"; - const platforms: { [key: string]: string } = { - "ia32 win32": "x86_64-pc-windows-msvc", - "x64 win32": "x86_64-pc-windows-msvc", - "x64 linux": "x86_64-unknown-linux-gnu", - "x64 darwin": "x86_64-apple-darwin", - "arm64 win32": "aarch64-pc-windows-msvc", - "arm64 linux": "aarch64-unknown-linux-gnu", - "arm64 darwin": "aarch64-apple-darwin", - }; - let platform = platforms[`${process.arch} ${process.platform}`]; - if (platform) { - if (platform === "x86_64-unknown-linux-gnu" && isMusl()) { - platform = "x86_64-unknown-linux-musl"; - } - const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : ""; - const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`); - const bundledExists = await vscode.workspace.fs.stat(bundled).then(() => true, () => false); - if (bundledExists) { - let server = bundled; - if (await isNixOs()) { - await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); - const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer-${platform}${ext}`); - let exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false); - if (exists && config.package.version !== state.serverVersion) { - await vscode.workspace.fs.delete(dest); - exists = false; - } - if (!exists) { - await vscode.workspace.fs.copy(bundled, dest); - await patchelf(dest); - server = dest; - } + const ext = process.platform === "win32" ? ".exe" : ""; + const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`); + const bundledExists = await vscode.workspace.fs.stat(bundled).then(() => true, () => false); + if (bundledExists) { + let server = bundled; + if (await isNixOs()) { + await vscode.workspace.fs.createDirectory(config.globalStorageUri).then(); + const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer${ext}`); + let exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false); + if (exists && config.package.version !== state.serverVersion) { + await vscode.workspace.fs.delete(dest); + exists = false; + } + if (!exists) { + await vscode.workspace.fs.copy(bundled, dest); + await patchelf(dest); + server = dest; } - await state.updateServerVersion(config.package.version); - return server.fsPath; } + await state.updateServerVersion(config.package.version); + return server.fsPath; } + + await state.updateServerVersion(undefined); await vscode.window.showErrorMessage( "Unfortunately we don't ship binaries for your platform yet. " + "You need to manually clone rust-analyzer repository and " + @@ -288,13 +275,6 @@ async function isNixOs(): Promise { } } -function isMusl(): boolean { - // We can detect Alpine by checking `/etc/os-release` but not Void Linux musl. - // Instead, we run `ldd` since it advertises the libc which it belongs to. - const res = spawnSync("ldd", ["--version"]); - return res.stderr != null && res.stderr.indexOf("musl libc") >= 0; -} - function warnAboutExtensionConflicts() { const conflicting = [ ["rust-analyzer", "matklad.rust-analyzer"], From f8724198476fec2dc297e7e0813e243f9b822bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 13:05:58 +0200 Subject: [PATCH 11/13] Drop kalitaalexey.vscode-rust check --- editors/code/src/main.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 3145326bc1cd..f1993d7df20c 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -279,7 +279,6 @@ function warnAboutExtensionConflicts() { const conflicting = [ ["rust-analyzer", "matklad.rust-analyzer"], ["Rust", "rust-lang.rust"], - ["Rust", "kalitaalexey.vscode-rust"], ]; const found = conflicting.filter( From 5bed9d6188f9489e1ea047412b5fb88bb30a63ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 13:08:06 +0200 Subject: [PATCH 12/13] Simplify conflict check --- editors/code/src/main.ts | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index f1993d7df20c..aac5cffa962c 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -276,23 +276,13 @@ async function isNixOs(): Promise { } function warnAboutExtensionConflicts() { - const conflicting = [ - ["rust-analyzer", "matklad.rust-analyzer"], - ["Rust", "rust-lang.rust"], - ]; - - const found = conflicting.filter( - nameId => vscode.extensions.getExtension(nameId[1]) !== undefined); - - if (found.length > 1) { - const fst = found[0]; - const sec = found[1]; + if (vscode.extensions.getExtension("rust-lang.rust")) { vscode.window.showWarningMessage( - `You have both the ${fst[0]} (${fst[1]}) and ${sec[0]} (${sec[1]}) ` + + `You have both the rust-analyzer (matklad.rust-analyzer) and Rust (rust-lang.rust) ` + "plugins enabled. These are known to conflict and cause various functions of " + "both plugins to not work correctly. You should disable one of them.", "Got it") .then(() => { }, console.error); - }; + } } /** From af2bbce8d97ef58de4681493509837de38b8b7fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 23 Dec 2021 14:04:46 +0200 Subject: [PATCH 13/13] Spelling fix --- editors/code/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index aac5cffa962c..df7580b9bc52 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -253,7 +253,7 @@ async function getServer(context: vscode.ExtensionContext, config: Config, state await state.updateServerVersion(undefined); await vscode.window.showErrorMessage( "Unfortunately we don't ship binaries for your platform yet. " + - "You need to manually clone rust-analyzer repository and " + + "You need to manually clone the rust-analyzer repository and " + "run `cargo xtask install --server` to build the language server from sources. " + "If you feel that your platform should be supported, please create an issue " + "about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we " +