Change:
//#endregion <del> //#region mjbvz,joh: https://github.com/Microsoft/vscode/issues/43768 /** * An event that is fired when files are going to be created. * * To make modifications to the workspace before the files are created, * call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a * thenable that resolves to a [workspace edit](#WorkspaceEdit). */ export interface FileWillCreateEvent { /** * The files that are going to be created. */ readonly files: ReadonlyArray<Uri>; /** * Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit). * * *Note:* This function can only be called during event dispatch and not * in an asynchronous manner: * * ```ts * workspace.onWillCreateFiles(event => { * 	// async, will *throw* an error * 	setTimeout(() => event.waitUntil(promise)); * * 	// sync, OK * 	event.waitUntil(promise); * }) * ``` * * @param thenable A thenable that delays saving. */ waitUntil(thenable: Thenable<WorkspaceEdit>): void; /** * Allows to pause the event until the provided thenable resolves. * * *Note:* This function can only be called during event dispatch. * * @param thenable A thenable that delays saving. */ waitUntil(thenable: Thenable<any>): void; } /** * An event that is fired after files are created. */ export interface FileCreateEvent { /** * The files that got created. */ readonly files: ReadonlyArray<Uri>; } /** * An event that is fired when files are going to be deleted. * * To make modifications to the workspace before the files are deleted, * call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a * thenable that resolves to a [workspace edit](#WorkspaceEdit). */ export interface FileWillDeleteEvent { /** * The files that are going to be deleted. */ readonly files: ReadonlyArray<Uri>; /** * Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit). * * *Note:* This function can only be called during event dispatch and not * in an asynchronous manner: * * ```ts * workspace.onWillCreateFiles(event => { * 	// async, will *throw* an error * 	setTimeout(() => event.waitUntil(promise)); * * 	// sync, OK * 	event.waitUntil(promise); * }) * ``` * * @param thenable A thenable that delays saving. */ waitUntil(thenable: Thenable<WorkspaceEdit>): void; /** * Allows to pause the event until the provided thenable resolves. * * *Note:* This function can only be called during event dispatch. * * @param thenable A thenable that delays saving. */ waitUntil(thenable: Thenable<any>): void; } /** * An event that is fired after files are deleted. */ export interface FileDeleteEvent { /** * The files that got deleted. */ readonly files: ReadonlyArray<Uri>; } /** * An event that is fired when files are going to be renamed. * * To make modifications to the workspace before the files are renamed, * call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a * thenable that resolves to a [workspace edit](#WorkspaceEdit). */ export interface FileWillRenameEvent { /** * The files that are going to be renamed. */ readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>; /** * Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit). * * *Note:* This function can only be called during event dispatch and not * in an asynchronous manner: * * ```ts * workspace.onWillCreateFiles(event => { * 	// async, will *throw* an error * 	setTimeout(() => event.waitUntil(promise)); * * 	// sync, OK * 	event.waitUntil(promise); * }) * ``` * * @param thenable A thenable that delays saving. */ waitUntil(thenable: Thenable<WorkspaceEdit>): void; /** * Allows to pause the event until the provided thenable resolves. * * *Note:* This function can only be called during event dispatch. * * @param thenable A thenable that delays saving. */ waitUntil(thenable: Thenable<any>): void; } /** * An event that is fired after files are renamed. */ export interface FileRenameEvent { /** * The files that got renamed. */ readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>; } export namespace workspace { /** * An event that is emitted when files are being created. * * *Note 1:* This event is triggered by user gestures, like creating a file from the * explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api. This event is *not* fired when * files change on disk, e.g triggered by another application, or when using the * [`workspace.fs`](#FileSystem)-api. * * *Note 2:* When this event is fired, edits to files thare are being created cannot be applied. */ export const onWillCreateFiles: Event<FileWillCreateEvent>; /** * An event that is emitted when files have been created. * * *Note:* This event is triggered by user gestures, like creating a file from the * explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when * files change on disk, e.g triggered by another application, or when using the * [`workspace.fs`](#FileSystem)-api. */ export const onDidCreateFiles: Event<FileCreateEvent>; /** * An event that is emitted when files are being deleted. * * *Note 1:* This event is triggered by user gestures, like deleting a file from the * explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when * files change on disk, e.g triggered by another application, or when using the * [`workspace.fs`](#FileSystem)-api. * * *Note 2:* When deleting a folder with children only one event is fired. */ export const onWillDeleteFiles: Event<FileWillDeleteEvent>; /** * An event that is emitted when files have been deleted. * * *Note 1:* This event is triggered by user gestures, like deleting a file from the * explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when * files change on disk, e.g triggered by another application, or when using the * [`workspace.fs`](#FileSystem)-api. * * *Note 2:* When deleting a folder with children only one event is fired. */ export const onDidDeleteFiles: Event<FileDeleteEvent>; /** * An event that is emitted when files are being renamed. * * *Note 1:* This event is triggered by user gestures, like renaming a file from the * explorer, and from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when * files change on disk, e.g triggered by another application, or when using the * [`workspace.fs`](#FileSystem)-api. * * *Note 2:* When renaming a folder with children only one event is fired. */ export const onWillRenameFiles: Event<FileWillRenameEvent>; /** * An event that is emitted when files have been renamed. * * *Note 1:* This event is triggered by user gestures, like renaming a file from the * explorer, and from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when * files change on disk, e.g triggered by another application, or when using the * [`workspace.fs`](#FileSystem)-api. * * *Note 2:* When renaming a folder with children only one event is fired. */ export const onDidRenameFiles: Event<FileRenameEvent>; } //#endregion </del> //#region Alex - OnEnter enhancement export interface OnEnterRule { /**

