From b071f1a79587522ea6782c27d7caab8ff88c1bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 15 May 2018 17:06:52 +0200 Subject: [PATCH] Make Elm linter backwards compatible with Elm 0.18 --- ale_linters/elm/make.vim | 156 +++++++++++++++--------- test/handler/test_elmmake_handler.vader | 140 ++++++++++++++++++++- 2 files changed, 234 insertions(+), 62 deletions(-) diff --git a/ale_linters/elm/make.vim b/ale_linters/elm/make.vim index 5f9334d..05907ac 100644 --- a/ale_linters/elm/make.vim +++ b/ale_linters/elm/make.vim @@ -16,62 +16,12 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort for l:line in a:lines if l:line[0] is# '{' - let l:report = json_decode(l:line) - - if l:report.type is? 'error' - " General problem - let l:details = ale_linters#elm#make#ParseMessage(l:report.message) - - if empty(l:report.path) - let l:report.path = 'Elm.Kernel' - endif - - if ale_linters#elm#make#FileIsBuffer(l:report.path) - call add(l:output, { - \ 'lnum': 1, - \ 'type': 'E', - \ 'text': l:details, - \}) - else - call add(l:output, { - \ 'lnum': 1, - \ 'type': 'E', - \ 'text': l:report.path .' - '. l:details, - \ 'detail': l:report.path ." ----------\n\n". l:details, - \}) - endif - else - " Compilation errors - for l:error in l:report.errors - let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.path) - - for l:problem in l:error.problems - let l:details = ale_linters#elm#make#ParseMessage(l:problem.message) - - if l:file_is_buffer - " Buffer module has problems - call add(l:output, { - \ 'lnum': l:problem.region.start.line, - \ 'col': l:problem.region.start.column, - \ 'end_lnum': l:problem.region.end.line, - \ 'end_col': l:problem.region.end.column, - \ 'type': 'E', - \ 'text': l:details, - \}) - else - " Imported module has problems - let l:location = l:error.path .':'. l:problem.region.start.line - call add(l:output, { - \ 'lnum': 1, - \ 'type': 'E', - \ 'text': l:location .' - '. l:details, - \ 'detail': l:location ." ----------\n\n". l:details, - \}) - endif - endfor - endfor - endif - else + " Elm 0.19 + call ale_linters#elm#make#HandleElm019Line(l:line, l:output) + elseif l:line[0] is# '[' + " Elm 0.18 + call ale_linters#elm#make#HandleElm018Line(l:line, l:output) + elseif l:line isnot# 'Successfully generated /dev/null' call add(l:unparsed_lines, l:line) endif endfor @@ -88,6 +38,95 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort return l:output endfunction +function! ale_linters#elm#make#HandleElm019Line(line, output) abort + let l:report = json_decode(a:line) + + if l:report.type is? 'error' + " General problem + let l:details = ale_linters#elm#make#ParseMessage(l:report.message) + + if empty(l:report.path) + let l:report.path = 'Elm' + endif + + if ale_linters#elm#make#FileIsBuffer(l:report.path) + call add(a:output, { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': l:details, + \}) + else + call add(a:output, { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': l:report.path .' - '. l:details, + \ 'detail': l:report.path ." ----------\n\n". l:details, + \}) + endif + else + " Compilation errors + for l:error in l:report.errors + let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.path) + + for l:problem in l:error.problems + let l:details = ale_linters#elm#make#ParseMessage(l:problem.message) + + if l:file_is_buffer + " Buffer module has problems + call add(a:output, { + \ 'lnum': l:problem.region.start.line, + \ 'col': l:problem.region.start.column, + \ 'end_lnum': l:problem.region.end.line, + \ 'end_col': l:problem.region.end.column, + \ 'type': 'E', + \ 'text': l:details, + \}) + else + " Imported module has problems + let l:location = l:error.path .':'. l:problem.region.start.line + call add(a:output, { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': l:location .' - '. l:details, + \ 'detail': l:location ." ----------\n\n". l:details, + \}) + endif + endfor + endfor + endif +endfunction + +function! ale_linters#elm#make#HandleElm018Line(line, output) abort + let l:errors = json_decode(a:line) + + for l:error in l:errors + let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.file) + + if l:file_is_buffer + " Current buffer has problems + call add(a:output, { + \ 'lnum': l:error.region.start.line, + \ 'col': l:error.region.start.column, + \ 'end_lnum': l:error.region.end.line, + \ 'end_col': l:error.region.end.column, + \ 'type': (l:error.type is? 'error') ? 'E' : 'W', + \ 'text': l:error.overview, + \ 'detail': l:error.overview . "\n\n" . l:error.details + \}) + elseif l:error.type is? 'error' + " Imported module has errors + let l:location = l:error.file .':'. l:error.region.start.line + + call add(a:output, { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': l:location .' - '. l:error.overview, + \ 'detail': l:location ." ----------\n\n". l:error.overview . "\n\n" . l:error.details + \}) + endif + endfor +endfunction + function! ale_linters#elm#make#FileIsBuffer(path) abort let l:is_windows = has('win32') let l:temp_dir = l:is_windows ? $TMP : $TMPDIR @@ -117,6 +156,11 @@ function! ale_linters#elm#make#GetCommand(buffer) abort let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json') let l:elm_exe = ale_linters#elm#make#GetExecutable(a:buffer) + if empty(l:elm_json) + " Fallback to Elm 0.18 + let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm-package.json') + endif + if empty(l:elm_json) let l:dir_set_cmd = '' else diff --git a/test/handler/test_elmmake_handler.vader b/test/handler/test_elmmake_handler.vader index 8abe329..41c9646 100644 --- a/test/handler/test_elmmake_handler.vader +++ b/test/handler/test_elmmake_handler.vader @@ -9,7 +9,10 @@ After: call ale#linter#Reset() -Execute(The elm make handler should parse general problems correctly): + +" Elm 0.19 + +Execute(The elm-make handler should parse Elm 0.19 general problems correctly): AssertEqual \ [ \ { @@ -27,7 +30,7 @@ Execute(The elm make handler should parse general problems correctly): \ }' \ ]) -Execute(The elm make handler should parse compilation errors correctly): +Execute(The elm-make handler should parse Elm 0.19 compilation errors correctly): AssertEqual \ [ \ { @@ -83,7 +86,7 @@ Execute(The elm make handler should parse compilation errors correctly): \ }' \ ]) -Execute(The elm make handler should handle errors in imported modules): +Execute(The elm-make handler should handle errors in Elm 0.19 imported modules): AssertEqual \ [ \ { @@ -95,8 +98,8 @@ Execute(The elm make handler should handle errors in imported modules): \ { \ 'lnum': 1, \ 'type': 'E', - \ 'text': "Elm.Kernel - error details\n\nstyled details", - \ 'detail': "Elm.Kernel ----------\n\nerror details\n\nstyled details" + \ 'text': "Elm - error details\n\nstyled details", + \ 'detail': "Elm ----------\n\nerror details\n\nstyled details" \ }, \ { \ 'lnum': 1, @@ -135,7 +138,125 @@ Execute(The elm make handler should handle errors in imported modules): \ }' \ ]) -Execute(The elm make handler should put an error on the first line if a line cannot be parsed): + +" Elm 0.18 + +Execute(The elm-make handler should parse Elm 0.18 compilation errors correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 33, + \ 'col': 1, + \ 'end_lnum': 33, + \ 'end_col': 19, + \ 'type': 'W', + \ 'text': 'warning overview', + \ 'detail': "warning overview\n\nwarning details", + \ }, + \ { + \ 'lnum': 404, + \ 'col': 1, + \ 'end_lnum': 408, + \ 'end_col': 18, + \ 'type': 'E', + \ 'text': 'error overview 1', + \ 'detail': "error overview 1\n\nerror details 1", + \ }, + \ { + \ 'lnum': 406, + \ 'col': 5, + \ 'end_lnum': 407, + \ 'end_col': 17, + \ 'type': 'E', + \ 'text': 'error overview 2', + \ 'detail': "error overview 2\n\nerror details 2", + \ }, + \ { + \ 'lnum': 406, + \ 'col': 5, + \ 'end_lnum': 406, + \ 'end_col': 93, + \ 'type': 'E', + \ 'text': 'error overview 3', + \ 'detail': "error overview 3\n\nerror details 3", + \ }, + \ ], + \ ale_linters#elm#make#Handle(347, [ + \ '[ + \ { + \ "tag": "unused import", + \ "overview": "warning overview", + \ "details": "warning details", + \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } }, + \ "type": "warning", + \ "file": "' . b:tmp . '/Module.elm" + \ } + \ ]', + \ '[ + \ { + \ "tag": "TYPE MISMATCH", + \ "overview": "error overview 1", + \ "subregion": { "start": { "line": 406, "column": 5 }, "end": { "line": 408, "column": 18 } }, + \ "details": "error details 1", + \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } }, + \ "type": "error", + \ "file":"' . b:tmp . '/Module.elm" + \ }, + \ { + \ "tag": "TYPE MISMATCH", + \ "overview": "error overview 2", + \ "subregion": { "start": { "line": 407, "column": 12 }, "end": { "line": 407, "column": 17 } }, + \ "details": "error details 2", + \ "region": { "start": { "line": 406, "column": 5}, "end": { "line": 407, "column": 17 } }, + \ "type":"error", + \ "file":"' . b:tmp . '/Module.elm" + \ }, + \ { + \ "tag": "TYPE MISMATCH", + \ "overview": "error overview 3", + \ "subregion": { "start": { "line": 406, "column": 88 }, "end": { "line": 406, "column": 93 } }, + \ "details": "error details 3", + \ "region": { "start": { "line": 406, "column": 5 }, "end": { "line": 406, "column": 93 } }, + \ "type":"error", + \ "file":"' . b:tmp . '/Module.elm" + \ } + \ ]' + \ ]) + +Execute(The elm-make handler should handle errors in Elm 0.18 imported modules): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'type': 'E', + \ 'text': "src/Module.elm:33 - error overview", + \ 'detail': "src/Module.elm:33 ----------\n\nerror overview\n\nerror details" + \ } + \ ], + \ ale_linters#elm#make#Handle(347, [ + \ '[ + \ { + \ "tag": "unused import", + \ "overview": "warning overview", + \ "details": "warning details", + \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } }, + \ "type": "warning", + \ "file": "src/Module.elm" + \ }, + \ { + \ "tag": "type error", + \ "overview": "error overview", + \ "details": "error details", + \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } }, + \ "type": "error", + \ "file": "src/Module.elm" + \ } + \ ]', + \ ]) + +" Generic + +Execute(The elm-make handler should put an error on the first line if a line cannot be parsed): AssertEqual \ [ \ { @@ -172,3 +293,10 @@ Execute(The elm make handler should put an error on the first line if a line can \ 'Not JSON', \ 'Also not JSON', \ ]) + +Execute(The elm-make handler should ignore success lines): + AssertEqual + \ [], + \ ale_linters#elm#make#Handle(347, [ + \ 'Successfully generated /dev/null', + \ ])