Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic pull diagnostics support #4280

Merged
merged 3 commits into from
Jul 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.org
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Add support for go to definition for external files (.dll) in CSharp projects for OmniSharp server.
* Added a new optional ~:action-filter~ argument when defining LSP clients that allows code action requests to be modified before they are sent to the server. This is used by the Haskell language server client to work around an ~lsp-mode~ parsing quirk that incorrectly sends ~null~ values instead of ~false~ in code action requests.
* Add support for C# via the [[https://github.com/dotnet/roslyn/tree/main/src/Features/LanguageServer][Roslyn language server]].
* Add basic support for [[https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics][pull diagnostics]] requests.

** 9.0.0
* Add language server config for QML (Qt Modeling Language) using qmlls.
Expand Down
67 changes: 54 additions & 13 deletions lsp-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,7 @@ directory")
("textDocument/signatureHelp" :capability :signatureHelpProvider)
("textDocument/typeDefinition" :capability :typeDefinitionProvider)
("textDocument/typeHierarchy" :capability :typeHierarchyProvider)
("textDocument/diagnostic" :capability :diagnosticProvider)
("workspace/executeCommand" :capability :executeCommandProvider)
("workspace/symbol" :capability :workspaceSymbolProvider))

Expand Down Expand Up @@ -2299,6 +2300,17 @@ Common usecase are:
The result format is vector [_ errors warnings infos hints] or nil."
(gethash (lsp--fix-path-casing path) lsp-diagnostic-stats))

(defun lsp-diagnostics--request-pull-diagnostics (workspace)
"Request new diagnostics for the current file within WORKSPACE.
This is only executed if the server supports pull diagnostics."
(when (lsp-feature? "textDocument/diagnostic")
(let ((path (lsp--fix-path-casing (buffer-file-name))))
(lsp-request-async "textDocument/diagnostic"
(list :textDocument (lsp--text-document-identifier))
(-lambda ((&DocumentDiagnosticReport :kind :items?))
(lsp-diagnostics--apply-pull-diagnostics workspace path kind items?))
:mode 'tick))))
Ruin0x11 marked this conversation as resolved.
Show resolved Hide resolved

(defun lsp-diagnostics--update-path (path new-stats)
(let ((new-stats (copy-sequence new-stats))
(path (lsp--fix-path-casing (directory-file-name path))))
Expand All @@ -2308,9 +2320,8 @@ The result format is vector [_ errors warnings infos hints] or nil."
(aref new-stats idx)))
(puthash path new-stats lsp-diagnostic-stats))))

(lsp-defun lsp--on-diagnostics-update-stats (workspace
(&PublishDiagnosticsParams :uri :diagnostics))
(let ((path (lsp--fix-path-casing (lsp--uri-to-path uri)))
(defun lsp-diagnostics--convert-and-update-path-stats (workspace path diagnostics)
(let ((path (lsp--fix-path-casing path))
(new-stats (make-vector 5 0)))
(mapc (-lambda ((&Diagnostic :severity?))
(cl-incf (aref new-stats (or severity? 1))))
Expand All @@ -2324,6 +2335,27 @@ The result format is vector [_ errors warnings infos hints] or nil."
(directory-file-name path)))))
(lsp-diagnostics--update-path path new-stats))))

(lsp-defun lsp--on-diagnostics-update-stats (workspace
(&PublishDiagnosticsParams :uri :diagnostics))
(lsp-diagnostics--convert-and-update-path-stats workspace (lsp--uri-to-path uri) diagnostics))

