From d511d5af11041ffe7802a6027c76483506c232ad Mon Sep 17 00:00:00 2001 From: Horacio Sanson Date: Sat, 30 Jan 2021 17:11:12 +0900 Subject: [PATCH] Fix 2726 - fix terraform linter. Instead of using `terraform fmt` for linting use `terraform validate` with json output. --- ale_linters/terraform/terraform.vim | 42 ++++++++----- ...terraform_terraform_command_callback.vader | 8 ++- test/handler/test_terraform_handler.vader | 59 ++++++++++++++----- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/ale_linters/terraform/terraform.vim b/ale_linters/terraform/terraform.vim index 0429cb7a..623fc2fd 100644 --- a/ale_linters/terraform/terraform.vim +++ b/ale_linters/terraform/terraform.vim @@ -9,30 +9,40 @@ endfunction function! ale_linters#terraform#terraform#GetCommand(buffer) abort 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 function! ale_linters#terraform#terraform#Handle(buffer, lines) abort - let l:head = '^Error running fmt: In : ' let l:output = [] - let l:patterns = [ - \ l:head.'At \(\d\+\):\(\d\+\): \(.*\)$', - \ l:head.'\(.*\)$' - \] - for l:match in ale#util#GetMatches(a:lines, l:patterns) - if len(l:match[2]) > 0 + let l:errors = ale#util#FuzzyJSONDecode(a:lines, {'diagnostics': []}) + 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, { - \ 'lnum': str2nr(l:match[1]), - \ 'col': str2nr(l:match[2]), - \ 'text': l:match[3], - \ 'type': 'E', + \ 'filename': ale#path#GetAbsPath(l:dir, l:error['range']['filename']), + \ 'lnum': l:error['range']['start']['line'], + \ 'col': l:error['range']['start']['column'], + \ 'text': l:error['detail'], + \ 'type': ale_linters#terraform#terraform#GetType(l:error['severity']), \}) else call add(l:output, { - \ 'lnum': line('$'), - \ 'text': l:match[1], - \ 'type': 'E', + \ 'filename': l:file, + \ 'lnum': 0, + \ 'col': 0, + \ 'text': l:error['detail'], + \ 'type': ale_linters#terraform#terraform#GetType(l:error['severity']), \}) endif endfor @@ -42,7 +52,7 @@ endfunction call ale#linter#Define('terraform', { \ 'name': 'terraform', -\ 'output_stream': 'stderr', +\ 'output_stream': 'stdout', \ 'executable': function('ale_linters#terraform#terraform#GetExecutable'), \ 'command': function('ale_linters#terraform#terraform#GetCommand'), \ 'callback': 'ale_linters#terraform#terraform#Handle', diff --git a/test/command_callback/test_terraform_terraform_command_callback.vader b/test/command_callback/test_terraform_terraform_command_callback.vader index fabd902d..25ca652a 100644 --- a/test/command_callback/test_terraform_terraform_command_callback.vader +++ b/test/command_callback/test_terraform_terraform_command_callback.vader @@ -6,4 +6,10 @@ After: call ale#assert#TearDownLinterTest() 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 ' diff --git a/test/handler/test_terraform_handler.vader b/test/handler/test_terraform_handler.vader index 976ce12a..b201f89a 100644 --- a/test/handler/test_terraform_handler.vader +++ b/test/handler/test_terraform_handler.vader @@ -1,34 +1,61 @@ Before: " Load the file which defines the linter. runtime ale_linters/terraform/terraform.vim + call ale#test#SetDirectory('/testplugin/test/terraform_files') + call ale#test#SetFilename('providers.tf') After: " Unload all linters again. call ale#linter#Reset() + call ale#test#RestoreDirectory() Execute(The output should be correct): AssertEqual \ [ \ { - \ 'lnum': 1, - \ 'col': 20, - \ 'type': 'E', - \ 'text': 'illegal char', + \ 'lnum': 17, + \ 'col': 13, + \ 'filename': '/testplugin/test/terraform_files/providers.tf', + \ 'type': 'W', + \ 'text': 'Terraform 0.13 and earlier allowed provider version', \ }, \ { - \ 'lnum': 2, - \ 'col': 14, + \ 'lnum': 0, + \ 'col': 0, + \ 'filename': '/testplugin/test/terraform_files/providers.tf', \ 'type': 'E', - \ 'text': 'literal not terminated', - \ }, - \ { - \ 'lnum': 1, - \ 'type': 'E', - \ 'text': 'object expected closing RBRACE got: EOF', - \ }, + \ 'text': 'Plugin reinitialization required. Please run "terraform"', + \ } \ ], \ ale_linters#terraform#terraform#Handle(bufnr(''), [ - \ 'Error running fmt: In : At 1:20: illegal char', - \ 'Error running fmt: In : At 2:14: literal not terminated', - \ 'Error running fmt: In : object expected closing RBRACE got: EOF', + \ '{', + \ '"valid": false,', + \ '"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\""', + \ ' }', + \ ' ]', + \ '}', \ ])