Skip to content

Commit 01b6114

Browse files
authored
Update VSC Notebook API (#12333)
1 parent ff1d4b0 commit 01b6114

File tree

12 files changed

+81
-47
lines changed

12 files changed

+81
-47
lines changed

src/client/common/application/notebook.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export class VSCodeNotebook implements IVSCodeNotebook {
3434
public get onDidCloseNotebookDocument(): Event<NotebookDocument> {
3535
return this.notebook.onDidCloseNotebookDocument;
3636
}
37+
public get notebookDocuments(): ReadonlyArray<NotebookDocument> {
38+
return this.notebook.notebookDocuments;
39+
}
3740
public get notebookEditors() {
3841
return this.notebook.visibleNotebookEditors;
3942
}

src/client/common/application/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,7 @@ export type NotebookCellChangedEvent =
15221522
| NotebookCellLanguageChangeEvent;
15231523
export const IVSCodeNotebook = Symbol('IVSCodeNotebook');
15241524
export interface IVSCodeNotebook {
1525+
readonly notebookDocuments: ReadonlyArray<NotebookDocument>;
15251526
readonly onDidOpenNotebookDocument: Event<NotebookDocument>;
15261527
readonly onDidCloseNotebookDocument: Event<NotebookDocument>;
15271528
readonly onDidChangeActiveNotebookEditor: Event<NotebookEditor | undefined>;

src/client/datascience/notebook/cellEditSyncService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export class CellEditSyncService implements IExtensionSingleActivationService, I
109109
return;
110110
}
111111

112-
this.mappedDocuments.set(cellDocument, { model: editor.model, cellId: getOriginalCellId(document, cell)! });
112+
this.mappedDocuments.set(cellDocument, { model: editor.model, cellId: getOriginalCellId(cell)! });
113113
return this.mappedDocuments.get(cellDocument);
114114
}
115115
}

