godot icon indicating copy to clipboard operation
godot copied to clipboard

Godots script editor overwrites code from external editor when saving (VS Code)

Open sventomasek opened this issue 1 year ago • 3 comments
trafficstars

Tested versions

  • Reproducible in: 4.2.1.stable

System information

Godot v4.2.1.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1070 Ti (NVIDIA; 31.0.15.5123) - AMD Ryzen 7 3700X 8-Core Processor (16 Threads)

Issue description

When a script is open in the Godot editor and I make changes in my external editor, the next time I save in Godot it'll save the old code from Godot's script editor. Sometimes it overwrites the code in the external editor too making me lose progress unless I had the script open in VS Code to undo the changes.

https://github.com/godotengine/godot/assets/61661787/f47a9bd4-c2ab-468b-bbc0-61a6c1c97533

Steps to reproduce

I'm not 100% sure how to consistently reproduce this but I noticed that when I get an error it opens the script in the Godot editor.

  1. make an error in a script and run the game, which should open the script in Godots script editor
  2. make changes to the script in VS Code (add an export variable so you can see if the code reverts back or not in the inspector)
  3. save in VS Code
  4. go back to Godot
  5. save the scene
  6. the code should now revert back to how it was before making the changes, which can be seen by the exported variables disappearing in the inspector

Minimal reproduction project (MRP)

N/A

sventomasek avatar Feb 16 '24 13:02 sventomasek

This nasty bug has been fixed on the master branch: https://github.com/godotengine/godot/pull/82113.

nongvantinh avatar Feb 17 '24 02:02 nongvantinh

Is there a great way to avoid running into this bug aside from building from master (where a fix has been merged) or waiting until the next release is cut? Is it just a matter of not making changes in an external editor while the build is in a failed state with a script focused in the Godot editor?

This bug has bit me several times; it's extremely painful to lose significant amounts of work to, and my paranoia is now slowing me down 😅

azjgard avatar Apr 18 '24 05:04 azjgard

I was able to reproduce this - unintentionally - by connecting signals.

As my file is small - less than 50 lines - I thought I was going mad or exhausted, so I am glad that this Issue exists.

Edit: Seems like #91314, but in my case is with Button, and basically any signal.

igorr0driguez avatar Apr 30 '24 23:04 igorr0driguez

Can anyone still reproduce this issue in Godot 4.3 dev 6 or greater?

raulsntos avatar May 06 '24 01:05 raulsntos

I was able to reproduce this - unintentionally - by connecting signals.

As my file is small - less than 50 lines - I thought I was going mad or exhausted, so I am glad that this Issue exists.

Edit: Seems like #91314, but in my case is with Button, and basically any signal.

This just happened to me with a 400 ln file. MISSION CRITICAL, FOLKS! devastating.

Was able to use the "undo" function in vscodium to restore the file.

Godot v4.2.1.stable unknown - Manjaro Linux #1 SMP PREEMPT_DYNAMIC TKG Tue, 07 Nov 2023 16:38:43 +0000 - X11 - GLES3 (Compatibility) - AMD Radeon RX 6800 (radeonsi, navi21, LLVM 16.0.6, DRM 3.54, 6.6.0-273-tkg-bore) () - AMD Ryzen 7 4700G with Radeon Graphics (16 Threads)

loteque avatar May 09 '24 06:05 loteque

If this happens to you and you're using VSCode, you can often use undo to revert your file. Not a solution, but it might save you if you lose some work.

PokkeFe avatar May 12 '24 05:05 PokkeFe

I've also ran into the same issue multiple times now. I'm gonna try & take a closer look at this.

ptfpinho23 avatar May 19 '24 15:05 ptfpinho23

I've been running into this issue on and off for at least a couple of years now. I think it started sometime around when Godot 4 was in alpha.

leftbones avatar May 24 '24 18:05 leftbones

I think it was introduced by 4.2.beta6, which I guess is caused by this pr #82956 , the built-in text editor does not update the script content when using the external editor.

