Merge remote-tracking branch 'origin/master' into pine/alwaysShowInlineDetails

This commit is contained in:
Pine Wu
2020-01-21 09:13:22 +01:00
179 changed files with 3424 additions and 2354 deletions

View File

@@ -0,0 +1,39 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export class Cache<T> {
private static readonly enableDebugLogging = false;
private readonly _data = new Map<number, readonly T[]>();
private _idPool = 1;
constructor(
private readonly id: string
) { }
add(item: readonly T[]): number {
const id = this._idPool++;
this._data.set(id, item);
this.logDebugInfo();
return id;
}
get(pid: number, id: number): T | undefined {
return this._data.has(pid) ? this._data.get(pid)![id] : undefined;
}
delete(id: number) {
this._data.delete(id);
this.logDebugInfo();
}
private logDebugInfo() {
if (!Cache.enableDebugLogging) {
return;
}
console.log(`${this.id} cache size — ${this._data.size}`);
}
}

View File

@@ -39,13 +39,14 @@ const configurationEntrySchema: IJSONSchema = {
},
scope: {
type: 'string',
enum: ['application', 'machine', 'window', 'resource', 'machine-overridable'],
enum: ['application', 'machine', 'window', 'resource', 'language-overridable', 'machine-overridable'],
default: 'window',
enumDescriptions: [
nls.localize('scope.application.description', "Configuration that can be configured only in the user settings."),
nls.localize('scope.machine.description', "Configuration that can be configured only in the user settings when the extension is running locally, or only in the remote settings when the extension is running remotely."),
nls.localize('scope.window.description', "Configuration that can be configured in the user, remote or workspace settings."),
nls.localize('scope.resource.description', "Configuration that can be configured in the user, remote, workspace or folder settings."),
nls.localize('scope.language-overridable.description', "Resource configuration that can be configured in language specific settings."),
nls.localize('scope.machine-overridable.description', "Machine configuration that can be configured also in workspace or folder settings.")
],
description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `application`, `machine`, `window`, `resource`, and `machine-overridable`.")
@@ -218,8 +219,8 @@ function validateProperties(configuration: IConfigurationNode, extension: IExten
propertyConfiguration.scope = ConfigurationScope.RESOURCE;
} else if (propertyConfiguration.scope.toString() === 'machine-overridable') {
propertyConfiguration.scope = ConfigurationScope.MACHINE_OVERRIDABLE;
} else if (propertyConfiguration.scope.toString() === 'resource-language') {
propertyConfiguration.scope = ConfigurationScope.RESOURCE_LANGUAGE;
} else if (propertyConfiguration.scope.toString() === 'language-overridable') {
propertyConfiguration.scope = ConfigurationScope.LANGUAGE_OVERRIDABLE;
} else {
propertyConfiguration.scope = ConfigurationScope.WINDOW;
}

View File

@@ -762,6 +762,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
openTunnel: (forward: vscode.TunnelOptions) => {
checkProposedApiEnabled(extension);
return extHostTunnelService.openTunnel(forward);
},
get tunnels() {
checkProposedApiEnabled(extension);
return extHostTunnelService.getTunnels();
},
onDidTunnelsChange: (listener, thisArg?, disposables?) => {
checkProposedApiEnabled(extension);
return extHostTunnelService.onDidTunnelsChange(listener, thisArg, disposables);
}
};

View File

