parent
8bf9cfa21b
commit
99104943f5
8 changed files with 307 additions and 107 deletions
|
@ -6,6 +6,7 @@
|
|||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellExecutionUpdateType, ICellExecuteUpdate } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
|
||||
export namespace NotebookDto {
|
||||
|
||||
|
@ -91,23 +92,25 @@ export namespace NotebookDto {
|
|||
};
|
||||
}
|
||||
|
||||
export function fromCellExecuteEditDto(data: extHostProtocol.CellExecuteEditDto): notebookCommon.IImmediateCellEditOperation {
|
||||
if (data.editType === notebookCommon.CellEditType.PartialInternalMetadata) {
|
||||
return data;
|
||||
} else if (data.editType === notebookCommon.CellEditType.Output) {
|
||||
export function fromCellExecuteUpdateDto(data: extHostProtocol.ICellExecuteUpdateDto): ICellExecuteUpdate {
|
||||
if (data.editType === CellExecutionUpdateType.Output) {
|
||||
return {
|
||||
editType: data.editType,
|
||||
handle: data.handle,
|
||||
executionHandle: data.executionHandle,
|
||||
cellHandle: data.cellHandle,
|
||||
append: data.append,
|
||||
outputs: data.outputs.map(fromNotebookOutputDto)
|
||||
};
|
||||
} else {
|
||||
} else if (data.editType === CellExecutionUpdateType.OutputItems) {
|
||||
return {
|
||||
editType: data.editType,
|
||||
executionHandle: data.executionHandle,
|
||||
append: data.append,
|
||||
outputId: data.outputId,
|
||||
items: data.items.map(fromNotebookOutputItemDto)
|
||||
};
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { flatten, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { flatten, groupBy, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { combinedDisposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
@ -14,9 +14,9 @@ import { NotebookDto } from 'vs/workbench/api/browser/mainThreadNotebookDto';
|
|||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService';
|
||||
import { ICellExecuteUpdate, INotebookCellExecution, INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
import { INotebookKernel, INotebookKernelChangeEvent, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { CellExecuteEditDto, ExtHostContext, ExtHostNotebookKernelsShape, IExtHostContext, INotebookKernelDto2, MainContext, MainThreadNotebookKernelsShape } from '../common/extHost.protocol';
|
||||
import { ICellExecuteUpdateDto, ExtHostContext, ExtHostNotebookKernelsShape, IExtHostContext, INotebookKernelDto2, MainContext, MainThreadNotebookKernelsShape } from '../common/extHost.protocol';
|
||||
|
||||
abstract class MainThreadKernel implements INotebookKernel {
|
||||
|
||||
|
@ -99,11 +99,14 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
|||
private readonly _kernels = new Map<number, [kernel: MainThreadKernel, registraion: IDisposable]>();
|
||||
private readonly _proxy: ExtHostNotebookKernelsShape;
|
||||
|
||||
private readonly _executions = new Map<number, MainThreadExecution>();
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IModeService private readonly _modeService: IModeService,
|
||||
@INotebookKernelService private readonly _notebookKernelService: INotebookKernelService,
|
||||
@INotebookService private readonly _notebookService: INotebookService,
|
||||
@INotebookExecutionService private readonly _notebookExecutionService: INotebookExecutionService,
|
||||
// @INotebookService private readonly _notebookService: INotebookService,
|
||||
@INotebookEditorService notebookEditorService: INotebookEditorService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebookKernels);
|
||||
|
@ -223,22 +226,43 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
|||
}
|
||||
}
|
||||
|
||||
// --- execution editss
|
||||
// --- execution
|
||||
|
||||
async $applyExecutionEdits(resource: UriComponents, cellEdits: CellExecuteEditDto[]): Promise<void> {
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
|
||||
if (!textModel) {
|
||||
throw new Error(`Can't apply edits to unknown notebook model: ${URI.revive(resource).toString()}`);
|
||||
$addExecution(handle: number, uri: UriComponents, cellHandle: number): void {
|
||||
const execution = new MainThreadExecution(handle, URI.revive(uri), cellHandle);
|
||||
this._executions.set(handle, execution);
|
||||
this._notebookExecutionService.registerNotebookCellExecution(execution);
|
||||
}
|
||||
|
||||
const edits = cellEdits.map(NotebookDto.fromCellExecuteEditDto);
|
||||
$updateExecutions(updates: ICellExecuteUpdateDto[]): void {
|
||||
const groupedUpdates = groupBy(updates, (a, b) => a.executionHandle - b.executionHandle);
|
||||
groupedUpdates.forEach(datas => {
|
||||
const first = datas[0];
|
||||
const execution = this._executions.get(first.executionHandle);
|
||||
if (!execution) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
textModel.applyEdits(edits, true, undefined, () => undefined, undefined, false);
|
||||
execution.update(datas.map(NotebookDto.fromCellExecuteUpdateDto));
|
||||
} catch (e) {
|
||||
// Clearing outputs at the same time as the EH calling append/replaceOutputItems is an expected race, and it should be a no-op.
|
||||
// And any other failure should not throw back to the extension.
|
||||
onUnexpectedError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class MainThreadExecution implements INotebookCellExecution {
|
||||
private readonly _onDidChange = new Emitter<ICellExecuteUpdate[]>();
|
||||
readonly onDidChange: Event<Readonly<ICellExecuteUpdate[]>> = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
readonly id: number,
|
||||
readonly notebook: URI,
|
||||
readonly cellHandle: number,
|
||||
) { }
|
||||
|
||||
update(updates: ICellExecuteUpdate[]): void {
|
||||
this._onDidChange.fire(updates);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views';
|
|||
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { IAdapterDescriptor, IConfig, IDebugSessionReplMode } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellExecutionUpdateType, ICellExecutionComplete, ICellExecutionStateUpdate } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { InputValidationType } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
|
@ -909,21 +910,23 @@ export interface INotebookKernelDto2 {
|
|||
preloads?: { uri: UriComponents; provides: string[] }[];
|
||||
}
|
||||
|
||||
export interface CellExecuteOutputEditDto {
|
||||
editType: notebookCommon.CellEditType.Output;
|
||||
export interface ICellExecuteOutputEditDto {
|
||||
editType: CellExecutionUpdateType.Output;
|
||||
executionHandle: number;
|
||||
cellHandle: number;
|
||||
append?: boolean;
|
||||
handle: number;
|
||||
outputs: NotebookOutputDto[]
|
||||
}
|
||||
|
||||
export interface CellExecuteOutputItemEditDto {
|
||||
editType: notebookCommon.CellEditType.OutputItems;
|
||||
export interface ICellExecuteOutputItemEditDto {
|
||||
editType: CellExecutionUpdateType.OutputItems;
|
||||
executionHandle: number;
|
||||
append?: boolean;
|
||||
outputId: string;
|
||||
items: NotebookOutputItemDto[]
|
||||
}
|
||||
|
||||
export type CellExecuteEditDto = CellExecuteOutputEditDto | CellExecuteOutputItemEditDto | notebookCommon.ICellPartialInternalMetadataEditByHandle;
|
||||
export type ICellExecuteUpdateDto = ICellExecuteOutputEditDto | ICellExecuteOutputItemEditDto | ICellExecutionStateUpdate | ICellExecutionComplete;
|
||||
|
||||
export interface MainThreadNotebookKernelsShape extends IDisposable {
|
||||
$postMessage(handle: number, editorId: string | undefined, message: any): Promise<boolean>;
|
||||
|
@ -932,7 +935,8 @@ export interface MainThreadNotebookKernelsShape extends IDisposable {
|
|||
$removeKernel(handle: number): void;
|
||||
$updateNotebookPriority(handle: number, uri: UriComponents, value: number | undefined): void;
|
||||
|
||||
$applyExecutionEdits(resource: UriComponents, edits: CellExecuteEditDto[]): Promise<void>;
|
||||
$addExecution(handle: number, uri: UriComponents, cellHandle: number): void;
|
||||
$updateExecutions(data: ICellExecuteUpdateDto[]): void;
|
||||
}
|
||||
|
||||
export interface MainThreadNotebookRenderersShape extends IDisposable {
|
||||
|
|
|
@ -3,25 +3,25 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { CellExecuteEditDto, ExtHostNotebookKernelsShape, IMainContext, INotebookKernelDto2, MainContext, MainThreadNotebookKernelsShape, NotebookOutputDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { asWebviewUri } from 'vs/workbench/api/common/shared/webview';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { ExtHostCell, ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
|
||||
import { CellEditType, NotebookCellExecutionState, NullablePartialNotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ICellExecuteUpdateDto, ExtHostNotebookKernelsShape, IMainContext, INotebookKernelDto2, MainContext, MainThreadNotebookKernelsShape, NotebookOutputDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostCell, ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { NotebookCellOutput } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { asWebviewUri } from 'vs/workbench/api/common/shared/webview';
|
||||
import { CellExecutionUpdateType } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
interface IKernelData {
|
||||
extensionId: ExtensionIdentifier,
|
||||
|
@ -324,6 +324,9 @@ enum NotebookCellExecutionTaskState {
|
|||
}
|
||||
|
||||
class NotebookCellExecutionTask extends Disposable {
|
||||
private static HANDLE = 0;
|
||||
private _handle = NotebookCellExecutionTask.HANDLE++;
|
||||
|
||||
private _onDidChangeState = new Emitter<void>();
|
||||
readonly onDidChangeState = this._onDidChangeState.event;
|
||||
|
||||
|
@ -332,7 +335,7 @@ class NotebookCellExecutionTask extends Disposable {
|
|||
|
||||
private readonly _tokenSource = this._register(new CancellationTokenSource());
|
||||
|
||||
private readonly _collector: TimeoutBasedCollector<CellExecuteEditDto>;
|
||||
private readonly _collector: TimeoutBasedCollector<ICellExecuteUpdateDto>;
|
||||
|
||||
private _executionOrder: number | undefined;
|
||||
|
||||
|
@ -343,25 +346,23 @@ class NotebookCellExecutionTask extends Disposable {
|
|||
) {
|
||||
super();
|
||||
|
||||
this._collector = new TimeoutBasedCollector(10, edits => this.applyEdits(edits));
|
||||
this._collector = new TimeoutBasedCollector(10, updates => this.update(updates));
|
||||
|
||||
this._executionOrder = _cell.internalMetadata.executionOrder;
|
||||
this.mixinMetadata({
|
||||
runState: NotebookCellExecutionState.Pending,
|
||||
executionOrder: null
|
||||
});
|
||||
this._proxy.$addExecution(this._handle, this._cell.notebook.uri, this._cell.handle);
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
this._tokenSource.cancel();
|
||||
}
|
||||
|
||||
private async applyEditSoon(edit: CellExecuteEditDto): Promise<void> {
|
||||
await this._collector.addItem(edit);
|
||||
private async updateSoon(update: ICellExecuteUpdateDto): Promise<void> {
|
||||
await this._collector.addItem(update);
|
||||
}
|
||||
|
||||
private async applyEdits(edits: CellExecuteEditDto[]): Promise<void> {
|
||||
return this._proxy.$applyExecutionEdits(this._document.uri, edits);
|
||||
private async update(update: ICellExecuteUpdateDto | ICellExecuteUpdateDto[]): Promise<void> {
|
||||
const updates = Array.isArray(update) ? update : [update];
|
||||
return this._proxy.$updateExecutions(updates);
|
||||
}
|
||||
|
||||
private verifyStateForOutput() {
|
||||
|
@ -374,14 +375,6 @@ class NotebookCellExecutionTask extends Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
private mixinMetadata(mixinMetadata: NullablePartialNotebookCellInternalMetadata) {
|
||||
this.applyEdits([{
|
||||
editType: CellEditType.PartialInternalMetadata,
|
||||
handle: this._cell.handle,
|
||||
internalMetadata: mixinMetadata
|
||||
}]);
|
||||
}
|
||||
|
||||
private cellIndexToHandle(cellOrCellIndex: vscode.NotebookCell | undefined): number {
|
||||
let cell: ExtHostCell | undefined = this._cell;
|
||||
if (cellOrCellIndex) {
|
||||
|
@ -410,12 +403,25 @@ class NotebookCellExecutionTask extends Disposable {
|
|||
private async updateOutputs(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell: vscode.NotebookCell | undefined, append: boolean): Promise<void> {
|
||||
const handle = this.cellIndexToHandle(cell);
|
||||
const outputDtos = this.validateAndConvertOutputs(asArray(outputs));
|
||||
return this.applyEditSoon({ editType: CellEditType.Output, handle, append, outputs: outputDtos });
|
||||
return this.updateSoon(
|
||||
{
|
||||
editType: CellExecutionUpdateType.Output,
|
||||
executionHandle: this._handle,
|
||||
cellHandle: handle,
|
||||
append,
|
||||
outputs: outputDtos
|
||||
});
|
||||
}
|
||||
|
||||
private async updateOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput, append: boolean): Promise<void> {
|
||||
items = NotebookCellOutput.ensureUniqueMimeTypes(asArray(items), true);
|
||||
return this.applyEditSoon({ editType: CellEditType.OutputItems, items: items.map(extHostTypeConverters.NotebookCellOutputItem.from), outputId: output.id, append });
|
||||
return this.updateSoon({
|
||||
editType: CellExecutionUpdateType.OutputItems,
|
||||
executionHandle: this._handle,
|
||||
items: items.map(extHostTypeConverters.NotebookCellOutputItem.from),
|
||||
outputId: output.id,
|
||||
append
|
||||
});
|
||||
}
|
||||
|
||||
asApiObject(): vscode.NotebookCellExecution {
|
||||
|
@ -426,9 +432,11 @@ class NotebookCellExecutionTask extends Disposable {
|
|||
get executionOrder() { return that._executionOrder; },
|
||||
set executionOrder(v: number | undefined) {
|
||||
that._executionOrder = v;
|
||||
that.mixinMetadata({
|
||||
executionOrder: v
|
||||
});
|
||||
that.update([{
|
||||
editType: CellExecutionUpdateType.ExecutionState,
|
||||
executionHandle: that._handle,
|
||||
executionOrder: that._executionOrder
|
||||
}]);
|
||||
},
|
||||
|
||||
start(startTime?: number): void {
|
||||
|
@ -439,9 +447,10 @@ class NotebookCellExecutionTask extends Disposable {
|
|||
that._state = NotebookCellExecutionTaskState.Started;
|
||||
that._onDidChangeState.fire();
|
||||
|
||||
that.mixinMetadata({
|
||||
runState: NotebookCellExecutionState.Executing,
|
||||
runStartTime: startTime ?? null
|
||||
that.update({
|
||||
editType: CellExecutionUpdateType.ExecutionState,
|
||||
executionHandle: that._handle,
|
||||
runStartTime: startTime
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -453,10 +462,11 @@ class NotebookCellExecutionTask extends Disposable {
|
|||
that._state = NotebookCellExecutionTaskState.Resolved;
|
||||
that._onDidChangeState.fire();
|
||||
|
||||
that.mixinMetadata({
|
||||
runState: null,
|
||||
lastRunSuccess: success ?? null,
|
||||
runEndTime: endTime ?? null,
|
||||
that.updateSoon({
|
||||
editType: CellExecutionUpdateType.Complete,
|
||||
executionHandle: that._handle,
|
||||
runEndTime: endTime,
|
||||
lastRunSuccess: success
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -495,7 +505,7 @@ class TimeoutBasedCollector<T> {
|
|||
|
||||
constructor(
|
||||
private readonly delay: number,
|
||||
private readonly callback: (items: T[]) => Promise<void>) { }
|
||||
private readonly callback: (items: T[]) => Promise<void> | void) { }
|
||||
|
||||
addItem(item: T): Promise<void> {
|
||||
this.batch.push(item);
|
||||
|
|
|
@ -89,6 +89,8 @@ import 'vs/workbench/contrib/notebook/browser/diff/notebookDiffActions';
|
|||
// Output renderers registration
|
||||
import 'vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform';
|
||||
import { editorOptionsRegistry } from 'vs/editor/common/config/editorOptions';
|
||||
import { NotebookExecutionService } from 'vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl';
|
||||
import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
|
||||
/*--------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -603,6 +605,7 @@ registerSingleton(INotebookEditorModelResolverService, NotebookModelResolverServ
|
|||
registerSingleton(INotebookCellStatusBarService, NotebookCellStatusBarService, true);
|
||||
registerSingleton(INotebookEditorService, NotebookEditorWidgetService, true);
|
||||
registerSingleton(INotebookKernelService, NotebookKernelService, true);
|
||||
registerSingleton(INotebookExecutionService, NotebookExecutionService, true);
|
||||
registerSingleton(INotebookRendererMessagingService, NotebookRendererMessagingService, true);
|
||||
|
||||
const schemas: IJSONSchemaMap = {};
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CellEditType, ICellEditOperation, NotebookCellExecutionState, NotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellExecutionUpdateType, ICellExecuteUpdate, INotebookCellExecution, INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
|
||||
export class NotebookExecutionService implements INotebookExecutionService {
|
||||
declare _serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
@INotebookService private readonly _notebookService: INotebookService,
|
||||
) {
|
||||
}
|
||||
|
||||
registerNotebookCellExecution(execution: INotebookCellExecution): void {
|
||||
const notebook = this._notebookService.getNotebookTextModel(execution.notebook);
|
||||
if (!notebook) {
|
||||
return;
|
||||
}
|
||||
|
||||
const startExecuteEdit: ICellEditOperation = {
|
||||
editType: CellEditType.PartialInternalMetadata,
|
||||
handle: execution.cellHandle,
|
||||
internalMetadata: {
|
||||
runState: NotebookCellExecutionState.Pending
|
||||
}
|
||||
};
|
||||
this._applyExecutionEdits(notebook, [startExecuteEdit]);
|
||||
|
||||
const listener = execution.onDidChange(updates => {
|
||||
const edits = updates.map(update => updateToEdit(update, execution.cellHandle));
|
||||
if (updates.some(update => update.editType === CellExecutionUpdateType.Complete)) {
|
||||
listener.dispose();
|
||||
}
|
||||
|
||||
this._applyExecutionEdits(notebook, edits);
|
||||
});
|
||||
}
|
||||
|
||||
private _applyExecutionEdits(notebook: NotebookTextModel, edits: ICellEditOperation[]): void {
|
||||
notebook.applyEdits(edits, true, undefined, () => undefined, undefined, false);
|
||||
}
|
||||
}
|
||||
|
||||
function updateToEdit(update: ICellExecuteUpdate, cellHandle: number): ICellEditOperation {
|
||||
if (update.editType === CellExecutionUpdateType.Output) {
|
||||
return {
|
||||
editType: CellEditType.Output,
|
||||
handle: update.cellHandle,
|
||||
append: update.append,
|
||||
outputs: update.outputs,
|
||||
};
|
||||
} else if (update.editType === CellExecutionUpdateType.OutputItems) {
|
||||
return {
|
||||
editType: CellEditType.OutputItems,
|
||||
items: update.items,
|
||||
append: update.append,
|
||||
outputId: update.outputId
|
||||
};
|
||||
} else if (update.editType === CellExecutionUpdateType.Complete) {
|
||||
return {
|
||||
editType: CellEditType.PartialInternalMetadata,
|
||||
handle: cellHandle,
|
||||
internalMetadata: {
|
||||
runState: null,
|
||||
lastRunSuccess: update.lastRunSuccess,
|
||||
runEndTime: update.runEndTime
|
||||
}
|
||||
};
|
||||
} else if (update.editType === CellExecutionUpdateType.ExecutionState) {
|
||||
const newInternalMetadata: Partial<NotebookCellInternalMetadata> = {
|
||||
runState: NotebookCellExecutionState.Executing,
|
||||
};
|
||||
if (typeof update.executionOrder !== 'undefined') {
|
||||
newInternalMetadata.executionOrder = update.executionOrder;
|
||||
}
|
||||
if (typeof update.runStartTime !== 'undefined') {
|
||||
newInternalMetadata.runStartTime = update.runStartTime;
|
||||
}
|
||||
return {
|
||||
editType: CellEditType.PartialInternalMetadata,
|
||||
handle: cellHandle,
|
||||
internalMetadata: newInternalMetadata
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error('Unknown cell update type');
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IOutputDto, IOutputItemDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
|
||||
export enum CellExecutionUpdateType {
|
||||
Output = 1,
|
||||
OutputItems = 2,
|
||||
ExecutionState = 3,
|
||||
Complete = 4,
|
||||
}
|
||||
|
||||
export interface ICellExecuteOutputEdit {
|
||||
editType: CellExecutionUpdateType.Output;
|
||||
executionHandle: number;
|
||||
cellHandle: number;
|
||||
append?: boolean;
|
||||
outputs: IOutputDto[]
|
||||
}
|
||||
|
||||
export interface ICellExecuteOutputItemEdit {
|
||||
editType: CellExecutionUpdateType.OutputItems;
|
||||
executionHandle: number;
|
||||
append?: boolean;
|
||||
outputId: string;
|
||||
items: IOutputItemDto[]
|
||||
}
|
||||
|
||||
export type ICellExecuteUpdate = ICellExecuteOutputEdit | ICellExecuteOutputItemEdit | ICellExecutionStateUpdate | ICellExecutionComplete;
|
||||
|
||||
export interface ICellExecutionStateUpdate {
|
||||
editType: CellExecutionUpdateType.ExecutionState;
|
||||
executionHandle: number;
|
||||
executionOrder?: number;
|
||||
runStartTime?: number;
|
||||
}
|
||||
|
||||
export interface ICellExecutionComplete {
|
||||
editType: CellExecutionUpdateType.Complete;
|
||||
executionHandle: number;
|
||||
runEndTime?: number;
|
||||
lastRunSuccess?: boolean;
|
||||
}
|
||||
|
||||
export interface INotebookCellExecution {
|
||||
readonly id: number;
|
||||
readonly notebook: URI;
|
||||
readonly cellHandle: number;
|
||||
readonly onDidChange: Event<Readonly<ICellExecuteUpdate[]>>;
|
||||
}
|
||||
|
||||
export const INotebookExecutionService = createDecorator<INotebookExecutionService>('INotebookExecutionService');
|
||||
|
||||
export interface INotebookExecutionService {
|
||||
_serviceBrand: undefined;
|
||||
|
||||
registerNotebookCellExecution(execution: INotebookCellExecution): void;
|
||||
}
|
|
@ -4,27 +4,28 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { CellExecuteEditDto, INotebookKernelDto2, MainContext, MainThreadCommandsShape, MainThreadNotebookDocumentsShape, MainThreadNotebookKernelsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookKernels } from 'vs/workbench/api/common/extHostNotebookKernels';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { CellEditType, CellKind, CellUri, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
|
||||
import { NotebookCellOutput, NotebookCellOutputItem } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { ICellExecuteUpdateDto, INotebookKernelDto2, MainContext, MainThreadCommandsShape, MainThreadNotebookDocumentsShape, MainThreadNotebookKernelsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
|
||||
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
|
||||
import { ExtHostNotebookKernels } from 'vs/workbench/api/common/extHostNotebookKernels';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { NotebookCellOutput, NotebookCellOutputItem } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { CellKind, CellUri, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellExecutionUpdateType } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
|
||||
import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
|
||||
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
|
||||
suite('NotebookKernel', function () {
|
||||
|
||||
|
@ -40,13 +41,13 @@ suite('NotebookKernel', function () {
|
|||
const kernelData = new Map<number, INotebookKernelDto2>();
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
const cellExecuteEdits: CellExecuteEditDto[] = [];
|
||||
const cellExecuteUpdates: ICellExecuteUpdateDto[] = [];
|
||||
|
||||
teardown(function () {
|
||||
disposables.clear();
|
||||
});
|
||||
setup(async function () {
|
||||
cellExecuteEdits.length = 0;
|
||||
cellExecuteUpdates.length = 0;
|
||||
kernelData.clear();
|
||||
|
||||
rpcProtocol = new TestRPCProtocol();
|
||||
|
@ -64,8 +65,8 @@ suite('NotebookKernel', function () {
|
|||
assert.strictEqual(kernelData.has(handle), true);
|
||||
kernelData.set(handle, { ...kernelData.get(handle)!, ...data, });
|
||||
}
|
||||
override async $applyExecutionEdits(resource: UriComponents, _edits: CellExecuteEditDto[]) {
|
||||
cellExecuteEdits.push(..._edits);
|
||||
override $updateExecutions(data: ICellExecuteUpdateDto[]): void {
|
||||
cellExecuteUpdates.push(...data);
|
||||
}
|
||||
});
|
||||
rpcProtocol.set(MainContext.MainThreadNotebookDocuments, new class extends mock<MainThreadNotebookDocumentsShape>() {
|
||||
|
@ -260,16 +261,16 @@ suite('NotebookKernel', function () {
|
|||
b.open(); // use barrier to signal that cancellation has happened
|
||||
});
|
||||
|
||||
cellExecuteEdits.length = 0;
|
||||
cellExecuteUpdates.length = 0;
|
||||
await extHostNotebookKernels.$cancelCells(0, notebook.uri, [0]);
|
||||
|
||||
await b.wait();
|
||||
|
||||
assert.strictEqual(cellExecuteEdits.length > 0, true);
|
||||
assert.strictEqual(cellExecuteUpdates.length > 0, true);
|
||||
|
||||
let found = false;
|
||||
for (let edit of cellExecuteEdits) {
|
||||
if (edit.editType === CellEditType.Output) {
|
||||
for (let edit of cellExecuteUpdates) {
|
||||
if (edit.editType === CellExecutionUpdateType.Output) {
|
||||
assert.strictEqual(edit.append, false);
|
||||
assert.strictEqual(edit.outputs.length, 1);
|
||||
assert.strictEqual(edit.outputs[0].items.length, 1);
|
||||
|
@ -296,14 +297,14 @@ suite('NotebookKernel', function () {
|
|||
task.end(true);
|
||||
};
|
||||
|
||||
cellExecuteEdits.length = 0;
|
||||
cellExecuteUpdates.length = 0;
|
||||
await extHostNotebookKernels.$cancelCells(0, notebook.uri, [0]);
|
||||
|
||||
assert.strictEqual(cellExecuteEdits.length > 0, true);
|
||||
assert.strictEqual(cellExecuteUpdates.length > 0, true);
|
||||
|
||||
let found = false;
|
||||
for (let edit of cellExecuteEdits) {
|
||||
if (edit.editType === CellEditType.Output) {
|
||||
for (let edit of cellExecuteUpdates) {
|
||||
if (edit.editType === CellExecutionUpdateType.Output) {
|
||||
assert.strictEqual(edit.append, false);
|
||||
assert.strictEqual(edit.outputs.length, 1);
|
||||
assert.strictEqual(edit.outputs[0].items.length, 1);
|
||||
|
|
Loading…
Reference in a new issue