diff options
-rw-r--r-- | README.md | 14 | ||||
-rw-r--r-- | ale_linters/dafny/dafny.vim | 25 | ||||
-rw-r--r-- | ale_linters/dart/language_server.vim | 30 | ||||
-rw-r--r-- | ale_linters/python/pyls.vim | 21 | ||||
-rw-r--r-- | ale_linters/typescript/tslint.vim | 4 | ||||
-rw-r--r-- | autoload/ale/fix.vim | 73 | ||||
-rw-r--r-- | autoload/ale/job.vim | 17 | ||||
-rw-r--r-- | autoload/ale/python.vim | 2 | ||||
-rw-r--r-- | doc/ale-python.txt | 9 | ||||
-rw-r--r-- | doc/ale.txt | 26 | ||||
-rw-r--r-- | test/handler/test_dafny_handler.vader | 26 | ||||
-rw-r--r-- | test/handler/test_tslint_handler.vader | 23 | ||||
-rw-r--r-- | test/test_ale_fix.vader | 113 | ||||
-rw-r--r-- | test/test_line_join.vader | 24 |
14 files changed, 362 insertions, 45 deletions
@@ -87,7 +87,8 @@ formatting. | CSS | [csslint](http://csslint.net/), [stylelint](https://github.com/stylelint/stylelint), [prettier](https://github.com/prettier/prettier) | | Cython (pyrex filetype) | [cython](http://cython.org/) | | D | [dmd](https://dlang.org/dmd-linux.html) | -| Dart | [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) !! | +| Dafny | [dafny](https://rise4fun.com/Dafny) !! | +| Dart | [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) !!, [language_server](https://github.com/natebosch/dart_language_server) | | Dockerfile | [hadolint](https://github.com/lukasmartinelli/hadolint) | | Elixir | [credo](https://github.com/rrrene/credo), [dogma](https://github.com/lpil/dogma) !! | | Elm | [elm-format](https://github.com/avh4/elm-format), [elm-make](https://github.com/elm-lang/elm-make) | @@ -125,7 +126,7 @@ formatting. | Pod | [proselint](http://proselint.com/), [write-good](https://github.com/btford/write-good) | | Pug | [pug-lint](https://github.com/pugjs/pug-lint) | | Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) | -| Python | [autopep8](https://github.com/hhatto/autopep8), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pylint](https://www.pylint.org/) !!, [yapf](https://github.com/google/yapf) | +| Python | [autopep8](https://github.com/hhatto/autopep8), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pyls](https://github.com/palantir/python-language-server), [pylint](https://www.pylint.org/) !!, [yapf](https://github.com/google/yapf) | | R | [lintr](https://github.com/jimhester/lintr) | | ReasonML | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-integration-reason-merlin` for configuration instructions, [refmt](https://github.com/reasonml/reason-cli) | | reStructuredText | [proselint](http://proselint.com/), [write-good](https://github.com/btford/write-good) | @@ -392,8 +393,13 @@ let g:ale_set_highlights = 0 ``` You can control all of the highlights ALE uses, say if you are using a different -color scheme which produces ugly highlights. See `:help ale-highlights` for more -information. +color scheme which produces ugly highlights. For example: + +```vim +highlight ALEWarning ctermbg=DarkMagenta +``` + +See `:help ale-highlights` for more information. <a name="faq-statusline"></a> diff --git a/ale_linters/dafny/dafny.vim b/ale_linters/dafny/dafny.vim new file mode 100644 index 00000000..8bbf1b13 --- /dev/null +++ b/ale_linters/dafny/dafny.vim @@ -0,0 +1,25 @@ +" Author: Taylor Blau <me@ttaylorr.com> + +function! ale_linters#dafny#dafny#Handle(buffer, lines) abort + let l:pattern = '\v(.*)\((\d+),(\d+)\): (.*): (.*)' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + call add(l:output, { + \ 'bufnr': a:buffer, + \ 'col': l:match[3] + 0, + \ 'lnum': l:match[2] + 0, + \ 'text': l:match[5], + \ 'type': l:match[4] =~# '^Error' ? 'E' : 'W' + \ }) + endfor + return l:output +endfunction + +call ale#linter#Define('dafny', { +\ 'name': 'dafny', +\ 'executable': 'dafny', +\ 'command': 'dafny %s /compile:0', +\ 'callback': 'ale_linters#dafny#dafny#Handle', +\ 'lint_file': 1, +\ }) diff --git a/ale_linters/dart/language_server.vim b/ale_linters/dart/language_server.vim new file mode 100644 index 00000000..15c77017 --- /dev/null +++ b/ale_linters/dart/language_server.vim @@ -0,0 +1,30 @@ +" Author: aurieh <me@aurieh.me> +" Description: A language server for dart + +call ale#Set('dart_language_server_executable', 'dart_language_server') + +function! ale_linters#dart#language_server#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'dart_language_server_executable') +endfunction + +function! ale_linters#dart#language_server#GetLanguage(buffer) abort + return 'dart' +endfunction + +function! ale_linters#dart#language_server#GetProjectRoot(buffer) abort + " Note: pub only looks for pubspec.yaml, there's no point in adding + " support for pubspec.yml + let l:pubspec = ale#path#FindNearestFile(a:buffer, 'pubspec.yaml') + + return !empty(l:pubspec) ? fnamemodify(l:pubspec, ':h:h') : '' +endfunction + +call ale#linter#Define('dart', { +\ 'name': 'language_server', +\ 'lsp': 'stdio', +\ 'executable_callback': 'ale_linters#dart#language_server#GetExecutable', +\ 'command_callback': 'ale_linters#dart#language_server#GetExecutable', +\ 'language_callback': 'ale_linters#dart#language_server#GetLanguage', +\ 'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot', +\}) + diff --git a/ale_linters/python/pyls.vim b/ale_linters/python/pyls.vim new file mode 100644 index 00000000..1b91c2c7 --- /dev/null +++ b/ale_linters/python/pyls.vim @@ -0,0 +1,21 @@ +" Author: aurieh <me@aurieh.me> +" Description: A language server for Python + +call ale#Set('python_pyls_executable', 'pyls') + +function! ale_linters#python#pyls#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'python_pyls_executable') +endfunction + +function! ale_linters#python#pyls#GetLanguage(buffer) abort + return 'python' +endfunction + +call ale#linter#Define('python', { +\ 'name': 'pyls', +\ 'lsp': 'stdio', +\ 'executable_callback': 'ale_linters#python#pyls#GetExecutable', +\ 'command_callback': 'ale_linters#python#pyls#GetExecutable', +\ 'language_callback': 'ale_linters#python#pyls#GetLanguage', +\ 'project_root_callback': 'ale#python#FindProjectRoot', +\}) diff --git a/ale_linters/typescript/tslint.vim b/ale_linters/typescript/tslint.vim index c3852b89..e366af8f 100644 --- a/ale_linters/typescript/tslint.vim +++ b/ale_linters/typescript/tslint.vim @@ -24,6 +24,10 @@ function! ale_linters#typescript#tslint#Handle(buffer, lines) abort let l:output = [] for l:error in ale#util#FuzzyJSONDecode(a:lines, []) + if get(l:error, 'ruleName', '') is# 'no-implicit-dependencies' + continue + endif + call add(l:output, { \ 'filename': ale#path#GetAbsPath(l:dir, l:error.name), \ 'type': (get(l:error, 'ruleSeverity', '') is# 'WARNING' ? 'W' : 'E'), diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim index a9bb7d48..a57ad195 100644 --- a/autoload/ale/fix.vim +++ b/autoload/ale/fix.vim @@ -108,17 +108,27 @@ function! s:HandleExit(job_id, exit_code) abort let l:job_info.output = readfile(l:job_info.file_to_read) endif + let l:chain_callback = get(l:job_info, 'chain_with', v:null) + " Use the output of the job for changing the file if it isn't empty, " otherwise skip this job and use the input from before. - let l:input = !empty(l:job_info.output) + " + " We'll use the input from before for chained commands. + let l:input = l:chain_callback is v:null && !empty(l:job_info.output) \ ? l:job_info.output \ : l:job_info.input + let l:next_index = l:chain_callback is v:null + \ ? l:job_info.callback_index + 1 + \ : l:job_info.callback_index + call s:RunFixer({ \ 'buffer': l:buffer, \ 'input': l:input, + \ 'output': l:job_info.output, \ 'callback_list': l:job_info.callback_list, - \ 'callback_index': l:job_info.callback_index + 1, + \ 'callback_index': l:next_index, + \ 'chain_callback': l:chain_callback, \}) endfunction @@ -172,6 +182,26 @@ function! s:RunJob(options) abort let l:input = a:options.input let l:output_stream = a:options.output_stream let l:read_temporary_file = a:options.read_temporary_file + let l:chain_with = a:options.chain_with + + if empty(l:command) + " If there's nothing further to chain the command with, stop here. + if l:chain_with is v:null + return 0 + endif + + " If there's another chained callback to run, then run that. + call s:RunFixer({ + \ 'buffer': l:buffer, + \ 'input': l:input, + \ 'callback_index': a:options.callback_index, + \ 'callback_list': a:options.callback_list, + \ 'chain_callback': l:chain_with, + \ 'output': [], + \}) + + return 1 + endif let [l:temporary_file, l:command] = ale#command#FormatCommand(l:buffer, l:command, 1) call s:CreateTemporaryFileForJob(l:buffer, l:temporary_file, l:input) @@ -186,8 +216,9 @@ function! s:RunJob(options) abort \ 'buffer': l:buffer, \ 'input': l:input, \ 'output': [], - \ 'callback_list': a:options.callback_list, + \ 'chain_with': l:chain_with, \ 'callback_index': a:options.callback_index, + \ 'callback_list': a:options.callback_list, \} if l:read_temporary_file @@ -250,13 +281,24 @@ function! s:RunFixer(options) abort let l:buffer = a:options.buffer let l:input = a:options.input let l:index = a:options.callback_index + let l:chain_callback = get(a:options, 'chain_callback', v:null) while len(a:options.callback_list) > l:index - let l:Function = a:options.callback_list[l:index] - - let l:result = ale#util#FunctionArgCount(l:Function) == 1 - \ ? call(l:Function, [l:buffer]) - \ : call(l:Function, [l:buffer, copy(l:input)]) + let l:Function = l:chain_callback isnot v:null + \ ? ale#util#GetFunction(l:chain_callback) + \ : a:options.callback_list[l:index] + + if l:chain_callback isnot v:null + " Chained commands accept (buffer, output, [input]) + let l:result = ale#util#FunctionArgCount(l:Function) == 2 + \ ? call(l:Function, [l:buffer, a:options.output]) + \ : call(l:Function, [l:buffer, a:options.output, copy(l:input)]) + else + " Chained commands accept (buffer, [input]) + let l:result = ale#util#FunctionArgCount(l:Function) == 1 + \ ? call(l:Function, [l:buffer]) + \ : call(l:Function, [l:buffer, copy(l:input)]) + endif if type(l:result) == type(0) && l:result == 0 " When `0` is returned, skip this item. @@ -271,6 +313,7 @@ function! s:RunFixer(options) abort \ 'input': l:input, \ 'output_stream': get(l:result, 'output_stream', 'stdout'), \ 'read_temporary_file': get(l:result, 'read_temporary_file', 0), + \ 'chain_with': get(l:result, 'chain_with', v:null), \ 'callback_list': a:options.callback_list, \ 'callback_index': l:index, \}) @@ -352,11 +395,21 @@ function! ale#fix#Fix(...) abort throw "fixing_flag must be either '' or 'save_file'" endif - let l:callback_list = s:GetCallbacks() + try + let l:callback_list = s:GetCallbacks() + catch /E700/ + let l:function_name = join(split(split(v:exception, ':')[3])) + echom printf( + \ 'There is no fixer named `%s`. Check :ALEFixSuggest', + \ l:function_name, + \) + + return 0 + endtry if empty(l:callback_list) if l:fixing_flag is# '' - echoerr 'No fixers have been defined. Try :ALEFixSuggest' + echom 'No fixers have been defined. Try :ALEFixSuggest' endif return 0 diff --git a/autoload/ale/job.vim b/autoload/ale/job.vim index 0f6b8577..e6a75c88 100644 --- a/autoload/ale/job.vim +++ b/autoload/ale/job.vim @@ -25,6 +25,11 @@ endfunction " Note that jobs and IDs are the same thing on NeoVim. function! ale#job#JoinNeovimOutput(job, last_line, data, mode, callback) abort + if a:mode is# 'raw' + call a:callback(a:job, join(a:data, "\n")) + return '' + endif + let l:lines = a:data[:-2] if len(a:data) > 1 @@ -34,15 +39,9 @@ function! ale#job#JoinNeovimOutput(job, last_line, data, mode, callback) abort let l:new_last_line = a:last_line . a:data[0] endif - if a:mode is# 'raw' - if !empty(l:lines) - call a:callback(a:job, join(l:lines, "\n") . "\n") - endif - else - for l:line in l:lines - call a:callback(a:job, l:line) - endfor - endif + for l:line in l:lines + call a:callback(a:job, l:line) + endfor return l:new_last_line endfunction diff --git a/autoload/ale/python.vim b/autoload/ale/python.vim index 2a15f454..90721ef1 100644 --- a/autoload/ale/python.vim +++ b/autoload/ale/python.vim @@ -18,6 +18,8 @@ function! ale#python#FindProjectRootIni(buffer) abort \|| filereadable(l:path . '/setup.cfg') \|| filereadable(l:path . '/pytest.ini') \|| filereadable(l:path . '/tox.ini') + \|| filereadable(l:path . '/pycodestyle.cfg') + \|| filereadable(l:path . '/flake8.cfg') return l:path endif endfor diff --git a/doc/ale-python.txt b/doc/ale-python.txt index 755094a3..e34b548f 100644 --- a/doc/ale-python.txt +++ b/doc/ale-python.txt @@ -189,6 +189,15 @@ g:ale_python_pylint_use_global *g:ale_python_pylint_use_global* See |ale-integrations-local-executables| +=============================================================================== +pyls *ale-python-pyls* + +g:ale_python_pyls_executable *g:ale_python_pyls_executable* + *b:ale_python_pyls_executable* + Type: |String| + Default: `pyls` + + See |ale-integrations-local-executables| =============================================================================== yapf *ale-python-yapf* diff --git a/doc/ale.txt b/doc/ale.txt index f00e1ac2..2ee2c2d7 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -145,6 +145,7 @@ CONTENTS *ale-contents* mypy................................|ale-python-mypy| pycodestyle.........................|ale-python-pycodestyle| pylint..............................|ale-python-pylint| + pyls................................|ale-python-pyls| yapf................................|ale-python-yapf| r.....................................|ale-r-options| lintr...............................|ale-r-lintr| @@ -270,7 +271,8 @@ Notes: * CSS: `csslint`, `stylelint`, `prettier` * Cython (pyrex filetype): `cython` * D: `dmd` -* Dart: `dartanalyzer`!! +* Dafny: `dafny`!! +* Dart: `dartanalyzer`!!, `language_server` * Dockerfile: `hadolint` * Elixir: `credo`, `dogma`!! * Elm: `elm-format, elm-make` @@ -308,7 +310,7 @@ Notes: * Pod: `proselint`, `write-good` * Pug: `pug-lint` * Puppet: `puppet`, `puppet-lint` -* Python: `autopep8`, `flake8`, `isort`, `mypy`, `pycodestyle`, `pylint`!!, `yapf` +* Python: `autopep8`, `flake8`, `isort`, `mypy`, `pycodestyle`, `pyls`, `pylint`!!, `yapf` * R: `lintr` * ReasonML: `merlin`, `refmt` * reStructuredText: `proselint`, `write-good` @@ -443,6 +445,26 @@ are supported for running the commands. for commands which need to modify some file on disk in order to fix files. + `chain_with` An optional key for defining a callback to call next. + + The callback must accept two or three arguments, + `(buffer, output)` or `(buffer, output, input)` . + Functions receiving a variable number of arguments will + only receive the first two values. The `output` argument + will contain the lines of output from the command run. + The `input` argument is the List of lines for the + buffer, after applying any previous fixers. + + The callback must return the same values returned for + any fixer function. This allows fixer functions to be + chained recursively. + + When the command string returned for a fixer is an empty + string, the next command in the chain will still be run. + This allows commands to be skipped, like version checks + that are cached. An empty List will be passed to the + next callback in the chain for the `output`. + *ale-fix-configuration* Synchronous functions and asynchronous jobs will be run in a sequence for diff --git a/test/handler/test_dafny_handler.vader b/test/handler/test_dafny_handler.vader new file mode 100644 index 00000000..1de9a77f --- /dev/null +++ b/test/handler/test_dafny_handler.vader @@ -0,0 +1,26 @@ +Execute(The Dafny handler should parse output correctly): + runtime ale_linters/dafny/dafny.vim + AssertEqual + \ [ + \ { + \ 'bufnr': 0, + \ 'col': 45, + \ 'lnum': 123, + \ 'text': 'A precondition for this call might not hold.', + \ 'type': 'E' + \ }, + \ { + \ 'bufnr': 0, + \ 'col': 90, + \ 'lnum': 678, + \ 'text': 'This is the precondition that might not hold.', + \ 'type': 'W' + \ } + \ ], + \ ale_linters#dafny#dafny#Handle(0, [ + \ 'File.dfy(123,45): Error BP5002: A precondition for this call might not hold.', + \ 'File.dfy(678,90): Related location: This is the precondition that might not hold.' + \ ]) + +After: + call ale#linter#Reset() diff --git a/test/handler/test_tslint_handler.vader b/test/handler/test_tslint_handler.vader index 2ed3357b..db6294cf 100644 --- a/test/handler/test_tslint_handler.vader +++ b/test/handler/test_tslint_handler.vader @@ -252,3 +252,26 @@ Execute(The tslint handler should report errors when the ignore option is on, bu \ 'position': 1 \ } \ }])]) + +Execute(The tslint handler should not report no-implicit-dependencies errors): + call ale#test#SetFilename('app/test.ts') + + AssertEqual + \ [ + \ ], + \ ale_linters#typescript#tslint#Handle(bufnr(''), [json_encode([{ + \ 'endPosition': { + \ 'character': 0, + \ 'line': 1, + \ 'position': 1 + \ }, + \ 'failure': 'this is ignored', + \ 'name': 'test.ts', + \ 'ruleName': 'no-implicit-dependencies', + \ 'ruleSeverity': 'ERROR', + \ 'startPosition': { + \ 'character': 0, + \ 'line': 1, + \ 'position': 1 + \ } + \ }])]) diff --git a/test/test_ale_fix.vader b/test/test_ale_fix.vader index fac9a25b..ffe3d93b 100644 --- a/test/test_ale_fix.vader +++ b/test/test_ale_fix.vader @@ -62,6 +62,49 @@ Before: return [{'lnum': 1, 'col': 1, 'text': 'xxx'}] endfunction + function! FirstChainCallback(buffer) + return {'command': 'echo echoline', 'chain_with': 'SecondChainCallback'} + endfunction + + function! FirstChainCallbackSkipped(buffer) + return {'command': '', 'chain_with': 'SecondChainCallback'} + endfunction + + function! FirstChainCallbackSecondSkipped(buffer) + return {'command': 'echo skipit', 'chain_with': 'SecondChainCallback'} + endfunction + + function! SecondChainCallback(buffer, output) + let l:previous_line = empty(a:output) + \ ? 'emptydefault' + \ : join(split(a:output[0])) + + if l:previous_line is# 'skipit' + return {'command': '', 'chain_with': 'ThirdChainCallback'} + endif + + return { + \ 'command': 'echo ' . l:previous_line, + \ 'chain_with': 'ThirdChainCallback', + \} + endfunction + + function! ThirdChainCallback(buffer, output, input) + let l:previous_line = empty(a:output) + \ ? 'thirddefault' + \ : join(split(a:output[0])) + + return a:input + [l:previous_line] + endfunction + + function! ChainWhereLastIsSkipped(buffer) + return {'command': 'echo echoline', 'chain_with': 'ChainEndSkipped'} + endfunction + + function! ChainEndSkipped(buffer, output) + return {'command': ''} + endfunction + function! SetUpLinters() call ale#linter#Define('testft', { \ 'name': 'testlinter', @@ -71,6 +114,16 @@ Before: \}) endfunction + function GetLastMessage() + redir => l:output + silent mess + redir END + + let l:lines = split(l:output, "\n") + + return empty(l:lines) ? '' : l:lines[-1] + endfunction + After: Restore unlet! g:ale_run_synchronously @@ -87,7 +140,15 @@ After: delfunction RemoveLastLine delfunction RemoveLastLineOneArg delfunction TestCallback + delfunction FirstChainCallback + delfunction FirstChainCallbackSkipped + delfunction FirstChainCallbackSecondSkipped + delfunction SecondChainCallback + delfunction ThirdChainCallback + delfunction ChainWhereLastIsSkipped + delfunction ChainEndSkipped delfunction SetUpLinters + delfunction GetLastMessage call ale#test#RestoreDirectory() @@ -104,14 +165,17 @@ After: let g:ale_fix_buffer_data = {} + " Clear the messages between tests. + echomsg '' + Given testft (A file with three lines): a b c Execute(ALEFix should complain when there are no functions to call): - AssertThrows ALEFix - AssertEqual 'Vim(echoerr):No fixers have been defined. Try :ALEFixSuggest', g:vader_exception + ALEFix + AssertEqual 'No fixers have been defined. Try :ALEFixSuggest', GetLastMessage() Execute(ALEFix should apply simple functions): let g:ale_fixers.testft = ['AddCarets'] @@ -450,3 +514,48 @@ Expect(An extra line should be added): b c d + +Execute(ALE should print a message telling you something isn't a valid fixer when you type some nonsense): + let g:ale_fixers.testft = ['CatLine', 'invalidname'] + ALEFix + + AssertEqual 'There is no fixer named `invalidname`. Check :ALEFixSuggest', GetLastMessage() + +Execute(Test fixing with chained callbacks): + let g:ale_fixers.testft = ['FirstChainCallback'] + ALEFix + +Expect(The echoed line should be added): + a + b + c + echoline + +Execute(Test fixing with chained callback where the first command is skipped): + let g:ale_fixers.testft = ['FirstChainCallbackSkipped'] + ALEFix + +Expect(The default line should be added): + a + b + c + emptydefault + +Execute(Test fixing with chained callback where the second command is skipped): + let g:ale_fixers.testft = ['FirstChainCallbackSecondSkipped'] + ALEFix + +Expect(The default line should be added): + a + b + c + thirddefault + +Execute(Test fixing with chained callback where the final callback is skipped): + let g:ale_fixers.testft = ['ChainWhereLastIsSkipped'] + ALEFix + +Expect(The lines should be the same): + a + b + c diff --git a/test/test_line_join.vader b/test/test_line_join.vader index 04264296..c93b192f 100644 --- a/test/test_line_join.vader +++ b/test/test_line_join.vader @@ -62,8 +62,8 @@ Execute (ALE should pass on full lines for NeoVim for raw data): Execute (ALE should pass on a single long line): let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x'], 'raw', function('RawCallback')) - AssertEqual '', g:data - AssertEqual 'x', g:last_line + AssertEqual 'x', g:data + AssertEqual '', g:last_line Execute (ALE should handle just a single line of output): let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', ''], 'raw', function('RawCallback')) @@ -71,20 +71,8 @@ Execute (ALE should handle just a single line of output): AssertEqual "x\n", g:data AssertEqual '', g:last_line -Execute (ALE should join two incomplete pieces of large lines together): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y'], 'raw', function('RawCallback')) - - AssertEqual '', g:data - AssertEqual 'xy', g:last_line - -Execute (ALE join incomplete lines, and set new ones): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y', 'z', 'a'], 'raw', function('RawCallback')) +Execute (ALE should pass on two lines and one incomplete one): + let g:last_line = ale#job#JoinNeovimOutput(1, '', ['y', 'z', 'a'], 'raw', function('RawCallback')) - AssertEqual "xy\nz\n", g:data - AssertEqual 'a', g:last_line - -Execute (ALE join incomplete lines, and set new ones, with two elements): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y', 'z'], 'raw', function('RawCallback')) - - AssertEqual "xy\n", g:data - AssertEqual 'z', g:last_line + AssertEqual "y\nz\na", g:data + AssertEqual '', g:last_line |