diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 302ee885009..0e23a20d71d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -427,7 +427,7 @@ Example:
}
```
-Overrides specifically for the Amazon Q language server can be set using the `aws.dev.amazonqLsp` setting. This is a JSON object consisting of keys/values required to override language server: `manifestUrl`, `supportedVersions`, `id`, and `locationOverride`.
+Overrides specifically for the Amazon Q language server can be set using the `aws.dev.amazonqLsp` setting. This is a JSON object consisting of keys/values required to override language server: `manifestUrl`, `supportedVersions`, `id`, and `path`.
Example:
@@ -436,7 +436,20 @@ Example:
"manifestUrl": "https://custom.url/manifest.json",
"supportedVersions": "4.0.0",
"id": "AmazonQ",
- "locationOverride": "/custom/path/to/local/lsp/folder",
+ "path": "/custom/path/to/local/lsp/folder",
+}
+```
+
+Overrides specifically for the Amazon Q Workspace Context language server can be set using the `aws.dev.amazonqWorkspaceLsp` setting. This is a JSON object consisting of keys/values required to override language server: `manifestUrl`, `supportedVersions`, `id`, and `path`.
+
+Example:
+
+```json
+"aws.dev.amazonqWorkspaceLsp": {
+ "manifestUrl": "https://custom.url/manifest.json",
+ "supportedVersions": "4.0.0",
+ "id": "AmazonQ",
+ "path": "/custom/path/to/local/lsp/folder",
}
```
@@ -488,7 +501,11 @@ Unlike the user setting overrides, not all of these environment variables have t
- `__AMAZONQLSP_MANIFEST_URL`: for aws.dev.amazonqLsp.manifestUrl
- `__AMAZONQLSP_SUPPORTED_VERSIONS`: for aws.dev.amazonqLsp.supportedVersions
- `__AMAZONQLSP_ID`: for aws.dev.amazonqLsp.id
-- `__AMAZONQLSP_LOCATION_OVERRIDE`: for aws.dev.amazonqLsp.locationOverride
+- `__AMAZONQLSP_PATH`: for aws.dev.amazonqWorkspaceLsp.locationOverride
+- `__AMAZONQWORKSPACELSP_MANIFEST_URL`: for aws.dev.amazonqWorkspaceLsp.manifestUrl
+- `__AMAZONQWORKSPACELSP_SUPPORTED_VERSIONS`: for aws.dev.amazonqWorkspaceLsp.supportedVersions
+- `__AMAZONQWORKSPACELSP_ID`: for aws.dev.amazonqWorkspaceLsp.id
+- `__AMAZONQWORKSPACELSP_PATH`: for aws.dev.amazonqWorkspaceLsp.locationOverride
#### Lambda
diff --git a/packages/amazonq/src/lsp/activation.ts b/packages/amazonq/src/lsp/activation.ts
index 783c35ddc94..4d7918d76b0 100644
--- a/packages/amazonq/src/lsp/activation.ts
+++ b/packages/amazonq/src/lsp/activation.ts
@@ -5,13 +5,13 @@
import vscode from 'vscode'
import { startLanguageServer } from './client'
-import { AmazonQLSPResolver } from './lspInstaller'
+import { AmazonQLspInstaller } from './lspInstaller'
import { Commands, lspSetupStage, ToolkitError } from 'aws-core-vscode/shared'
export async function activate(ctx: vscode.ExtensionContext): Promise {
try {
await lspSetupStage('all', async () => {
- const installResult = await new AmazonQLSPResolver().resolve()
+ const installResult = await new AmazonQLspInstaller().resolve()
await lspSetupStage('launch', async () => await startLanguageServer(ctx, installResult.resourcePaths))
})
ctx.subscriptions.push(
diff --git a/packages/amazonq/src/lsp/config.ts b/packages/amazonq/src/lsp/config.ts
index 44b08fbc396..634cc43aab2 100644
--- a/packages/amazonq/src/lsp/config.ts
+++ b/packages/amazonq/src/lsp/config.ts
@@ -4,25 +4,19 @@
*/
import { DevSettings, getServiceEnvVarConfig } from 'aws-core-vscode/shared'
+import { LspConfig } from 'aws-core-vscode/amazonq'
-export interface AmazonQLspConfig {
- manifestUrl: string
- supportedVersions: string
- id: string
- locationOverride?: string
-}
-
-export const defaultAmazonQLspConfig: AmazonQLspConfig = {
+export const defaultAmazonQLspConfig: LspConfig = {
manifestUrl: 'https://aws-toolkit-language-servers.amazonaws.com/codewhisperer/0/manifest.json',
supportedVersions: '^3.1.1',
id: 'AmazonQ', // used for identification in global storage/local disk location. Do not change.
- locationOverride: undefined,
+ path: undefined,
}
-export function getAmazonQLspConfig(): AmazonQLspConfig {
+export function getAmazonQLspConfig(): LspConfig {
return {
...defaultAmazonQLspConfig,
- ...(DevSettings.instance.getServiceConfig('amazonqLsp', {}) as AmazonQLspConfig),
+ ...(DevSettings.instance.getServiceConfig('amazonqLsp', {}) as LspConfig),
...getServiceEnvVarConfig('amazonqLsp', Object.keys(defaultAmazonQLspConfig)),
}
}
diff --git a/packages/amazonq/src/lsp/lspInstaller.ts b/packages/amazonq/src/lsp/lspInstaller.ts
index e3be27a9580..e041682ee74 100644
--- a/packages/amazonq/src/lsp/lspInstaller.ts
+++ b/packages/amazonq/src/lsp/lspInstaller.ts
@@ -3,64 +3,32 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import * as vscode from 'vscode'
-import {
- ManifestResolver,
- LanguageServerResolver,
- LspResolver,
- fs,
- LspResolution,
- getNodeExecutableName,
- cleanLspDownloads,
- getLogger,
-} from 'aws-core-vscode/shared'
+import { fs, getNodeExecutableName, BaseLspInstaller, ResourcePaths } from 'aws-core-vscode/shared'
import path from 'path'
-import { Range } from 'semver'
import { getAmazonQLspConfig } from './config'
-const logger = getLogger('amazonqLsp')
+export class AmazonQLspInstaller extends BaseLspInstaller.BaseLspInstaller {
+ constructor() {
+ super(getAmazonQLspConfig(), 'amazonqLsp')
+ }
+
+ protected override async postInstall(assetDirectory: string): Promise {
+ const resourcePaths = this.resourcePaths(assetDirectory)
+ await fs.chmod(resourcePaths.node, 0o755)
+ }
-export class AmazonQLSPResolver implements LspResolver {
- async resolve(): Promise {
- const { id, manifestUrl, supportedVersions, locationOverride } = getAmazonQLspConfig()
- if (locationOverride) {
- void vscode.window.showInformationMessage(`Using language server override location: ${locationOverride}`)
+ protected override resourcePaths(assetDirectory?: string): ResourcePaths {
+ if (!assetDirectory) {
return {
- assetDirectory: locationOverride,
- location: 'override',
- version: '0.0.0',
- resourcePaths: {
- lsp: locationOverride,
- node: getNodeExecutableName(),
- },
+ lsp: this.config.path ?? '',
+ node: getNodeExecutableName(),
}
}
- // "AmazonQ" is shared across toolkits to provide a common access point, don't change it
- const manifest = await new ManifestResolver(manifestUrl, id).resolve()
- const installationResult = await new LanguageServerResolver(
- manifest,
- id,
- new Range(supportedVersions, {
- includePrerelease: true,
- })
- ).resolve()
-
- const nodePath = path.join(installationResult.assetDirectory, `servers/${getNodeExecutableName()}`)
- await fs.chmod(nodePath, 0o755)
-
- const deletedVersions = await cleanLspDownloads(
- manifest.versions,
- path.dirname(installationResult.assetDirectory)
- )
- logger.debug(`Cleaned up ${deletedVersions.length} old versions`)
-
+ const nodePath = path.join(assetDirectory, `servers/${getNodeExecutableName()}`)
return {
- ...installationResult,
- resourcePaths: {
- lsp: path.join(installationResult.assetDirectory, 'servers/aws-lsp-codewhisperer.js'),
- node: nodePath,
- },
+ lsp: path.join(assetDirectory, 'servers/aws-lsp-codewhisperer.js'),
+ node: nodePath,
}
}
}
diff --git a/packages/amazonq/test/e2e/lsp/lspInstaller.test.ts b/packages/amazonq/test/e2e/lsp/lspInstaller.test.ts
index 0447d7f5fcf..04752640050 100644
--- a/packages/amazonq/test/e2e/lsp/lspInstaller.test.ts
+++ b/packages/amazonq/test/e2e/lsp/lspInstaller.test.ts
@@ -5,7 +5,7 @@
import assert from 'assert'
import sinon from 'sinon'
-import { AmazonQLSPResolver } from '../../../src/lsp/lspInstaller'
+import { AmazonQLspInstaller } from '../../../src/lsp/lspInstaller'
import {
DevSettings,
fs,
@@ -18,9 +18,9 @@ import {
} from 'aws-core-vscode/shared'
import * as semver from 'semver'
import { assertTelemetry } from 'aws-core-vscode/test'
-import { LspController } from 'aws-core-vscode/amazonq'
+import { LspConfig, LspController } from 'aws-core-vscode/amazonq'
import { LanguageServerSetup } from 'aws-core-vscode/telemetry'
-import { AmazonQLspConfig, getAmazonQLspConfig } from '../../../src/lsp/config'
+import { getAmazonQLspConfig } from '../../../src/lsp/config'
function createVersion(version: string) {
return {
@@ -44,13 +44,13 @@ function createVersion(version: string) {
}
describe('AmazonQLSPInstaller', () => {
- let resolver: AmazonQLSPResolver
+ let resolver: AmazonQLspInstaller
let sandbox: sinon.SinonSandbox
let tempDir: string
// If globalState contains an ETag that is up to date with remote, we won't fetch it resulting in inconsistent behavior.
// Therefore, we clear it temporarily for these tests to ensure consistent behavior.
let manifestStorage: { [key: string]: any }
- let lspConfig: AmazonQLspConfig
+ let lspConfig: LspConfig
before(async () => {
manifestStorage = globals.globalState.get(manifestStorageKey) || {}
@@ -59,7 +59,7 @@ describe('AmazonQLSPInstaller', () => {
beforeEach(async () => {
sandbox = sinon.createSandbox()
- resolver = new AmazonQLSPResolver()
+ resolver = new AmazonQLspInstaller()
tempDir = await makeTemporaryToolkitFolder()
sandbox.stub(LanguageServerResolver.prototype, 'defaultDownloadFolder').returns(tempDir)
// Called on extension activation and can contaminate telemetry.
diff --git a/packages/amazonq/test/unit/amazonq/lsp/config.test.ts b/packages/amazonq/test/unit/amazonq/lsp/config.test.ts
index c26e4a87239..9a9ba1ef348 100644
--- a/packages/amazonq/test/unit/amazonq/lsp/config.test.ts
+++ b/packages/amazonq/test/unit/amazonq/lsp/config.test.ts
@@ -7,73 +7,104 @@ import assert from 'assert'
import { DevSettings } from 'aws-core-vscode/shared'
import sinon from 'sinon'
import { defaultAmazonQLspConfig, getAmazonQLspConfig } from '../../../../src/lsp/config'
+import { LspConfig, getAmazonQWorkspaceLspConfig, defaultAmazonQWorkspaceLspConfig } from 'aws-core-vscode/amazonq'
-describe('getAmazonQLspConfig', () => {
- let sandbox: sinon.SinonSandbox
- let serviceConfigStub: sinon.SinonStub
- const settingConfig = {
- manifestUrl: 'https://custom.url/manifest.json',
- supportedVersions: '4.0.0',
- id: 'AmazonQSetting',
- locationOverride: '/custom/path',
- }
+for (const [name, config, defaultConfig, setEnv, resetEnv] of [
+ [
+ 'getAmazonQLspConfig',
+ getAmazonQLspConfig,
+ defaultAmazonQLspConfig,
+ (envConfig: LspConfig) => {
+ process.env.__AMAZONQLSP_MANIFEST_URL = envConfig.manifestUrl
+ process.env.__AMAZONQLSP_SUPPORTED_VERSIONS = envConfig.supportedVersions
+ process.env.__AMAZONQLSP_ID = envConfig.id
+ process.env.__AMAZONQLSP_PATH = envConfig.path
+ },
+ () => {
+ delete process.env.__AMAZONQLSP_MANIFEST_URL
+ delete process.env.__AMAZONQLSP_SUPPORTED_VERSIONS
+ delete process.env.__AMAZONQLSP_ID
+ delete process.env.__AMAZONQLSP_PATH
+ },
+ ],
+ [
+ 'getAmazonQWorkspaceLspConfig',
+ getAmazonQWorkspaceLspConfig,
+ defaultAmazonQWorkspaceLspConfig,
+ (envConfig: LspConfig) => {
+ process.env.__AMAZONQWORKSPACELSP_MANIFEST_URL = envConfig.manifestUrl
+ process.env.__AMAZONQWORKSPACELSP_SUPPORTED_VERSIONS = envConfig.supportedVersions
+ process.env.__AMAZONQWORKSPACELSP_ID = envConfig.id
+ process.env.__AMAZONQWORKSPACELSP_PATH = envConfig.path
+ },
+ () => {
+ delete process.env.__AMAZONQWORKSPACELSP_MANIFEST_URL
+ delete process.env.__AMAZONQWORKSPACELSP_SUPPORTED_VERSIONS
+ delete process.env.__AMAZONQWORKSPACELSP_ID
+ delete process.env.__AMAZONQWORKSPACELSP_PATH
+ },
+ ],
+] as const) {
+ describe(name, () => {
+ let sandbox: sinon.SinonSandbox
+ let serviceConfigStub: sinon.SinonStub
+ const settingConfig: LspConfig = {
+ manifestUrl: 'https://custom.url/manifest.json',
+ supportedVersions: '4.0.0',
+ id: 'AmazonQSetting',
+ path: '/custom/path',
+ }
- beforeEach(() => {
- sandbox = sinon.createSandbox()
+ beforeEach(() => {
+ sandbox = sinon.createSandbox()
- serviceConfigStub = sandbox.stub()
- sandbox.stub(DevSettings, 'instance').get(() => ({
- getServiceConfig: serviceConfigStub,
- }))
- })
+ serviceConfigStub = sandbox.stub()
+ sandbox.stub(DevSettings, 'instance').get(() => ({
+ getServiceConfig: serviceConfigStub,
+ }))
+ })
- afterEach(() => {
- sandbox.restore()
- })
+ afterEach(() => {
+ sandbox.restore()
+ resetEnv()
+ })
- it('uses default config', () => {
- serviceConfigStub.returns({})
- const config = getAmazonQLspConfig()
- assert.deepStrictEqual(config, defaultAmazonQLspConfig)
- })
+ it('uses default config', () => {
+ serviceConfigStub.returns({})
+ assert.deepStrictEqual(config(), defaultConfig)
+ })
- it('overrides location', () => {
- const locationOverride = '/custom/path/to/lsp'
- serviceConfigStub.returns({ locationOverride })
+ it('overrides location', () => {
+ const path = '/custom/path/to/lsp'
+ serviceConfigStub.returns({ path })
- const config = getAmazonQLspConfig()
- assert.deepStrictEqual(config, {
- ...defaultAmazonQLspConfig,
- locationOverride,
+ assert.deepStrictEqual(config(), {
+ ...defaultConfig,
+ path,
+ })
})
- })
-
- it('overrides default settings', () => {
- serviceConfigStub.returns(settingConfig)
- const config = getAmazonQLspConfig()
- assert.deepStrictEqual(config, settingConfig)
- })
+ it('overrides default settings', () => {
+ serviceConfigStub.returns(settingConfig)
- it('environment variable takes precedence over settings', () => {
- const envConfig = {
- manifestUrl: 'https://another-custom.url/manifest.json',
- supportedVersions: '5.1.1',
- id: 'AmazonQEnv',
- locationOverride: '/some/new/custom/path',
- }
+ assert.deepStrictEqual(config(), settingConfig)
+ })
- process.env.__AMAZONQLSP_MANIFEST_URL = envConfig.manifestUrl
- process.env.__AMAZONQLSP_SUPPORTED_VERSIONS = envConfig.supportedVersions
- process.env.__AMAZONQLSP_ID = envConfig.id
- process.env.__AMAZONQLSP_LOCATION_OVERRIDE = envConfig.locationOverride
+ it('environment variable takes precedence over settings', () => {
+ const envConfig: LspConfig = {
+ manifestUrl: 'https://another-custom.url/manifest.json',
+ supportedVersions: '5.1.1',
+ id: 'AmazonQEnv',
+ path: '/some/new/custom/path',
+ }
- serviceConfigStub.returns(settingConfig)
+ setEnv(envConfig)
+ serviceConfigStub.returns(settingConfig)
- const config = getAmazonQLspConfig()
- assert.deepStrictEqual(config, {
- ...defaultAmazonQLspConfig,
- ...envConfig,
+ assert.deepStrictEqual(config(), {
+ ...defaultAmazonQLspConfig,
+ ...envConfig,
+ })
})
})
-})
+}
diff --git a/packages/core/src/amazonq/index.ts b/packages/core/src/amazonq/index.ts
index 84a3bf4f454..f1a285c7161 100644
--- a/packages/core/src/amazonq/index.ts
+++ b/packages/core/src/amazonq/index.ts
@@ -43,6 +43,7 @@ export { ExtensionMessage } from '../amazonq/webview/ui/commands'
export { CodeReference } from '../codewhispererChat/view/connector/connector'
export { extractAuthFollowUp } from './util/authUtils'
export { Messenger } from './commons/connector/baseMessenger'
+export * from './lsp/config'
import { FeatureContext } from '../shared/featureConfig'
/**
diff --git a/packages/core/src/amazonq/lsp/config.ts b/packages/core/src/amazonq/lsp/config.ts
new file mode 100644
index 00000000000..1a597032a35
--- /dev/null
+++ b/packages/core/src/amazonq/lsp/config.ts
@@ -0,0 +1,29 @@
+/*!
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { DevSettings } from '../../shared/settings'
+import { getServiceEnvVarConfig } from '../../shared/vscode/env'
+
+export interface LspConfig {
+ manifestUrl: string
+ supportedVersions: string
+ id: string
+ path?: string
+}
+
+export const defaultAmazonQWorkspaceLspConfig: LspConfig = {
+ manifestUrl: 'https://aws-toolkit-language-servers.amazonaws.com/q-context/manifest.json',
+ supportedVersions: '0.1.35',
+ id: 'AmazonQ-Workspace', // used for identification in global storage/local disk location. Do not change.
+ path: undefined,
+}
+
+export function getAmazonQWorkspaceLspConfig(): LspConfig {
+ return {
+ ...defaultAmazonQWorkspaceLspConfig,
+ ...(DevSettings.instance.getServiceConfig('amazonqWorkspaceLsp', {}) as LspConfig),
+ ...getServiceEnvVarConfig('amazonqWorkspaceLsp', Object.keys(defaultAmazonQWorkspaceLspConfig)),
+ }
+}
diff --git a/packages/core/src/amazonq/lsp/lspController.ts b/packages/core/src/amazonq/lsp/lspController.ts
index 2ed3065cc29..62ac37cd1d8 100644
--- a/packages/core/src/amazonq/lsp/lspController.ts
+++ b/packages/core/src/amazonq/lsp/lspController.ts
@@ -14,7 +14,7 @@ import { telemetry } from '../../shared/telemetry/telemetry'
import { isCloud9 } from '../../shared/extensionUtilities'
import globals, { isWeb } from '../../shared/extensionGlobals'
import { isAmazonInternalOs } from '../../shared/vscode/env'
-import { WorkspaceLSPResolver } from './workspaceInstaller'
+import { WorkspaceLSPInstaller } from './workspaceInstaller'
import { lspSetupStage } from '../../shared/lsp/utils/setupStage'
export interface Chunk {
@@ -186,7 +186,7 @@ export class LspController {
private async setupLsp(context: vscode.ExtensionContext) {
await lspSetupStage('all', async () => {
- const installResult = await new WorkspaceLSPResolver().resolve()
+ const installResult = await new WorkspaceLSPInstaller().resolve()
await lspSetupStage('launch', async () => activateLsp(context, installResult.resourcePaths))
this.logger.info('LspController: LSP activated')
})
diff --git a/packages/core/src/amazonq/lsp/workspaceInstaller.ts b/packages/core/src/amazonq/lsp/workspaceInstaller.ts
index 849fd3a37c5..604aa89a9fd 100644
--- a/packages/core/src/amazonq/lsp/workspaceInstaller.ts
+++ b/packages/core/src/amazonq/lsp/workspaceInstaller.ts
@@ -4,49 +4,36 @@
*/
import path from 'path'
-import { LspResolution, LspResolver } from '../../shared/lsp/types'
-import { ManifestResolver } from '../../shared/lsp/manifestResolver'
-import { LanguageServerResolver } from '../../shared/lsp/lspResolver'
-import { Range } from 'semver'
+import { ResourcePaths } from '../../shared/lsp/types'
import { getNodeExecutableName } from '../../shared/lsp/utils/platform'
import { fs } from '../../shared/fs/fs'
-import { cleanLspDownloads } from '../../shared/lsp/utils/cleanup'
-import { getLogger } from '../../shared/logger/logger'
+import { BaseLspInstaller } from '../../shared/lsp/baseLspInstaller'
+import { getAmazonQWorkspaceLspConfig } from './config'
-const manifestUrl = 'https://aws-toolkit-language-servers.amazonaws.com/q-context/manifest.json'
-// this LSP client in Q extension is only going to work with these LSP server versions
-const supportedLspServerVersions = '0.1.35'
-const logger = getLogger('amazonqWorkspaceLsp')
+export class WorkspaceLSPInstaller extends BaseLspInstaller {
+ constructor() {
+ super(getAmazonQWorkspaceLspConfig(), 'amazonqWorkspaceLsp')
+ }
-export class WorkspaceLSPResolver implements LspResolver {
- async resolve(): Promise {
- const name = 'AmazonQ-Workspace'
- const manifest = await new ManifestResolver(manifestUrl, name).resolve()
- const installationResult = await new LanguageServerResolver(
- manifest,
- name,
- new Range(supportedLspServerVersions)
- ).resolve()
+ protected override async postInstall(assetDirectory: string): Promise {
+ const resourcePaths = this.resourcePaths(assetDirectory)
+ await fs.chmod(resourcePaths.node, 0o755)
+ }
- const nodeName =
- process.platform === 'win32' ? getNodeExecutableName() : `node-${process.platform}-${process.arch}`
- const nodePath = path.join(installationResult.assetDirectory, nodeName)
- await fs.chmod(nodePath, 0o755)
+ protected override resourcePaths(assetDirectory?: string): ResourcePaths {
+ // local version
+ if (!assetDirectory) {
+ return {
+ lsp: this.config.path ?? '',
+ node: getNodeExecutableName(),
+ }
+ }
- const deletedVersions = await cleanLspDownloads(
- manifest.versions,
- path.basename(installationResult.assetDirectory)
- )
- logger.debug(`cleaning old LSP versions deleted ${deletedVersions.length} versions`)
+ const lspNodeName =
+ process.platform === 'win32' ? getNodeExecutableName() : `node-${process.platform}-${process.arch}`
return {
- ...installationResult,
- resourcePaths: {
- lsp: path.join(
- installationResult.assetDirectory,
- `qserver-${process.platform}-${process.arch}/qserver/lspServer.js`
- ),
- node: nodePath,
- },
+ lsp: path.join(assetDirectory, `qserver-${process.platform}-${process.arch}/qserver/lspServer.js`),
+ node: path.join(assetDirectory, lspNodeName),
}
}
}
diff --git a/packages/core/src/dev/activation.ts b/packages/core/src/dev/activation.ts
index a712e984dfb..7f0c6290435 100644
--- a/packages/core/src/dev/activation.ts
+++ b/packages/core/src/dev/activation.ts
@@ -25,7 +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'
+import { WorkspaceLSPInstaller } from '../amazonq/lsp/workspaceInstaller'
interface MenuOption {
readonly label: string
@@ -546,7 +546,7 @@ async function resetNotificationsState() {
}
async function resetWorkspaceLspDownload() {
- await new WorkspaceLSPResolver().resolve()
+ await new WorkspaceLSPInstaller().resolve()
}
async function editNotifications() {
diff --git a/packages/core/src/shared/index.ts b/packages/core/src/shared/index.ts
index 6193a68445c..f35f7c2daab 100644
--- a/packages/core/src/shared/index.ts
+++ b/packages/core/src/shared/index.ts
@@ -70,3 +70,4 @@ export * from './lsp/utils/cleanup'
export { default as request } from './request'
export * from './lsp/utils/platform'
export * as processUtils from './utilities/processUtils'
+export * as BaseLspInstaller from './lsp/baseLspInstaller'
diff --git a/packages/core/src/shared/lsp/baseLspInstaller.ts b/packages/core/src/shared/lsp/baseLspInstaller.ts
new file mode 100644
index 00000000000..ccc229e9445
--- /dev/null
+++ b/packages/core/src/shared/lsp/baseLspInstaller.ts
@@ -0,0 +1,65 @@
+/*!
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import * as nodePath from 'path'
+import vscode from 'vscode'
+import { LspConfig } from '../../amazonq/lsp/config'
+import { LanguageServerResolver } from './lspResolver'
+import { ManifestResolver } from './manifestResolver'
+import { LspResolution, ResourcePaths } from './types'
+import { cleanLspDownloads } from './utils/cleanup'
+import { Range } from 'semver'
+import { getLogger } from '../logger/logger'
+import type { Logger, LogTopic } from '../logger/logger'
+
+export abstract class BaseLspInstaller {
+ private logger: Logger
+
+ constructor(
+ protected config: LspConfig,
+ loggerName: Extract
+ ) {
+ this.logger = getLogger(loggerName)
+ }
+
+ async resolve(): Promise {
+ const { id, manifestUrl, supportedVersions, path } = this.config
+ if (path) {
+ const overrideMsg = `Using language server override location: ${path}`
+ this.logger.info(overrideMsg)
+ void vscode.window.showInformationMessage(overrideMsg)
+ return {
+ assetDirectory: path,
+ location: 'override',
+ version: '0.0.0',
+ resourcePaths: this.resourcePaths(),
+ }
+ }
+
+ const manifest = await new ManifestResolver(manifestUrl, id).resolve()
+ const installationResult = await new LanguageServerResolver(
+ manifest,
+ id,
+ new Range(supportedVersions, {
+ includePrerelease: true,
+ })
+ ).resolve()
+
+ const assetDirectory = installationResult.assetDirectory
+
+ await this.postInstall(assetDirectory)
+
+ const deletedVersions = await cleanLspDownloads(manifest.versions, nodePath.dirname(assetDirectory))
+ this.logger.debug(`cleaning old LSP versions deleted ${deletedVersions.length} versions`)
+
+ return {
+ ...installationResult,
+ resourcePaths: this.resourcePaths(assetDirectory),
+ }
+ }
+
+ protected abstract postInstall(assetDirectory: string): Promise
+ protected abstract resourcePaths(assetDirectory?: string): ResourcePaths
+}
diff --git a/packages/core/src/shared/settings.ts b/packages/core/src/shared/settings.ts
index 09b7396f0d1..180244e6f6f 100644
--- a/packages/core/src/shared/settings.ts
+++ b/packages/core/src/shared/settings.ts
@@ -758,6 +758,7 @@ const devSettings = {
codecatalystService: Record(String, String),
codewhispererService: Record(String, String),
amazonqLsp: Record(String, String),
+ amazonqWorkspaceLsp: Record(String, String),
ssoCacheDirectory: String,
autofillStartUrl: String,
webAuth: Boolean,
@@ -771,6 +772,7 @@ interface ServiceTypeMap {
codecatalystService: codecatalyst.CodeCatalystConfig
codewhispererService: codewhisperer.CodeWhispererConfig
amazonqLsp: object // type is provided inside of amazon q
+ amazonqWorkspaceLsp: object // type is provided inside of amazon q
}
/**