Skip to content

Commit 77907f4

Browse files
committed
Fixup SwiftPackage tests, less coupling in task queue
1 parent 7941406 commit 77907f4

File tree

5 files changed

+167
-135
lines changed

5 files changed

+167
-135
lines changed

src/FolderContext.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ export class FolderContext implements vscode.Disposable {
5858
) {
5959
this.packageWatcher = new PackageWatcher(this, workspaceContext.logger);
6060
this.backgroundCompilation = new BackgroundCompilation(this);
61-
this.taskQueue = new TaskQueue(this);
61+
this.taskQueue = new TaskQueue(
62+
workspaceContext.tasks,
63+
workspaceContext.statusItem,
64+
workspaceContext.logger,
65+
this.name
66+
);
6267
this.testRunManager = new TestRunManager();
6368

6469
// In order to track down why a FolderContext may be created when we don't want one,

src/SwiftPackage.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,17 @@ export class SwiftPackage {
266266
public async loadPackageState(
267267
folderContext: FolderContext,
268268
disableSwiftPMIntegration: boolean = false
269-
): Promise<void> {
269+
): Promise<SwiftPackageState> {
270270
// When SwiftPM integration is disabled, return empty package structure
271271
if (disableSwiftPMIntegration) {
272-
this.contentsResolve({
272+
const empty = {
273273
name: path.basename(folderContext.folder.fsPath),
274274
products: [],
275275
dependencies: [],
276276
targets: [],
277-
});
278-
return;
277+
};
278+
this.contentsResolve(empty);
279+
return empty;
279280
}
280281

281282
try {
@@ -290,26 +291,21 @@ export class SwiftPackage {
290291
};
291292

292293
this.contentsResolve(packageState);
293-
} catch (error) {
294-
const execError = error as { stderr: string };
294+
return packageState;
295+
} catch (error: unknown) {
296+
const errorMessage = error instanceof Error ? error.message : String(error);
295297
// if caught error and it begins with "error: root manifest" then there is no Package.swift
296298
if (
297-
execError.stderr !== undefined &&
298-
(execError.stderr.startsWith("error: root manifest") ||
299-
execError.stderr.startsWith("error: Could not find Package.swift"))
299+
errorMessage.startsWith("error: root manifest") ||
300+
errorMessage.startsWith("error: Could not find Package.swift")
300301
) {
301-
this.contentsResolve({
302-
name: path.basename(folderContext.folder.fsPath),
303-
products: [],
304-
dependencies: [],
305-
targets: [],
306-
});
307-
return;
302+
this.contentsResolve(undefined);
303+
return undefined;
308304
} else {
309305
// otherwise it is an error loading the Package.swift so return `null` indicating
310-
// we have a package but we failed to load it
311-
this.contentsReject(Error(getErrorDescription(error)));
312-
return;
306+
// we have a package but we failed to load it. Calling resolve instead of reject is intent
307+
this.contentsResolve(Error(getErrorDescription(error)));
308+
return undefined;
313309
}
314310
}
315311
}
@@ -393,7 +389,12 @@ export class SwiftPackage {
393389
});
394390
this.contentsResolve = res!;
395391
this.contentsReject = rej!;
396-
await this.loadPackageState(folderContext, disableSwiftPMIntegration);
392+
const loadedContents = await this.loadPackageState(
393+
folderContext,
394+
disableSwiftPMIntegration
395+
);
396+
397+
this._contents = loadedContents;
397398
}
398399

399400
/** Reload Package.resolved file */

