diff --git a/package-lock.json b/package-lock.json index b667841bec..b1317c7b29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "@typescript-eslint/eslint-plugin": "6.4.0", "@typescript-eslint/parser": "6.4.0", "@ungap/structured-clone": "1.2.0", + "@vscode/debugprotocol": "1.61.0", "@vscode/test-electron": "2.3.4", "@vscode/vsce": "2.20.1", "esbuild": "0.19.2", @@ -1297,6 +1298,12 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vscode/debugprotocol": { + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.61.0.tgz", + "integrity": "sha512-K/kF27jIStVFqlmUaGc2u+Dj8IR7YdEiSqShWr7MWhDudqpAW7uu7XMwoFwjpuC9LSaVwJMIX7EFC5OJ/RmnDQ==", + "dev": true + }, "node_modules/@vscode/extension-telemetry": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.8.2.tgz", @@ -6064,6 +6071,12 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "@vscode/debugprotocol": { + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.61.0.tgz", + "integrity": "sha512-K/kF27jIStVFqlmUaGc2u+Dj8IR7YdEiSqShWr7MWhDudqpAW7uu7XMwoFwjpuC9LSaVwJMIX7EFC5OJ/RmnDQ==", + "dev": true + }, "@vscode/extension-telemetry": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.8.2.tgz", diff --git a/package.json b/package.json index 8125a7fbc3..00bb89705c 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "@typescript-eslint/eslint-plugin": "6.4.0", "@typescript-eslint/parser": "6.4.0", "@ungap/structured-clone": "1.2.0", + "@vscode/debugprotocol": "1.61.0", "@vscode/test-electron": "2.3.4", "@vscode/vsce": "2.20.1", "esbuild": "0.19.2", diff --git a/src/features/DebugSession.ts b/src/features/DebugSession.ts index 55dd794e55..884b01ee7f 100644 --- a/src/features/DebugSession.ts +++ b/src/features/DebugSession.ts @@ -24,6 +24,7 @@ import { QuickPickOptions, DebugConfigurationProviderTriggerKind } from "vscode"; +import type { DebugProtocol } from "@vscode/debugprotocol"; import { NotificationType, RequestType } from "vscode-languageclient"; import { LanguageClient } from "vscode-languageclient/node"; import { LanguageClientConsumer } from "../languageClientConsumer"; @@ -375,25 +376,48 @@ export class DebugSessionFeature extends LanguageClientConsumer dotnetAttachConfig.processId = pid; // Ensure the .NET session stops before the PowerShell session so that the .NET debug session doesn't emit an error about the process unexpectedly terminating. - const startDebugEvent = debug.onDidStartDebugSession((dotnetAttachSession) => { + let tempConsoleDotnetAttachSession: DebugSession; + const startDebugEvent = debug.onDidStartDebugSession(dotnetAttachSession => { + if (dotnetAttachSession.configuration.name != dotnetAttachConfig.name) { return; } + // Makes the event one-time // HACK: This seems like you would be calling a method on a variable not assigned yet, but it does work in the flow. // The dispose shorthand demonry for making an event one-time courtesy of: https://github.com/OmniSharp/omnisharp-vscode/blob/b8b07bb12557b4400198895f82a94895cb90c461/test/integrationTests/launchConfiguration.integration.test.ts#L41-L45 startDebugEvent.dispose(); + this.logger.writeVerbose(`Debugger session detected: ${dotnetAttachSession.name} (${dotnetAttachSession.id})`); - if (dotnetAttachSession.configuration.name == dotnetAttachConfig.name) { - const stopDebugEvent = debug.onDidTerminateDebugSession(async (terminatedDebugSession) => { - // Makes the event one-time - stopDebugEvent.dispose(); - this.logger.writeVerbose(`Debugger session stopped: ${terminatedDebugSession.name} (${terminatedDebugSession.id})`); + tempConsoleDotnetAttachSession = dotnetAttachSession; + + const stopDebugEvent = debug.onDidTerminateDebugSession(async tempConsoleSession => { + if (tempConsoleDotnetAttachSession.parentSession?.id !== tempConsoleSession.id) { return; } - if (terminatedDebugSession === session) { - this.logger.writeVerbose("Terminating dotnet debugger session associated with PowerShell debug session!"); - await debug.stopDebugging(dotnetAttachSession); + // Makes the event one-time + stopDebugEvent.dispose(); + + this.logger.writeVerbose(`Debugger session terminated: ${tempConsoleSession.name} (${tempConsoleSession.id})`); + + // HACK: As of 2023-08-17, there is no vscode debug API to request the C# debugger to detach, so we send it a custom DAP request instead. + const disconnectRequest: DebugProtocol.DisconnectRequest = { + command: "disconnect", + seq: 0, + type: "request", + arguments: { + restart: false, + terminateDebuggee: false, + suspendDebuggee: false } - }); - } + }; + + try { + await dotnetAttachSession.customRequest( + disconnectRequest.command, + disconnectRequest.arguments + ); + } catch (err) { + this.logger.writeWarning(`Disconnect request to dotnet debugger failed: ${err}`); + } + }); }); // Start a child debug session to attach the dotnet debugger diff --git a/test/features/DebugSession.test.ts b/test/features/DebugSession.test.ts index 3b9b854680..60e18021cc 100644 --- a/test/features/DebugSession.test.ts +++ b/test/features/DebugSession.test.ts @@ -428,13 +428,16 @@ describe("DebugSessionFeature", () => { }); }); -describe("DebugSessionFeature E2E", () => { +describe("DebugSessionFeature E2E", function() { + // E2E tests can take a while to run since the debugger has to start up and attach + this.slow(20000); before(async () => { // Registers and warms up the debug adapter and the PowerShell Extension Terminal await ensureEditorServicesIsConnected(); }); it("Starts and stops a debugging session", async () => { + // Inspect the debug session via the started events to ensure it is correct const startDebugSession = new Promise((resolve) => { const event = debug.onDidStartDebugSession((session) => { diff --git a/test/features/ISECompatibility.test.ts b/test/features/ISECompatibility.test.ts index 792c3dd7bb..0f2152c1c6 100644 --- a/test/features/ISECompatibility.test.ts +++ b/test/features/ISECompatibility.test.ts @@ -73,6 +73,8 @@ describe("ISE compatibility feature", function () { }); describe("Color theme interactions", function () { + // These tests are slow because they change the user's theme. + this.slow(3000); beforeEach(enableISEMode); function assertISESettings(): void {