diff --git a/modules/tools/debugger/packages.el b/modules/tools/debugger/packages.el index 936fc4e6d..ea81f3d5b 100644 --- a/modules/tools/debugger/packages.el +++ b/modules/tools/debugger/packages.el @@ -1,10 +1,10 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/debugger/packages.el -(when (package! realgud :pin "de31e772092bf40cdc7de4ab3c63efe04f8e6736") +(when (package! realgud :pin "5b0ed08364b1f5e2df2f3f7d5a6e7a2fedb5189a") (when (featurep! :lang javascript) (package! realgud-trepan-ni :pin "6e38cf838c7b47b5f1353d00901b939ffa36d707"))) (when (featurep! +lsp) - (package! dap-mode :pin "8c59b0a4dd0372c0b4efc74d021443894a9bd470") - (package! posframe :pin "b3028b01a96699b1dfc9b2b5f4e3ba2bc1aa8317")) + (package! dap-mode :pin "85a61630499bb836bdb378fb62ea4ddd4f61a2dd") + (package! posframe :pin "6d604a71deb45295f7b6ff3f98e06aeece9888be")) diff --git a/modules/tools/lsp/+lsp.el b/modules/tools/lsp/+lsp.el index f919519a2..148051b2e 100644 --- a/modules/tools/lsp/+lsp.el +++ b/modules/tools/lsp/+lsp.el @@ -12,36 +12,44 @@ Can be a list of backends; accepts any value `company-backends' accepts.") :commands lsp-install-server :init (setq lsp-session-file (concat doom-etc-dir "lsp-session")) - ;; Auto-kill LSP server after last workspace buffer is killed. - (setq lsp-keep-workspace-alive nil) ;; For `lsp-clients' - (setq lsp-server-install-dir (concat doom-etc-dir "lsp/") - lsp-intelephense-storage-path (concat doom-cache-dir "lsp-intelephense/")) + (setq lsp-server-install-dir (concat doom-etc-dir "lsp/")) + ;; Don't auto-kill LSP server after last workspace buffer is killed, because I + ;; will do it for you, after `+lsp-defer-shutdown' seconds. + (setq lsp-keep-workspace-alive nil) + ;; Let doom bind the lsp keymap. (when (featurep! :config default +bindings) - ;; Let doom bind the lsp keymap. (setq lsp-keymap-prefix nil)) - ;; Disable LSP's superfluous, expensive and/or debatably unnecessary features. - ;; Some servers implement these poorly. Better to just rely on Emacs' native - ;; mechanisms and make these opt-in. - (setq lsp-enable-folding nil + ;; NOTE I tweak LSP's defaults in order to make its more expensive or imposing + ;; features opt-in. Some servers implement these poorly and, in most + ;; cases, it's safer to rely on Emacs' native mechanisms (eldoc vs + ;; lsp-ui-doc, open in popup vs sideline, etc). + + ;; Disable features that have great potential to be slow. + (setq lsp-enable-file-watchers nil + lsp-enable-folding nil ;; HACK Fix #2911, until it is resolved upstream. Links come in ;; asynchronously from the server, but lsp makes no effort to ;; "select" the original buffer before laying them down, so they ;; could be rendered in the wrong buffer (like the minibuffer). - lsp-enable-links nil - ;; Potentially slow - lsp-enable-file-watchers nil - lsp-enable-text-document-color nil - lsp-enable-semantic-highlighting nil - ;; Don't modify our code without our permission - lsp-enable-indentation nil - lsp-enable-on-type-formatting nil - ;; capf is the preferred completion mechanism for lsp-mode now - lsp-prefer-capf t) + lsp-enable-links t + lsp-enable-text-document-color nil) + + ;; Disable features that modify our code without our permission. + (setq lsp-enable-indentation nil + lsp-enable-on-type-formatting nil) :config + (setq lsp-intelephense-storage-path (concat doom-cache-dir "lsp-intelephense/") + lsp-vetur-global-snippets-dir (expand-file-name "vetur" + (or (bound-and-true-p +snippets-dir) + (concat doom-private-dir "snippets/"))) + lsp-clients-emmy-lua-jar-path (concat lsp-server-install-dir "EmmyLua-LS-all.jar") + lsp-xml-jar-file (concat lsp-server-install-dir "org.eclipse.lsp4xml-0.3.0-uber.jar") + lsp-groovy-server-file (concat lsp-server-install-dir "groovy-language-server-all.jar")) + (set-popup-rule! "^\\*lsp-help" :size 0.35 :quit t :select t) (set-lookup-handlers! 'lsp-mode :async t :documentation #'lsp-describe-thing-at-point @@ -50,97 +58,56 @@ Can be a list of backends; accepts any value `company-backends' accepts.") :type-definition #'lsp-find-type-definition :references #'lsp-find-references) - ;; TODO Lazy load these. They don't need to be loaded all at once unless the - ;; user uses `lsp-install-server'. - (when lsp-auto-configure - (mapc (lambda (package) (require package nil t)) - lsp-client-packages)) - - (defadvice! +lsp-init-a (&optional arg) - "Enable `lsp-mode' in the current buffer. - -Meant to gimp `lsp', which is too eager about installing LSP servers, or -prompting to do so, or complaining about no LSP servers, or initializing -lsp-ui-mode, company, yasnippet and flycheck. We want LSP to work only if the -server is present, and for server installation to be a deliberate act by the -end-user. Also, setting up these other packages are handled by their respective -modules. - -Also see: -+ `+lsp-init-company-h' (on `lsp-mode-hook') -+ `+lsp-init-flycheck-or-flymake-h' (on `lsp-mode-hook') - -This also logs the resolved project root, if found, so we know where we are." - :override #'lsp - (interactive "P") - (and (buffer-file-name (buffer-base-buffer)) - (require 'lsp-mode nil t) - (setq-local - lsp--buffer-workspaces - (or (lsp--try-open-in-library-workspace) - (lsp--try-project-root-workspaces - (equal arg '(4)) - (and arg (not (equal arg 1)))))) - ;; read-process-output-max is only available on recent - ;; development builds of Emacs 27 and above - (or (not (boundp 'read-process-output-max)) - (setq-local read-process-output-max (* 1024 1024))) - ;; REVIEW LSP causes a lot of allocations, with or without Emacs 27+'s - ;; native JSON library, so we up the GC threshold to stave off - ;; GC-induced slowdowns/freezes. - (setq-local gcmh-high-cons-threshold (* 2 gcmh-high-cons-threshold)) - (prog1 (lsp-mode 1) - (setq lsp-buffer-uri (lsp--buffer-uri)) - ;; Announce what project root we're using, for diagnostic purposes - (if-let (root (lsp--calculate-root (lsp-session) (buffer-file-name))) - (lsp--info "Guessed project root is %s" (abbreviate-file-name root)) - (lsp--info "Could not guess project root.")) - (lsp--info "Connected to %s." - (apply #'concat - (mapcar - (lambda (it) (format "[%s]" (lsp--workspace-print it))) - lsp--buffer-workspaces)))))) - + ;; REVIEW The ' c l' prefix is hardcoded here, unfortunately. (when (featurep! :config default +bindings) (dolist (leader-key (list doom-leader-key doom-leader-alt-key)) (let ((lsp-keymap-prefix (concat leader-key " c l"))) (lsp-enable-which-key-integration)))) + (defadvice! +lsp--dont-auto-install-servers-a (orig-fn &rest args) + "Don't auto-install LSP servers. Only complain if there aren't available." + :around #'lsp + ;; `lsp' is normally eager to automatically install LSP servers, or + ;; prompting to do so, but (in my opinion) server installation should be a + ;; deliberate act by the end-user: + (letf! (defun lsp--client-download-server-fn (&rest _)) + (apply orig-fn args))) + (add-hook! 'lsp-mode-hook - (defun +lsp-init-company-h () - (if (not (bound-and-true-p company-mode)) - (add-hook 'company-mode-hook #'+lsp-init-company-h t t) - ;; Ensure `company-capf' is at the front of `company-backends' - (setq-local company-backends - (cons +lsp-company-backends - (remove +lsp-company-backends - (remq 'company-capf company-backends)))) - (remove-hook 'company-mode-hook #'+lsp-init-company-h t))) - (defun +lsp-init-flycheck-or-flymake-h () - "Set up flycheck-mode or flymake-mode, depending on `lsp-diagnostic-package'." - (pcase lsp-diagnostic-package - ((or :auto 'nil) ; try flycheck, fall back to flymake - (let ((lsp-diagnostic-package - (if (require 'flycheck nil t) :flycheck :flymake))) - (+lsp-init-flycheck-or-flymake-h))) - ((or :flymake 't) - (lsp--flymake-setup)) - (:flycheck - ;; Ensure file/dir local `flycheck-checker' is respected - (unless flycheck-checker - (if (flycheck-checker-supports-major-mode-p 'lsp major-mode) - (lsp-flycheck-enable) - (let ((old-checker (flycheck-get-checker-for-buffer))) - (lsp-flycheck-enable) - (when old-checker - (flycheck-add-next-checker 'lsp old-checker)))) - (kill-local-variable 'flycheck-checker)))))) + (defun +lsp-init-optimizations-h () + "Increase `read-process-output-max' and `gcmh-high-cons-threshold'." + ;; `read-process-output-max' is only available on recent development + ;; builds of Emacs 27 and above. + (unless (boundp 'read-process-output-max) + (setq-local read-process-output-max (* 1024 1024))) + ;; REVIEW LSP causes a lot of allocations, with or without Emacs 27+'s + ;; native JSON library, so we up the GC threshold to stave off + ;; GC-induced slowdowns/freezes. Doom uses `gcmh' to enforce its GC + ;; strategy, so we modify its variables rather than + ;; `gc-cons-threshold' directly. + (setq-local gcmh-high-cons-threshold (* 2 (default-value 'gcmh-high-cons-threshold)))) + (defun +lsp-display-guessed-project-root-h () + "Log what LSP things is the root of the current project." + ;; Makes it easier to detect root resolution issues. + (when-let (path (buffer-file-name (buffer-base-buffer))) + (if-let (root (lsp--calculate-root (lsp-session) path)) + (lsp--info "Guessed project root is %s" (abbreviate-file-name root)) + (lsp--info "Could not guess project root."))))) + + (add-hook! 'lsp-completion-mode-hook + (defun +lsp-init-company-backends-h () + (when lsp-completion-mode + (set (make-local-variable 'company-backends) + (cons +lsp-company-backends + (remove +lsp-company-backends + (remq 'company-capf company-backends))))))) (defvar +lsp--deferred-shutdown-timer nil) (defadvice! +lsp-defer-server-shutdown-a (orig-fn &optional restart) "Defer server shutdown for a few seconds. This gives the user a chance to open other project files before the server is -auto-killed (which is a potentially expensive process)." +auto-killed (which is a potentially expensive process). It also prevents the +server getting expensively restarted when reverting buffers." :around #'lsp--shutdown-workspace (if (or lsp-keep-workspace-alive restart @@ -156,10 +123,7 @@ auto-killed (which is a potentially expensive process)." (let ((lsp--cur-workspace workspace)) (unless (lsp--workspace-buffers lsp--cur-workspace) (funcall orig-fn)))) - lsp--cur-workspace)))) - - ;; Don't prompt to restart LSP servers while quitting Emacs - (add-hook! 'kill-emacs-hook (setq lsp-restart 'ignore))) + lsp--cur-workspace))))) (use-package! lsp-ui diff --git a/modules/tools/lsp/packages.el b/modules/tools/lsp/packages.el index a896e01f1..7f606c3d4 100644 --- a/modules/tools/lsp/packages.el +++ b/modules/tools/lsp/packages.el @@ -5,7 +5,7 @@ (progn (package! eglot :pin "fb6b17e86eddc22b9ec81f52718fad6bcbb53668") (package! project :pin "da0333a697b18f0a863c1b1523d2fc7991b31174")) - (package! lsp-mode :pin "0131f1f4c9e7823955c3b1f80881fcd7c2eaa551") + (package! lsp-mode :pin "edb81194f0974643861a24d1bbc386dd53554748") (package! lsp-ui :pin "1f3e9700395f4fae024ca45ca64c8d70e99b39d2") (when (featurep! :completion ivy) (package! lsp-ivy :pin "4cdb739fc2bc47f7d4dcad824f9240c70c4cb37d"))