From a686a77e0579a04eff5db406966619afd6ff880e Mon Sep 17 00:00:00 2001 From: Troy Brown Date: Sat, 20 Apr 2024 02:08:47 -0400 Subject: [PATCH] Add a defcustom to control default diagnostic severity. Previously, there was a Flycheck specific defcustom, which was used to select a default error level for Flycheck. However, there was nothing for Flymake. Additionally, there were numerous other places in lsp-mode which query the severity attribute of the diagnostic, such as for statistics, modeline, headerline, etc. All of these were being handled inconsistently, either not at all (causing an error when the attribute was not sent by the server), ignoring it when it was missing (causing statistics to be inaccurate) or assuming a default of error, which might have been different than the Flycheck specific configuration, therefore causing an inconsistency in the modeline statistics vs what Flycheck would report. This change creates a common defcustom which is then used anywhere the diagnostic severity is needed, but was not provided by the server. This should create consistent statistics between the modeline and the back-end checkers. Additionally, the mapping between this defcustom and the checker specific values happens in the diagnostic package. Since this defcustom is used outside of the lsp-diagnostic package, it resides in the lsp-mode package and renamed more generally. Additionally, the Flycheck specific defcustom has been obsoleted. --- lsp-diagnostics.el | 51 ++++++++++++++++++++++------------------------ lsp-headerline.el | 6 +++++- lsp-mode.el | 25 +++++++++++++++++++++-- lsp-modeline.el | 6 ++++-- 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/lsp-diagnostics.el b/lsp-diagnostics.el index 1ce1b8070bf..a5eb8609874 100644 --- a/lsp-diagnostics.el +++ b/lsp-diagnostics.el @@ -50,13 +50,9 @@ (define-obsolete-variable-alias 'lsp-flycheck-default-level 'lsp-diagnostics-flycheck-default-level "lsp-mode 7.0.1") -(defcustom lsp-diagnostics-flycheck-default-level 'error - "Error level to use when the server does not report back a diagnostic level." - :type '(choice - (const error) - (const warning) - (const info)) - :group 'lsp-diagnostics) +;;;###autoload +(define-obsolete-variable-alias 'lsp-diagnostics-flycheck-default-level + 'lsp-diagnostics-default-severity "lsp-mode 9.0.1") (defcustom lsp-diagnostics-attributes `((unnecessary :foreground "gray") @@ -131,18 +127,19 @@ g. `error', `warning') and list of LSP TAGS." (defun lsp-diagnostics--flycheck-calculate-level (severity tags) "Calculate flycheck level by SEVERITY and TAGS." - (let ((level (pcase severity - (1 'error) - (2 'warning) - (3 'info) - (4 'info) - (_ lsp-flycheck-default-level))) - ;; materialize only first tag. - (tags (seq-map (lambda (tag) - (cond - ((= tag lsp/diagnostic-tag-unnecessary) 'unnecessary) - ((= tag lsp/diagnostic-tag-deprecated) 'deprecated))) - tags))) + (let* ((severity (or severity + (lsp-diagnostics-severity->numeric + lsp-diagnostics-default-severity))) + (level (cond ((= severity lsp/diagnostic-severity-error) 'error) + ((= severity lsp/diagnostic-severity-warning) 'warning) + ((= severity lsp/diagnostic-severity-information) 'info) + ((= severity lsp/diagnostic-severity-hint) 'info))) + ;; materialize only first tag. + (tags (seq-map (lambda (tag) + (cond + ((= tag lsp/diagnostic-tag-unnecessary) 'unnecessary) + ((= tag lsp/diagnostic-tag-deprecated) 'deprecated))) + tags))) (if tags (lsp-diagnostics--flycheck-level level tags) level))) @@ -305,14 +302,14 @@ See https://github.com/emacs-lsp/lsp-mode." (goto-char (point-min)) (setq start (line-beginning-position (1+ start-line)) end (line-end-position (1+ end-line)))))) - (flymake-make-diagnostic (current-buffer) - start - end - (cl-case severity? - (1 :error) - (2 :warning) - (t :note)) - message)))) + (let* ((severity (or severity? + (lsp-diagnostics-severity->numeric + lsp-diagnostics-default-severity))) + (type (cond ((= severity lsp/diagnostic-severity-error) :error) + ((= severity lsp/diagnostic-severity-warning) :warning) + ((= severity lsp/diagnostic-severity-information) :note) + ((= severity lsp/diagnostic-severity-hint) :note)))) + (flymake-make-diagnostic (current-buffer) start end type message))))) ;; This :region keyword forces flymake to delete old diagnostics in ;; case the buffer hasn't changed since the last call to the report ;; function. See https://github.com/joaotavora/eglot/issues/159 diff --git a/lsp-headerline.el b/lsp-headerline.el index cbdc7654173..b69d978cc4b 100644 --- a/lsp-headerline.el +++ b/lsp-headerline.el @@ -306,7 +306,11 @@ PATH is the current folder to be checked." (let ((range-severity 10)) (mapc (-lambda ((&Diagnostic :range (&Range :start) :severity?)) (when (lsp-point-in-range? start range) - (setq range-severity (min range-severity severity?)))) + (setq range-severity + (min range-severity + (or severity? + (lsp-diagnostics-severity->numeric + lsp-diagnostics-default-severity)))))) (lsp--get-buffer-diagnostics)) range-severity)) diff --git a/lsp-mode.el b/lsp-mode.el index e599af2def8..b35dee46545 100644 --- a/lsp-mode.el +++ b/lsp-mode.el @@ -634,6 +634,15 @@ diagnostics have changed." :type 'hook :group 'lsp-mode) +(defcustom lsp-diagnostics-default-severity 'error + "Error level to use when the server does not report one." + :type '(choice (const :tag "Error" error) + (const :tag "Warning" warning) + (const :tag "Information" info) + (const :tag "Hint" hint)) + :group 'lsp-mode + :package-version '(lsp-mode . "9.0.1")) + (define-obsolete-variable-alias 'lsp-workspace-folders-changed-hook 'lsp-workspace-folders-changed-functions "lsp-mode 6.3") @@ -2277,6 +2286,14 @@ Common usecase are: result))) (ht))) +(defun lsp-diagnostics-severity->numeric (severity) + "Determine numeric severity from symbolic SEVERITY." + (pcase severity + ('error lsp/diagnostic-severity-error) + ('warning lsp/diagnostic-severity-warning) + ('info lsp/diagnostic-severity-information) + ('hint lsp/diagnostic-severity-hint))) + (defun lsp-diagnostics-stats-for (path) "Get diagnostics statistics for PATH. The result format is vector [_ errors warnings infos hints] or nil." @@ -2296,11 +2313,15 @@ The result format is vector [_ errors warnings infos hints] or nil." (let ((path (lsp--fix-path-casing (lsp--uri-to-path uri))) (new-stats (make-vector 5 0))) (mapc (-lambda ((&Diagnostic :severity?)) - (cl-incf (aref new-stats (or severity? 1)))) + (cl-incf (aref new-stats (or severity? + (lsp-diagnostics-severity->numeric + lsp-diagnostics-default-severity))))) diagnostics) (when-let ((old-diags (gethash path (lsp--workspace-diagnostics workspace)))) (mapc (-lambda ((&Diagnostic :severity?)) - (cl-decf (aref new-stats (or severity? 1)))) + (cl-decf (aref new-stats (or severity? + (lsp-diagnostics-severity->numeric + lsp-diagnostics-default-severity))))) old-diags)) (lsp-diagnostics--update-path path new-stats) (while (not (string= path (setf path (file-name-directory diff --git a/lsp-modeline.el b/lsp-modeline.el index 9449f5c8b07..0199b91ad4f 100644 --- a/lsp-modeline.el +++ b/lsp-modeline.el @@ -229,8 +229,10 @@ The `:global' workspace is global one.") (mapc (lambda (buf-diags) (mapc (lambda (diag) (-let [(&Diagnostic? :severity?) diag] - (when severity? - (cl-incf (aref stats severity?))))) + (cl-incf (aref stats + (or severity? + (lsp-diagnostics-severity->numeric + lsp-diagnostics-default-severity)))))) buf-diags)) diagnostics) (while (< i lsp/diagnostic-severity-max)