Skip to content
Open
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
69 changes: 69 additions & 0 deletions client-node-tests/src/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2337,6 +2337,75 @@ suite('Full notebook tests', () => {
await revertAllDirty();
}).timeout(5000);

test('Notebook document: text changes refresh dependent cells without waiting for background pulls', async(): Promise<void> => {
const notebook = await vscode.workspace.openNotebookDocument('jupyter-notebook', new vscode.NotebookData([
new vscode.NotebookCellData(vscode.NotebookCellKind.Code, 'value = 1', 'python'),
new vscode.NotebookCellData(vscode.NotebookCellKind.Code, 'other = 2', 'python'),
new vscode.NotebookCellData(vscode.NotebookCellKind.Code, 'value + other', 'python'),
new vscode.NotebookCellData(vscode.NotebookCellKind.Code, 'const unrelated = 1;', 'javascript')
]));
const cellUris = new Set(notebook.getCells().map(cell => cell.document.uri.toString()));
const expected = notebook.getCells().slice(0, 3).map(cell => cell.document.uri.toString());
const opened = new Set<string>();
const pulled: string[] = [];
let observingChanges = false;
client.middleware.provideDiagnostics = async (document, previousResultId, token, next) => {
const uri = document instanceof vscode.Uri ? document.toString() : document.uri.toString();
if (observingChanges && cellUris.has(uri)) {
pulled.push(uri);
}
const result = await next(document, previousResultId, token);
if (!observingChanges && cellUris.has(uri)) {
opened.add(uri);
}
return result;
};

const runtime = lsclient.RAL();
// Hold background pulls so the assertion does not depend on machine speed.
lsclient.RAL.install({
...runtime,
timer: {
...runtime.timer,
setTimeout: (callback, milliseconds, ...args) => milliseconds === 500
? lsclient.Disposable.create(() => {})
: runtime.timer.setTimeout(callback, milliseconds, ...args)
}
});
let listener: vscode.Disposable | undefined;
let notificationTimeout: ReturnType<typeof setTimeout> | undefined;
try {
await vscode.window.showNotebookDocument(notebook);
const deadline = Date.now() + 3000;
while (opened.size < expected.length && Date.now() < deadline) {
await waitForNextTurn();
}
assert.deepStrictEqual([...opened].sort(), [...expected].sort());
await waitForNextTurn();
observingChanges = true;
const changed = new Promise<void>((resolve, reject) => {
notificationTimeout = setTimeout(() => reject(new Error('No notebook text change notification was sent')), 3000);
listener = client.getFeature(lsclient.NotebookDocumentSyncRegistrationType.method).onChangeNotificationSent(event => {
if (event.notebook === notebook && event.cells?.textContent?.length) {
resolve();
}
});
});
const edit = new vscode.WorkspaceEdit();
edit.insert(notebook.cellAt(0).document.uri, new vscode.Position(0, 0), '# changed\n');
assert.strictEqual(await vscode.workspace.applyEdit(edit), true);
await changed;
await waitForNextTurn();
assert.deepStrictEqual(pulled.sort(), [...expected].sort(), 'Pull each matching cell once, including unchanged dependent cells');
} finally {
clearTimeout(notificationTimeout);
listener?.dispose();
lsclient.RAL.install(runtime);
client.middleware.provideDiagnostics = undefined;
await revertAllDirty();
}
}).timeout(8000);

test('Notebook document: reordering cells pulls diagnostics', async(): Promise<void> => {
const notebook = await vscode.workspace.openNotebookDocument('jupyter-notebook', createNotebookData());
await vscode.window.showNotebookDocument(notebook);
Expand Down
8 changes: 4 additions & 4 deletions client/src/common/diagnostic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1045,10 +1045,10 @@ class DiagnosticFeatureProviderImpl implements DiagnosticProviderShape {
}
}

// Moving cells changes the order of the notebook without changing the text
// or the URIs of the cells. Cell order can change the diagnostics of other
// cells when the server reports inter file dependencies.
if (options.interFileDependencies && event.cells?.structure !== undefined) {
// Text edits and cell order changes can affect other cells when the server
// reports inter file dependencies. Refresh them together instead of waiting
// for the background scheduler's per-document delay.
if (options.interFileDependencies && (textEvents.length > 0 || event.cells?.structure !== undefined)) {
for (const cell of event.notebook.getCells()) {
// Cells pulled above for this event do not need a second pull.
if (matchesCell(cell) && !pulledUris.has(cell.document.uri.toString())) {
Expand Down