Allow for a pylance middleware that does exclusions based on isDocumentAllowed but doesn't change anything
This commit is contained in:
Родитель
883ee82068
Коммит
0d6523198b
|
@ -0,0 +1,59 @@
|
|||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"files.exclude": {
|
||||
"out": true, // set this to true to hide the "out" folder with the compiled JS files
|
||||
"**/*.pyc": true,
|
||||
".nyc_output": true,
|
||||
"obj": true,
|
||||
"bin": true,
|
||||
"**/__pycache__": true,
|
||||
"**/node_modules": false,
|
||||
".vscode-test": true,
|
||||
".vscode test": true,
|
||||
".venv": true,
|
||||
"**/.pytest_cache/**": true,
|
||||
"languageServer.*/**": true,
|
||||
"**/.mypy_cache/**": true,
|
||||
"**/.ropeproject/**": true
|
||||
},
|
||||
"search.exclude": {
|
||||
"out": true, // set this to false to include "out" folder in search results
|
||||
"**/node_modules": true,
|
||||
"coverage": true,
|
||||
"languageServer*/**": true,
|
||||
".vscode-test": true,
|
||||
".vscode test": true
|
||||
},
|
||||
"[python]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version
|
||||
"python.linting.enabled": false,
|
||||
"python.testing.promptToConfigure": false,
|
||||
"python.workspaceSymbols.enabled": false,
|
||||
"python.formatting.provider": "black",
|
||||
"typescript.preferences.quoteStyle": "single",
|
||||
"javascript.preferences.quoteStyle": "single",
|
||||
"typescriptHero.imports.stringQuoteStyle": "'",
|
||||
"prettier.printWidth": 120,
|
||||
"prettier.singleQuote": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true,
|
||||
"source.fixAll.tslint": true
|
||||
},
|
||||
"python.languageServer": "Pylance",
|
||||
"python.analysis.logLevel": "Trace",
|
||||
"python.linting.pylintEnabled": false,
|
||||
"python.linting.flake8Enabled": true,
|
||||
"python.linting.flake8Args": [
|
||||
// Match what black does.
|
||||
"--max-line-length=88"
|
||||
],
|
||||
"typescript.preferences.importModuleSpecifier": "relative"
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vscode/jupyter-lsp-middleware",
|
||||
"version": "0.2.17",
|
||||
"version": "0.2.18",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vscode/jupyter-lsp-middleware",
|
||||
"version": "0.2.17",
|
||||
"version": "0.2.18",
|
||||
"description": "VS Code Python Language Server Middleware for Jupyter Notebook",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
15
src/index.ts
15
src/index.ts
|
@ -6,6 +6,7 @@ import { LanguageClient, Middleware } from 'vscode-languageclient/node';
|
|||
import { IVSCodeNotebook } from './common/types';
|
||||
import { HidingMiddlewareAddon } from './hidingMiddlewareAddon';
|
||||
import { NotebookMiddlewareAddon } from './notebookMiddlewareAddon';
|
||||
import { PylanceMiddlewareAddon } from './pylanceMiddlewareAddon';
|
||||
|
||||
export type NotebookMiddleware = Middleware & Disposable & {
|
||||
stopWatching(notebook: NotebookDocument): void;
|
||||
|
@ -40,3 +41,17 @@ export function createNotebookMiddleware(
|
|||
isDocumentAllowed
|
||||
);
|
||||
}
|
||||
|
||||
export function createPylanceMiddleware(
|
||||
getClient: () => LanguageClient | undefined,
|
||||
pythonPath: string,
|
||||
isDocumentAllowed: (uri: Uri) => boolean
|
||||
): NotebookMiddleware {
|
||||
// LanguageClients are created per interpreter (as they start) with a selector for all notebooks
|
||||
// Middleware swallows all requests for notebooks that don't match itself (isDocumentAllowed returns false)
|
||||
return new PylanceMiddlewareAddon(
|
||||
getClient,
|
||||
pythonPath,
|
||||
isDocumentAllowed
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,577 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
import {
|
||||
CallHierarchyIncomingCall,
|
||||
CallHierarchyItem,
|
||||
CallHierarchyOutgoingCall,
|
||||
CancellationToken,
|
||||
CodeAction,
|
||||
CodeActionContext,
|
||||
CodeLens,
|
||||
Color,
|
||||
ColorInformation,
|
||||
ColorPresentation,
|
||||
Command,
|
||||
CompletionContext,
|
||||
CompletionItem,
|
||||
Declaration,
|
||||
Definition,
|
||||
DefinitionLink,
|
||||
Diagnostic,
|
||||
Disposable,
|
||||
DocumentHighlight,
|
||||
DocumentLink,
|
||||
DocumentSymbol,
|
||||
FoldingContext,
|
||||
FoldingRange,
|
||||
FormattingOptions,
|
||||
LinkedEditingRanges,
|
||||
Location,
|
||||
NotebookDocument,
|
||||
Position,
|
||||
Position as VPosition,
|
||||
ProviderResult,
|
||||
Range,
|
||||
SelectionRange,
|
||||
SemanticTokens,
|
||||
SemanticTokensEdits,
|
||||
SignatureHelp,
|
||||
SignatureHelpContext,
|
||||
SymbolInformation,
|
||||
TextDocument,
|
||||
TextEdit,
|
||||
Uri,
|
||||
WorkspaceEdit
|
||||
} from 'vscode';
|
||||
import {
|
||||
ConfigurationParams,
|
||||
ConfigurationRequest,
|
||||
DidCloseTextDocumentNotification,
|
||||
DidOpenTextDocumentNotification,
|
||||
HandleDiagnosticsSignature,
|
||||
LanguageClient,
|
||||
Middleware,
|
||||
PrepareRenameSignature,
|
||||
ProvideCodeActionsSignature,
|
||||
ProvideCodeLensesSignature,
|
||||
ProvideCompletionItemsSignature,
|
||||
ProvideDefinitionSignature,
|
||||
ProvideDocumentFormattingEditsSignature,
|
||||
ProvideDocumentHighlightsSignature,
|
||||
ProvideDocumentLinksSignature,
|
||||
ProvideDocumentRangeFormattingEditsSignature,
|
||||
ProvideDocumentSymbolsSignature,
|
||||
ProvideHoverSignature,
|
||||
ProvideOnTypeFormattingEditsSignature,
|
||||
ProvideReferencesSignature,
|
||||
ProvideRenameEditsSignature,
|
||||
ProvideSignatureHelpSignature,
|
||||
ProvideWorkspaceSymbolsSignature,
|
||||
ResolveCodeLensSignature,
|
||||
ResolveCompletionItemSignature,
|
||||
ResolveDocumentLinkSignature,
|
||||
ResponseError
|
||||
} from 'vscode-languageclient/node';
|
||||
|
||||
import { ProvideDeclarationSignature } from 'vscode-languageclient/lib/common/declaration';
|
||||
import { isThenable } from './common/utils';
|
||||
import { ProvideTypeDefinitionSignature } from 'vscode-languageclient/lib/common/typeDefinition';
|
||||
import { ProvideImplementationSignature } from 'vscode-languageclient/lib/common/implementation';
|
||||
import {
|
||||
ProvideDocumentColorsSignature,
|
||||
ProvideColorPresentationSignature
|
||||
} from 'vscode-languageclient/lib/common/colorProvider';
|
||||
import { ProvideFoldingRangeSignature } from 'vscode-languageclient/lib/common/foldingRange';
|
||||
import { ProvideSelectionRangeSignature } from 'vscode-languageclient/lib/common/selectionRange';
|
||||
import {
|
||||
PrepareCallHierarchySignature,
|
||||
CallHierarchyIncomingCallsSignature,
|
||||
CallHierarchyOutgoingCallsSignature
|
||||
} from 'vscode-languageclient/lib/common/callHierarchy';
|
||||
import {
|
||||
DocumentRangeSemanticTokensSignature,
|
||||
DocumentSemanticsTokensEditsSignature,
|
||||
DocumentSemanticsTokensSignature
|
||||
} from 'vscode-languageclient/lib/common/semanticTokens';
|
||||
import { ProvideLinkedEditingRangeSignature } from 'vscode-languageclient/lib/common/linkedEditingRange';
|
||||
|
||||
/**
|
||||
* This class is a temporary solution to handling intellisense and diagnostics in python based notebooks.
|
||||
*
|
||||
* It is responsible for sending requests to pylance if they are allowed.
|
||||
*/
|
||||
export class PylanceMiddlewareAddon implements Middleware, Disposable {
|
||||
constructor(
|
||||
private readonly getClient: () => LanguageClient | undefined,
|
||||
private readonly pythonPath: string,
|
||||
private readonly isDocumentAllowed: (uri: Uri) => boolean
|
||||
) {
|
||||
// Make sure a bunch of functions are bound to this. VS code can call them without a this context
|
||||
this.handleDiagnostics = this.handleDiagnostics.bind(this);
|
||||
this.didOpen = this.didOpen.bind(this);
|
||||
}
|
||||
|
||||
public workspace = {
|
||||
configuration: async (
|
||||
params: ConfigurationParams,
|
||||
token: CancellationToken,
|
||||
next: ConfigurationRequest.HandlerSignature
|
||||
) => {
|
||||
// Handle workspace/configuration requests.
|
||||
let settings = next(params, token);
|
||||
if (isThenable(settings)) {
|
||||
settings = await settings;
|
||||
}
|
||||
if (settings instanceof ResponseError) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
for (const [i, item] of params.items.entries()) {
|
||||
if (item.section === 'python') {
|
||||
settings[i].pythonPath = this.pythonPath;
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
};
|
||||
|
||||
public dispose(): void {
|
||||
// Nothing to dispose at the moment
|
||||
}
|
||||
|
||||
public stopWatching(notebook: NotebookDocument): void {
|
||||
// Close all of the cells. This should cause diags and other things to be cleared
|
||||
const client = this.getClient();
|
||||
if (client && notebook.cellCount > 0) {
|
||||
notebook.getCells().forEach((c) => {
|
||||
const params = client.code2ProtocolConverter.asCloseTextDocumentParams(c.document);
|
||||
client.sendNotification(DidCloseTextDocumentNotification.type, params);
|
||||
});
|
||||
|
||||
// Set the diagnostics to nothing for all the cells
|
||||
if (client.diagnostics) {
|
||||
notebook.getCells().forEach((c) => {
|
||||
client.diagnostics?.set(c.document.uri, []);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public startWatching(notebook: NotebookDocument): void {
|
||||
// We need to talk directly to the language client here.
|
||||
const client = this.getClient();
|
||||
|
||||
// Mimic a document open for all cells
|
||||
if (client && notebook.cellCount > 0) {
|
||||
notebook.getCells().forEach((c) => {
|
||||
this.didOpen(c.document, (ev) => {
|
||||
const params = client.code2ProtocolConverter.asOpenTextDocumentParams(ev);
|
||||
client.sendNotification(DidOpenTextDocumentNotification.type, params);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public didOpen(document: TextDocument, next: (ev: TextDocument) => void) {
|
||||
next(document);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
public provideCompletionItem(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
context: CompletionContext,
|
||||
token: CancellationToken,
|
||||
next: ProvideCompletionItemsSignature
|
||||
) {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, context, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
public provideHover(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
token: CancellationToken,
|
||||
next: ProvideHoverSignature
|
||||
) {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public resolveCompletionItem(
|
||||
item: CompletionItem,
|
||||
token: CancellationToken,
|
||||
next: ResolveCompletionItemSignature
|
||||
): ProviderResult<CompletionItem> {
|
||||
// Range should have already been remapped.
|
||||
|
||||
// TODO: What if the LS needs to read the range? It won't make sense. This might mean
|
||||
// doing this at the extension level is not possible.
|
||||
return next(item, token);
|
||||
}
|
||||
|
||||
public provideSignatureHelp(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
context: SignatureHelpContext,
|
||||
token: CancellationToken,
|
||||
next: ProvideSignatureHelpSignature
|
||||
): ProviderResult<SignatureHelp> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, context, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideDefinition(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
token: CancellationToken,
|
||||
next: ProvideDefinitionSignature
|
||||
): ProviderResult<Definition | DefinitionLink[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideReferences(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
options: {
|
||||
includeDeclaration: boolean;
|
||||
},
|
||||
token: CancellationToken,
|
||||
next: ProvideReferencesSignature
|
||||
): ProviderResult<Location[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, options, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideDocumentHighlights(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
token: CancellationToken,
|
||||
next: ProvideDocumentHighlightsSignature
|
||||
): ProviderResult<DocumentHighlight[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideDocumentSymbols(
|
||||
document: TextDocument,
|
||||
token: CancellationToken,
|
||||
next: ProvideDocumentSymbolsSignature
|
||||
): ProviderResult<SymbolInformation[] | DocumentSymbol[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideWorkspaceSymbols(
|
||||
query: string,
|
||||
token: CancellationToken,
|
||||
next: ProvideWorkspaceSymbolsSignature
|
||||
): ProviderResult<SymbolInformation[]> {
|
||||
// Is this one possible to check?
|
||||
return next(query, token);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public provideCodeActions(
|
||||
document: TextDocument,
|
||||
range: Range,
|
||||
context: CodeActionContext,
|
||||
token: CancellationToken,
|
||||
next: ProvideCodeActionsSignature
|
||||
): ProviderResult<(Command | CodeAction)[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, range, context, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public provideCodeLenses(
|
||||
document: TextDocument,
|
||||
token: CancellationToken,
|
||||
next: ProvideCodeLensesSignature
|
||||
): ProviderResult<CodeLens[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public resolveCodeLens(
|
||||
codeLens: CodeLens,
|
||||
token: CancellationToken,
|
||||
next: ResolveCodeLensSignature
|
||||
): ProviderResult<CodeLens> {
|
||||
// Range should have already been remapped.
|
||||
|
||||
// TODO: What if the LS needs to read the range? It won't make sense. This might mean
|
||||
// doing this at the extension level is not possible.
|
||||
return next(codeLens, token);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public provideDocumentFormattingEdits(
|
||||
document: TextDocument,
|
||||
options: FormattingOptions,
|
||||
token: CancellationToken,
|
||||
next: ProvideDocumentFormattingEditsSignature
|
||||
): ProviderResult<TextEdit[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, options, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public provideDocumentRangeFormattingEdits(
|
||||
document: TextDocument,
|
||||
range: Range,
|
||||
options: FormattingOptions,
|
||||
token: CancellationToken,
|
||||
next: ProvideDocumentRangeFormattingEditsSignature
|
||||
): ProviderResult<TextEdit[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, range, options, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public provideOnTypeFormattingEdits(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
ch: string,
|
||||
options: FormattingOptions,
|
||||
token: CancellationToken,
|
||||
next: ProvideOnTypeFormattingEditsSignature
|
||||
): ProviderResult<TextEdit[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, ch, options, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public provideRenameEdits(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
newName: string,
|
||||
token: CancellationToken,
|
||||
next: ProvideRenameEditsSignature
|
||||
): ProviderResult<WorkspaceEdit> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, newName, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public prepareRename(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
token: CancellationToken,
|
||||
next: PrepareRenameSignature
|
||||
): ProviderResult<
|
||||
| Range
|
||||
| {
|
||||
range: Range;
|
||||
placeholder: string;
|
||||
}
|
||||
> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public provideDocumentLinks(
|
||||
document: TextDocument,
|
||||
token: CancellationToken,
|
||||
next: ProvideDocumentLinksSignature
|
||||
): ProviderResult<DocumentLink[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, token);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
public resolveDocumentLink(
|
||||
link: DocumentLink,
|
||||
token: CancellationToken,
|
||||
next: ResolveDocumentLinkSignature
|
||||
): ProviderResult<DocumentLink> {
|
||||
// Range should have already been remapped.
|
||||
|
||||
// TODO: What if the LS needs to read the range? It won't make sense. This might mean
|
||||
// doing this at the extension level is not possible.
|
||||
return next(link, token);
|
||||
}
|
||||
|
||||
public handleDiagnostics(uri: Uri, diagnostics: Diagnostic[], next: HandleDiagnosticsSignature): void {
|
||||
if (this.shouldProvideIntellisense(uri)) {
|
||||
return next(uri, diagnostics);
|
||||
} else {
|
||||
// Swallow all other diagnostics
|
||||
next(uri, []);
|
||||
}
|
||||
}
|
||||
|
||||
public provideTypeDefinition(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
token: CancellationToken,
|
||||
next: ProvideTypeDefinitionSignature
|
||||
) {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideImplementation(
|
||||
document: TextDocument,
|
||||
position: VPosition,
|
||||
token: CancellationToken,
|
||||
next: ProvideImplementationSignature
|
||||
): ProviderResult<Definition | DefinitionLink[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideDocumentColors(
|
||||
document: TextDocument,
|
||||
token: CancellationToken,
|
||||
next: ProvideDocumentColorsSignature
|
||||
): ProviderResult<ColorInformation[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, token);
|
||||
}
|
||||
}
|
||||
public provideColorPresentations(
|
||||
color: Color,
|
||||
context: {
|
||||
document: TextDocument;
|
||||
range: Range;
|
||||
},
|
||||
token: CancellationToken,
|
||||
next: ProvideColorPresentationSignature
|
||||
): ProviderResult<ColorPresentation[]> {
|
||||
if (this.shouldProvideIntellisense(context.document.uri)) {
|
||||
return next(color, context, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideFoldingRanges(
|
||||
document: TextDocument,
|
||||
context: FoldingContext,
|
||||
token: CancellationToken,
|
||||
next: ProvideFoldingRangeSignature
|
||||
): ProviderResult<FoldingRange[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, context, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideDeclaration(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
token: CancellationToken,
|
||||
next: ProvideDeclarationSignature
|
||||
): ProviderResult<Declaration> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideSelectionRanges(
|
||||
document: TextDocument,
|
||||
positions: Position[],
|
||||
token: CancellationToken,
|
||||
next: ProvideSelectionRangeSignature
|
||||
): ProviderResult<SelectionRange[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, positions, token);
|
||||
}
|
||||
}
|
||||
|
||||
public prepareCallHierarchy(
|
||||
document: TextDocument,
|
||||
positions: Position,
|
||||
token: CancellationToken,
|
||||
next: PrepareCallHierarchySignature
|
||||
): ProviderResult<CallHierarchyItem | CallHierarchyItem[]> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, positions, token);
|
||||
}
|
||||
}
|
||||
public provideCallHierarchyIncomingCalls(
|
||||
item: CallHierarchyItem,
|
||||
token: CancellationToken,
|
||||
next: CallHierarchyIncomingCallsSignature
|
||||
): ProviderResult<CallHierarchyIncomingCall[]> {
|
||||
if (this.shouldProvideIntellisense(item.uri)) {
|
||||
return next(item, token);
|
||||
}
|
||||
}
|
||||
public provideCallHierarchyOutgoingCalls(
|
||||
item: CallHierarchyItem,
|
||||
token: CancellationToken,
|
||||
next: CallHierarchyOutgoingCallsSignature
|
||||
): ProviderResult<CallHierarchyOutgoingCall[]> {
|
||||
if (this.shouldProvideIntellisense(item.uri)) {
|
||||
return next(item, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideDocumentSemanticTokens(
|
||||
document: TextDocument,
|
||||
token: CancellationToken,
|
||||
next: DocumentSemanticsTokensSignature
|
||||
): ProviderResult<SemanticTokens> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, token);
|
||||
}
|
||||
}
|
||||
public provideDocumentSemanticTokensEdits(
|
||||
document: TextDocument,
|
||||
previousResultId: string,
|
||||
token: CancellationToken,
|
||||
next: DocumentSemanticsTokensEditsSignature
|
||||
): ProviderResult<SemanticTokensEdits | SemanticTokens> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, previousResultId, token);
|
||||
}
|
||||
}
|
||||
public provideDocumentRangeSemanticTokens(
|
||||
document: TextDocument,
|
||||
range: Range,
|
||||
token: CancellationToken,
|
||||
next: DocumentRangeSemanticTokensSignature
|
||||
): ProviderResult<SemanticTokens> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, range, token);
|
||||
}
|
||||
}
|
||||
|
||||
public provideLinkedEditingRange(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
token: CancellationToken,
|
||||
next: ProvideLinkedEditingRangeSignature
|
||||
): ProviderResult<LinkedEditingRanges> {
|
||||
if (this.shouldProvideIntellisense(document.uri)) {
|
||||
return next(document, position, token);
|
||||
}
|
||||
}
|
||||
|
||||
private shouldProvideIntellisense(uri: Uri): boolean {
|
||||
// Make sure document is allowed
|
||||
return this.isDocumentAllowed(uri);
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ import {
|
|||
ServerCapabilities,
|
||||
StaticFeature
|
||||
} from 'vscode-languageclient/node';
|
||||
import { createNotebookMiddleware, createHidingMiddleware } from '../..';
|
||||
import { createNotebookMiddleware, createHidingMiddleware, createPylanceMiddleware } from '../..';
|
||||
import { FileBasedCancellationStrategy } from '../../fileBasedCancellationStrategy';
|
||||
import * as uuid from 'uuid/v4';
|
||||
|
||||
|
@ -870,10 +870,40 @@ export class LanguageServer implements vscode.Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
export type MiddlewareType = 'pylance' | 'hiding' | 'notebook';
|
||||
|
||||
function createMiddleware(
|
||||
middlewareType: MiddlewareType,
|
||||
notebookApi: IVSCodeNotebook,
|
||||
getClient: () => LanguageClient | undefined,
|
||||
traceInfo: (...args: any[]) => void,
|
||||
cellSelector: DocumentSelector,
|
||||
notebookFileRegex: RegExp,
|
||||
pythonPath: string,
|
||||
isDocumentAllowed: (uri: vscode.Uri) => boolean
|
||||
) {
|
||||
switch (middlewareType) {
|
||||
case 'hiding':
|
||||
return createHidingMiddleware();
|
||||
case 'pylance':
|
||||
return createPylanceMiddleware(getClient, pythonPath, isDocumentAllowed);
|
||||
case 'notebook':
|
||||
return createNotebookMiddleware(
|
||||
notebookApi,
|
||||
getClient,
|
||||
traceInfo,
|
||||
cellSelector,
|
||||
notebookFileRegex,
|
||||
pythonPath,
|
||||
isDocumentAllowed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function startLanguageServer(
|
||||
outputChannel: string,
|
||||
languageServerFolder: string,
|
||||
hidingMiddleware: boolean,
|
||||
middlewareType: MiddlewareType,
|
||||
pythonPath: string,
|
||||
selector: DocumentSelector,
|
||||
shouldProvideIntellisense: (uri: vscode.Uri) => boolean
|
||||
|
@ -902,7 +932,8 @@ async function startLanguageServer(
|
|||
}
|
||||
};
|
||||
|
||||
const middleware = hidingMiddleware ? createHidingMiddleware() : createNotebookMiddleware(
|
||||
const middleware = createMiddleware(
|
||||
middlewareType,
|
||||
notebookApi,
|
||||
() => languageClient,
|
||||
traceInfo,
|
||||
|
@ -952,7 +983,7 @@ async function startLanguageServer(
|
|||
export async function createLanguageServer(
|
||||
outputChannel: string,
|
||||
selector: DocumentSelector,
|
||||
hidingMiddleware: boolean,
|
||||
middlewareType: MiddlewareType,
|
||||
shouldProvideIntellisense: (uri: vscode.Uri) => boolean
|
||||
): Promise<LanguageServer | undefined> {
|
||||
// Python should be installed too.
|
||||
|
@ -972,7 +1003,7 @@ export async function createLanguageServer(
|
|||
return startLanguageServer(
|
||||
outputChannel,
|
||||
path.join(pylance.extensionPath, 'dist'),
|
||||
hidingMiddleware,
|
||||
middlewareType,
|
||||
pythonPath,
|
||||
selector,
|
||||
shouldProvideIntellisense
|
||||
|
|
|
@ -3,15 +3,7 @@
|
|||
|
||||
/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
|
||||
import { assert } from 'chai';
|
||||
import {
|
||||
Position,
|
||||
Disposable,
|
||||
languages,
|
||||
Range,
|
||||
WorkspaceEdit,
|
||||
workspace,
|
||||
Uri
|
||||
} from 'vscode';
|
||||
import { Position, Disposable, languages, Range, WorkspaceEdit, workspace, Uri } from 'vscode';
|
||||
import { DocumentFilter } from 'vscode-languageserver-protocol';
|
||||
import {
|
||||
canRunNotebookTests,
|
||||
|
@ -56,7 +48,7 @@ suite('Hiding tests', function () {
|
|||
languageServer = await createLanguageServer(
|
||||
'lsp-middleware-test',
|
||||
NOTEBOOK_SELECTOR,
|
||||
true,
|
||||
'hiding',
|
||||
shouldProvideIntellisense
|
||||
);
|
||||
});
|
||||
|
|
|
@ -63,7 +63,7 @@ suite('Notebook tests', function () {
|
|||
languageServer = await createLanguageServer(
|
||||
'lsp-middleware-test',
|
||||
NOTEBOOK_SELECTOR,
|
||||
false,
|
||||
'notebook',
|
||||
shouldProvideIntellisense
|
||||
);
|
||||
});
|
||||
|
@ -230,7 +230,7 @@ suite('Notebook tests', function () {
|
|||
);
|
||||
});
|
||||
test('Make sure diags are skipped when not allowing', async function () {
|
||||
this.skip(); // Skip for now. Requires jupyter to not be providing intellisense too
|
||||
this.skip(); // Skip for now. Requires jupyter extension to not be providing intellisense too
|
||||
allowIntellisense = false;
|
||||
await insertCodeCell('import sys\nprint(sys.executable)');
|
||||
await insertCodeCell('import sys\nprint(sys.executable)');
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
|
||||
import { assert } from 'chai';
|
||||
import { Position, Disposable, languages, Range, WorkspaceEdit, workspace, Uri } from 'vscode';
|
||||
import { DocumentFilter } from 'vscode-languageserver-protocol';
|
||||
import {
|
||||
canRunNotebookTests,
|
||||
closeNotebooksAndCleanUpAfterTests,
|
||||
insertCodeCell,
|
||||
createEmptyPythonNotebook,
|
||||
traceInfo,
|
||||
createLanguageServer,
|
||||
focusCell,
|
||||
captureScreenShot,
|
||||
captureOutputMessages,
|
||||
LanguageServer,
|
||||
waitForDiagnostics
|
||||
} from './helper';
|
||||
|
||||
export const PYTHON_LANGUAGE = 'python';
|
||||
export const NotebookCellScheme = 'vscode-notebook-cell';
|
||||
export const InteractiveInputScheme = 'vscode-interactive-input';
|
||||
export const NOTEBOOK_SELECTOR: DocumentFilter[] = [
|
||||
{ scheme: NotebookCellScheme, language: PYTHON_LANGUAGE },
|
||||
{ scheme: InteractiveInputScheme, language: PYTHON_LANGUAGE }
|
||||
];
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any, no-invalid-this */
|
||||
suite('Pylance tests', function () {
|
||||
const disposables: Disposable[] = [];
|
||||
let languageServer: LanguageServer | undefined = undefined;
|
||||
let allowIntellisense = true;
|
||||
let emptyNotebookUri: Uri | undefined;
|
||||
const shouldProvideIntellisense = (uri: Uri) => {
|
||||
if (emptyNotebookUri?.fsPath === uri.fsPath) {
|
||||
return allowIntellisense;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
this.timeout(120_000);
|
||||
suiteSetup(async function () {
|
||||
this.timeout(120_000);
|
||||
if (!canRunNotebookTests()) {
|
||||
return this.skip();
|
||||
}
|
||||
languageServer = await createLanguageServer(
|
||||
'lsp-middleware-test',
|
||||
NOTEBOOK_SELECTOR,
|
||||
'pylance',
|
||||
shouldProvideIntellisense
|
||||
);
|
||||
});
|
||||
// Use same notebook without starting kernel in every single test (use one for whole suite).
|
||||
setup(async function () {
|
||||
traceInfo(`Start Test ${this.currentTest?.title}`);
|
||||
allowIntellisense = true;
|
||||
emptyNotebookUri = await createEmptyPythonNotebook(disposables);
|
||||
traceInfo(`Start Test (completed) ${this.currentTest?.title}`);
|
||||
});
|
||||
teardown(async function () {
|
||||
traceInfo(`Ended Test ${this.currentTest?.title}`);
|
||||
if (this.currentTest && this.currentTest.state === 'failed') {
|
||||
await captureScreenShot(this.currentTest.title);
|
||||
await captureOutputMessages();
|
||||
}
|
||||
await closeNotebooksAndCleanUpAfterTests(disposables);
|
||||
traceInfo(`Ended Test (completed) ${this.currentTest?.title}`);
|
||||
});
|
||||
suiteTeardown(async () => {
|
||||
closeNotebooksAndCleanUpAfterTests(disposables);
|
||||
await languageServer?.dispose();
|
||||
});
|
||||
test('Edit a cell and make sure diagnostics do show up', async () => {
|
||||
// Pylance should definitely be able to handle a single cell
|
||||
const cell = await insertCodeCell('import sys\nprint(sys.executable)\na = 1');
|
||||
// Should be no diagnostics yet
|
||||
let diagnostics = languages.getDiagnostics(cell.document.uri);
|
||||
assert.isEmpty(diagnostics, 'No diagnostics should be found in the first cell');
|
||||
|
||||
// Edit the cell
|
||||
await focusCell(cell);
|
||||
const edit = new WorkspaceEdit();
|
||||
edit.replace(cell.document.uri, new Range(new Position(0, 7), new Position(0, 10)), 'system');
|
||||
await workspace.applyEdit(edit);
|
||||
|
||||
// There should be diagnostics now
|
||||
await waitForDiagnostics(cell.document.uri);
|
||||
});
|
||||
});
|
|
@ -766,8 +766,9 @@ declare module 'vscode' {
|
|||
preserveFocus?: boolean;
|
||||
|
||||
/**
|
||||
* An optional flag that controls if an {@link TextEditor editor}-tab will be replaced
|
||||
* with the next editor or if it will be kept.
|
||||
* An optional flag that controls if an {@link TextEditor editor}-tab shows as preview. Preview tabs will
|
||||
* be replaced and reused until set to stay - either explicitly or through editing. The default behaviour depends
|
||||
* on the `workbench.editor.enablePreview`-setting.
|
||||
*/
|
||||
preview?: boolean;
|
||||
|
||||
|
@ -2566,11 +2567,12 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
/**
|
||||
* The MarkdownString represents human-readable text that supports formatting via the
|
||||
* markdown syntax. Standard markdown is supported, also tables, but no embedded html.
|
||||
* Human-readable text that supports formatting via the [markdown syntax](https://commonmark.org).
|
||||
*
|
||||
* Rendering of {@link ThemeIcon theme icons} via the `$(<name>)`-syntax is supported
|
||||
* when the {@linkcode MarkdownString.supportThemeIcons supportThemeIcons} is set to `true`.
|
||||
* when the {@linkcode supportThemeIcons} is set to `true`.
|
||||
*
|
||||
* Rendering of embedded html is supported when {@linkcode supportHtml} is set to `true`.
|
||||
*/
|
||||
export class MarkdownString {
|
||||
|
||||
|
@ -2591,7 +2593,7 @@ declare module 'vscode' {
|
|||
supportThemeIcons?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates that this markdown string can contain raw html tags. Defaults to false.
|
||||
* Indicates that this markdown string can contain raw html tags. Defaults to `false`.
|
||||
*
|
||||
* When `supportHtml` is false, the markdown renderer will strip out any raw html tags
|
||||
* that appear in the markdown text. This means you can only use markdown syntax for rendering.
|
||||
|
@ -3550,7 +3552,7 @@ declare module 'vscode' {
|
|||
*
|
||||
* This is the id that will be passed to `DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits` (if implemented).
|
||||
*/
|
||||
readonly resultId?: string;
|
||||
readonly resultId: string | undefined;
|
||||
/**
|
||||
* The actual tokens data.
|
||||
* @see {@link DocumentSemanticTokensProvider.provideDocumentSemanticTokens provideDocumentSemanticTokens} for an explanation of the format.
|
||||
|
@ -3570,7 +3572,7 @@ declare module 'vscode' {
|
|||
*
|
||||
* This is the id that will be passed to `DocumentSemanticTokensProvider.provideDocumentSemanticTokensEdits` (if implemented).
|
||||
*/
|
||||
readonly resultId?: string;
|
||||
readonly resultId: string | undefined;
|
||||
/**
|
||||
* The edits to the tokens data.
|
||||
* All edits refer to the initial data state.
|
||||
|
@ -3596,7 +3598,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* The elements to insert.
|
||||
*/
|
||||
readonly data?: Uint32Array;
|
||||
readonly data: Uint32Array | undefined;
|
||||
|
||||
constructor(start: number, deleteCount: number, data?: Uint32Array);
|
||||
}
|
||||
|
@ -5745,7 +5747,7 @@ declare module 'vscode' {
|
|||
* The priority of this item. Higher value means the item should
|
||||
* be shown more to the left.
|
||||
*/
|
||||
readonly priority?: number;
|
||||
readonly priority: number | undefined;
|
||||
|
||||
/**
|
||||
* The name of the entry, like 'Python Language Indicator', 'Git Status' etc.
|
||||
|
@ -5801,7 +5803,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Accessibility information used when a screen reader interacts with this StatusBar item
|
||||
*/
|
||||
accessibilityInformation?: AccessibilityInformation;
|
||||
accessibilityInformation: AccessibilityInformation | undefined;
|
||||
|
||||
/**
|
||||
* Shows the entry in the status bar.
|
||||
|
@ -8421,7 +8423,7 @@ declare module 'vscode' {
|
|||
|
||||
/**
|
||||
* The detected default shell for the extension host, this is overridden by the
|
||||
* `terminal.integrated.shell` setting for the extension host's platform. Note that in
|
||||
* `terminal.integrated.defaultProfile` setting for the extension host's platform. Note that in
|
||||
* environments that do not support a shell the value is the empty string.
|
||||
*/
|
||||
export const shell: string;
|
||||
|
@ -9723,6 +9725,8 @@ declare module 'vscode' {
|
|||
* Note writing `\n` will just move the cursor down 1 row, you need to write `\r` as well
|
||||
* to move the cursor to the left-most cell.
|
||||
*
|
||||
* Events fired before {@link Pseudoterminal.open} is called will be be ignored.
|
||||
*
|
||||
* **Example:** Write red text to the terminal
|
||||
* ```typescript
|
||||
* const writeEmitter = new vscode.EventEmitter<string>();
|
||||
|
@ -9748,6 +9752,8 @@ declare module 'vscode' {
|
|||
* bar). Set to `undefined` for the terminal to go back to the regular dimensions (fit to
|
||||
* the size of the panel).
|
||||
*
|
||||
* Events fired before {@link Pseudoterminal.open} is called will be be ignored.
|
||||
*
|
||||
* **Example:** Override the dimensions of a terminal to 20 columns and 10 rows
|
||||
* ```typescript
|
||||
* const dimensionsEmitter = new vscode.EventEmitter<vscode.TerminalDimensions>();
|
||||
|
@ -9770,6 +9776,8 @@ declare module 'vscode' {
|
|||
/**
|
||||
* An event that when fired will signal that the pty is closed and dispose of the terminal.
|
||||
*
|
||||
* Events fired before {@link Pseudoterminal.open} is called will be be ignored.
|
||||
*
|
||||
* A number can be used to provide an exit code for the terminal. Exit codes must be
|
||||
* positive and a non-zero exit codes signals failure which shows a notification for a
|
||||
* regular terminal and allows dependent tasks to proceed when used with the
|
||||
|
@ -9799,6 +9807,8 @@ declare module 'vscode' {
|
|||
/**
|
||||
* An event that when fired allows changing the name of the terminal.
|
||||
*
|
||||
* Events fired before {@link Pseudoterminal.open} is called will be be ignored.
|
||||
*
|
||||
* **Example:** Change the terminal name to "My new terminal".
|
||||
* ```typescript
|
||||
* const writeEmitter = new vscode.EventEmitter<string>();
|
||||
|
@ -10835,8 +10845,8 @@ declare module 'vscode' {
|
|||
* will be matched against the file paths of resulting matches relative to their workspace. Use a {@link RelativePattern relative pattern}
|
||||
* to restrict the search results to a {@link WorkspaceFolder workspace folder}.
|
||||
* @param exclude A {@link GlobPattern glob pattern} that defines files and folders to exclude. The glob pattern
|
||||
* will be matched against the file paths of resulting matches relative to their workspace. When `undefined`, default excludes and the user's
|
||||
* configured excludes will apply. When `null`, no excludes will apply.
|
||||
* will be matched against the file paths of resulting matches relative to their workspace. When `undefined`, default file-excludes (e.g. the `files.exclude`-setting
|
||||
* but not `search.exclude`) will apply. When `null`, no excludes will apply.
|
||||
* @param maxResults An upper-bound for the result.
|
||||
* @param token A token that can be used to signal cancellation to the underlying search engine.
|
||||
* @return A thenable that resolves to an array of resource identifiers. Will return no results if no
|
||||
|
@ -12733,8 +12743,9 @@ declare module 'vscode' {
|
|||
* The UI-visible count of {@link SourceControlResourceState resource states} of
|
||||
* this source control.
|
||||
*
|
||||
* Equals to the total number of {@link SourceControlResourceState resource state}
|
||||
* of this source control, if undefined.
|
||||
* If undefined, this source control will
|
||||
* - display its UI-visible count as zero, and
|
||||
* - contribute the count of its {@link SourceControlResourceState resource states} to the UI-visible aggregated count for all source controls
|
||||
*/
|
||||
count?: number;
|
||||
|
||||
|
@ -14101,7 +14112,7 @@ declare module 'vscode' {
|
|||
* Associated tag for the profile. If this is set, only {@link TestItem}
|
||||
* instances with the same tag will be eligible to execute in this profile.
|
||||
*/
|
||||
tag?: TestTag;
|
||||
tag: TestTag | undefined;
|
||||
|
||||
/**
|
||||
* If this method is present, a configuration gear will be present in the
|
||||
|
@ -14109,7 +14120,7 @@ declare module 'vscode' {
|
|||
* you can take other editor actions, such as showing a quick pick or
|
||||
* opening a configuration file.
|
||||
*/
|
||||
configureHandler?: () => void;
|
||||
configureHandler: (() => void) | undefined;
|
||||
|
||||
/**
|
||||
* Handler called to start a test run. When invoked, the function should call
|
||||
|
@ -14258,7 +14269,7 @@ declare module 'vscode' {
|
|||
* The process of running tests should resolve the children of any test
|
||||
* items who have not yet been resolved.
|
||||
*/
|
||||
readonly include?: TestItem[];
|
||||
readonly include: TestItem[] | undefined;
|
||||
|
||||
/**
|
||||
* An array of tests the user has marked as excluded from the test included
|
||||
|
@ -14267,14 +14278,14 @@ declare module 'vscode' {
|
|||
* May be omitted if no exclusions were requested. Test controllers should
|
||||
* not run excluded tests or any children of excluded tests.
|
||||
*/
|
||||
readonly exclude?: TestItem[];
|
||||
readonly exclude: TestItem[] | undefined;
|
||||
|
||||
/**
|
||||
* The profile used for this request. This will always be defined
|
||||
* for requests issued from the editor UI, though extensions may
|
||||
* programmatically create requests not associated with any profile.
|
||||
*/
|
||||
readonly profile?: TestRunProfile;
|
||||
readonly profile: TestRunProfile | undefined;
|
||||
|
||||
/**
|
||||
* @param tests Array of specific tests to run, or undefined to run all tests
|
||||
|
@ -14293,7 +14304,7 @@ declare module 'vscode' {
|
|||
* disambiguate multiple sets of results in a test run. It is useful if
|
||||
* tests are run across multiple platforms, for example.
|
||||
*/
|
||||
readonly name?: string;
|
||||
readonly name: string | undefined;
|
||||
|
||||
/**
|
||||
* A cancellation token which will be triggered when the test run is
|
||||
|
@ -14433,7 +14444,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* URI this `TestItem` is associated with. May be a file or directory.
|
||||
*/
|
||||
readonly uri?: Uri;
|
||||
readonly uri: Uri | undefined;
|
||||
|
||||
/**
|
||||
* The children of this test item. For a test suite, this may contain the
|
||||
|
@ -14446,7 +14457,7 @@ declare module 'vscode' {
|
|||
* top-level items in the {@link TestController.items} and for items that
|
||||
* aren't yet included in another item's {@link children}.
|
||||
*/
|
||||
readonly parent?: TestItem;
|
||||
readonly parent: TestItem | undefined;
|
||||
|
||||
/**
|
||||
* Tags associated with this test item. May be used in combination with
|
||||
|
@ -14488,7 +14499,7 @@ declare module 'vscode' {
|
|||
*
|
||||
* This is only meaningful if the `uri` points to a file.
|
||||
*/
|
||||
range?: Range;
|
||||
range: Range | undefined;
|
||||
|
||||
/**
|
||||
* Optional error encountered while loading the test.
|
||||
|
@ -14496,7 +14507,7 @@ declare module 'vscode' {
|
|||
* Note that this is not a test result and should only be used to represent errors in
|
||||
* test discovery, such as syntax errors.
|
||||
*/
|
||||
error?: string | MarkdownString;
|
||||
error: string | MarkdownString | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1575,6 +1575,10 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
export interface NotebookController {
|
||||
/**
|
||||
* The human-readable label used to categorise controllers.
|
||||
*/
|
||||
kind?: string;
|
||||
|
||||
// todo@API allow add, not remove
|
||||
readonly rendererScripts: NotebookRendererScript[];
|
||||
|
@ -1822,6 +1826,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* The text of the hint.
|
||||
*/
|
||||
// todo@API label?
|
||||
text: string;
|
||||
/**
|
||||
* The position of this hint.
|
||||
|
|
Загрузка…
Ссылка в новой задаче