joaotavora / eglot

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

eglot--connect: Symbol’s function definition is void: project-root #549

Closed bcmills closed 4 years ago

bcmills commented 4 years ago

Steps to reproduce

  1. Install eglot 20200830.1254 using the Emacs package menu.
  2. Install gopls v0.5.0 using the instructions at https://github.com/golang/tools/blob/master/gopls/doc/user.md#installation.
  3. Install the go toolchain from source using the instructions at https://golang.org/doc/install/source.
  4. (cd $(go env GOROOT)/src/cmd && emacs -nw ./go/internal/modload/load.go)
  5. M-x eglot

Expected behavior

Eglot starts successfully.

Observed behavior

In the *Messages* buffer and the minibuffer:

eglot--connect: Symbol’s function definition is void: project-root

The eglot-events-buffer command requested in https://github.com/joaotavora/eglot#reporting-bugs does not work, because eglot does not finish initializing.

Backtrace

Debugger entered--Lisp error: (void-function project-root)
  project-root((transient . "~/go/src/cmd/go/internal/modload/"))
  eglot--connect(go-mode (transient . "~/go/src/cmd/go/internal/modload/") eglot-lsp-server ("gopls"))
  eglot(go-mode (transient . "~/go/src/cmd/go/internal/modload/") eglot-lsp-server ("gopls") t)
  funcall-interactively(eglot go-mode (transient . "~/go/src/cmd/go/internal/modload/") eglot-lsp-server ("gopls") t)
  #<subr call-interactively>(eglot record nil)
  apply(#<subr call-interactively> eglot (record nil))
  call-interactively@ido-cr+-record-current-command(#<subr call-interactively> eglot record nil)
  apply(call-interactively@ido-cr+-record-current-command #<subr call-interactively> (eglot record nil))
  call-interactively(eglot record nil)
  command-execute(eglot record)
  execute-extended-command(nil "eglot" "egl")
  funcall-interactively(execute-extended-command nil "eglot" "egl")
  #<subr call-interactively>(execute-extended-command nil nil)
  apply(#<subr call-interactively> execute-extended-command (nil nil))
  call-interactively@ido-cr+-record-current-command(#<subr call-interactively> execute-extended-command nil nil)
  apply(call-interactively@ido-cr+-record-current-command #<subr call-interactively> (execute-extended-command nil nil))
  call-interactively(execute-extended-command nil nil)
  command-execute(execute-extended-command)
joaotavora commented 4 years ago

Thanks, it seems to be that however you isntalled eglot, it didn't successfully pull it its project dependency. This is similar to #518 or #491. A number of conditions can lead up to this, but they are all related to a mis-installed project. It should be the one listed here https://elpa.gnu.org/packages/project.html. Alternatively, an Emacs running from the master branch can be used.

joaotavora commented 4 years ago

(closing this, since it is a duplicate. Which doesn't mean that the conversation can't proceed, or that I won't re-open it eventually).

bcmills commented 4 years ago

That's surprising, given that I installed eglot using the Emacs package menu. (package-list-packages reports project 0.5.2, which is marked as current on https://elpa.gnu.org/packages/project.html.)

joaotavora commented 4 years ago

yep, and that's a valid way of installing it. Sometimes there are bootstrap problems. Do you mind restarting your Emacs and seeing what M-x find-library RET project RET results in?

bcmills commented 4 years ago

M-x find-library RET project RET gives me a source code listing for project.el with the following:

;;; project.el --- Operations on the current project  -*- lexical-binding: t; -*-

;; Copyright (C) 2015-2020 Free Software Foundation, Inc.
;; Version: 0.5.2
;; Package-Requires: ((emacs "26.3") (xref "1.0.2"))

;; This is a GNU ELPA :core package.  Avoid using functionality that
;; not compatible with the version of Emacs recorded above.

;; This file is part of GNU Emacs.

The source file is loaded from ~/.emacs.d/elpa/project-0.5.2/project.el.

joaotavora commented 4 years ago

And what does C-h f project-root RET show?

bcmills commented 4 years ago
project-roots is a compiled Lisp function in ‘project.el’.

(project-roots PROJECT)

Return the list of directory roots of the current project.

Most often it’s just one directory which contains the project
build file and everything else in the project.  But in more
advanced configurations, a project can span multiple directories.

The directory names should be absolute.

This is a generic function.

Implementations:

((project (head vc))) in ‘project.el’.

Undocumented

((project (head transient))) in ‘project.el’.

Undocumented
joaotavora commented 4 years ago

That's project-roots, plural. Can you just confirm you can't find the description for project-root singular ?

bcmills commented 4 years ago

M-x ielm:

*** Welcome to IELM ***  Type (describe-mode) for help.
ELISP> (describe-function 'project-root)
*** Eval error ***  Symbol’s function definition is void: project-root
ELISP> (describe-function 'project-roots)
#("project-roots is a compiled Lisp function in ‘project.el’.

(project-roots PROJECT)

Return the list of directory roots of the current project.

Most often it’s just one directory which contains the project
build file and everything else in the project.  But in more
advanced configurations, a project can span multiple directories.

The directory names should be absolute.

This is a generic function.

Implementations:

((project (head vc))) in ‘project.el’.

Undocumented

((project (head transient))) in ‘project.el’.

Undocumented

" 46 56
(help-args
 (project-roots "/usr/share/google-emacs/27.1+gg3+1.20200824.053401.rc115/lisp/progmodes/project.el")
 category help-function-def-button button
 (t))
75 82
(face help-argument-name)
404 422
(face bold)
448 458
(help-args
 ((project-roots nil
                 (head vc))
  "/usr/share/google-emacs/27.1+gg3+1.20200824.053401.rc115/lisp/progmodes/project.el" cl-defmethod)
 category help-function-def-button button
 (t))
509 519
(help-args
 ((project-roots nil
<                 (head transient))
  "/usr/share/google-emacs/27.1+gg3+1.20200824.053401.rc115/lisp/progmodes/project.el" cl-defmethod)
 category help-function-def-button button
 (t)))

ELISP> 
bcmills commented 4 years ago

Looks like that API was changed in https://github.com/emacs-mirror/emacs/commit/5044c19001fe608f2eac621add2e05cbca6c804b.

(I guess that's the downside of using an experimental API. 😞)

joaotavora commented 4 years ago

Looks like that API was changed in emacs-mirror/emacs@5044c19.

No, you're on the wrong track. THe problem is that somehow your "google emacs" setup is preventing the 0.5.2 version of the project.el library, which we've established lives in ~/.emacs.d/elpa/project-0.5.2/project.el, from being loaded.

bcmills commented 4 years ago

Aha, neato! I'll have to look into that and get back to you. Thanks for all the help tracking this down!

bcmills commented 4 years ago

I figured out that the built-in project was being loaded (somehow‽) during package-activate-all, which to me suggested that some package's -autoloads.el was erroneously loading it.

I noticed that package-list-packages was reporting a lot of external packages, and tracked those down to some preinstalled Debian packages from my distro. I ran sudo apt-get remove elpa-* to remove them, and now eglot seems to be loading fine.

I'm still not sure exactly which package it was, but I'm always happy to fix problems by uninstalling things.

Thanks again for the debugging help!

joaotavora commented 4 years ago

I'm always happy to fix problems by uninstalling things.

Almost as good as fixing bugs by deleting code. That's without deleting all the program or uninstalling the OS, that is.

finalclass commented 3 years ago

I had the similar problem. In my case emacs was using built in project.el found in /usr/local/share/emacs/27.0.91/lisp/progmodes/project.el I've removed this file (and project.el.gz file) and then copied project.el@0.5.2 from elpa, placed it in my custom libs under .emacs.d and in init.el added:

(require 'project)

Then after restarting it started to work. It would be nice if eglot would work fine with project.el shipped with emacs 27 so please reopen the issue.

dowgird commented 3 years ago

I had the same problem, but I decided not to delete the shared project.{el.,el.gz} files.

I forced the correct version by putting (load-file "/home/dowgird/.emacs.d/elpa/project-0.5.3/project.el") in my .emacs.d/early-init.el.

This worked but it feels like masking the actual problem rather than fixing it. Do we know why Emacs chooses the shared version of project.el over the one installed from ELPA?

kkonevets commented 3 years ago

I had the similar problem. In my case emacs was using built in project.el found in /usr/local/share/emacs/27.0.91/lisp/progmodes/project.el I've removed this file (and project.el.gz file) and then copied project.el@0.5.2 from elpa, placed it in my custom libs under .emacs.d and in init.el added:

(require 'project)

Then after restarting it started to work. It would be nice if eglot would work fine with project.el shipped with emacs 27 so please reopen the issue.

Yes, that helped!

I did (use-package project :ensure t)

jjba23 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)
    )