Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support list package at client side #1241

Merged
merged 1 commit into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public Set<IType> findTestItemsInContainer(IJavaElement element, IProgressMonito
} catch (OperationCanceledException e) {
return Collections.emptySet();
}

return types;
}
}
7 changes: 7 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,10 @@ export namespace ExtensionName {
export namespace Context {
export const ACTIVATION_CONTEXT_KEY: string = 'java:testRunnerActivated';
}

/**
* This is the prefix of the invocation test item's id.
* Invocation test items are created during test run.
* For example, the invocations from a parameterized test.
*/
export const INVOCATION_PREFIX: string = '[__INVOCATION__]-';
23 changes: 19 additions & 4 deletions src/controller/testController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

import * as _ from 'lodash';
import { CancellationToken, TestController, TestItem, tests } from 'vscode';
import { instrumentOperation } from 'vscode-extension-telemetry-wrapper';
import { isStandardServerReady } from '../extension';
import { loadJavaProjects } from './utils';
import { IJavaTestItem, TestLevel } from '../types';
import { dataCache, ITestItemData } from './testItemDataCache';
import { findTestPackagesAndTypes, loadJavaProjects, synchronizeItemsRecursively } from './utils';

export let testController: TestController | undefined;

Expand All @@ -20,10 +23,22 @@ export function createTestController(): void {
};
}

export async function loadChildren(item: TestItem, token?: CancellationToken): Promise<void> {
export const loadChildren: (item: TestItem, token?: CancellationToken) => any = instrumentOperation('java.test.explorer.loadChildren', async (_operationId: string, item: TestItem, token?: CancellationToken) => {
if (!item) {
await loadJavaProjects();
return;
}
// todo: load other items
}

const data: ITestItemData | undefined = dataCache.get(item);
if (!data) {
return;
}
if (data.testLevel === TestLevel.Project) {
const packageAndTypes: IJavaTestItem[] = await findTestPackagesAndTypes(data.jdtHandler, token);
synchronizeItemsRecursively(item, packageAndTypes);
} else if (data.testLevel === TestLevel.Package) {
// unreachable code
} else if (data.testLevel === TestLevel.Class) {
// todo
}
});
59 changes: 58 additions & 1 deletion src/controller/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

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

/**
* This method is used to synchronize the test items for the given parent node recursively. which means:
* - If an existing child is not contained in the childrenData parameter, it will be deleted
* - If a child does not exist, create it, otherwise, update it as well as its metadata.
*/
export function synchronizeItemsRecursively(parent: TestItem, childrenData: IJavaTestItem[] | undefined): void {
if (childrenData) {
// remove the out-of-date children
parent.children.forEach((child: TestItem) => {
if (child.id.startsWith(INVOCATION_PREFIX)) {
// only remove the invocation items before a new test session starts
return;
}
const existingItem: IJavaTestItem | undefined = childrenData.find((data: IJavaTestItem) => data.id === child.id);
if (!existingItem) {
parent.children.delete(child.id);
}
});
// update/create children
for (const child of childrenData) {
const childItem: TestItem = updateOrCreateTestItem(parent, child);
if (child.testLevel <= TestLevel.Class) {
childItem.canResolveChildren = true;
}
synchronizeItemsRecursively(childItem, child.children);
}
}
}

function updateOrCreateTestItem(parent: TestItem, childData: IJavaTestItem): TestItem {
let childItem: TestItem | undefined = parent.children.get(childData.id);
if (childItem) {
updateTestItem(childItem, childData);
} else {
childItem = createTestItem(childData, parent);
}
return childItem;
}

function updateTestItem(testItem: TestItem, metaInfo: IJavaTestItem): void {
testItem.range = asRange(metaInfo.range);
if (metaInfo.testLevel !== TestLevel.Invocation) {
dataCache.set(testItem, {
jdtHandler: metaInfo.jdtHandler,
fullName: metaInfo.fullName,
projectName: metaInfo.projectName,
testLevel: metaInfo.testLevel,
testKind: metaInfo.testKind,
});
}
}

/**
* Create test item which will be shown in the test explorer
* @param metaInfo The data from the server side of the test item
Expand Down Expand Up @@ -72,3 +124,8 @@ export async function getJavaProjects(workspaceFolder: WorkspaceFolder, token?:
return await executeJavaLanguageServerCommand<IJavaTestItem[]>(
JavaTestRunnerDelegateCommands.FIND_JAVA_PROJECTS, workspaceFolder.uri.toString(), token) || [];
}

export async function findTestPackagesAndTypes(handlerId: string, token?: CancellationToken): Promise<IJavaTestItem[]> {
return await executeJavaLanguageServerCommand<IJavaTestItem[]>(
JavaTestRunnerDelegateCommands.FIND_TEST_PACKAGES_AND_TYPES, handlerId, token) || [];
}