From 0f44d338f17bd426ab43f6a619873c9ac91bc51e Mon Sep 17 00:00:00 2001 From: Brian Leung Date: Mon, 10 Jan 2022 21:48:21 -0800 Subject: [PATCH] Support optional diagnostic.tags https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#diagnosticTag A DiagnosticTag can be either 1 (DiagnosticTag.Unnecessary) or 2 (DiagnosticTag.Deprecated). Following the rendering suggestions in the protocol, we fade out Unnecessary code and strike-through Deprecated code. * eglot.el (eglot-diagnostic-tag-unnecessary-face) (eglot-diagnostic-tag-deprecated-face): New faces. (eglot--tag-faces): New defconst. (eglot--lsp-interface-alist): Add Diagnostic.tags. (eglot-client-capabilities): Advertise supported tags. (eglot-handle-notification): Assign the appropriate properties. * eglot-tests.el (diagnostic-tags-unnecessary-code): New test. GitHub-reference: per https://github.com/joaotavora/eglot/issues/794 --- lisp/progmodes/eglot.el | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 813b29775e2..dc20ef751b8 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -252,6 +252,14 @@ CONTACT can be: '((t (:inherit font-lock-constant-face :weight bold))) "Face for package-name in EGLOT's mode line.") +(defface eglot-diagnostic-tag-unnecessary-face + '((t . (:weight ultra-light))) + "Face used to render unused or unnecessary code.") + +(defface eglot-diagnostic-tag-deprecated-face + '((t . (:strike-through t))) + "Face used to render deprecated or obsolete code.") + (defcustom eglot-autoreconnect 3 "Control ability to reconnect automatically to the LSP server. If t, always reconnect automatically (not recommended). If nil, @@ -332,6 +340,10 @@ This can be useful when using docker to run a language server.") (21 . "Constant") (22 . "Struct") (23 . "Event") (24 . "Operator") (25 . "TypeParameter"))) +(defconst eglot--tag-faces + `((1 . eglot-diagnostic-tag-unnecessary-face) + (2 . eglot-diagnostic-tag-deprecated-face))) + (defconst eglot--{} (make-hash-table) "The empty JSON object.") (defun eglot--executable-find (command &optional remote) @@ -353,7 +365,7 @@ This can be useful when using docker to run a language server.") :sortText :filterText :insertText :insertTextFormat :textEdit :additionalTextEdits :commitCharacters :command :data)) - (Diagnostic (:range :message) (:severity :code :source :relatedInformation :codeDescription)) + (Diagnostic (:range :message) (:severity :code :source :relatedInformation :codeDescription :tags)) (DocumentHighlight (:range) (:kind)) (FileSystemWatcher (:globPattern) (:kind)) (Hover (:contents) (:range)) @@ -695,7 +707,11 @@ treated as in `eglot-dbind'." ;; TODO: We can support :codeDescription after ;; adding an appropriate UI to ;; Flymake. - :codeDescriptionSupport :json-false)) + :codeDescriptionSupport :json-false + :tagSupport + `(:valueSet + [,@(mapcar + #'car eglot--tag-faces)]))) :experimental eglot--{}))) (defclass eglot-lsp-server (jsonrpc-process-connection) @@ -1811,7 +1827,7 @@ COMMAND is a symbol naming the command." (with-current-buffer buffer (cl-loop for diag-spec across diagnostics - collect (eglot--dbind ((Diagnostic) range message severity source) + collect (eglot--dbind ((Diagnostic) range message severity source tags) diag-spec (setq message (concat source ": " message)) (pcase-let @@ -1839,7 +1855,11 @@ COMMAND is a symbol naming the command." ((<= sev 1) 'eglot-error) ((= sev 2) 'eglot-warning) (t 'eglot-note)) - message `((eglot-lsp-diag . ,diag-spec))))) + message `((eglot-lsp-diag . ,diag-spec)) + (and tags + `((face . ,(mapcar (lambda (tag) + (alist-get tag eglot--tag-faces)) + tags))))))) into diags finally (cond (eglot--current-flymake-report-fn (eglot--report-to-flymake diags)) -- 2.39.5