diff options
-rw-r--r-- | autoload/ale/lsp.vim | 32 | ||||
-rw-r--r-- | autoload/ale/lsp/tsserver_message.vim | 34 | ||||
-rw-r--r-- | test/lsp/test_lsp_client_messages.vader | 70 | ||||
-rw-r--r-- | test/lsp/test_lsp_connections.vader | 58 |
4 files changed, 193 insertions, 1 deletions
diff --git a/autoload/ale/lsp.vim b/autoload/ale/lsp.vim index 36620228..76d0c8df 100644 --- a/autoload/ale/lsp.vim +++ b/autoload/ale/lsp.vim @@ -42,9 +42,35 @@ function! ale#lsp#GetNextMessageID() abort return l:id endfunction +" TypeScript messages use a different format. +function! s:CreateTSServerMessageData(message) abort + let l:is_notification = a:message[0] + + let l:obj = { + \ 'seq': v:null, + \ 'type': 'request', + \ 'command': a:message[1][3:], + \} + + if !l:is_notification + let l:obj.seq = ale#lsp#GetNextMessageID() + endif + + if len(a:message) > 2 + let l:obj.arguments = a:message[2] + endif + + let l:data = json_encode(l:obj) + return [l:is_notification ? 0 : l:obj.seq, l:data] +endfunction + " Given a List of one or two items, [method_name] or [method_name, params], " return a List containing [message_id, message_data] function! ale#lsp#CreateMessageData(message) abort + if a:message[1] =~# '^ts@' + return s:CreateTSServerMessageData(a:message) + endif + let l:is_notification = a:message[0] let l:obj = { @@ -117,7 +143,11 @@ function! ale#lsp#HandleMessage(conn, message) abort " Call our callbacks. for l:response in l:response_list - let l:callback = a:conn.callback_map.pop(l:response.id) + 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) endfor endfunction diff --git a/autoload/ale/lsp/tsserver_message.vim b/autoload/ale/lsp/tsserver_message.vim new file mode 100644 index 00000000..fff1797e --- /dev/null +++ b/autoload/ale/lsp/tsserver_message.vim @@ -0,0 +1,34 @@ +" Author: w0rp <devw0rp@gmail.com> +" Description: tsserver message implementations +" +" Messages in this movie will be returned in the format +" [is_notification, command_name, params?] +" +" Every command must begin with the string 'ts@', which will be used to +" detect the different message format for tsserver, and this string will +" be removed from the actual command name, + +function! ale#lsp#tsserver_message#Open(buffer) abort + return [1, 'ts@open', {'file': expand('#' . a:buffer . ':p')}] +endfunction + +function! ale#lsp#tsserver_message#Close(buffer) abort + return [1, 'ts@close', {'file': expand('#' . a:buffer . ':p')}] +endfunction + +function! ale#lsp#tsserver_message#Change(buffer) abort + let l:lines = getbufline(a:buffer, 1, '$') + + return [1, 'ts@change', { + \ 'file': expand('#' . a:buffer . ':p'), + \ 'line': 1, + \ 'offset': 1, + \ 'endLine': len(l:lines), + \ 'endOffset': len(l:lines[-1]), + \ 'insertString': join(l:lines, "\n"), + \}] +endfunction + +function! ale#lsp#tsserver_message#Geterr(buffer) abort + return [1, 'ts@geterr', {'files': [expand('#' . a:buffer . ':p')]}] +endfunction diff --git a/test/lsp/test_lsp_client_messages.vader b/test/lsp/test_lsp_client_messages.vader index de18a4b8..a967e4ec 100644 --- a/test/lsp/test_lsp_client_messages.vader +++ b/test/lsp/test_lsp_client_messages.vader @@ -1,3 +1,11 @@ +Before: + silent! cd /testplugin/test/lsp + let b:dir = getcwd() + +After: + silent execute 'cd ' . fnameescape(b:dir) + unlet! b:dir + Execute(ale#lsp#message#Initialize() should return correct messages): AssertEqual \ [ @@ -76,3 +84,65 @@ Execute(ale#lsp#message#DidClose() should return correct messages): \ } \ ], \ ale#lsp#message#DidClose('/foo/bar') + +Execute(ale#lsp#tsserver_message#Open() should return correct messages): + silent! noautocmd file foo.ts + + AssertEqual + \ [ + \ 1, + \ 'ts@open', + \ { + \ 'file': b:dir . '/foo.ts', + \ } + \ ], + \ ale#lsp#tsserver_message#Open(bufnr('')) + +Execute(ale#lsp#tsserver_message#Close() should return correct messages): + silent! noautocmd file foo.ts + + AssertEqual + \ [ + \ 1, + \ 'ts@close', + \ { + \ 'file': b:dir . '/foo.ts', + \ } + \ ], + \ ale#lsp#tsserver_message#Close(bufnr('')) + +Given typescript(A TypeScript file with 3 lines): + foo() + bar() + baz() + +Execute(ale#lsp#tsserver_message#Change() should return correct messages): + silent! noautocmd file foo.ts + + AssertEqual + \ [ + \ 1, + \ 'ts@change', + \ { + \ 'file': b:dir . '/foo.ts', + \ 'line': 1, + \ 'offset': 1, + \ 'endLine': 3, + \ 'endOffset': 5, + \ 'insertString': "foo()\nbar()\nbaz()", + \ } + \ ], + \ ale#lsp#tsserver_message#Change(bufnr('')) + +Execute(ale#lsp#tsserver_message#Geterr() should return correct messages): + silent! noautocmd file foo.ts + + AssertEqual + \ [ + \ 1, + \ 'ts@geterr', + \ { + \ 'files': [b:dir . '/foo.ts'], + \ } + \ ], + \ ale#lsp#tsserver_message#Geterr(bufnr('')) diff --git a/test/lsp/test_lsp_connections.vader b/test/lsp/test_lsp_connections.vader index d5ed7702..82e3fc64 100644 --- a/test/lsp/test_lsp_connections.vader +++ b/test/lsp/test_lsp_connections.vader @@ -105,6 +105,64 @@ Execute(ale#lsp#CreateMessageData() should create notifications): \ ale#lsp#CreateMessageData([1, 'someNotification', {'foo': 'bar'}]) endif +Execute(ale#lsp#CreateMessageData() should create tsserver notification messages): + if has('nvim') + AssertEqual + \ [ + \ 0, + \ '{"seq": null, "type": "request", "command": "someNotification"}', + \ ], + \ ale#lsp#CreateMessageData([1, 'ts@someNotification']) + AssertEqual + \ [ + \ 0, + \ '{"seq": null, "arguments": {"foo": "bar"}, "type": "request", "command": "someNotification"}', + \ ], + \ ale#lsp#CreateMessageData([1, 'ts@someNotification', {'foo': 'bar'}]) + else + AssertEqual + \ [ + \ 0, + \ '{"seq":null,"type":"request","command":"someNotification"}', + \ ], + \ ale#lsp#CreateMessageData([1, 'ts@someNotification']) + AssertEqual + \ [ + \ 0, + \ '{"seq":null,"arguments":{"foo":"bar"},"type":"request","command":"someNotification"}', + \ ], + \ ale#lsp#CreateMessageData([1, 'ts@someNotification', {'foo': 'bar'}]) + endif + +Execute(ale#lsp#CreateMessageData() should create tsserver messages excepting responses): + if has('nvim') + AssertEqual + \ [ + \ 1, + \ '{"seq": 1, "type": "request", "command": "someMessage"}', + \ ], + \ ale#lsp#CreateMessageData([0, 'ts@someMessage']) + AssertEqual + \ [ + \ 2, + \ '{"seq": 2, "arguments": {"foo": "bar"}, "type": "request", "command": "someMessage"}', + \ ], + \ ale#lsp#CreateMessageData([0, 'ts@someMessage', {'foo': 'bar'}]) + else + AssertEqual + \ [ + \ 1, + \ '{"seq":1,"type":"request","command":"someMessage"}', + \ ], + \ ale#lsp#CreateMessageData([0, 'ts@someMessage']) + AssertEqual + \ [ + \ 2, + \ '{"seq":2,"arguments":{"foo":"bar"},"type":"request","command":"someMessage"}', + \ ], + \ ale#lsp#CreateMessageData([0, 'ts@someMessage', {'foo': 'bar'}]) + endif + Execute(ale#lsp#ReadMessageData() should read single whole messages): AssertEqual \ ['', [{'id': 2, 'jsonrpc': '2.0', 'result': {'foo': 'barÜ'}}]], |