diff --git a/src/LanguageServerManager.ts b/src/LanguageServerManager.ts index 762a6d94..69449d64 100644 --- a/src/LanguageServerManager.ts +++ b/src/LanguageServerManager.ts @@ -133,7 +133,10 @@ export class LanguageServerManager { //dynamically enable or disable the language server based on user settings vscode.workspace.onDidChangeConfiguration(async (configuration) => { - await this.syncVersionAndTryRun(); + //if we've changed the bsdk setting, restart the language server + if (configuration.affectsConfiguration('brightscript.bsdk')) { + await this.syncVersionAndTryRun(); + } }); await this.syncVersionAndTryRun(); } diff --git a/src/commands/LanguageServerInfoCommand.ts b/src/commands/LanguageServerInfoCommand.ts index 6b3ba428..484acaa5 100644 --- a/src/commands/LanguageServerInfoCommand.ts +++ b/src/commands/LanguageServerInfoCommand.ts @@ -12,6 +12,7 @@ import { util } from '../util'; import type { LocalPackageManager } from '../managers/LocalPackageManager'; import { standardizePath as s } from 'brighterscript'; import * as dayjs from 'dayjs'; +import type { QuickPickItem } from 'vscode'; dayjs.extend(relativeTime); export class LanguageServerInfoCommand { @@ -71,10 +72,11 @@ export class LanguageServerInfoCommand { await vscode.commands.executeCommand('extension.brightscript.languageServer.restart'); } - private discoverBrighterScriptVersions(workspaceFolders: string[]): BscVersionInfo[] { - const versions: BscVersionInfo[] = [{ + private discoverBrighterScriptVersions(workspaceFolders: string[]): QuickPickItemEnhanced[] { + const versions: QuickPickItemEnhanced[] = [{ label: `Use VSCode's version`, - description: languageServerManager.embeddedBscInfo.version + description: languageServerManager.embeddedBscInfo.version, + value: 'embedded' }]; //look for brighterscript in node_modules from all workspace folders @@ -100,7 +102,8 @@ export class LanguageServerInfoCommand { versions.push({ label: 'Use Workspace Version', description: version, - detail: bscPath.replace(/\\+/g, '/') + detail: bscPath.replace(/\\+/g, '/'), + value: bscPath.replace(/\\+/g, '/') }); } } @@ -147,7 +150,7 @@ export class LanguageServerInfoCommand { * If this changes the user/folder/workspace settings, that will trigger a reload of the language server so there's no need to * call the reload manually */ - public async selectBrighterScriptVersion() { + public async selectBrighterScriptVersion(): Promise { const quickPickItems = this.discoverBrighterScriptVersions( vscode.workspace.workspaceFolders.map(x => this.getWorkspaceOrFolderPath(x.uri.fsPath)) ); @@ -161,35 +164,33 @@ export class LanguageServerInfoCommand { description: '', detail: '', command: async () => { - let versionsFromNpm = (await versionsFromNpmPromise).map(x => ({ + let versionsFromNpm: QuickPickItemEnhanced[] = (await versionsFromNpmPromise).map(x => ({ label: x.version, - detail: x.version, + value: x.version, description: dayjs(x.date).fromNow(true) + ' ago' })); return await vscode.window.showQuickPick(versionsFromNpm, { placeHolder: `Select the BrighterScript version used for BrightScript and BrighterScript language features` }) as any; } } as any); - let selection = await vscode.window.showQuickPick(quickPickItems, { placeHolder: `Select the BrighterScript version used for BrightScript and BrighterScript language features` }) as any; + let selection: QuickPickItemEnhanced = await vscode.window.showQuickPick(quickPickItems, { placeHolder: `Select the BrighterScript version used for BrightScript and BrighterScript language features` }) as any; //if the selection has a command, run it before continuing; selection = await selection?.command?.() ?? selection; if (selection) { const config = vscode.workspace.getConfiguration('brightscript'); - //quickly clear the setting, then set it again so we are guaranteed to trigger a change event - await config.update('bsdk', undefined); - - //if the user picked "use embedded version", then remove the setting - if (quickPickItems.indexOf(selection) === 0) { - //setting to undefined means "remove" - await config.update('bsdk', 'embedded'); - return 'embedded'; + const currentValue = config.get('bsdk') ?? 'embedded'; + + //if the user chose the same value that's already there, just restart the language server + if (selection.value === currentValue) { + await this.restartLanguageServer(); + //set the new value } else { //save this to workspace/folder settings (vscode automatically decides if it goes into the code-workspace settings or the folder settings) - await config.update('bsdk', selection.detail); - return selection.detail; + await config.update('bsdk', selection.value); } + return selection.value; } } @@ -203,10 +204,6 @@ export class LanguageServerInfoCommand { } } -interface BscVersionInfo { - label: string; - description: string; - detail?: string; -} +type QuickPickItemEnhanced = QuickPickItem & { value: string; command?: () => Promise }; export const languageServerInfoCommand = new LanguageServerInfoCommand(); diff --git a/src/managers/LocalPackageManager.spec.ts b/src/managers/LocalPackageManager.spec.ts index 57f72a03..cb976b90 100644 --- a/src/managers/LocalPackageManager.spec.ts +++ b/src/managers/LocalPackageManager.spec.ts @@ -82,7 +82,15 @@ describe('LocalPackageManager', () => { customKey: 'test' }); - await manager.install('is-odd', '1.0.0'); + expect( + await manager.install('is-odd', '1.0.0') + ).to.include({ + packageDir: s`${storageDir}/is-odd/1.0.0/node_modules/is-odd`, + packageName: 'is-odd', + rootDir: s`${storageDir}/is-odd/1.0.0`, + versionDirName: '1.0.0', + versionInfo: '1.0.0' + }); expect( fsExtra.readJsonSync(`${storageDir}/is-odd/1.0.0/node_modules/is-odd/package.json`).customKey diff --git a/src/managers/LocalPackageManager.ts b/src/managers/LocalPackageManager.ts index 0dd8b768..5ea9bf1c 100644 --- a/src/managers/LocalPackageManager.ts +++ b/src/managers/LocalPackageManager.ts @@ -67,14 +67,13 @@ export class LocalPackageManager { //if this package is already installed, skip the install if (packageInfo.isInstalled) { - return; + return packageInfo; } - const rootDir = s`${this.storageLocation}/${packageName}/${packageInfo.versionDirName}`; - fsExtra.ensureDirSync(rootDir); + fsExtra.ensureDirSync(packageInfo.rootDir); //write a simple package.json file referencing the version of brighterscript we want - await fsExtra.outputJson(`${rootDir}/package.json`, { + await fsExtra.outputJson(`${packageInfo.rootDir}/package.json`, { name: 'vscode-brighterscript-host', private: true, version: '1.0.0', @@ -85,7 +84,7 @@ export class LocalPackageManager { //install the package await util.spawnNpmAsync(['install'], { - cwd: rootDir + cwd: packageInfo.rootDir }); //update the catalog diff --git a/src/util.ts b/src/util.ts index 05b65bd3..79c4d3c9 100644 --- a/src/util.ts +++ b/src/util.ts @@ -461,11 +461,17 @@ class Util { spawnNpmAsync(args: Array, options?: childProcess.SpawnOptions) { //filter out undefined args args = args.filter(arg => arg !== undefined); - return this.spawnAsync( - this.isWindowsPlatform() ? 'npm.cmd' : 'npm', - args, - options - ); + + if (this.isWindowsPlatform()) { + return this.spawnAsync('npm.cmd', args, { + ...options, + shell: true, + detached: false, + windowsHide: true + }); + } else { + return this.spawnAsync('npm', args, options); + } } /**