]> git.madduck.net Git - etc/vim.git/blob - autoload/ale/lsp/response.vim

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Squashed '.vim/bundle/ale/' content from commit 22185c4c
[etc/vim.git] / autoload / ale / lsp / response.vim
1 " Author: w0rp <devw0rp@gmail.com>
2 " Description: Parsing and transforming of LSP server responses.
3
4 " Constants for error codes.
5 " Defined by JSON RPC
6 let s:PARSE_ERROR = -32700
7 let s:INVALID_REQUEST = -32600
8 let s:METHOD_NOT_FOUND = -32601
9 let s:INVALID_PARAMS = -32602
10 let s:INTERNAL_ERROR = -32603
11 let s:SERVER_ERROR_START = -32099
12 let s:SERVER_ERROR_END = -32000
13 let s:SERVER_NOT_INITIALIZED = -32002
14 let s:UNKNOWN_ERROR_CODE = -32001
15 " Defined by the protocol.
16 let s:REQUEST_CANCELLED = -32800
17
18 " Constants for message severity codes.
19 let s:SEVERITY_ERROR = 1
20 let s:SEVERITY_WARNING = 2
21 let s:SEVERITY_INFORMATION = 3
22 let s:SEVERITY_HINT = 4
23
24 " Convert Diagnostic[] data from a language server to an ALE loclist.
25 function! ale#lsp#response#ReadDiagnostics(diagnostics) abort
26     let l:loclist = []
27
28     for l:diagnostic in a:diagnostics
29         let l:severity = get(l:diagnostic, 'severity', 0)
30         let l:loclist_item = {
31         \   'text': substitute(l:diagnostic.message, '\(\r\n\|\n\|\r\)', ' ', 'g'),
32         \   'type': 'E',
33         \   'lnum': l:diagnostic.range.start.line + 1,
34         \   'col': l:diagnostic.range.start.character + 1,
35         \   'end_lnum': l:diagnostic.range.end.line + 1,
36         \   'end_col': l:diagnostic.range.end.character,
37         \}
38
39         if l:severity == s:SEVERITY_WARNING
40             let l:loclist_item.type = 'W'
41         elseif l:severity == s:SEVERITY_INFORMATION
42             " TODO: Use 'I' here in future.
43             let l:loclist_item.type = 'W'
44         elseif l:severity == s:SEVERITY_HINT
45             " TODO: Use 'H' here in future
46             let l:loclist_item.type = 'W'
47         endif
48
49         if has_key(l:diagnostic, 'code')
50             if type(l:diagnostic.code) == v:t_string
51                 let l:loclist_item.code = l:diagnostic.code
52             elseif type(l:diagnostic.code) == v:t_number && l:diagnostic.code != -1
53                 let l:loclist_item.code = string(l:diagnostic.code)
54                 let l:loclist_item.nr = l:diagnostic.code
55             endif
56         endif
57
58         if has_key(l:diagnostic, 'relatedInformation')
59         \ && l:diagnostic.relatedInformation isnot v:null
60             let l:related = deepcopy(l:diagnostic.relatedInformation)
61             call map(l:related, {key, val ->
62             \   ale#util#ToResource(val.location.uri) .
63             \   ':' . (val.location.range.start.line + 1) .
64             \   ':' . (val.location.range.start.character + 1) .
65             \   ":\n\t" . val.message
66             \})
67             let l:loclist_item.detail = l:diagnostic.message . "\n" . join(l:related, "\n")
68         endif
69
70         if has_key(l:diagnostic, 'source')
71             let l:loclist_item.detail = printf(
72             \   '[%s] %s',
73             \   l:diagnostic.source,
74             \   l:diagnostic.message
75             \)
76         endif
77
78         call add(l:loclist, l:loclist_item)
79     endfor
80
81     return l:loclist
82 endfunction
83
84 function! ale#lsp#response#ReadTSServerDiagnostics(response) abort
85     let l:loclist = []
86
87     for l:diagnostic in a:response.body.diagnostics
88         let l:loclist_item = {
89         \   'text': l:diagnostic.text,
90         \   'type': 'E',
91         \   'lnum': l:diagnostic.start.line,
92         \   'col': l:diagnostic.start.offset,
93         \   'end_lnum': l:diagnostic.end.line,
94         \   'end_col': l:diagnostic.end.offset - 1,
95         \}
96
97         if has_key(l:diagnostic, 'code')
98             if type(l:diagnostic.code) == v:t_string
99                 let l:loclist_item.code = l:diagnostic.code
100             elseif type(l:diagnostic.code) == v:t_number && l:diagnostic.code != -1
101                 let l:loclist_item.code = string(l:diagnostic.code)
102                 let l:loclist_item.nr = l:diagnostic.code
103             endif
104         endif
105
106         if get(l:diagnostic, 'category') is# 'warning'
107             let l:loclist_item.type = 'W'
108         endif
109
110         if get(l:diagnostic, 'category') is# 'suggestion'
111             let l:loclist_item.type = 'I'
112         endif
113
114         call add(l:loclist, l:loclist_item)
115     endfor
116
117     return l:loclist
118 endfunction
119
120 function! ale#lsp#response#GetErrorMessage(response) abort
121     if type(get(a:response, 'error', 0)) isnot v:t_dict
122         return ''
123     endif
124
125     let l:code = get(a:response.error, 'code')
126
127     " Only report things for these error codes.
128     if l:code isnot s:INVALID_PARAMS && l:code isnot s:INTERNAL_ERROR
129         return ''
130     endif
131
132     let l:message = get(a:response.error, 'message', '')
133
134     if empty(l:message)
135         return ''
136     endif
137
138     " Include the traceback or error data as details, if present.
139     let l:error_data = get(a:response.error, 'data', {})
140
141     if type(l:error_data) is v:t_string
142         let l:message .= "\n" . l:error_data
143     elseif type(l:error_data) is v:t_dict
144         let l:traceback = get(l:error_data, 'traceback', [])
145
146         if type(l:traceback) is v:t_list && !empty(l:traceback)
147             let l:message .= "\n" . join(l:traceback, "\n")
148         endif
149     endif
150
151     return l:message
152 endfunction