diff options
-rw-r--r-- | ale_linters/javascript/eslint.vim | 18 | ||||
-rw-r--r-- | autoload/ale/engine.vim | 5 | ||||
-rw-r--r-- | autoload/ale/highlight.vim | 2 | ||||
-rw-r--r-- | autoload/ale/job.vim | 2 | ||||
-rw-r--r-- | autoload/ale/lsp.vim | 32 | ||||
-rw-r--r-- | test/handler/test_eslint_handler.vader | 58 | ||||
-rw-r--r-- | test/test_highlight_placement.vader | 13 | ||||
-rw-r--r-- | test/test_loclist_corrections.vader | 36 |
8 files changed, 143 insertions, 23 deletions
diff --git a/ale_linters/javascript/eslint.vim b/ale_linters/javascript/eslint.vim index d5e51acb..f1c3bb01 100644 --- a/ale_linters/javascript/eslint.vim +++ b/ale_linters/javascript/eslint.vim @@ -39,6 +39,13 @@ function! ale_linters#javascript#eslint#GetCommand(buffer) abort \ . ' -f unix --stdin --stdin-filename %s' endfunction +let s:col_end_patterns = [ +\ '\vParsing error: Unexpected token (.+) ', +\ '\v''(.+)'' is not defined.', +\ '\v%(Unexpected|Redundant use of) [''`](.+)[''`]', +\ '\vUnexpected (console) statement', +\] + function! ale_linters#javascript#eslint#Handle(buffer, lines) abort let l:config_error_pattern = '\v^ESLint couldn''t find a configuration file' \ . '|^Cannot read config file' @@ -77,13 +84,18 @@ function! ale_linters#javascript#eslint#Handle(buffer, lines) abort let l:text .= ' [' . l:match[4] . ']' endif - call add(l:output, { - \ 'bufnr': a:buffer, + let l:obj = { \ 'lnum': l:match[1] + 0, \ 'col': l:match[2] + 0, \ 'text': l:text, \ 'type': l:type ==# 'Warning' ? 'W' : 'E', - \}) + \} + + for l:col_match in ale#util#GetMatches(l:text, s:col_end_patterns) + let l:obj.end_col = l:obj.col + len(l:col_match[1]) - 1 + endfor + + call add(l:output, l:obj) endfor return l:output diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index c778f253..49cc2a9a 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -288,6 +288,11 @@ function! ale#engine#FixLocList(buffer, linter, loclist) abort let l:item.detail = l:old_item.detail endif + " Pass on a col_length key if set, used for highlights. + if has_key(l:old_item, 'end_col') + let l:item.end_col = str2nr(l:old_item.end_col) + endif + if l:item.lnum == 0 " When errors appear at line 0, put them at line 1 instead. let l:item.lnum = 1 diff --git a/autoload/ale/highlight.vim b/autoload/ale/highlight.vim index f3a479e3..4ac1d1e4 100644 --- a/autoload/ale/highlight.vim +++ b/autoload/ale/highlight.vim @@ -86,7 +86,7 @@ function! ale#highlight#UpdateHighlights() abort let l:col = l:item.col let l:group = l:item.type ==# 'E' ? 'ALEError' : 'ALEWarning' let l:line = l:item.lnum - let l:size = 1 + let l:size = has_key(l:item, 'end_col') ? l:item.end_col - l:col + 1 : 1 " Rememeber the match ID for the item. " This ID will be used to preserve loclist items which are set diff --git a/autoload/ale/job.vim b/autoload/ale/job.vim index d0572f51..11a36045 100644 --- a/autoload/ale/job.vim +++ b/autoload/ale/job.vim @@ -220,7 +220,7 @@ function! ale#job#SendRaw(job_id, string) abort if has('nvim') call jobsend(a:job_id, a:string) else - call ch_sendraw(job_getchannel(s:job_map[a:job_id]), a:string) + call ch_sendraw(job_getchannel(s:job_map[a:job_id].job), a:string) endif endfunction diff --git a/autoload/ale/lsp.vim b/autoload/ale/lsp.vim index acf47408..36620228 100644 --- a/autoload/ale/lsp.vim +++ b/autoload/ale/lsp.vim @@ -160,22 +160,28 @@ function! ale#lsp#SendMessageToProgram(executable, command, message, ...) abort let [l:id, l:data] = ale#lsp#CreateMessageData(a:message) let l:matches = filter(s:connections[:], 'v:val.executable ==# a:executable') - - if empty(l:matches) - " We haven't looked at this executable before. - " Create a new connection. - let l:conn = NewConnection() - endif + " Get the current connection or a new one. + let l:conn = !empty(l:matches) ? l:matches[0] : s:NewConnection() if !ale#job#IsRunning(l:conn.job_id) - let l:options = {'mode': 'raw', 'out_cb': 's:HandleCommandMessage'} + let l:options = { + \ 'mode': 'raw', + \ 'out_cb': function('s:HandleCommandMessage'), + \} let l:job_id = ale#job#Start(ale#job#PrepareCommand(a:command), l:options) endif - if l:job_id > 0 + if l:job_id <= 0 return 0 endif + " The ID is 0 when the message is a Notification, which is a JSON-RPC + " request for which the server must not return a response. + if l:id != 0 + " Add the callback, which the server will respond to later. + let l:conn.callback_map[l:id] = a:1 + endif + call ale#job#SendRaw(l:job_id, l:data) let l:conn.job_id = l:job_id @@ -201,18 +207,14 @@ function! ale#lsp#SendMessageToAddress(address, message, ...) abort let [l:id, l:data] = ale#lsp#CreateMessageData(a:message) let l:matches = filter(s:connections[:], 'v:val.address ==# a:address') - - if empty(l:matches) - " We haven't looked at this address before. - " Create a new connection. - let l:conn = NewConnection() - endif + " Get the current connection or a new one. + let l:conn = !empty(l:matches) ? l:matches[0] : s:NewConnection() if !has_key(l:conn, 'channel') || ch_status(l:conn.channel) !=# 'open' let l:conn.channnel = ch_open(a:address, { \ 'mode': 'raw', \ 'waittime': 0, - \ 'callback': 's:HandleChannelMessage', + \ 'callback': function('s:HandleChannelMessage'), \}) endif diff --git a/test/handler/test_eslint_handler.vader b/test/handler/test_eslint_handler.vader index 6d84ff7e..9d5e98fc 100644 --- a/test/handler/test_eslint_handler.vader +++ b/test/handler/test_eslint_handler.vader @@ -5,21 +5,18 @@ Execute(The eslint handler should parse lines correctly): AssertEqual \ [ \ { - \ 'bufnr': 347, \ 'lnum': 47, \ 'col': 14, \ 'text': 'Missing trailing comma. [Warning/comma-dangle]', \ 'type': 'W', \ }, \ { - \ 'bufnr': 347, \ 'lnum': 56, \ 'col': 41, \ 'text': 'Missing semicolon. [Error/semi]', \ 'type': 'E', \ }, \ { - \ 'bufnr': 347, \ 'lnum': 13, \ 'col': 3, \ 'text': 'Parsing error: Unexpected token', @@ -117,3 +114,58 @@ Execute(The eslint handler should print a message for invalid configuration sett \ 'detail': join(g:config_error_lines, "\n"), \ }], \ ale_linters#javascript#eslint#Handle(347, g:config_error_lines[:]) + +Execute(The eslint handler should output end_col values where appropriate): + AssertEqual + \ [ + \ { + \ 'lnum': 4, + \ 'col': 3, + \ 'end_col': 15, + \ 'text': 'Parsing error: Unexpected token ''some string'' [Error]', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 70, + \ 'col': 3, + \ 'end_col': 5, + \ 'text': '''foo'' is not defined. [Error/no-undef]', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 71, + \ 'col': 2, + \ 'end_col': 6, + \ 'text': 'Unexpected `await` inside a loop. [Error/no-await-in-loop]', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 72, + \ 'col': 6, + \ 'end_col': 10, + \ 'text': 'Redundant use of `await` on a return value. [Error/no-return-await]', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 73, + \ 'col': 4, + \ 'end_col': 10, + \ 'text': 'Unexpected console statement [Error/no-console]', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 74, + \ 'col': 4, + \ 'end_col': 11, + \ 'text': 'Unexpected ''debugger'' statement. [Error/no-debugger]', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#javascript#eslint#Handle(347, [ + \ 'app.js:4:3: Parsing error: Unexpected token ''some string'' [Error]', + \ 'app.js:70:3: ''foo'' is not defined. [Error/no-undef]', + \ 'app.js:71:2: Unexpected `await` inside a loop. [Error/no-await-in-loop]', + \ 'app.js:72:6: Redundant use of `await` on a return value. [Error/no-return-await]', + \ 'app.js:73:4: Unexpected console statement [Error/no-console]', + \ 'app.js:74:4: Unexpected ''debugger'' statement. [Error/no-debugger]', + \ ]) diff --git a/test/test_highlight_placement.vader b/test/test_highlight_placement.vader index 25c98784..b5878922 100644 --- a/test/test_highlight_placement.vader +++ b/test/test_highlight_placement.vader @@ -137,3 +137,16 @@ Execute(Only ALE highlights should be restored when buffers are restored): " Only our matches should appear again. AssertEqual 1, len(getmatches()), 'The highlights weren''t set again!' + +Execute(Higlight end columns should set an appropriate size): + call ale#highlight#SetHighlights(bufnr('%'), [ + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2, 'end_col': 5}, + \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 4, 'col': 1, 'end_col': 5}, + \]) + + AssertEqual + \ [ + \ {'group': 'ALEError', 'id': 15, 'priority': 10, 'pos1': [3, 2, 4]}, + \ {'group': 'ALEWarning', 'id': 16, 'priority': 10, 'pos1': [4, 1, 5]}, + \ ], + \ getmatches() diff --git a/test/test_loclist_corrections.vader b/test/test_loclist_corrections.vader index 281f6787..8e01dfbc 100644 --- a/test/test_loclist_corrections.vader +++ b/test/test_loclist_corrections.vader @@ -128,3 +128,39 @@ Execute(FixLocList should convert line and column numbers correctly): \ {'name': 'foobar'}, \ [{'text': 'a', 'lnum': '010', 'col': '010'}], \ ) + +Execute(FixLocList should pass on col_length values): + " The numbers should be 10, not 8 as octals. + AssertEqual + \ [ + \ { + \ 'text': 'a', + \ 'lnum': 10, + \ 'col': 10, + \ 'end_col': 12, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ }, + \ { + \ 'text': 'a', + \ 'lnum': 10, + \ 'col': 11, + \ 'end_col': 12, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'foobar', + \ }, + \], + \ ale#engine#FixLocList( + \ bufnr('%'), + \ {'name': 'foobar'}, + \ [ + \ {'text': 'a', 'lnum': '010', 'col': '010', 'end_col': '012'}, + \ {'text': 'a', 'lnum': '010', 'col': '011', 'end_col': 12}, + \ ], + \ ) |