From 0eaf8340858e3975320297756b69989e9af353d8 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 24 Jul 2025 18:24:35 +0000 Subject: [PATCH] Improve handling of dart format stderr output Previously the `stdout` and `stderr` from the format execution were merged and there was special handling for 1 specific warning message followed by a standard 2 lines of boilerplate. Now `stdout` an `stderr` are read separately. `stderr` is ignored unless there is no output on `stdout`. This filters any warnings that didn't prevent formatting, including the old hardcoded warning as well as a new one around resolving `analysis_options.yaml` and any future warnings that may come up. When there is no `stdout` content treat the `stderr` as using the diagnostic format. Ignore any lines that don't match the error format. I'm not currently aware of any output here that we _wouldn't_ want to hide, but if error output becomes important for the user to see we may need to revisit this design. - Migrate from `systemlist` to `job_start` which allows separating the output streams. - Pull the result handling out into a separate function so it can be the callback for when the output has been read. --- autoload/dart.vim | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/autoload/dart.vim b/autoload/dart.vim index fd4409a..699ab12 100644 --- a/autoload/dart.vim +++ b/autoload/dart.vim @@ -29,33 +29,47 @@ function! dart#fmt(...) abort let l:dartfmt = s:FindDartFmt() if empty(l:dartfmt) | return | endif let buffer_content = getline(1, '$') - let l:cmd = extend(l:dartfmt, ['--stdin-name', shellescape(expand('%'))]) + let l:cmd = extend(l:dartfmt, ['--stdin-name', expand('%')]) if exists('g:dartfmt_options') call extend(l:cmd, g:dartfmt_options) endif call extend(l:cmd, a:000) - let lines = systemlist(join(l:cmd), join(buffer_content, "\n")) - " TODO(https://github.com/dart-lang/sdk/issues/38507) - Remove once the - " tool no longer emits this line on SDK upgrades. - if lines[-1] ==# 'Isolate creation failed' - let lines = lines[:-2] + let l:stdout_data = [] + let l:stderr_data = [] + let l:options = { + \ 'out_cb': { ch, msg -> add(l:stdout_data, msg) }, + \ 'err_cb': { ch, msg -> add(l:stderr_data, msg) }, + \ 'close_cb': { ch -> + \ s:formatResult(l:stdout_data, l:stderr_data, l:buffer_content)} } + if has('patch-8.1.350') + let options['noblock'] = v:true endif - if buffer_content == lines + let l:job = job_start(l:cmd, l:options) + call ch_sendraw(job_getchannel(l:job), join(l:buffer_content, "\n")) + call ch_close_in(job_getchannel(l:job)) +endfunction + +function! s:formatResult(stdout, stderr, buffer_content) abort + if a:buffer_content == a:stdout call s:clearQfList('dartfmt') return endif - if 0 == v:shell_error + if !empty(a:stdout) let win_view = winsaveview() - silent keepjumps call setline(1, lines) - if line('$') > len(lines) - silent keepjumps execute string(len(lines)+1).',$ delete' + silent keepjumps call setline(1, a:stdout) + if line('$') > len(a:stdout) + silent keepjumps execute string(len(a:stdout)+1).',$ delete' endif call winrestview(win_view) call s:clearQfList('dartfmt') else - let errors = lines[2:] - let error_format = '%Aline %l\, column %c of %f: %m,%C%.%#' - call s:cexpr(error_format, errors, 'dartfmt') + let l:skip_count = 0 + while l:skip_count < len(a:stderr) && a:stderr[l:skip_count] =~# '^||' + let l:skip_count += 1 + endwhile + let l:diagnostics = a:stderr[l:skip_count:] + let l:format = '%Aline %l\, column %c of %f: %m,%C%.%#,%-G%.%#' + call s:cexpr(l:format, l:diagnostics, 'dartfmt') endif endfunction