Add Ale integration support
authorMagnus Groß <magnus@mggross.com>
Fri, 2 Jun 2023 16:28:18 +0000 (18:28 +0200)
committerMagnus Groß <magnus@mggross.com>
Fri, 2 Jun 2023 16:28:18 +0000 (18:28 +0200)
Ale [0] is a famous plugin to show linter warnings and diagnostics. It
already provides extensive functionality and configurability to display
those diagnostics.
In order to allow diagnostics from other plugins (e.g. LSP plugins) to
be shown together with those linter warnings, Ale has API so that those
diagnostics can be sent to Ale.

Ale will then display them as if they came from Ale itself. This is
useful for many reasons, e.g. this ensures a consistent look and allows
the location list for a window to be populated with all diagnostics,
regardless from which plugin they come.

There are other famous LSP plugins, that already integrate with Ale,
e.g. coc.nvim [1] allows this with "diagnostic.displayByAle".

This patch implements the same functionality by adding an "aleSupport"
option that is off by default. If the option is turned on, diagnostics
will be sent to Ale instead of being displayed by this plugin directly.

[0] https://github.com/dense-analysis/ale
[1] https://github.com/neoclide/coc.nvim

README.md
autoload/lsp/diag.vim
autoload/lsp/options.vim
doc/lsp.txt

index 0c88aa58c929ac3e684226705962fe0e059de5f6..892cc75c0842b9ea8ba1f00c47dadfc95689c8d6 100644 (file)
--- a/README.md
+++ b/README.md
@@ -108,6 +108,7 @@ Some of the LSP plugin features can be enabled or disabled by using the LspOptio
 Here is an example of configuration with default values:
 ```viml
 call LspOptionsSet(#{
+       \   aleSupport: v:false,
        \   autoComplete: v:true,
        \   autoHighlight: v:false,
        \   autoHighlightDiags: v:true,
index ec3f971e4548f1d41662eafff6d8d6abb41c7526..e453dff6a243225025eb2a099e45d47ca6881962 100644 (file)
@@ -82,6 +82,10 @@ export def InitOnce()
   hlset([{name: 'LspDiagVirtualText', default: true, linksto: 'LineNr'}])
   prop_type_add('LspDiagVirtualText', {highlight: 'LspDiagVirtualText',
                                        override: true})
+
+  if opt.lspOptions.aleSupport
+    autocmd_add([{group: 'LspAleCmds', event: 'User', pattern: 'ALEWantResults', cmd: 'AleHook(g:ale_want_results_buffer)'}])
+  endif
 enddef
 
 # Sort diagnostics ascending based on line and character offset
@@ -235,6 +239,29 @@ def DiagsRefresh(bnr: number)
   signs->sign_placelist()
 enddef
 
+# Sends diagnostics to Ale
+def SendAleDiags(bnr: number, timerid: number)
+  if !diagsMap->has_key(bnr)
+    return
+  endif
+
+  # Conver to Ale's diagnostics format (:h ale-loclist-format)
+  ale#other_source#ShowResults(bnr, 'lsp', diagsMap[bnr].sortedDiagnostics->mapnew((_, v) => {
+     return {text: v.message,
+             lnum: v.range.start.line + 1,
+             col: util.GetLineByteFromPos(bnr, v.range.start) + 1,
+             end_lnum: v.range.end.line + 1,
+             end_col: util.GetLineByteFromPos(bnr, v.range.end) + 1,
+             type: "EWIH"[v.severity - 1]}
+  }))
+enddef
+
+# Hook called when Ale wants to retrieve new diagnostics
+def AleHook(bnr: number)
+  ale#other_source#StartChecking(bnr, 'lsp')
+  timer_start(0, function('SendAleDiags', [bnr]))
+enddef
+
 # New LSP diagnostic messages received from the server for a file.
 # Update the signs placed in the buffer for this file
 export def ProcessNewDiags(bnr: number)
@@ -242,7 +269,10 @@ export def ProcessNewDiags(bnr: number)
     DiagsUpdateLocList(bnr)
   endif
 
-  if !opt.lspOptions.autoHighlightDiags
+  if opt.lspOptions.aleSupport
+    SendAleDiags(bnr, -1)
+    return
+  elseif !opt.lspOptions.autoHighlightDiags
     return
   endif
 
index 610631ffdafbb0bf8614fff2189240cc8a88f127..8ccf7e478331da564d84774d7b6b788663569aca 100644 (file)
@@ -3,6 +3,10 @@ vim9script
 # LSP plugin options
 # User can override these by calling the OptionsSet() function.
 export var lspOptions: dict<any> = {
+  # Enable ale diagnostics support.
+  # If true, diagnostics will be sent to ale, which will be responsible for
+  # showing them.
+  aleSupport: false,
   # In insert mode, complete the current symbol automatically
   # Otherwise, use omni-completion
   autoComplete: true,
index 19e8256ddf45dc54a21cb5139ed74b5cb79e7a48..cb9fea6bd290102754ff942b86c00b0ca5cc3646 100644 (file)
@@ -412,6 +412,11 @@ Some of the LSP plugin features can be enabled or disabled by using the
 LspOptionsSet() function. This function accepts a dictionary argument with the
 following optional items:
 
+                                               *lsp-opt-aleSupport*
+aleSupport             |Boolean| option. If true, diagnostics will be sent to
+                       Ale, instead of being displayed by this plugin.
+                       This is useful to combine all LSP and linter
+                       diagnostics. By default this is set to false.
                                                *lsp-opt-autoComplete*
 autoComplete           |Boolean| option. In insert mode, automatically
                        complete the current symbol. Otherwise use