mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-23 01:58:53 +01:00
Merge remote-tracking branch 'origin/master' into pine/alwaysShowInlineDetails
This commit is contained in:
39
src/vs/workbench/api/common/cache.ts
Normal file
39
src/vs/workbench/api/common/cache.ts
Normal 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}`);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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> { }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user