1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
Before:
runtime autoload/ale/linter.vim
runtime autoload/ale/lsp.vim
runtime autoload/ale/lsp_linter.vim
let g:address = 'ccls_address'
let g:conn_id = -1
let g:executable = 'ccls'
let g:executable_or_address = ''
let g:linter_name = 'ccls'
let g:magic_number = 42
let g:no_result = 0
let g:message_list = []
let g:message_id = 1
let g:method = '$ccls/call'
let g:parameters = {}
let g:project_root = '/project/root'
let g:response = ''
let g:return_value = -1
let g:linter_list = [{
\ 'output_stream': 'stdout',
\ 'lint_file': 0,
\ 'language': 'cpp',
\ 'name': g:linter_name,
\ 'project_root': {b -> g:project_root},
\ 'aliases': [],
\ 'read_buffer': 1,
\ 'command': '%e'
\ }]
let g:callback_result = g:no_result
" Encode dictionary to jsonrpc
function! Encode(obj) abort
let l:body = json_encode(a:obj)
return 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body
endfunction
" Replace the StartLSP function to mock an LSP linter
function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
let g:conn_id = ale#lsp#Register(g:executable_or_address, g:project_root, {})
call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer)
call ale#lsp#HandleMessage(g:conn_id, Encode({'method': 'initialize'}))
let l:details = {
\ 'command': g:executable,
\ 'buffer': a:buffer,
\ 'connection_id': g:conn_id,
\ 'project_root': g:project_root,
\}
call ale#lsp_linter#OnInit(a:linter, l:details, a:Callback)
endfunction
" Dummy callback
function! Callback(response) abort
let g:callback_result = a:response.result.value
endfunction
" Replace the GetAll function to mock an LSP linter
function! ale#linter#GetAll(filetype) abort
return g:linter_list
endfunction
" Replace the Send function to mock an LSP linter
function! ale#lsp#Send(conn_id, message) abort
call add(g:message_list, a:message)
return g:message_id
endfunction
" Code for a test case
function! TestCase(is_notification) abort
" Test sending a custom request
let g:return_value = ale#lsp_linter#SendRequest(
\ bufnr('%'),
\ g:linter_name,
\ [a:is_notification, g:method, g:parameters],
\ function('Callback'))
Assert index(g:message_list, [a:is_notification, g:method, g:parameters]) >= 0
" Mock an incoming response to the request
let g:response = Encode({
\ 'id': g:message_id,
\ 'jsonrpc': '2.0',
\ 'result': {'value': g:magic_number}
\ })
call ale#lsp#HandleMessage(g:conn_id, g:response)
AssertEqual
\ a:is_notification ? g:no_result : g:magic_number,
\ g:callback_result
endfunction
After:
if g:conn_id isnot v:null
call ale#lsp#RemoveConnectionWithID(g:conn_id)
endif
unlet! g:callback_result
unlet! g:conn_id
unlet! g:executable
unlet! g:is_notification
unlet! g:linter_name
unlet! g:magic_number
unlet! g:message_list
unlet! g:message_id
unlet! g:method
unlet! g:no_result
unlet! g:parameters
unlet! g:project_root
unlet! g:response
unlet! g:return_value
delfunction Encode
delfunction Callback
delfunction TestCase
runtime autoload/ale/linter.vim
runtime autoload/ale/lsp.vim
runtime autoload/ale/lsp_linter.vim
Given cpp(Empty cpp file):
Execute(Test custom request to server identified by executable):
let g:executable_or_address = g:executable
let g:linter_list[0].executable = {b -> g:executable}
let g:linter_list[0].lsp = 'stdio'
let g:is_notification = 0
call TestCase(g:is_notification)
Given cpp(Empty cpp file):
Execute(Test custom notification to server identified by executable):
let g:executable_or_address = g:executable
let g:linter_list[0].executable = {b -> g:executable}
let g:linter_list[0].lsp = 'stdio'
let g:is_notification = 1
call TestCase(g:is_notification)
Given cpp(Empty cpp file):
Execute(Test custom request to server identified by address):
let g:executable_or_address = g:address
let g:linter_list[0].address = {b -> g:address}
let g:linter_list[0].lsp = 'socket'
let g:is_notification = 0
call TestCase(g:is_notification)
Given cpp(Empty cpp file):
Execute(Test custom notification to server identified by address):
let g:executable_or_address = g:address
let g:linter_list[0].address = {b -> g:address}
let g:linter_list[0].lsp = 'socket'
let g:is_notification = 1
call TestCase(g:is_notification)
|