From da410caff8b2a7ba5c57e210ce24ac229ce347f0 Mon Sep 17 00:00:00 2001 From: Matthew Turland Date: Mon, 17 Jul 2017 14:28:21 -0500 Subject: [PATCH] Add yaml swaglint linter (#771) * Add yaml swaglint linter --- README.md | 2 +- ale_linters/yaml/swaglint.vim | 41 +++++++++++++ doc/ale-yaml.txt | 34 +++++++++++ doc/ale.txt | 3 +- .../swaglint_paths/docs/swagger.yaml | 0 .../swaglint_paths/node_modules/.bin/swaglint | 0 .../test_swaglint_command_callback.vader | 36 ++++++++++++ test/handler/test_swaglint_handler.vader | 58 +++++++++++++++++++ 8 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 ale_linters/yaml/swaglint.vim create mode 100644 test/command_callback/swaglint_paths/docs/swagger.yaml create mode 100644 test/command_callback/swaglint_paths/node_modules/.bin/swaglint create mode 100644 test/command_callback/test_swaglint_command_callback.vader create mode 100644 test/handler/test_swaglint_handler.vader diff --git a/README.md b/README.md index a975b9d0..926402aa 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ name. That seems to be the fairest way to arrange this table. | Vim help^ | [proselint](http://proselint.com/)| | XHTML | [proselint](http://proselint.com/)| | XML | [xmllint](http://xmlsoft.org/xmllint.html/)| -| YAML | [yamllint](https://yamllint.readthedocs.io/) | +| YAML | [swaglint](https://github.com/byCedric/swaglint), [yamllint](https://yamllint.readthedocs.io/) | * *^ No linters for text or Vim help filetypes are enabled by default.* diff --git a/ale_linters/yaml/swaglint.vim b/ale_linters/yaml/swaglint.vim new file mode 100644 index 00000000..1368d7b7 --- /dev/null +++ b/ale_linters/yaml/swaglint.vim @@ -0,0 +1,41 @@ +" Author: Matthew Turland +" Description: This file adds support for linting Swagger / OpenAPI documents using swaglint + +call ale#Set('yaml_swaglint_executable', 'swaglint') +call ale#Set('yaml_swaglint_use_global', 0) + +function! ale_linters#yaml#swaglint#GetExecutable(buffer) abort + return ale#node#FindExecutable(a:buffer, 'yaml_swaglint', [ + \ 'node_modules/.bin/swaglint', + \]) +endfunction + +function! ale_linters#yaml#swaglint#GetCommand(buffer) abort + return ale_linters#yaml#swaglint#GetExecutable(a:buffer) + \ . ' -r compact --stdin' +endfunction + +function! ale_linters#yaml#swaglint#Handle(buffer, lines) abort + let l:pattern = ': \([^\s]\+\) @ \(\d\+\):\(\d\+\) - \(.\+\)$' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + let l:obj = { + \ 'type': l:match[1] ==# 'error' ? 'E' : 'W', + \ 'lnum': l:match[2] + 0, + \ 'col': l:match[3] + 0, + \ 'text': l:match[4], + \} + + call add(l:output, l:obj) + endfor + + return l:output +endfunction + +call ale#linter#Define('yaml', { +\ 'name': 'swaglint', +\ 'executable_callback': 'ale_linters#yaml#swaglint#GetExecutable', +\ 'command_callback': 'ale_linters#yaml#swaglint#GetCommand', +\ 'callback': 'ale_linters#yaml#swaglint#Handle', +\}) diff --git a/doc/ale-yaml.txt b/doc/ale-yaml.txt index 4a24afa1..a902f25d 100644 --- a/doc/ale-yaml.txt +++ b/doc/ale-yaml.txt @@ -2,6 +2,40 @@ ALE YAML Integration *ale-yaml-options* +=============================================================================== +swaglint *ale-yaml-swaglint* + +Website: https://github.com/byCedric/swaglint + + +Installation +------------------------------------------------------------------------------- + +Install swaglint either globally or locally: > + + npm install swaglint -g # global + npm install swaglint # local +< + +Options +------------------------------------------------------------------------------- + +g:ale_yaml_swaglint_executable *g:ale_yaml_swaglint_executable* + *b:ale_yaml_swaglint_executable* + Type: |String| + Default: `'swaglint'` + + This variable can be set to change the path to swaglint. + + +g:ale_yaml_swaglint_use_global *g:ale_yaml_swaglint_use_global* + *b:ale_yaml_swaglint_use_global* + Type: |String| + Default: `0` + + See |ale-integrations-local-executables| + + =============================================================================== yamllint *ale-yaml-yamllint* diff --git a/doc/ale.txt b/doc/ale.txt index 7a551c0d..be79cedf 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -121,6 +121,7 @@ CONTENTS *ale-contents* xml...................................|ale-xml-options| xmllint.............................|ale-xml-xmllint| yaml..................................|ale-yaml-options| + swaglint............................|ale-yaml-swaglint| yamllint............................|ale-yaml-yamllint| 6. Commands/Keybinds....................|ale-commands| 7. API..................................|ale-api| @@ -224,7 +225,7 @@ The following languages and tools are supported. * Vim help: 'proselint' * XHTML: 'proselint' * XML: 'xmllint' -* YAML: 'yamllint' +* YAML: 'swaglint', 'yamllint' =============================================================================== 3. Global Options *ale-options* diff --git a/test/command_callback/swaglint_paths/docs/swagger.yaml b/test/command_callback/swaglint_paths/docs/swagger.yaml new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/swaglint_paths/node_modules/.bin/swaglint b/test/command_callback/swaglint_paths/node_modules/.bin/swaglint new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/test_swaglint_command_callback.vader b/test/command_callback/test_swaglint_command_callback.vader new file mode 100644 index 00000000..5d04e923 --- /dev/null +++ b/test/command_callback/test_swaglint_command_callback.vader @@ -0,0 +1,36 @@ +Before: + runtime ale_linters/yaml/swaglint.vim + call ale#test#SetDirectory('/testplugin/test/command_callback') + +After: + call ale#linter#Reset() + let g:ale_yaml_swaglint_executable = 'swaglint' + let g:ale_yaml_swaglint_use_global = 0 + +Execute(The yaml swaglint command callback should return the correct default string): + AssertEqual 'swaglint', + \ ale_linters#yaml#swaglint#GetExecutable(bufnr('')) + AssertEqual 'swaglint -r compact --stdin', + \ ale_linters#yaml#swaglint#GetCommand(bufnr('')) + +Execute(The yaml swaglint command callback should be configurable): + let g:ale_yaml_swaglint_executable = '~/.local/bin/swaglint' + AssertEqual '~/.local/bin/swaglint', + \ ale_linters#yaml#swaglint#GetExecutable(bufnr('')) + AssertEqual '~/.local/bin/swaglint -r compact --stdin', + \ ale_linters#yaml#swaglint#GetCommand(bufnr('')) + +Execute(The yaml swaglint command callback should allow a global installation to be used): + let g:ale_yaml_swaglint_executable = '/usr/local/bin/swaglint' + let g:ale_yaml_swaglint_use_global = 1 + AssertEqual '/usr/local/bin/swaglint', + \ ale_linters#yaml#swaglint#GetExecutable(bufnr('')) + AssertEqual '/usr/local/bin/swaglint -r compact --stdin', + \ ale_linters#yaml#swaglint#GetCommand(bufnr('')) + +Execute(The yaml swaglint command callback should allow a local installation to be used): + call ale#test#SetFilename('swaglint_paths/docs/swagger.yaml') + AssertEqual g:dir . '/swaglint_paths/node_modules/.bin/swaglint', + \ ale_linters#yaml#swaglint#GetExecutable(bufnr('')) + AssertEqual g:dir . '/swaglint_paths/node_modules/.bin/swaglint -r compact --stdin', + \ ale_linters#yaml#swaglint#GetCommand(bufnr('')) diff --git a/test/handler/test_swaglint_handler.vader b/test/handler/test_swaglint_handler.vader new file mode 100644 index 00000000..e2c27301 --- /dev/null +++ b/test/handler/test_swaglint_handler.vader @@ -0,0 +1,58 @@ +Before: + runtime ale_linters/yaml/swaglint.vim + +Execute(The swaglint handler should parse lines correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 1, + \ 'text': 'Missing required property: info (sway_object_missing_required_property)', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 6, + \ 'col': 9, + \ 'text': 'Not a valid response definition (sway_one_of_missing)', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 7, + \ 'col': 11, + \ 'text': 'Missing required property: description (sway_object_missing_required_property)', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 7, + \ 'col': 11, + \ 'text': 'Missing required property: $ref (sway_object_missing_required_property)', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 1, + \ 'col': 10, + \ 'text': 'Expected type string but found type integer (sway_invalid_type)', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 1, + \ 'col': 10, + \ 'text': 'No enum match for: 2 (sway_enum_mismatch)', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 14, + \ 'col': 3, + \ 'text': 'Definition is not used: #/definitions/Foo (sway_unused_definition)', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#yaml#swaglint#Handle(347, [ + \ 'swagger.yaml: error @ 1:1 - Missing required property: info (sway_object_missing_required_property)', + \ 'swagger.yaml: error @ 6:9 - Not a valid response definition (sway_one_of_missing)', + \ 'swagger.yaml: error @ 7:11 - Missing required property: description (sway_object_missing_required_property)', + \ 'swagger.yaml: error @ 7:11 - Missing required property: $ref (sway_object_missing_required_property)', + \ 'swagger.yaml: error @ 1:10 - Expected type string but found type integer (sway_invalid_type)', + \ 'swagger.yaml: error @ 1:10 - No enum match for: 2 (sway_enum_mismatch)', + \ 'swagger.yaml: warning @ 14:3 - Definition is not used: #/definitions/Foo (sway_unused_definition)', + \ ])