Add saved and executed events to notebook changed (#5848)

- Updated the notebook API to add a change kind, and support saved, executed and other simplified status
- Plumbed this through to the main thread classes
- Support sending the events from cell / input to the notebook model so they loop over the extension host as a content changed event
- Add executed event from the cell
This commit is contained in:
Kevin Cunnane
2019-06-05 16:34:26 -07:00
committed by GitHub
parent 7d67711336
commit 44d6bb66da
20 changed files with 128 additions and 29 deletions

View File

@@ -4430,10 +4430,17 @@ declare module 'azdata' {
*/ */
cells: NotebookCell[]; cells: NotebookCell[];
/** /**
* The [change kind](#TextEditorSelectionChangeKind) which has triggered this * The [change kind](#NotebookChangeKind) which has triggered this
* event. Can be `undefined`. * event. Can be `undefined`.
*/ */
kind?: vscode.TextEditorSelectionChangeKind; kind?: NotebookChangeKind;
}
export enum NotebookChangeKind {
ContentUpdated = 0,
MetadataUpdated = 1,
Save = 2,
CellExecuted = 3
} }
/** /**

View File

@@ -646,3 +646,10 @@ export enum ActionOnCellCheckboxCheck {
selectRow = 0, selectRow = 0,
customAction = 1 customAction = 1
} }
export enum NotebookChangeKind {
ContentUpdated = 0,
MetadataUpdated = 1,
Save = 2,
CellExecuted = 3
}

View File

@@ -147,7 +147,7 @@ export class ExtHostNotebookDocumentsAndEditors implements ExtHostNotebookDocume
this._onDidChangeNotebookCell.fire({ this._onDidChangeNotebookCell.fire({
cells: data.document.cells, cells: data.document.cells,
notebook: data.document, notebook: data.document,
kind: undefined kind: e.changeKind
}); });
} }
} }

View File

@@ -22,7 +22,7 @@ import {
} from 'sql/workbench/api/node/sqlExtHost.protocol'; } from 'sql/workbench/api/node/sqlExtHost.protocol';
import { NotebookInput } from 'sql/workbench/parts/notebook/notebookInput'; import { NotebookInput } from 'sql/workbench/parts/notebook/notebookInput';
import { INotebookService, INotebookEditor, IProviderInfo } from 'sql/workbench/services/notebook/common/notebookService'; import { INotebookService, INotebookEditor, IProviderInfo } from 'sql/workbench/services/notebook/common/notebookService';
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes'; import { ISingleNotebookEditOperation, NotebookChangeKind } from 'sql/workbench/api/common/sqlExtHostTypes';
import { disposed } from 'vs/base/common/errors'; import { disposed } from 'vs/base/common/errors';
import { ICellModel, NotebookContentChange, INotebookModel } from 'sql/workbench/parts/notebook/models/modelInterfaces'; import { ICellModel, NotebookContentChange, INotebookModel } from 'sql/workbench/parts/notebook/models/modelInterfaces';
import { NotebookChangeType, CellTypes } from 'sql/workbench/parts/notebook/models/contracts'; import { NotebookChangeType, CellTypes } from 'sql/workbench/parts/notebook/models/contracts';
@@ -564,11 +564,32 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements
providerId: editor.providerId, providerId: editor.providerId,
providers: editor.providers, providers: editor.providers,
uri: editor.uri, uri: editor.uri,
kernelSpec: this.getKernelSpec(editor) kernelSpec: this.getKernelSpec(editor),
changeKind: this.mapChangeKind(e.changeType)
}; };
return changeData; return changeData;
} }
mapChangeKind(changeType: NotebookChangeType): NotebookChangeKind {
switch (changeType) {
case NotebookChangeType.CellDeleted:
case NotebookChangeType.CellsAdded:
case NotebookChangeType.CellOutputUpdated:
case NotebookChangeType.CellSourceUpdated:
case NotebookChangeType.DirtyStateChanged:
return NotebookChangeKind.ContentUpdated;
case NotebookChangeType.KernelChanged:
case NotebookChangeType.TrustChanged:
return NotebookChangeKind.MetadataUpdated;
case NotebookChangeType.Saved:
return NotebookChangeKind.Save;
case NotebookChangeType.CellExecuted:
return NotebookChangeKind.CellExecuted;
default:
return NotebookChangeKind.ContentUpdated;
}
}
private getKernelSpec(editor: MainThreadNotebookEditor): azdata.nb.IKernelSpec { private getKernelSpec(editor: MainThreadNotebookEditor): azdata.nb.IKernelSpec {
let spec = editor && editor.model && editor.model.clientSession ? editor.model.clientSession.cachedKernelSpec : undefined; let spec = editor && editor.model && editor.model.clientSession ? editor.model.clientSession.cachedKernelSpec : undefined;
return spec; return spec;

View File

@@ -496,7 +496,8 @@ export function createApiFactory(
registerNotebookProvider(provider: azdata.nb.NotebookProvider): vscode.Disposable { registerNotebookProvider(provider: azdata.nb.NotebookProvider): vscode.Disposable {
return extHostNotebook.registerNotebookProvider(provider); return extHostNotebook.registerNotebookProvider(provider);
}, },
CellRange: sqlExtHostTypes.CellRange CellRange: sqlExtHostTypes.CellRange,
NotebookChangeKind: sqlExtHostTypes.NotebookChangeKind
}; };
return { return {

View File

@@ -18,7 +18,9 @@ import { ITreeComponentItem } from 'sql/workbench/common/views';
import { ITaskHandlerDescription } from 'sql/platform/tasks/common/tasks'; import { ITaskHandlerDescription } from 'sql/platform/tasks/common/tasks';
import { import {
IItemConfig, IComponentShape, IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails, IItemConfig, IComponentShape, IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails,
IModelViewWizardDetails, IModelViewWizardPageDetails, INotebookManagerDetails, INotebookSessionDetails, INotebookKernelDetails, INotebookFutureDetails, FutureMessageType, INotebookFutureDone, ISingleNotebookEditOperation IModelViewWizardDetails, IModelViewWizardPageDetails, INotebookManagerDetails, INotebookSessionDetails,
INotebookKernelDetails, INotebookFutureDetails, FutureMessageType, INotebookFutureDone, ISingleNotebookEditOperation,
NotebookChangeKind
} from 'sql/workbench/api/common/sqlExtHostTypes'; } from 'sql/workbench/api/common/sqlExtHostTypes';
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor'; import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
import { IUndoStopOptions } from 'vs/workbench/api/common/extHost.protocol'; import { IUndoStopOptions } from 'vs/workbench/api/common/extHost.protocol';
@@ -870,6 +872,7 @@ export interface INotebookModelChangedData {
isDirty: boolean; isDirty: boolean;
cells: azdata.nb.NotebookCell[]; cells: azdata.nb.NotebookCell[];
kernelSpec: azdata.nb.IKernelSpec; kernelSpec: azdata.nb.IKernelSpec;
changeKind: NotebookChangeKind;
} }
export interface INotebookEditorAddData { export interface INotebookEditorAddData {

View File

@@ -39,7 +39,7 @@ export class OutputComponent extends AngularDisposable implements OnInit {
@Inject(IThemeService) private _themeService: IThemeService @Inject(IThemeService) private _themeService: IThemeService
) { ) {
super(); super();
this.registry = _notebookService.getMimeRegistry(); this.registry = this._notebookService.getMimeRegistry();
} }
ngOnInit() { ngOnInit() {

View File

@@ -13,11 +13,13 @@ import * as notebookUtils from '../notebookUtils';
import { CellTypes, CellType, NotebookChangeType } from 'sql/workbench/parts/notebook/models/contracts'; import { CellTypes, CellType, NotebookChangeType } from 'sql/workbench/parts/notebook/models/contracts';
import { NotebookModel } from 'sql/workbench/parts/notebook/models/notebookModel'; import { NotebookModel } from 'sql/workbench/parts/notebook/models/notebookModel';
import { ICellModel, notebookConstants, IOutputChangedEvent } from 'sql/workbench/parts/notebook/models/modelInterfaces'; import { ICellModel, notebookConstants, IOutputChangedEvent } from 'sql/workbench/parts/notebook/models/modelInterfaces';
import { ICellModelOptions, IModelFactory, FutureInternal, CellExecutionState } from './modelInterfaces'; import { ICellModelOptions, FutureInternal, CellExecutionState } from './modelInterfaces';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { INotebookService } from 'sql/workbench/services/notebook/common/notebookService';
import { optional } from 'vs/platform/instantiation/common/instantiation';
let modelId = 0; let modelId = 0;
export class CellModel implements ICellModel { export class CellModel implements ICellModel {
@@ -39,7 +41,10 @@ export class CellModel implements ICellModel {
private _connectionManagementService: IConnectionManagementService; private _connectionManagementService: IConnectionManagementService;
private _stdInHandler: nb.MessageHandler<nb.IStdinMessage>; private _stdInHandler: nb.MessageHandler<nb.IStdinMessage>;
constructor(private factory: IModelFactory, cellData?: nb.ICellContents, private _options?: ICellModelOptions) { constructor(cellData: nb.ICellContents,
private _options: ICellModelOptions,
@optional(INotebookService) private _notebookService?: INotebookService
) {
this.id = `${modelId++}`; this.id = `${modelId++}`;
if (cellData) { if (cellData) {
// Read in contents if available // Read in contents if available
@@ -178,6 +183,12 @@ export class CellModel implements ICellModel {
this._onExecutionStateChanged.fire(this.executionState); this._onExecutionStateChanged.fire(this.executionState);
} }
private notifyExecutionComplete(): void {
if (this._notebookService) {
this._notebookService.serializeNotebookStateChange(this.notebookModel.notebookUri, NotebookChangeType.CellExecuted);
}
}
public get executionState(): CellExecutionState { public get executionState(): CellExecutionState {
let isRunning = !!(this._future && this._future.inProgress); let isRunning = !!(this._future && this._future.inProgress);
if (isRunning) { if (isRunning) {
@@ -256,6 +267,7 @@ export class CellModel implements ICellModel {
} finally { } finally {
this.disposeFuture(); this.disposeFuture();
this.fireExecutionStateChanged(); this.fireExecutionStateChanged();
this.notifyExecutionComplete();
} }
return true; return true;

View File

@@ -43,5 +43,7 @@ export enum NotebookChangeType {
CellOutputUpdated, CellOutputUpdated,
DirtyStateChanged, DirtyStateChanged,
KernelChanged, KernelChanged,
TrustChanged TrustChanged,
Saved,
CellExecuted
} }

View File

@@ -8,11 +8,15 @@ import { nb } from 'azdata';
import { CellModel } from './cell'; import { CellModel } from './cell';
import { IClientSession, IClientSessionOptions, ICellModelOptions, ICellModel, IModelFactory } from './modelInterfaces'; import { IClientSession, IClientSessionOptions, ICellModelOptions, ICellModel, IModelFactory } from './modelInterfaces';
import { ClientSession } from './clientSession'; import { ClientSession } from './clientSession';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export class ModelFactory implements IModelFactory { export class ModelFactory implements IModelFactory {
constructor(private instantiationService: IInstantiationService) {
}
public createCell(cell: nb.ICellContents, options: ICellModelOptions): ICellModel { public createCell(cell: nb.ICellContents, options: ICellModelOptions): ICellModel {
return new CellModel(this, cell, options); return this.instantiationService.createInstance(CellModel, cell, options);
} }
public createClientSession(options: IClientSessionOptions): IClientSession { public createClientSession(options: IClientSessionOptions): IClientSession {

View File

@@ -401,6 +401,9 @@ export interface INotebookModel {
/** Event fired once we get call back from ConfigureConnection method in sqlops extension */ /** Event fired once we get call back from ConfigureConnection method in sqlops extension */
readonly onValidConnectionSelected: Event<boolean>; readonly onValidConnectionSelected: Event<boolean>;
serializationStateChanged(changeType: NotebookChangeType): void;
} }
export interface NotebookContentChange { export interface NotebookContentChange {

View File

@@ -954,4 +954,13 @@ export class NotebookModel extends Disposable implements INotebookModel {
this._contentChangedEmitter.fire(changeInfo); this._contentChangedEmitter.fire(changeInfo);
} }
serializationStateChanged(changeType: NotebookChangeType): void {
let changeInfo: NotebookContentChange = {
changeType: changeType,
cells: undefined
};
this._contentChangedEmitter.fire(changeInfo);
}
} }

