mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-13 03:28:33 -05:00
Merge from vscode 073a24de05773f2261f89172987002dc0ae2f1cd (#9711)
This commit is contained in:
@@ -202,7 +202,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
login(providerId: string, scopes: string[]): Thenable<vscode.AuthenticationSession> {
|
||||
return extHostAuthentication.login(extension, providerId, scopes);
|
||||
},
|
||||
get onDidChangeSessions(): Event<string[]> {
|
||||
get onDidChangeSessions(): Event<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }> {
|
||||
return extHostAuthentication.onDidChangeSessions;
|
||||
},
|
||||
};
|
||||
@@ -549,9 +549,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } }));
|
||||
},
|
||||
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable<R>) {
|
||||
if (typeof options.location === 'object') {
|
||||
checkProposedApiEnabled(extension);
|
||||
}
|
||||
return extHostProgress.withProgress(extension, options, task);
|
||||
},
|
||||
createOutputChannel(name: string): vscode.OutputChannel {
|
||||
@@ -586,9 +583,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
registerWebviewPanelSerializer: (viewType: string, serializer: vscode.WebviewPanelSerializer) => {
|
||||
return extHostWebviews.registerWebviewPanelSerializer(extension, viewType, serializer);
|
||||
},
|
||||
registerCustomEditorProvider: (viewType: string, provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider, options?: vscode.WebviewPanelOptions) => {
|
||||
registerCustomEditorProvider: (viewType: string, provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider, options?: { webviewOptions?: vscode.WebviewPanelOptions }) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options);
|
||||
return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options?.webviewOptions);
|
||||
},
|
||||
registerDecorationProvider(provider: vscode.DecorationProvider) {
|
||||
checkProposedApiEnabled(extension);
|
||||
@@ -1048,12 +1045,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
CallHierarchyItem: extHostTypes.CallHierarchyItem,
|
||||
DebugConsoleMode: extHostTypes.DebugConsoleMode,
|
||||
Decoration: extHostTypes.Decoration,
|
||||
WebviewContentState: extHostTypes.WebviewContentState,
|
||||
UIKind: UIKind,
|
||||
ColorThemeKind: extHostTypes.ColorThemeKind,
|
||||
TimelineItem: extHostTypes.TimelineItem,
|
||||
CellKind: extHostTypes.CellKind,
|
||||
CellOutputKind: extHostTypes.CellOutputKind
|
||||
CellOutputKind: extHostTypes.CellOutputKind,
|
||||
CustomDocument: extHostTypes.CustomDocument,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ export interface MainThreadCommentsShape extends IDisposable {
|
||||
export interface MainThreadAuthenticationShape extends IDisposable {
|
||||
$registerAuthenticationProvider(id: string, displayName: string): void;
|
||||
$unregisterAuthenticationProvider(id: string): void;
|
||||
$onDidChangeSessions(id: string): void;
|
||||
$onDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void;
|
||||
$getSessionsPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean>;
|
||||
$loginPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean>;
|
||||
}
|
||||
@@ -626,6 +626,12 @@ export interface WebviewPanelViewStateData {
|
||||
};
|
||||
}
|
||||
|
||||
export interface CustomDocumentEditState {
|
||||
readonly allEdits: readonly number[];
|
||||
readonly currentIndex: number;
|
||||
readonly saveIndex: number;
|
||||
}
|
||||
|
||||
export interface ExtHostWebviewsShape {
|
||||
$onMessage(handle: WebviewPanelHandle, message: any): void;
|
||||
$onMissingCsp(handle: WebviewPanelHandle, extensionId: string): void;
|
||||
@@ -638,9 +644,9 @@ export interface ExtHostWebviewsShape {
|
||||
$createWebviewCustomEditorDocument(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<{ editable: boolean }>;
|
||||
$disposeWebviewCustomEditorDocument(resource: UriComponents, viewType: string): Promise<void>;
|
||||
|
||||
$undo(resource: UriComponents, viewType: string, editId: number): Promise<void>;
|
||||
$redo(resource: UriComponents, viewType: string, editId: number): Promise<void>;
|
||||
$revert(resource: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }): Promise<void>;
|
||||
$undo(resource: UriComponents, viewType: string, editId: number, state: CustomDocumentEditState): Promise<void>;
|
||||
$redo(resource: UriComponents, viewType: string, editId: number, state: CustomDocumentEditState): Promise<void>;
|
||||
$revert(resource: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }, state: CustomDocumentEditState): Promise<void>;
|
||||
$disposeEdits(resourceComponents: UriComponents, viewType: string, editIds: number[]): void;
|
||||
|
||||
$onSave(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void>;
|
||||
@@ -691,7 +697,8 @@ export interface MainThreadNotebookShape extends IDisposable {
|
||||
$unregisterNotebookRenderer(handle: number): Promise<void>;
|
||||
$createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void>;
|
||||
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
|
||||
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata | undefined): Promise<void>;
|
||||
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise<void>;
|
||||
$updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata | undefined): Promise<void>;
|
||||
$spliceNotebookCells(viewType: string, resource: UriComponents, splices: NotebookCellsSplice[], renderers: number[]): Promise<void>;
|
||||
$spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void>;
|
||||
$postMessage(handle: number, value: any): Promise<boolean>;
|
||||
|
||||
@@ -17,8 +17,8 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
private _onDidChangeAuthenticationProviders = new Emitter<vscode.AuthenticationProvidersChangeEvent>();
|
||||
readonly onDidChangeAuthenticationProviders: Event<vscode.AuthenticationProvidersChangeEvent> = this._onDidChangeAuthenticationProviders.event;
|
||||
|
||||
private _onDidChangeSessions = new Emitter<string[]>();
|
||||
readonly onDidChangeSessions: Event<string[]> = this._onDidChangeSessions.event;
|
||||
private _onDidChangeSessions = new Emitter<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }>();
|
||||
readonly onDidChangeSessions: Event<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }> = this._onDidChangeSessions.event;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication);
|
||||
@@ -85,9 +85,9 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
|
||||
this._authenticationProviders.set(provider.id, provider);
|
||||
|
||||
const listener = provider.onDidChangeSessions(_ => {
|
||||
this._proxy.$onDidChangeSessions(provider.id);
|
||||
this._onDidChangeSessions.fire([provider.id]);
|
||||
const listener = provider.onDidChangeSessions(e => {
|
||||
this._proxy.$onDidChangeSessions(provider.id, e);
|
||||
this._onDidChangeSessions.fire({ [provider.id]: e });
|
||||
});
|
||||
|
||||
this._proxy.$registerAuthenticationProvider(provider.id, provider.displayName);
|
||||
|
||||
@@ -16,6 +16,12 @@ import { INotebookDisplayOrder, ITransformedDisplayOutputDto, IOrderedMimeType,
|
||||
import { ISplice } from 'vs/base/common/sequence';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
|
||||
const notebookDocumentMetadataDefaults: vscode.NotebookDocumentMetadata = {
|
||||
editable: true,
|
||||
cellEditable: true,
|
||||
cellRunnable: true
|
||||
};
|
||||
|
||||
export class ExtHostCell implements vscode.NotebookCell {
|
||||
|
||||
public source: string[];
|
||||
@@ -27,13 +33,16 @@ export class ExtHostCell implements vscode.NotebookCell {
|
||||
private _outputMapping = new Set<vscode.CellOutput>();
|
||||
|
||||
constructor(
|
||||
private viewType: string,
|
||||
private documentUri: URI,
|
||||
readonly handle: number,
|
||||
readonly uri: URI,
|
||||
private _content: string,
|
||||
public cellKind: CellKind,
|
||||
public language: string,
|
||||
outputs: any[],
|
||||
public metadata: vscode.NotebookCellMetadata | undefined,
|
||||
private _metadata: vscode.NotebookCellMetadata | undefined,
|
||||
private _proxy: MainThreadNotebookShape
|
||||
) {
|
||||
this.source = this._content.split(/\r|\n|\r\n/g);
|
||||
this._outputs = outputs;
|
||||
@@ -62,6 +71,20 @@ export class ExtHostCell implements vscode.NotebookCell {
|
||||
this._onDidChangeOutputs.fire(diffs);
|
||||
}
|
||||
|
||||
get metadata() {
|
||||
return this._metadata;
|
||||
}
|
||||
|
||||
set metadata(newMetadata: vscode.NotebookCellMetadata | undefined) {
|
||||
const newMetadataWithDefaults: vscode.NotebookCellMetadata | undefined = newMetadata ? {
|
||||
editable: newMetadata.editable,
|
||||
runnable: newMetadata.runnable
|
||||
} : undefined;
|
||||
|
||||
this._metadata = newMetadataWithDefaults;
|
||||
this._proxy.$updateNotebookCellMetadata(this.viewType, this.documentUri, this.handle, newMetadataWithDefaults);
|
||||
}
|
||||
|
||||
getContent(): string {
|
||||
if (this._textDocument && this._initalVersion !== this._textDocument?.version) {
|
||||
return this._textDocument.getText();
|
||||
@@ -131,14 +154,14 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
this._proxy.$updateNotebookLanguages(this.viewType, this.uri, this._languages);
|
||||
}
|
||||
|
||||
private _metadata: vscode.NotebookDocumentMetadata | undefined = undefined;
|
||||
private _metadata: vscode.NotebookDocumentMetadata | undefined = notebookDocumentMetadataDefaults;
|
||||
|
||||
get metadata() {
|
||||
return this._metadata;
|
||||
}
|
||||
|
||||
set metadata(newMetadata: vscode.NotebookDocumentMetadata | undefined) {
|
||||
this._metadata = newMetadata;
|
||||
this._metadata = newMetadata || notebookDocumentMetadataDefaults;
|
||||
this._proxy.$updateNotebookMetadata(this.viewType, this.uri, this._metadata);
|
||||
}
|
||||
|
||||
@@ -201,6 +224,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
outputs: outputs,
|
||||
metadata: cell.metadata,
|
||||
isDirty: false
|
||||
};
|
||||
});
|
||||
@@ -346,7 +370,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
|
||||
|
||||
constructor(
|
||||
viewType: string,
|
||||
private readonly viewType: string,
|
||||
readonly id: string,
|
||||
public uri: URI,
|
||||
private _proxy: MainThreadNotebookShape,
|
||||
@@ -381,7 +405,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
createCell(content: string, language: string, type: CellKind, outputs: vscode.CellOutput[], metadata: vscode.NotebookCellMetadata | undefined): vscode.NotebookCell {
|
||||
const handle = ExtHostNotebookEditor._cellhandlePool++;
|
||||
const uri = CellUri.generate(this.document.uri, handle);
|
||||
const cell = new ExtHostCell(handle, uri, content, type, language, outputs, metadata);
|
||||
const cell = new ExtHostCell(this.viewType, this.uri, handle, uri, content, type, language, outputs, metadata, this._proxy);
|
||||
return cell;
|
||||
}
|
||||
|
||||
@@ -469,9 +493,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -580,7 +603,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
let editor = this._editors.get(URI.revive(uri).toString());
|
||||
let document = this._documents.get(URI.revive(uri).toString());
|
||||
|
||||
let rawCell = editor?.editor.createCell('', language, type, [], undefined) as ExtHostCell;
|
||||
let rawCell = editor?.editor.createCell('', language, type, [], { editable: true, runnable: true }) as ExtHostCell;
|
||||
document?.insertCell(index, rawCell!);
|
||||
|
||||
let allDocuments = this._documentsAndEditors.allDocuments();
|
||||
|
||||
@@ -4,16 +4,19 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { coalesce, equals } from 'vs/base/common/arrays';
|
||||
import { escapeCodicons } from 'vs/base/common/codicons';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { isMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import type * as vscode from 'vscode';
|
||||
import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files';
|
||||
import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { escapeCodicons } from 'vs/base/common/codicons';
|
||||
import type * as vscode from 'vscode';
|
||||
import { Cache } from './cache';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
|
||||
function es5ClassCompat(target: Function): any {
|
||||
///@ts-ignore
|
||||
@@ -2538,13 +2541,6 @@ export class Decoration {
|
||||
bubble?: boolean;
|
||||
}
|
||||
|
||||
export enum WebviewContentState {
|
||||
Readonly = 1,
|
||||
Unchanged = 2,
|
||||
Dirty = 3,
|
||||
}
|
||||
|
||||
|
||||
//#region Theming
|
||||
|
||||
@es5ClassCompat
|
||||
@@ -2584,3 +2580,84 @@ export class TimelineItem implements vscode.TimelineItem {
|
||||
}
|
||||
|
||||
//#endregion Timeline
|
||||
|
||||
//#region Custom Editors
|
||||
|
||||
interface EditState {
|
||||
readonly allEdits: readonly number[];
|
||||
readonly currentIndex: number;
|
||||
readonly saveIndex: number;
|
||||
}
|
||||
|
||||
export class CustomDocument<EditType = unknown> implements vscode.CustomDocument<EditType> {
|
||||
|
||||
|
||||
readonly #edits = new Cache<EditType>('edits');
|
||||
|
||||
#editState: EditState;
|
||||
|
||||
readonly #viewType: string;
|
||||
readonly #uri: vscode.Uri;
|
||||
|
||||
constructor(viewType: string, uri: vscode.Uri) {
|
||||
this.#viewType = viewType;
|
||||
this.#uri = uri;
|
||||
this.#editState = {
|
||||
allEdits: [],
|
||||
currentIndex: 0,
|
||||
saveIndex: 0
|
||||
};
|
||||
}
|
||||
|
||||
//#region Public API
|
||||
|
||||
public get viewType(): string { return this.#viewType; }
|
||||
|
||||
public get uri(): vscode.Uri { return this.#uri; }
|
||||
|
||||
#onDidDispose = new Emitter<void>();
|
||||
public readonly onDidDispose = this.#onDidDispose.event;
|
||||
|
||||
get appliedEdits() {
|
||||
return this.#editState.allEdits.slice(0, this.#editState.currentIndex + 1)
|
||||
.map(id => this._getEdit(id));
|
||||
}
|
||||
|
||||
get savedEdits() {
|
||||
return this.#editState.allEdits.slice(0, this.#editState.saveIndex + 1)
|
||||
.map(id => this._getEdit(id));
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
/** @internal */ _dispose(): void {
|
||||
this.#onDidDispose.fire();
|
||||
this.#onDidDispose.dispose();
|
||||
}
|
||||
|
||||
/** @internal */ _updateEditState(state: EditState) {
|
||||
this.#editState = state;
|
||||
}
|
||||
|
||||
/** @internal*/ _getEdit(editId: number): EditType {
|
||||
return assertIsDefined(this.#edits.get(editId, 0));
|
||||
}
|
||||
|
||||
/** @internal*/ _disposeEdits(editIds: number[]) {
|
||||
for (const editId of editIds) {
|
||||
this.#edits.delete(editId);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal*/ _addEdit(edit: EditType): number {
|
||||
const id = this.#edits.add([edit]);
|
||||
this.#editState = {
|
||||
allEdits: [...this.#editState.allEdits.slice(0, this.#editState.currentIndex), id],
|
||||
currentIndex: this.#editState.currentIndex + 1,
|
||||
saveIndex: this.#editState.saveIndex,
|
||||
};
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
@@ -18,9 +18,8 @@ import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import type * as vscode from 'vscode';
|
||||
import { Cache } from './cache';
|
||||
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewExtensionDescription, WebviewPanelHandle, WebviewPanelViewStateData } from './extHost.protocol';
|
||||
import { Disposable as VSCodeDisposable } from './extHostTypes';
|
||||
import * as extHostProtocol from './extHost.protocol';
|
||||
import * as extHostTypes from './extHostTypes';
|
||||
|
||||
type IconPath = URI | { light: URI, dark: URI };
|
||||
|
||||
@@ -33,8 +32,8 @@ export class ExtHostWebview implements vscode.Webview {
|
||||
public readonly onDidReceiveMessage: Event<any> = this._onMessageEmitter.event;
|
||||
|
||||
constructor(
|
||||
private readonly _handle: WebviewPanelHandle,
|
||||
private readonly _proxy: MainThreadWebviewsShape,
|
||||
private readonly _handle: extHostProtocol.WebviewPanelHandle,
|
||||
private readonly _proxy: extHostProtocol.MainThreadWebviewsShape,
|
||||
private _options: vscode.WebviewOptions,
|
||||
private readonly _initData: WebviewInitData,
|
||||
private readonly _workspace: IExtHostWorkspace | undefined,
|
||||
@@ -99,8 +98,8 @@ export class ExtHostWebview implements vscode.Webview {
|
||||
|
||||
export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPanel {
|
||||
|
||||
private readonly _handle: WebviewPanelHandle;
|
||||
private readonly _proxy: MainThreadWebviewsShape;
|
||||
private readonly _handle: extHostProtocol.WebviewPanelHandle;
|
||||
private readonly _proxy: extHostProtocol.MainThreadWebviewsShape;
|
||||
private readonly _viewType: string;
|
||||
private _title: string;
|
||||
private _iconPath?: IconPath;
|
||||
@@ -121,8 +120,8 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
|
||||
public readonly onDidChangeViewState = this.#onDidChangeViewState.event;
|
||||
|
||||
constructor(
|
||||
handle: WebviewPanelHandle,
|
||||
proxy: MainThreadWebviewsShape,
|
||||
handle: extHostProtocol.WebviewPanelHandle,
|
||||
proxy: extHostProtocol.MainThreadWebviewsShape,
|
||||
viewType: string,
|
||||
title: string,
|
||||
viewColumn: vscode.ViewColumn | undefined,
|
||||
@@ -246,114 +245,14 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
|
||||
}
|
||||
}
|
||||
|
||||
class CustomDocument extends Disposable implements vscode.CustomDocument {
|
||||
|
||||
public static create(
|
||||
viewType: string,
|
||||
uri: vscode.Uri,
|
||||
editingDelegate: vscode.CustomEditorEditingDelegate | undefined
|
||||
) {
|
||||
return Object.seal(new CustomDocument(viewType, uri, editingDelegate));
|
||||
}
|
||||
|
||||
// Explicitly initialize all properties as we seal the object after creation!
|
||||
|
||||
readonly #_edits = new Cache<unknown>('edits');
|
||||
|
||||
readonly #viewType: string;
|
||||
readonly #uri: vscode.Uri;
|
||||
readonly #editingDelegate: vscode.CustomEditorEditingDelegate | undefined;
|
||||
|
||||
private constructor(
|
||||
viewType: string,
|
||||
uri: vscode.Uri,
|
||||
editingDelegate: vscode.CustomEditorEditingDelegate | undefined,
|
||||
) {
|
||||
super();
|
||||
this.#viewType = viewType;
|
||||
this.#uri = uri;
|
||||
this.#editingDelegate = editingDelegate;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.#onDidDispose.fire();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
//#region Public API
|
||||
|
||||
public get viewType(): string { return this.#viewType; }
|
||||
|
||||
public get uri(): vscode.Uri { return this.#uri; }
|
||||
|
||||
#onDidDispose = this._register(new Emitter<void>());
|
||||
public readonly onDidDispose = this.#onDidDispose.event;
|
||||
|
||||
public userData: unknown = undefined;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Internal
|
||||
|
||||
/** @internal*/ async _revert(changes: { undoneEdits: number[], redoneEdits: number[] }) {
|
||||
const editing = this.getEditingDelegate();
|
||||
const undoneEdits = changes.undoneEdits.map(id => this.#_edits.get(id, 0));
|
||||
const appliedEdits = changes.redoneEdits.map(id => this.#_edits.get(id, 0));
|
||||
return editing.revert(this, { undoneEdits, appliedEdits });
|
||||
}
|
||||
|
||||
/** @internal*/ _undo(editId: number) {
|
||||
const editing = this.getEditingDelegate();
|
||||
const edit = this.#_edits.get(editId, 0);
|
||||
return editing.undoEdits(this, [edit]);
|
||||
}
|
||||
|
||||
/** @internal*/ _redo(editId: number) {
|
||||
const editing = this.getEditingDelegate();
|
||||
const edit = this.#_edits.get(editId, 0);
|
||||
return editing.applyEdits(this, [edit]);
|
||||
}
|
||||
|
||||
/** @internal*/ _save(cancellation: CancellationToken) {
|
||||
return this.getEditingDelegate().save(this, cancellation);
|
||||
}
|
||||
|
||||
/** @internal*/ _saveAs(target: vscode.Uri) {
|
||||
return this.getEditingDelegate().saveAs(this, target);
|
||||
}
|
||||
|
||||
/** @internal*/ _backup(cancellation: CancellationToken) {
|
||||
return this.getEditingDelegate().backup(this, cancellation);
|
||||
}
|
||||
|
||||
/** @internal*/ _disposeEdits(editIds: number[]) {
|
||||
for (const editId of editIds) {
|
||||
this.#_edits.delete(editId);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal*/ _pushEdit(edit: unknown): number {
|
||||
return this.#_edits.add([edit]);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
private getEditingDelegate(): vscode.CustomEditorEditingDelegate {
|
||||
if (!this.#editingDelegate) {
|
||||
throw new Error('Document is not editable');
|
||||
}
|
||||
return this.#editingDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
class WebviewDocumentStore {
|
||||
private readonly _documents = new Map<string, CustomDocument>();
|
||||
private readonly _documents = new Map<string, extHostTypes.CustomDocument>();
|
||||
|
||||
public get(viewType: string, resource: vscode.Uri): CustomDocument | undefined {
|
||||
public get(viewType: string, resource: vscode.Uri): extHostTypes.CustomDocument | undefined {
|
||||
return this._documents.get(this.key(viewType, resource));
|
||||
}
|
||||
|
||||
public add(document: CustomDocument) {
|
||||
public add(document: extHostTypes.CustomDocument) {
|
||||
const key = this.key(document.viewType, document.uri);
|
||||
if (this._documents.has(key)) {
|
||||
throw new Error(`Document already exists for viewType:${document.viewType} resource:${document.uri}`);
|
||||
@@ -361,7 +260,7 @@ class WebviewDocumentStore {
|
||||
this._documents.set(key, document);
|
||||
}
|
||||
|
||||
public delete(document: CustomDocument) {
|
||||
public delete(document: extHostTypes.CustomDocument) {
|
||||
const key = this.key(document.viewType, document.uri);
|
||||
this._documents.delete(key);
|
||||
}
|
||||
@@ -406,18 +305,18 @@ class EditorProviderStore {
|
||||
throw new Error(`Provider for viewType:${viewType} already registered`);
|
||||
}
|
||||
this._providers.set(viewType, { type, extension, provider } as ProviderEntry);
|
||||
return new VSCodeDisposable(() => this._providers.delete(viewType));
|
||||
return new extHostTypes.Disposable(() => this._providers.delete(viewType));
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
|
||||
private static newHandle(): WebviewPanelHandle {
|
||||
private static newHandle(): extHostProtocol.WebviewPanelHandle {
|
||||
return generateUuid();
|
||||
}
|
||||
|
||||
private readonly _proxy: MainThreadWebviewsShape;
|
||||
private readonly _webviewPanels = new Map<WebviewPanelHandle, ExtHostWebviewEditor>();
|
||||
private readonly _proxy: extHostProtocol.MainThreadWebviewsShape;
|
||||
private readonly _webviewPanels = new Map<extHostProtocol.WebviewPanelHandle, ExtHostWebviewEditor>();
|
||||
|
||||
private readonly _serializers = new Map<string, {
|
||||
readonly serializer: vscode.WebviewPanelSerializer;
|
||||
@@ -429,14 +328,14 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
private readonly _documents = new WebviewDocumentStore();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
mainContext: extHostProtocol.IMainContext,
|
||||
private readonly initData: WebviewInitData,
|
||||
private readonly workspace: IExtHostWorkspace | undefined,
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _deprecationService: IExtHostApiDeprecationService,
|
||||
private readonly _extHostDocuments: ExtHostDocuments,
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadWebviews);
|
||||
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadWebviews);
|
||||
}
|
||||
|
||||
public createWebviewPanel(
|
||||
@@ -473,7 +372,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
this._serializers.set(viewType, { serializer, extension });
|
||||
this._proxy.$registerSerializer(viewType);
|
||||
|
||||
return new VSCodeDisposable(() => {
|
||||
return new extHostTypes.Disposable(() => {
|
||||
this._serializers.delete(viewType);
|
||||
this._proxy.$unregisterSerializer(viewType);
|
||||
});
|
||||
@@ -497,21 +396,21 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
if (provider.editingDelegate) {
|
||||
disposables.add(provider.editingDelegate.onDidEdit(e => {
|
||||
const document = e.document;
|
||||
const editId = (document as CustomDocument)._pushEdit(e.edit);
|
||||
const editId = (document as extHostTypes.CustomDocument)._addEdit(e.edit);
|
||||
this._proxy.$onDidEdit(document.uri, document.viewType, editId, e.label);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
return VSCodeDisposable.from(
|
||||
return extHostTypes.Disposable.from(
|
||||
disposables,
|
||||
new VSCodeDisposable(() => {
|
||||
new extHostTypes.Disposable(() => {
|
||||
this._proxy.$unregisterEditorProvider(viewType);
|
||||
}));
|
||||
}
|
||||
|
||||
public $onMessage(
|
||||
handle: WebviewPanelHandle,
|
||||
handle: extHostProtocol.WebviewPanelHandle,
|
||||
message: any
|
||||
): void {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
@@ -521,13 +420,13 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
public $onMissingCsp(
|
||||
_handle: WebviewPanelHandle,
|
||||
_handle: extHostProtocol.WebviewPanelHandle,
|
||||
extensionId: string
|
||||
): void {
|
||||
this._logService.warn(`${extensionId} created a webview without a content security policy: https://aka.ms/vscode-webview-missing-csp`);
|
||||
}
|
||||
|
||||
public $onDidChangeWebviewPanelViewStates(newStates: WebviewPanelViewStateData): void {
|
||||
public $onDidChangeWebviewPanelViewStates(newStates: extHostProtocol.WebviewPanelViewStateData): void {
|
||||
const handles = Object.keys(newStates);
|
||||
// Notify webviews of state changes in the following order:
|
||||
// - Non-visible
|
||||
@@ -560,7 +459,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
}
|
||||
|
||||
async $onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Promise<void> {
|
||||
async $onDidDisposeWebviewPanel(handle: extHostProtocol.WebviewPanelHandle): Promise<void> {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
if (panel) {
|
||||
panel.dispose();
|
||||
@@ -569,7 +468,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
async $deserializeWebviewPanel(
|
||||
webviewHandle: WebviewPanelHandle,
|
||||
webviewHandle: extHostProtocol.WebviewPanelHandle,
|
||||
viewType: string,
|
||||
title: string,
|
||||
state: any,
|
||||
@@ -599,9 +498,8 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
const revivedResource = URI.revive(resource);
|
||||
const document = CustomDocument.create(viewType, revivedResource, entry.provider.editingDelegate);
|
||||
await entry.provider.resolveCustomDocument(document, cancellation);
|
||||
this._documents.add(document);
|
||||
const document = await entry.provider.openCustomDocument(revivedResource, cancellation);
|
||||
this._documents.add(document as extHostTypes.CustomDocument);
|
||||
return {
|
||||
editable: !!entry.provider.editingDelegate,
|
||||
};
|
||||
@@ -620,12 +518,12 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
const revivedResource = URI.revive(resource);
|
||||
const document = this.getCustomDocument(viewType, revivedResource);
|
||||
this._documents.delete(document);
|
||||
document.dispose();
|
||||
document._dispose();
|
||||
}
|
||||
|
||||
async $resolveWebviewEditor(
|
||||
resource: UriComponents,
|
||||
handle: WebviewPanelHandle,
|
||||
handle: extHostProtocol.WebviewPanelHandle,
|
||||
viewType: string,
|
||||
title: string,
|
||||
position: EditorViewColumn,
|
||||
@@ -686,50 +584,73 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
await (entry.provider as vscode.CustomTextEditorProvider).moveCustomTextEditor!(document, webview, CancellationToken.None);
|
||||
}
|
||||
|
||||
async $undo(resourceComponents: UriComponents, viewType: string, editId: number): Promise<void> {
|
||||
async $undo(resourceComponents: UriComponents, viewType: string, editId: number, state: extHostProtocol.CustomDocumentEditState): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return document._undo(editId);
|
||||
document._updateEditState(state);
|
||||
return delegate.undoEdits(document, [document._getEdit(editId)]);
|
||||
}
|
||||
|
||||
async $redo(resourceComponents: UriComponents, viewType: string, editId: number): Promise<void> {
|
||||
async $redo(resourceComponents: UriComponents, viewType: string, editId: number, state: extHostProtocol.CustomDocumentEditState): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return document._redo(editId);
|
||||
document._updateEditState(state);
|
||||
return delegate.applyEdits(document, [document._getEdit(editId)]);
|
||||
}
|
||||
|
||||
async $revert(resourceComponents: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }): Promise<void> {
|
||||
async $revert(resourceComponents: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }, state: extHostProtocol.CustomDocumentEditState): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return document._revert(changes);
|
||||
const undoneEdits = changes.undoneEdits.map(id => document._getEdit(id));
|
||||
const appliedEdits = changes.redoneEdits.map(id => document._getEdit(id));
|
||||
document._updateEditState(state);
|
||||
return delegate.revert(document, { undoneEdits, appliedEdits });
|
||||
}
|
||||
|
||||
async $onSave(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return document._save(cancellation);
|
||||
return delegate.save(document, cancellation);
|
||||
}
|
||||
|
||||
async $onSaveAs(resourceComponents: UriComponents, viewType: string, targetResource: UriComponents): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return document._saveAs(URI.revive(targetResource));
|
||||
return delegate.saveAs(document, URI.revive(targetResource));
|
||||
}
|
||||
|
||||
async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void> {
|
||||
const delegate = this.getEditingDelegate(viewType);
|
||||
const document = this.getCustomDocument(viewType, resourceComponents);
|
||||
return document._backup(cancellation);
|
||||
return delegate.backup(document, cancellation);
|
||||
}
|
||||
|
||||
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined {
|
||||
private getWebviewPanel(handle: extHostProtocol.WebviewPanelHandle): ExtHostWebviewEditor | undefined {
|
||||
return this._webviewPanels.get(handle);
|
||||
}
|
||||
|
||||
private getCustomDocument(viewType: string, resource: UriComponents): CustomDocument {
|
||||
private getCustomDocument(viewType: string, resource: UriComponents): extHostTypes.CustomDocument {
|
||||
const document = this._documents.get(viewType, URI.revive(resource));
|
||||
if (!document) {
|
||||
throw new Error('No webview editor custom document found');
|
||||
}
|
||||
return document;
|
||||
}
|
||||
|
||||
private getEditingDelegate(viewType: string): vscode.CustomEditorEditingDelegate {
|
||||
const entry = this._editorProviders.get(viewType);
|
||||
if (!entry) {
|
||||
throw new Error(`No provider found for '${viewType}'`);
|
||||
}
|
||||
const delegate = (entry.provider as vscode.CustomEditorProvider).editingDelegate;
|
||||
if (!delegate) {
|
||||
throw new Error(`Provider for ${viewType}' does not support editing`);
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
|
||||
function toExtensionData(extension: IExtensionDescription): WebviewExtensionDescription {
|
||||
function toExtensionData(extension: IExtensionDescription): extHostProtocol.WebviewExtensionDescription {
|
||||
return { id: extension.identifier, location: extension.extensionLocation };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user