Skip to content

Commit 3c63564

Browse files
committed
Merge branch 'topic/gnattest' into 'master'
Fix retrieval of test list when test tree is not expanded Closes #1581 See merge request eng/ide/ada_language_server!1884
2 parents e50444e + dee2a5a commit 3c63564

File tree

1 file changed

+53
-24
lines changed

1 file changed

+53
-24
lines changed

integration/vscode/ada/src/gnattest.ts

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -514,9 +514,15 @@ async function handleRunRequestedTests(request: vscode.TestRunRequest, token?: C
514514
/**
515515
* Collect and filter tests to run.
516516
*/
517-
const requestedLeafTests = requestedRootTests.flatMap((i) => collectLeafItems(i, token));
517+
const requestedLeafTests = (
518+
await Promise.all(requestedRootTests.map(async (i) => await collectLeafItems(i, token)))
519+
).flat();
518520
const excludedLeafTests = request.exclude
519-
? request.exclude.flatMap((i) => collectLeafItems(i, token))
521+
? (
522+
await Promise.all(
523+
request.exclude.map(async (i) => await collectLeafItems(i, token)),
524+
)
525+
).flat()
520526
: [];
521527
const testsToRun = requestedLeafTests.filter((t) => {
522528
if (token?.isCancellationRequested) {
@@ -614,7 +620,7 @@ async function handleRunAll(request: vscode.TestRunRequest, token?: Cancellation
614620
/**
615621
* Collect all tests, i.e. all leafs of the TestItem tree.
616622
*/
617-
const allTests: TestItem[] = collectLeafsFromCollection(controller.items, token);
623+
const allTests: TestItem[] = await collectLeafsFromCollection(controller.items, token);
618624

619625
/**
620626
* Mark tests as queued
@@ -630,17 +636,6 @@ async function handleRunAll(request: vscode.TestRunRequest, token?: Cancellation
630636
throw new vscode.CancellationError();
631637
}
632638

633-
/**
634-
* Resolve all the test tree before collecting tests
635-
*/
636-
const promises: Promise<void>[] = [];
637-
controller.items.forEach((i) => promises.push(resolveHandler(i, true, token)));
638-
await Promise.all(promises);
639-
640-
if (token?.isCancellationRequested) {
641-
throw new vscode.CancellationError();
642-
}
643-
644639
/**
645640
* Mark all tests as started.
646641
*/
@@ -810,37 +805,71 @@ export function determineTestOutcome(
810805
*
811806
* @param items - a {@link vscode.TestItemCollection}
812807
* @param token - a cancellation token to stop the traversal
808+
* @param resolve - whether to resolve items that can have children or process
809+
* them as they are
813810
* @returns the array of leaf TestItems reachable from the given collection.
814811
*/
815-
export function collectLeafsFromCollection(
812+
export async function collectLeafsFromCollection(
816813
items: vscode.TestItemCollection,
817814
token?: CancellationToken,
818-
): vscode.TestItem[] {
815+
resolve: boolean = true,
816+
): Promise<vscode.TestItem[]> {
819817
const res: vscode.TestItem[] = [];
820-
items.forEach((i) => {
818+
819+
/**
820+
* items.forEach() wouldn't work here because each iteration produces a
821+
* promise that we can't await. Ideally we could have used
822+
* Promise.all(items.map(...)) but the TestItemCollection type doesn't
823+
* offer a map method. So instead we use a regular for-loop and await in
824+
* each iteration.
825+
*/
826+
for (const [, item] of items) {
821827
if (token?.isCancellationRequested) {
822828
throw new vscode.CancellationError();
823829
}
824-
res.push(...collectLeafItems(i, token));
825-
});
830+
res.push(...(await collectLeafItems(item, token, resolve)));
831+
}
826832
return res;
827833
}
828834

829835
/**
830836
*
831-
* @param item - a {@link vscode.TestItem}
837+
* @param item - a {@link TestItem}
832838
* @param token - a cancellation token to stop the traversal
839+
* @param resolve - whether to resolve items that can have children or process
840+
* them as they are
833841
* @returns the array of leaf TestItems reachable from the given TestItem
834842
*/
835-
export function collectLeafItems(item: TestItem, token?: CancellationToken): vscode.TestItem[] {
843+
export async function collectLeafItems(
844+
item: TestItem,
845+
token?: CancellationToken,
846+
resolve: boolean = true,
847+
): Promise<vscode.TestItem[]> {
848+
/**
849+
* If the TestItem has never been expanded in the UI, its children may have
850+
* not been populated yet. Force a resolve operation to load the children.
851+
*/
852+
if (resolve && item.canResolveChildren && controller.resolveHandler) {
853+
await controller.resolveHandler(item);
854+
}
855+
836856
if (item.children.size > 0) {
837857
const res: vscode.TestItem[] = [];
838-
item.children.forEach((i) => {
858+
859+
/**
860+
* items.forEach() wouldn't work here because each iteration produces a
861+
* promise that we can't await. Ideally we could have used
862+
* Promise.all(items.map(...)) but the TestItemCollection type doesn't
863+
* offer a map method. So instead we use a regular for-loop and await in
864+
* each iteration.
865+
*/
866+
for (const [, i] of item.children) {
839867
if (token?.isCancellationRequested) {
840868
throw new vscode.CancellationError();
841869
}
842-
res.push(...collectLeafItems(i, token));
843-
});
870+
res.push(...(await collectLeafItems(i, token, resolve)));
871+
}
872+
844873
return res;
845874
} else {
846875
return [item];

0 commit comments

Comments
 (0)