diff --git a/packages/amazonq/src/lsp/lspInstaller.ts b/packages/amazonq/src/lsp/lspInstaller.ts index 72d0746cdcf..aea483e6b0e 100644 --- a/packages/amazonq/src/lsp/lspInstaller.ts +++ b/packages/amazonq/src/lsp/lspInstaller.ts @@ -42,7 +42,7 @@ export class AmazonQLSPResolver implements LspResolver { manifest, name, new Range(supportedLspServerVersions) - ).resolve() + ).resolveWithProgress() const nodePath = path.join(installationResult.assetDirectory, `servers/${getNodeExecutableName()}`) await fs.chmod(nodePath, 0o755) diff --git a/packages/core/src/amazonq/lsp/workspaceInstaller.ts b/packages/core/src/amazonq/lsp/workspaceInstaller.ts index c4c688d7bc1..275d5244737 100644 --- a/packages/core/src/amazonq/lsp/workspaceInstaller.ts +++ b/packages/core/src/amazonq/lsp/workspaceInstaller.ts @@ -24,7 +24,7 @@ export class WorkspaceLSPResolver implements LspResolver { manifest, name, new Range(supportedLspServerVersions) - ).resolve() + ).resolveWithProgress() const nodeName = process.platform === 'win32' ? getNodeExecutableName() : `node-${process.platform}-${process.arch}` diff --git a/packages/core/src/dev/activation.ts b/packages/core/src/dev/activation.ts index 0033eaa8548..4254ed904dc 100644 --- a/packages/core/src/dev/activation.ts +++ b/packages/core/src/dev/activation.ts @@ -25,6 +25,7 @@ import { NotificationsController } from '../notifications/controller' import { DevNotificationsState } from '../notifications/types' import { QuickPickItem } from 'vscode' import { ChildProcess } from '../shared/utilities/processUtils' +import { WorkspaceLSPResolver } from '../amazonq/lsp/workspaceInstaller' interface MenuOption { readonly label: string @@ -464,6 +465,12 @@ const resettableFeatures: readonly ResettableFeature[] = [ detail: 'Resets memory/global state for the notifications panel (includes dismissed, onReceive).', executor: resetNotificationsState, }, + { + name: 'workspace lsp', + label: 'Lsp', + detail: 'Resets workspace LSP', + executor: resetWorkspaceLspDownload, + }, ] as const // TODO this is *somewhat* similar to `openStorageFromInput`. If we need another @@ -552,6 +559,10 @@ async function resetNotificationsState() { await targetNotificationsController.reset() } +async function resetWorkspaceLspDownload() { + await new WorkspaceLSPResolver().resolve() +} + async function editNotifications() { const storageKey = 'aws.notifications.dev' const current = globalState.get(storageKey) ?? {} diff --git a/packages/core/src/shared/lsp/lspResolver.ts b/packages/core/src/shared/lsp/lspResolver.ts index 5a907b96a02..2fb3aa8ea21 100644 --- a/packages/core/src/shared/lsp/lspResolver.ts +++ b/packages/core/src/shared/lsp/lspResolver.ts @@ -4,6 +4,7 @@ */ import fs from '../fs/fs' +import * as vscode from 'vscode' import { ToolkitError } from '../errors' import * as semver from 'semver' import * as path from 'path' @@ -22,6 +23,20 @@ export class LanguageServerResolver { private readonly _defaultDownloadFolder?: string ) {} + // wraps the resolver to show download status message + async resolveWithProgress() { + return vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: `Downloading '${this.lsName}' language server`, + cancellable: false, + }, + async (progress) => { + return this.resolve() + } + ) + } + /** * Downloads and sets up the Language Server, attempting different locations in order: * 1. Local cache @@ -30,63 +45,67 @@ export class LanguageServerResolver { * @throws ToolkitError if no compatible version can be found */ async resolve() { - const result: LspResult = { - location: 'unknown', - version: '', - assetDirectory: '', - } - - const latestVersion = this.latestCompatibleLspVersion() - const targetContents = this.getLSPTargetContents(latestVersion) - const cacheDirectory = this.getDownloadDirectory(latestVersion.serverVersion) + try { + const result: LspResult = { + location: 'unknown', + version: '', + assetDirectory: '', + } - if (await this.hasValidLocalCache(cacheDirectory, targetContents)) { - result.location = 'cache' - result.version = latestVersion.serverVersion - result.assetDirectory = cacheDirectory - return result - } else { - // Delete the cached directory since it's invalid - if (await fs.existsDir(cacheDirectory)) { - await fs.delete(cacheDirectory, { - recursive: true, - }) + const latestVersion = this.latestCompatibleLspVersion() + const targetContents = this.getLSPTargetContents(latestVersion) + const cacheDirectory = this.getDownloadDirectory(latestVersion.serverVersion) + + if (await this.hasValidLocalCache(cacheDirectory, targetContents)) { + result.location = 'cache' + result.version = latestVersion.serverVersion + result.assetDirectory = cacheDirectory + return result + } else { + // Delete the cached directory since it's invalid + if (await fs.existsDir(cacheDirectory)) { + await fs.delete(cacheDirectory, { + recursive: true, + }) + } } - } - if (await this.downloadRemoteTargetContent(targetContents, latestVersion.serverVersion)) { - result.location = 'remote' - result.version = latestVersion.serverVersion - result.assetDirectory = cacheDirectory - return result - } else { - // clean up any leftover content that may have been downloaded - if (await fs.existsDir(cacheDirectory)) { - await fs.delete(cacheDirectory, { - recursive: true, - }) + if (await this.downloadRemoteTargetContent(targetContents, latestVersion.serverVersion)) { + result.location = 'remote' + result.version = latestVersion.serverVersion + result.assetDirectory = cacheDirectory + return result + } else { + // clean up any leftover content that may have been downloaded + if (await fs.existsDir(cacheDirectory)) { + await fs.delete(cacheDirectory, { + recursive: true, + }) + } } - } - logger.info( - `Unable to download language server version ${latestVersion.serverVersion}. Attempting to fetch from fallback location` - ) + logger.info( + `Unable to download language server version ${latestVersion.serverVersion}. Attempting to fetch from fallback location` + ) - const fallbackDirectory = await this.getFallbackDir(latestVersion.serverVersion) - if (!fallbackDirectory) { - throw new ToolkitError('Unable to find a compatible version of the Language Server') - } + const fallbackDirectory = await this.getFallbackDir(latestVersion.serverVersion) + if (!fallbackDirectory) { + throw new ToolkitError('Unable to find a compatible version of the Language Server') + } - const version = path.basename(fallbackDirectory) - logger.info( - `Unable to install ${this.lsName} language server v${latestVersion.serverVersion}. Launching a previous version from ${fallbackDirectory}` - ) + const version = path.basename(fallbackDirectory) + logger.info( + `Unable to install ${this.lsName} language server v${latestVersion.serverVersion}. Launching a previous version from ${fallbackDirectory}` + ) - result.location = 'fallback' - result.version = version - result.assetDirectory = fallbackDirectory + result.location = 'fallback' + result.version = version + result.assetDirectory = fallbackDirectory - return result + return result + } finally { + logger.info(`Finished setting up LSP server`) + } } /**