mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-23 18:19:12 +01:00
Merge remote-tracking branch 'origin/master' into tyriar/link_providers
This commit is contained in:
@@ -46,7 +46,7 @@ import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ExtHostUrls } from 'vs/workbench/api/common/extHostUrls';
|
||||
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
|
||||
import { ExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
|
||||
import { IExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
|
||||
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { throwProposedApiError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
@@ -97,6 +97,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostLogService = accessor.get(ILogService);
|
||||
const extHostTunnelService = accessor.get(IExtHostTunnelService);
|
||||
const extHostApiDeprecation = accessor.get(IExtHostApiDeprecationService);
|
||||
const extHostWindow = accessor.get(IExtHostWindow);
|
||||
|
||||
// register addressable instances
|
||||
rpcProtocol.set(ExtHostContext.ExtHostLogService, <ExtHostLogServiceShape><any>extHostLogService);
|
||||
@@ -105,6 +106,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostTunnelService, extHostTunnelService);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostWindow, extHostWindow);
|
||||
|
||||
// automatically create and register addressable instances
|
||||
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations));
|
||||
@@ -131,7 +133,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
|
||||
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
||||
const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands, extHostDocuments));
|
||||
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
|
||||
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
||||
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
|
||||
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, initData.environment, extensionStoragePaths));
|
||||
|
||||
@@ -108,7 +108,7 @@ export interface IConfigurationInitData extends IConfigurationData {
|
||||
}
|
||||
|
||||
export interface IExtHostContext extends IRPCProtocol {
|
||||
remoteAuthority: string;
|
||||
remoteAuthority: string | null;
|
||||
}
|
||||
|
||||
export interface IMainContext extends IRPCProtocol {
|
||||
@@ -712,6 +712,9 @@ export interface MainThreadNotebookShape extends IDisposable {
|
||||
$updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata | undefined): Promise<void>;
|
||||
$spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void>;
|
||||
$postMessage(handle: number, value: any): Promise<boolean>;
|
||||
|
||||
$onDidEdit(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
|
||||
$onContentChange(resource: UriComponents, viewType: string): void;
|
||||
}
|
||||
|
||||
export interface MainThreadUrlsShape extends IDisposable {
|
||||
@@ -776,7 +779,8 @@ export interface MainThreadTaskShape extends IDisposable {
|
||||
$registerTaskProvider(handle: number, type: string): Promise<void>;
|
||||
$unregisterTaskProvider(handle: number): Promise<void>;
|
||||
$fetchTasks(filter?: tasks.TaskFilterDTO): Promise<tasks.TaskDTO[]>;
|
||||
$executeTask(task: tasks.TaskHandleDTO | tasks.TaskDTO): Promise<tasks.TaskExecutionDTO>;
|
||||
$getTaskExecution(value: tasks.TaskHandleDTO | tasks.TaskDTO): Promise<tasks.TaskExecutionDTO>;
|
||||
$executeTask(task: tasks.TaskDTO): Promise<tasks.TaskExecutionDTO>;
|
||||
$terminateTask(id: string): Promise<void>;
|
||||
$registerTaskSystem(scheme: string, info: tasks.TaskSystemInfoDTO): void;
|
||||
$customExecutionComplete(id: string, result?: number): Promise<void>;
|
||||
@@ -1597,11 +1601,11 @@ export interface INotebookDocumentsAndEditorsDelta {
|
||||
|
||||
export interface ExtHostNotebookShape {
|
||||
$resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise<NotebookDataDto | undefined>;
|
||||
$resolveNotebookEditor(viewType: string, uri: UriComponents, editorId: string): Promise<void>;
|
||||
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
|
||||
$executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
|
||||
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;
|
||||
$saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean>;
|
||||
$revert(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise<void>;
|
||||
$backup(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise<string | undefined>;
|
||||
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
|
||||
$renderOutputs(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<UriComponents>): Promise<IOutputRenderResponse<UriComponents> | undefined>;
|
||||
@@ -1610,6 +1614,9 @@ export interface ExtHostNotebookShape {
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void;
|
||||
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void;
|
||||
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): Promise<void>;
|
||||
$undoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise<void>;
|
||||
$redoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise<void>;
|
||||
|
||||
}
|
||||
|
||||
export interface ExtHostStorageShape {
|
||||
|
||||
@@ -25,6 +25,7 @@ import { joinPath } from 'vs/base/common/resources';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { Cache } from './cache';
|
||||
|
||||
interface IObservable<T> {
|
||||
proxy: T;
|
||||
@@ -250,6 +251,43 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
|
||||
private _backup?: vscode.NotebookDocumentBackup;
|
||||
|
||||
|
||||
private readonly _edits = new Cache<vscode.NotebookDocumentEditEvent>('notebook documents');
|
||||
|
||||
|
||||
addEdit(item: vscode.NotebookDocumentEditEvent): number {
|
||||
return this._edits.add([item]);
|
||||
}
|
||||
|
||||
async undo(editId: number, isDirty: boolean): Promise<void> {
|
||||
await this.getEdit(editId).undo();
|
||||
// if (!isDirty) {
|
||||
// this.disposeBackup();
|
||||
// }
|
||||
}
|
||||
|
||||
async redo(editId: number, isDirty: boolean): Promise<void> {
|
||||
await this.getEdit(editId).redo();
|
||||
// if (!isDirty) {
|
||||
// this.disposeBackup();
|
||||
// }
|
||||
}
|
||||
|
||||
private getEdit(editId: number): vscode.NotebookDocumentEditEvent {
|
||||
const edit = this._edits.get(editId, 0);
|
||||
if (!edit) {
|
||||
throw new Error('No edit found');
|
||||
}
|
||||
|
||||
return edit;
|
||||
}
|
||||
|
||||
disposeEdits(editIds: number[]): void {
|
||||
for (const id of editIds) {
|
||||
this._edits.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
private _disposed = false;
|
||||
|
||||
constructor(
|
||||
@@ -515,6 +553,30 @@ export class NotebookEditorCellEditBuilder implements vscode.NotebookEditorCellE
|
||||
}
|
||||
}
|
||||
|
||||
class ExtHostWebviewComm extends Disposable {
|
||||
|
||||
onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
|
||||
|
||||
constructor(
|
||||
readonly id: string,
|
||||
public uri: URI,
|
||||
private _proxy: MainThreadNotebookShape,
|
||||
private _onDidReceiveMessage: Emitter<any>,
|
||||
private _webviewInitData: WebviewInitData,
|
||||
public document: ExtHostNotebookDocument,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async postMessage(message: any): Promise<boolean> {
|
||||
return this._proxy.$postMessage(this.document.handle, message);
|
||||
}
|
||||
|
||||
asWebviewUri(localResource: vscode.Uri): vscode.Uri {
|
||||
return asWebviewUri(this._webviewInitData, this.id, localResource);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostNotebookEditor extends Disposable implements vscode.NotebookEditor {
|
||||
private _viewColumn: vscode.ViewColumn | undefined;
|
||||
|
||||
@@ -548,6 +610,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
|
||||
private _onDidDispose = new Emitter<void>();
|
||||
readonly onDidDispose: Event<void> = this._onDidDispose.event;
|
||||
private _onDidReceiveMessage = new Emitter<any>();
|
||||
onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
|
||||
|
||||
constructor(
|
||||
@@ -555,8 +618,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
readonly id: string,
|
||||
public uri: URI,
|
||||
private _proxy: MainThreadNotebookShape,
|
||||
private _onDidReceiveMessage: Emitter<any>,
|
||||
private _webviewInitData: WebviewInitData,
|
||||
private _webComm: ExtHostWebviewComm,
|
||||
public document: ExtHostNotebookDocument,
|
||||
private _documentsAndEditors: ExtHostDocumentsAndEditors
|
||||
) {
|
||||
@@ -582,6 +644,10 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this._webComm.onDidReceiveMessage(e => {
|
||||
this._onDidReceiveMessage.fire(e);
|
||||
}));
|
||||
}
|
||||
|
||||
edit(callback: (editBuilder: NotebookEditorCellEditBuilder) => void): Thenable<boolean> {
|
||||
@@ -641,11 +707,11 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
}
|
||||
|
||||
async postMessage(message: any): Promise<boolean> {
|
||||
return this._proxy.$postMessage(this.document.handle, message);
|
||||
return this._webComm.postMessage(message);
|
||||
}
|
||||
|
||||
asWebviewUri(localResource: vscode.Uri): vscode.Uri {
|
||||
return asWebviewUri(this._webviewInitData, this.id, localResource);
|
||||
return this._webComm.asWebviewUri(localResource);
|
||||
}
|
||||
dispose() {
|
||||
this._onDidDispose.fire();
|
||||
@@ -666,8 +732,8 @@ export class ExtHostNotebookOutputRenderer {
|
||||
}
|
||||
|
||||
matches(mimeType: string): boolean {
|
||||
if (this.filter.subTypes) {
|
||||
if (this.filter.subTypes.indexOf(mimeType) >= 0) {
|
||||
if (this.filter.mimeTypes) {
|
||||
if (this.filter.mimeTypes.indexOf(mimeType) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -692,7 +758,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
private readonly _notebookKernels = new Map<string, { readonly kernel: vscode.NotebookKernel, readonly extension: IExtensionDescription; }>();
|
||||
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
|
||||
private readonly _unInitializedDocuments = new Map<string, ExtHostNotebookDocument>();
|
||||
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }>();
|
||||
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor }>();
|
||||
private readonly _webviewComm = new Map<string, { comm: ExtHostWebviewComm, onDidReceiveMessage: Emitter<any> }>();
|
||||
private readonly _notebookOutputRenderers = new Map<string, ExtHostNotebookOutputRenderer>();
|
||||
private readonly _onDidChangeNotebookCells = new Emitter<vscode.NotebookCellsChangeEvent>();
|
||||
readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
|
||||
@@ -871,12 +938,26 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
this._notebookContentProviders.set(viewType, { extension, provider });
|
||||
|
||||
const listener = provider.onDidChangeNotebook
|
||||
? provider.onDidChangeNotebook(e => this._proxy.$onNotebookChange(viewType, e.document.uri))
|
||||
? provider.onDidChangeNotebook(e => {
|
||||
const document = this._documents.get(URI.revive(e.document.uri).toString());
|
||||
|
||||
if (!document) {
|
||||
throw new Error(`Notebook document ${e.document.uri.toString()} not found`);
|
||||
}
|
||||
|
||||
if (isEditEvent(e)) {
|
||||
const editId = document.addEdit(e);
|
||||
this._proxy.$onDidEdit(e.document.uri, viewType, editId, e.label);
|
||||
} else {
|
||||
this._proxy.$onContentChange(e.document.uri, viewType);
|
||||
}
|
||||
})
|
||||
: Disposable.None;
|
||||
|
||||
const supportBackup = !!provider.backupNotebook && !!provider.revertNotebook;
|
||||
const supportBackup = !!provider.backupNotebook;
|
||||
|
||||
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType, supportBackup, provider.kernel ? { id: viewType, label: provider.kernel.label, extensionLocation: extension.extensionLocation, preloads: provider.kernel.preloads } : undefined);
|
||||
|
||||
return new extHostTypes.Disposable(() => {
|
||||
listener.dispose();
|
||||
this._notebookContentProviders.delete(viewType);
|
||||
@@ -946,6 +1027,30 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
return;
|
||||
}
|
||||
|
||||
async $resolveNotebookEditor(viewType: string, uri: UriComponents, editorId: string): Promise<void> {
|
||||
const provider = this._notebookContentProviders.get(viewType);
|
||||
const revivedUri = URI.revive(uri);
|
||||
const document = this._documents.get(revivedUri.toString());
|
||||
if (!document || !provider) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!provider.provider.resolveNotebook) {
|
||||
return;
|
||||
}
|
||||
|
||||
let webComm = this._webviewComm.get(editorId)?.comm;
|
||||
|
||||
if (webComm) {
|
||||
await provider.provider.resolveNotebook(document, webComm);
|
||||
} else {
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
webComm = new ExtHostWebviewComm(editorId, revivedUri, this._proxy, onDidReceiveMessage, this._webviewInitData, document);
|
||||
this._webviewComm.set(editorId, { comm: webComm, onDidReceiveMessage });
|
||||
await provider.provider.resolveNotebook(document, webComm);
|
||||
}
|
||||
}
|
||||
|
||||
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
|
||||
let document = this._documents.get(URI.revive(uri).toString());
|
||||
|
||||
@@ -1027,16 +1132,26 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
return false;
|
||||
}
|
||||
|
||||
async $revert(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise<void> {
|
||||
async $undoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise<void> {
|
||||
const document = this._documents.get(URI.revive(uri).toString());
|
||||
const provider = this._notebookContentProviders.get(viewType);
|
||||
|
||||
if (document && provider && provider.provider.revertNotebook) {
|
||||
await provider.provider.revertNotebook(document, cancellation);
|
||||
document.disposeBackup();
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.undo(editId, isDirty);
|
||||
|
||||
}
|
||||
|
||||
async $redoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise<void> {
|
||||
const document = this._documents.get(URI.revive(uri).toString());
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.redo(editId, isDirty);
|
||||
}
|
||||
|
||||
|
||||
async $backup(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise<string | undefined> {
|
||||
const document = this._documents.get(URI.revive(uri).toString());
|
||||
const provider = this._notebookContentProviders.get(viewType);
|
||||
@@ -1057,7 +1172,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
// TODO: remove document - editor one on one mapping
|
||||
private _getEditorFromURI(uriComponents: UriComponents) {
|
||||
const uriStr = URI.revive(uriComponents).toString();
|
||||
let editor: { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; } | undefined;
|
||||
let editor: { editor: ExtHostNotebookEditor } | undefined;
|
||||
this._editors.forEach(e => {
|
||||
if (e.editor.uri.toString() === uriStr) {
|
||||
editor = e;
|
||||
@@ -1068,10 +1183,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
}
|
||||
|
||||
$onDidReceiveMessage(editorId: string, message: any): void {
|
||||
let editor = this._editors.get(editorId);
|
||||
let messageEmitter = this._webviewComm.get(editorId)?.onDidReceiveMessage;
|
||||
|
||||
if (editor) {
|
||||
editor.onDidReceiveMessage.fire(message);
|
||||
if (messageEmitter) {
|
||||
messageEmitter.fire(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1110,16 +1225,21 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
}
|
||||
|
||||
private _createExtHostEditor(document: ExtHostNotebookDocument, editorId: string, selections: number[]) {
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
const revivedUri = document.uri;
|
||||
let webComm = this._webviewComm.get(editorId)?.comm;
|
||||
|
||||
if (!webComm) {
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
webComm = new ExtHostWebviewComm(editorId, revivedUri, this._proxy, onDidReceiveMessage, this._webviewInitData, document);
|
||||
this._webviewComm.set(editorId, { comm: webComm!, onDidReceiveMessage });
|
||||
}
|
||||
|
||||
let editor = new ExtHostNotebookEditor(
|
||||
document.viewType,
|
||||
editorId,
|
||||
revivedUri,
|
||||
this._proxy,
|
||||
onDidReceiveMessage,
|
||||
this._webviewInitData,
|
||||
webComm,
|
||||
document,
|
||||
this._documentsAndEditors
|
||||
);
|
||||
@@ -1135,7 +1255,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
|
||||
this._editors.get(editorId)?.editor.dispose();
|
||||
|
||||
this._editors.set(editorId, { editor, onDidReceiveMessage });
|
||||
this._editors.set(editorId, { editor });
|
||||
}
|
||||
|
||||
async $acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta) {
|
||||
@@ -1156,7 +1276,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
[...this._editors.values()].forEach((e) => {
|
||||
if (e.editor.uri.toString() === revivedUriStr) {
|
||||
e.editor.dispose();
|
||||
e.onDidReceiveMessage.dispose();
|
||||
this._editors.delete(e.editor.id);
|
||||
editorChanged = true;
|
||||
}
|
||||
@@ -1239,7 +1358,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
});
|
||||
}
|
||||
|
||||
const removedEditors: { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }[] = [];
|
||||
const removedEditors: { editor: ExtHostNotebookEditor }[] = [];
|
||||
|
||||
if (delta.removedEditors) {
|
||||
delta.removedEditors.forEach(editorid => {
|
||||
@@ -1261,7 +1380,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
if (editorChanged) {
|
||||
removedEditors.forEach(e => {
|
||||
e.editor.dispose();
|
||||
e.onDidReceiveMessage.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1307,3 +1425,8 @@ function hashPath(resource: URI): string {
|
||||
const str = resource.scheme === Schemas.file || resource.scheme === Schemas.untitled ? resource.fsPath : resource.toString();
|
||||
return hash(str) + '';
|
||||
}
|
||||
|
||||
function isEditEvent(e: vscode.NotebookDocumentEditEvent | vscode.NotebookDocumentContentChangeEvent): e is vscode.NotebookDocumentEditEvent {
|
||||
return typeof (e as vscode.NotebookDocumentEditEvent).undo === 'function'
|
||||
&& typeof (e as vscode.NotebookDocumentEditEvent).redo === 'function';
|
||||
}
|
||||
|
||||
@@ -12,14 +12,17 @@ import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { score } from 'vs/editor/common/modes/languageSelector';
|
||||
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { basename } from 'vs/base/common/resources';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { ExtHostDocumentLine } from 'vs/workbench/api/common/extHostDocumentData';
|
||||
|
||||
export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextDocument {
|
||||
export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextDocument, vscode.TextDocument {
|
||||
|
||||
private _disposables = new DisposableStore();
|
||||
private _isClosed = false;
|
||||
|
||||
private _cells!: ExtHostCell[];
|
||||
private _cellByUri!: ResourceMap<number>;
|
||||
private _cellLengths!: PrefixSumComputer;
|
||||
private _cellLines!: PrefixSumComputer;
|
||||
private _versionId = 0;
|
||||
@@ -27,17 +30,27 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
private readonly _onDidChange = new Emitter<void>();
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
readonly uri: vscode.Uri;
|
||||
readonly fileName: string;
|
||||
readonly languageId: string;
|
||||
readonly isUntitled: boolean = false;
|
||||
readonly isDirty: boolean = false;
|
||||
|
||||
constructor(
|
||||
extHostNotebooks: ExtHostNotebookController,
|
||||
extHostDocuments: ExtHostDocuments,
|
||||
private readonly _notebook: vscode.NotebookDocument,
|
||||
private readonly _selector: vscode.DocumentSelector | undefined,
|
||||
) {
|
||||
this.uri = _notebook.uri.with({ scheme: 'vscode-notebook-concat-doc' });
|
||||
this.fileName = basename(this.uri);
|
||||
this.languageId = this._createLanguageId();
|
||||
|
||||
this._init();
|
||||
|
||||
this._disposables.add(extHostDocuments.onDidChangeDocument(e => {
|
||||
let cellIdx = this._cells.findIndex(cell => isEqual(cell.uri, e.document.uri));
|
||||
if (cellIdx >= 0) {
|
||||
const cellIdx = this._cellByUri.get(e.document.uri);
|
||||
if (typeof cellIdx === 'number') {
|
||||
this._cellLengths.changeValue(cellIdx, this._cells[cellIdx].document.getText().length + 1);
|
||||
this._cellLines.changeValue(cellIdx, this._cells[cellIdx].document.lineCount);
|
||||
this._versionId += 1;
|
||||
@@ -68,10 +81,12 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
|
||||
private _init() {
|
||||
this._cells = [];
|
||||
this._cellByUri = new ResourceMap();
|
||||
const cellLengths: number[] = [];
|
||||
const cellLineCounts: number[] = [];
|
||||
for (let cell of this._notebook.cells) {
|
||||
if (cell.cellKind === CellKind.Code && (!this._selector || score(this._selector, cell.uri, cell.language, true))) {
|
||||
this._cellByUri.set(cell.uri, this._cells.length);
|
||||
this._cells.push(<ExtHostCell>cell);
|
||||
cellLengths.push(cell.document.getText().length + 1);
|
||||
cellLineCounts.push(cell.document.lineCount);
|
||||
@@ -81,6 +96,67 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
this._cellLines = new PrefixSumComputer(new Uint32Array(cellLineCounts));
|
||||
}
|
||||
|
||||
private _createLanguageId(): string {
|
||||
const languageIds = new Set<string>();
|
||||
(function fillInLanguageIds(selector: vscode.DocumentSelector | undefined) {
|
||||
if (Array.isArray(selector)) {
|
||||
selector.forEach(fillInLanguageIds);
|
||||
} else if (typeof selector === 'string') {
|
||||
languageIds.add(selector);
|
||||
} else if (selector?.language) {
|
||||
languageIds.add(selector.language);
|
||||
}
|
||||
})(this._selector);
|
||||
|
||||
if (languageIds.size === 0) {
|
||||
return 'unknown';
|
||||
}
|
||||
return [...languageIds.values()].sort().join(';');
|
||||
}
|
||||
|
||||
save(): Thenable<boolean> {
|
||||
// todo@jrieken throw error instead?
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
get eol(): vscode.EndOfLine {
|
||||
return types.EndOfLine.LF;
|
||||
}
|
||||
|
||||
get lineCount(): number {
|
||||
let total = 0;
|
||||
for (let cell of this._cells) {
|
||||
total += cell.document.lineCount;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
lineAt(lineOrPosition: number | vscode.Position): vscode.TextLine {
|
||||
const line = typeof lineOrPosition === 'number' ? lineOrPosition : lineOrPosition.line;
|
||||
const cellIdx = this._cellLines.getIndexOf(line);
|
||||
return new ExtHostDocumentLine(
|
||||
line,
|
||||
this._cells[cellIdx.index].document.lineAt(cellIdx.remainder).text,
|
||||
line >= this.lineCount
|
||||
);
|
||||
}
|
||||
|
||||
getWordRangeAtPosition(position: vscode.Position, regex?: RegExp | undefined): vscode.Range | undefined {
|
||||
const cellIdx = this._cellLines.getIndexOf(position.line);
|
||||
return this._cells[cellIdx.index].document.getWordRangeAtPosition(position.with({ line: cellIdx.remainder }), regex);
|
||||
}
|
||||
|
||||
validateRange(range: vscode.Range): vscode.Range {
|
||||
const start = this.validatePosition(range.start);
|
||||
const end = this.validatePosition(range.end);
|
||||
return range.with({ start, end });
|
||||
}
|
||||
|
||||
validatePosition(position: vscode.Position): vscode.Position {
|
||||
const cellIdx = this._cellLines.getIndexOf(position.line);
|
||||
return this._cells[cellIdx.index].document.validatePosition(position.with({ line: cellIdx.remainder }));
|
||||
}
|
||||
|
||||
get version(): number {
|
||||
return this._versionId;
|
||||
}
|
||||
@@ -103,8 +179,8 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
// get start and end locations and create substrings
|
||||
const start = this.locationAt(range.start);
|
||||
const end = this.locationAt(range.end);
|
||||
const startCell = this._cells.find(cell => isEqual(cell.uri, start.uri));
|
||||
const endCell = this._cells.find(cell => isEqual(cell.uri, end.uri));
|
||||
const startCell = this._cells[this._cellByUri.get(start.uri) ?? -1];
|
||||
const endCell = this._cells[this._cellByUri.get(end.uri) ?? -1];
|
||||
|
||||
if (!startCell || !endCell) {
|
||||
return '';
|
||||
@@ -131,8 +207,8 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
|
||||
return this._cells[idx.index].document.positionAt(idx.remainder).translate(lineCount);
|
||||
}
|
||||
|
||||
const idx = this._cells.findIndex(cell => isEqual(cell.uri, locationOrOffset.uri));
|
||||
if (idx >= 0) {
|
||||
const idx = this._cellByUri.get(locationOrOffset.uri);
|
||||
if (typeof idx === 'number') {
|
||||
let line = this._cellLines.getAccumulatedValue(idx - 1);
|
||||
return new types.Position(line + locationOrOffset.range.start.line, locationOrOffset.range.start.character);
|
||||
}
|
||||
|
||||
@@ -706,7 +706,7 @@ export class WorkerExtHostTask extends ExtHostTaskBase {
|
||||
public async executeTask(extension: IExtensionDescription, task: vscode.Task): Promise<vscode.TaskExecution> {
|
||||
const dto = TaskDTO.from(task, extension);
|
||||
if (dto === undefined) {
|
||||
return Promise.reject(new Error('Task is not valid'));
|
||||
throw new Error('Task is not valid');
|
||||
}
|
||||
|
||||
// If this task is a custom execution, then we need to save it away
|
||||
@@ -718,7 +718,10 @@ export class WorkerExtHostTask extends ExtHostTaskBase {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task));
|
||||
// Always get the task execution first to prevent timing issues when retrieving it later
|
||||
const execution = await this.getTaskExecution(await this._proxy.$getTaskExecution(dto), task);
|
||||
this._proxy.$executeTask(dto).catch(error => { throw new Error(error); });
|
||||
return execution;
|
||||
}
|
||||
|
||||
protected provideTasksInternal(validTypes: { [key: string]: boolean; }, taskIdPromises: Promise<void>[], handler: HandlerData, value: vscode.Task[] | null | undefined): { tasks: tasks.TaskDTO[], extension: IExtensionDescription } {
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostWindowShape, MainContext, MainThreadWindowShape, IMainContext, IOpenUriOptions } from './extHost.protocol';
|
||||
import { ExtHostWindowShape, MainContext, MainThreadWindowShape, IOpenUriOptions } from './extHost.protocol';
|
||||
import { WindowState } from 'vscode';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
|
||||
export class ExtHostWindow implements ExtHostWindowShape {
|
||||
export class ExtHostWindow implements IExtHostWindow {
|
||||
|
||||
private static InitialState: WindowState = {
|
||||
focused: true
|
||||
@@ -24,8 +26,8 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
||||
private _state = ExtHostWindow.InitialState;
|
||||
get state(): WindowState { return this._state; }
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadWindow);
|
||||
constructor(@IExtHostRpcService extHostRpc: IExtHostRpcService) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadWindow);
|
||||
this._proxy.$getWindowVisibility().then(isFocused => this.$onDidChangeWindowFocus(isFocused));
|
||||
}
|
||||
|
||||
@@ -67,3 +69,6 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
||||
return URI.from(result);
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtHostWindow = createDecorator<IExtHostWindow>('IExtHostWindow');
|
||||
export interface IExtHostWindow extends ExtHostWindow, ExtHostWindowShape { }
|
||||
|
||||
Reference in New Issue
Block a user