diff --git a/ale_linters/sql/sqlfluff.vim b/ale_linters/sql/sqlfluff.vim new file mode 100644 index 00000000..91a39908 --- /dev/null +++ b/ale_linters/sql/sqlfluff.vim @@ -0,0 +1,66 @@ +" Author: Carl Smedstad +" Description: sqlfluff for SQL files + +let g:ale_sql_sqlfluff_executable = +\ get(g:, 'ale_sql_sqlfluff_executable', 'sqlfluff') + +let g:ale_sql_sqlfluff_options = +\ get(g:, 'ale_sql_sqlfluff_options', '') + +function! ale_linters#sql#sqlfluff#Executable(buffer) abort + return ale#Var(a:buffer, 'sql_sqlfluff_executable') +endfunction + +function! ale_linters#sql#sqlfluff#Command(buffer) abort + let l:executable = ale_linters#sql#sqlfluff#Executable(a:buffer) + let l:options = ale#Var(a:buffer, 'sql_sqlfluff_options') + + let l:cmd = + \ ale#Escape(l:executable) + \ . ' lint' + + let l:config_file = ale#path#FindNearestFile(a:buffer, '.sqlfluff') + + if !empty(l:config_file) + let l:cmd .= ' --config ' . ale#Escape(l:config_file) + else + let l:cmd .= ' --dialect ansi' + endif + + let l:cmd .= + \ ' --format json ' + \ . l:options + \ . ' %t' + + return l:cmd +endfunction + +function! ale_linters#sql#sqlfluff#Handle(buffer, lines) abort + let l:output = [] + let l:json = ale#util#FuzzyJSONDecode(a:lines, {})[0] + + " if there's no warning, 'result' is `null`. + if empty(get(l:json, 'violations')) + return l:output + endif + + for l:violation in get(l:json, 'violations', []) + call add(l:output, { + \ 'filename': l:json.filepath, + \ 'lnum': l:violation.line_no, + \ 'col': l:violation.line_pos, + \ 'text': l:violation.description, + \ 'code': l:violation.code, + \ 'type': 'W', + \}) + endfor + + return l:output +endfunction + +call ale#linter#Define('sql', { +\ 'name': 'sqlfluff', +\ 'executable': function('ale_linters#sql#sqlfluff#Executable'), +\ 'command': function('ale_linters#sql#sqlfluff#Command'), +\ 'callback': 'ale_linters#sql#sqlfluff#Handle', +\}) diff --git a/doc/ale-sql.txt b/doc/ale-sql.txt index 80929264..225ac7df 100644 --- a/doc/ale-sql.txt +++ b/doc/ale-sql.txt @@ -27,6 +27,27 @@ g:ale_sql_pgformatter_options *g:ale_sql_pgformatter_options* This variable can be set to pass additional options to the pgformatter fixer. +=============================================================================== +sqlfluff *ale-sql-sqlfluff* + +g:ale_sql_sqlfluff_executable *g:ale_sql_sqlfluff_executable* + *b:ale_sql_sqlfluff_executable* + Type: |String| + Default: `'sqlfluff'` + + This variable sets executable used for sqlfluff. + +g:ale_sql_sqlfluff_options *g:ale_sql_sqlfluff_options* + *b:ale_sql_sqlfluff_options* + Type: |String| + Default: `''` + + This variable can be set to pass additional options to the sqlfluff linter. + + +=============================================================================== + + =============================================================================== sqlfmt *ale-sql-sqlfmt* diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index 591f1cb3..7261bf2a 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -573,6 +573,7 @@ Notes: * `dprint` * `pgformatter` * `sql-lint` + * `sqlfluff` * `sqlfmt` * `sqlformat` * `sqlint` diff --git a/doc/ale.txt b/doc/ale.txt index 27d2c65c..aff40fd6 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -3241,6 +3241,7 @@ documented in additional help files. sql.....................................|ale-sql-options| dprint................................|ale-sql-dprint| pgformatter...........................|ale-sql-pgformatter| + sqlfluff..............................|ale-sql-sqlfluff| sqlfmt................................|ale-sql-sqlfmt| sqlformat.............................|ale-sql-sqlformat| stylus..................................|ale-stylus-options| diff --git a/supported-tools.md b/supported-tools.md index 2989bfbc..fa84aed7 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -582,6 +582,7 @@ formatting. * [dprint](https://dprint.dev) * [pgformatter](https://github.com/darold/pgFormatter) * [sql-lint](https://github.com/joereynolds/sql-lint) + * [sqlfluff](https://github.com/sqlfluff/sqlfluff) * [sqlfmt](https://github.com/jackc/sqlfmt) * [sqlformat](https://github.com/andialbrecht/sqlparse) * [sqlint](https://github.com/purcell/sqlint) diff --git a/test/handler/test_sql_sqlfluff_handler.vader b/test/handler/test_sql_sqlfluff_handler.vader new file mode 100644 index 00000000..f1f684bd --- /dev/null +++ b/test/handler/test_sql_sqlfluff_handler.vader @@ -0,0 +1,39 @@ +Before: + runtime ale_linters/sql/sqlfluff.vim + +After: + Restore + + call ale#linter#Reset() + +Execute(The sqlfluff handler should handle basic warnings): + AssertEqual + \ [ + \ { + \ 'filename': 'schema.sql', + \ 'lnum': 1, + \ 'col': 8, + \ 'type': 'W', + \ 'code': 'L010', + \ 'text': 'Keywords must be consistently upper case.', + \ }, + \ { + \ 'filename': 'schema.sql', + \ 'lnum': 13, + \ 'col': 2, + \ 'type': 'W', + \ 'code': 'L003', + \ 'text': 'Expected 1 indentation, found 0 [compared to line 12]', + \ }, + \ { + \ 'filename': 'schema.sql', + \ 'lnum': 16, + \ 'col': 1, + \ 'type': 'W', + \ 'code': 'L009', + \ 'text': 'Files must end with a single trailing newline.', + \ }, + \ ], + \ ale_linters#sql#sqlfluff#Handle(1, [ + \ '[{"filepath": "schema.sql", "violations": [{"line_no": 1, "line_pos": 8, "code": "L010", "description": "Keywords must be consistently upper case."}, {"line_no": 13, "line_pos": 2, "code": "L003", "description": "Expected 1 indentation, found 0 [compared to line 12]"}, {"line_no": 16, "line_pos": 1, "code": "L009", "description": "Files must end with a single trailing newline."}]}]', + \ ]) diff --git a/test/linter/test_sql_sqlfluff.vader b/test/linter/test_sql_sqlfluff.vader new file mode 100644 index 00000000..9b474017 --- /dev/null +++ b/test/linter/test_sql_sqlfluff.vader @@ -0,0 +1,25 @@ +Before: + call ale#assert#SetUpLinterTest('sql', 'sqlfluff') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'sqlfluff', + \ ale#Escape('sqlfluff') + \ . ' lint --dialect ansi --format json %t' + +Execute(The executable should be configurable): + let g:ale_sql_sqlfluff_executable = 'foobar' + + AssertLinter 'foobar', + \ ale#Escape('foobar') + \ . ' lint --dialect ansi --format json %t' + +Execute(Overriding options should work): + let g:ale_sql_sqlfluff_executable = 'foobar' + let g:ale_sql_sqlfluff_options = '--whatever' + + AssertLinter 'foobar', + \ ale#Escape('foobar') + \ . ' lint --dialect ansi --format json --whatever %t'