Discussion:
Many languages import files by filename: If a user renames this file using explorer, the code references to it become broken and need fixing up. The Dart language server has support for returning the code edits required during a file rename to avoid this. As far as I can see there isn't an API for this yet. I think could be useful for many languages (Dart, JS, TS, maybe even HTML's script tags/link tags!).
Do you want to be part of the rename-file-command or just have an event/file-event that tells you something has been renamed?
Based on the language server docs: I guess I'd need to know before it happened (I guess once the rename has happened, it may not be able to figure out the changes required). The API in theory could return errors, so it may be worthwhile allowing cancellation of it with some sort of message, though I don't know whether that's actually a possibility in the implementation (their MOVE_FILE is part of a refactor API which handles other things so the API is somewhat generic).
Thanks for clarifying - I have updated the title accordingly
TS just merged an API for rename file: Cases we'd need events for: Rename file in explorer Drag and drop file between folders in explorer If we want to allow extensions to react to renames (this is how TS API is designed to be used), the expected API could be something like: If we want extensions to be able to participate in the rename itself, we'd need a new hook (or possibly a new provider) I'd say we should only handle renames in the explore and not try to handle renames outside of the editor or try making this API part of the . This should simplify the implementation while still covering most of the use cases for triggering actions based on file renames
This sounds reasonable to me; however to handle this for Dart we really need to be called before the rename occurs; will be too late.
Agreed, but going a step further to say this is shouldn't be depend on events at all. When moving a file (via whatever user-gesture) we should now that there is a move/rename participant that we need to involve in the process. And it should probably not be the default (or behind a prompt) so that you still move a file without the smarts
Related to
A few thoughts on possible API designs: Event Simplest.

