summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Borden <eborden@users.noreply.github.com>2018-09-28 04:05:01 -0400
committerw0rp <w0rp@users.noreply.github.com>2018-09-28 09:05:01 +0100
commita8915d885b79ba8e243c228c9f38dddbcb1c479a (patch)
treee3d0549ec17717a8ad5a3a66c4fb5dbc63d83c07
parenta26b3319a1f37c82be8098b6eae4e6f2985a31eb (diff)
downloadale-a8915d885b79ba8e243c228c9f38dddbcb1c479a.zip
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
-rw-r--r--README.md2
-rw-r--r--ale_linters/haskell/ghc-mod.vim18
-rw-r--r--ale_linters/haskell/ghc_mod.vim19
-rw-r--r--ale_linters/haskell/hdevtools.vim5
-rw-r--r--ale_linters/haskell/hie.vim15
-rw-r--r--ale_linters/haskell/hlint.vim10
-rw-r--r--autoload/ale/fixers/brittany.vim10
-rw-r--r--autoload/ale/fixers/hfmt.vim2
-rw-r--r--autoload/ale/fixers/hlint.vim5
-rw-r--r--autoload/ale/fixers/stylish_haskell.vim10
-rw-r--r--autoload/ale/handlers/haskell_stack.vim7
-rw-r--r--autoload/ale/handlers/hlint.vim8
-rw-r--r--doc/ale-haskell.txt10
-rw-r--r--doc/ale.txt3
-rw-r--r--test/command_callback/test_haskell_ghc_mod_command_callbacks.vader10
-rw-r--r--test/command_callback/test_haskell_hlint_command_callbacks.vader4
-rw-r--r--test/fixers/test_hlint_fixer_callback.vader7
-rw-r--r--test/handler/test_haskell_stack_handler.vader7
18 files changed, 104 insertions, 48 deletions
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 <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',
-\})
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 <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',
+\})
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 <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',
\})
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 <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',
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
@@ -23,6 +23,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*
g:ale_haskell_cabal_ghc_options *g:ale_haskell_cabal_ghc_options*
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')