@@ -31,7 +31,7 @@ import { LogLevel } from 'vs/platform/log/common/log';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
import * as quickInput from 'vs/platform/quickinput/common/quickInput';
import { RemoteAuthorityResolverErrorCode, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { RemoteAuthorityResolverErrorCode, ResolverResult, TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver';
import * as statusbar from 'vs/workbench/services/statusbar/common/statusbar';
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
@@ -563,6 +563,7 @@ export interface WebviewExtensionDescription {
export enum WebviewEditorCapabilities {
Editable,
SupportsHotExit,
}
export interface MainThreadWebviewsShape extends IDisposable {
@@ -583,7 +584,7 @@ export interface MainThreadWebviewsShape extends IDisposable {
$registerEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: readonly WebviewEditorCapabilities[]): void;
$unregisterEditorProvider(viewType: string): void;
$onEdit(resource: UriComponents, viewType: string, editJson: any): void;
$onEdit(resource: UriComponents, viewType: string, editId: number): void;
}
export interface WebviewPanelViewStateData {
@@ -603,8 +604,9 @@ export interface ExtHostWebviewsShape {
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
$resolveWebviewEditor(resource: UriComponents, newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
$undoEdits(resource: UriComponents, viewType: string, edits: readonly any[]): void;
$applyEdits(resource: UriComponents, viewType: string, edits: readonly any[]): void;
$undoEdits(resource: UriComponents, viewType: string, editIds: readonly number[]): void;
$applyEdits(resource: UriComponents, viewType: string, editIds: readonly number[]): void;
$disposeEdits(editIds: readonly number[]): void;
$onSave(resource: UriComponents, viewType: string): Promise<void>;
$onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise<void>;
@@ -783,8 +785,10 @@ export interface MainThreadWindowShape extends IDisposable {
export interface MainThreadTunnelServiceShape extends IDisposable {
$openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined>;
$closeTunnel(remote: { host: string, port: number }): Promise<void>;
$getTunnels(): Promise<TunnelDescription[]>;
$registerCandidateFinder(): Promise<void>;
$setTunnelProvider(): Promise<void>;
$setCandidateFilter(): Promise<void>;
}
// -- extension host
@@ -1068,25 +1072,22 @@ export interface IWorkspaceSymbolsDto extends IdObject {
symbols: IWorkspaceSymbolDto[];
}
export interface IResourceFileEditDto {
export interface IWorkspaceFileEditDto {
oldUri?: UriComponents;
newUri?: UriComponents;
options?: {
overwrite?: boolean;
ignoreIfExists?: boolean;
ignoreIfNotExists?: boolean;
recursive?: boolean;
};
options?: modes.WorkspaceFileEditOptions
metadata?: modes.WorkspaceEditMetadata;
}
export interface IResourceTextEditDto {
export interface IWorkspaceTextEditDto {
resource: UriComponents;
edit: modes.TextEdit;
modelVersionId?: number;
edits: modes.TextEdit[];
metadata?: modes.WorkspaceEditMetadata;
}
export interface IWorkspaceEditDto {
edits: Array<IResourceFileEditDto | IResourceTextEditDto>;
edits: Array<IWorkspaceFileEditDto | IWorkspaceTextEditDto>;
// todo@joh reject should go into rename
rejectReason?: string;
@@ -1095,11 +1096,11 @@ export interface IWorkspaceEditDto {
export function reviveWorkspaceEditDto(data: IWorkspaceEditDto | undefined): modes.WorkspaceEdit {
if (data && data.edits) {
for (const edit of data.edits) {
if (typeof (<IResourceTextEditDto>edit).resource === 'object') {
(<IResourceTextEditDto>edit).resource = URI.revive((<IResourceTextEditDto>edit).resource);
if (typeof (<IWorkspaceTextEditDto>edit).resource === 'object') {
(<IWorkspaceTextEditDto>edit).resource = URI.revive((<IWorkspaceTextEditDto>edit).resource);
} else {
(<IResourceFileEditDto>edit).newUri = URI.revive((<IResourceFileEditDto>edit).newUri);
(<IResourceFileEditDto>edit).oldUri = URI.revive((<IResourceFileEditDto>edit).oldUri);
(<IWorkspaceFileEditDto>edit).newUri = URI.revive((<IWorkspaceFileEditDto>edit).newUri);
(<IWorkspaceFileEditDto>edit).oldUri = URI.revive((<IWorkspaceFileEditDto>edit).oldUri);
}
}
}
@@ -1422,8 +1423,10 @@ export interface MainThreadThemingShape extends IDisposable {
export interface ExtHostTunnelServiceShape {
$findCandidatePorts(): Promise<{ host: string, port: number, detail: string }[]>;
$filterCandidates(candidates: { host: string, port: number, detail: string }[]): Promise<boolean[]>;
$forwardPort(tunnelOptions: TunnelOptions): Promise<TunnelDto> | undefined;
$closeTunnel(remote: { host: string, port: number }): Promise<void>;
$onDidTunnelsChange(): Promise<void>;
}
// --- proxy identifiers

View File

@@ -46,7 +46,7 @@ type ConfigurationInspect<T> = {
workspaceLanguageValue?: T;
workspaceFolderLanguageValue?: T;
languages?: string[];
languageIds?: string[];
};
function isUri(thing: any): thing is vscode.Uri {
@@ -267,7 +267,7 @@ export class ExtHostConfigProvider {
workspaceLanguageValue: config.workspace?.override,
workspaceFolderLanguageValue: config.workspaceFolder?.override,
languages: config.overrideIdentifiers
languageIds: config.overrideIdentifiers
};
}
return undefined;

View File

@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event';
import { URI, UriComponents } from 'vs/base/common/uri';
import { sequence } from 'vs/base/common/async';
import { illegalState } from 'vs/base/common/errors';
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IResourceTextEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { TextEdit } from 'vs/workbench/api/common/extHostTypes';
import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
@@ -141,19 +141,17 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
});
}).then(values => {
const resourceEdit: IResourceTextEditDto = {
resource: document.uri,
edits: []
};
const dto: IWorkspaceEditDto = { edits: [] };
for (const value of values) {
if (Array.isArray(value) && (<vscode.TextEdit[]>value).every(e => e instanceof TextEdit)) {
for (const { newText, newEol, range } of value) {
resourceEdit.edits.push({
range: range && Range.from(range),
text: newText,
eol: newEol && EndOfLine.from(newEol)
dto.edits.push({
resource: document.uri,
edit: {
range: range && Range.from(range),
text: newText,
eol: newEol && EndOfLine.from(newEol)
}
});
}
}
@@ -161,12 +159,12 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
// apply edits if any and if document
// didn't change somehow in the meantime
if (resourceEdit.edits.length === 0) {
if (dto.edits.length === 0) {
return undefined;
}
if (version === document.version) {
return this._mainThreadEditors.$tryApplyWorkspaceEdit({ edits: [resourceEdit] });
return this._mainThreadEditors.$tryApplyWorkspaceEdit(dto);
}
return Promise.reject(new Error('concurrent_edits'));

View File

@@ -645,7 +645,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
try {
const result = await resolver.resolve(remoteAuthority, { resolveAttempt });
this._disposables.add(await this._extHostTunnelService.setForwardPortProvider(resolver));
this._disposables.add(await this._extHostTunnelService.setTunnelExtensionFunctions(resolver));
// Split merged API result into separate authority/options
const authority: ResolvedAuthority = {
@@ -662,7 +662,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
value: {
authority,
options,
tunnelInformation: { environmentTunnels: result.environmentTunnels, hideCandidatePorts: result.hideCandidatePorts }
tunnelInformation: { environmentTunnels: result.environmentTunnels }
}
};
} catch (err) {

View File

@@ -8,7 +8,7 @@ import { IRelativePattern, parse } from 'vs/base/common/glob';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import type * as vscode from 'vscode';
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, MainThreadTextEditorsShape, IResourceFileEditDto, IResourceTextEditDto } from './extHost.protocol';
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, MainThreadTextEditorsShape, IWorkspaceFileEditDto, IWorkspaceTextEditDto } from './extHost.protocol';
import * as typeConverter from './extHostTypeConverters';
import { Disposable, WorkspaceEdit } from './extHostTypes';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
@@ -219,7 +219,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
if (edits.length > 0) {
// flatten all WorkspaceEdits collected via waitUntil-call
// and apply them in one go.
const allEdits = new Array<Array<IResourceFileEditDto | IResourceTextEditDto>>();
const allEdits = new Array<Array<IWorkspaceFileEditDto | IWorkspaceTextEditDto>>();
for (let edit of edits) {
let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors);
allEdits.push(edits);

View File

@@ -30,6 +30,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
import { encodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokens';
import { IdGenerator } from 'vs/base/common/idGenerator';
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { Cache } from './cache';
// --- adapter
@@ -1064,40 +1065,6 @@ class SignatureHelpAdapter {
}
}
class Cache<T> {
private static readonly enableDebugLogging = false;
private readonly _data = new Map<number, readonly T[]>();
private _idPool = 1;
constructor(
private readonly id: string
) { }
add(item: readonly T[]): number {
const id = this._idPool++;
this._data.set(id, item);
this.logDebugInfo();
return id;
}
get(pid: number, id: number): T | undefined {
return this._data.has(pid) ? this._data.get(pid)![id] : undefined;
}
delete(id: number) {
this._data.delete(id);
this.logDebugInfo();
}
private logDebugInfo() {
if (!Cache.enableDebugLogging) {
return;
}
console.log(`${this.id} cache size — ${this._data.size}`);
}
}
class LinkProviderAdapter {
private _cache = new Cache<vscode.DocumentLink>('DocumentLink');

View File

@@ -8,6 +8,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import type * as vscode from 'vscode';
import { RemoteTunnel, TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event';
export interface TunnelDto {
remoteAddress: { port: number, host: string };
@@ -31,21 +32,31 @@ export interface Tunnel extends vscode.Disposable {
export interface IExtHostTunnelService extends ExtHostTunnelServiceShape {
readonly _serviceBrand: undefined;
openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined>;
setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable>;
getTunnels(): Promise<vscode.TunnelDescription[]>;
onDidTunnelsChange: vscode.Event<void>;
setTunnelExtensionFunctions(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable>;
}
export const IExtHostTunnelService = createDecorator<IExtHostTunnelService>('IExtHostTunnelService');
export class ExtHostTunnelService implements IExtHostTunnelService {
_serviceBrand: undefined;
onDidTunnelsChange: vscode.Event<void> = (new Emitter<void>()).event;
async openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
return undefined;
}
async getTunnels(): Promise<vscode.TunnelDescription[]> {
return [];
}
async $findCandidatePorts(): Promise<{ host: string, port: number; detail: string; }[]> {
return [];
}
async setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable> { return { dispose: () => { } }; }
async $filterCandidates(candidates: { host: string, port: number, detail: string }[]): Promise<boolean[]> {
return candidates.map(() => true);
}
async setTunnelExtensionFunctions(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable> { return { dispose: () => { } }; }
$forwardPort(tunnelOptions: TunnelOptions): Promise<TunnelDto> | undefined { return undefined; }
async $closeTunnel(remote: { host: string, port: number }): Promise<void> { }
async $onDidTunnelsChange(): Promise<void> { }
}

View File

@@ -483,15 +483,29 @@ export namespace WorkspaceEdit {
const result: extHostProtocol.IWorkspaceEditDto = {
edits: []
};
for (const entry of (value as types.WorkspaceEdit)._allEntries()) {
const [uri, uriOrEdits] = entry;
if (Array.isArray(uriOrEdits)) {
// text edits
const doc = documents && uri ? documents.getDocument(uri) : undefined;
result.edits.push(<extHostProtocol.IResourceTextEditDto>{ resource: uri, modelVersionId: doc && doc.version, edits: uriOrEdits.map(TextEdit.from) });
} else {
// resource edits
result.edits.push(<extHostProtocol.IResourceFileEditDto>{ oldUri: uri, newUri: uriOrEdits, options: entry[2] });
if (value instanceof types.WorkspaceEdit) {
for (let entry of value.allEntries()) {
if (entry._type === 1) {
// file operation
result.edits.push(<extHostProtocol.IWorkspaceFileEditDto>{
oldUri: entry.from,
newUri: entry.to,
options: entry.options,
metadata: entry.metadata
});
} else {
// text edits
const doc = documents?.getDocument(entry.uri);
result.edits.push(<extHostProtocol.IWorkspaceTextEditDto>{
resource: entry.uri,
edit: TextEdit.from(entry.edit),
modelVersionId: doc?.version,
metadata: entry.metadata
});
}
}
}
return result;
@@ -500,16 +514,17 @@ export namespace WorkspaceEdit {
export function to(value: extHostProtocol.IWorkspaceEditDto) {
const result = new types.WorkspaceEdit();
for (const edit of value.edits) {
if (Array.isArray((<extHostProtocol.IResourceTextEditDto>edit).edits)) {
result.set(
URI.revive((<extHostProtocol.IResourceTextEditDto>edit).resource),
<types.TextEdit[]>(<extHostProtocol.IResourceTextEditDto>edit).edits.map(TextEdit.to)
if ((<extHostProtocol.IWorkspaceTextEditDto>edit).edit) {
result.replace(
URI.revive((<extHostProtocol.IWorkspaceTextEditDto>edit).resource),
Range.to((<extHostProtocol.IWorkspaceTextEditDto>edit).edit.range),
(<extHostProtocol.IWorkspaceTextEditDto>edit).edit.text
);
} else {
result.renameFile(
URI.revive((<extHostProtocol.IResourceFileEditDto>edit).oldUri!),
URI.revive((<extHostProtocol.IResourceFileEditDto>edit).newUri!),
(<extHostProtocol.IResourceFileEditDto>edit).options
URI.revive((<extHostProtocol.IWorkspaceFileEditDto>edit).oldUri!),
URI.revive((<extHostProtocol.IWorkspaceFileEditDto>edit).newUri!),
(<extHostProtocol.IWorkspaceFileEditDto>edit).options
);
}
}

View File

@@ -564,7 +564,6 @@ export class TextEdit {
}
}
export interface IFileOperationOptions {
overwrite?: boolean;
ignoreIfExists?: boolean;
@@ -577,12 +576,14 @@ export interface IFileOperation {
from?: URI;
to?: URI;
options?: IFileOperationOptions;
metadata?: vscode.WorkspaceEditMetadata;
}
export interface IFileTextEdit {
_type: 2;
uri: URI;
edit: TextEdit;
metadata?: vscode.WorkspaceEditMetadata;
}
@es5ClassCompat
@@ -590,28 +591,28 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
private _edits = new Array<IFileOperation | IFileTextEdit>();
renameFile(from: vscode.Uri, to: vscode.Uri, options?: { overwrite?: boolean, ignoreIfExists?: boolean; }): void {
this._edits.push({ _type: 1, from, to, options });
renameFile(from: vscode.Uri, to: vscode.Uri, options?: { overwrite?: boolean, ignoreIfExists?: boolean; }, metadata?: vscode.WorkspaceEditMetadata): void {
this._edits.push({ _type: 1, from, to, options, metadata });
}
createFile(uri: vscode.Uri, options?: { overwrite?: boolean, ignoreIfExists?: boolean; }): void {
this._edits.push({ _type: 1, from: undefined, to: uri, options });
createFile(uri: vscode.Uri, options?: { overwrite?: boolean, ignoreIfExists?: boolean; }, metadata?: vscode.WorkspaceEditMetadata): void {
this._edits.push({ _type: 1, from: undefined, to: uri, options, metadata });
}
deleteFile(uri: vscode.Uri, options?: { recursive?: boolean, ignoreIfNotExists?: boolean; }): void {
this._edits.push({ _type: 1, from: uri, to: undefined, options });
deleteFile(uri: vscode.Uri, options?: { recursive?: boolean, ignoreIfNotExists?: boolean; }, metadata?: vscode.WorkspaceEditMetadata): void {
this._edits.push({ _type: 1, from: uri, to: undefined, options, metadata });
}
replace(uri: URI, range: Range, newText: string): void {
this._edits.push({ _type: 2, uri, edit: new TextEdit(range, newText) });
replace(uri: URI, range: Range, newText: string, metadata?: vscode.WorkspaceEditMetadata): void {
this._edits.push({ _type: 2, uri, edit: new TextEdit(range, newText), metadata });
}
insert(resource: URI, position: Position, newText: string): void {
this.replace(resource, new Range(position, position), newText);
insert(resource: URI, position: Position, newText: string, metadata?: vscode.WorkspaceEditMetadata): void {
this.replace(resource, new Range(position, position), newText, metadata);
}
delete(resource: URI, range: Range): void {
this.replace(resource, range, '');
delete(resource: URI, range: Range, metadata?: vscode.WorkspaceEditMetadata): void {
this.replace(resource, range, '', metadata);
}
has(uri: URI): boolean {
@@ -663,18 +664,22 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
return values(textEdits);
}
_allEntries(): ([URI, TextEdit[]] | [URI?, URI?, IFileOperationOptions?])[] {
const res: ([URI, TextEdit[]] | [URI?, URI?, IFileOperationOptions?])[] = [];
for (let edit of this._edits) {
if (edit._type === 1) {
res.push([edit.from, edit.to, edit.options]);
} else {
res.push([edit.uri, [edit.edit]]);
}
}
return res;
allEntries(): ReadonlyArray<IFileTextEdit | IFileOperation> {
return this._edits;
}
// _allEntries(): ([URI, TextEdit] | [URI?, URI?, IFileOperationOptions?])[] {
// const res: ([URI, TextEdit] | [URI?, URI?, IFileOperationOptions?])[] = [];
// for (let edit of this._edits) {
// if (edit._type === 1) {
// res.push([edit.from, edit.to, edit.options]);
// } else {
// res.push([edit.uri, edit.edit]);
// }
// }
// return res;
// }
get size(): number {
return this.entries().length;
}

View File

@@ -15,6 +15,7 @@ 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, WebviewEditorCapabilities, WebviewPanelHandle, WebviewPanelViewStateData } from './extHost.protocol';
import { Disposable as VSCodeDisposable } from './extHostTypes';
@@ -251,8 +252,18 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
private readonly _proxy: MainThreadWebviewsShape;
private readonly _webviewPanels = new Map<WebviewPanelHandle, ExtHostWebviewEditor>();
private readonly _serializers = new Map<string, { readonly serializer: vscode.WebviewPanelSerializer, readonly extension: IExtensionDescription }>();
private readonly _editorProviders = new Map<string, { readonly provider: vscode.WebviewCustomEditorProvider, readonly extension: IExtensionDescription }>();
private readonly _serializers = new Map<string, {
readonly serializer: vscode.WebviewPanelSerializer;
readonly extension: IExtensionDescription;
}>();
private readonly _editorProviders = new Map<string, {
readonly provider: vscode.WebviewCustomEditorProvider;
readonly extension: IExtensionDescription;
}>();
private readonly _edits = new Cache<unknown>('edits');
constructor(
mainContext: IMainContext,
@@ -312,11 +323,14 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
if (this._editorProviders.has(viewType)) {
throw new Error(`Editor provider for '${viewType}' already registered`);
}
this._editorProviders.set(viewType, { extension, provider, });
this._proxy.$registerEditorProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType, options || {}, this.getCapabilites(provider));
// Hook up events
provider?.editingDelegate?.onEdit(({ edit, resource }) => {
this._proxy.$onEdit(resource, viewType, edit);
const id = this._edits.add([edit]);
this._proxy.$onEdit(resource, viewType, id);
});
return new VSCodeDisposable(() => {
@@ -426,14 +440,32 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
await provider.resolveWebviewEditor(revivedResource, revivedPanel);
}
$undoEdits(resource: UriComponents, viewType: string, edits: readonly any[]): void {
$undoEdits(resourceComponents: UriComponents, viewType: string, editIds: readonly number[]): void {
const provider = this.getEditorProvider(viewType);
provider?.editingDelegate?.undoEdits(URI.revive(resource), edits);
if (!provider?.editingDelegate) {
return;
}
const resource = URI.revive(resourceComponents);
const edits = editIds.map(id => this._edits.get(id, 0));
provider.editingDelegate.undoEdits(resource, edits);
}
$applyEdits(resource: UriComponents, viewType: string, edits: readonly any[]): void {
$applyEdits(resourceComponents: UriComponents, viewType: string, editIds: readonly number[]): void {
const provider = this.getEditorProvider(viewType);
provider?.editingDelegate?.applyEdits(URI.revive(resource), edits);
if (!provider?.editingDelegate) {
return;
}
const resource = URI.revive(resourceComponents);
const edits = editIds.map(id => this._edits.get(id, 0));
provider.editingDelegate.applyEdits(resource, edits);
}
$disposeEdits(editIds: readonly number[]): void {
for (const edit of editIds) {
this._edits.delete(edit);
}
}
async $onSave(resource: UriComponents, viewType: string): Promise<void> {