Fix 2726 - fix terraform linter.

Instead of using `terraform fmt` for linting use `terraform validate`
with json output.
This commit is contained in:
Horacio Sanson 2021-01-30 17:11:12 +09:00
parent 7c44f4e403
commit d511d5af11
3 changed files with 76 additions and 33 deletions

View file

@ -9,30 +9,40 @@ endfunction
function! ale_linters#terraform#terraform#GetCommand(buffer) abort function! ale_linters#terraform#terraform#GetCommand(buffer) abort
return ale#Escape(ale_linters#terraform#terraform#GetExecutable(a:buffer)) return ale#Escape(ale_linters#terraform#terraform#GetExecutable(a:buffer))
\ . ' fmt -no-color --check=true -' \ . ' validate -no-color -json '
endfunction
function! ale_linters#terraform#terraform#GetType(severity) abort
if a:severity is? 'warning'
return 'W'
endif
return 'E'
endfunction endfunction
function! ale_linters#terraform#terraform#Handle(buffer, lines) abort function! ale_linters#terraform#terraform#Handle(buffer, lines) abort
let l:head = '^Error running fmt: In <standard input>: '
let l:output = [] let l:output = []
let l:patterns = [
\ l:head.'At \(\d\+\):\(\d\+\): \(.*\)$',
\ l:head.'\(.*\)$'
\]
for l:match in ale#util#GetMatches(a:lines, l:patterns) let l:errors = ale#util#FuzzyJSONDecode(a:lines, {'diagnostics': []})
if len(l:match[2]) > 0 let l:dir = expand('#' . a:buffer . ':p:h')
let l:file = expand('#' . a:buffer . ':p')
for l:error in l:errors['diagnostics']
if has_key(l:error, 'range')
call add(l:output, { call add(l:output, {
\ 'lnum': str2nr(l:match[1]), \ 'filename': ale#path#GetAbsPath(l:dir, l:error['range']['filename']),
\ 'col': str2nr(l:match[2]), \ 'lnum': l:error['range']['start']['line'],
\ 'text': l:match[3], \ 'col': l:error['range']['start']['column'],
\ 'type': 'E', \ 'text': l:error['detail'],
\ 'type': ale_linters#terraform#terraform#GetType(l:error['severity']),
\}) \})
else else
call add(l:output, { call add(l:output, {
\ 'lnum': line('$'), \ 'filename': l:file,
\ 'text': l:match[1], \ 'lnum': 0,
\ 'type': 'E', \ 'col': 0,
\ 'text': l:error['detail'],
\ 'type': ale_linters#terraform#terraform#GetType(l:error['severity']),
\}) \})
endif endif
endfor endfor
@ -42,7 +52,7 @@ endfunction
call ale#linter#Define('terraform', { call ale#linter#Define('terraform', {
\ 'name': 'terraform', \ 'name': 'terraform',
\ 'output_stream': 'stderr', \ 'output_stream': 'stdout',
\ 'executable': function('ale_linters#terraform#terraform#GetExecutable'), \ 'executable': function('ale_linters#terraform#terraform#GetExecutable'),
\ 'command': function('ale_linters#terraform#terraform#GetCommand'), \ 'command': function('ale_linters#terraform#terraform#GetCommand'),
\ 'callback': 'ale_linters#terraform#terraform#Handle', \ 'callback': 'ale_linters#terraform#terraform#Handle',

View file

@ -6,4 +6,10 @@ After:
call ale#assert#TearDownLinterTest() call ale#assert#TearDownLinterTest()
Execute(The default command should be correct): Execute(The default command should be correct):
AssertLinter 'terraform', ale#Escape('terraform') . ' fmt -no-color --check=true -' AssertLinter 'terraform',
\ ale#Escape('terraform') . ' validate -no-color -json '
Execute(The default command should be overriden):
let b:ale_terraform_terraform_executable = '/bin/other/terraform'
AssertLinter '/bin/other/terraform',
\ ale#Escape('/bin/other/terraform') . ' validate -no-color -json '

View file

@ -1,34 +1,61 @@
Before: Before:
" Load the file which defines the linter. " Load the file which defines the linter.
runtime ale_linters/terraform/terraform.vim runtime ale_linters/terraform/terraform.vim
call ale#test#SetDirectory('/testplugin/test/terraform_files')
call ale#test#SetFilename('providers.tf')
After: After:
" Unload all linters again. " Unload all linters again.
call ale#linter#Reset() call ale#linter#Reset()
call ale#test#RestoreDirectory()
Execute(The output should be correct): Execute(The output should be correct):
AssertEqual AssertEqual
\ [ \ [
\ { \ {
\ 'lnum': 1, \ 'lnum': 17,
\ 'col': 20, \ 'col': 13,
\ 'type': 'E', \ 'filename': '/testplugin/test/terraform_files/providers.tf',
\ 'text': 'illegal char', \ 'type': 'W',
\ 'text': 'Terraform 0.13 and earlier allowed provider version',
\ }, \ },
\ { \ {
\ 'lnum': 2, \ 'lnum': 0,
\ 'col': 14, \ 'col': 0,
\ 'filename': '/testplugin/test/terraform_files/providers.tf',
\ 'type': 'E', \ 'type': 'E',
\ 'text': 'literal not terminated', \ 'text': 'Plugin reinitialization required. Please run "terraform"',
\ }, \ }
\ {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': 'object expected closing RBRACE got: EOF',
\ },
\ ], \ ],
\ ale_linters#terraform#terraform#Handle(bufnr(''), [ \ ale_linters#terraform#terraform#Handle(bufnr(''), [
\ 'Error running fmt: In <standard input>: At 1:20: illegal char', \ '{',
\ 'Error running fmt: In <standard input>: At 2:14: literal not terminated', \ '"valid": false,',
\ 'Error running fmt: In <standard input>: object expected closing RBRACE got: EOF', \ '"error_count": 1,',
\ '"warning_count": 1,',
\ '"diagnostics": [',
\ ' {',
\ ' "severity": "warning",',
\ ' "summary": "Version constraints inside provider configuration blocks are deprecated",',
\ ' "detail": "Terraform 0.13 and earlier allowed provider version",',
\ ' "range": {',
\ ' "filename": "providers.tf",',
\ ' "start": {',
\ ' "line": 17,',
\ ' "column": 13,',
\ ' "byte": 669',
\ ' },',
\ ' "end": {',
\ ' "line": 17,',
\ ' "column": 24,',
\ ' "byte": 680',
\ ' }',
\ ' }',
\ ' },',
\ ' {',
\ ' "severity": "error",',
\ ' "summary": "Could not load plugin",',
\ ' "detail": "Plugin reinitialization required. Please run \"terraform\""',
\ ' }',
\ ' ]',
\ '}',
\ ]) \ ])