" Author: Daniel Schemala , " w0rp " " Description: This file implements handlers specific to Rust. if !exists('g:ale_rust_ignore_error_codes') let g:ale_rust_ignore_error_codes = [] endif if !exists('g:ale_rust_ignore_secondary_spans') let g:ale_rust_ignore_secondary_spans = 0 endif function! s:ProcessSpan(buffer, error, span) abort if ale#Var(a:buffer, 'rust_ignore_secondary_spans') && !get(a:span, 'is_primary', 1) return {} endif if !empty(a:span) " :help ale-loclist-format let l:output_line = { \ 'lnum': a:span.line_start, \ 'end_lnum': a:span.line_end, \ 'col': a:span.column_start, \ 'end_col': a:span.column_end-1, \ 'text': empty(a:span.label) ? a:error.message : printf('%s: %s', a:error.message, a:span.label), \ 'type': toupper(a:error.level[0]), \} " When operating on stdin rustc (and possibly others) gives '' " as the file_name. Leaving the filename property of the loclist " unpopulated makes ale connect such errors with the linted buffer. if a:span.file_name !=# '' let l:output_line['filename'] = a:span.file_name endif if has_key(a:error, 'rendered') && !empty(a:error.rendered) let l:output_line.detail = a:error.rendered endif return l:output_line endif return {} endfunction function! ale#handlers#rust#HandleRustErrors(buffer, lines) abort let l:output = [] " Format of JSON is documented at " rustc: https://doc.rust-lang.org/rustc/json.html " cargo: https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages for l:diagnosticsline in a:lines " ignore everything that is not JSON if l:diagnosticsline !~# '^{' continue endif let l:diagnostics = json_decode(l:diagnosticsline) if has_key(l:diagnostics, 'message') && type(l:diagnostics.message) is v:t_dict let l:diagnostics = l:diagnostics.message endif if !has_key(l:diagnostics, 'code') continue endif if !empty(l:diagnostics.code) && index(g:ale_rust_ignore_error_codes, l:diagnostics.code.code) > -1 continue endif let l:spans = [] " FIXME One might also wish to loop over l:diagnostics.children and " their spans. for l:span in l:diagnostics.spans call add(l:spans, l:span) let l:expansion = l:span.expansion if !empty(l:expansion) let l:expansion_span = l:expansion.span call add(l:spans, l:expansion_span) endif endfor for l:span in l:spans let l:output_line = s:ProcessSpan(a:buffer, l:diagnostics, l:span) if !empty(l:output_line) call add(l:output, l:output_line) endif endfor endfor return l:output endfunction