diff --git a/README.md b/README.md index ccabc3a..38ad43e 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ name. That seems to be the fairest way to arrange this table. | Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) | | SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) | | SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) | -| Scala | [scalac](http://scala-lang.org) | +| Scala | [scalac](http://scala-lang.org), [scalastyle](http://www.scalastyle.org) | | Slim | [slim-lint](https://github.com/sds/slim-lint) | SML | [smlnj](http://www.smlnj.org/) | | Stylus | [stylelint](https://github.com/stylelint/stylelint) | diff --git a/ale_linters/scala/scalastyle.vim b/ale_linters/scala/scalastyle.vim new file mode 100644 index 0000000..ea56c0e --- /dev/null +++ b/ale_linters/scala/scalastyle.vim @@ -0,0 +1,83 @@ +" Author: Kevin Kays - https://github.com/okkays +" Description: Support for the scalastyle checker. + +let g:ale_scala_scalastyle_options = +\ get(g:, 'ale_scala_scalastyle_options', '') + +let g:ale_scalastyle_config_loc = +\ get(g:, 'ale_scalastyle_config_loc', '') + +function! ale_linters#scala#scalastyle#Handle(buffer, lines) abort + " Matches patterns like the following: + " + " warning file=/home/blurble/Doop.scala message=Missing or badly formed ScalaDoc: Extra @param foobles line=190 + + let l:patterns = [ + \ '^\(.\+\) .\+ message=\(.\+\) line=\(\d\+\)$', + \ '^\(.\+\) .\+ message=\(.\+\) line=\(\d\+\) column=\(\d\+\)$', + \] + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:patterns) + let l:args = { + \ 'lnum': l:match[3] + 0, + \ 'type': l:match[1] =~? 'error' ? 'E' : 'W', + \ 'text': l:match[2] + \} + + if !empty(l:match[4]) + let l:args['col'] = l:match[4] + 1 + endif + + call add(l:output, l:args) + endfor + + return l:output +endfunction + +function! ale_linters#scala#scalastyle#GetCommand(buffer) abort + " Search for scalastyle config in parent directories. + let l:scalastyle_config = '' + let l:potential_configs = [ + \ 'scalastyle_config.xml', + \ 'scalastyle-config.xml' + \] + for l:config in l:potential_configs + let l:scalastyle_config = ale#path#ResolveLocalPath( + \ a:buffer, + \ l:config, + \ '' + \) + if !empty(l:scalastyle_config) + break + endif + endfor + + " If all else fails, try the global config. + if empty(l:scalastyle_config) + let l:scalastyle_config = get(g:, 'ale_scalastyle_config_loc', '') + endif + + " Build the command using the config file and additional options. + let l:command = 'scalastyle' + + if !empty(l:scalastyle_config) + let l:command .= ' --config ' . ale#Escape(l:scalastyle_config) + endif + + if !empty(g:ale_scala_scalastyle_options) + let l:command .= ' ' . g:ale_scala_scalastyle_options + endif + + let l:command .= ' %t' + + return l:command +endfunction + +call ale#linter#Define('scala', { +\ 'name': 'scalastyle', +\ 'executable': 'scalastyle', +\ 'output_stream': 'stdout', +\ 'command_callback': 'ale_linters#scala#scalastyle#GetCommand', +\ 'callback': 'ale_linters#scala#scalastyle#Handle', +\}) diff --git a/doc/ale-scala-scalastyle.txt b/doc/ale-scala-scalastyle.txt new file mode 100644 index 0000000..c819e00 --- /dev/null +++ b/doc/ale-scala-scalastyle.txt @@ -0,0 +1,25 @@ +=============================================================================== +ALE Scala Integration *ale-scala-options* + + +=============================================================================== +scalastyle *ale-scala-scalastyle* + +g:ale_scalastyle_config_loc *g:ale_scalastyle_config_loc* + + Type: |String| + Default: `''` + + A string containing the location of a global fallback config file. + By default, ALE will look for a config file named `scalastyle_config.xml` or + `scalastyle-config.xml` in the current file's directory or parent directories. + +g:ale_scala_scalastyle_options *g:ale_scala_scalastyle_options* + + Type: |String| + Default: `''` + + A string containing additional options to pass to scalastyle. + +=============================================================================== + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale.txt b/doc/ale.txt index eafbbcc..e027ef1 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -93,6 +93,8 @@ CONTENTS *ale-contents* rustc...............................|ale-rust-rustc| sass..................................|ale-sass-options| stylelint...........................|ale-sass-stylelint| + scala.................................|ale-scala-options| + scalastyle..........................|ale-scala-scalastyle| scss..................................|ale-scss-options| stylelint...........................|ale-scss-stylelint| sh....................................|ale-sh-options| @@ -206,7 +208,7 @@ The following languages and tools are supported. * Ruby: 'reek', 'rubocop' * SASS: 'sasslint', 'stylelint' * SCSS: 'sasslint', 'scsslint', 'stylelint' -* Scala: 'scalac' +* Scala: 'scalac', 'scalastyle' * Slim: 'slim-lint' * SML: 'smlnj' * Stylus: 'stylelint' diff --git a/test/command_callback/test_scalastyle_command_callback.vader b/test/command_callback/test_scalastyle_command_callback.vader new file mode 100644 index 0000000..f051b02 --- /dev/null +++ b/test/command_callback/test_scalastyle_command_callback.vader @@ -0,0 +1,27 @@ +Before: + runtime ale_linters/scala/scalastyle.vim + +After: + call ale#linter#Reset() + let g:ale_scala_scalastyle_options = '' + let g:ale_scalastyle_conf_loc = '' + +Execute(Should return the correct default command): + AssertEqual + \ 'scalastyle %t', + \ ale_linters#scala#scalastyle#GetCommand(bufnr('')) + +Execute(Should allow using a custom config file): + let g:ale_scalastyle_config_loc = '/dooper/config.xml' + + AssertEqual + \ 'scalastyle --config ''/dooper/config.xml'' %t', + \ ale_linters#scala#scalastyle#GetCommand(bufnr('')) + +Execute(Should allow using custom options): + let g:ale_scala_scalastyle_options = '--warnings false --quiet true' + + AssertEqual + \ 'scalastyle --config ''/dooper/config.xml'' --warnings false --quiet true %t', + \ ale_linters#scala#scalastyle#GetCommand(bufnr('')) + diff --git a/test/handler/test_scalastyle_handler.vader b/test/handler/test_scalastyle_handler.vader new file mode 100644 index 0000000..b03d18e --- /dev/null +++ b/test/handler/test_scalastyle_handler.vader @@ -0,0 +1,38 @@ +Execute(The scalastyle handler should parse lines correctly): + runtime! ale_linters/scala/scalastyle.vim + + AssertEqual + \ [ + \ { + \ 'lnum': 190, + \ 'text': 'Missing or badly formed ScalaDoc: Missing @param str', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 200, + \ 'col': 34, + \ 'text': 'There should be a space before the plus (+) sign', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 200, + \ 'col': 1, + \ 'text': 'There should be a space before the plus (+) sign', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#scala#scalastyle#Handle(347, [ + \ 'Starting scalastyle', + \ 'start file /home/test/Doop.scala', + \ 'warning file=/home/test/Doop.scala message=Missing or badly formed ScalaDoc: Missing @param str line=190', + \ 'error file=/home/test/Doop.scala message=There should be a space before the plus (+) sign line=200 column=33', + \ 'error file=/home/test/Doop.scala message=There should be a space before the plus (+) sign line=200 column=0', + \ 'end file /home/test/Doop.scala', + \ 'Processed 1 file(s)', + \ 'Found 0 errors', + \ 'Found 3 warnings', + \ 'Finished in 934 ms', + \ ]) + +After: + call ale#linter#Reset()