(defun lsp-diagnostics--apply-pull-diagnostics (workspace path kind diagnostics?)
"Update WORKSPACE diagnostics at PATH with DIAGNOSTICS?.
Depends on KIND being a \\='full\\=' update."
(cond
((equal kind "full")
;; TODO support `lsp-diagnostic-filter'
;; (the params types differ from the published diagnostics response)
(lsp-diagnostics--convert-and-update-path-stats workspace path diagnostics?)
(-let* ((lsp--virtual-buffer-mappings (ht))
(workspace-diagnostics (lsp--workspace-diagnostics workspace)))
(if (seq-empty-p diagnostics?)
(remhash path workspace-diagnostics)
(puthash path (append diagnostics? nil) workspace-diagnostics))
(run-hooks 'lsp-diagnostics-updated-hook)))
((equal kind "unchanged") t)
(t (lsp--error "Unknown pull diagnostic result kind '%s'" kind))))

(defun lsp--on-diagnostics (workspace params)
"Callback for textDocument/publishDiagnostics.
interface PublishDiagnosticsParams {
Expand Down Expand Up @@ -3744,6 +3776,8 @@ disappearing, unset all the variables related to it."
(publishDiagnostics . ((relatedInformation . t)
(tagSupport . ((valueSet . [1 2])))
(versionSupport . t)))
(diagnostic . ((dynamicRegistration . :json-false)
(relatedDocumentSupport . :json-false)))
(linkedEditingRange . ((dynamicRegistration . t)))))
(window . ((workDoneProgress . t)
(showDocument . ((support . t))))))
Expand Down Expand Up @@ -4265,6 +4299,8 @@ yet."

(lsp-managed-mode 1)

(lsp-diagnostics--request-pull-diagnostics lsp--cur-workspace)

(run-hooks 'lsp-after-open-hook)
(when-let ((client (-some-> lsp--cur-workspace (lsp--workspace-client))))
(-some-> (lsp--client-after-open-fn client)
Expand Down Expand Up @@ -4809,7 +4845,8 @@ Added to `after-change-functions'."
(with-lsp-workspace workspace
(lsp-notify "textDocument/didChange"
(list :contentChanges (vector (lsp--full-change-event))
:textDocument (lsp--versioned-text-document-identifier))))))
:textDocument (lsp--versioned-text-document-identifier)))
(lsp-diagnostics--request-pull-diagnostics workspace))))
(2
(with-lsp-workspace workspace
(lsp-notify
Expand All @@ -4819,7 +4856,8 @@ Added to `after-change-functions'."
(if content-change-event-fn
(funcall content-change-event-fn start end length)
(lsp--text-document-content-change-event
start end length)))))))))
start end length)))))
(lsp-diagnostics--request-pull-diagnostics workspace)))))
(lsp-workspaces))
(when lsp--delay-timer (cancel-timer lsp--delay-timer))
(setq lsp--delay-timer (run-with-idle-timer
Expand All @@ -4828,14 +4866,7 @@ Added to `after-change-functions'."
#'lsp--flush-delayed-changes))
;; force cleanup overlays after each change
(lsp--remove-overlays 'lsp-highlight)
(lsp--after-change (current-buffer))
(setq lsp--signature-last-index nil
lsp--signature-last nil)
;; cleanup diagnostics
(when lsp-diagnostic-clean-after-change
(lsp-foreach-workspace
(-let [diagnostics (lsp--workspace-diagnostics lsp--cur-workspace)]
(remhash (lsp--fix-path-casing (buffer-file-name)) diagnostics))))))))
(lsp--after-change (current-buffer))))))



Expand Down Expand Up @@ -4892,6 +4923,16 @@ Added to `after-change-functions'."
(run-hooks 'lsp-on-change-hook)))

(defun lsp--after-change (buffer)
"Called after most textDocument/didChange events."
(setq lsp--signature-last-index nil
lsp--signature-last nil)

;; cleanup diagnostics
(when lsp-diagnostic-clean-after-change
(dolist (workspace (lsp-workspaces))
(-let [diagnostics (lsp--workspace-diagnostics workspace)]
(remhash (lsp--fix-path-casing (buffer-file-name)) diagnostics))))

(when (fboundp 'lsp--semantic-tokens-refresh-if-enabled)
(lsp--semantic-tokens-refresh-if-enabled buffer))
(when lsp--on-change-timer
Expand Down
5 changes: 5 additions & 0 deletions lsp-protocol.el
Original file line number Diff line number Diff line change
Expand Up @@ -603,10 +603,15 @@ See `-let' for a description of the destructuring mechanism."
(DefinitionCapabilities nil (:dynamicRegistration :linkSupport))
(DeleteFileOptions nil (:ignoreIfNotExists :recursive))
(Diagnostic (:range :message) (:code :relatedInformation :severity :source :tags))
(DiagnosticClientCapabilities nil (:dynamicRegistration :relatedDocumentSupport))
(DiagnosticOptions (:interFileDependencies :workspaceDiagnostics) (:identifier))
(DiagnosticRelatedInformation (:location :message) nil)
(DiagnosticServerCancellationData (:retriggerRequest) nil)
(DiagnosticsTagSupport (:valueSet) nil)
(DidChangeConfigurationCapabilities nil (:dynamicRegistration))
(DidChangeWatchedFilesCapabilities nil (:dynamicRegistration))
(DocumentDiagnosticParams (:textDocument) (:identifier :previousResultId))
(DocumentDiagnosticReport (:kind) (:resultId :items :relatedDocuments))
(DocumentFilter nil (:language :pattern :scheme))
(DocumentHighlightCapabilities nil (:dynamicRegistration))
(DocumentLinkCapabilities nil (:dynamicRegistration :tooltipSupport))
Expand Down
Loading