mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
- Jupyter completion item support was awaiting info before responding. Fix is to check if this is even a notebook cell first, then only await stuff if that's true
This commit is contained in:
@@ -11,22 +11,30 @@ import * as vscode from 'vscode';
|
|||||||
import { charCountToJsCountDiff, jsIndexToCharIndex } from './text';
|
import { charCountToJsCountDiff, jsIndexToCharIndex } from './text';
|
||||||
import { JupyterNotebookProvider } from '../jupyter/jupyterNotebookProvider';
|
import { JupyterNotebookProvider } from '../jupyter/jupyterNotebookProvider';
|
||||||
import { JupyterSessionManager } from '../jupyter/jupyterSessionManager';
|
import { JupyterSessionManager } from '../jupyter/jupyterSessionManager';
|
||||||
import { Deferred } from '../common/promise';
|
|
||||||
|
|
||||||
const timeoutMilliseconds = 4000;
|
const timeoutMilliseconds = 3000;
|
||||||
|
|
||||||
export class NotebookCompletionItemProvider implements vscode.CompletionItemProvider {
|
export class NotebookCompletionItemProvider implements vscode.CompletionItemProvider {
|
||||||
private _allDocuments: nb.NotebookDocument[];
|
|
||||||
private kernelDeferred = new Deferred<nb.IKernel>();
|
|
||||||
|
|
||||||
constructor(private _notebookProvider: JupyterNotebookProvider) {
|
constructor(private _notebookProvider: JupyterNotebookProvider) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext)
|
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext)
|
||||||
: vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
|
: vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
|
||||||
this._allDocuments = nb.notebookDocuments;
|
let info = this.findMatchingCell(document, nb.notebookDocuments);
|
||||||
let info = this.findMatchingCell(document);
|
if (!info || !this._notebookProvider) {
|
||||||
this.isNotConnected(document, info);
|
// No matching document found
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
return this.getCompletionItemsForNotebookCell(document, position, token, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getCompletionItemsForNotebookCell(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, info: INewIntellisenseInfo
|
||||||
|
): Promise<vscode.CompletionItem[] | vscode.CompletionList> {
|
||||||
|
info.kernel = await this.tryFindKernelForDocument(document, info);
|
||||||
|
if (!info.kernel) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
// Get completions, with cancellation on timeout or if cancel is requested.
|
// Get completions, with cancellation on timeout or if cancel is requested.
|
||||||
// Note that it's important we always return some value, or intellisense will never complete
|
// Note that it's important we always return some value, or intellisense will never complete
|
||||||
let promises = [this.requestCompletions(info, position, document), this.onCanceled(token), this.onTimeout(timeoutMilliseconds)];
|
let promises = [this.requestCompletions(info, position, document), this.onCanceled(token), this.onTimeout(timeoutMilliseconds)];
|
||||||
@@ -37,38 +45,29 @@ export class NotebookCompletionItemProvider implements vscode.CompletionItemProv
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private isNotConnected(document: vscode.TextDocument, info: INewIntellisenseInfo): void {
|
private async tryFindKernelForDocument(document: vscode.TextDocument, info: INewIntellisenseInfo): Promise<nb.IKernel> {
|
||||||
if (!info || !this._notebookProvider) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let notebookManager: nb.NotebookManager = undefined;
|
|
||||||
|
|
||||||
let kernel: nb.IKernel = undefined;
|
|
||||||
try {
|
try {
|
||||||
this._notebookProvider.getNotebookManager(document.uri).then(manager => {
|
let notebookManager = await this._notebookProvider.getNotebookManager(document.uri);
|
||||||
notebookManager = manager;
|
if (notebookManager) {
|
||||||
if (notebookManager) {
|
let sessionManager: JupyterSessionManager = <JupyterSessionManager>(notebookManager.sessionManager);
|
||||||
let sessionManager: JupyterSessionManager = <JupyterSessionManager>(notebookManager.sessionManager);
|
let sessions = sessionManager.listRunning();
|
||||||
let sessions = sessionManager.listRunning();
|
if (sessions && sessions.length > 0) {
|
||||||
if (sessions && sessions.length > 0) {
|
let session = sessions.find(session => session.path === info.notebook.uri.path);
|
||||||
let session = sessions.find(session => session.path === info.notebook.uri.path);
|
if (!session) {
|
||||||
if (!session) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
kernel = session.kernel;
|
|
||||||
}
|
}
|
||||||
|
return session.kernel;
|
||||||
}
|
}
|
||||||
this.kernelDeferred.resolve(kernel);
|
}
|
||||||
});
|
|
||||||
} catch {
|
} catch {
|
||||||
// If an exception occurs, swallow it currently
|
// If an exception occurs, swallow it currently
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private findMatchingCell(document: vscode.TextDocument): INewIntellisenseInfo {
|
private findMatchingCell(document: vscode.TextDocument, allDocuments: nb.NotebookDocument[]): INewIntellisenseInfo {
|
||||||
if (this._allDocuments && document) {
|
if (allDocuments && document) {
|
||||||
for (let doc of this._allDocuments) {
|
for (let doc of allDocuments) {
|
||||||
for (let cell of doc.cells) {
|
for (let cell of doc.cells) {
|
||||||
if (cell && cell.uri && cell.uri.path === document.uri.path) {
|
if (cell && cell.uri && cell.uri.path === document.uri.path) {
|
||||||
return {
|
return {
|
||||||
@@ -84,9 +83,7 @@ export class NotebookCompletionItemProvider implements vscode.CompletionItemProv
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async requestCompletions(info: INewIntellisenseInfo, position: vscode.Position, cellTextDocument: vscode.TextDocument): Promise<vscode.CompletionItem[]> {
|
private async requestCompletions(info: INewIntellisenseInfo, position: vscode.Position, cellTextDocument: vscode.TextDocument): Promise<vscode.CompletionItem[]> {
|
||||||
let kernel = await this.kernelDeferred.promise;
|
if (!info || !info.kernel || !info.kernel.supportsIntellisense || !info.kernel.isReady) {
|
||||||
this.kernelDeferred = new Deferred<nb.IKernel>();
|
|
||||||
if (!info || kernel === undefined || !kernel.supportsIntellisense || !kernel.isReady) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
let source = cellTextDocument.getText();
|
let source = cellTextDocument.getText();
|
||||||
@@ -94,7 +91,7 @@ export class NotebookCompletionItemProvider implements vscode.CompletionItemProv
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
let cursorPosition = this.toCursorPosition(position, source);
|
let cursorPosition = this.toCursorPosition(position, source);
|
||||||
let result = await kernel.requestComplete({
|
let result = await info.kernel.requestComplete({
|
||||||
code: source,
|
code: source,
|
||||||
cursor_pos: cursorPosition.adjustedPosition
|
cursor_pos: cursorPosition.adjustedPosition
|
||||||
});
|
});
|
||||||
@@ -197,4 +194,5 @@ export interface INewIntellisenseInfo {
|
|||||||
editorUri: string;
|
editorUri: string;
|
||||||
cell: nb.NotebookCell;
|
cell: nb.NotebookCell;
|
||||||
notebook: nb.NotebookDocument;
|
notebook: nb.NotebookDocument;
|
||||||
|
kernel?: nb.IKernel;
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,6 @@ export class JupyterController implements vscode.Disposable {
|
|||||||
this.apiWrapper.registerCommand(constants.jupyterConfigurePython, () => { return this.doConfigurePython(jupyterInstaller); });
|
this.apiWrapper.registerCommand(constants.jupyterConfigurePython, () => { return this.doConfigurePython(jupyterInstaller); });
|
||||||
|
|
||||||
let supportedFileFilter: vscode.DocumentFilter[] = [
|
let supportedFileFilter: vscode.DocumentFilter[] = [
|
||||||
{ scheme: 'file', language: '*' },
|
|
||||||
{ scheme: 'untitled', language: '*' }
|
{ scheme: 'untitled', language: '*' }
|
||||||
];
|
];
|
||||||
this.extensionContext.subscriptions.push(this.apiWrapper.registerCompletionItemProvider(supportedFileFilter, new NotebookCompletionItemProvider(notebookProvider)));
|
this.extensionContext.subscriptions.push(this.apiWrapper.registerCompletionItemProvider(supportedFileFilter, new NotebookCompletionItemProvider(notebookProvider)));
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ export class JupyterNotebookProvider implements nb.NotebookProvider {
|
|||||||
if (!notebookUri) {
|
if (!notebookUri) {
|
||||||
return Promise.reject(localize('errNotebookUriMissing', 'A notebook path is required'));
|
return Promise.reject(localize('errNotebookUriMissing', 'A notebook path is required'));
|
||||||
}
|
}
|
||||||
return this.doGetNotebookManager(notebookUri);
|
return Promise.resolve(this.doGetNotebookManager(notebookUri));
|
||||||
}
|
}
|
||||||
|
|
||||||
private doGetNotebookManager(notebookUri: vscode.Uri): Promise<nb.NotebookManager> {
|
private doGetNotebookManager(notebookUri: vscode.Uri): nb.NotebookManager {
|
||||||
let uriString = notebookUri.toString();
|
let uriString = notebookUri.toString();
|
||||||
let manager = this.managerTracker.get(uriString);
|
let manager = this.managerTracker.get(uriString);
|
||||||
if (!manager) {
|
if (!manager) {
|
||||||
@@ -38,7 +38,7 @@ export class JupyterNotebookProvider implements nb.NotebookProvider {
|
|||||||
manager = new JupyterNotebookManager(serverManager);
|
manager = new JupyterNotebookManager(serverManager);
|
||||||
this.managerTracker.set(uriString, manager);
|
this.managerTracker.set(uriString, manager);
|
||||||
}
|
}
|
||||||
return Promise.resolve(manager);
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNotebookClosed(notebookUri: vscode.Uri): void {
|
handleNotebookClosed(notebookUri: vscode.Uri): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user