Skip to content

Commit 53515e0

Browse files
authored
Support list package at client side (#1241)
1 parent eb1c3c5 commit 53515e0

File tree

4 files changed

+85
-6
lines changed

4 files changed

+85
-6
lines changed

java-extension/com.microsoft.java.test.plugin/src/main/java/com/microsoft/java/test/plugin/searcher/JUnit4TestSearcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public Set<IType> findTestItemsInContainer(IJavaElement element, IProgressMonito
7474
} catch (OperationCanceledException e) {
7575
return Collections.emptySet();
7676
}
77-
77+
7878
return types;
7979
}
8080
}

src/constants.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,10 @@ export namespace ExtensionName {
5454
export namespace Context {
5555
export const ACTIVATION_CONTEXT_KEY: string = 'java:testRunnerActivated';
5656
}
57+
58+
/**
59+
* This is the prefix of the invocation test item's id.
60+
* Invocation test items are created during test run.
61+
* For example, the invocations from a parameterized test.
62+
*/
63+
export const INVOCATION_PREFIX: string = '[__INVOCATION__]-';

src/controller/testController.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33

44
import * as _ from 'lodash';
55
import { CancellationToken, TestController, TestItem, tests } from 'vscode';
6+
import { instrumentOperation } from 'vscode-extension-telemetry-wrapper';
67
import { isStandardServerReady } from '../extension';
7-
import { loadJavaProjects } from './utils';
8+
import { IJavaTestItem, TestLevel } from '../types';
9+
import { dataCache, ITestItemData } from './testItemDataCache';
10+
import { findTestPackagesAndTypes, loadJavaProjects, synchronizeItemsRecursively } from './utils';
811

912
export let testController: TestController | undefined;
1013

@@ -20,10 +23,22 @@ export function createTestController(): void {
2023
};
2124
}
2225

23-
export async function loadChildren(item: TestItem, token?: CancellationToken): Promise<void> {
26+
export const loadChildren: (item: TestItem, token?: CancellationToken) => any = instrumentOperation('java.test.explorer.loadChildren', async (_operationId: string, item: TestItem, token?: CancellationToken) => {
2427
if (!item) {
2528
await loadJavaProjects();
2629
return;
2730
}
28-
// todo: load other items
29-
}
31+
32+
const data: ITestItemData | undefined = dataCache.get(item);
33+
if (!data) {
34+
return;
35+
}
36+
if (data.testLevel === TestLevel.Project) {
37+
const packageAndTypes: IJavaTestItem[] = await findTestPackagesAndTypes(data.jdtHandler, token);
38+
synchronizeItemsRecursively(item, packageAndTypes);
39+
} else if (data.testLevel === TestLevel.Package) {
40+
// unreachable code
41+
} else if (data.testLevel === TestLevel.Class) {
42+
// todo
43+
}
44+
});

src/controller/utils.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import * as _ from 'lodash';
55
import { CancellationToken, Range, TestItem, Uri, workspace, WorkspaceFolder } from 'vscode';
6-
import { JavaTestRunnerDelegateCommands } from '../constants';
6+
import { INVOCATION_PREFIX, JavaTestRunnerDelegateCommands } from '../constants';
77
import { IJavaTestItem, TestLevel } from '../types';
88
import { executeJavaLanguageServerCommand } from '../utils/commandUtils';
99
import { testController } from './testController';
@@ -26,6 +26,58 @@ export async function loadJavaProjects(): Promise<void> {
2626
}
2727
}
2828

29+
/**
30+
* This method is used to synchronize the test items for the given parent node recursively. which means:
31+
* - If an existing child is not contained in the childrenData parameter, it will be deleted
32+
* - If a child does not exist, create it, otherwise, update it as well as its metadata.
33+
*/
34+
export function synchronizeItemsRecursively(parent: TestItem, childrenData: IJavaTestItem[] | undefined): void {
35+
if (childrenData) {
36+
// remove the out-of-date children
37+
parent.children.forEach((child: TestItem) => {
38+
if (child.id.startsWith(INVOCATION_PREFIX)) {
39+
// only remove the invocation items before a new test session starts
40+
return;
41+
}
42+
const existingItem: IJavaTestItem | undefined = childrenData.find((data: IJavaTestItem) => data.id === child.id);
43+
if (!existingItem) {
44+
parent.children.delete(child.id);
45+
}
46+
});
47+
// update/create children
48+
for (const child of childrenData) {
49+
const childItem: TestItem = updateOrCreateTestItem(parent, child);
50+
if (child.testLevel <= TestLevel.Class) {
51+
childItem.canResolveChildren = true;
52+
}
53+
synchronizeItemsRecursively(childItem, child.children);
54+
}
55+
}
56+
}
57+
58+
function updateOrCreateTestItem(parent: TestItem, childData: IJavaTestItem): TestItem {
59+
let childItem: TestItem | undefined = parent.children.get(childData.id);
60+
if (childItem) {
61+
updateTestItem(childItem, childData);
62+
} else {
63+
childItem = createTestItem(childData, parent);
64+
}
65+
return childItem;
66+
}
67+
68+
function updateTestItem(testItem: TestItem, metaInfo: IJavaTestItem): void {
69+
testItem.range = asRange(metaInfo.range);
70+
if (metaInfo.testLevel !== TestLevel.Invocation) {
71+
dataCache.set(testItem, {
72+
jdtHandler: metaInfo.jdtHandler,
73+
fullName: metaInfo.fullName,
74+
projectName: metaInfo.projectName,
75+
testLevel: metaInfo.testLevel,
76+
testKind: metaInfo.testKind,
77+
});
78+
}
79+
}
80+
2981
/**
3082
* Create test item which will be shown in the test explorer
3183
* @param metaInfo The data from the server side of the test item
@@ -72,3 +124,8 @@ export async function getJavaProjects(workspaceFolder: WorkspaceFolder, token?:
72124
return await executeJavaLanguageServerCommand<IJavaTestItem[]>(
73125
JavaTestRunnerDelegateCommands.FIND_JAVA_PROJECTS, workspaceFolder.uri.toString(), token) || [];
74126
}
127+
128+
export async function findTestPackagesAndTypes(handlerId: string, token?: CancellationToken): Promise<IJavaTestItem[]> {
129+
return await executeJavaLanguageServerCommand<IJavaTestItem[]>(
130+
JavaTestRunnerDelegateCommands.FIND_TEST_PACKAGES_AND_TYPES, handlerId, token) || [];
131+
}

0 commit comments

Comments
 (0)