Change:
Add support for setting the contents of files created by workspace edits My proposed would be to add a option to : For , we want to support copying images from desktop into with drag and drop. Right now we have to use the apis to create the image file Using a workspace edit would let us express the entire operation in a single , which will play more nicely with undo/redo
Looks like support for this may already exist internally: However getting a of new file data from the extension host to the main process may be tricky. We can only efficiently serialize a if it is a top level argument to an RPC call or if the entire object is wrapped in a (which has a perf cost). Open to ideas on how to handle this
I do like the and believe the cost is manageable - we don't send edits is large frequencies and of large sizes. I can take a look at this but it honestly is stretch for June - there is some debt in how workspace edits are represented on the wire and I would take this issue as a reason to clean things up
work started here: I didn't bother with or hoisting the data to the top but instead it uses quick and dirty base64 encoding. I'd suggest we go with that and see how it works out over time.

Discussion:
assert.strictEqual(document.getText(), 'foobarhellonworld'); assert.deepStrictEqual(edt.selections, [new vscode.Selection(0, 0, 0, 3)]); }); <ins> test('Support creating binary files in a WorkspaceEdit', async function (): Promise<any> { const fileUri = vscode.Uri.parse(`${testFs.scheme}:/${rndName()}`); const data = Buffer.from('Hello Binary Files'); const ws = new vscode.WorkspaceEdit(); ws.createFile(fileUri, { contents: data, ignoreIfExists: false, overwrite: false }); const success = await vscode.workspace.applyEdit(ws); assert.ok(success); const actual = await vscode.workspace.fs.readFile(fileUri); assert.deepStrictEqual(actual, data); }); </ins> });

folder?: boolean; skipTrashBin?: boolean; maxSize?: number; <ins> contentsBase64?: string; </ins> } export interface IWorkspaceFileEdit {

*--------------------------------------------------------------------------------------------*/ import { asArray, coalesce, isNonEmptyArray } from 'vs/base/common/arrays'; <del> import { VSBuffer } from 'vs/base/common/buffer'; </del> <ins> import { encodeBase64, VSBuffer } from 'vs/base/common/buffer'; </ins> import * as htmlContent from 'vs/base/common/htmlContent'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { ResourceSet } from 'vs/base/common/map';

result.edits.push(<languages.IWorkspaceFileEdit>{ oldResource: entry.from, newResource: entry.to, <del> options: entry.options, </del> <ins> options: { ...entry.options, contentsBase64: entry.options?.contents && encodeBase64(VSBuffer.wrap(entry.options.contents)) }, </ins> metadata: entry.metadata });

ignoreIfExists?: boolean; ignoreIfNotExists?: boolean; recursive?: boolean; <ins> contents?: Uint8Array; </ins> } export const enum FileEditType {

this._edits.push({ _type: FileEditType.File, from, to, options, metadata }); } <del> createFile(uri: vscode.Uri, options?: { overwrite?: boolean; ignoreIfExists?: boolean }, metadata?: vscode.WorkspaceEditEntryMetadata): void { </del> <ins> createFile(uri: vscode.Uri, options?: { overwrite?: boolean; ignoreIfExists?: boolean; contents?: Uint8Array }, metadata?: vscode.WorkspaceEditEntryMetadata): void { </ins> this._edits.push({ _type: FileEditType.File, from: undefined, to: uri, options, metadata }); }

import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; <del> import { VSBuffer } from 'vs/base/common/buffer'; </del> <ins> import { decodeBase64, VSBuffer } from 'vs/base/common/buffer'; </ins> import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; import { CancellationToken } from 'vs/base/common/cancellation'; import { tail } from 'vs/base/common/arrays';

} else if (!edit.newResource && edit.oldResource) { edits.push(new DeleteEdit(edit.oldResource, edit.options ?? {}, false)); } else if (edit.newResource && !edit.oldResource) { <del> edits.push(new CreateEdit(edit.newResource, edit.options ?? {}, undefined)); </del> <ins> edits.push(new CreateEdit(edit.newResource, edit.options ?? {}, edit.options.contentsBase64 ? decodeBase64(edit.options.contentsBase64) : undefined)); </ins> } }

/** * Create a regular file. * <del> * @param uri Uri of the new file.. </del> <ins> * @param uri Uri of the new file. </ins> * @param options Defines if an existing file should be overwritten or be <del> * ignored. When overwrite and ignoreIfExists are both set overwrite wins. </del> <ins> * ignored. When `overwrite` and `ignoreIfExists` are both set `overwrite` wins. </ins> * When both are unset and when the file already exists then the edit cannot <del> * be applied successfully. </del> <ins> * be applied successfully. The `content`-property allows to set the initial contents * the file is being created with. </ins> * @param metadata Optional metadata for the entry. */ <del> createFile(uri: Uri, options?: { overwrite?: boolean; ignoreIfExists?: boolean }, metadata?: WorkspaceEditEntryMetadata): void; </del> <ins> createFile(uri: Uri, options?: { overwrite?: boolean; ignoreIfExists?: boolean; contents?: Uint8Array }, metadata?: WorkspaceEditEntryMetadata): void; </ins> /** * Delete a file or folder.