src/commands/dependencies/common.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,18 @@ export async function executeSwiftPackageCommand<T>(
6767
const success = await executeTaskWithUI(task, config.uiMessage, folderContext, false);
6868
updateAfterError(success, folderContext);
6969

70-
const stdout = outputChunks.join("");
71-
if (!stdout.trim()) {
70+
const output = outputChunks.join("");
71+
72+
if (!success) {
73+
throw new Error(output);
74+
}
75+
76+
if (!output.trim()) {
7277
throw new Error(`No output received from swift ${config.commandName} command`);
7378
}
7479

7580
try {
76-
const trimmedOutput = SwiftPackage.trimStdout(stdout);
81+
const trimmedOutput = SwiftPackage.trimStdout(output);
7782
const parsedOutput = JSON.parse(trimmedOutput);
7883

7984
// Validate the parsed output is an object

src/tasks/TaskQueue.ts

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
import * as vscode from "vscode";
1515

1616
import { FolderContext } from "../FolderContext";
17-
import { WorkspaceContext } from "../WorkspaceContext";
17+
import { SwiftLogger } from "../logging/SwiftLogger";
18+
import { StatusItem } from "../ui/StatusItem";
1819
import { execSwift, poll } from "../utilities/utilities";
20+
import { TaskManager } from "./TaskManager";
1921

2022
export interface SwiftOperationOptions {
2123
// Should I show a status item
@@ -39,7 +41,8 @@ export interface SwiftOperation {
3941
isBuildOperation: boolean;
4042
// run operation
4143
run(
42-
workspaceContext: WorkspaceContext,
44+
taskManager: TaskManager,
45+
logger: SwiftLogger,
4346
token: vscode.CancellationToken | undefined
4447
): Promise<number | undefined>;
4548
}
@@ -82,14 +85,15 @@ export class TaskOperation implements SwiftOperation {
8285
}
8386

8487
run(
85-
workspaceContext: WorkspaceContext,
88+
taskManager: TaskManager,
89+
logger: SwiftLogger,
8690
token?: vscode.CancellationToken
8791
): Promise<number | undefined> {
8892
if (token?.isCancellationRequested) {
8993
return Promise.resolve(undefined);
9094
}
91-
workspaceContext.logger.info(`Exec Task: ${this.task.detail ?? this.task.name}`);
92-
return workspaceContext.tasks.executeTaskAndWait(this.task, token);
95+
logger.info(`Exec Task: ${this.task.detail ?? this.task.name}`);
96+
return taskManager.executeTaskAndWait(this.task, token);
9397
}
9498
}
9599

@@ -153,8 +157,8 @@ class QueuedOperation {
153157
public token?: vscode.CancellationToken
154158
) {}
155159

156-
run(workspaceContext: WorkspaceContext): Promise<number | undefined> {
157-
return this.operation.run(workspaceContext, this.token);
160+
run(taskManager: TaskManager, logger: SwiftLogger): Promise<number | undefined> {
161+
return this.operation.run(taskManager, logger, this.token);
158162
}
159163
}
160164

@@ -164,17 +168,16 @@ class QueuedOperation {
164168
* Queue swift task operations to be executed serially
165169
*/
166170
export class TaskQueue implements vscode.Disposable {
167-
queue: QueuedOperation[];
171+
queue: QueuedOperation[] = [];
168172
activeOperation?: QueuedOperation;
169-
workspaceContext: WorkspaceContext;
170-
disabled: boolean;
173+
disabled: boolean = false;
171174

172-
constructor(private folderContext: FolderContext) {
173-
this.queue = [];
174-
this.workspaceContext = folderContext.workspaceContext;
175-
this.activeOperation = undefined;
176-
this.disabled = false;
177-
}
175+
constructor(
176+
private taskManager: TaskManager,
177+
private statusItem: StatusItem,
178+
private logger: SwiftLogger,
179+
private name: string
180+
) {}
178181

179182
dispose() {
180183
this.queue = [];
@@ -244,34 +247,25 @@ export class TaskQueue implements vscode.Disposable {
244247
this.activeOperation = operation;
245248
// show active task status item
246249
if (operation.showStatusItem === true) {
247-
this.workspaceContext.statusItem.start(operation.operation.statusItemId);
250+
this.statusItem.start(operation.operation.statusItemId);
248251
}
249252
// wait while queue is disabled before running task
250253
await this.waitWhileDisabled();
251254
// log start
252255
if (operation.log) {
253-
this.workspaceContext.logger.info(
254-
`${operation.log}: starting ... `,
255-
this.folderContext.name
256-
);
256+
this.logger.info(`${operation.log}: starting ... `, this.name);
257257
}
258258
operation
259-
.run(this.workspaceContext)
259+
.run(this.taskManager, this.logger)
260260
.then(result => {
261261
// log result
262262
if (operation.log && !operation.token?.isCancellationRequested) {
263263
switch (result) {
264264
case 0:
265-
this.workspaceContext.logger.info(
266-
`${operation.log}: ... done.`,
267-
this.folderContext.name
268-
);
265+
this.logger.info(`${operation.log}: ... done.`, this.name);
269266
break;
270267
default:
271-
this.workspaceContext.logger.error(
272-
`${operation.log}: ... failed.`,
273-
this.folderContext.name
274-
);
268+
this.logger.error(`${operation.log}: ... failed.`, this.name);
275269
break;
276270
}
277271
}
@@ -280,10 +274,7 @@ export class TaskQueue implements vscode.Disposable {
280274
.catch(error => {
281275
// log error
282276
if (operation.log) {
283-
this.workspaceContext.logger.error(
284-
`${operation.log}: ${error}`,
285-
this.folderContext.name
286-
);
277+
this.logger.error(`${operation.log}: ${error}`, this.name);
287278
}
288279
this.finishTask(operation, { fail: error });
289280
});
@@ -294,7 +285,7 @@ export class TaskQueue implements vscode.Disposable {
294285
private finishTask(operation: QueuedOperation, result: TaskQueueResult) {
295286
operation.cb(result);
296287
if (operation.showStatusItem === true) {
297-
this.workspaceContext.statusItem.end(operation.operation.statusItemId);
288+
this.statusItem.end(operation.operation.statusItemId);
298289
}
299290
this.activeOperation = undefined;
300291
void this.processQueue();

0 commit comments

Comments
 (0)