joaotavora / eglot

A client for Language Server Protocol servers
GNU General Public License v3.0
2.21k stars 203 forks source link

eglot--connect: Symbol’s function definition is void: project-name #1193

Closed jaybarra closed 1 year ago

jaybarra commented 1 year ago

Environment

Emacs for Mac 28.2 eglot-1.13

Reproduction Steps

  1. Ensure the clangd LSP server is installed and available in path
  2. Delete or rename ~/.emacs.d
  3. Recreate ~/.emacs.d directory
  4. Recreate ~/.emacs.d/init.el with the following contents
    
    ;;; init.el --- Minimum eglot example
    ;;; Commentary:
    ;;; Code:

(unless (fboundp 'package-activate-all) (package-initialize))

;;; init.el ends here

4. Open Emacs
5. `M-x package-install RET eglot RET`
6. `M-x make-directory RET eglot-mre RET`
7. `C-x C-f ~/eglot-mre/main.c RET`
8. Fill with the following
```c
/* main.c */
int main(int argc, char *argv[]) {
  return 0;
}
  1. C-x C-s
  2. M-x eglot and receive this error in the *Messages* buffer eglot--connect: Symbol’s function definition is void: project-name
joaotavora commented 1 year ago

Reproduced. The problem goes away simply restarting Emacs.

I don't understand why project.el is being loaded as part of the package-install process of Eglot.

joaotavora commented 1 year ago

I don't understand why project.el is being loaded as part of the package-install process of Eglot.

Or rather, I do understand that, eglot.el has a (require 'project) which is run at compilation time.
But I don't understand why is it that, if project.el is a dependency of Eglot, and thus must be installed before, why it isn't in place already when this require happens.

Maybe @monnier can shed some light?

basil-conto commented 1 year ago

Is this [similar to] https://bugs.gnu.org/61048 ?

I.e. is Emacs 28.2 picking up the built-in project that lacks project-name, rather than the more recent version of project required by Eglot?

joaotavora commented 1 year ago

I.e. is Emacs 28.2 picking up the built-in project that lacks project-name, rather than the more recent version of project required by Eglot?

Yes. And this can happen if you have previously loaded the build in project.el before you issue M-x package-install RET eglot RET. But in this recipe, you'll notice that (featurep 'project) reports nil in the beginning. So at a certain point, the old built-in project.el is loaded, when, AFAICT only eglot.el 's compilation require s it. And by that time, the new version should have been installed already, becasue project.el is a dependency of eglot.el.

Is this [similar to] https://bugs.gnu.org/61048 ?

I'll have a look.

joaotavora commented 1 year ago

Is this [similar to] https://bugs.gnu.org/61048 ?

I don't think so. I think there the problem was the failure to pull in a transitive dependency right?

Here, it's -- I presume -- not having the right load-path setup by the time that the (require 'project) happens.

monnier commented 1 year ago

Or rather, I do understand that, eglot.el has a (require 'project) which is run at compilation time.
But I don't understand why it is that, if project.el is a dependency of Eglot, and thus must be installed before, why it isn't in place already when this require happens.

Maybe @monnier can shed some light?

AFAIK package.el has code that intends to handle this correctly, so it sounds like either a bug in that code, or some funny interaction somewhere causes project.el to be loaded somehow before package.el tweaks the load path to include the updated project package.

joaotavora commented 1 year ago

In the meantime, I think the best is for eglot to replace (require 'project) with (load "project") right? It's a bit unidiomatic, but I see no better way to protect users against this.

The problem can still happen very easily if you decide to M-x package-install RET eglot after doing some project.el things.

Unless we force the dependent libraries to be loaded after each package-install. Not pretty, but safer.

monnier commented 1 year ago

In the meantime, I think the best is for eglot to replace (require 'project) with (load "project") right? It's a bit unidiomatic, but I see no better way to protect users against this.

In theory that should not be necessary because package.el should itself reload project.el after setting up the new path (if project.el had been loaded earlier).

joaotavora commented 1 year ago

In theory that should not be necessary because package.el should itself reload project.el after setting up the new path (if project.el had been loaded earlier).

So can you follow Jay's reproduction recipe and find out why this isn't happening?

João

monnier commented 1 year ago

So can you follow Jay's reproduction recipe and find out why this isn't happening?

I don't have much time to dig into this now. Maybe the best bet is to M-x report-emacs-bug with this recipe (and put me in X-Debbug-Cc`) so there's less risk that I forget about it.

joaotavora commented 1 year ago

Done, here's the report.

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=62576

In the meaning, i think I'll put the load statements there.

joaotavora commented 1 year ago

In the meaning, i think I'll put the load statements there.

This is now in Eglot 1.14, I've just tested this recipe and it doesn't error anymore. Please test and report back here to reopen if it doesn'twork.

OrdoFlammae commented 1 year ago

I just ran into this, and I had to explicitly (require 'eglot) before doing anything (I was originally using the autoloaded eglot function to load the library). I'm not sure if this can be fixed, or if it will just need to be mentioned as a workaround.

EDIT: A Minimum Reproducible Example is in the works, I apologize, I posted this hastily. EDIT 2: I could not quite reproduce with a basic example, my guess is that my issue was dependent on my particular setup (the straight package manager, in particular). If anyone does run into this issue, where any of the project.el functions are being used from the built in version, rather than the version installed with eglot, just make sure to run (require 'eglot) somewhere so that the new version of project.el is used.

joaotavora commented 1 year ago

I just ran into this

Can you explain exactly how you ran into this? There are many possible ways to "run into this". Your require eglot doesn't make much sense.

So please, if you can, provide a Minimum Reproducible Example just like @jaybarra did.

teutonicjoe commented 1 year ago

For people using ELPACA (i am on Emacs 28.2), you need to install project first:

  (defun my-eglot-organize-imports () (interactive)
         (eglot-code-actions nil nil "source.organizeImports" t))

  (use-package project :demand t)

  (use-package eglot
    :demand t
    :after (project projectile)
    :hook (
           (scala-mode . eglot-ensure)
           (sh-mode . eglot-ensure)
           (python-mode . eglot-ensure)
           (java-mode . eglot-ensure)
           (yaml-mode . eglot-ensure)
           (haskell-mode . eglot-ensure)
           (go-mode . eglot-ensure)
           (dockerfile-mode . eglot-ensure)
           )
    :config
    (add-hook 'before-save-hook 'my-eglot-organize-imports nil t)
    (add-hook 'before-save-hook 'eglot-format-buffer)
    )