diff --git a/ale_linters/crystal/crystal.vim b/ale_linters/crystal/crystal.vim index fd076e02..81579d63 100644 --- a/ale_linters/crystal/crystal.vim +++ b/ale_linters/crystal/crystal.vim @@ -4,31 +4,21 @@ function! ale_linters#crystal#crystal#Handle(buffer, lines) abort let l:output = [] - let l:lines = join(a:lines, '') - - if !empty(l:lines) - let l:errors = json_decode(l:lines) - - for l:error in l:errors - call add(l:output, { - \ 'bufnr': a:buffer, - \ 'lnum': l:error.line + 0, - \ 'col': l:error.column + 0, - \ 'text': l:error.message, - \ 'type': 'E', - \}) - endfor - endif + for l:error in ale#util#FuzzyJSONDecode(a:lines, []) + call add(l:output, { + \ 'lnum': l:error.line + 0, + \ 'col': l:error.column + 0, + \ 'text': l:error.message, + \}) + endfor return l:output endfunction function! ale_linters#crystal#crystal#GetCommand(buffer) abort - let l:crystal_cmd = 'crystal build -f json --no-codegen --no-color -o ' - let l:crystal_cmd .= ale#Escape(g:ale#util#nul_file) - let l:crystal_cmd .= ' %s' - - return l:crystal_cmd + return 'crystal build -f json --no-codegen --no-color -o ' + \ . ale#Escape(g:ale#util#nul_file) + \ . ' %s' endfunction call ale#linter#Define('crystal', { diff --git a/ale_linters/handlebars/embertemplatelint.vim b/ale_linters/handlebars/embertemplatelint.vim index e7fa149c..963ab568 100644 --- a/ale_linters/handlebars/embertemplatelint.vim +++ b/ale_linters/handlebars/embertemplatelint.vim @@ -16,16 +16,10 @@ function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer) abort endfunction function! ale_linters#handlebars#embertemplatelint#Handle(buffer, lines) abort - if len(a:lines) == 0 - return [] - endif - let l:output = [] + let l:json = ale#util#FuzzyJSONDecode(a:lines, {}) - let l:input_json = json_decode(join(a:lines, '')) - let l:file_errors = values(l:input_json)[0] - - for l:error in l:file_errors + for l:error in get(values(l:json), 0, []) if has_key(l:error, 'fatal') call add(l:output, { \ 'bufnr': a:buffer, diff --git a/ale_linters/haskell/hlint.vim b/ale_linters/haskell/hlint.vim index accae374..91e65123 100644 --- a/ale_linters/haskell/hlint.vim +++ b/ale_linters/haskell/hlint.vim @@ -2,15 +2,9 @@ " Description: hlint for Haskell files function! ale_linters#haskell#hlint#Handle(buffer, lines) abort - if empty(a:lines) - return [] - endif - - let l:errors = json_decode(join(a:lines, '')) - let l:output = [] - for l:error in l:errors + for l:error in ale#util#FuzzyJSONDecode(a:lines, []) if l:error.severity ==# 'Error' let l:type = 'E' elseif l:error.severity ==# 'Suggestion' diff --git a/ale_linters/ruby/brakeman.vim b/ale_linters/ruby/brakeman.vim index 565c8c70..0070c15c 100644 --- a/ale_linters/ruby/brakeman.vim +++ b/ale_linters/ruby/brakeman.vim @@ -5,20 +5,10 @@ let g:ale_ruby_brakeman_options = \ get(g:, 'ale_ruby_brakeman_options', '') function! ale_linters#ruby#brakeman#Handle(buffer, lines) abort - if len(a:lines) == 0 - return [] - endif - - try - let l:result = json_decode(join(a:lines, '')) - catch /E474/ - " Ignore invalid JSON - return [] - endtry - let l:output = [] + let l:json = ale#util#FuzzyJSONDecode(a:lines, {}) - for l:warning in l:result.warnings + for l:warning in get(l:json, 'warnings', []) " Brakeman always outputs paths relative to the Rails app root let l:rails_root = ale#ruby#FindRailsRoot(a:buffer) let l:warning_file = l:rails_root . '/' . l:warning.file diff --git a/ale_linters/ruby/rails_best_practices.vim b/ale_linters/ruby/rails_best_practices.vim index a3d9f7a2..503a115c 100644 --- a/ale_linters/ruby/rails_best_practices.vim +++ b/ale_linters/ruby/rails_best_practices.vim @@ -5,17 +5,11 @@ let g:ale_ruby_rails_best_practices_options = \ get(g:, 'ale_ruby_rails_best_practices_options', '') function! ale_linters#ruby#rails_best_practices#Handle(buffer, lines) abort - if len(a:lines) == 0 - return [] - endif - - let l:result = json_decode(join(a:lines, '')) - let l:output = [] - for l:warning in l:result + for l:warning in ale#util#FuzzyJSONDecode(a:lines, []) if !ale#path#IsBufferPath(a:buffer, l:warning.filename) - continue + continue endif call add(l:output, { diff --git a/ale_linters/ruby/reek.vim b/ale_linters/ruby/reek.vim index 5f476fb1..10bc9a84 100644 --- a/ale_linters/ruby/reek.vim +++ b/ale_linters/ruby/reek.vim @@ -1,22 +1,13 @@ " Author: Eddie Lebow https://github.com/elebow " Description: Reek, a code smell detector for Ruby files -let g:ale_ruby_reek_show_context = -\ get(g:, 'ale_ruby_reek_show_context', 0) - -let g:ale_ruby_reek_show_wiki_link = -\ get(g:, 'ale_ruby_reek_show_wiki_link', 0) +call ale#Set('ruby_reek_show_context', 0) +call ale#Set('ruby_reek_show_wiki_link', 0) function! ale_linters#ruby#reek#Handle(buffer, lines) abort - if len(a:lines) == 0 - return [] - endif - - let l:errors = json_decode(a:lines[0]) - let l:output = [] - for l:error in l:errors + for l:error in ale#util#FuzzyJSONDecode(a:lines, []) for l:location in l:error.lines call add(l:output, { \ 'lnum': l:location, diff --git a/ale_linters/typescript/tslint.vim b/ale_linters/typescript/tslint.vim index e9b31644..7cd1cb4b 100644 --- a/ale_linters/typescript/tslint.vim +++ b/ale_linters/typescript/tslint.vim @@ -14,11 +14,7 @@ endfunction function! ale_linters#typescript#tslint#Handle(buffer, lines) abort let l:output = [] - if empty(a:lines) - return [] - endif - - for l:error in json_decode(join(a:lines, '')) + for l:error in ale#util#FuzzyJSONDecode(a:lines, []) if ale#path#IsBufferPath(a:buffer, l:error.name) call add(l:output, { \ 'type': (get(l:error, 'ruleSeverity', '') ==# 'WARNING' ? 'W' : 'E'), diff --git a/test/handler/test_crystal_handler.vader b/test/handler/test_crystal_handler.vader index bdc44644..984b976f 100644 --- a/test/handler/test_crystal_handler.vader +++ b/test/handler/test_crystal_handler.vader @@ -4,9 +4,7 @@ Execute(The crystal handler should parse lines correctly and add the column if i \ [ \ { \ 'lnum': 2, - \ 'bufnr': 255, \ 'col': 1, - \ 'type': 'E', \ 'text': 'unexpected token: EOF' \ } \ ], diff --git a/test/handler/test_embertemplatelint_handler.vader b/test/handler/test_embertemplatelint_handler.vader index cc3e8bb9..8e132d36 100644 --- a/test/handler/test_embertemplatelint_handler.vader +++ b/test/handler/test_embertemplatelint_handler.vader @@ -75,9 +75,11 @@ Execute(The ember-template-lint handler should handle template parsing error cor Execute(The ember-template-lint handler should handle no lint errors/warnings): AssertEqual - \ [ - \ ], + \ [], \ ale_linters#handlebars#embertemplatelint#Handle(347, []) + AssertEqual + \ [], + \ ale_linters#handlebars#embertemplatelint#Handle(347, ['{}']) After: call ale#linter#Reset() diff --git a/test/handler/test_rails_best_practices_handler.vader b/test/handler/test_rails_best_practices_handler.vader index 037d2527..11875cbd 100644 --- a/test/handler/test_rails_best_practices_handler.vader +++ b/test/handler/test_rails_best_practices_handler.vader @@ -1,20 +1,15 @@ Before: - " Switch to the test rails directory. - let b:path = getcwd() - silent! cd /testplugin/test/handler - cd ../ruby_fixtures/valid_rails_app/app/models + call ale#test#SetDirectory('/testplugin/test/handler') + cd .. - runtime ale_linters/ruby/rails_best_practices.vim + runtime ale_linters/ruby/rails_best_practices.vim After: - " Switch back to whatever directory it was that we started on. - silent! 'cd ' . fnameescape(b:path) - unlet! b:path - - call ale#linter#Reset() + call ale#test#RestoreDirectory() + call ale#linter#Reset() Execute(The rails_best_practices handler should parse JSON correctly): - silent file! thing.rb + call ale#test#SetFilename('ruby_fixtures/valid_rails_app/app/models/thing.rb') AssertEqual \ [ @@ -34,11 +29,11 @@ Execute(The rails_best_practices handler should parse JSON correctly): \ '{', \ '"message": "use local variable",', \ '"line_number": "5",', - \ '"filename": "/testplugin/test/ruby_fixtures/valid_rails_app/app/models/thing.rb"', + \ '"filename": "' . g:dir . '/ruby_fixtures/valid_rails_app/app/models/thing.rb"', \ '},{', \ '"message": "other advice",', \ '"line_number": "10",', - \ '"filename": "/testplugin/test/ruby_fixtures/valid_rails_app/app/models/thing.rb"', + \ '"filename": "' . g:dir . '/ruby_fixtures/valid_rails_app/app/models/thing.rb"', \ '}', \ ']' \ ]) @@ -48,3 +43,10 @@ Execute(The rails_best_practices handler should parse JSON correctly when there \ [], \ ale_linters#ruby#rails_best_practices#Handle(347, [ \ ]) + +Execute(The rails_best_practices handler should handle garbage output): + AssertEqual + \ [], + \ ale_linters#ruby#rails_best_practices#Handle(347, [ + \ 'No such command in 2.4.1 of ruby', + \ ]) diff --git a/test/handler/test_reek_handler.vader b/test/handler/test_reek_handler.vader index 67ba6f60..6861428c 100644 --- a/test/handler/test_reek_handler.vader +++ b/test/handler/test_reek_handler.vader @@ -2,68 +2,75 @@ Before: runtime ale_linters/ruby/reek.vim After: - call ale#linter#Reset() + call ale#linter#Reset() Execute(The reek handler should parse JSON correctly, with only context enabled): - let g:ale_ruby_reek_show_context = 1 - let g:ale_ruby_reek_show_wiki_link = 0 + let g:ale_ruby_reek_show_context = 1 + let g:ale_ruby_reek_show_wiki_link = 0 - AssertEqual - \ [ - \ { - \ 'lnum': 12, - \ 'text': 'Rule1: Context#method violates rule number one', - \ 'type': 'W', - \ }, - \ { - \ 'lnum': 34, - \ 'text': 'Rule2: Context#method violates rule number two', - \ 'type': 'W', - \ }, - \ { - \ 'lnum': 56, - \ 'text': 'Rule2: Context#method violates rule number two', - \ 'type': 'W', - \ }, - \ ], - \ ale_linters#ruby#reek#Handle(347, [ - \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"},{"context":"Context#method","lines":[34, 56],"message":"violates rule number two","smell_type":"Rule2","source":"/home/user/file.rb","name":"bad code","count":2,"wiki_link":"https://example.com/Rule1.md"}]' - \ ]) + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'text': 'Rule1: Context#method violates rule number one', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 34, + \ 'text': 'Rule2: Context#method violates rule number two', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 56, + \ 'text': 'Rule2: Context#method violates rule number two', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#ruby#reek#Handle(347, [ + \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"},{"context":"Context#method","lines":[34, 56],"message":"violates rule number two","smell_type":"Rule2","source":"/home/user/file.rb","name":"bad code","count":2,"wiki_link":"https://example.com/Rule1.md"}]' + \ ]) Execute(The reek handler should parse JSON correctly, with no context or wiki links): - let g:ale_ruby_reek_show_context = 0 - let g:ale_ruby_reek_show_wiki_link = 0 + let g:ale_ruby_reek_show_context = 0 + let g:ale_ruby_reek_show_wiki_link = 0 - AssertEqual - \ [ - \ { - \ 'lnum': 12, - \ 'text': 'Rule1: violates rule number one', - \ 'type': 'W', - \ }, - \ ], - \ ale_linters#ruby#reek#Handle(347, [ - \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]' - \ ]) + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'text': 'Rule1: violates rule number one', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#ruby#reek#Handle(347, [ + \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]' + \ ]) Execute(The reek handler should parse JSON correctly, with both context and wiki links): - let g:ale_ruby_reek_show_context = 1 - let g:ale_ruby_reek_show_wiki_link = 1 + let g:ale_ruby_reek_show_context = 1 + let g:ale_ruby_reek_show_wiki_link = 1 - AssertEqual - \ [ - \ { - \ 'lnum': 12, - \ 'text': 'Rule1: Context#method violates rule number one [https://example.com/Rule1.md]', - \ 'type': 'W', - \ }, - \ ], - \ ale_linters#ruby#reek#Handle(347, [ - \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]' - \ ]) + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'text': 'Rule1: Context#method violates rule number one [https://example.com/Rule1.md]', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#ruby#reek#Handle(347, [ + \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]' + \ ]) Execute(The reek handler should parse JSON correctly when there is no output from reek): - AssertEqual - \ [], - \ ale_linters#ruby#reek#Handle(347, [ - \ ]) + AssertEqual + \ [], + \ ale_linters#ruby#reek#Handle(347, [ + \ ]) + +Execute(The reek handler should handle garbage output): + AssertEqual + \ [], + \ ale_linters#ruby#reek#Handle(347, [ + \ 'No such command in 2.4.1 of ruby', + \ ])