Add better support for Haskell stack compiler tools (#1851)
* Add better support for Haskell stack compiler tools This commit adds support for `stack` as the executable of a tool. This follows a pattern that has been implemented for `bundler`'s tool chain. * Move hlint command to linter file * Add vader test for stack exec handling * Update ghc-mod to support stack execution `ghc-mod` was previously broken into 2 linters. 1. ghc_mod 2. stack_ghc_mod This additional linter is not necessary with proper support for executable variables and `stack exec` handling. * Support stack exec in hfmt * Support stack in hdevtools
This commit is contained in:
parent
a26b3319a1
commit
a8915d885b
18 changed files with 104 additions and 48 deletions
|
@ -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) |
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
" Author: wizzup <wizzup@gmail.com>
|
||||
" 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',
|
||||
\})
|
19
ale_linters/haskell/ghc_mod.vim
Normal file
19
ale_linters/haskell/ghc_mod.vim
Normal file
|
@ -0,0 +1,19 @@
|
|||
" Author: wizzup <wizzup@gmail.com>
|
||||
" 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',
|
||||
\})
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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',
|
||||
\})
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
" Author: jparoz <jesse.paroz@gmail.com>
|
||||
" 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',
|
||||
\})
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
" Author: eborden <evan@evan-borden.com>
|
||||
" 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',
|
||||
|
|
|
@ -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,
|
||||
|
|
7
autoload/ale/handlers/haskell_stack.vim
Normal file
7
autoload/ale/handlers/haskell_stack.vim
Normal file
|
@ -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
|
8
autoload/ale/handlers/hlint.vim
Normal file
8
autoload/ale/handlers/hlint.vim
Normal file
|
@ -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
|
|
@ -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*
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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'
|
|
@ -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:
|
||||
|
|
|
@ -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',
|
||||
|
|
7
test/handler/test_haskell_stack_handler.vader
Normal file
7
test/handler/test_haskell_stack_handler.vader
Normal file
|
@ -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')
|
Reference in a new issue