View File

@@ -345,7 +345,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
private get modelFactory(): IModelFactory { private get modelFactory(): IModelFactory {
if (!this._notebookParams.modelFactory) { if (!this._notebookParams.modelFactory) {
this._notebookParams.modelFactory = new ModelFactory(); this._notebookParams.modelFactory = new ModelFactory(this.instantiationService);
} }
return this._notebookParams.modelFactory; return this._notebookParams.modelFactory;
} }

View File

@@ -11,7 +11,7 @@ import * as resources from 'vs/base/common/resources';
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import { IStandardKernelWithProvider, getProvidersForFileName, getStandardKernelsForProvider } from 'sql/workbench/parts/notebook/notebookUtils'; import { IStandardKernelWithProvider, getProvidersForFileName, getStandardKernelsForProvider } from 'sql/workbench/parts/notebook/notebookUtils';
import { INotebookService, DEFAULT_NOTEBOOK_PROVIDER, IProviderInfo, SerializationStateChangeType } from 'sql/workbench/services/notebook/common/notebookService'; import { INotebookService, DEFAULT_NOTEBOOK_PROVIDER, IProviderInfo } from 'sql/workbench/services/notebook/common/notebookService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { INotebookModel, IContentManager, NotebookContentChange } from 'sql/workbench/parts/notebook/models/modelInterfaces'; import { INotebookModel, IContentManager, NotebookContentChange } from 'sql/workbench/parts/notebook/models/modelInterfaces';
@@ -118,7 +118,7 @@ export class NotebookEditorModel extends EditorModel {
private sendNotebookSerializationStateChange() { private sendNotebookSerializationStateChange() {
let notebookModel = this.getNotebookModel(); let notebookModel = this.getNotebookModel();
if (notebookModel) { if (notebookModel) {
this.notebookService.serializeNotebookStateChange(this.notebookUri, SerializationStateChangeType.Saved); this.notebookService.serializeNotebookStateChange(this.notebookUri, NotebookChangeType.Saved);
} }
} }
@@ -127,7 +127,7 @@ export class NotebookEditorModel extends EditorModel {
} }
private getNotebookModel(): INotebookModel { private getNotebookModel(): INotebookModel {
let editor = this.notebookService.listNotebookEditors().find(n => n.id === this.notebookUri.toString()); let editor = this.notebookService.findNotebookEditor(this.notebookUri);
if (editor) { if (editor) {
return editor.model; return editor.model;
} }

View File

@@ -15,6 +15,7 @@ import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { NotebookInput } from 'sql/workbench/parts/notebook/notebookInput'; import { NotebookInput } from 'sql/workbench/parts/notebook/notebookInput';
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes'; import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
import { ICellModel, INotebookModel, ILanguageMagic } from 'sql/workbench/parts/notebook/models/modelInterfaces'; import { ICellModel, INotebookModel, ILanguageMagic } from 'sql/workbench/parts/notebook/models/modelInterfaces';
import { NotebookChangeType } from 'sql/workbench/parts/notebook/models/contracts';
export const SERVICE_ID = 'notebookService'; export const SERVICE_ID = 'notebookService';
export const INotebookService = createDecorator<INotebookService>(SERVICE_ID); export const INotebookService = createDecorator<INotebookService>(SERVICE_ID);
@@ -65,6 +66,8 @@ export interface INotebookService {
listNotebookEditors(): INotebookEditor[]; listNotebookEditors(): INotebookEditor[];
findNotebookEditor(notebookUri: URI): INotebookEditor | undefined;
getMimeRegistry(): RenderMimeRegistry; getMimeRegistry(): RenderMimeRegistry;
renameNotebookEditor(oldUri: URI, newUri: URI, currentEditor: INotebookEditor): void; renameNotebookEditor(oldUri: URI, newUri: URI, currentEditor: INotebookEditor): void;
@@ -85,7 +88,7 @@ export interface INotebookService {
* sent to listeners that can act on the point-in-time notebook state * sent to listeners that can act on the point-in-time notebook state
* @param notebookUri the URI identifying a notebook * @param notebookUri the URI identifying a notebook
*/ */
serializeNotebookStateChange(notebookUri: URI, changeType: SerializationStateChangeType): void; serializeNotebookStateChange(notebookUri: URI, changeType: NotebookChangeType): void;
} }
@@ -128,8 +131,3 @@ export interface INotebookEditor {
runAllCells(): Promise<boolean>; runAllCells(): Promise<boolean>;
clearAllOutputs(): Promise<boolean>; clearAllOutputs(): Promise<boolean>;
} }
export enum SerializationStateChangeType {
Saved,
Executed
}

View File

@@ -10,7 +10,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { import {
INotebookService, INotebookManager, INotebookProvider, INotebookService, INotebookManager, INotebookProvider,
DEFAULT_NOTEBOOK_FILETYPE, INotebookEditor, SQL_NOTEBOOK_PROVIDER, OVERRIDE_EDITOR_THEMING_SETTING, SerializationStateChangeType DEFAULT_NOTEBOOK_FILETYPE, INotebookEditor, SQL_NOTEBOOK_PROVIDER, OVERRIDE_EDITOR_THEMING_SETTING
} from 'sql/workbench/services/notebook/common/notebookService'; } from 'sql/workbench/services/notebook/common/notebookService';
import { RenderMimeRegistry } from 'sql/workbench/parts/notebook/outputs/registry'; import { RenderMimeRegistry } from 'sql/workbench/parts/notebook/outputs/registry';
import { standardRendererFactories } from 'sql/workbench/parts/notebook/outputs/factories'; import { standardRendererFactories } from 'sql/workbench/parts/notebook/outputs/factories';
@@ -40,6 +40,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { toErrorMessage } from 'vs/base/common/errorMessage'; import { toErrorMessage } from 'vs/base/common/errorMessage';
import { NotebookChangeType } from 'sql/workbench/parts/notebook/models/contracts';
export interface NotebookProviderProperties { export interface NotebookProviderProperties {
provider: string; provider: string;
@@ -384,6 +385,15 @@ export class NotebookService extends Disposable implements INotebookService {
return editors; return editors;
} }
findNotebookEditor(notebookUri: URI): INotebookEditor | undefined {
if (!notebookUri) {
return undefined;
}
let uriString = notebookUri.toString();
let editor = this.listNotebookEditors().find(n => n.id === uriString);
return editor;
}
renameNotebookEditor(oldUri: URI, newUri: URI, currentEditor: INotebookEditor): void { renameNotebookEditor(oldUri: URI, newUri: URI, currentEditor: INotebookEditor): void {
let oldUriKey = oldUri.toString(); let oldUriKey = oldUri.toString();
if (this._editors.has(oldUriKey)) { if (this._editors.has(oldUriKey)) {
@@ -552,7 +562,7 @@ export class NotebookService extends Disposable implements INotebookService {
} }
} }
serializeNotebookStateChange(notebookUri: URI, changeType: SerializationStateChangeType): void { serializeNotebookStateChange(notebookUri: URI, changeType: NotebookChangeType): void {
if (notebookUri.scheme !== Schemas.untitled) { if (notebookUri.scheme !== Schemas.untitled) {
// Conditions for saving: // Conditions for saving:
// 1. Not untitled. They're always trusted as we open them // 1. Not untitled. They're always trusted as we open them
@@ -560,7 +570,7 @@ export class NotebookService extends Disposable implements INotebookService {
// 3. Not already saving (e.g. isn't in the queue to be cached) // 3. Not already saving (e.g. isn't in the queue to be cached)
// 4. Notebook is trusted. Don't need to save state of untrusted notebooks // 4. Notebook is trusted. Don't need to save state of untrusted notebooks
let notebookUriString = notebookUri.toString(); let notebookUriString = notebookUri.toString();
if (changeType === SerializationStateChangeType.Saved && this._trustedCacheQueue.findIndex(uri => uri.toString() === notebookUriString) < 0) { if (changeType === NotebookChangeType.Saved && this._trustedCacheQueue.findIndex(uri => uri.toString() === notebookUriString) < 0) {
// Only save if it's trusted // Only save if it's trusted
let notebook = this.listNotebookEditors().find(n => n.id === notebookUriString); let notebook = this.listNotebookEditors().find(n => n.id === notebookUriString);
if (notebook && notebook.model.trustedMode) { if (notebook && notebook.model.trustedMode) {
@@ -568,6 +578,11 @@ export class NotebookService extends Disposable implements INotebookService {
this._updateTrustCacheScheduler.schedule(); this._updateTrustCacheScheduler.schedule();
} }
} }
}
let editor = this.findNotebookEditor(notebookUri);
if (editor && editor.model) {
editor.model.serializationStateChanged(changeType);
// TODO add history notification if a non-untitled notebook has a state change // TODO add history notification if a non-untitled notebook has a state change
} }
} }

View File

@@ -102,6 +102,9 @@ export class NotebookModelStub implements INotebookModel {
toJSON(): nb.INotebookContents { toJSON(): nb.INotebookContents {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
serializationStateChanged(changeType: NotebookChangeType): void {
throw new Error('Method not implemented.');
}
} }
export class NotebookManagerStub implements INotebookManager { export class NotebookManagerStub implements INotebookManager {

View File

@@ -15,9 +15,17 @@ import { NotebookModelStub } from '../common';
import { EmptyFuture } from 'sql/workbench/services/notebook/common/sessionManager'; import { EmptyFuture } from 'sql/workbench/services/notebook/common/sessionManager';
import { ICellModel } from 'sql/workbench/parts/notebook/models/modelInterfaces'; import { ICellModel } from 'sql/workbench/parts/notebook/models/modelInterfaces';
import { Deferred } from 'sql/base/common/promise'; import { Deferred } from 'sql/base/common/promise';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
let instantiationService: IInstantiationService;
suite('Cell Model', function (): void { suite('Cell Model', function (): void {
let factory = new ModelFactory(); let serviceCollection = new ServiceCollection();
instantiationService = new InstantiationService(serviceCollection, true);
let factory = new ModelFactory(instantiationService);
test('Should set default values if none defined', async function (): Promise<void> { test('Should set default values if none defined', async function (): Promise<void> {
let cell = factory.createCell(undefined, undefined); let cell = factory.createCell(undefined, undefined);
should(cell.cellType).equal(CellTypes.Code); should(cell.cellType).equal(CellTypes.Code);

View File

@@ -25,6 +25,9 @@ import { Emitter } from 'vs/base/common/event';
import { CapabilitiesTestService } from 'sqltest/stubs/capabilitiesTestService'; import { CapabilitiesTestService } from 'sqltest/stubs/capabilitiesTestService';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService'; import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { TestStorageService, TestLogService } from 'vs/workbench/test/workbenchTestServices'; import { TestStorageService, TestLogService } from 'vs/workbench/test/workbenchTestServices';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
let expectedNotebookContent: nb.INotebookContents = { let expectedNotebookContent: nb.INotebookContents = {
cells: [{ cells: [{
@@ -72,6 +75,7 @@ let sessionReady: Deferred<void>;
let mockModelFactory: TypeMoq.Mock<ModelFactory>; let mockModelFactory: TypeMoq.Mock<ModelFactory>;
let notificationService: TypeMoq.Mock<INotificationService>; let notificationService: TypeMoq.Mock<INotificationService>;
let capabilitiesService: TypeMoq.Mock<ICapabilitiesService>; let capabilitiesService: TypeMoq.Mock<ICapabilitiesService>;
let instantiationService: IInstantiationService;
suite('notebook model', function (): void { suite('notebook model', function (): void {
let notebookManagers = [new NotebookManagerStub()]; let notebookManagers = [new NotebookManagerStub()];
@@ -87,9 +91,11 @@ suite('notebook model', function (): void {
memento.setup(x => x.getMemento(TypeMoq.It.isAny())).returns(() => void 0); memento.setup(x => x.getMemento(TypeMoq.It.isAny())).returns(() => void 0);
queryConnectionService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, memento.object, undefined, new TestStorageService()); queryConnectionService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, memento.object, undefined, new TestStorageService());
queryConnectionService.callBase = true; queryConnectionService.callBase = true;
let serviceCollection = new ServiceCollection();
instantiationService = new InstantiationService(serviceCollection, true);
defaultModelOptions = { defaultModelOptions = {
notebookUri: defaultUri, notebookUri: defaultUri,
factory: new ModelFactory(), factory: new ModelFactory(instantiationService),
notebookManagers, notebookManagers,
contentManager: undefined, contentManager: undefined,
notificationService: notificationService.object, notificationService: notificationService.object,

View File

@@ -54,8 +54,8 @@ class NotebookUpdateParticipant implements ISaveParticipantParticipant {
} }
public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> { public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
let uriString = model.getResource().toString(); let uri = model.getResource();
let notebookEditor = this.notebookService.listNotebookEditors().find((editor) => editor.id === uriString); let notebookEditor = this.notebookService.findNotebookEditor(uri);
if (notebookEditor) { if (notebookEditor) {
notebookEditor.notebookParams.input.updateModel(); notebookEditor.notebookParams.input.updateModel();
} }