Allow an extension to be notified after the rename has occurred (thus not solving the dart requirement). Also cannot be scoped per language/filetype Provider / Handler Create a standarized provider that can handle renames. This provider could start out simple and be extended with other functionality, such as intercepting renames before they happen with . One question is how to handle directory renames and how these would work if we also use a document selector
Obviously I prefer the provider =) I think it may be confusing to have both provideRenameEdits and prepareRename if they both fire before the rename though. What about just calling for each file inside? Renaming a folder is somewhat the same as creating a folder, moving all the files to it (we've been calling it , but might be more appropriate, since it should be able to span folders) and then deleting the old folder. It's also worth thinking about how these will chain together if more than one is registered (if that's allowed).
Is this API usable by us in v1.24, or only internal extensions? Was it implemented in a way that supports our rename operations?
No, this api is still in proposed and does not support being triggered pre-rename
Is it likely that this will be supported in future?
re Not sure if provider is a good name here... Maybe add the concept of a participant or have . That would be much in-line with our -event, e.g
An -event requires some internal infrastructure (similar to ) and the question is where to put it. We have the corresponding functions in the file service interface but I also know that renaming a file is much more elaborated (reverting changes, closing editor etc). What is your recommendation esp. since debt-work is planned. Will there be an injectable, service-like rename-operation which should handle this?
I think this could go into the text file service once it implements the rename/delete logic for the text resource edits (). The explorer will use that service once it is capable of these methods.
One other thing to consider: we may need a new activation event so that a language extension that handles moves/renames can be activated even if no files of that language have been opened yet.

See Would be best if we could do this per language: Not clear what to do about directory renames here
For a directory, you could just get languages for all descendants and fire the event for them? I think we activate on workspaceContains so a new activation event probably isn't necessary (I don't know if that's common though).
This is the current proposal How would you like to wait? Do you need to run some checks on the server before renaming or do you need to modify the workspace first? Also, do you want to prompt the user with something and prevent rename?
Sorry for the delay.. I need to send the request to my server before the rename happens, and it will then return me the edits. However I'm not sure if I need to apply those edits before or after the rename (eg. if the edits contain a filename that was also being renamed, for ex. if a folder was being renamed). I'll do some testing and post back shortly..
Let's try that again... What happens when a user renames a folder? Are you going to call this multiple times? If so, at what point does the underlying folder get renamed? My API only works for a file at a time, but if you're going to call it sequentially it might need to create a new folder then move each file individually into it? Another option would be to allow me to return the edits to you; that way you can collect all the edits, rename the folder, and then apply the edits (and you have a mapping of the file names, so can apply the edits to the correct file even if it's moved since the edits were generated).
Renaming a folder is an "atomic" thing - you rename that folder and that's it. So, that will make it a single call/event. Yeah, that's the question. We can make this analog to the -event which calls each listener sequentially and allowing them to run async operations. Like so It would mean that you can asynchronously compute a workspace edit and that we would apply it before renaming the file/folder.
Ah sorry, I was thinking this was just a file because of the class prefix. sounds good. If my server can't do folders, I guess it's valid for me to list the files inside that Uri and send requests for all the edits and then merge them together?

Since you're applying them atomically, the offsets/etc. will all be correct since they're all based on the same state of the document (eg. all calculated from the same starting point). Let me know if this becomes available to test in Insiders and I can wire it up for real and give it a good test.
I have just pushed a first cut of this. The -function can now be called with promises that resolve to a workspace edit which we then apply. My test sample looks like this. That that you can call waitUntil multiple times and that we will create a single workspace edit. The order of its edits is the order in which waitUntil is called, not in which the promises resolve.
Cool; thanks! I presume since you're making a single edit the whole thing is atomic and all locations resolved from the original docs, so I can just call it multiple times for convenience with no change from building a single one? I'll see if I can get time to try this out on Monday in Insiders and let you know how I get on :-)
Yeah, it should be the state at which the event occurred and you can compute your things from there. Obviously things can change in parallel but then we try to fail the operation.
I hit an issue while implemented this with my language server; it's throwing an unexpected error, so I'm blocked on testing this until I've figured that out. I'll come back to this as soon as I can though. Btw, something that popped into my head while working on this - what happens if docs are modified during this process? For other refactors, I grab a copy of and then at the time I come to apply the edit (after all the async, server stuff) if it has changed, I reject the edit. I can't do anything like that here because I don't know what documents will be in the returned edits (well, I'd have to grab document versions for all potentially affected docs and that would be messy). Is code doing anything special here? If a document is modified while this rename is "in flight" the offsets etc. that come back are potentially invalid and might make bad edits.
No worries, we won't make this API stable this month and we have til the end of July to stabilise this. Yeah, fair question.

Currently we capture the document versions when serialising the workspace edit and we will bail out if the documents change while applying but we don't capture all versions before calling listeners. That something I can look into as extensions should have smooth sailing here.
Well this is embarrassing... Despite being documented (including being really explicit about needing to send the request before the rename occurs), it's not actually implemented in the Dart analysis server yet. Doh! So; the API seems good to me, but I can't make a real implementation just yet. I may look at doing the implementation if nobody else gets to it soon. I hope since it's a new implementation we can make it handle directories server-side to avoid me having to send tons of requests (which is how I'd started). Not sure what you want to do with the API in the meantime; I'm not sure how quick we'll have an implementation (if I end up doing it, I might need some help so there may be some back & forth).
Hehe - no worries. We can leave it in proposed for longer and/or reach out to other candidates. Keep me posted. Thanks
Will do - I've got some pointers on how to implement it so I hope to find time to have a crack at it next month.
I'm also interested in this feature and would like the ability to prevent the rename operation.
+1. Java language side also need this feature for post renaming actions.
Any progress on this?
I got blocked on my implementation in Dart, but there was a proposed API detailed above that I presume would work for other extensions wanting to try it out and give feedback.
I'd like to write an extension that performs some actions on file rename - I'll try and get something working with the proposed API and see where it goes... cheers.
Here is a use-case: providers should be able to watch file rename events in the associated workspace and build a map of original and new file names. For example, the Git provider could then run rather than showing one new file and one deleted file thus forever losing the association and file history. I am implementing a custom source control provider and can test the api when available.
really sorry it took sooooo long for me to get back to this. I got most of the implementation done in the Dart SDK and then never got back to it.

Recently someone finished it off and enabled it anyway, and I've just tested with the proposed APIs, and it seems to work perfectly :-) I'll need to add some prompt (like TS has) for the user to approve/opt-out before shipping, but the API seems good to finalize IMO :-)
is it too late to finalize this in the May release?
yes
I suspected so :) Any reason it couldn't go into June? (someone asked about it, and it seems all the real work is done, it just needs to be available in stable and I could ship :-))
We are a small team but there are also some concerns how well (or actually not so well) this aligns with the exiting file watcher API. E.g the latter doesn't have rename at all while the former only has rename. We need to make it more clear that one source of events is the filesystem and that other source of events is file operations triggered from inside VS Code, e.g will not fire if you use the command. In the same spirit we might need to add more events, like on[WillDelete] events
My expectation was that this would only fire for things the user did in the UI, so that doesn't concern me. In fact, the purpose of this API was for those that needed to construct edits prior to the rename, so I'm not sure if it'd ever work with a watcher if it only fires events after they've happened?
Yes, we just need to make sure that everyone understands this.
Makes sense - but does that need anything more than comments on the event?
let me know if there's anything I can do to help this along - it'd be neat to ship my rename work :-)
is it likely this will be considered for the next release? If the only thing required is ensuring the docs/tooltips make it clear this doesn't fire for filesystem changes but only UI events, I could send a PR?
Nothing planned yet - we are pretty busy with the web companion but I will bring in up for July planning.
Understood. Thanks!
When selecting multiple files simultaneously, drag and drop, listener will receive multiple standalone FileWillRenameEvents, this will require language server itself to associate them together. If the vscode client is able to pack them to a composite event in advance, feel like make more sense.
I agree that there is merit in having the event talk about multiple resources, e.g.

