diff --git a/README.md b/README.md index bdde278f..0eeaf514 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ formatting. | Hack | [hack](http://hacklang.org/), [hackfmt](https://github.com/facebook/hhvm/tree/master/hphp/hack/hackfmt), [hhast](https://github.com/hhvm/hhast) (disabled by default; see `:help ale-integration-hack`) | | Haml | [haml-lint](https://github.com/brigade/haml-lint) | | Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) | -| Haskell | [brittany](https://github.com/lspitzner/brittany), [ghc](https://www.haskell.org/ghc/), [cabal-ghc](https://www.haskell.org/cabal/), [stylish-haskell](https://github.com/jaspervdj/stylish-haskell), [stack-ghc](https://haskellstack.org/), [stack-build](https://haskellstack.org/) !!, [ghc-mod](https://github.com/DanielG/ghc-mod), [stack-ghc-mod](https://github.com/DanielG/ghc-mod), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools), [hfmt](https://github.com/danstiner/hfmt), [hie](https://github.com/haskell/haskell-ide-engine) | +| Haskell | [brittany](https://github.com/lspitzner/brittany), [ghc](https://www.haskell.org/ghc/), [cabal-ghc](https://www.haskell.org/cabal/), [stylish-haskell](https://github.com/jaspervdj/stylish-haskell), [stack-ghc](https://haskellstack.org/), [stack-build](https://haskellstack.org/) !!, [ghc-mod](https://github.com/DanielG/ghc-mod), [hlint](https://hackage.haskell.org/package/hlint), [hdevtools](https://hackage.haskell.org/package/hdevtools), [hfmt](https://github.com/danstiner/hfmt), [hie](https://github.com/haskell/haskell-ide-engine) | | HTML | [alex](https://github.com/wooorm/alex) !!, [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/), [write-good](https://github.com/btford/write-good) | | Idris | [idris](http://www.idris-lang.org/) | | Java | [checkstyle](http://checkstyle.sourceforge.net), [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html), [google-java-format](https://github.com/google/google-java-format), [PMD](https://pmd.github.io/), [javalsp](https://github.com/georgewfraser/vscode-javac), [uncrustify](https://github.com/uncrustify/uncrustify) | diff --git a/ale_linters/haskell/ghc-mod.vim b/ale_linters/haskell/ghc-mod.vim deleted file mode 100644 index eb032f50..00000000 --- a/ale_linters/haskell/ghc-mod.vim +++ /dev/null @@ -1,18 +0,0 @@ -" Author: wizzup -" Description: ghc-mod for Haskell files - -call ale#linter#Define('haskell', { -\ 'name': 'ghc_mod', -\ 'aliases': ['ghc-mod'], -\ 'executable': 'ghc-mod', -\ 'command': 'ghc-mod --map-file %s=%t check %s', -\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', -\}) - -call ale#linter#Define('haskell', { -\ 'name': 'stack_ghc_mod', -\ 'aliases': ['stack-ghc-mod'], -\ 'executable': 'stack', -\ 'command': 'stack exec ghc-mod -- --map-file %s=%t check %s', -\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', -\}) diff --git a/ale_linters/haskell/ghc_mod.vim b/ale_linters/haskell/ghc_mod.vim new file mode 100644 index 00000000..9762be7a --- /dev/null +++ b/ale_linters/haskell/ghc_mod.vim @@ -0,0 +1,19 @@ +" Author: wizzup +" Description: ghc-mod for Haskell files + +call ale#Set('haskell_ghc_mod_executable', 'ghc-mod') + +function! ale_linters#haskell#ghc_mod#GetCommand (buffer) abort + let l:executable = ale#Var(a:buffer, 'haskell_ghc_mod_executable') + + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'ghc-mod') + \ . ' --map-file %s=%t check %s' +endfunction + +call ale#linter#Define('haskell', { +\ 'name': 'ghc_mod', +\ 'aliases': ['ghc-mod'], +\ 'executable_callback': ale#VarFunc('haskell_ghc_mod_executable'), +\ 'command_callback': 'ale_linters#haskell#ghc_mod#GetCommand', +\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', +\}) diff --git a/ale_linters/haskell/hdevtools.vim b/ale_linters/haskell/hdevtools.vim index fbd5278e..cc5ce56f 100644 --- a/ale_linters/haskell/hdevtools.vim +++ b/ale_linters/haskell/hdevtools.vim @@ -5,7 +5,10 @@ call ale#Set('haskell_hdevtools_executable', 'hdevtools') call ale#Set('haskell_hdevtools_options', get(g:, 'hdevtools_options', '-g -Wall')) function! ale_linters#haskell#hdevtools#GetCommand(buffer) abort - return '%e check' . ale#Pad(ale#Var(a:buffer, 'haskell_hdevtools_options')) + let l:executable = ale#Var(a:buffer, 'haskell_hdevtools_executable') + + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'hdevtools') + \ . ' check' . ale#Pad(ale#Var(a:buffer, 'haskell_hdevtools_options')) \ . ' -p %s %t' endfunction diff --git a/ale_linters/haskell/hie.vim b/ale_linters/haskell/hie.vim index 558d36a3..3ff1180a 100644 --- a/ale_linters/haskell/hie.vim +++ b/ale_linters/haskell/hie.vim @@ -3,10 +3,6 @@ call ale#Set('haskell_hie_executable', 'hie') -function! ale_linters#haskell#hie#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'haskell_hie_executable') -endfunction - function! ale_linters#haskell#hie#GetProjectRoot(buffer) abort " Search for the stack file first let l:project_file = ale#path#FindNearestFile(a:buffer, 'stack.yaml') @@ -35,10 +31,17 @@ function! ale_linters#haskell#hie#GetProjectRoot(buffer) abort return l:project_file endfunction +function! ale_linters#haskell#hie#GetCommand(buffer) abort + let l:executable = ale#Var(a:buffer, 'haskell_hie_executable') + + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'hie') +\ . ' --lsp' +endfunction + call ale#linter#Define('haskell', { \ 'name': 'hie', \ 'lsp': 'stdio', -\ 'command': '%e --lsp', -\ 'executable_callback': 'ale_linters#haskell#hie#GetExecutable', +\ 'command_callback': 'ale_linters#haskell#hie#GetCommand', +\ 'executable_callback': ale#VarFunc('haskell_hie_executable'), \ 'project_root_callback': 'ale_linters#haskell#hie#GetProjectRoot', \}) diff --git a/ale_linters/haskell/hlint.vim b/ale_linters/haskell/hlint.vim index 3ee864bf..fbb49fdb 100644 --- a/ale_linters/haskell/hlint.vim +++ b/ale_linters/haskell/hlint.vim @@ -1,9 +1,6 @@ " Author: jparoz " Description: hlint for Haskell files -call ale#Set('haskell_hlint_executable', 'hlint') -call ale#Set('haskell_hlint_options', get(g:, 'hlint_options', '')) - function! ale_linters#haskell#hlint#Handle(buffer, lines) abort let l:output = [] @@ -32,14 +29,15 @@ endfunction function! ale_linters#haskell#hlint#GetCommand(buffer) abort let l:hlintopts = '--color=never --json' - return '%e' + return ale#handlers#hlint#GetExecutable(a:buffer) \ . ' ' . ale#Var(a:buffer, 'haskell_hlint_options') - \ . ' ' . l:hlintopts . ' -' + \ . ' ' . l:hlintopts + \ . ' -' endfunction call ale#linter#Define('haskell', { \ 'name': 'hlint', \ 'executable_callback': ale#VarFunc('haskell_hlint_executable'), -\ 'command_callback': 'ale_linters#haskell#hlint#GetCommand', +\ 'command_callback': 'ale_linters#haskell#hlint#GetCommand' , \ 'callback': 'ale_linters#haskell#hlint#Handle', \}) diff --git a/autoload/ale/fixers/brittany.vim b/autoload/ale/fixers/brittany.vim index 57c77325..c2448348 100644 --- a/autoload/ale/fixers/brittany.vim +++ b/autoload/ale/fixers/brittany.vim @@ -3,11 +3,17 @@ call ale#Set('haskell_brittany_executable', 'brittany') -function! ale#fixers#brittany#Fix(buffer) abort +function! ale#fixers#brittany#GetExecutable(buffer) abort let l:executable = ale#Var(a:buffer, 'haskell_brittany_executable') + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'brittany') +endfunction + +function! ale#fixers#brittany#Fix(buffer) abort + let l:executable = ale#fixers#brittany#GetExecutable(a:buffer) + return { - \ 'command': ale#Escape(l:executable) + \ 'command': l:executable \ . ' --write-mode inplace' \ . ' %t', \ 'read_temporary_file': 1, diff --git a/autoload/ale/fixers/hfmt.vim b/autoload/ale/fixers/hfmt.vim index ea061da4..0407b713 100644 --- a/autoload/ale/fixers/hfmt.vim +++ b/autoload/ale/fixers/hfmt.vim @@ -7,7 +7,7 @@ function! ale#fixers#hfmt#Fix(buffer) abort let l:executable = ale#Var(a:buffer, 'haskell_hfmt_executable') return { - \ 'command': ale#Escape(l:executable) + \ 'command': ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'hfmt') \ . ' -w' \ . ' %t', \ 'read_temporary_file': 1, diff --git a/autoload/ale/fixers/hlint.vim b/autoload/ale/fixers/hlint.vim index 94dd736e..88779a55 100644 --- a/autoload/ale/fixers/hlint.vim +++ b/autoload/ale/fixers/hlint.vim @@ -1,13 +1,10 @@ " Author: eborden " Description: Integration of hlint refactor with ALE. " -call ale#Set('haskell_hlint_executable', 'hlint') function! ale#fixers#hlint#Fix(buffer) abort - let l:executable = ale#Var(a:buffer, 'haskell_hlint_executable') - return { - \ 'command': ale#Escape(l:executable) + \ 'command': ale#handlers#hlint#GetExecutable(a:buffer) \ . ' --refactor' \ . ' --refactor-options="--inplace"' \ . ' %t', diff --git a/autoload/ale/fixers/stylish_haskell.vim b/autoload/ale/fixers/stylish_haskell.vim index a352312f..ce71c1ce 100644 --- a/autoload/ale/fixers/stylish_haskell.vim +++ b/autoload/ale/fixers/stylish_haskell.vim @@ -3,11 +3,17 @@ " call ale#Set('haskell_stylish_haskell_executable', 'stylish-haskell') -function! ale#fixers#stylish_haskell#Fix(buffer) abort +function! ale#fixers#stylish_haskell#GetExecutable(buffer) abort let l:executable = ale#Var(a:buffer, 'haskell_stylish_haskell_executable') + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'stylish-haskell') +endfunction + +function! ale#fixers#stylish_haskell#Fix(buffer) abort + let l:executable = ale#fixers#stylish_haskell#GetExecutable(a:buffer) + return { - \ 'command': ale#Escape(l:executable) + \ 'command': l:executable \ . ' --inplace' \ . ' %t', \ 'read_temporary_file': 1, diff --git a/autoload/ale/handlers/haskell_stack.vim b/autoload/ale/handlers/haskell_stack.vim new file mode 100644 index 00000000..108301a9 --- /dev/null +++ b/autoload/ale/handlers/haskell_stack.vim @@ -0,0 +1,7 @@ +function! ale#handlers#haskell_stack#EscapeExecutable(executable, stack_exec) abort + let l:exec_args = a:executable =~? 'stack$' + \ ? ' exec ' . ale#Escape(a:stack_exec) . ' --' + \ : '' + + return ale#Escape(a:executable) . l:exec_args +endfunction diff --git a/autoload/ale/handlers/hlint.vim b/autoload/ale/handlers/hlint.vim new file mode 100644 index 00000000..b9a8c322 --- /dev/null +++ b/autoload/ale/handlers/hlint.vim @@ -0,0 +1,8 @@ +call ale#Set('haskell_hlint_executable', 'hlint') +call ale#Set('haskell_hlint_options', get(g:, 'hlint_options', '')) + +function! ale#handlers#hlint#GetExecutable(buffer) abort + let l:executable = ale#Var(a:buffer, 'haskell_hlint_executable') + + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'hlint') +endfunction diff --git a/doc/ale-haskell.txt b/doc/ale-haskell.txt index a59fa4e2..a4db683b 100644 --- a/doc/ale-haskell.txt +++ b/doc/ale-haskell.txt @@ -22,6 +22,16 @@ g:ale_haskell_ghc_options *g:ale_haskell_ghc_options* This variable can be changed to modify flags given to ghc. +=============================================================================== +ghc-mod *ale-haskell-ghc-mod* + +g:ale_haskell_ghc_mod_executable *g:ale_haskell_ghc_mod_executable* + *b:ale_haskell_ghc_mod_executable* + Type: |String| + Default: `'ghc-mod'` + + This variable can be changed to use a different executable for ghc-mod. + =============================================================================== cabal-ghc *ale-haskell-cabal-ghc* diff --git a/doc/ale.txt b/doc/ale.txt index ec44f3b8..3c561e2f 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -117,6 +117,7 @@ CONTENTS *ale-contents* haskell...............................|ale-haskell-options| brittany............................|ale-haskell-brittany| ghc.................................|ale-haskell-ghc| + ghc-mod.............................|ale-haskell-ghc-mod| cabal-ghc...........................|ale-haskell-cabal-ghc| hdevtools...........................|ale-haskell-hdevtools| hfmt................................|ale-haskell-hfmt| @@ -411,7 +412,7 @@ Notes: * Hack: `hack`, `hackfmt`, `hhast` * Haml: `haml-lint` * Handlebars: `ember-template-lint` -* Haskell: `brittany`, `ghc`, `cabal-ghc`, `stylish-haskell`, `stack-ghc`, `stack-build`!!, `ghc-mod`, `stack-ghc-mod`, `hlint`, `hdevtools`, `hfmt`, `hie` +* Haskell: `brittany`, `ghc`, `cabal-ghc`, `stylish-haskell`, `stack-ghc`, `stack-build`!!, `ghc-mod`, `hlint`, `hdevtools`, `hfmt`, `hie` * HTML: `alex`!!, `HTMLHint`, `proselint`, `tidy`, `write-good` * Idris: `idris` * Java: `checkstyle`, `javac`, `google-java-format`, `PMD`, `javalsp`, `uncrustify` diff --git a/test/command_callback/test_haskell_ghc_mod_command_callbacks.vader b/test/command_callback/test_haskell_ghc_mod_command_callbacks.vader new file mode 100644 index 00000000..c1cc8597 --- /dev/null +++ b/test/command_callback/test_haskell_ghc_mod_command_callbacks.vader @@ -0,0 +1,10 @@ +Before: + call ale#assert#SetUpLinterTest('haskell', 'ghc_mod') + +After: + call ale#assert#TearDownLinterTest() + +Execute(Default should use ghc-mod): + AssertLinter + \ 'ghc-mod', + \ ale#Escape('ghc-mod') . ' --map-file %s=%t check %s' diff --git a/test/command_callback/test_haskell_hlint_command_callbacks.vader b/test/command_callback/test_haskell_hlint_command_callbacks.vader index fb354ed4..d4ee708c 100644 --- a/test/command_callback/test_haskell_hlint_command_callbacks.vader +++ b/test/command_callback/test_haskell_hlint_command_callbacks.vader @@ -1,5 +1,9 @@ Before: call ale#assert#SetUpLinterTest('haskell', 'hlint') + + let g:ale_haskell_hlint_executable = 'hlint' + let g:ale_haskell_hlint_options = '' + let b:base_opts = '--color=never --json -' After: diff --git a/test/fixers/test_hlint_fixer_callback.vader b/test/fixers/test_hlint_fixer_callback.vader index 48f26c7c..08f08fae 100644 --- a/test/fixers/test_hlint_fixer_callback.vader +++ b/test/fixers/test_hlint_fixer_callback.vader @@ -1,9 +1,4 @@ Before: - Save g:ale_haskell_hlint_executable - - " Use an invalid global executable, so we don't match it. - let g:ale_haskell_hlint_executable = 'xxxinvalid' - call ale#test#SetDirectory('/testplugin/test/fixers') After: @@ -17,7 +12,7 @@ Execute(The hlint callback should return the correct default values): AssertEqual \ { \ 'read_temporary_file': 1, - \ 'command': ale#Escape('xxxinvalid') + \ 'command': ale#Escape('hlint') \ . ' --refactor' \ . ' --refactor-options="--inplace"' \ . ' %t', diff --git a/test/handler/test_haskell_stack_handler.vader b/test/handler/test_haskell_stack_handler.vader new file mode 100644 index 00000000..07e7e69c --- /dev/null +++ b/test/handler/test_haskell_stack_handler.vader @@ -0,0 +1,7 @@ +Before: + runtime ale/handlers/haskell_stack.vim + +Execute(Escape stack should correctly identify a stack exec command): + AssertEqual + \ ale#Escape('stack') . ' exec ' . ale#Escape('hlint') . ' --', + \ ale#handlers#haskell_stack#EscapeExecutable('stack', 'hlint')