Skip to content

Instantly share code, notes, and snippets.

@vkjr
Created December 6, 2024 21:41
Show Gist options
  • Save vkjr/0e585c7f8ef2ea918bb0faaba5ba5334 to your computer and use it in GitHub Desktop.
Save vkjr/0e585c7f8ef2ea918bb0faaba5ba5334 to your computer and use it in GitHub Desktop.
Command to show all project errors from LSP in a convenient xref buffer
(defun vk/show-lsp-diagnostics-xref ()
"Display LSP diagnostics in a persistent `xref`-style buffer."
(interactive)
(let ((diagnostics (lsp-diagnostics))
(xref-items '())) ;; Initialize xref items list
;; Collect diagnostics as `xref-item` structures
(maphash
(lambda (file errors)
(dolist (error errors)
(let* ((range (gethash "range" error))
(start (gethash "start" range))
(line (1+ (gethash "line" start)))
(character (gethash "character" start))
(message (gethash "message" error))
(location (xref-make-file-location file line character)))
(push (xref-make message location) xref-items))))
diagnostics)
;; Create a custom xref group for diagnostics
(let ((xref-buffer-name "*LSP Diagnostics Xref*"))
(with-current-buffer (get-buffer-create xref-buffer-name)
;; Use `xref` display machinery with custom buffer
(let ((xref-backend-functions
(list (lambda () (lambda () xref-items)))))
(xref--show-xrefs (lambda () xref-items) nil)))
;; Display the custom xref buffer
(pop-to-buffer xref-buffer-name))))
@ilmotta
Copy link

ilmotta commented Dec 7, 2024

I had to adapt the snippet to use map-elt because in my version of lsp the error instance is not a hashmap, that's why the original snippet was failing for me.

The xref buffer appears to me in the minibuffer, which is very nice. I also liked to export the results with embark-export.

(defun vk/show-lsp-diagnostics-xref ()
  "Display LSP diagnostics in a persistent `xref`-style buffer."
  (interactive)
  (let ((diagnostics (lsp-diagnostics))
        (xref-items '())) ;; Initialize xref items list
    ;; Collect diagnostics as `xref-item` structures
    (maphash
     (lambda (file errors)
       (dolist (error errors)
         (let* ((range (map-elt error :range))
                (start (map-elt range :start))
                (line (1+ (map-elt start :line)))
                (character (map-elt start :character))
                (message (map-elt error :message))
                (location (xref-make-file-location file line character)))
           (push (xref-make message location) xref-items))))
     diagnostics)
    ;; Create a custom xref group for diagnostics
    (let ((xref-buffer-name "*LSP Diagnostics Xref*"))
      (with-current-buffer (get-buffer-create xref-buffer-name)
        ;; Use `xref` display machinery with custom buffer
        (let ((xref-backend-functions
               (list (lambda () (lambda () xref-items)))))
          (xref--show-xrefs (lambda () xref-items) nil)))
      ;; Display the custom xref buffer
      (pop-to-buffer xref-buffer-name))))

@vkjr
Copy link
Author

vkjr commented Dec 9, 2024

@ilmotta, thanks for pointing to embark-export, looks very convenient!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment