From 90cc7fb4e1400db6908b2c48de4ac060c813d704 Mon Sep 17 00:00:00 2001 From: Andy Jordan <2226434+andyleejordan@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:41:53 -0700 Subject: [PATCH] Check if the Terminal Shell Integration setting is changed Because if it is, we'll need to restart the Extension Terminal (unless it was hidden at startup). Also add a test to ensure we can find VS Code's script (in case its location changes upstream). --- src/session.ts | 38 +++++++++++++++++++++++--------------- src/utils.ts | 2 ++ test/core/paths.test.ts | 7 ++++++- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/session.ts b/src/session.ts index 238becbf04..d9667ef7a0 100644 --- a/src/session.ts +++ b/src/session.ts @@ -89,6 +89,7 @@ export class SessionManager implements Middleware { private sessionDetails: IEditorServicesSessionDetails | undefined; private sessionsFolder: vscode.Uri; private sessionStatus: SessionStatus = SessionStatus.NotStarted; + private shellIntegrationEnabled = false; private startCancellationTokenSource: vscode.CancellationTokenSource | undefined; private suppressRestartPrompt = false; private versionDetails: IPowerShellVersionDetails | undefined; @@ -109,6 +110,7 @@ export class SessionManager implements Middleware { // We have to override the scheme because it defaults to // 'vscode-userdata' which breaks UNC paths. this.sessionsFolder = vscode.Uri.joinPath(extensionContext.globalStorageUri.with({ scheme: "file" }), "sessions"); + this.platformDetails = getPlatformDetails(); this.HostName = hostName; this.DisplayName = displayName; @@ -189,6 +191,9 @@ export class SessionManager implements Middleware { // Migrate things. await this.migrateWhitespaceAroundPipeSetting(); + // Update non-PowerShell settings. + this.shellIntegrationEnabled = vscode.workspace.getConfiguration("terminal.integrated.shellIntegration").get("enabled") ?? false; + // Find the PowerShell executable to use for the server. this.PowerShellExeDetails = await this.findPowerShell(); @@ -447,19 +452,23 @@ export class SessionManager implements Middleware { private async onConfigurationUpdated(): Promise { const settings = getSettings(); + const shellIntegrationEnabled = vscode.workspace.getConfiguration("terminal.integrated.shellIntegration").get("enabled"); this.logger.updateLogLevel(settings.developer.editorServicesLogLevel); // Detect any setting changes that would affect the session. - if (!this.suppressRestartPrompt && this.sessionStatus === SessionStatus.Running && - (settings.cwd !== this.sessionSettings.cwd - || settings.powerShellDefaultVersion !== this.sessionSettings.powerShellDefaultVersion - || settings.developer.editorServicesLogLevel !== this.sessionSettings.developer.editorServicesLogLevel - || settings.developer.bundledModulesPath !== this.sessionSettings.developer.bundledModulesPath - || settings.developer.editorServicesWaitForDebugger !== this.sessionSettings.developer.editorServicesWaitForDebugger - || settings.developer.setExecutionPolicy !== this.sessionSettings.developer.setExecutionPolicy - || settings.integratedConsole.useLegacyReadLine !== this.sessionSettings.integratedConsole.useLegacyReadLine - || settings.integratedConsole.startInBackground !== this.sessionSettings.integratedConsole.startInBackground - || settings.integratedConsole.startLocation !== this.sessionSettings.integratedConsole.startLocation)) { + if (!this.suppressRestartPrompt + && this.sessionStatus === SessionStatus.Running + && ((shellIntegrationEnabled !== this.shellIntegrationEnabled + && !settings.integratedConsole.startInBackground) + || settings.cwd !== this.sessionSettings.cwd + || settings.powerShellDefaultVersion !== this.sessionSettings.powerShellDefaultVersion + || settings.developer.editorServicesLogLevel !== this.sessionSettings.developer.editorServicesLogLevel + || settings.developer.bundledModulesPath !== this.sessionSettings.developer.bundledModulesPath + || settings.developer.editorServicesWaitForDebugger !== this.sessionSettings.developer.editorServicesWaitForDebugger + || settings.developer.setExecutionPolicy !== this.sessionSettings.developer.setExecutionPolicy + || settings.integratedConsole.useLegacyReadLine !== this.sessionSettings.integratedConsole.useLegacyReadLine + || settings.integratedConsole.startInBackground !== this.sessionSettings.integratedConsole.startInBackground + || settings.integratedConsole.startLocation !== this.sessionSettings.integratedConsole.startLocation)) { this.logger.writeVerbose("Settings changed, prompting to restart..."); const response = await vscode.window.showInformationMessage( @@ -610,10 +619,6 @@ export class SessionManager implements Middleware { }); }; - // When Terminal Shell Integration is enabled, we pass the path to the script that the server should execute. - // Passing an empty string implies integration is disabled. - const shellIntegrationEnabled = vscode.workspace.getConfiguration("terminal.integrated.shellIntegration").get("enabled"); - const shellIntegrationScript = path.join(vscode.env.appRoot, "out", "vs", "workbench", "contrib", "terminal", "browser", "media", "shellIntegration.ps1"); const clientOptions: LanguageClientOptions = { documentSelector: this.documentSelector, @@ -624,10 +629,13 @@ export class SessionManager implements Middleware { // TODO: fileEvents: vscode.workspace.createFileSystemWatcher('**/.eslintrc') }, // NOTE: Some settings are only applicable on startup, so we send them during initialization. + // When Terminal Shell Integration is enabled, we pass the path to the script that the server should execute. + // Passing an empty string implies integration is disabled. initializationOptions: { enableProfileLoading: this.sessionSettings.enableProfileLoading, initialWorkingDirectory: await validateCwdSetting(this.logger), - shellIntegrationScript: shellIntegrationEnabled ? shellIntegrationScript : "", + shellIntegrationScript: this.shellIntegrationEnabled + ? utils.ShellIntegrationScript : "", }, errorHandler: { // Override the default error handler to prevent it from diff --git a/src/utils.ts b/src/utils.ts index 182612194e..9ae6e8f03a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,6 +7,8 @@ import vscode = require("vscode"); export const PowerShellLanguageId = "powershell"; +export const ShellIntegrationScript = path.join(vscode.env.appRoot, "out", "vs", "workbench", "contrib", "terminal", "browser", "media", "shellIntegration.ps1"); + export function escapeSingleQuotes(p: string): string { return p.replace(new RegExp("'", "g"), "''"); } diff --git a/test/core/paths.test.ts b/test/core/paths.test.ts index 628034a581..15f60f5bd1 100644 --- a/test/core/paths.test.ts +++ b/test/core/paths.test.ts @@ -5,7 +5,7 @@ import assert from "assert"; import * as vscode from "vscode"; import { IPowerShellExtensionClient } from "../../src/features/ExternalApi"; import utils = require("../utils"); -import { checkIfDirectoryExists } from "../../src/utils"; +import { checkIfDirectoryExists, checkIfFileExists, ShellIntegrationScript } from "../../src/utils"; describe("Path assumptions", function () { let globalStorageUri: vscode.Uri; @@ -21,4 +21,9 @@ describe("Path assumptions", function () { it("Creates the log folder at the correct path", async function () { assert(await checkIfDirectoryExists(vscode.Uri.joinPath(globalStorageUri, "logs"))); }); + + it("Finds the Terminal Shell Integration Script", async function () { + // If VS Code changes the location of the script, we need to know ASAP (as it's not a public API). + assert(await checkIfFileExists(ShellIntegrationScript)); + }); });