From 1bf445c6d5c805db0e0733846538fa4bfd5d8a68 Mon Sep 17 00:00:00 2001 From: w0rp Date: Sun, 10 Sep 2023 17:44:25 +0100 Subject: Print the most severe problem with virtualtext Fix the ordering of virtualtext so we print the most severe problem on a line. If two problems are the most severe, we will print the left-most problem. --- autoload/ale/virtualtext.vim | 48 +++++++++++++++++++++++++++++++++++--------- doc/ale.txt | 6 +++--- test/test_virtualtext.vader | 32 ++++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/autoload/ale/virtualtext.vim b/autoload/ale/virtualtext.vim index 1f4d1fde..551211e8 100644 --- a/autoload/ale/virtualtext.vim +++ b/autoload/ale/virtualtext.vim @@ -274,6 +274,32 @@ function! ale#virtualtext#ShowCursorWarningWithDelay() abort endif endfunction +function! ale#virtualtext#CompareSeverityPerLine(left, right) abort + " Compare lines + if a:left.lnum < a:right.lnum + return -1 + endif + + if a:left.lnum > a:right.lnum + return 1 + endif + + let l:left_priority = ale#util#GetItemPriority(a:left) + let l:right_priority = ale#util#GetItemPriority(a:right) + + " Put highest priority items first. + if l:left_priority > l:right_priority + return -1 + endif + + if l:left_priority < l:right_priority + return 1 + endif + + " Put the first seen problem first. + return a:left.col - a:right.col +endfunction + function! ale#virtualtext#SetTexts(buffer, loclist) abort if !has('nvim') && s:emulate_virt return @@ -281,17 +307,19 @@ function! ale#virtualtext#SetTexts(buffer, loclist) abort call ale#virtualtext#Clear(a:buffer) - let l:filter = ale#Var(a:buffer,'virtualtext_single') - let l:seen = {} + let l:buffer_list = filter(copy(a:loclist), 'v:val.bufnr == a:buffer') - for l:item in a:loclist - if l:item.bufnr == a:buffer - let l:line = max([1, l:item.lnum]) + if ale#Var(a:buffer,'virtualtext_single') + " If we want a single problem per line, sort items on each line by + " highest severity and then lowest column position, then de-duplicate + " the items by line. + call uniq( + \ sort(l:buffer_list, function('ale#virtualtext#CompareSeverityPerLine')), + \ {a, b -> a.lnum - b.lnum} + \) + endif - if !has_key(l:seen,l:line) || l:filter == 0 - call ale#virtualtext#ShowMessage(a:buffer, l:item) - let l:seen[l:line] = 1 - endif - endif + for l:item in l:buffer_list + call ale#virtualtext#ShowMessage(a:buffer, l:item) endfor endfunction diff --git a/doc/ale.txt b/doc/ale.txt index 2b73337c..0263c8cc 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2443,9 +2443,9 @@ g:ale_virtualtext_single *g:ale_virtualtext_single* appended in turn. With `single` set to a non-zero value, only the first problem on a line will - be printed with virtual text. The problem at the left-most position on a - line will be printed. If two problems exist at the same position, the most - severe problem will be printed. + be printed with virtual text. The most severe problem on a line will be + printed. If two problems exist on a line of equal severity, the problem at + the left-most position will be printed. g:ale_virtualenv_dir_names *g:ale_virtualenv_dir_names* diff --git a/test/test_virtualtext.vader b/test/test_virtualtext.vader index 25965f50..da58c9f0 100644 --- a/test/test_virtualtext.vader +++ b/test/test_virtualtext.vader @@ -37,6 +37,27 @@ Before: \ 'col': 5, \ 'text': 'Line 2 warning 2', \ }, + \ { + \ 'bufnr': bufnr(''), + \ 'type': 'W', + \ 'lnum': 3, + \ 'col': 3, + \ 'text': 'Line 3 warning 1', + \ }, + \ { + \ 'bufnr': bufnr(''), + \ 'type': 'E', + \ 'lnum': 3, + \ 'col': 5, + \ 'text': 'Line 3 error 1', + \ }, + \ { + \ 'bufnr': bufnr(''), + \ 'type': 'E', + \ 'lnum': 3, + \ 'col': 6, + \ 'text': 'Line 3 error 2', + \ }, \ ], \ }, \} @@ -79,6 +100,7 @@ Execute(Comment text should be detected correctly for HTML files): Given python(An example Python file): # line 1 # line 2 + # line 3 Execute(We should not show virtualtext when disabled): if has('patch-9.0.0297') || has('nvim-0.8.0') @@ -157,11 +179,11 @@ Execute(We should be able to change the virtualtext prefix per-buffer): AssertEqual 'B> Line 1 error', ale#virtualtext#GetLastMessageForTests() endif -Execute(We should set errors across all lines): +Execute(We should be able to set messages across all lines): if has('patch-9.0.0297') || has('nvim-0.8.0') call ale#virtualtext#SetTexts(bufnr(''), g:ale_buffer_info[bufnr('')].loclist) - AssertEqual '# W: Line 2 warning 2', ale#virtualtext#GetLastMessageForTests() + AssertEqual '# E: Line 3 error 2', ale#virtualtext#GetLastMessageForTests() if has('patch-9.0.0297') AssertEqual ['ALEVirtualTextError'], map(prop_list(1), {_, v -> v.type}) @@ -176,12 +198,12 @@ Execute(We should be able to limit virtual messages to the first one only): if has('patch-9.0.0297') || has('nvim-0.8.0') call ale#virtualtext#SetTexts(bufnr(''), g:ale_buffer_info[bufnr('')].loclist) - AssertEqual '# W: Line 2 warning 1', ale#virtualtext#GetLastMessageForTests() + AssertEqual '# E: Line 3 error 1', ale#virtualtext#GetLastMessageForTests() if has('patch-9.0.0297') AssertEqual ['ALEVirtualTextError'], map(prop_list(1), {_, v -> v.type}) - AssertEqual ['ALEVirtualTextWarning'], - \ map(prop_list(2), {_, v -> v.type}) + AssertEqual ['ALEVirtualTextWarning'], map(prop_list(2), {_, v -> v.type}) + AssertEqual ['ALEVirtualTextError'], map(prop_list(3), {_, v -> v.type}) endif endif -- cgit v1.2.3