src/client/datascience/notebook/executionService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ export class NotebookExecutionService implements INotebookExecutionService {
179179
.flatMap((item) => (item.data.outputs as unknown) as nbformat.IOutput[])
180180
.filter((output) => !hasTransientOutputForAnotherCell(output));
181181

182-
const notebookCellModel = findMappedNotebookCellModel(document, cell, model.cells);
182+
const notebookCellModel = findMappedNotebookCellModel(cell, model.cells);
183183

184184
// Set execution count, all messages should have it
185185
if (
@@ -206,7 +206,7 @@ export class NotebookExecutionService implements INotebookExecutionService {
206206
cell.metadata.statusMessage = '';
207207

208208
// Update metadata in our model.
209-
const notebookCellModel = findMappedNotebookCellModel(document, cell, model.cells);
209+
const notebookCellModel = findMappedNotebookCellModel(cell, model.cells);
210210
updateCellExecutionTimes(
211211
notebookCellModel,
212212
cell.metadata.runStartTime,

src/client/datascience/notebook/helpers/cellMappers.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ type ICellId = string;
2525
const cellMapsByNotebookDocument = new WeakMap<NotebookDocument, Map<VSCodeCellUri, ICellId>>();
2626
const mapOfCellsToNotebookCells = new WeakMap<ICell, VSCodeCellUri>();
2727

28-
export function mapVSCNotebookCellToCellModel(document: NotebookDocument, vscCell: NotebookCell, cell: ICell) {
29-
if (!cellMapsByNotebookDocument.has(document)) {
30-
cellMapsByNotebookDocument.set(document, new Map<VSCodeCellUri, ICellId>());
28+
export function mapVSCNotebookCellToCellModel(vscCell: NotebookCell, cell: ICell) {
29+
if (!cellMapsByNotebookDocument.has(vscCell.notebook)) {
30+
cellMapsByNotebookDocument.set(vscCell.notebook, new Map<VSCodeCellUri, ICellId>());
3131
}
32-
cellMapsByNotebookDocument.get(document)!.set(vscCell.uri.toString(), cell.id);
32+
cellMapsByNotebookDocument.get(vscCell.notebook)!.set(vscCell.uri.toString(), cell.id);
3333
mapOfCellsToNotebookCells.set(cell, vscCell.uri.toString());
3434
}
3535

36-
export function getOriginalCellId(document: NotebookDocument, cell: NotebookCell): string | undefined {
37-
const map = cellMapsByNotebookDocument.get(document);
36+
export function getOriginalCellId(cell: NotebookCell): string | undefined {
37+
const map = cellMapsByNotebookDocument.get(cell.notebook);
3838
if (!map) {
3939
return;
4040
}
@@ -61,7 +61,7 @@ export function mapVSCNotebookCellsToNotebookCellModels(document: NotebookDocume
6161

6262
document.cells.forEach((vscCell, index) => {
6363
const cell = model.cells[index];
64-
mapVSCNotebookCellToCellModel(document, vscCell, cell);
64+
mapVSCNotebookCellToCellModel(vscCell, cell);
6565
});
6666
}
6767

@@ -74,10 +74,10 @@ export function findMappedNotebookCell(source: ICell, cells: NotebookCell[]): No
7474
return found[0];
7575
}
7676

77-
export function findMappedNotebookCellModel(document: NotebookDocument, source: NotebookCell, cells: ICell[]): ICell {
77+
export function findMappedNotebookCellModel(source: NotebookCell, cells: ICell[]): ICell {
7878
// If so, then we have a problem.
79-
const found = cells.filter((cell) => cell.id === getOriginalCellId(document, source));
80-
assert.ok(found.length, `ICell not found, for CellId = ${getOriginalCellId(document, source)} in ${source}`);
79+
const found = cells.filter((cell) => cell.id === getOriginalCellId(source));
80+
assert.ok(found.length, `ICell not found, for CellId = ${getOriginalCellId(source)} in ${source}`);
8181

8282
return found[0];
8383
}

src/client/datascience/notebook/helpers/cellUpdateHelpers.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function clearCellOutput(change: NotebookCellOutputsChangeEvent, model: INoteboo
5959

6060
// If a cell has been cleared, then clear the corresponding ICell (cell in INotebookModel).
6161
change.cells.forEach((vscCell) => {
62-
const cell = findMappedNotebookCellModel(change.document, vscCell, model.cells);
62+
const cell = findMappedNotebookCellModel(vscCell, model.cells);
6363
cell.data.outputs = [];
6464
updateVSCNotebookCellMetadata(vscCell.metadata, cell);
6565
model.update({
@@ -73,7 +73,7 @@ function clearCellOutput(change: NotebookCellOutputsChangeEvent, model: INoteboo
7373
}
7474

7575
function changeCellLanguage(change: NotebookCellLanguageChangeEvent, model: INotebookModel) {
76-
const cellModel = findMappedNotebookCellModel(change.document, change.cell, model.cells);
76+
const cellModel = findMappedNotebookCellModel(change.cell, model.cells);
7777

7878
// VSC fires event if changing cell language from markdown to markdown.
7979
// https://github.com/microsoft/vscode/issues/98836
@@ -93,7 +93,7 @@ function changeCellLanguage(change: NotebookCellLanguageChangeEvent, model: INot
9393

9494
// Create a new cell & replace old one.
9595
const oldCellIndex = model.cells.indexOf(cellModel);
96-
model.cells[oldCellIndex] = createCellFromVSCNotebookCell(change.document, change.cell, model);
96+
model.cells[oldCellIndex] = createCellFromVSCNotebookCell(change.cell, model);
9797
}
9898

9999
function handleChangesToCells(change: NotebookCellsChangeEvent, model: INotebookModel) {
@@ -149,7 +149,7 @@ function isCellInsertion(change: NotebookCellsChangeEvent) {
149149
function handleCellMove(change: NotebookCellsChangeEvent, model: INotebookModel) {
150150
assert.equal(change.changes.length, 2, 'When moving cells we must have only 2 changes');
151151
const [, insertChange] = change.changes;
152-
const cellToSwap = findMappedNotebookCellModel(change.document, insertChange.items[0]!, model.cells);
152+
const cellToSwap = findMappedNotebookCellModel(insertChange.items[0]!, model.cells);
153153
const cellToSwapWith = model.cells[insertChange.start];
154154
assert.notEqual(cellToSwap, cellToSwapWith, 'Cannot swap cell with the same cell');
155155

@@ -162,7 +162,7 @@ function handleCellInsertion(change: NotebookCellsChangeEvent, model: INotebookM
162162
assert.equal(change.changes[0].items.length, 1, 'Insertion of more than 1 cell is not supported');
163163
const insertChange = change.changes[0];
164164
const cell = change.changes[0].items[0];
165-
const newCell = createCellFromVSCNotebookCell(change.document, cell, model);
165+
const newCell = createCellFromVSCNotebookCell(cell, model);
166166
model.cells.splice(insertChange.start, 0, newCell);
167167
}
168168
function handleCellDelete(change: NotebookCellsChangeEvent, model: INotebookModel) {

src/client/datascience/notebook/helpers/helpers.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ import type {
1414
NotebookCell,
1515
NotebookCellData,
1616
NotebookCellMetadata,
17-
NotebookData,
18-
NotebookDocument
17+
NotebookData
1918
} from 'vscode-proposed';
2019
import { NotebookCellRunState } from '../../../../../typings/vscode-proposed';
2120
import {
@@ -76,11 +75,7 @@ export function notebookModelToVSCNotebookData(model: INotebookModel): NotebookD
7675
}
7776
};
7877
}
79-
export function createCellFromVSCNotebookCell(
80-
document: NotebookDocument,
81-
vscCell: NotebookCell,
82-
model: INotebookModel
83-
): ICell {
78+
export function createCellFromVSCNotebookCell(vscCell: NotebookCell, model: INotebookModel): ICell {
8479
const cell = (() => {
8580
if (vscCell.cellKind === vscodeNotebookEnums.CellKind.Markdown) {
8681
return {
@@ -112,7 +107,7 @@ export function createCellFromVSCNotebookCell(
112107
};
113108
}
114109
// Ensure we add the cell id of the new cell to the VSC cell to map into ours.
115-
mapVSCNotebookCellToCellModel(document, vscCell, cell);
110+
mapVSCNotebookCellToCellModel(vscCell, cell);
116111

117112
return cell;
118113
}

src/test/datascience/notebook/contentProvider.ds.test.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,7 @@ suite('DataScience - VSCode Notebook - (Open)', function () {
6868
const vscCell = notebook.cells[index];
6969
const cell = model.cells[index];
7070
// Given a VS Code Cell, we should be able to find the corresponding ICell.
71-
assert.equal(
72-
cell,
73-
findMappedNotebookCellModel(notebook, vscCell, model.cells),
74-
'Could not find mapped ICell'
75-
);
71+
assert.equal(cell, findMappedNotebookCellModel(vscCell, model.cells), 'Could not find mapped ICell');
7672

7773
// Given an ICell, we should be able to find the corresponding VS Code Cell.
7874
assert.equal(vscCell, findMappedNotebookCell(cell, notebook.cells), 'Could not find mapped NotebookCell');

src/test/datascience/notebook/helper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export async function insertPythonCell(source: string, index: number = 0) {
7777
await waitForCondition(
7878
async () =>
7979
vscEditor!.document.cells.every((cell) =>
80-
findMappedNotebookCellModel(vscEditor!.document, cell, nbEditor!.model!.cells)
80+
findMappedNotebookCellModel(cell, nbEditor!.model!.cells)
8181
),
8282
1_000,
8383
'Cell not assigned a cell Id'

types/vscode-proposed/index.d.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ export interface CellErrorOutput {
4545
traceback: string[];
4646
}
4747

48+
export interface NotebookCellOutputMetadata {
49+
/**
50+
* Additional attributes of a cell metadata.
51+
*/
52+
custom?: { [key: string]: any };
53+
}
54+
4855
export interface CellDisplayOutput {
4956
outputKind: CellOutputKind.Rich;
5057
/**
@@ -65,6 +72,8 @@ export interface CellDisplayOutput {
6572
* }
6673
*/
6774
data: { [key: string]: any };
75+
76+
readonly metadata?: NotebookCellOutputMetadata;
6877
}
6978

7079
export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput;
@@ -132,11 +141,10 @@ export interface NotebookCellMetadata {
132141
}
133142

134143
export interface NotebookCell {
144+
readonly notebook: NotebookDocument;
135145
readonly uri: Uri;
136146
readonly cellKind: CellKind;
137147
readonly document: TextDocument;
138-
// API remove `source` or doc it as shorthand for document.getText()
139-
readonly source: string;
140148
language: string;
141149
outputs: CellOutput[];
142150
metadata: NotebookCellMetadata;
@@ -184,6 +192,7 @@ export interface NotebookDocumentMetadata {
184192
export interface NotebookDocument {
185193
readonly uri: Uri;
186194
readonly fileName: string;
195+
readonly viewType: string;
187196
readonly isDirty: boolean;
188197
readonly cells: NotebookCell[];
189198
languages: string[];
@@ -286,6 +295,7 @@ export interface NotebookOutputRenderer {
286295
export interface NotebookCellsChangeData {
287296
readonly start: number;
288297
readonly deletedCount: number;
298+
readonly deletedItems: NotebookCell[];
289299
readonly items: NotebookCell[];
290300
}
291301

@@ -379,12 +389,15 @@ export namespace notebook {
379389

380390
export const onDidOpenNotebookDocument: Event<NotebookDocument>;
381391
export const onDidCloseNotebookDocument: Event<NotebookDocument>;
392+
393+
/**
394+
* All currently known notebook documents.
395+
*/
396+
export const notebookDocuments: ReadonlyArray<NotebookDocument>;
397+
382398
export let visibleNotebookEditors: NotebookEditor[];
383399
export const onDidChangeVisibleNotebookEditors: Event<NotebookEditor[]>;
384400

385-
// remove activeNotebookDocument, now that there is activeNotebookEditor.document
386-
export let activeNotebookDocument: NotebookDocument | undefined;
387-
388401
export let activeNotebookEditor: NotebookEditor | undefined;
389402
export const onDidChangeActiveNotebookEditor: Event<NotebookEditor | undefined>;
390403
export const onDidChangeNotebookCells: Event<NotebookCellsChangeEvent>;

types/vscode.proposed.d.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ declare module 'vscode' {
4646
traceback: string[];
4747
}
4848

49+
export interface NotebookCellOutputMetadata {
50+
/**
51+
* Additional attributes of a cell metadata.
52+
*/
53+
custom?: { [key: string]: any };
54+
}
55+
4956
export interface CellDisplayOutput {
5057
outputKind: CellOutputKind.Rich;
5158
/**
@@ -66,6 +73,8 @@ declare module 'vscode' {
6673
* }
6774
*/
6875
data: { [key: string]: any };
76+
77+
readonly metadata?: NotebookCellOutputMetadata;
6978
}
7079

7180
export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput;
@@ -133,11 +142,10 @@ declare module 'vscode' {
133142
}
134143

135144
export interface NotebookCell {
145+
readonly notebook: NotebookDocument;
136146
readonly uri: Uri;
137147
readonly cellKind: CellKind;
138148
readonly document: TextDocument;
139-
// API remove `source` or doc it as shorthand for document.getText()
140-
readonly source: string;
141149
language: string;
142150
outputs: CellOutput[];
143151
metadata: NotebookCellMetadata;
@@ -185,6 +193,7 @@ declare module 'vscode' {
185193
export interface NotebookDocument {
186194
readonly uri: Uri;
187195
readonly fileName: string;
196+
readonly viewType: string;
188197
readonly isDirty: boolean;
189198
readonly cells: NotebookCell[];
190199
languages: string[];
@@ -287,6 +296,7 @@ declare module 'vscode' {
287296
export interface NotebookCellsChangeData {
288297
readonly start: number;
289298
readonly deletedCount: number;
299+
readonly deletedItems: NotebookCell[];
290300
readonly items: NotebookCell[];
291301
}
292302

@@ -384,12 +394,15 @@ declare module 'vscode' {
384394

385395
export const onDidOpenNotebookDocument: Event<NotebookDocument>;
386396
export const onDidCloseNotebookDocument: Event<NotebookDocument>;
397+
398+
/**
399+
* All currently known notebook documents.
400+
*/
401+
export const notebookDocuments: ReadonlyArray<NotebookDocument>;
402+
387403
export let visibleNotebookEditors: NotebookEditor[];
388404
export const onDidChangeVisibleNotebookEditors: Event<NotebookEditor[]>;
389405

390-
// remove activeNotebookDocument, now that there is activeNotebookEditor.document
391-
export let activeNotebookDocument: NotebookDocument | undefined;
392-
393406
export let activeNotebookEditor: NotebookEditor | undefined;
394407
export const onDidChangeActiveNotebookEditor: Event<NotebookEditor | undefined>;
395408
export const onDidChangeNotebookCells: Event<NotebookCellsChangeEvent>;

0 commit comments

Comments
 (0)