summaryrefslogtreecommitdiff
path: root/autoload
diff options
context:
space:
mode:
authorw0rp <devw0rp@gmail.com>2019-02-13 00:31:33 +0000
committerw0rp <devw0rp@gmail.com>2019-02-13 17:26:37 +0000
commit1ee56713b8f9cfd0faa99dd7930437fa7ed986b0 (patch)
tree47e49ac8038f82892316e2d42a973e168c3b8d9a /autoload
parente88243687a2da8cd02962bc78874ec0e60aecaf2 (diff)
downloadale-1ee56713b8f9cfd0faa99dd7930437fa7ed986b0.zip
#2132 Use an on-init callback for all LSP logic
Diffstat (limited to 'autoload')
-rw-r--r--autoload/ale/completion.vim29
-rw-r--r--autoload/ale/definition.vim29
-rw-r--r--autoload/ale/hover.vim26
-rw-r--r--autoload/ale/lsp.vim40
-rw-r--r--autoload/ale/lsp_linter.vim36
-rw-r--r--autoload/ale/references.vim37
-rw-r--r--autoload/ale/symbol.vim25
7 files changed, 97 insertions, 125 deletions
diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim
index 8a96032e..4a566d4f 100644
--- a/autoload/ale/completion.vim
+++ b/autoload/ale/completion.vim
@@ -446,10 +446,15 @@ function! ale#completion#HandleLSPResponse(conn_id, response) abort
\)
endfunction
-function! s:OnReady(linter, lsp_details, ...) abort
- let l:buffer = a:lsp_details.buffer
+function! s:OnReady(linter, lsp_details) abort
let l:id = a:lsp_details.connection_id
+ if !ale#lsp#HasCapability(l:id, 'completion')
+ return
+ endif
+
+ let l:buffer = a:lsp_details.buffer
+
" If we have sent a completion request already, don't send another.
if b:ale_completion_info.request_id
return
@@ -498,21 +503,6 @@ function! s:OnReady(linter, lsp_details, ...) abort
endif
endfunction
-function! s:GetLSPCompletions(linter) abort
- let l:buffer = bufnr('')
- let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter)
-
- if empty(l:lsp_details)
- return 0
- endif
-
- let l:id = l:lsp_details.connection_id
-
- let l:OnReady = function('s:OnReady', [a:linter, l:lsp_details])
-
- call ale#lsp#WaitForCapability(l:id, 'completion', l:OnReady)
-endfunction
-
function! ale#completion#GetCompletions() abort
if !g:ale_completion_enabled
return
@@ -543,9 +533,12 @@ function! ale#completion#AlwaysGetCompletions(need_prefix) abort
\ 'request_id': 0,
\}
+ let l:buffer = bufnr('')
+ let l:Callback = function('s:OnReady')
+
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
- call s:GetLSPCompletions(l:linter)
+ call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
endif
endfor
endfunction
diff --git a/autoload/ale/definition.vim b/autoload/ale/definition.vim
index a732e501..9fc47834 100644
--- a/autoload/ale/definition.vim
+++ b/autoload/ale/definition.vim
@@ -57,10 +57,15 @@ function! ale#definition#HandleLSPResponse(conn_id, response) abort
endif
endfunction
-function! s:OnReady(linter, lsp_details, line, column, options, capability, ...) abort
- let l:buffer = a:lsp_details.buffer
+function! s:OnReady(line, column, options, capability, linter, lsp_details) abort
let l:id = a:lsp_details.connection_id
+ if !ale#lsp#HasCapability(l:id, a:capability)
+ return
+ endif
+
+ let l:buffer = a:lsp_details.buffer
+
let l:Callback = a:linter.lsp is# 'tsserver'
\ ? function('ale#definition#HandleTSServerResponse')
\ : function('ale#definition#HandleLSPResponse')
@@ -100,21 +105,13 @@ endfunction
function! s:GoToLSPDefinition(linter, options, capability) abort
let l:buffer = bufnr('')
let [l:line, l:column] = getcurpos()[1:2]
- let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter)
-
- if a:linter.lsp isnot# 'tsserver'
- let l:column = min([l:column, len(getline(l:line))])
- endif
-
- if empty(l:lsp_details)
- return 0
- endif
-
- let l:id = l:lsp_details.connection_id
+ let l:column = min([l:column, len(getline(l:line))])
- call ale#lsp#WaitForCapability(l:id, a:capability, function('s:OnReady', [
- \ a:linter, l:lsp_details, l:line, l:column, a:options, a:capability
- \]))
+ let l:Callback = function(
+ \ 's:OnReady',
+ \ [l:line, l:column, a:options, a:capability]
+ \)
+ call ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
endfunction
function! ale#definition#GoTo(options) abort
diff --git a/autoload/ale/hover.vim b/autoload/ale/hover.vim
index 873c9558..6a3f58c9 100644
--- a/autoload/ale/hover.vim
+++ b/autoload/ale/hover.vim
@@ -106,10 +106,15 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
endif
endfunction
-function! s:OnReady(linter, lsp_details, line, column, opt, ...) abort
- let l:buffer = a:lsp_details.buffer
+function! s:OnReady(line, column, opt, linter, lsp_details) abort
let l:id = a:lsp_details.connection_id
+ if !ale#lsp#HasCapability(l:id, 'hover')
+ return
+ endif
+
+ let l:buffer = a:lsp_details.buffer
+
let l:Callback = a:linter.lsp is# 'tsserver'
\ ? function('ale#hover#HandleTSServerResponse')
\ : function('ale#hover#HandleLSPResponse')
@@ -144,20 +149,6 @@ function! s:OnReady(linter, lsp_details, line, column, opt, ...) abort
\}
endfunction
-function! s:ShowDetails(linter, buffer, line, column, opt, ...) abort
- let l:lsp_details = ale#lsp_linter#StartLSP(a:buffer, a:linter)
-
- if empty(l:lsp_details)
- return 0
- endif
-
- let l:id = l:lsp_details.connection_id
-
- call ale#lsp#WaitForCapability(l:id, 'hover', function('s:OnReady', [
- \ a:linter, l:lsp_details, a:line, a:column, a:opt
- \]))
-endfunction
-
" Obtain Hover information for the specified position
" Pass optional arguments in the dictionary opt.
" Currently, only one key/value is useful:
@@ -169,12 +160,13 @@ endfunction
" - as status message otherwise
function! ale#hover#Show(buffer, line, col, opt) abort
let l:show_documentation = get(a:opt, 'show_documentation', 0)
+ let l:Callback = function('s:OnReady', [a:line, a:col, a:opt])
for l:linter in ale#linter#Get(getbufvar(a:buffer, '&filetype'))
" Only tsserver supports documentation requests at the moment.
if !empty(l:linter.lsp)
\&& (!l:show_documentation || l:linter.lsp is# 'tsserver')
- call s:ShowDetails(l:linter, a:buffer, a:line, a:col, a:opt)
+ call ale#lsp_linter#StartLSP(a:buffer, l:linter, l:Callback)
endif
endfor
endfunction
diff --git a/autoload/ale/lsp.vim b/autoload/ale/lsp.vim
index 5667b2e0..d1b3710e 100644
--- a/autoload/ale/lsp.vim
+++ b/autoload/ale/lsp.vim
@@ -36,7 +36,7 @@ function! ale#lsp#Register(executable_or_address, project, init_options) abort
\ 'config': {},
\ 'callback_list': [],
\ 'message_queue': [],
- \ 'capabilities_queue': [],
+ \ 'init_queue': [],
\ 'capabilities': {
\ 'hover': 0,
\ 'references': 0,
@@ -259,13 +259,11 @@ function! ale#lsp#HandleInitResponse(conn, response) abort
let a:conn.message_queue = []
" Call capabilities callbacks queued for the project.
- for [l:capability, l:Callback] in a:conn.capabilities_queue
- if a:conn.capabilities[l:capability]
- call call(l:Callback, [a:conn.id])
- endif
+ for [l:Callback] in a:conn.init_queue
+ call l:Callback()
endfor
- let a:conn.capabilities_queue = []
+ let a:conn.init_queue = []
endfunction
function! ale#lsp#HandleMessage(conn_id, message) abort
@@ -501,26 +499,32 @@ function! ale#lsp#NotifyForChanges(conn_id, buffer) abort
return l:notified
endfunction
-" Given some LSP details that must contain at least `connection_id` and
-" `project_root` keys,
-function! ale#lsp#WaitForCapability(conn_id, capability, callback) abort
+" Wait for an LSP server to be initialized.
+function! ale#lsp#OnInit(conn_id, Callback) abort
let l:conn = get(s:connections, a:conn_id, {})
if empty(l:conn)
return
endif
+ if l:conn.initialized
+ call a:Callback()
+ else
+ call add(l:conn.init_queue, a:Callback)
+ endif
+endfunction
+
+" Check if an LSP has a given capability.
+function! ale#lsp#HasCapability(conn_id, capability) abort
+ let l:conn = get(s:connections, a:conn_id, {})
+
+ if empty(l:conn)
+ return 0
+ endif
+
if type(get(l:conn.capabilities, a:capability, v:null)) isnot v:t_number
throw 'Invalid capability ' . a:capability
endif
- if l:conn.initialized
- if l:conn.capabilities[a:capability]
- " The project has been initialized, so call the callback now.
- call call(a:callback, [a:conn_id])
- endif
- else
- " Call the callback later, once we have the information we need.
- call add(l:conn.capabilities_queue, [a:capability, a:callback])
- endif
+ return l:conn.capabilities[a:capability]
endfunction
diff --git a/autoload/ale/lsp_linter.vim b/autoload/ale/lsp_linter.vim
index 70299655..95b92228 100644
--- a/autoload/ale/lsp_linter.vim
+++ b/autoload/ale/lsp_linter.vim
@@ -187,7 +187,7 @@ endfunction
" Given a buffer, an LSP linter, start up an LSP linter and get ready to
" receive messages for the document.
-function! ale#lsp_linter#StartLSP(buffer, linter) abort
+function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
let l:command = ''
let l:address = ''
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, a:linter)
@@ -195,7 +195,7 @@ function! ale#lsp_linter#StartLSP(buffer, linter) abort
if empty(l:root) && a:linter.lsp isnot# 'tsserver'
" If there's no project root, then we can't check files with LSP,
" unless we are using tsserver, which doesn't use project roots.
- return {}
+ return 0
endif
let l:init_options = ale#lsp_linter#GetOptions(a:buffer, a:linter)
@@ -208,7 +208,7 @@ function! ale#lsp_linter#StartLSP(buffer, linter) abort
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter)
if empty(l:executable) || !executable(l:executable)
- return {}
+ return 0
endif
let l:conn_id = ale#lsp#Register(l:executable, l:root, l:init_options)
@@ -225,7 +225,7 @@ function! ale#lsp_linter#StartLSP(buffer, linter) abort
call ale#history#Add(a:buffer, 'failed', l:conn_id, l:command)
endif
- return {}
+ return 0
endif
" tsserver behaves differently, so tell the LSP API that it is tsserver.
@@ -257,18 +257,20 @@ function! ale#lsp_linter#StartLSP(buffer, linter) abort
call ale#lsp#NotifyForChanges(l:conn_id, a:buffer)
endif
- return l:details
+ call ale#lsp#OnInit(l:conn_id, {-> a:Callback(a:linter, l:details)})
+
+ return 1
endfunction
-function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort
- let l:info = g:ale_buffer_info[a:buffer]
- let l:lsp_details = ale#lsp_linter#StartLSP(a:buffer, a:linter)
+function! s:CheckWithLSP(linter, details) abort
+ let l:buffer = a:details.buffer
+ let l:info = get(g:ale_buffer_info, l:buffer)
- if empty(l:lsp_details)
- return 0
+ if empty(l:info)
+ return
endif
- let l:id = l:lsp_details.connection_id
+ let l:id = a:details.connection_id
" Register a callback now for handling errors now.
let l:Callback = function('ale#lsp_linter#HandleLSPResponse')
@@ -278,16 +280,16 @@ function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort
let s:lsp_linter_map[l:id] = a:linter.name
if a:linter.lsp is# 'tsserver'
- let l:message = ale#lsp#tsserver_message#Geterr(a:buffer)
+ let l:message = ale#lsp#tsserver_message#Geterr(l:buffer)
let l:notified = ale#lsp#Send(l:id, l:message) != 0
else
- let l:notified = ale#lsp#NotifyForChanges(l:id, a:buffer)
+ let l:notified = ale#lsp#NotifyForChanges(l:id, l:buffer)
endif
" If this was a file save event, also notify the server of that.
if a:linter.lsp isnot# 'tsserver'
- \&& getbufvar(a:buffer, 'ale_save_event_fired', 0)
- let l:save_message = ale#lsp#message#DidSave(a:buffer)
+ \&& getbufvar(l:buffer, 'ale_save_event_fired', 0)
+ let l:save_message = ale#lsp#message#DidSave(l:buffer)
let l:notified = ale#lsp#Send(l:id, l:save_message) != 0
endif
@@ -305,8 +307,10 @@ function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort
call add(l:info.active_linter_list, a:linter)
endif
endif
+endfunction
- return l:notified
+function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort
+ return ale#lsp_linter#StartLSP(a:buffer, a:linter, function('s:CheckWithLSP'))
endfunction
" Clear LSP linter data for the linting engine.
diff --git a/autoload/ale/references.vim b/autoload/ale/references.vim
index 6d33b443..14f3cd15 100644
--- a/autoload/ale/references.vim
+++ b/autoload/ale/references.vim
@@ -65,10 +65,15 @@ function! ale#references#HandleLSPResponse(conn_id, response) abort
endif
endfunction
-function! s:OnReady(linter, lsp_details, line, column, options, ...) abort
- let l:buffer = a:lsp_details.buffer
+function! s:OnReady(line, column, options, linter, lsp_details) abort
let l:id = a:lsp_details.connection_id
+ if !ale#lsp#HasCapability(l:id, 'references')
+ return
+ endif
+
+ let l:buffer = a:lsp_details.buffer
+
let l:Callback = a:linter.lsp is# 'tsserver'
\ ? function('ale#references#HandleTSServerResponse')
\ : function('ale#references#HandleLSPResponse')
@@ -96,27 +101,6 @@ function! s:OnReady(linter, lsp_details, line, column, options, ...) abort
\}
endfunction
-function! s:FindReferences(linter, options) abort
- let l:buffer = bufnr('')
- let [l:line, l:column] = getcurpos()[1:2]
-
- if a:linter.lsp isnot# 'tsserver'
- let l:column = min([l:column, len(getline(l:line))])
- endif
-
- let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter)
-
- if empty(l:lsp_details)
- return 0
- endif
-
- let l:id = l:lsp_details.connection_id
-
- call ale#lsp#WaitForCapability(l:id, 'references', function('s:OnReady', [
- \ a:linter, l:lsp_details, l:line, l:column, a:options
- \]))
-endfunction
-
function! ale#references#Find(...) abort
let l:options = {}
@@ -128,9 +112,14 @@ function! ale#references#Find(...) abort
endfor
endif
+ let l:buffer = bufnr('')
+ let [l:line, l:column] = getcurpos()[1:2]
+ let l:column = min([l:column, len(getline(l:line))])
+ let l:Callback = function('s:OnReady', [l:line, l:column, l:options])
+
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
- call s:FindReferences(l:linter, l:options)
+ call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
endif
endfor
endfunction
diff --git a/autoload/ale/symbol.vim b/autoload/ale/symbol.vim
index dba78afa..ae4151ab 100644
--- a/autoload/ale/symbol.vim
+++ b/autoload/ale/symbol.vim
@@ -57,7 +57,13 @@ function! ale#symbol#HandleLSPResponse(conn_id, response) abort
endif
endfunction
-function! s:OnReady(linter, lsp_details, query, options, ...) abort
+function! s:OnReady(query, options, linter, lsp_details) abort
+ let l:id = a:lsp_details.connection_id
+
+ if !ale#lsp#HasCapability(l:id, 'symbol_search')
+ return
+ endif
+
let l:buffer = a:lsp_details.buffer
" If we already made a request, stop here.
@@ -65,8 +71,6 @@ function! s:OnReady(linter, lsp_details, query, options, ...) abort
return
endif
- let l:id = a:lsp_details.connection_id
-
let l:Callback = function('ale#symbol#HandleLSPResponse')
call ale#lsp#RegisterCallback(l:id, l:Callback)
@@ -80,18 +84,6 @@ function! s:OnReady(linter, lsp_details, query, options, ...) abort
\}
endfunction
-function! s:Search(linter, buffer, query, options) abort
- let l:lsp_details = ale#lsp_linter#StartLSP(a:buffer, a:linter)
-
- if !empty(l:lsp_details)
- call ale#lsp#WaitForCapability(
- \ l:lsp_details.connection_id,
- \ 'symbol_search',
- \ function('s:OnReady', [a:linter, l:lsp_details, a:query, a:options]),
- \)
- endif
-endfunction
-
function! ale#symbol#Search(args) abort
let [l:opts, l:query] = ale#args#Parse(['relative'], a:args)
@@ -108,10 +100,11 @@ function! ale#symbol#Search(args) abort
" Set a flag so we only make one request.
call setbufvar(l:buffer, 'ale_symbol_request_made', 0)
+ let l:Callback = function('s:OnReady', [l:query, l:options])
for l:linter in ale#linter#Get(getbufvar(l:buffer, '&filetype'))
if !empty(l:linter.lsp) && l:linter.lsp isnot# 'tsserver'
- call s:Search(l:linter, l:buffer, l:query, l:options)
+ call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
endif
endfor
endfunction