From f61134e1980580050f34701db3441081a5519e4c Mon Sep 17 00:00:00 2001 From: Veetaha Date: Sat, 15 Feb 2020 00:15:06 +0200 Subject: vscode: renmed ArtifactMetadata -> ArtifactReleaseInfo, languageServer -> langServer --- editors/code/src/client.ts | 4 +- .../installation/fetch_latest_artifact_metadata.ts | 46 ------- .../fetch_latest_artifact_release_info.ts | 46 +++++++ editors/code/src/installation/interfaces.ts | 2 +- editors/code/src/installation/lang_server.ts | 148 +++++++++++++++++++++ editors/code/src/installation/language_server.ts | 148 --------------------- 6 files changed, 197 insertions(+), 197 deletions(-) delete mode 100644 editors/code/src/installation/fetch_latest_artifact_metadata.ts create mode 100644 editors/code/src/installation/fetch_latest_artifact_release_info.ts create mode 100644 editors/code/src/installation/lang_server.ts delete mode 100644 editors/code/src/installation/language_server.ts (limited to 'editors') diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index dcf9d0c06..33d9b66df 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -2,7 +2,7 @@ import * as lc from 'vscode-languageclient'; import * as vscode from 'vscode'; import { Config } from './config'; -import { ensureLanguageServerBinary } from './installation/language_server'; +import { ensureLangServerBinary } from './installation/lang_server'; import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.proposed'; export async function createClient(config: Config): Promise { @@ -11,7 +11,7 @@ export async function createClient(config: Config): Promise { - - const repoOwner = encodeURIComponent(repo.owner); - const repoName = encodeURIComponent(repo.name); - - const apiEndpointPath = `/repos/${repoOwner}/${repoName}/releases/latest`; - const requestUrl = GITHUB_API_ENDPOINT_URL + apiEndpointPath; - - // We skip runtime type checks for simplicity (here we cast from `any` to `GithubRelease`) - - console.log("Issuing request for released artifacts metadata to", requestUrl); - - const response: GithubRelease = await fetch(requestUrl, { - headers: { Accept: "application/vnd.github.v3+json" } - }) - .then(res => res.json()); - - const artifact = response.assets.find(artifact => artifact.name === artifactFileName); - - if (!artifact) return null; - - return { - releaseName: response.name, - downloadUrl: artifact.browser_download_url - }; - - // We omit declaration of tremendous amount of fields that we are not using here - interface GithubRelease { - name: string; - assets: Array<{ - name: string; - browser_download_url: string; - }>; - } -} diff --git a/editors/code/src/installation/fetch_latest_artifact_release_info.ts b/editors/code/src/installation/fetch_latest_artifact_release_info.ts new file mode 100644 index 000000000..29ee029a7 --- /dev/null +++ b/editors/code/src/installation/fetch_latest_artifact_release_info.ts @@ -0,0 +1,46 @@ +import fetch from "node-fetch"; +import { GithubRepo, ArtifactReleaseInfo } from "./interfaces"; + +const GITHUB_API_ENDPOINT_URL = "https://api.github.com"; + +/** + * Fetches the latest release from GitHub `repo` and returns metadata about + * `artifactFileName` shipped with this release or `null` if no such artifact was published. + */ +export async function fetchLatestArtifactReleaseInfo( + repo: GithubRepo, artifactFileName: string +): Promise { + + const repoOwner = encodeURIComponent(repo.owner); + const repoName = encodeURIComponent(repo.name); + + const apiEndpointPath = `/repos/${repoOwner}/${repoName}/releases/latest`; + const requestUrl = GITHUB_API_ENDPOINT_URL + apiEndpointPath; + + // We skip runtime type checks for simplicity (here we cast from `any` to `GithubRelease`) + + console.log("Issuing request for released artifacts metadata to", requestUrl); + + const response: GithubRelease = await fetch(requestUrl, { + headers: { Accept: "application/vnd.github.v3+json" } + }) + .then(res => res.json()); + + const artifact = response.assets.find(artifact => artifact.name === artifactFileName); + + if (!artifact) return null; + + return { + releaseName: response.name, + downloadUrl: artifact.browser_download_url + }; + + // We omit declaration of tremendous amount of fields that we are not using here + interface GithubRelease { + name: string; + assets: Array<{ + name: string; + browser_download_url: string; + }>; + } +} diff --git a/editors/code/src/installation/interfaces.ts b/editors/code/src/installation/interfaces.ts index 8039d0b90..93ea577d4 100644 --- a/editors/code/src/installation/interfaces.ts +++ b/editors/code/src/installation/interfaces.ts @@ -6,7 +6,7 @@ export interface GithubRepo { /** * Metadata about particular artifact retrieved from GitHub releases. */ -export interface ArtifactMetadata { +export interface ArtifactReleaseInfo { releaseName: string; downloadUrl: string; } diff --git a/editors/code/src/installation/lang_server.ts b/editors/code/src/installation/lang_server.ts new file mode 100644 index 000000000..ccb936bf5 --- /dev/null +++ b/editors/code/src/installation/lang_server.ts @@ -0,0 +1,148 @@ +import * as vscode from "vscode"; +import * as path from "path"; +import { strict as assert } from "assert"; +import { promises as fs } from "fs"; +import { promises as dns } from "dns"; +import { spawnSync } from "child_process"; +import { throttle } from "throttle-debounce"; + +import { BinarySource } from "./interfaces"; +import { fetchLatestArtifactReleaseInfo } from "./fetch_latest_artifact_release_info"; +import { downloadFile } from "./download_file"; + +export async function downloadLatestLangServer( + {file: artifactFileName, dir: installationDir, repo}: BinarySource.GithubRelease +) { + const { releaseName, downloadUrl } = (await fetchLatestArtifactReleaseInfo( + repo, artifactFileName + ))!; + + await fs.mkdir(installationDir).catch(err => assert.strictEqual( + err?.code, + "EEXIST", + `Couldn't create directory "${installationDir}" to download `+ + `language server binary: ${err.message}` + )); + + const installationPath = path.join(installationDir, artifactFileName); + + console.time("Downloading ra_lsp_server"); + await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + cancellable: false, // FIXME: add support for canceling download? + title: `Downloading language server (${releaseName})` + }, + async (progress, _cancellationToken) => { + let lastPrecentage = 0; + const filePermissions = 0o755; // (rwx, r_x, r_x) + await downloadFile(downloadUrl, installationPath, filePermissions, throttle( + 200, + /* noTrailing: */ true, + (readBytes, totalBytes) => { + const newPercentage = (readBytes / totalBytes) * 100; + progress.report({ + message: newPercentage.toFixed(0) + "%", + increment: newPercentage - lastPrecentage + }); + + lastPrecentage = newPercentage; + }) + ); + } + ); + console.timeEnd("Downloading ra_lsp_server"); +} +export async function ensureLangServerBinary( + langServerSource: null | BinarySource +): Promise { + + if (!langServerSource) { + 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 null; + } + + switch (langServerSource.type) { + case BinarySource.Type.ExplicitPath: { + if (isBinaryAvailable(langServerSource.path)) { + return langServerSource.path; + } + + vscode.window.showErrorMessage( + `Unable to run ${langServerSource.path} binary. ` + + `To use the pre-built language server, set "rust-analyzer.raLspServerPath" ` + + "value to `null` or remove it from the settings to use it by default." + ); + return null; + } + case BinarySource.Type.GithubRelease: { + const prebuiltBinaryPath = path.join(langServerSource.dir, langServerSource.file); + + if (isBinaryAvailable(prebuiltBinaryPath)) { + return prebuiltBinaryPath; + } + + const userResponse = await vscode.window.showInformationMessage( + "Language server binary for rust-analyzer was not found. " + + "Do you want to download it now?", + "Download now", "Cancel" + ); + if (userResponse !== "Download now") return null; + + try { + await downloadLatestLangServer(langServerSource); + } catch (err) { + vscode.window.showErrorMessage( + `Failed to download language server from ${langServerSource.repo.name} ` + + `GitHub repository: ${err.message}` + ); + + console.error(err); + + dns.resolve('example.com').then( + addrs => console.log("DNS resolution for example.com was successful", addrs), + err => { + console.error( + "DNS resolution for example.com failed, " + + "there might be an issue with Internet availability" + ); + console.error(err); + } + ); + + return null; + } + + if (!isBinaryAvailable(prebuiltBinaryPath)) assert(false, + `Downloaded language server binary is not functional.` + + `Downloaded from: ${JSON.stringify(langServerSource)}` + ); + + + vscode.window.showInformationMessage( + "Rust analyzer language server was successfully installed 🦀" + ); + + return prebuiltBinaryPath; + } + } + + function isBinaryAvailable(binaryPath: string) { + const res = spawnSync(binaryPath, ["--version"]); + + // ACHTUNG! `res` type declaration is inherently wrong, see + // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/42221 + + console.log("Checked binary availablity via --version", res); + console.log(binaryPath, "--version output:", res.output?.map(String)); + + return res.status === 0; + } +} diff --git a/editors/code/src/installation/language_server.ts b/editors/code/src/installation/language_server.ts deleted file mode 100644 index 4797c3f01..000000000 --- a/editors/code/src/installation/language_server.ts +++ /dev/null @@ -1,148 +0,0 @@ -import * as vscode from "vscode"; -import * as path from "path"; -import { strict as assert } from "assert"; -import { promises as fs } from "fs"; -import { promises as dns } from "dns"; -import { spawnSync } from "child_process"; -import { throttle } from "throttle-debounce"; - -import { BinarySource } from "./interfaces"; -import { fetchLatestArtifactMetadata } from "./fetch_latest_artifact_metadata"; -import { downloadFile } from "./download_file"; - -export async function downloadLatestLanguageServer( - {file: artifactFileName, dir: installationDir, repo}: BinarySource.GithubRelease -) { - const { releaseName, downloadUrl } = (await fetchLatestArtifactMetadata( - repo, artifactFileName - ))!; - - await fs.mkdir(installationDir).catch(err => assert.strictEqual( - err?.code, - "EEXIST", - `Couldn't create directory "${installationDir}" to download `+ - `language server binary: ${err.message}` - )); - - const installationPath = path.join(installationDir, artifactFileName); - - console.time("Downloading ra_lsp_server"); - await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - cancellable: false, // FIXME: add support for canceling download? - title: `Downloading language server (${releaseName})` - }, - async (progress, _cancellationToken) => { - let lastPrecentage = 0; - const filePermissions = 0o755; // (rwx, r_x, r_x) - await downloadFile(downloadUrl, installationPath, filePermissions, throttle( - 200, - /* noTrailing: */ true, - (readBytes, totalBytes) => { - const newPercentage = (readBytes / totalBytes) * 100; - progress.report({ - message: newPercentage.toFixed(0) + "%", - increment: newPercentage - lastPrecentage - }); - - lastPrecentage = newPercentage; - }) - ); - } - ); - console.timeEnd("Downloading ra_lsp_server"); -} -export async function ensureLanguageServerBinary( - langServerSource: null | BinarySource -): Promise { - - if (!langServerSource) { - 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 null; - } - - switch (langServerSource.type) { - case BinarySource.Type.ExplicitPath: { - if (isBinaryAvailable(langServerSource.path)) { - return langServerSource.path; - } - - vscode.window.showErrorMessage( - `Unable to run ${langServerSource.path} binary. ` + - `To use the pre-built language server, set "rust-analyzer.raLspServerPath" ` + - "value to `null` or remove it from the settings to use it by default." - ); - return null; - } - case BinarySource.Type.GithubRelease: { - const prebuiltBinaryPath = path.join(langServerSource.dir, langServerSource.file); - - if (isBinaryAvailable(prebuiltBinaryPath)) { - return prebuiltBinaryPath; - } - - const userResponse = await vscode.window.showInformationMessage( - "Language server binary for rust-analyzer was not found. " + - "Do you want to download it now?", - "Download now", "Cancel" - ); - if (userResponse !== "Download now") return null; - - try { - await downloadLatestLanguageServer(langServerSource); - } catch (err) { - vscode.window.showErrorMessage( - `Failed to download language server from ${langServerSource.repo.name} ` + - `GitHub repository: ${err.message}` - ); - - console.error(err); - - dns.resolve('example.com').then( - addrs => console.log("DNS resolution for example.com was successful", addrs), - err => { - console.error( - "DNS resolution for example.com failed, " + - "there might be an issue with Internet availability" - ); - console.error(err); - } - ); - - return null; - } - - if (!isBinaryAvailable(prebuiltBinaryPath)) assert(false, - `Downloaded language server binary is not functional.` + - `Downloaded from: ${JSON.stringify(langServerSource)}` - ); - - - vscode.window.showInformationMessage( - "Rust analyzer language server was successfully installed 🦀" - ); - - return prebuiltBinaryPath; - } - } - - function isBinaryAvailable(binaryPath: string) { - const res = spawnSync(binaryPath, ["--version"]); - - // ACHTUNG! `res` type declaration is inherently wrong, see - // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/42221 - - console.log("Checked binary availablity via --version", res); - console.log(binaryPath, "--version output:", res.output?.map(String)); - - return res.status === 0; - } -} -- cgit v1.2.3