diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b9aaff50911..ec1898d0851 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -171,7 +171,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostWebviewPanels = rpcProtocol.set(ExtHostContext.ExtHostWebviewPanels, new ExtHostWebviewPanels(rpcProtocol, extHostWebviews, extHostWorkspace)); const extHostCustomEditors = rpcProtocol.set(ExtHostContext.ExtHostCustomEditors, new ExtHostCustomEditors(rpcProtocol, extHostDocuments, extensionStoragePaths, extHostWebviews, extHostWebviewPanels)); const extHostWebviewViews = rpcProtocol.set(ExtHostContext.ExtHostWebviewViews, new ExtHostWebviewViews(rpcProtocol, extHostWebviews)); - const extHostTesting = rpcProtocol.set(ExtHostContext.ExtHostTesting, new ExtHostTesting(rpcProtocol)); + const extHostTesting = rpcProtocol.set(ExtHostContext.ExtHostTesting, new ExtHostTesting(rpcProtocol, extHostCommands)); const extHostUriOpeners = rpcProtocol.set(ExtHostContext.ExtHostUriOpeners, new ExtHostUriOpeners(rpcProtocol)); // Check that no named customers are missing diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts index 3244e884554..79ff7e37808 100644 --- a/src/vs/workbench/api/common/extHostTesting.ts +++ b/src/vs/workbench/api/common/extHostTesting.ts @@ -11,10 +11,12 @@ import { Emitter, Event } from 'vs/base/common/event'; import { once } from 'vs/base/common/functional'; import { Iterable } from 'vs/base/common/iterator'; import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; +import { MarshalledId } from 'vs/base/common/marshalling'; import { deepFreeze } from 'vs/base/common/objects'; import { isDefined } from 'vs/base/common/types'; import { generateUuid } from 'vs/base/common/uuid'; import { ExtHostTestingShape, MainContext, MainThreadTestingShape } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import * as Convert from 'vs/workbench/api/common/extHostTypeConverters'; import { TestItemImpl } from 'vs/workbench/api/common/extHostTypes'; @@ -35,10 +37,15 @@ export class ExtHostTesting implements ExtHostTestingShape { public onResultsChanged = this.resultsChangedEmitter.event; public results: ReadonlyArray = []; - constructor(@IExtHostRpcService rpc: IExtHostRpcService) { + constructor(@IExtHostRpcService rpc: IExtHostRpcService, commands: ExtHostCommands) { this.proxy = rpc.getProxy(MainContext.MainThreadTesting); this.observer = new TestObservers(this.proxy); this.runTracker = new TestRunCoordinator(this.proxy); + + commands.registerArgumentProcessor({ + processArgument: arg => + arg?.$mid === MarshalledId.TestItemContext ? Convert.TestItem.toItemFromContext(arg) : arg, + }); } /** diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 62ed8915ab7..77859120957 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -30,7 +30,7 @@ import { EditorGroupColumn, SaveReason } from 'vs/workbench/common/editor'; import * as notebooks from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import * as search from 'vs/workbench/contrib/search/common/search'; -import { ISerializedTestResults, ITestItem, ITestMessage, SerializedTestResultItem } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ISerializedTestResults, ITestItem, ITestItemContext, ITestMessage, SerializedTestResultItem } from 'vs/workbench/contrib/testing/common/testCollection'; import { ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import type * as vscode from 'vscode'; import * as types from './extHostTypes'; @@ -1677,14 +1677,23 @@ export namespace TestItem { }; } - export function to(item: ITestItem): types.TestItemImpl { - const testItem = new types.TestItemImpl(item.extId, item.label, URI.revive(item.uri), undefined, undefined); + export function to(item: ITestItem, parent?: vscode.TestItem): types.TestItemImpl { + const testItem = new types.TestItemImpl(item.extId, item.label, URI.revive(item.uri), undefined, parent); testItem.range = Range.to(item.range || undefined); testItem.debuggable = item.debuggable; testItem.description = item.description || undefined; testItem.runnable = item.runnable; return testItem; } + + export function toItemFromContext(context: ITestItemContext): types.TestItemImpl { + let node: types.TestItemImpl | undefined; + for (const test of context.tests) { + node = to(test.item, node); + } + + return node!; + } } export namespace TestResults { diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts index c7e62c52e97..5136d861d79 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts @@ -9,8 +9,9 @@ import { FuzzyScore } from 'vs/base/common/filters'; import { IMarkdownString } from 'vs/base/common/htmlContent'; import { Iterable } from 'vs/base/common/iterator'; import { IDisposable } from 'vs/base/common/lifecycle'; +import { MarshalledId } from 'vs/base/common/marshalling'; import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; -import { identifyTest, InternalTestItem, ITestIdWithSrc } from 'vs/workbench/contrib/testing/common/testCollection'; +import { identifyTest, InternalTestItem, ITestIdWithSrc, ITestItemContext } from 'vs/workbench/contrib/testing/common/testCollection'; /** * Describes a rendering of tests in the explorer view. Different @@ -170,6 +171,19 @@ export class TestItemTreeElement implements IActionableTestTreeElement { public readonly test: InternalTestItem, public readonly parent: TestItemTreeElement | null = null, ) { } + + public toJSON() { + const context: ITestItemContext = { + $mid: MarshalledId.TestItemContext, + tests: [this.test], + }; + + for (let p = this.parent; p; p = p.parent) { + context.tests.unshift(p.test); + } + + return context; + } } export class TestTreeErrorMessage { diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index 93122602561..3b431ca4064 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -61,7 +61,7 @@ import { cmpPriority, isFailedState, isStateWithResult } from 'vs/workbench/cont import { getPathForTestInResult, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { ITestService, testCollectionIsEmpty } from 'vs/workbench/contrib/testing/common/testService'; -import { GoToTest, internalTestActionIds } from './testExplorerActions'; +import { GoToTest } from './testExplorerActions'; export class TestingExplorerView extends ViewPane { public viewModel!: TestingExplorerViewModel; @@ -770,13 +770,7 @@ class TestExplorerActionRunner extends ActionRunner { const contextIsSelected = selection.some(s => s === context); const actualContext = contextIsSelected ? selection : [context]; const actionable = actualContext.filter((t): t is TestItemTreeElement => t instanceof TestItemTreeElement); - - // Is there a better way to do this? - if (internalTestActionIds.has(action.id)) { - await action.run(...actionable); - } else { - await action.run(...actionable.map(a => a.test.item.extId)); - } + await action.run(...actionable); } } diff --git a/src/vs/workbench/contrib/testing/common/testCollection.ts b/src/vs/workbench/contrib/testing/common/testCollection.ts index b3d0481425c..e3bdb3e55c3 100644 --- a/src/vs/workbench/contrib/testing/common/testCollection.ts +++ b/src/vs/workbench/contrib/testing/common/testCollection.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { MarshalledId } from 'vs/base/common/marshalling'; import { URI } from 'vs/base/common/uri'; import { IRange, Range } from 'vs/editor/common/core/range'; import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; @@ -200,10 +201,14 @@ export type TestsDiffOp = | [op: TestDiffOpType.IncrementPendingExtHosts, amount: number]; /** - * Utility function to get a unique string for a subscription to a resource, - * useful to keep maps of document or workspace folder subscription info. + * Context for actions taken in the test explorer view. */ -export const getTestSubscriptionKey = (resource: ExtHostTestingResource, uri: URI) => `${resource}:${uri.toString()}`; +export interface ITestItemContext { + /** Marshalling marker */ + $mid: MarshalledId.TestItemContext; + /** Tests and parents from the root to the current items */ + tests: InternalTestItem[]; +} /** * Request from the ext host or main thread to indicate that tests have