Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor to use inline action buttons
  • Loading branch information
plemarquand committed Feb 21, 2025
commit 9ddd56b7c20e8277cbf53fc14caeada817a747bb
6 changes: 5 additions & 1 deletion assets/test/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@
"-DTEST_ARGUMENT_SET_VIA_TEST_BUILD_ARGUMENTS_SETTING"
],
"lldb.verboseLogging": true,
"swift.backgroundCompilation": false
"swift.backgroundCompilation": false,
"swift.debugger.useDebugAdapterFromToolchain": false,
"lldb.library": "/usr/lib/liblldb.so",
"lldb.launch.expressions": "native",
"swift.pluginPermissions": {}
}
4 changes: 4 additions & 0 deletions assets/test/targets/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,9 @@ let package = Package(
name: "TargetsTests",
dependencies: ["LibraryTarget"]
),
.testTarget(
name: "AnotherTests",
dependencies: ["LibraryTarget"]
),
]
)
5 changes: 4 additions & 1 deletion assets/test/targets/Sources/LibraryTarget/Targets.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book

func foo() {
public func foo() {
print("foo")
}
public func bar() {
print("bar")
}
8 changes: 8 additions & 0 deletions assets/test/targets/Tests/AnotherTests/AnotherTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import LibraryTarget
import XCTest

class AnotherTests: XCTestCase {
func testExample() {
bar()
}
}
2 changes: 2 additions & 0 deletions assets/test/targets/Tests/TargetsTests/TargetsTests.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import LibraryTarget
import XCTest

class TargetsTests: XCTestCase {
func testExample() {
foo()
}
}
80 changes: 74 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,14 @@
{
"command": "swift.runSnippet",
"title": "Run Swift Snippet",
"category": "Swift"
"category": "Swift",
"icon": "$(play)"
},
{
"command": "swift.debugSnippet",
"title": "Debug Swift Snippet",
"category": "Swift"
"category": "Swift",
"icon": "$(debug)"
},
{
"command": "swift.runPluginTask",
Expand Down Expand Up @@ -266,13 +268,27 @@
},
{
"command": "swift.runAllTestsParallel",
"title": "Run All Tests in Parallel",
"category": "Test"
"title": "Run Tests in Parallel",
"category": "Test",
"icon": "$(testing-run-all-icon)"
},
{
"command": "swift.runAllTests",
"title": "Run All Tests",
"category": "Test"
"title": "Run Tests",
"category": "Test",
"icon": "$(testing-run-icon)"
},
{
"command": "swift.debugAllTests",
"title": "Debug Tests",
"category": "Test",
"icon": "$(testing-debug-icon)"
},
{
"command": "swift.coverAllTests",
"title": "Run Tests with Coverage",
"category": "Test",
"icon": "$(debug-coverage)"
}
],
"configuration": [
Expand Down Expand Up @@ -915,6 +931,18 @@
{
"command": "swift.runAllTestsParallel",
"when": "swift.isActivated"
},
{
"command": "swift.runAllTests",
"when": "false"
},
{
"command": "swift.debugAllTests",
"when": "false"
},
{
"command": "swift.coverAllTests",
"when": "false"
}
],
"editor/context": [
Expand Down Expand Up @@ -1020,6 +1048,46 @@
{
"command": "swift.openExternal",
"when": "view == projectPanel && (viewItem == 'editing' || viewItem == 'remote')"
},
{
"command": "swift.run",
"when": "view == projectPanel && viewItem == 'runnable'",
"group": "inline@0"
},
{
"command": "swift.debug",
"when": "view == projectPanel && viewItem == 'runnable'",
"group": "inline@1"
},
{
"command": "swift.runSnippet",
"when": "view == projectPanel && viewItem == 'snippet_runnable'",
"group": "inline@0"
},
{
"command": "swift.debugSnippet",
"when": "view == projectPanel && viewItem == 'snippet_runnable'",
"group": "inline@1"
},
{
"command": "swift.runAllTests",
"when": "view == projectPanel && viewItem == 'test_runnable'",
"group": "inline@0"
},
{
"command": "swift.debugAllTests",
"when": "view == projectPanel && viewItem == 'test_runnable'",
"group": "inline@1"
},
{
"command": "swift.runAllTestsParallel",
"when": "view == projectPanel && viewItem == 'test_runnable'",
"group": "inline@2"
},
{
"command": "swift.coverAllTests",
"when": "view == projectPanel && viewItem == 'test_runnable'",
"group": "inline@3"
}
]
},
Expand Down
17 changes: 15 additions & 2 deletions src/TestExplorer/TestRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,14 +520,27 @@ export class TestRunner {
];
}