when dropping/pasting many resources. Making that API change is easy but the underlying infrastructure isn't fit so the API implementation will have a bug (for a long time) such that the array is always of length 1. That will help us get this API out (and stable) but it will not help extensions...
Do the latest comments mean the API will change to have an array (even though it'll be called repeatedly for now)? Do you have an idea when this might be finalised so it can be used in published extensions?
What's holding moving this API from proposed to production?. I hope is not about the array stuff, as there are many other events that doesn't provide such pattern.
is there any update on this? It's not clear what the next step is - will there be changes and do you need feedback, or could it ship in its current form?
No update, still the old problems/tasks current implementation from to events for create/deletion of files creating/moving/deleting N files at once (so that we can reflect that correctly in the API) N files support in explorer (and others?) extensions API you are welcome to help out, step 1 and 2 should be relatively easy
any chance for this getting finished during the October housekeeping iteration?
Merged , there is some work left, namely this [x] TextFileService should support to delete/rename/create (?) multiple files [x] Explorer should always use TextFileService [x] Should we enforce time limits for the onWill-events, like onWillSaveTextDocument, or should we only show a status bar message? this is for now 5 sec and comes with a setting [x] Should we blame bad listeners (slow, throwing exceptions...) [x] Should the onWill-events allow to do stuff, like sending off a workspace edits etc Apart from the questions about there is now onWill and onDid event for create, delete, and rename. The design is that these events will fire when the corresponding operations are triggered from the UI (e.g. explorer) or when triggered via the WorkspaceEdit-API. They are not* triggered when using -API or the corresponding internal low level API, e.g when creating a log-file or a temp-folder.
makes sense, i can look into this next week.
This is the current proposal: Can you give it a try/read.

Note the ways in which the event is triggered, e.g via user gestures and but not via OS file events or the -api. Make sense? Surprises?
looks good to me. I think it's worth being explicit in the comments about what happens when a folder is moved though - does it send a single entry with the folder in it, or a collection of all the descendant files? Also - if the move will conflict with existing files (eg. I drag into which already has a ) how will that behave? Will VS Code prompt to overwrite first? Should extensions assume if they get a rename event and a destination already exists, VS Code is going to replace it unconditionally (and if so, would that first fire a delete event?)
Only the folder changes, that to the notes There is no guarantee that the operation will succeed when will-events are created and generally no preparation has been performed yet. The latter shouldn't be too much of a problem because the WorkspaceEdit that listeners can add should generally allow you create folders etc
That's true, but there are weird unfixed bugs like :(
I have api via now the explorer no longer uses the fileService, only for resolving, checking if it can handle a resource and minor things like that. All operations now use the . The only exception being the creation of a folder, since I did not want to introduce notion of folders to the for now. Explorer does not use the bulk api, since the fileService could not reliebly do multiple file operations in parallel. So for now the textFileService does not need this api. Try it out and let me know how it beahves. I just verified that the operations in the explorer work as before. will there be a test plan item for this? I would not mind having some people verify that the explorer actions are working as before. Please let me know if anything else is needed from the Explorer side. Thanks
Yes - be aware that you'll receive the issues for not supporting N-file operation. It's not about running them in parallel but about signalling correctly to the outside world. Simply add a moveN-function that fires an event for all and then talks to the file service sequentially.
yes, makes sense. Thanks
curious what kind of issue you saw when using the file service in parallel with different operations?
that was the older issue almost a year ago.

Some operations would not be executed. I can try it again and let you know if that is still the case
yes please do and file a separate issue