New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(lsp): add a bypass for magit-find-file #6309
Conversation
This looks fine to me, might be better served in lsp-mode though EDIT: After some discussion, I'm going to see if I can propose a fix on magit |
Calling `magit-find-file` in a rust lsp environment causes `#'lsp` to be called again with the contents of the older file instead. This commit seems to resolve it, but I'm not sure if I also have to wrap the let-bind to prevent buffer hooks from being called. See linked issue[1] for more information and a lengthier discussion [1] doomemacs/doomemacs#6309
For that newly-opened buffer to have syntax coloring this function briefly sets buffer-file-name and performs (normal-mode t). This, in turn, triggers related major-mode hooks, which at least in the case of lsp causes issues. Also discussed in doomemacs/doomemacs#6309.
@Patryk27 if you unpin magit locally and |
Hi, I've just checked and unfortunately it remains an issue 😢 |
I'm struggling to replacate, are you sure you have the latest magit changes? |
Yeah, I've ensured by locating the changed Magit's function through |
Yeah I just made a dummy project with If you have a repo you can repro with I'll do a deeper dive later today. |
Sure - a pretty minimal reproduction is:
With those, the scenario goes:
|
Yeah, looks like it works - thanks! 🙂 If that patch gets upstream, then I guess we can close the pull request here. |
I will try, though I don't know how it'll be recieved :p |
Ah wait, sorry - I think I've forgotten to undo my change before applying yours 😅 Starting from a clean Doom Emacs, adding your
... and I think it doesn't load the newer code, so I can't check it |
Okie, I've managed to make it work by exploiting the fact that GitHub stores forks together with their parent repository, so pinning by commit works (even though the commit doesn't really belong to the original Magit's repo):
|
That's not an error, it's intended. Might have to wrap it in |
Back to the drawing board it seems then xD I was confident it was resolved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Magit could implement a minor mode called magit-preview-mode and activate it for all "preview-like" actions; the lsp advice could then exploit the existence of magit-preview-mode instead of hacking around magit-buffer-revision.
Could we use magit-setup-buffer-hook
instead? E.g.
(setq-hook! 'magit-setup-buffer-hook doom-inhibit-local-var-hooks t)
Doom places all its expensive server init hooks on MAJOR-MODE-local-vars-hook
, so this has the benefit of addressing more beyond the lsp-mode use-case.
Hm that's a decent idea, I was hoping for an upstreamable fix but that might work |
Just been pinged by Tarsius; are we happy with this PR? |
Hi, I've just checked and this issue doesn't happen anymore on recent Doom Emacs & Magit, so it seems that fixes on Magit's side were sufficient 🙂 |
I intend to revert the "fix" for this: magit/magit@f331092. As reported in magit/magit#4986 (but I have run into this myself too), that change prevents hook functions from being run, that we actually want to run.
"And stuff" includes running arbitrary functions on major-mode hooks, and I want to bring that back. If I understand the above correctly, the problem is that lsp runs some thing asynchronously and because of what magit does it runs it at the wrong time and/or twice. Could someone please check if 458758b (or similar) still works. If so, would someone volunteer to upstream that to lsp? |
I can try to verify it & merge it at some soon yeah |
This reverts [1: f331092], which disabled it for the benefit of `lsp', which does something that isn't compatible with what we are doing here. At least for the time being, advice the `lsp' function instead, which I have been told, also works around the incompatibility. Fixes #4986. Re #4683. Re doomemacs/doomemacs#6309. 1: 2022-05-08 f331092 magit-revert-rev-file-buffer: Use delay-mode-hook
Fixes #6144.
The Bug
magit-find-file
is a handy function that creates a new buffer containing an older revision of the currently viewed file inside of it.For that newly-opened buffer to have syntax coloring and stuff, Magit briefly sets
buffer-file-name
and performs(normal-mode t)
. This, in turn, triggers related major-mode hooks, such as those which activate lsp -- and you can probably guess where this is going.Becuase Magit doesn't know about lsp (and vice versa), after the buffer gets opened, lsp - being unaware that the buffer is merely a "temporary preview" - thinks the entire file got suddenly replaced with some new content; among others, this misplaces inlay hints and can even make the original buffer unnavigable (since the original buffer's contents are not actually replaced, but lsp thinks otherwise).
The Fix
When you use
magit-find-file
, that newly-opened buffer gets created a local variable calledmagit-buffer-revision
, which contains a Git revision used to read that file; the fix creates an advice around lsp's entry point and exploits that fact, skipping lsp initialization when that variable is present.Drawbacks
Taking a brief look through Magit's code suggests that
magit-buffer-revision
is the correct variable to lay on, but I ain't no Magit hacker - it might be the case that sometimes it's set for regular, file-backed buffers (a bit of testing shows otherwise for the time being, though).Alternatives
magit-preview-mode
Magit could implement a minor mode called
magit-preview-mode
and activate it for all "preview-like" actions; the lsp advice could then exploit the existence ofmagit-preview-mode
instead of hacking aroundmagit-buffer-revision
.lsp-deferred
This whole issue is caused by the fact that Magit has to set
buffer-file-name
, at least for a nanosecond for(normal-mode 1)
to figure out which major mode to activate - in the next tick,buffer-file-name
gets set tonil
anyway.So if we delayed initializing lsp by a single tick - e.g. by calling/hooking
lsp-deferred
instead oflsp
- the issue would be solved, too (since by the time lsp is initialized then,buffer-file-name
would be empty, and lsp itself already has a check for that).Unfortunately, even a single-tick delay introduces nasty UI artifacts - e.g. it makes lsp-headerline appear after that next tick, and this Drives Me Mad ™️ (yes, I've checked it).