https://github.com/godotengine/godot/pull/82956/files#diff-611b108c1fab72a983d86a27c5241ed994b00c7e2f9f6a2d43eed8986608b823L2598-R2601

saierXP avatar May 28 '24 14:05 saierXP

I think this problem here is related to what if mentioned in https://github.com/godotengine/godot/pull/82956#issue-1931311539.

The script tabs on the internal Editor should probably be closed in the check but this is not relevant for this problem (engine crash) and more changes are required for it because the trigger is not on the main thread.

As long as there are files loaded in the internal code editor there are event which use them and not the files from the external editor if I remember correct.

Chtau avatar May 28 '24 20:05 Chtau

I have the external editor configured as well. Honestly I'm surprised the internal editor is still available when an external one is configured. I'd welcome a setting that completely removes it (I find it fairly unintuitive that it's a Script setting at the top but the tabs are still the scenes). I keep running into scenarios where a script will get opened in the internal editor (in the background to me) and start to cause problems until I switch over to the Script mode and choose Close All. If I have an external editor configured I'd never expect to see any scripts open in there, yet I do.

Edit: I just found out about this Debug With External Editor setting from this comment. I guess that's a good workaround, but it's fairly maddening how buried this is (why is it not an editor setting? why isn't it the default if an external editor is configured?)

ogapo avatar May 31 '24 13:05 ogapo

(why is it not an editor setting? why isn't it the default if an external editor is configured?)

The reason it isn't the default is likely that some external editors don't have debugging support in the first place, or their extension doesn't support debugging.

I agree it should be moved to editor settings, but whether it should be enabled by default is more debatable. Given the external editors that are typically in use now, having this enabled by default might not be too bad, but it will probably fail pretty badly if your external editor does not have debugging support (or an extension without debugging support).

Calinou avatar Jun 01 '24 09:06 Calinou

That makes sense. I'd love to see it right in the external editor config settings where you set the editor command line up in the first. It'd be so much more discoverable there! Perhaps it could be a dropdown "Debug with External Editor", "Debug with Internal Editor", or "Open with External Editor" with the last one maybe being the safe default.

Before I found this setting I most often observed it opening files automatically when a script would throw an error. I have GodotTools installed but I haven't been able to get it to use the VSCode debugger. That said, I'd still prefer it never open in the internal editor, just being able to see the file and line is often enough, especially if the internal debug panel (which is visible without being in scripts mode) still works.

From a UX perspective, I think I speak for most external editor users that I'd rather have all my files open in a consistent place. I don't ever use the internal editor so I am not familiar with its quirks (the reloading/overwriting of files being the chief annoyance). Having the engine automatically open a script that then lingers in the background there is an unfortunate a experience.

ogapo avatar Jun 01 '24 10:06 ogapo

Reproducible in 4.3Beta2 still. This ones a stinker.

Godot v4.3.beta2 - Linux Mint 21.3 (Virginia) - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3060 Laptop GPU - Intel(R) Core(TM) i5-10500H CPU @ 2.50GHz (12 Threads)

SamDevelopsCode avatar Jul 01 '24 17:07 SamDevelopsCode

I have the external editor configured as well. Honestly I'm surprised the internal editor is still available when an external one is configured. I'd welcome a setting that completely removes it (I find it fairly unintuitive that it's a Script setting at the top but the tabs are still the scenes). I keep running into scenarios where a script will get opened in the internal editor (in the background to me) and start to cause problems until I switch over to the Script mode and choose Close All. If I have an external editor configured I'd never expect to see any scripts open in there, yet I do.

Edit: I just found out about this Debug With External Editor setting from this comment. I guess that's a good workaround, but it's fairly maddening how buried this is (why is it not an editor setting? why isn't it the default if an external editor is configured?)

this bug has been driving me insane and the workaround mentioned on the comment above (the "Debug With External Editor" setting) seems to no longer exist in 4.3-beta2. Am I missing something? I'd love to at least have a temporary workaround to deal with this.

Ideally I'd love to see the internal editor be completely disabled/deactivated in cases where an external editor is configured.

zaftnotameni avatar Jul 05 '24 05:07 zaftnotameni

It doesn't happen only when Godot's script editor is open. It also often happens when or after you click the stop button (or close the game window?) while the game is running. This makes debugging very difficult, because stopping the game also makes all the error messages disappear, so you kind of have to leave it until after you've fixed the code. Then Godot reverts all the bugs you've just fixed! It doesn't happen every time, but often enough to be a major nuisance.

realh avatar Jul 08 '24 11:07 realh

Please be aware, guys, that I have debugged this issue before, and it turns out that this piece of code is overriding your work with cached data.

https://github.com/godotengine/godot/blob/ec02d406ca0b9c822addff49cf58e9a72cf74eb0/editor/editor_node.cpp#L1772-L1783

In the past, I have allowed the editor to load external changes to scripts (https://github.com/godotengine/godot/pull/82113), but it seems like there are still some instances where the code does not get the newest changes to your scripts. Remember, the fix (#82113) will check if it is a valid script and is not opened by the internal editor. If so, it will update the cached object with the newest changes. I'm not sure what conditions are met on your side :satisfied:

nongvantinh avatar Jul 08 '24 13:07 nongvantinh

It looks like "the fix" was merged into the master branch in September 2023, yet multiple people (including myself) have experienced the problem persisting to this day – in which case I would argue that it is not a fix 😅.

I'm still not even sure how to reliably replicate the behavior, but I suppose if I'm able to figure out a way, I suppose we can start looking at the conditions while doing the replication to see what's causing the fix to not work.

Meorge avatar Jul 08 '24 14:07 Meorge

I'm not trying to start an argument, but your comment does not provide much information to help resolve the problem.

When I was debugging this issue, I found the exact location and the reason why it behaves that way. That's why I created the PR. It has been tested by multiple people and has been confirmed to fix the issue using the reproducible method. However, given the size of this project, I'm aware that my PR does not fully fix the issue, but the cause remains the same. I commented it here so that anyone interested can use that information to start debugging by themselves.

nongvantinh avatar Jul 08 '24 14:07 nongvantinh

No worries – the point of my comment was just that the issue is still definitely occurring, so we shouldn't consider it fixed.

Having the location of the bad behavior pinned down to a specific block of code is definitely great, so we can continue debugging it and determine why the current fix isn't working in all cases. I'll see what I can do in the coming days to reproduce the issue and from there, determine what might be causing it to persist.

Meorge avatar Jul 08 '24 15:07 Meorge

It looks like "the fix" was merged into the master branch in September 2023, yet multiple people (including myself) have experienced the problem persisting to this day – in which case I would argue that it is not a fix 😅.

I'm still not even sure how to reliably replicate the behavior, but I suppose if I'm able to figure out a way, I suppose we can start looking at the conditions while doing the replication to see what's causing the fix to not work.

I've been able to replicate that with 100% success (4.3-beta2 - windows, non-c# version of godot) by:

  1. configure godot to use an external editor, in particular an editor that doesn't play well with the debugging protocol (i've had it happen with both neovim and vscode)
  2. introduce some error on my script that would cause godot to stop automatically as a breakpoint.
  3. run the project, this causes the script to be opened in the internal script editor (because of the error acting as a breakpoint - and either the external editor doesn't support the debug protocol or the connection has been lost)
  4. hit the stop button (do not close the script in the internal editor)
  5. switch back to 2d/3d view on godot
  6. on your external editor, make changes to the script that is already opened in the internal editor
  7. go to godot and run the project again

Expected: the changes from the external editor are more recent, when running the project it notices that and updates the buffer for the script that is open in the internal editor. The new version of the code runs (from the external editor)

Observed: the old version in the internal editor is saved to disk, overriding the newer changes made in the external editor. The old version of the code runs (from the internal editor). Going back to the external editor shows that the file has been updated in the filesystem (with the old version).

My preferred solution would be: if an external editor is configured, under no circumstances the internal editor should open for scripts (or at least make it a setting hidden behind the "advanced settings" toggle). This would eliminate any and all scenarios where this problem could happen, instead of chasing after fixing case by case.

zaftnotameni avatar Jul 08 '24 17:07 zaftnotameni

Strangely, I tried following the steps you laid out and couldn't reproduce (4.3-beta2, macOS, non-C#). VS Code is set as my external editor.

https://github.com/godotengine/godot/assets/9957987/bd3e875b-bcc0-4464-89fe-a6dacbf2e46d

The one big difference I noticed between the steps you described and what I did is that the editor's internal script editor doesn't open for me when it hits the assert statement.

If I disable the godot-tools extension in VS Code, then when I modify the script in VS Code, I get a popup about files being newer on disk:

CleanShot 2024-07-08 at 11 05 35@2x

This popup is nice, definitely better than it just undoing my changes, but I'm pretty sure this is not the same thing as the bug being discussed here 😅. I could've sworn the issue was occurring for me (with no popup) when godot-tools was active and connected to the language server.

Meorge avatar Jul 08 '24 18:07 Meorge

Strangely, I tried following the steps you laid out and couldn't reproduce (4.3-beta2, macOS, non-C#). VS Code is set as my external editor.

Godot.4.3-beta2.Not.Replicating.External.Editor.Overwrite.Bug.mp4 The one big difference I noticed between the steps you described and what I did is that the editor's internal script editor doesn't open for me when it hits the assert statement.

If I disable the godot-tools extension in VS Code, then when I modify the script in VS Code, I get a popup about files being newer on disk:

CleanShot 2024-07-08 at 11 05 35@2x

This popup is nice, definitely better than it just undoing my changes, but I'm pretty sure this is not the same thing as the bug being discussed here 😅. I could've sworn the issue was occurring for me (with no popup) when godot-tools was active and connected to the language server.

if the popup is from godot, then you are indeed seeing something different if the popup is from vscode, then we are talking about the same thing (some editors will show a popup, some will just load the new contents, depending on configuration)

the problem happens once godot tries to debug something with an external editor and for some reason (either the editor doesn't support it, or connection is lost) it cannot debug using the external editor and instead uses the internal one... from that point onward the problem is persistent until you manually close the script open in the internal editor

I wonder if it's OS dependent as well (maybe differences in how each OS updates timestamps of files?)

zaftnotameni avatar Jul 08 '24 19:07 zaftnotameni

The popup is from Godot, so I suppose it is a different thing then. Whenever I've had the issue with VS Code, the godot-tools extension has been running and there is no indication (such as a popup window) that the contents were reverted, except that I go back to the VS Code window and the file is what it had been before I made changes. In the past I hadn't paid close attention to whether or not VS Code was connected to the Godot language server, but will try to keep an eye out for it in the future.

Meorge avatar Jul 08 '24 20:07 Meorge

It looks like "the fix" was merged into the master branch in September 2023, yet multiple people (including myself) have experienced the problem persisting to this day – in which case I would argue that it is not a fix 😅. I'm still not even sure how to reliably replicate the behavior, but I suppose if I'm able to figure out a way, I suppose we can start looking at the conditions while doing the replication to see what's causing the fix to not work.

I've been able to replicate that with 100% success (4.3-beta2 - windows, non-c# version of godot) by:

1. configure godot to use an external editor, in particular an editor that doesn't play well with the debugging protocol (i've had it happen with both neovim and vscode)

2. introduce some error on my script that would cause godot to stop automatically as a breakpoint.

3. run the project, this causes the script to be opened in the internal script editor (because of the error acting as a breakpoint - and either the external editor doesn't support the debug protocol or the connection has been lost)

4. hit the stop button (do not close the script in the internal editor)

5. switch back to 2d/3d view on godot

6. on your _external_ editor, make changes to the script that is already opened in the internal editor

7. go to godot and run the project again

Expected: the changes from the external editor are more recent, when running the project it notices that and updates the buffer for the script that is open in the internal editor. The new version of the code runs (from the external editor)

Observed: the old version in the internal editor is saved to disk, overriding the newer changes made in the external editor. The old version of the code runs (from the internal editor). Going back to the external editor shows that the file has been updated in the filesystem (with the old version).

My preferred solution would be: if an external editor is configured, under no circumstances the internal editor should open for scripts (or at least make it a setting hidden behind the "advanced settings" toggle). This would eliminate any and all scenarios where this problem could happen, instead of chasing after fixing case by case.

image Godot v4.3.beta (ec02d406c) - Arch Linux #1 SMP PREEMPT_DYNAMIC Fri, 31 May 2024 15:14:45 +0000 - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1650 (nvidia; 550.78) - Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz (8 Threads) image

well this is awkward...

radiantgurl avatar Jul 11 '24 19:07 radiantgurl

Is there a way to completely disable the Godot code editor? This issue consistently is blocker, causes me to not trust myself or my editors for short periods of time, often -- gonna be death by a thousand cuts.

loteque avatar Aug 09 '24 17:08 loteque

Is there a way to completely disable the Godot code editor? This issue consistently is blocker, causes me to not trust myself or my editors for short periods of time, often -- gonna be death by a thousand cuts.

Yeah, take a look at This Comment. It worked for me in fixing this issue, as well as the issue that it links to in regards to not opening the external editor from errors (which I think is what was causing the issue of my code being overwritten too).

RobTheFiveNine avatar Aug 14 '24 12:08 RobTheFiveNine

Is there a way to completely disable the Godot code editor? This issue consistently is blocker, causes me to not trust myself or my editors for short periods of time, often -- gonna be death by a thousand cuts.

Yeah, take a look at This Comment. It worked for me in fixing this issue, as well as the issue that it links to in regards to not opening the external editor from errors (which I think is what was causing the issue of my code being overwritten too).

Even just based on how that setting is named, I wouldn't have guessed it would fix this issue. It's definitely not clear at all.

leftbones avatar Aug 14 '24 16:08 leftbones

Is there a way to completely disable the Godot code editor? This issue consistently is blocker, causes me to not trust myself or my editors for short periods of time, often -- gonna be death by a thousand cuts.

Yeah, take a look at This Comment. It worked for me in fixing this issue, as well as the issue that it links to in regards to not opening the external editor from errors (which I think is what was causing the issue of my code being overwritten too).

Thank you RobTheFiveNine. For me this is a serviceable workaround for the time being. It is not, however, a precise solution to the workflow which lot of us are using and unexpected behavior from Godot is still occurring under the conditions described below. That workflow would be to compose in vscode(ium) and debug in Godot. The debugger in Godot has features not available in vscode, for instance the ability to drill down into objects and see their properties as they appear in the inspector.

So there are two requirements for this issue to be resolved.

PROBLEM: Godot opens files AND Godot changes files in userland without consent of user.

  1. The internal editor must not open scripts when using an external editor under any circumstance. (It most certainly should not be making changes to files in userland without user consent.)

PROBLEM: User cannot access features of Godot debug interface while using an external editor

  2. The User should be able to have access to in-editor debug features when debugging with external editor; 

  2a. User should be able to debug in Godot without Godot opening or changing files.

What the comment suggests is turning of editor debugging (shown in the attached image.) Assuming that means it will stop the internal editor from opening the file and overwriting it - we have: solved issue one but: issue two is unresolved.

image

loteque avatar Aug 14 '24 17:08 loteque

Connecting any signals to a script that is opened in the internal editor will also revert scripts opened in external to the internal version.

Morokiane avatar Aug 21 '24 14:08 Morokiane