/**
* Extracts a list of unique test Targets from the list of test items.
*/
private testTargets(items: vscode.TestItem[]): string[] {
const targets = new Set<string>();
for (const item of items) {
const target = item.id.split(".")[0];
targets.add(target);
}
return Array.from(targets);
}

/**
* Test run handler. Run a series of tests and extracts the results from the output
* @param shouldDebug Should we run the debugger
* @param token Cancellation token
* @returns When complete
*/
async runHandler() {
this.workspaceContext.testsStarted(this.folderContext, this.testKind);
const testTargets = this.testTargets(this.testArgs.testItems);
this.workspaceContext.testsStarted(this.folderContext, this.testKind, testTargets);

const runState = new TestRunnerTestRunState(this.testRun);

Expand All @@ -554,7 +567,7 @@ export class TestRunner {
cancellationDisposable.dispose();
await this.testRun.end();

this.workspaceContext.testsFinished(this.folderContext, this.testKind);
this.workspaceContext.testsFinished(this.folderContext, this.testKind, testTargets);
}

/** Run test session without attaching to a debugger */
Expand Down
9 changes: 5 additions & 4 deletions src/WorkspaceContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,12 @@ export class WorkspaceContext implements vscode.Disposable {
await this.fireEvent(folderContext, FolderOperation.focus);
}

public testsFinished(folder: FolderContext, kind: TestKind) {
this.testFinishEmitter.fire({ kind, folder });
public testsFinished(folder: FolderContext, kind: TestKind, targets: string[]) {
this.testFinishEmitter.fire({ kind, folder, targets });
}

public testsStarted(folder: FolderContext, kind: TestKind) {
this.testStartEmitter.fire({ kind, folder });
public testsStarted(folder: FolderContext, kind: TestKind, targets: string[]) {
this.testStartEmitter.fire({ kind, folder, targets });
}

public buildStarted(
Expand Down Expand Up @@ -634,6 +634,7 @@ export class WorkspaceContext implements vscode.Disposable {
interface TestEvent {
kind: TestKind;
folder: FolderContext;
targets: string[];
}

/** Build events for build + run start/stop */
Expand Down
49 changes: 40 additions & 9 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { updateDependencies } from "./commands/dependencies/update";
import { runPluginTask } from "./commands/runPluginTask";
import { runTestMultipleTimes } from "./commands/testMultipleTimes";
import { newSwiftFile } from "./commands/newFile";
import { runAllTests, runAllTestsParallel } from "./commands/runAllTests";
import { runAllTests } from "./commands/runAllTests";
import { updateDependenciesViewList } from "./commands/dependencies/updateDepViewList";
import { runTask } from "./commands/runTask";
import { TestKind } from "./TestExplorer/TestKind";
Expand Down Expand Up @@ -84,6 +84,10 @@ export enum Commands {
RUN_SNIPPET = "swift.runSnippet",
DEBUG_SNIPPET = "swift.debugSnippet",
PREVIEW_DOCUMENTATION = "swift.previewDocumentation",
RUN_ALL_TESTS = "swift.runAllTests",
RUN_ALL_TESTS_PARALLEL = "swift.runAllTestsParallel",
DEBUG_ALL_TESTS = "swift.debugAllTests",
COVER_ALL_TESTS = "swift.coverAllTests",
}

/**
Expand All @@ -98,8 +102,12 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] {
vscode.commands.registerCommand(Commands.UPDATE_DEPENDENCIES, () =>
updateDependencies(ctx)
),
vscode.commands.registerCommand(Commands.RUN, target => runBuild(ctx, target)),
vscode.commands.registerCommand(Commands.DEBUG, target => debugBuild(ctx, target)),
vscode.commands.registerCommand(Commands.RUN, target =>
runBuild(ctx, ...unwrapTreeItem(target))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to mention that SourceKit-LSP will include the target name as a string for the swift.run and swift.debug commands starting in 6.2, but it looks like that case is already covered by unwrapTreeItem(). Nice.

),
vscode.commands.registerCommand(Commands.DEBUG, target =>
debugBuild(ctx, ...unwrapTreeItem(target))
),
vscode.commands.registerCommand(Commands.CLEAN_BUILD, () => cleanBuild(ctx)),
vscode.commands.registerCommand(Commands.RUN_TESTS_MULTIPLE_TIMES, item => {
if (ctx.currentFolder) {
Expand All @@ -120,9 +128,11 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] {
return openPackage(ctx.toolchain.swiftVersion, ctx.currentFolder.folder);
}
}),
vscode.commands.registerCommand(Commands.RUN_SNIPPET, target => runSnippet(ctx, target)),
vscode.commands.registerCommand(Commands.RUN_SNIPPET, target =>
runSnippet(ctx, ...unwrapTreeItem(target))
),
vscode.commands.registerCommand(Commands.DEBUG_SNIPPET, target =>
debugSnippet(ctx, target)
debugSnippet(ctx, ...unwrapTreeItem(target))
),
vscode.commands.registerCommand(Commands.RUN_PLUGIN_TASK, () => runPluginTask()),
vscode.commands.registerCommand(Commands.RUN_TASK, name => runTask(ctx, name)),
Expand Down Expand Up @@ -164,12 +174,20 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] {
),
vscode.commands.registerCommand("swift.captureDiagnostics", () => captureDiagnostics(ctx)),
vscode.commands.registerCommand(
"swift.runAllTestsParallel",
async () => await runAllTestsParallel(ctx)
Commands.RUN_ALL_TESTS_PARALLEL,
async item => await runAllTests(ctx, TestKind.parallel, ...unwrapTreeItem(item))
),
vscode.commands.registerCommand(
"swift.runAllTests",
async (testKind: TestKind) => await runAllTests(ctx, testKind)
Commands.RUN_ALL_TESTS,
async item => await runAllTests(ctx, TestKind.standard, ...unwrapTreeItem(item))
),
vscode.commands.registerCommand(
Commands.DEBUG_ALL_TESTS,
async item => await runAllTests(ctx, TestKind.debug, ...unwrapTreeItem(item))
),
vscode.commands.registerCommand(
Commands.COVER_ALL_TESTS,
async item => await runAllTests(ctx, TestKind.coverage, ...unwrapTreeItem(item))
),
vscode.commands.registerCommand(
Commands.PREVIEW_DOCUMENTATION,
Expand All @@ -183,3 +201,16 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] {
),
];
}

/**
* Certain commands can be called via a vscode TreeView, which will pass a {@link CommandNode} object.
* If the command is called via a command palette or other means, the target will be a string.
*/
function unwrapTreeItem(target?: string | { args: string[] }): string[] {
if (typeof target === "object" && target !== null && "args" in target) {
return target.args ?? [];
} else if (typeof target === "string") {
return [target];
}
return [];
}
14 changes: 8 additions & 6 deletions src/commands/runAllTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { TestKind } from "../TestExplorer/TestKind";
import { WorkspaceContext } from "../WorkspaceContext";
import { flattenTestItemCollection } from "../TestExplorer/TestUtils";

export async function runAllTests(ctx: WorkspaceContext, testKind: TestKind) {
export async function runAllTests(ctx: WorkspaceContext, testKind: TestKind, target?: string) {
const testExplorer = ctx.currentFolder?.testExplorer;
if (testExplorer === undefined) {
return;
Expand All @@ -28,7 +28,13 @@ export async function runAllTests(ctx: WorkspaceContext, testKind: TestKind) {
return;
}

const tests = flattenTestItemCollection(testExplorer.controller.items);
let tests = flattenTestItemCollection(testExplorer.controller.items);

// If a target is specified, filter the tests to only run those that match the target.
if (target) {
const targetRegex = new RegExp(`^${target}(\\.|$)`);
tests = tests.filter(test => targetRegex.test(test.id));
}
const tokenSource = new vscode.CancellationTokenSource();
await profile.runHandler(
new vscode.TestRunRequest(tests, undefined, profile),
Expand All @@ -37,7 +43,3 @@ export async function runAllTests(ctx: WorkspaceContext, testKind: TestKind) {

await vscode.commands.executeCommand("testing.showMostRecentOutput");
}

export async function runAllTestsParallel(ctx: WorkspaceContext) {
await runAllTests(ctx, TestKind.parallel);
}
1 change: 1 addition & 0 deletions src/debugger/launch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export function createSnippetConfiguration(
args: [],
cwd: folder,
env: swiftRuntimeEnv(true),
runType: "snippet",
...CI_DISABLE_ASLR,
};
}
Expand Down
Loading