summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ale_linters/typescript/tsserver.vim23
-rw-r--r--autoload/ale/engine.vim157
-rw-r--r--autoload/ale/lsp.vim126
-rw-r--r--autoload/ale/lsp/response.vim25
-rw-r--r--autoload/ale/lsp/tsserver_message.vim7
-rw-r--r--test/lsp/test_lsp_client_messages.vader4
-rw-r--r--test/lsp/test_lsp_connections.vader26
-rw-r--r--test/lsp/test_read_lsp_diagnostics.vader26
-rw-r--r--test/test_loclist_corrections.vader16
9 files changed, 284 insertions, 126 deletions
diff --git a/ale_linters/typescript/tsserver.vim b/ale_linters/typescript/tsserver.vim
new file mode 100644
index 00000000..332e32e5
--- /dev/null
+++ b/ale_linters/typescript/tsserver.vim
@@ -0,0 +1,23 @@
+" Author: w0rp <devw0rp@gmail.com>
+" Description: tsserver integration for ALE
+
+call ale#Set('typescript_tsserver_executable', 'tsserver')
+call ale#Set('typescript_tsserver_config_path', '')
+call ale#Set('typescript_tsserver_use_global', 0)
+
+function! ale_linters#typescript#tsserver#GetExecutable(buffer) abort
+ return ale#node#FindExecutable(a:buffer, 'typescript_tsserver', [
+ \ 'node_modules/.bin/tsserver',
+ \])
+endfunction
+
+function! ale_linters#typescript#tsserver#Handle(buffer, lines) abort
+ return a:lines
+endfunction
+
+call ale#linter#Define('typescript', {
+\ 'name': 'tsserver',
+\ 'lsp': 'tsserver',
+\ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable',
+\ 'callback': 'ale_linters#typescript#tsserver#Handle',
+\})
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim
index 3049ab5b..d15ab901 100644
--- a/autoload/ale/engine.vim
+++ b/autoload/ale/engine.vim
@@ -42,6 +42,7 @@ function! ale#engine#InitBufferInfo(buffer) abort
\ 'temporary_file_list': [],
\ 'temporary_directory_list': [],
\ 'history': [],
+ \ 'open_lsp_documents': [],
\}
endif
endfunction
@@ -103,6 +104,51 @@ function! s:GatherOutput(job_id, line) abort
endif
endfunction
+function! s:HandleLoclist(linter_name, buffer, loclist) abort
+ " Make some adjustments to the loclists to fix common problems, and also
+ " to set default values for loclist items.
+ let l:linter_loclist = ale#engine#FixLocList(a:buffer, a:linter_name, a:loclist)
+
+ " Remove previous items for this linter.
+ call filter(g:ale_buffer_info[a:buffer].loclist, 'v:val.linter_name !=# a:linter_name')
+ " Add the new items.
+ call extend(g:ale_buffer_info[a:buffer].loclist, l:linter_loclist)
+
+ " Sort the loclist again.
+ " We need a sorted list so we can run a binary search against it
+ " for efficient lookup of the messages in the cursor handler.
+ call sort(g:ale_buffer_info[a:buffer].loclist, 'ale#util#LocItemCompare')
+
+ let l:linting_is_done = empty(g:ale_buffer_info[a:buffer].job_list)
+ \ && !get(g:ale_buffer_info[a:buffer], 'waiting_for_tsserver', 0)
+
+ if l:linting_is_done
+ " Automatically remove all managed temporary files and directories
+ " now that all jobs have completed.
+ call ale#engine#RemoveManagedFiles(a:buffer)
+
+ " Figure out which linters are still enabled, and remove
+ " problems for linters which are no longer enabled.
+ let l:name_map = {}
+
+ for l:linter in ale#linter#Get(getbufvar(a:buffer, '&filetype'))
+ let l:name_map[l:linter.name] = 1
+ endfor
+
+ call filter(
+ \ g:ale_buffer_info[a:buffer].loclist,
+ \ 'get(l:name_map, v:val.linter_name)',
+ \)
+ endif
+
+ call ale#engine#SetResults(a:buffer, g:ale_buffer_info[a:buffer].loclist)
+
+ if l:linting_is_done
+ " Call user autocommands. This allows users to hook into ALE's lint cycle.
+ silent doautocmd User ALELint
+ endif
+endfunction
+
function! s:HandleExit(job_id, exit_code) abort
if !has_key(s:job_info_map, a:job_id)
return
@@ -143,55 +189,39 @@ function! s:HandleExit(job_id, exit_code) abort
call ale#history#RememberOutput(l:buffer, a:job_id, l:output[:])
endif
- let l:linter_loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output)
-
- " Make some adjustments to the loclists to fix common problems, and also
- " to set default values for loclist items.
- let l:linter_loclist = ale#engine#FixLocList(l:buffer, l:linter, l:linter_loclist)
-
- " Remove previous items for this linter.
- call filter(g:ale_buffer_info[l:buffer].loclist, 'v:val.linter_name !=# l:linter.name')
- " Add the new items.
- call extend(g:ale_buffer_info[l:buffer].loclist, l:linter_loclist)
+ let l:loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output)
- " Sort the loclist again.
- " We need a sorted list so we can run a binary search against it
- " for efficient lookup of the messages in the cursor handler.
- call sort(g:ale_buffer_info[l:buffer].loclist, 'ale#util#LocItemCompare')
+ call s:HandleLoclist(l:linter.name, l:buffer, l:loclist)
+endfunction
- let l:linting_is_done = empty(g:ale_buffer_info[l:buffer].job_list)
+function! s:HandleLSPResponse(response) abort
+ let l:is_diag_response = get(a:response, 'type', '') ==# 'event'
+ \ && get(a:response, 'event', '') ==# 'semanticDiag'
- if l:linting_is_done
- " Automatically remove all managed temporary files and directories
- " now that all jobs have completed.
- call ale#engine#RemoveManagedFiles(l:buffer)
+ if !l:is_diag_response
+ return
+ endif
- " Figure out which linters are still enabled, and remove
- " problems for linters which are no longer enabled.
- let l:name_map = {}
+ let l:buffer = bufnr(a:response.body.file)
- for l:linter in ale#linter#Get(getbufvar(l:buffer, '&filetype'))
- let l:name_map[l:linter.name] = 1
- endfor
+ let l:info = get(g:ale_buffer_info, l:buffer, {})
- call filter(
- \ g:ale_buffer_info[l:buffer].loclist,
- \ 'get(l:name_map, v:val.linter_name)',
- \)
+ if empty(l:info)
+ return
endif
- call ale#engine#SetResults(l:buffer, g:ale_buffer_info[l:buffer].loclist)
+ let l:info.waiting_for_tsserver = 0
- if l:linting_is_done
- " Call user autocommands. This allows users to hook into ALE's lint cycle.
- silent doautocmd User ALELint
- endif
+ let l:loclist = ale#lsp#response#ReadTSServerDiagnostics(a:response)
+
+ call s:HandleLoclist('tsserver', l:buffer, l:loclist)
endfunction
function! ale#engine#SetResults(buffer, loclist) abort
let l:info = get(g:ale_buffer_info, a:buffer, {})
let l:job_list = get(l:info, 'job_list', [])
- let l:linting_is_done = empty(l:job_list)
+ let l:waiting_for_tsserver = get(l:info, 'waiting_for_tsserver', 0)
+ let l:linting_is_done = empty(l:job_list) && !l:waiting_for_tsserver
" Set signs first. This could potentially fix some line numbers.
" The List could be sorted again here by SetSigns.
@@ -227,7 +257,7 @@ function! ale#engine#SetResults(buffer, loclist) abort
endif
endfunction
-function! ale#engine#FixLocList(buffer, linter, loclist) abort
+function! ale#engine#FixLocList(buffer, linter_name, loclist) abort
let l:new_loclist = []
" Some errors have line numbers beyond the end of the file,
@@ -256,7 +286,7 @@ function! ale#engine#FixLocList(buffer, linter, loclist) abort
\ 'vcol': get(l:old_item, 'vcol', 0),
\ 'type': get(l:old_item, 'type', 'E'),
\ 'nr': get(l:old_item, 'nr', -1),
- \ 'linter_name': a:linter.name,
+ \ 'linter_name': a:linter_name,
\}
if has_key(l:old_item, 'detail')
@@ -498,16 +528,55 @@ function! ale#engine#StopCurrentJobs(buffer, include_lint_file_jobs) abort
" Update the List, so it includes only the jobs we still need.
let l:info.job_list = l:new_job_list
+ " Ignore current LSP commands.
+ " We should consider cancelling them in future.
+ let l:info.lsp_command_list = []
endfunction
-function! ale#engine#Invoke(buffer, linter) abort
- let l:executable = has_key(a:linter, 'executable_callback')
- \ ? ale#util#GetFunction(a:linter.executable_callback)(a:buffer)
- \ : a:linter.executable
+function! s:CheckWithTSServer(buffer, linter, executable) abort
+ let l:info = g:ale_buffer_info[a:buffer]
+ let l:open_documents = l:info.open_lsp_documents
+ let l:is_open = index(l:open_documents, a:linter.name) >= 0
+
+ call ale#lsp#StartProgram(a:executable, a:executable, function('s:HandleLSPResponse'))
+
+ if !l:is_open
+ call add(l:open_documents, a:linter.name)
+ call ale#lsp#SendMessageToProgram(
+ \ a:executable,
+ \ ale#lsp#tsserver_message#Open(a:buffer),
+ \)
+ endif
- " Run this program if it can be executed.
- if s:IsExecutable(l:executable)
- call s:InvokeChain(a:buffer, a:linter, 0, [])
+ call ale#lsp#SendMessageToProgram(
+ \ a:executable,
+ \ ale#lsp#tsserver_message#Change(a:buffer),
+ \)
+
+ let l:request_id = ale#lsp#SendMessageToProgram(
+ \ a:executable,
+ \ ale#lsp#tsserver_message#Geterr(a:buffer),
+ \)
+
+ if l:request_id != 0
+ let l:info.waiting_for_tsserver = 1
+ endif
+endfunction
+
+function! ale#engine#Invoke(buffer, linter) abort
+ if empty(a:linter.lsp) || a:linter.lsp ==# 'tsserver'
+ let l:executable = has_key(a:linter, 'executable_callback')
+ \ ? ale#util#GetFunction(a:linter.executable_callback)(a:buffer)
+ \ : a:linter.executable
+
+ " Run this program if it can be executed.
+ if s:IsExecutable(l:executable)
+ if a:linter.lsp ==# 'tsserver'
+ call s:CheckWithTSServer(a:buffer, a:linter, l:executable)
+ else
+ call s:InvokeChain(a:buffer, a:linter, 0, [])
+ endif
+ endif
endif
endfunction
diff --git a/autoload/ale/lsp.vim b/autoload/ale/lsp.vim
index 76d0c8df..449aa304 100644
--- a/autoload/ale/lsp.vim
+++ b/autoload/ale/lsp.vim
@@ -8,13 +8,11 @@ let g:ale_lsp_next_message_id = 1
function! s:NewConnection() abort
" data: The message data received so far.
- " callback_map: A mapping from connections to response callbacks.
" address: An address only set for server connections.
" executable: An executable only set for program connections.
" job: A job ID only set for running programs.
let l:conn = {
\ 'data': '',
- \ 'callback_map': {},
\ 'address': '',
\ 'executable': '',
\ 'job_id': -1,
@@ -60,7 +58,7 @@ function! s:CreateTSServerMessageData(message) abort
let l:obj.arguments = a:message[2]
endif
- let l:data = json_encode(l:obj)
+ let l:data = json_encode(l:obj) . "\n"
return [l:is_notification ? 0 : l:obj.seq, l:data]
endfunction
@@ -143,12 +141,9 @@ function! ale#lsp#HandleMessage(conn, message) abort
" Call our callbacks.
for l:response in l:response_list
- let l:id = has_key(l:response, 'seq')
- \ ? l:response.seq
- \ : l:response.id
-
- let l:callback = a:conn.callback_map.pop(l:id)
- call ale#util#GetFunction(l:callback)(l:response)
+ if has_key(a:conn, 'callback')
+ call ale#util#GetFunction(a:conn.callback)(l:response)
+ endif
endfor
endfunction
@@ -166,32 +161,18 @@ function! s:HandleCommandMessage(job_id, message) abort
call ale#lsp#HandleMessage(l:conn, a:message)
endfunction
-" Send a message to a server with a given executable, and a command for
-" running the executable.
-"
-" A callback can be registered to handle the response.
-" Notifications do not need to be handled.
-" (executable, command, message, callback?)
-"
-" Returns 1 when a message is sent, 0 otherwise.
-function! ale#lsp#SendMessageToProgram(executable, command, message, ...) abort
- if a:0 > 1
- throw 'Too many arguments!'
- endif
-
- if !a:message[0] && a:0 == 0
- throw 'A callback must be set for messages which are not notifications!'
- endif
-
+" Start a program for LSP servers which run with executables.
+function! ale#lsp#StartProgram(executable, command, callback) abort
if !executable(a:executable)
return 0
endif
- let [l:id, l:data] = ale#lsp#CreateMessageData(a:message)
-
let l:matches = filter(s:connections[:], 'v:val.executable ==# a:executable')
+
" Get the current connection or a new one.
let l:conn = !empty(l:matches) ? l:matches[0] : s:NewConnection()
+ let l:conn.executable = a:executable
+ let l:conn.callback = a:callback
if !ale#job#IsRunning(l:conn.job_id)
let l:options = {
@@ -199,43 +180,50 @@ function! ale#lsp#SendMessageToProgram(executable, command, message, ...) abort
\ 'out_cb': function('s:HandleCommandMessage'),
\}
let l:job_id = ale#job#Start(ale#job#PrepareCommand(a:command), l:options)
+ else
+ let l:job_id = l:conn.job_id
endif
if l:job_id <= 0
return 0
endif
- " The ID is 0 when the message is a Notification, which is a JSON-RPC
- " request for which the server must not return a response.
- if l:id != 0
- " Add the callback, which the server will respond to later.
- let l:conn.callback_map[l:id] = a:1
- endif
-
- call ale#job#SendRaw(l:job_id, l:data)
-
let l:conn.job_id = l:job_id
return 1
endfunction
-" Send a message to a server at a given address.
-" A callback can be registered to handle the response.
-" Notifications do not need to be handled.
-" (address, message, callback?)
+" Send a message to a server with a given executable, and a command for
+" running the executable.
"
-" Returns 1 when a message is sent, 0 otherwise.
-function! ale#lsp#SendMessageToAddress(address, message, ...) abort
- if a:0 > 1
- throw 'Too many arguments!'
+" Returns -1 when a message is sent, but no response is expected
+" 0 when the message is not sent and
+" >= 1 with the message ID when a response is expected.
+function! ale#lsp#SendMessageToProgram(executable, message) abort
+ let [l:id, l:data] = ale#lsp#CreateMessageData(a:message)
+
+ let l:matches = filter(s:connections[:], 'v:val.executable ==# a:executable')
+
+ " No connection is currently open.
+ if empty(l:matches)
+ return 0
endif
- if !a:message[0] && a:0 == 0
- throw 'A callback must be set for messages which are not notifications!'
+ " Get the current connection or a new one.
+ let l:conn = l:matches[0]
+ let l:conn.executable = a:executable
+
+ if get(l:conn, 'job_id', 0) == 0
+ return 0
endif
- let [l:id, l:data] = ale#lsp#CreateMessageData(a:message)
+ call ale#job#SendRaw(l:conn.job_id, l:data)
+ return l:id == 0 ? -1 : l:id
+endfunction
+
+" Connect to an address and set up a callback for handling responses.
+function! ale#lsp#ConnectToAddress(address, callback) abort
let l:matches = filter(s:connections[:], 'v:val.address ==# a:address')
" Get the current connection or a new one.
let l:conn = !empty(l:matches) ? l:matches[0] : s:NewConnection()
@@ -248,17 +236,47 @@ function! ale#lsp#SendMessageToAddress(address, message, ...) abort
\})
endif
- " The ID is 0 when the message is a Notification, which is a JSON-RPC
- " request for which the server must not return a response.
- if l:id != 0
- " Add the callback, which the server will respond to later.
- let l:conn.callback_map[l:id] = a:1
+ if ch_status(l:conn.channnel) ==# 'fail'
+ return 0
endif
- if ch_status(l:conn.channnel) ==# 'fail'
+ let l:conn.callback = a:callback
+
+ return 1
+endfunction
+
+" Send a message to a server at a given address.
+" Notifications do not need to be handled.
+"
+" Returns -1 when a message is sent, but no response is expected
+" 0 when the message is not sent and
+" >= 1 with the message ID when a response is expected.
+function! ale#lsp#SendMessageToAddress(address, message) abort
+ if a:0 > 1
+ throw 'Too many arguments!'
+ endif
+
+ if !a:message[0] && a:0 == 0
+ throw 'A callback must be set for messages which are not notifications!'
+ endif
+
+ let [l:id, l:data] = ale#lsp#CreateMessageData(a:message)
+
+ let l:matches = filter(s:connections[:], 'v:val.address ==# a:address')
+
+ " No connection is currently open.
+ if empty(l:matches)
+ return 0
+ endif
+
+ let l:conn = l:matches[0]
+
+ if ch_status(l:conn.channnel) !=# 'open'
return 0
endif
" Send the message to the server
call ch_sendraw(l:conn.channel, l:data)
+
+ return l:id == 0 ? -1 : l:id
endfunction
diff --git a/autoload/ale/lsp/response.vim b/autoload/ale/lsp/response.vim
index aeb93a58..a2146f6a 100644
--- a/autoload/ale/lsp/response.vim
+++ b/autoload/ale/lsp/response.vim
@@ -15,7 +15,7 @@ function! ale#lsp#response#ReadDiagnostics(params) abort
for l:diagnostic in a:params.diagnostics
let l:severity = get(l:diagnostic, 'severity', 0)
let l:loclist_item = {
- \ 'message': l:diagnostic.message,
+ \ 'text': l:diagnostic.message,
\ 'type': 'E',
\ 'lnum': l:diagnostic.range.start.line + 1,
\ 'col': l:diagnostic.range.start.character + 1,
@@ -42,3 +42,26 @@ function! ale#lsp#response#ReadDiagnostics(params) abort
return [l:filename, l:loclist]
endfunction
+
+function! ale#lsp#response#ReadTSServerDiagnostics(response) abort
+ let l:loclist = []
+
+ for l:diagnostic in a:response.body.diagnostics
+ let l:loclist_item = {
+ \ 'text': l:diagnostic.text,
+ \ 'type': 'E',
+ \ 'lnum': l:diagnostic.start.line,
+ \ 'col': l:diagnostic.start.offset,
+ \ 'end_lnum': l:diagnostic.end.line,
+ \ 'end_col': l:diagnostic.end.offset,
+ \}
+
+ if has_key(l:diagnostic, 'code')
+ let l:loclist_item.nr = l:diagnostic.code
+ endif
+
+ call add(l:loclist, l:loclist_item)
+ endfor
+
+ return l:loclist
+endfunction
diff --git a/autoload/ale/lsp/tsserver_message.vim b/autoload/ale/lsp/tsserver_message.vim
index fff1797e..e78b29e3 100644
--- a/autoload/ale/lsp/tsserver_message.vim
+++ b/autoload/ale/lsp/tsserver_message.vim
@@ -19,12 +19,15 @@ endfunction
function! ale#lsp#tsserver_message#Change(buffer) abort
let l:lines = getbufline(a:buffer, 1, '$')
+ " We will always use a very high endLine number, so we can delete
+ " lines from files. tsserver will gladly accept line numbers beyond the
+ " end.
return [1, 'ts@change', {
\ 'file': expand('#' . a:buffer . ':p'),
\ 'line': 1,
\ 'offset': 1,
- \ 'endLine': len(l:lines),
- \ 'endOffset': len(l:lines[-1]),
+ \ 'endLine': 1073741824 ,
+ \ 'endOffset': 1,
\ 'insertString': join(l:lines, "\n"),
\}]
endfunction
diff --git a/test/lsp/test_lsp_client_messages.vader b/test/lsp/test_lsp_client_messages.vader
index a967e4ec..5decbf6c 100644
--- a/test/lsp/test_lsp_client_messages.vader
+++ b/test/lsp/test_lsp_client_messages.vader
@@ -127,8 +127,8 @@ Execute(ale#lsp#tsserver_message#Change() should return correct messages):
\ 'file': b:dir . '/foo.ts',
\ 'line': 1,
\ 'offset': 1,
- \ 'endLine': 3,
- \ 'endOffset': 5,
+ \ 'endLine': 1073741824,
+ \ 'endOffset': 1,
\ 'insertString': "foo()\nbar()\nbaz()",
\ }
\ ],
diff --git a/test/lsp/test_lsp_connections.vader b/test/lsp/test_lsp_connections.vader
index 82e3fc64..1faa7a03 100644
--- a/test/lsp/test_lsp_connections.vader
+++ b/test/lsp/test_lsp_connections.vader
@@ -110,55 +110,63 @@ Execute(ale#lsp#CreateMessageData() should create tsserver notification messages
AssertEqual
\ [
\ 0,
- \ '{"seq": null, "type": "request", "command": "someNotification"}',
+ \ '{"seq": null, "type": "request", "command": "someNotification"}'
+ \ . "\n",
\ ],
\ ale#lsp#CreateMessageData([1, 'ts@someNotification'])
AssertEqual
\ [
\ 0,
- \ '{"seq": null, "arguments": {"foo": "bar"}, "type": "request", "command": "someNotification"}',
+ \ '{"seq": null, "arguments": {"foo": "bar"}, "type": "request", "command": "someNotification"}'
+ \ . "\n",
\ ],
\ ale#lsp#CreateMessageData([1, 'ts@someNotification', {'foo': 'bar'}])
else
AssertEqual
\ [
\ 0,
- \ '{"seq":null,"type":"request","command":"someNotification"}',
+ \ '{"seq":null,"type":"request","command":"someNotification"}'
+ \ . "\n",
\ ],
\ ale#lsp#CreateMessageData([1, 'ts@someNotification'])
AssertEqual
\ [
\ 0,
- \ '{"seq":null,"arguments":{"foo":"bar"},"type":"request","command":"someNotification"}',
+ \ '{"seq":null,"arguments":{"foo":"bar"},"type":"request","command":"someNotification"}'
+ \ . "\n",
\ ],
\ ale#lsp#CreateMessageData([1, 'ts@someNotification', {'foo': 'bar'}])
endif
-Execute(ale#lsp#CreateMessageData() should create tsserver messages excepting responses):
+Execute(ale#lsp#CreateMessageData() should create tsserver messages expecting responses):
if has('nvim')
AssertEqual
\ [
\ 1,
- \ '{"seq": 1, "type": "request", "command": "someMessage"}',
+ \ '{"seq": 1, "type": "request", "command": "someMessage"}'
+ \ . "\n",
\ ],
\ ale#lsp#CreateMessageData([0, 'ts@someMessage'])
AssertEqual
\ [
\ 2,
- \ '{"seq": 2, "arguments": {"foo": "bar"}, "type": "request", "command": "someMessage"}',
+ \ '{"seq": 2, "arguments": {"foo": "bar"}, "type": "request", "command": "someMessage"}'
+ \ . "\n",
\ ],
\ ale#lsp#CreateMessageData([0, 'ts@someMessage', {'foo': 'bar'}])
else
AssertEqual
\ [
\ 1,
- \ '{"seq":1,"type":"request","command":"someMessage"}',
+ \ '{"seq":1,"type":"request","command":"someMessage"}'
+ \ . "\n",
\ ],
\ ale#lsp#CreateMessageData([0, 'ts@someMessage'])
AssertEqual
\ [
\ 2,
- \ '{"seq":2,"arguments":{"foo":"bar"},"type":"request","command":"someMessage"}',
+ \ '{"seq":2,"arguments":{"foo":"bar"},"type":"request","command":"someMessage"}'
+ \ . "\n",
\ ],
\ ale#lsp#CreateMessageData([0, 'ts@someMessage', {'foo': 'bar'}])
endif
diff --git a/test/lsp/test_read_lsp_diagnostics.vader b/test/lsp/test_read_lsp_diagnostics.vader
index b52da1bd..63086a7f 100644
--- a/test/lsp/test_read_lsp_diagnostics.vader
+++ b/test/lsp/test_read_lsp_diagnostics.vader
@@ -13,7 +13,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle errors):
AssertEqual ['filename.ts', [
\ {
\ 'type': 'E',
- \ 'message': 'Something went wrong!',
+ \ 'text': 'Something went wrong!',
\ 'lnum': 3,
\ 'col': 11,
\ 'end_lnum': 5,
@@ -34,7 +34,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle warnings):
AssertEqual ['filename.ts', [
\ {
\ 'type': 'W',
- \ 'message': 'Something went wrong!',
+ \ 'text': 'Something went wrong!',
\ 'lnum': 2,
\ 'col': 4,
\ 'end_lnum': 2,
@@ -55,7 +55,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should treat messages with missing se
AssertEqual ['filename.ts', [
\ {
\ 'type': 'E',
- \ 'message': 'Something went wrong!',
+ \ 'text': 'Something went wrong!',
\ 'lnum': 3,
\ 'col': 11,
\ 'end_lnum': 5,
@@ -75,7 +75,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle messages without codes)
AssertEqual ['filename.ts', [
\ {
\ 'type': 'E',
- \ 'message': 'Something went wrong!',
+ \ 'text': 'Something went wrong!',
\ 'lnum': 3,
\ 'col': 11,
\ 'end_lnum': 5,
@@ -93,7 +93,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages):
AssertEqual ['filename.ts', [
\ {
\ 'type': 'E',
- \ 'message': 'Something went wrong!',
+ \ 'text': 'Something went wrong!',
\ 'lnum': 1,
\ 'col': 3,
\ 'end_lnum': 1,
@@ -101,7 +101,7 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages):
\ },
\ {
\ 'type': 'W',
- \ 'message': 'A warning',
+ \ 'text': 'A warning',
\ 'lnum': 2,
\ 'col': 5,
\ 'end_lnum': 2,
@@ -119,3 +119,17 @@ Execute(ale#lsp#response#ReadDiagnostics() should handle multiple messages):
\ 'message': 'A warning',
\ },
\ ]})
+
+Execute(ale#lsp#response#ReadTSServerDiagnostics() should handle tsserver responses):
+ AssertEqual [
+ \ {
+ \ 'type': 'E',
+ \ 'nr': 2365,
+ \ 'text': 'Operator ''''+'''' cannot be applied to types ''''3'''' and ''''{}''''.',
+ \ 'lnum': 1,
+ \ 'col': 11,
+ \ 'end_lnum': 1,
+ \ 'end_col': 17,
+ \ },
+ \],
+ \ ale#lsp#response#ReadTSServerDiagnostics({"seq":0,"type":"event","event":"semanticDiag","body":{"file":"/bar/foo.ts","diagnostics":[{"start":{"line":1,"offset":11},"end":{"line":1,"offset":17},"text":"Operator ''+'' cannot be applied to types ''3'' and ''{}''.","code":2365}]}})
diff --git a/test/test_loclist_corrections.vader b/test/test_loclist_corrections.vader
index 4e3f543c..e23109ed 100644
--- a/test/test_loclist_corrections.vader
+++ b/test/test_loclist_corrections.vader
@@ -36,7 +36,7 @@ Execute(FixLocList should set all the default values correctly):
\],
\ ale#engine#FixLocList(
\ bufnr('%'),
- \ {'name': 'foobar'},
+ \ 'foobar',
\ [{'text': 'a', 'lnum': 2}, {'text': 'b', 'lnum': 2}],
\ )
@@ -56,7 +56,7 @@ Execute(FixLocList should use the values we supply):
\],
\ ale#engine#FixLocList(
\ bufnr('%'),
- \ {'name': 'foobar'},
+ \ 'foobar',
\ [{
\ 'text': 'a',
\ 'lnum': 3,
@@ -84,7 +84,7 @@ Execute(FixLocList should set items with lines beyond the end to the last line):
\],
\ ale#engine#FixLocList(
\ bufnr('%'),
- \ {'name': 'foobar'},
+ \ 'foobar',
\ [{'text': 'a', 'lnum': 11}],
\ )
@@ -104,7 +104,7 @@ Execute(FixLocList should move line 0 to line 1):
\],
\ ale#engine#FixLocList(
\ bufnr('%'),
- \ {'name': 'foobar'},
+ \ 'foobar',
\ [{'text': 'a', 'lnum': 0}],
\ )
@@ -125,7 +125,7 @@ Execute(FixLocList should convert line and column numbers correctly):
\],
\ ale#engine#FixLocList(
\ bufnr('%'),
- \ {'name': 'foobar'},
+ \ 'foobar',
\ [{'text': 'a', 'lnum': '010', 'col': '010'}],
\ )
@@ -158,7 +158,7 @@ Execute(FixLocList should pass on end_col values):
\],
\ ale#engine#FixLocList(
\ bufnr('%'),
- \ {'name': 'foobar'},
+ \ 'foobar',
\ [
\ {'text': 'a', 'lnum': '010', 'col': '010', 'end_col': '012'},
\ {'text': 'a', 'lnum': '010', 'col': '011', 'end_col': 12},
@@ -195,7 +195,7 @@ Execute(FixLocList should pass on end_lnum values):
\],
\ ale#engine#FixLocList(
\ bufnr('%'),
- \ {'name': 'foobar'},
+ \ 'foobar',
\ [
\ {'text': 'a', 'lnum': '010', 'col': '010', 'end_col': '012', 'end_lnum': '013'},
\ {'text': 'a', 'lnum': '010', 'col': '011', 'end_col': 12, 'end_lnum': 13},
@@ -220,6 +220,6 @@ Execute(FixLocList should allow subtypes to be set):
\],
\ ale#engine#FixLocList(
\ bufnr('%'),
- \ {'name': 'foobar'},
+ \ 'foobar',
\ [{'text': 'a', 'lnum': 11, 'sub_type': 'style'}],
\ )