Path: blob/main/extensions/copilot/src/util/common/test/shims/editing.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/456import { coalesceInPlace } from '../../../vs/base/common/arrays';7import { ResourceMap } from '../../../vs/base/common/map';8import { URI as Uri } from '../../../vs/base/common/uri';9import { Position } from '../../../vs/workbench/api/common/extHostTypes/position';10import { Range } from '../../../vs/workbench/api/common/extHostTypes/range';11import { SnippetString } from '../../../vs/workbench/api/common/extHostTypes/snippetString';12import { SnippetTextEdit } from '../../../vs/workbench/api/common/extHostTypes/snippetTextEdit';13import { TextEdit } from '../../../vs/workbench/api/common/extHostTypes/textEdit';1415export interface WorkspaceEditEntryMetadata {16needsConfirmation: boolean;17label: string;18description?: string;19// iconPath?: Uri | { light: Uri; dark: Uri } | ThemeIcon;20}2122export interface IFileOperationOptions {23readonly overwrite?: boolean;24readonly ignoreIfExists?: boolean;25readonly ignoreIfNotExists?: boolean;26readonly recursive?: boolean;27readonly contents?: Uint8Array;28}2930export const enum FileEditType {31File = 1,32Text = 2,33Cell = 3,34CellReplace = 5,35Snippet = 6,36}3738export interface IFileOperation {39readonly _type: FileEditType.File;40readonly from?: Uri;41readonly to?: Uri;42readonly options?: IFileOperationOptions;43readonly metadata?: WorkspaceEditEntryMetadata;44}4546export interface IFileTextEdit {47readonly _type: FileEditType.Text;48readonly uri: Uri;49readonly edit: TextEdit;50readonly metadata?: WorkspaceEditEntryMetadata;51}5253export interface IFileSnippetTextEdit {54readonly _type: FileEditType.Snippet;55readonly uri: Uri;56readonly range: Range;57readonly edit: SnippetString;58readonly metadata?: WorkspaceEditEntryMetadata;59}6061type WorkspaceEditEntry = IFileOperation | IFileTextEdit | IFileSnippetTextEdit;6263export class WorkspaceEdit {64private readonly _edits: WorkspaceEditEntry[] = [];6566_allEntries(): ReadonlyArray<WorkspaceEditEntry> {67return this._edits;68}6970// --- file7172renameFile(73from: Uri,74to: Uri,75options?: { readonly overwrite?: boolean; readonly ignoreIfExists?: boolean },76metadata?: WorkspaceEditEntryMetadata77): void {78this._edits.push({ _type: FileEditType.File, from, to, options, metadata });79}8081createFile(82uri: Uri,83options?: { readonly overwrite?: boolean; readonly ignoreIfExists?: boolean; readonly contents?: Uint8Array },84metadata?: WorkspaceEditEntryMetadata85): void {86this._edits.push({ _type: FileEditType.File, from: undefined, to: uri, options, metadata });87}8889deleteFile(90uri: Uri,91options?: { readonly recursive?: boolean; readonly ignoreIfNotExists?: boolean },92metadata?: WorkspaceEditEntryMetadata93): void {94this._edits.push({ _type: FileEditType.File, from: uri, to: undefined, options, metadata });95}9697// --- text9899replace(uri: Uri, range: Range, newText: string, metadata?: WorkspaceEditEntryMetadata): void {100this._edits.push({ _type: FileEditType.Text, uri, edit: new TextEdit(range, newText), metadata });101}102103insert(resource: Uri, position: Position, newText: string, metadata?: WorkspaceEditEntryMetadata): void {104this.replace(resource, new Range(position, position), newText, metadata);105}106107delete(resource: Uri, range: Range, metadata?: WorkspaceEditEntryMetadata): void {108this.replace(resource, range, '', metadata);109}110111// --- text (Maplike)112113has(uri: Uri): boolean {114return this._edits.some(edit => edit._type === FileEditType.Text && edit.uri.toString() === uri.toString());115}116117set(uri: Uri, edits: ReadonlyArray<TextEdit | SnippetTextEdit>): void;118set(uri: Uri, edits: ReadonlyArray<[TextEdit | SnippetTextEdit, WorkspaceEditEntryMetadata]>): void;119120set(121uri: Uri,122edits:123| null124| undefined125| ReadonlyArray<TextEdit | SnippetTextEdit | [TextEdit | SnippetTextEdit, WorkspaceEditEntryMetadata]>126): void {127if (!edits) {128// remove all text, snippet, or notebook edits for `uri`129for (let i = 0; i < this._edits.length; i++) {130const element = this._edits[i];131switch (element._type) {132case FileEditType.Text:133case FileEditType.Snippet:134if (element.uri.toString() === uri.toString()) {135this._edits[i] = undefined!; // will be coalesced down below136}137break;138}139}140coalesceInPlace(this._edits);141} else {142// append edit to the end143for (const editOrTuple of edits) {144if (!editOrTuple) {145continue;146}147let edit: TextEdit | SnippetTextEdit;148let metadata: WorkspaceEditEntryMetadata | undefined;149if (Array.isArray(editOrTuple)) {150edit = editOrTuple[0];151metadata = editOrTuple[1];152} else {153edit = editOrTuple;154}155if (SnippetTextEdit.isSnippetTextEdit(edit)) {156this._edits.push({157_type: FileEditType.Snippet,158uri,159range: edit.range,160edit: edit.snippet,161metadata,162});163} else {164this._edits.push({ _type: FileEditType.Text, uri, edit, metadata });165}166}167}168}169170get(uri: Uri): TextEdit[] {171const res: TextEdit[] = [];172for (const candidate of this._edits) {173if (candidate._type === FileEditType.Text && candidate.uri.toString() === uri.toString()) {174res.push(candidate.edit);175}176}177return res;178}179180entries(): [Uri, TextEdit[]][] {181const textEdits = new ResourceMap<[Uri, TextEdit[]]>();182for (const candidate of this._edits) {183if (candidate._type === FileEditType.Text) {184let textEdit = textEdits.get(candidate.uri);185if (!textEdit) {186textEdit = [candidate.uri, []];187textEdits.set(candidate.uri, textEdit);188}189textEdit[1].push(candidate.edit);190}191}192return [...textEdits.values()];193}194195get size(): number {196return this.entries().length;197}198199toJSON(): any {200return this.entries();201}202}203204205/**206* Represents sources that can cause {@link window.onDidChangeTextEditorSelection selection change events}.207*/208export enum TextEditorSelectionChangeKind {209/**210* Selection changed due to typing in the editor.211*/212Keyboard = 1,213/**214* Selection change due to clicking in the editor.215*/216Mouse = 2,217/**218* Selection changed because a command ran.219*/220Command = 3221}222223/**224* Reasons for why a text document has changed.225*/226export enum TextDocumentChangeReason {227/** The text change is caused by an undo operation. */228Undo = 1,229230/** The text change is caused by an redo operation. */231Redo = 2,232}233234