Skip to content

Commit 6476307

Browse files
committed
- Added module enum for workbench commands string constant
- Added comments for clarification - Added utilities to listen for dap message, this is useful for test synchronization. Code takes inspiration from #1126
1 parent 690f49d commit 6476307

File tree

8 files changed

+123
-8
lines changed

8 files changed

+123
-8
lines changed

src/ui/ReloadExtension.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
import * as vscode from "vscode";
16+
import { Workbench } from "../utilities/command";
1617

1718
/**
1819
* Prompts the user to reload the extension in cases where we are unable to do
@@ -29,7 +30,7 @@ export async function showReloadExtensionNotification<T extends string>(
2930
const buttons: ("Reload Extensions" | T)[] = ["Reload Extensions", ...items];
3031
const selected = await vscode.window.showWarningMessage(message, ...buttons);
3132
if (selected === "Reload Extensions") {
32-
await vscode.commands.executeCommand("workbench.action.reloadWindow");
33+
await vscode.commands.executeCommand(Workbench.ACTION_RELOADWINDOW);
3334
}
3435
return selected;
3536
}

src/utilities/command.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2024 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
//
15+
export enum Workbench {
16+
ACTION_DEBUG_CONTINUE = "workbench.action.debug.continue",
17+
ACTION_CLOSEALLEDITORS = "workbench.action.closeAllEditors",
18+
ACTION_RELOADWINDOW = "workbench.action.reloadWindow",
19+
}

test/integration-tests/BackgroundCompilation.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { WorkspaceContext } from "../../src/WorkspaceContext";
1818
import { globalWorkspaceContextPromise } from "./extension.test";
1919
import { testAssetUri } from "../fixtures";
2020
import { waitForNoRunningTasks } from "../utilities";
21+
import { Workbench } from "../../src/utilities/command";
2122

2223
suite("BackgroundCompilation Test Suite", () => {
2324
let workspaceContext: WorkspaceContext;
@@ -31,7 +32,7 @@ suite("BackgroundCompilation Test Suite", () => {
3132

3233
suiteTeardown(async () => {
3334
await vscode.workspace.getConfiguration("swift").update("backgroundCompilation", undefined);
34-
await vscode.commands.executeCommand("workbench.action.closeActiveEditor");
35+
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);
3536
});
3637

3738
test("build all on save @slow", async () => {

test/integration-tests/DiagnosticsManager.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { DiagnosticsManager } from "../../src/DiagnosticsManager";
2323
import { FolderContext } from "../../src/FolderContext";
2424
import { Version } from "../../src/utilities/version";
2525
import { folderContextPromise, globalWorkspaceContextPromise } from "./extension.test";
26+
import { Workbench } from "../../src/utilities/command";
2627

2728
const waitForDiagnostics = (uris: vscode.Uri[], allowEmpty: boolean = true) =>
2829
new Promise<void>(res =>
@@ -907,7 +908,7 @@ suite("DiagnosticsManager Test Suite", async function () {
907908
});
908909

909910
teardown(async () => {
910-
await vscode.commands.executeCommand("workbench.action.closeAllEditors");
911+
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);
911912
});
912913

913914
test("Provides swift diagnostics", async () => {

test/integration-tests/commands/build.test.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import { FolderContext } from "../../../src/FolderContext";
2323
import { WorkspaceContext } from "../../../src/WorkspaceContext";
2424
import { Commands } from "../../../src/commands";
2525
import { makeDebugConfigurations } from "../../../src/debugger/launch";
26+
import { Workbench } from "../../../src/utilities/command";
27+
import { continueSession, waitForDebugAdapterCommand } from "../../utilities/debug";
2628

2729
suite("Build Commands", function () {
2830
let folderContext: FolderContext;
@@ -42,7 +44,7 @@ suite("Build Commands", function () {
4244
});
4345

4446
suiteTeardown(async () => {
45-
await vscode.commands.executeCommand("workbench.action.closeAllEditors");
47+
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);
4648
});
4749

4850
test("Swift: Run Build", async () => {
@@ -63,16 +65,27 @@ suite("Build Commands", function () {
6365
expect(result).to.be.true;
6466

6567
const afterItemCount = fs.readdirSync(buildPath).length;
68+
// This test will run in order after the Swift: Run Build test,
69+
// where .build folder is going to be filled with built artifacts.
70+
// After executing the clean command the build directory is guranteed to have less entry.
6671
expect(afterItemCount).to.be.lessThan(beforeItemCount);
6772
});
6873

69-
test("Swift: Debug Build", async () => {
74+
test("Swift: Debug Build @slow", async () => {
7075
vscode.debug.addBreakpoints(breakpoints);
76+
// Promise used to indicate we hit the break point.
77+
// NB: "stopped" is the exact command when debuggee has stopped due to break point,
78+
// but "stackTrace" is the deterministic sync point we will use to make sure we can execute continue
79+
const bpPromise = waitForDebugAdapterCommand(
80+
"Debug PackageExe (defaultPackage)",
81+
"stackTrace",
82+
workspaceContext
83+
);
7184

7285
const result = vscode.commands.executeCommand(Commands.DEBUG);
7386
expect(result).to.eventually.be.true;
7487

75-
await vscode.commands.executeCommand("workbench.action.debug.continue");
88+
await bpPromise.then(() => continueSession());
7689
vscode.debug.removeBreakpoints(breakpoints);
7790
});
7891
});

test/integration-tests/editor/CommentCompletion.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import * as assert from "assert";
1616
import * as vscode from "vscode";
1717
import { CommentCompletionProviders } from "../../../src/editor/CommentCompletion";
18+
import { Workbench } from "../../../src/utilities/command";
1819

1920
suite("CommentCompletion Test Suite", () => {
2021
let document: vscode.TextDocument | undefined;
@@ -31,7 +32,7 @@ suite("CommentCompletion Test Suite", () => {
3132

3233
if (editor && document) {
3334
await vscode.window.showTextDocument(document, editor.viewColumn);
34-
await vscode.commands.executeCommand("workbench.action.closeActiveEditor");
35+
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);
3536
}
3637

3738
provider.dispose();

test/unit-tests/ui/ReloadExtension.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { expect } from "chai";
1515
import { mockGlobalObject } from "../../MockUtils";
1616
import * as vscode from "vscode";
1717
import { showReloadExtensionNotification } from "../../../src/ui/ReloadExtension";
18+
import { Workbench } from "../../../src/utilities/command";
1819

1920
suite("showReloadExtensionNotification()", async function () {
2021
const mockedVSCodeWindow = mockGlobalObject(vscode, "window");
@@ -38,7 +39,7 @@ suite("showReloadExtensionNotification()", async function () {
3839
await showReloadExtensionNotification("Want to reload?");
3940

4041
expect(mockedVSCodeCommands.executeCommand).to.have.been.calledOnceWithExactly(
41-
"workbench.action.reloadWindow"
42+
Workbench.ACTION_RELOADWINDOW
4243
);
4344
});
4445

test/utilities/debug.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2024 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
import * as vscode from "vscode";
15+
import { Workbench } from "../../src/utilities/command";
16+
import { DebugAdapter } from "../../src/debugger/debugAdapter";
17+
import { WorkspaceContext } from "../../src/WorkspaceContext";
18+
19+
export async function continueSession(): Promise<void> {
20+
await vscode.commands.executeCommand(Workbench.ACTION_DEBUG_CONTINUE);
21+
}
22+
23+
/**
24+
* Waits for a specific message from the debug adapter.
25+
*
26+
* @param name The name of the debug session to wait for.
27+
* @param matches A function to match the desired message.
28+
* @param workspaceContext The workspace context containing toolchain information.
29+
* @returns A promise that resolves with the matching message.
30+
*/
31+
export async function waitForDebugAdapterMessage(
32+
name: string,
33+
matches: (message: any) => boolean,
34+
workspaceContext: WorkspaceContext
35+
): Promise<any> {
36+
return await new Promise<any>(res => {
37+
const disposable = vscode.debug.registerDebugAdapterTrackerFactory(
38+
DebugAdapter.getLaunchConfigType(workspaceContext.toolchain.swiftVersion),
39+
{
40+
createDebugAdapterTracker: function (
41+
session: vscode.DebugSession
42+
): vscode.ProviderResult<vscode.DebugAdapterTracker> {
43+
if (session.name !== name) {
44+
return;
45+
}
46+
return {
47+
onDidSendMessage(message) {
48+
if (matches(message)) {
49+
disposable.dispose();
50+
res(message);
51+
}
52+
},
53+
};
54+
},
55+
}
56+
);
57+
});
58+
}
59+
60+
/**
61+
* Waits for a specific command to be sent by the debug adapter.
62+
*
63+
* @param name The name of the debug session to wait for.
64+
* @param command The command to wait for.
65+
* @param workspaceContext The workspace context containing toolchain information.
66+
* @returns A promise that resolves with the matching command message.
67+
*/
68+
export async function waitForDebugAdapterCommand(
69+
name: string,
70+
command: string,
71+
workspaceContext: WorkspaceContext
72+
): Promise<any> {
73+
return await waitForDebugAdapterMessage(
74+
name,
75+
(m: any) => m.command === command,
76+
workspaceContext
77+
);
78+
}

0 commit comments

Comments
 (0)