summaryrefslogtreecommitdiff
path: root/test/linter
diff options
context:
space:
mode:
authorw0rp <devw0rp@gmail.com>2021-03-21 00:21:49 +0000
committerw0rp <devw0rp@gmail.com>2021-03-21 00:25:33 +0000
commitf7852dbd0a063d6d82ee17a5057fea53cb79b21d (patch)
tree00b98a3c668af9313eedd6936475c81eeef7e9b8 /test/linter
parent35caaecc9fc5822f0474e913d0b7655048fd30ee (diff)
downloadale-f7852dbd0a063d6d82ee17a5057fea53cb79b21d.zip
#3633 - Move linter tests into test/linter
Diffstat (limited to 'test/linter')
-rw-r--r--test/linter/test_ada_gcc.vader42
-rw-r--r--test/linter/test_adals.vader17
-rw-r--r--test/linter/test_alex.vader34
-rw-r--r--test/linter/test_ameba.vader20
-rw-r--r--test/linter/test_angular.vader44
-rw-r--r--test/linter/test_ansible_lint.vader22
-rw-r--r--test/linter/test_asciidoc_textlint.vader65
-rw-r--r--test/linter/test_asm_gcc.vader19
-rw-r--r--test/linter/test_bandit.vader71
-rw-r--r--test/linter/test_bashate.vader15
-rw-r--r--test/linter/test_bib_bibclean.vader24
-rw-r--r--test/linter/test_bingo.vader74
-rw-r--r--test/linter/test_brakeman.vader37
-rw-r--r--test/linter/test_c_cc.vader55
-rw-r--r--test/linter/test_c_ccls.vader69
-rw-r--r--test/linter/test_c_clang_tidy.vader77
-rw-r--r--test/linter/test_c_clangd.vader47
-rw-r--r--test/linter/test_c_cppcheck.vader46
-rw-r--r--test/linter/test_c_cquery.vader37
-rw-r--r--test/linter/test_c_flawfinder.vader24
-rw-r--r--test/linter/test_c_import_paths.vader162
-rw-r--r--test/linter/test_cargo.vader222
-rw-r--r--test/linter/test_checkstyle.vader72
-rw-r--r--test/linter/test_clang_tidy.vader84
-rw-r--r--test/linter/test_cookstyle.vader19
-rw-r--r--test/linter/test_cpp_cc.vader55
-rw-r--r--test/linter/test_cpp_ccls.vader69
-rw-r--r--test/linter/test_cpp_clangcheck.vader35
-rw-r--r--test/linter/test_cpp_clazy.vader56
-rw-r--r--test/linter/test_cpp_cppcheck.vader66
-rw-r--r--test/linter/test_cpp_cquery.vader40
-rw-r--r--test/linter/test_cpp_flawfinder.vader26
-rw-r--r--test/linter/test_cpplint.vader17
-rw-r--r--test/linter/test_cs_csc.vader42
-rw-r--r--test/linter/test_cs_mcs.vader13
-rw-r--r--test/linter/test_cs_mcsc.vader42
-rw-r--r--test/linter/test_cucumber.vader18
-rw-r--r--test/linter/test_cuda_nvcc.vader20
-rw-r--r--test/linter/test_cypher_cypher_lint.vader8
-rw-r--r--test/linter/test_d_dls.vader19
-rw-r--r--test/linter/test_dart_analysis_server.vader15
-rw-r--r--test/linter/test_dart_language_server.vader8
-rw-r--r--test/linter/test_dartanalyzer.vader20
-rw-r--r--test/linter/test_desktop_file_validate.vader15
-rw-r--r--test/linter/test_dialyxir.vader16
-rw-r--r--test/linter/test_dockerfile_lint.vader19
-rw-r--r--test/linter/test_dogma.vader16
-rw-r--r--test/linter/test_eclipselsp.vader111
-rw-r--r--test/linter/test_elixir_credo.vader43
-rw-r--r--test/linter/test_elixir_ls.vader34
-rw-r--r--test/linter/test_elixir_mix.vader19
-rw-r--r--test/linter/test_elm_ls.vader29
-rw-r--r--test/linter/test_elm_make.vader63
-rw-r--r--test/linter/test_embertemplatelint.vader17
-rw-r--r--test/linter/test_erb.vader16
-rw-r--r--test/linter/test_erlang_dialyzer.vader45
-rw-r--r--test/linter/test_erlang_elvis.vader16
-rw-r--r--test/linter/test_erlang_erlc.vader40
-rw-r--r--test/linter/test_erlang_syntaxerl.vader45
-rw-r--r--test/linter/test_erubi.vader32
-rw-r--r--test/linter/test_erubis.vader16
-rw-r--r--test/linter/test_eslint.vader76
-rw-r--r--test/linter/test_fecs.vader9
-rw-r--r--test/linter/test_flake8.vader201
-rw-r--r--test/linter/test_flow.vader42
-rw-r--r--test/linter/test_foodcritic.vader18
-rw-r--r--test/linter/test_fortran_fortls.vader18
-rw-r--r--test/linter/test_fsc.vader13
-rw-r--r--test/linter/test_fusionlint.vader19
-rw-r--r--test/linter/test_gawk.vader25
-rw-r--r--test/linter/test_gfortran.vader24
-rw-r--r--test/linter/test_ghdl.vader19
-rw-r--r--test/linter/test_gitlint.vader43
-rw-r--r--test/linter/test_glslang.vader19
-rw-r--r--test/linter/test_glslls.vader19
-rw-r--r--test/linter/test_gobuild.vader33
-rw-r--r--test/linter/test_gofmt.vader26
-rw-r--r--test/linter/test_golangci_lint.vader50
-rw-r--r--test/linter/test_golangserver.vader76
-rw-r--r--test/linter/test_golint.vader30
-rw-r--r--test/linter/test_gometalinter.vader49
-rw-r--r--test/linter/test_gopls.vader77
-rw-r--r--test/linter/test_gosimple.vader19
-rw-r--r--test/linter/test_gotype.vader24
-rw-r--r--test/linter/test_govet.vader32
-rw-r--r--test/linter/test_graphql_gqlint.vader9
-rw-r--r--test/linter/test_haml_hamllint.vader41
-rw-r--r--test/linter/test_haskell_cabal_ghc.vader13
-rw-r--r--test/linter/test_haskell_ghc.vader12
-rw-r--r--test/linter/test_haskell_ghc_mod.vader10
-rw-r--r--test/linter/test_haskell_hdevtools.vader16
-rw-r--r--test/linter/test_haskell_hie.vader27
-rw-r--r--test/linter/test_haskell_hlint.vader17
-rw-r--r--test/linter/test_haskell_hls.vader27
-rw-r--r--test/linter/test_haskell_stack_build.vader13
-rw-r--r--test/linter/test_haskell_stack_ghc.vader18
-rw-r--r--test/linter/test_hdl_checker_options.vader86
-rw-r--r--test/linter/test_html_stylelint.vader60
-rw-r--r--test/linter/test_htmlhint.vader51
-rw-r--r--test/linter/test_ibm_openapi_validator.vader15
-rw-r--r--test/linter/test_idris.vader21
-rw-r--r--test/linter/test_ink_ls.vader22
-rw-r--r--test/linter/test_inko_inko.vader20
-rw-r--r--test/linter/test_ispc_ispc.vader20
-rw-r--r--test/linter/test_iverilog.vader14
-rw-r--r--test/linter/test_javac.vader326
-rw-r--r--test/linter/test_javalsp.vader80
-rw-r--r--test/linter/test_javascript_tsserver.vader16
-rw-r--r--test/linter/test_jq.vader8
-rw-r--r--test/linter/test_jscs.vader15
-rw-r--r--test/linter/test_jshint.vader17
-rw-r--r--test/linter/test_julia_languageserver.vader30
-rw-r--r--test/linter/test_kotlin_languageserver.vader23
-rw-r--r--test/linter/test_kotlinc.vader9
-rw-r--r--test/linter/test_languagetool.vader22
-rw-r--r--test/linter/test_less_stylelint.vader31
-rw-r--r--test/linter/test_lessc.vader46
-rw-r--r--test/linter/test_lintr.vader34
-rw-r--r--test/linter/test_llc.vader21
-rw-r--r--test/linter/test_luac.vader13
-rw-r--r--test/linter/test_luacheck.vader23
-rw-r--r--test/linter/test_markdown_markdownlint.vader13
-rw-r--r--test/linter/test_markdown_mdl.vader19
-rw-r--r--test/linter/test_markdown_vale.vader32
-rw-r--r--test/linter/test_mercury_mmc.vader22
-rw-r--r--test/linter/test_mypy.vader90
-rw-r--r--test/linter/test_nagelfar.vader19
-rw-r--r--test/linter/test_nasm_nasm.vader32
-rw-r--r--test/linter/test_nimlsp.vader12
-rw-r--r--test/linter/test_objc_ccls.vader66
-rw-r--r--test/linter/test_ocaml_ocamllsp.vader29
-rw-r--r--test/linter/test_ocaml_ols.vader40
-rw-r--r--test/linter/test_perl.vader14
-rw-r--r--test/linter/test_perl6.vader14
-rw-r--r--test/linter/test_perlcritic.vader36
-rw-r--r--test/linter/test_php.vader15
-rw-r--r--test/linter/test_php_intelephense.vader26
-rw-r--r--test/linter/test_php_langserver.vader30
-rw-r--r--test/linter/test_phpcs.vader42
-rw-r--r--test/linter/test_phpmd.vader12
-rw-r--r--test/linter/test_phpstan.vader85
-rw-r--r--test/linter/test_pony_ponyc.vader12
-rw-r--r--test/linter/test_prospector.vader20
-rw-r--r--test/linter/test_proto.vader16
-rw-r--r--test/linter/test_psalm.vader38
-rw-r--r--test/linter/test_puglint.vader48
-rw-r--r--test/linter/test_purescript_ls.vader31
-rw-r--r--test/linter/test_pycodestyle.vader33
-rw-r--r--test/linter/test_pydocstyle.vader33
-rw-r--r--test/linter/test_pyflakes.vader46
-rw-r--r--test/linter/test_pylama.vader76
-rw-r--r--test/linter/test_pylint.vader81
-rw-r--r--test/linter/test_pyls.vader57
-rw-r--r--test/linter/test_pyre.vader46
-rw-r--r--test/linter/test_pyrex_cython.vader30
-rw-r--r--test/linter/test_pyright.vader116
-rw-r--r--test/linter/test_qmlfmt.vader13
-rw-r--r--test/linter/test_r_languageserver.vader22
-rw-r--r--test/linter/test_racket_raco.vader10
-rw-r--r--test/linter/test_rails_best_practices.vader42
-rw-r--r--test/linter/test_reason_ls.vader21
-rw-r--r--test/linter/test_reason_ols.vader41
-rw-r--r--test/linter/test_reek.vader49
-rw-r--r--test/linter/test_remark_lint.vader37
-rw-r--r--test/linter/test_revive.vader30
-rw-r--r--test/linter/test_rnix.vader12
-rw-r--r--test/linter/test_rst_textlint.vader65
-rw-r--r--test/linter/test_rubocop.vader26
-rw-r--r--test/linter/test_ruby.vader13
-rw-r--r--test/linter/test_ruby_debride.vader8
-rw-r--r--test/linter/test_ruby_solargraph.vader43
-rw-r--r--test/linter/test_rust_analyzer.vader20
-rw-r--r--test/linter/test_rust_rls.vader30
-rw-r--r--test/linter/test_rustc.vader21
-rw-r--r--test/linter/test_ruumba.vader26
-rw-r--r--test/linter/test_sass_sasslint.vader43
-rw-r--r--test/linter/test_scala_metals.vader21
-rw-r--r--test/linter/test_scala_sbtserver.vader23
-rw-r--r--test/linter/test_scalac.vader13
-rw-r--r--test/linter/test_scalastyle.vader34
-rw-r--r--test/linter/test_scss_sasslint.vader43
-rw-r--r--test/linter/test_scss_stylelint.vader31
-rw-r--r--test/linter/test_shellcheck.vader106
-rw-r--r--test/linter/test_slimlint.vader19
-rw-r--r--test/linter/test_solc.vader13
-rw-r--r--test/linter/test_sorbet.vader34
-rw-r--r--test/linter/test_spectral.vader31
-rw-r--r--test/linter/test_sqllint.vader12
-rw-r--r--test/linter/test_standard.vader43
-rw-r--r--test/linter/test_standardrb.vader26
-rw-r--r--test/linter/test_standardts.vader43
-rw-r--r--test/linter/test_staticcheck.vader35
-rw-r--r--test/linter/test_sugarss_stylelint.vader31
-rw-r--r--test/linter/test_svelteserver.vader8
-rw-r--r--test/linter/test_swaglint.vader29
-rw-r--r--test/linter/test_swift_sourcekitlsp.vader21
-rw-r--r--test/linter/test_swift_swiftformat.vader25
-rw-r--r--test/linter/test_swiftlint.vader43
-rw-r--r--test/linter/test_systemd_analyze.vader9
-rw-r--r--test/linter/test_terraform_ls.vader61
-rw-r--r--test/linter/test_terraform_lsp.vader48
-rw-r--r--test/linter/test_terraform_terraform.vader15
-rw-r--r--test/linter/test_terraform_tflint.vader28
-rw-r--r--test/linter/test_tex_lacheck.vader13
-rw-r--r--test/linter/test_tex_textlint.vader65
-rw-r--r--test/linter/test_texlab.vader30
-rw-r--r--test/linter/test_textlint.vader65
-rw-r--r--test/linter/test_thrift.vader53
-rw-r--r--test/linter/test_tslint.vader23
-rw-r--r--test/linter/test_typescript_deno_lsp.vader43
-rw-r--r--test/linter/test_typescript_tsserver.vader8
-rw-r--r--test/linter/test_vcom.vader19
-rw-r--r--test/linter/test_verilator.vader14
-rw-r--r--test/linter/test_vim_vimls.vader76
-rw-r--r--test/linter/test_vint.vader34
-rw-r--r--test/linter/test_vlog.vader19
-rw-r--r--test/linter/test_vulture.vader58
-rw-r--r--test/linter/test_write_good.vader55
-rw-r--r--test/linter/test_xmllint.vader20
-rw-r--r--test/linter/test_xo.vader23
-rw-r--r--test/linter/test_xots.vader23
-rw-r--r--test/linter/test_xvhdl.vader19
-rw-r--r--test/linter/test_xvlog.vader19
-rw-r--r--test/linter/test_yang_lsp.vader12
-rw-r--r--test/linter/test_zig_zls.vader15
225 files changed, 8200 insertions, 0 deletions
diff --git a/test/linter/test_ada_gcc.vader b/test/linter/test_ada_gcc.vader
new file mode 100644
index 00000000..906b31a4
--- /dev/null
+++ b/test/linter/test_ada_gcc.vader
@@ -0,0 +1,42 @@
+Before:
+ call ale#assert#SetUpLinterTest('ada', 'gcc')
+ call ale#test#SetFilename('dummy.adb')
+
+ function! GetOutputDir(command) abort
+ let l:split_command = split(a:command)
+ let l:index = index(l:split_command, '-o')
+ return l:split_command[l:index + 1]
+ endfunction
+
+ let b:out_file = GetOutputDir(ale_linters#ada#gcc#GetCommand(bufnr('')))
+
+After:
+ delfunction GetOutputDir
+
+ unlet! b:out_file
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc') . ' -x ada -c -gnatc'
+ \ . ' -o ' . b:out_file
+ \ . ' -I %s:h'
+ \ . ' -gnatwa -gnatq %t'
+
+ let b:ale_ada_gcc_executable = 'foo'
+
+ AssertLinter 'foo',
+ \ ale#Escape('foo') . ' -x ada -c -gnatc'
+ \ . ' -o ' . b:out_file
+ \ . ' -I %s:h'
+ \ . ' -gnatwa -gnatq %t'
+
+Execute(The options should be configurable):
+ let g:ale_ada_gcc_options = '--foo --bar'
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc') . ' -x ada -c -gnatc'
+ \ . ' -o ' . b:out_file
+ \ . ' -I %s:h'
+ \ . ' --foo --bar %t'
diff --git a/test/linter/test_adals.vader b/test/linter/test_adals.vader
new file mode 100644
index 00000000..5a04594e
--- /dev/null
+++ b/test/linter/test_adals.vader
@@ -0,0 +1,17 @@
+Before:
+ call ale#assert#SetUpLinterTest('ada', 'adals')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Sets adals executable):
+ let g:ale_ada_adals_executable = '/path/to /Ada'
+ AssertLinter '/path/to /Ada', ale#Escape('/path/to /Ada')
+
+Execute(Sets adals encoding):
+ let b:ale_ada_adals_encoding = 'iso-8859-1'
+ AssertLSPConfig {'ada.defaultCharset': 'iso-8859-1', 'ada.projectFile': 'default.gpr'}
+
+Execute(Sets adals project):
+ let g:ale_ada_adals_project = 'myproject.gpr'
+ AssertLSPConfig {'ada.defaultCharset': 'utf-8', 'ada.projectFile': 'myproject.gpr'}
diff --git a/test/linter/test_alex.vader b/test/linter/test_alex.vader
new file mode 100644
index 00000000..20e20301
--- /dev/null
+++ b/test/linter/test_alex.vader
@@ -0,0 +1,34 @@
+Before:
+ call ale#assert#SetUpLinterTest('tex', 'alex')
+ call ale#test#SetFilename('test_file.tex')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The global executable should be used when the local one cannot be found):
+ AssertLinter 'alex',
+ \ ale#Escape('alex') . ' %s --text',
+
+Execute(Should use the node_modules/.bin executable, if available):
+ call ale#test#SetFilename('../test-files/alex/node-modules/test_file.tex')
+
+ AssertLinter ale#path#Simplify(g:dir . '/../test-files/alex/node-modules/node_modules/.bin/alex'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/alex/node-modules/node_modules/.bin/alex'))
+ \ . ' %s --text',
+
+Execute(Should use the node_modules/alex executable, if available):
+ call ale#test#SetFilename('../test-files/alex/node-modules-2/test_file.tex')
+
+ AssertLinter ale#path#Simplify(g:dir . '/../test-files/alex/node-modules-2/node_modules/alex/cli.js'),
+ \ (has('win32') ? 'node.exe ' : '')
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/alex/node-modules-2/node_modules/alex/cli.js'))
+ \ . ' %s --text',
+
+Execute(Should let users configure a global executable and override local paths):
+ call ale#test#SetFilename('../test-files/write-good/node-modules-2/test_file.tex')
+
+ let g:ale_alex_executable = '/path/to/custom/alex'
+ let g:ale_alex_use_global = 1
+
+ AssertLinter '/path/to/custom/alex',
+ \ ale#Escape('/path/to/custom/alex') . ' %s --text'
diff --git a/test/linter/test_ameba.vader b/test/linter/test_ameba.vader
new file mode 100644
index 00000000..7746b44f
--- /dev/null
+++ b/test/linter/test_ameba.vader
@@ -0,0 +1,20 @@
+Before:
+ call ale#assert#SetUpLinterTest('crystal', 'ameba')
+ call ale#test#SetFilename('dummy.cr')
+
+ let g:ale_crystal_ameba_executable = 'bin/ameba'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to bin/ameba):
+ AssertLinter 'bin/ameba', ale#Escape('bin/ameba')
+ \ . ' --format json '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.cr'))
+
+Execute(Should be able to set a custom executable):
+ let g:ale_crystal_ameba_executable = 'ameba'
+
+ AssertLinter 'ameba' , ale#Escape('ameba')
+ \ . ' --format json '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.cr'))
diff --git a/test/linter/test_angular.vader b/test/linter/test_angular.vader
new file mode 100644
index 00000000..fe0749a1
--- /dev/null
+++ b/test/linter/test_angular.vader
@@ -0,0 +1,44 @@
+Before:
+ call ale#assert#SetUpLinterTest('html', 'angular')
+ let g:paths = {}
+
+After:
+ call ale#assert#TearDownLinterTest()
+ unlet g:paths
+
+Execute(The Angular LSP connection shouldn't be created outside of Angular projects):
+ AssertLSPLanguage 'html'
+ AssertLSPConfig {}
+ AssertLSPProject ''
+ AssertLinterNotExecuted
+
+Execute(The default command for Angular should be correct):
+ call ale#test#SetFilename('../test-files/angular/test.html')
+ let g:paths = {
+ \ 'ngserver': ale#test#GetFilename('../test-files/angular/node_modules/@angular/language-server/bin/ngserver'),
+ \ 'service': ale#test#GetFilename('../test-files/angular/node_modules/@angular/language-service'),
+ \ 'typescript': ale#test#GetFilename('../test-files/angular/node_modules/typescript'),
+ \}
+
+ AssertLSPLanguage 'html'
+ AssertLSPProject ale#test#GetFilename('../test-files/angular')
+ AssertLinter g:paths.ngserver, ale#Escape(g:paths.ngserver)
+ \ . ' --ngProbeLocations ' . ale#Escape(g:paths.service)
+ \ . ' --tsProbeLocations ' . ale#Escape(g:paths.typescript)
+ \ . ' --stdio'
+
+Execute(It should be possible to use the global ngserver):
+ let b:ale_html_angular_use_global = 1
+
+ call ale#test#SetFilename('../test-files/angular/test.html')
+ let g:paths = {
+ \ 'service': ale#test#GetFilename('../test-files/angular/node_modules/@angular/language-service'),
+ \ 'typescript': ale#test#GetFilename('../test-files/angular/node_modules/typescript'),
+ \}
+
+ AssertLSPLanguage 'html'
+ AssertLSPProject ale#test#GetFilename('../test-files/angular')
+ AssertLinter 'ngserver', ale#Escape('ngserver')
+ \ . ' --ngProbeLocations ' . ale#Escape(g:paths.service)
+ \ . ' --tsProbeLocations ' . ale#Escape(g:paths.typescript)
+ \ . ' --stdio'
diff --git a/test/linter/test_ansible_lint.vader b/test/linter/test_ansible_lint.vader
new file mode 100644
index 00000000..a3fbde23
--- /dev/null
+++ b/test/linter/test_ansible_lint.vader
@@ -0,0 +1,22 @@
+Before:
+ call ale#assert#SetUpLinterTest('ansible', 'ansible_lint')
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+ call ale#assert#TearDownLinterTest()
+
+Execute(The ansible_lint version <5.0.0 command callback should return default string):
+ GivenCommandOutput ['v4.1.2']
+ AssertLinter 'ansible-lint', ale#Escape('ansible-lint') . ' -p %t'
+
+Execute(The ansible_lint version >=5.0.0 command callback should return default string):
+ GivenCommandOutput ['v5.1.2']
+ AssertLinter 'ansible-lint', ale#Escape('ansible-lint') . ' --parseable-severity -x yaml'
+
+Execute(The ansible_lint executable should be configurable):
+ let g:ale_ansible_ansible_lint_executable = '~/.local/bin/ansible-lint'
+ GivenCommandOutput ['v4.1.2']
+ AssertLinter '~/.local/bin/ansible-lint',
+ \ ale#Escape('~/.local/bin/ansible-lint') . ' -p %t'
diff --git a/test/linter/test_asciidoc_textlint.vader b/test/linter/test_asciidoc_textlint.vader
new file mode 100644
index 00000000..a79a0ae3
--- /dev/null
+++ b/test/linter/test_asciidoc_textlint.vader
@@ -0,0 +1,65 @@
+" Author: januswel, w0rp
+
+Before:
+ " This is just one language for the linter.
+ call ale#assert#SetUpLinterTest('asciidoc', 'textlint')
+
+ " The configuration is shared between many languages.
+ Save g:ale_textlint_executable
+ Save g:ale_textlint_use_global
+ Save g:ale_textlint_options
+
+ let g:ale_textlint_executable = 'textlint'
+ let g:ale_textlint_use_global = 0
+ let g:ale_textlint_options = ''
+
+ unlet! b:ale_textlint_executable
+ unlet! b:ale_textlint_use_global
+ unlet! b:ale_textlint_options
+
+After:
+ unlet! b:command_tail
+ unlet! b:ale_textlint_executable
+ unlet! b:ale_textlint_use_global
+ unlet! b:ale_textlint_options
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'textlint',
+ \ ale#Escape('textlint') . ' -f json --stdin --stdin-filename %s'
+
+Execute(The executable should be configurable):
+ let b:ale_textlint_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -f json --stdin --stdin-filename %s'
+
+Execute(The options should be configurable):
+ let b:ale_textlint_options = '--something'
+
+ AssertLinter 'textlint',
+ \ ale#Escape('textlint') . ' --something -f json --stdin --stdin-filename %s'
+
+Execute(The local executable from .bin should be used if available):
+ call ale#test#SetFilename('../test-files/textlint/with_bin_path/foo.txt')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_bin_path/node_modules/.bin/textlint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_bin_path/node_modules/.bin/textlint'))
+ \ . ' -f json --stdin --stdin-filename %s'
+
+Execute(The local executable from textlint/bin should be used if available):
+ call ale#test#SetFilename('../test-files/textlint/with_textlint_bin_path/foo.txt')
+
+ if has('win32')
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'),
+ \ ale#Escape('node.exe') . ' ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'))
+ \ . ' -f json --stdin --stdin-filename %s'
+ else
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'))
+ \ . ' -f json --stdin --stdin-filename %s'
+ endif
diff --git a/test/linter/test_asm_gcc.vader b/test/linter/test_asm_gcc.vader
new file mode 100644
index 00000000..5976b5f2
--- /dev/null
+++ b/test/linter/test_asm_gcc.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('asm', 'gcc')
+ call ale#test#SetFilename('test.cpp')
+ let b:command_tail = ' -x assembler'
+ \ . ' -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . '-iquote %s:h'
+ \ . ' -Wall -'
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'gcc', ale#Escape('gcc') . b:command_tail
+
+ let b:ale_asm_gcc_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail
diff --git a/test/linter/test_bandit.vader b/test/linter/test_bandit.vader
new file mode 100644
index 00000000..3d3a60a3
--- /dev/null
+++ b/test/linter/test_bandit.vader
@@ -0,0 +1,71 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'bandit')
+ let b:bandit_flags = ' --format custom '
+ \ . '--msg-template "{line}:{test_id}:{severity}:{msg}" '
+
+After:
+ call ale#assert#TearDownLinterTest()
+ unlet! b:bandit_flags
+
+Execute(The bandit command callback should return default string):
+ AssertLinter 'bandit',
+ \ ale#Escape('bandit')
+ \ . b:bandit_flags
+ \ . ' -'
+
+Execute(The bandit command callback should allow options):
+ let g:ale_python_bandit_options = '--configfile bandit.yaml'
+
+ AssertLinter 'bandit',
+ \ ale#Escape('bandit')
+ \ . b:bandit_flags
+ \ . ' --configfile bandit.yaml -'
+
+Execute(The bandit executable should be configurable):
+ let g:ale_python_bandit_executable = '~/.local/bin/bandit'
+
+ AssertLinter '~/.local/bin/bandit',
+ \ ale#Escape('~/.local/bin/bandit')
+ \ . b:bandit_flags
+ \ . ' -'
+
+Execute(Setting executable to 'pipenv' appends 'run bandit'):
+ let g:ale_python_bandit_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv')
+ \ . ' run bandit'
+ \ . b:bandit_flags
+ \ . ' -'
+
+Execute(Pipenv is detected when python_bandit_auto_pipenv is set):
+ let g:ale_python_bandit_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv')
+ \ . ' run bandit'
+ \ . b:bandit_flags
+ \ . ' -'
+
+Execute(The bandit command callback should add .bandit by default):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_bandit/namespace/foo/bar.py')
+
+ let b:config_path = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_bandit/.bandit'
+ \)
+
+ AssertLinter 'bandit',
+ \ ale#Escape('bandit')
+ \ . ' --ini ' . ale#Escape(b:config_path)
+ \ . b:bandit_flags
+ \ . ' -'
+
+Execute(The bandit command callback should support not using .bandit):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_bandit/subdir/foo/bar.py')
+ let g:ale_python_bandit_use_config = 0
+
+ AssertLinter 'bandit',
+ \ ale#Escape('bandit')
+ \ . b:bandit_flags
+ \ . ' -'
diff --git a/test/linter/test_bashate.vader b/test/linter/test_bashate.vader
new file mode 100644
index 00000000..714cf690
--- /dev/null
+++ b/test/linter/test_bashate.vader
@@ -0,0 +1,15 @@
+Before:
+ call ale#assert#SetUpLinterTest('sh', 'bashate')
+ call ale#test#SetFilename('test.sh')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default bashate command should be correct):
+ AssertLinter 'bashate', ale#Escape('bashate') . ' %t'
+
+Execute(The bashate command should accept options):
+ let b:ale_sh_bashate_options = '-i E310 --max-line-length 100'
+
+ AssertLinter 'bashate',
+ \ ale#Escape('bashate') . ' -i E310 --max-line-length 100 %t'
diff --git a/test/linter/test_bib_bibclean.vader b/test/linter/test_bib_bibclean.vader
new file mode 100644
index 00000000..fa6f7d33
--- /dev/null
+++ b/test/linter/test_bib_bibclean.vader
@@ -0,0 +1,24 @@
+Before:
+ call ale#assert#SetUpLinterTest('bib', 'bibclean')
+
+ let g:ale_ruby_rubocop_executable = 'bibclean'
+ let g:ale_ruby_rubocop_options = ''
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to bibclean):
+ AssertLinter 'bibclean', ale#Escape('bibclean')
+ \ . ' -file-position '
+
+Execute(Should be able to set a custom executable):
+ let g:ale_bib_bibclean_executable = 'bin/bibclean'
+
+ AssertLinter 'bin/bibclean' , ale#Escape('bin/bibclean')
+ \ . ' -file-position '
+
+Execute(Should not include custom options):
+ let g:ale_bib_bibclean_options = '-no-prettryprint'
+
+ AssertLinter 'bibclean' , ale#Escape('bibclean')
+ \ . ' -file-position '
diff --git a/test/linter/test_bingo.vader b/test/linter/test_bingo.vader
new file mode 100644
index 00000000..d8328414
--- /dev/null
+++ b/test/linter/test_bingo.vader
@@ -0,0 +1,74 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'bingo')
+
+After:
+ Restore
+
+ if isdirectory(g:dir . '/.git')
+ call delete(g:dir . '/.git', 'd')
+ endif
+
+ unlet! b:ale_completion_enabled
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set correct defaults):
+ AssertLinter 'bingo', ale#Escape('bingo') . ' --mode stdio'
+
+Execute(should configure bingo callback executable):
+ let b:ale_go_bingo_executable = 'boo'
+ let b:ale_go_bingo_options = ''
+
+ AssertLinter 'boo', ale#Escape('boo')
+
+Execute(should set bingo options):
+ call ale#test#SetFilename('../test-files/go/go1/prj1/file.go')
+ " let b:ale_completion_enabled = 1
+ let b:ale_go_bingo_options = ''
+
+ AssertLinter 'bingo',
+ \ ale#Escape('bingo') . ''
+
+ let b:ale_go_bingo_options = '--mode stdio --trace'
+
+ AssertLinter 'bingo',
+ \ ale#Escape('bingo') . ' --mode stdio --trace'
+
+Execute(should support Go environment variables):
+ call ale#test#SetFilename('../test-files/go/go1/prj1/file.go')
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'bingo',
+ \ ale#Env('GO111MODULE', 'on') . ale#Escape('bingo') . ' --mode stdio'
+
+
+Execute(Should return directory for 'go.mod' if found in parent directory):
+ call ale#test#SetFilename('../test-files/go/test.go')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/go')
+
+Execute(Should return nearest directory with '.git' if found in parent directory):
+ call ale#test#SetFilename('test.go')
+ call mkdir(g:dir . '/.git')
+
+ AssertLSPProject g:dir
+
+Execute(Should ignore 'go.mod' and return '.git' dir if modules off):
+ call ale#test#SetFilename('../test-files/go/test.go')
+
+ let b:ale_go_go111module = 'off'
+ let b:parent_dir = ale#path#Simplify(g:dir . '/..')
+ let b:git_dir = b:parent_dir . '/.git'
+
+ if !isdirectory(b:git_dir)
+ call mkdir(b:git_dir)
+ endif
+
+ AssertLSPProject b:parent_dir
+
+ call delete(b:git_dir, 'd')
+ unlet! b:parent_dir
+ unlet! b:git_dir
diff --git a/test/linter/test_brakeman.vader b/test/linter/test_brakeman.vader
new file mode 100644
index 00000000..d3bf1920
--- /dev/null
+++ b/test/linter/test_brakeman.vader
@@ -0,0 +1,37 @@
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'brakeman')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The brakeman command callback should detect absence of a valid Rails app):
+ call ale#test#SetFilename('../test-files/ruby/not_a_rails_app/test.rb')
+
+ AssertLinter 'brakeman', ''
+
+Execute(The brakeman command callback should find a valid Rails app root):
+ call ale#test#SetFilename('../test-files/ruby/valid_rails_app/db/test.rb')
+
+ AssertLinter 'brakeman', ale#Escape('brakeman')
+ \ . ' -f json -q -p '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/ruby/valid_rails_app'))
+
+Execute(The brakeman command callback should include configured options):
+ call ale#test#SetFilename('../test-files/ruby/valid_rails_app/db/test.rb')
+
+ let g:ale_ruby_brakeman_options = '--combobulate'
+
+ AssertLinter 'brakeman', ale#Escape('brakeman')
+ \ . ' -f json -q --combobulate -p '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/ruby/valid_rails_app'))
+
+Execute(Setting bundle appends 'exec brakeman'):
+ call ale#test#SetFilename('../test-files/ruby/valid_rails_app/db/test.rb')
+
+ let g:ale_ruby_brakeman_executable = 'bundle'
+ let g:ale_ruby_brakeman_options = '--combobulate'
+
+ AssertLinter 'bundle', ale#Escape('bundle')
+ \ . ' exec brakeman'
+ \ . ' -f json -q --combobulate -p '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/ruby/valid_rails_app'))
diff --git a/test/linter/test_c_cc.vader b/test/linter/test_c_cc.vader
new file mode 100644
index 00000000..c8c2de7d
--- /dev/null
+++ b/test/linter/test_c_cc.vader
@@ -0,0 +1,55 @@
+Before:
+ Save g:ale_c_parse_makefile
+ Save g:ale_history_enabled
+
+ let g:ale_c_parse_makefile = 0
+ let g:ale_history_enabled = 0
+
+ let g:get_cflags_return_value = ''
+ let g:executable_map = {}
+
+ runtime autoload/ale/c.vim
+ runtime autoload/ale/engine.vim
+
+ function! ale#engine#IsExecutable(buffer, executable) abort
+ return has_key(g:executable_map, a:executable)
+ endfunction
+
+ function! ale#c#GetCFlags(buffer, output) abort
+ return g:get_cflags_return_value
+ endfunction
+
+ call ale#assert#SetUpLinterTest('c', 'cc')
+
+ let b:command_tail = ' -S -x c'
+ \ . ' -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -std=c11 -Wall -'
+
+After:
+ unlet! g:get_cflags_return_value
+ unlet! g:executable_map
+ unlet! b:command_tail
+
+ runtime autoload/ale/c.vim
+ runtime autoload/ale/engine.vim
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(clang should be used instead of gcc, if available):
+ let g:executable_map = {'clang': 1}
+
+ AssertLinter 'clang', [ale#Escape('clang') . b:command_tail]
+
+Execute(The executable should be configurable):
+ AssertLinter 'gcc', [ale#Escape('gcc') . b:command_tail]
+
+ let b:ale_c_cc_executable = 'foobar'
+
+ AssertLinter 'foobar', [ale#Escape('foobar') . b:command_tail]
+
+Execute(The -std flag should be replaced by parsed C flags):
+ let b:command_tail = substitute(b:command_tail, 'c11', 'c99 ', '')
+ let g:get_cflags_return_value = '-std=c99'
+
+ AssertLinter 'gcc', ale#Escape('gcc') . b:command_tail
diff --git a/test/linter/test_c_ccls.vader b/test/linter/test_c_ccls.vader
new file mode 100644
index 00000000..a4f575c6
--- /dev/null
+++ b/test/linter/test_c_ccls.vader
@@ -0,0 +1,69 @@
+" Author: Ye Jingchen <ye.jingchen@gmail.com>, Ben Falconer <ben@falconers.me.uk>
+" Description: A language server for C
+
+Before:
+ call ale#assert#SetUpLinterTest('c', 'ccls')
+
+ Save b:ale_c_build_dir_names
+ Save b:ale_c_ccls_executable
+ Save b:ale_c_ccls_init_options
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The project root should be detected correctly using compile_commands.json file):
+ call ale#test#SetFilename(tempname() . '/dummy.c')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_compile_commands_json/dummy.c')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_compile_commands_json')
+
+Execute(The project root should be detected correctly using .ccls file):
+ call ale#test#SetFilename(tempname() . '/dummy.c')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_ccls/dummy.c')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_ccls')
+
+Execute(The project root should be detected correctly using .ccls-root file):
+ call ale#test#SetFilename(tempname() . '/dummy.c')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_ccls-root/dummy.c')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_ccls-root')
+
+Execute(The executable should be configurable):
+ AssertLinter 'ccls', ale#Escape('ccls')
+
+ let b:ale_c_ccls_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+
+Execute(The initialization options should be configurable):
+ AssertLSPOptions {}
+
+ let b:ale_c_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' }
+
+ AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' }
+
+Execute(The compile command database should be detected correctly):
+ call ale#test#SetFilename('../test-files/ccls/with_ccls/dummy.c')
+
+ AssertLSPOptions {}
+
+ call ale#test#SetFilename('../test-files/ccls/with_compile_commands_json/dummy.c')
+
+ AssertLSPOptions { 'compilationDatabaseDirectory':
+ \ ale#path#Simplify(g:dir . '/../test-files/ccls/with_compile_commands_json') }
+
+ call ale#test#SetFilename('../test-files/ccls/with_build_dir/dummy.c')
+ let b:ale_c_build_dir_names = ['unusual_build_dir_name']
+
+ AssertLSPOptions { 'compilationDatabaseDirectory':
+ \ ale#path#Simplify(g:dir . '/../test-files/ccls/with_build_dir/unusual_build_dir_name') }
diff --git a/test/linter/test_c_clang_tidy.vader b/test/linter/test_c_clang_tidy.vader
new file mode 100644
index 00000000..c4433550
--- /dev/null
+++ b/test/linter/test_c_clang_tidy.vader
@@ -0,0 +1,77 @@
+Before:
+ Save g:ale_c_parse_makefile
+ let g:ale_c_parse_makefile = 0
+
+ call ale#assert#SetUpLinterTest('c', 'clangtidy')
+ call ale#test#SetFilename('test.c')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The clangtidy command default should be correct):
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy') . ' %s'
+
+Execute(You should be able to remove the -checks option for clang-tidy):
+ let b:ale_c_clangtidy_checks = []
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy') . ' %s'
+
+Execute(You should be able to set other checks for clang-tidy):
+ let b:ale_c_clangtidy_checks = ['-*', 'clang-analyzer-*']
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s'
+
+Execute(You should be able to manually set compiler flags for clang-tidy):
+ let b:ale_c_clangtidy_checks = ['*']
+ let b:ale_c_clangtidy_options = '-Wall'
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall'
+
+Execute(You should be able to manually set flags for clang-tidy):
+ let b:ale_c_clangtidy_extra_options = '-config='
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy') . ' ' . ale#Escape('-config=') . ' %s'
+
+Execute(The build directory should be configurable):
+ let b:ale_c_clangtidy_checks = ['*']
+ let b:ale_c_build_dir = '/foo/bar'
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('*') . ' %s'
+ \ . ' -p ' . ale#Escape('/foo/bar')
+
+Execute(The build directory setting should override the options):
+ let b:ale_c_clangtidy_checks = ['*']
+ let b:ale_c_build_dir = '/foo/bar'
+ let b:ale_c_clangtidy_options = '-Wall'
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('*') . ' %s'
+ \ . ' -p ' . ale#Escape('/foo/bar')
+
+Execute(The build directory should be used for header files):
+ call ale#test#SetFilename('test.h')
+
+ let b:ale_c_clangtidy_checks = ['*']
+ let b:ale_c_build_dir = '/foo/bar'
+ let b:ale_c_clangtidy_options = '-Wall'
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('*') . ' %s'
+ \ . ' -p ' . ale#Escape('/foo/bar')
+
+Execute(The executable should be configurable):
+ let b:ale_c_clangtidy_checks = ['*']
+ let b:ale_c_clangtidy_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -checks=' . ale#Escape('*') . ' %s'
diff --git a/test/linter/test_c_clangd.vader b/test/linter/test_c_clangd.vader
new file mode 100644
index 00000000..b7a4e029
--- /dev/null
+++ b/test/linter/test_c_clangd.vader
@@ -0,0 +1,47 @@
+Before:
+ call ale#assert#SetUpLinterTest('c', 'clangd')
+
+ Save b:ale_c_clangd_options
+ Save b:ale_c_build_dir
+ Save b:ale_c_build_dir_names
+ Save b:ale_c_parse_compile_commands
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The language string should be correct):
+ AssertLSPLanguage 'c'
+
+Execute(The default executable should be correct):
+ AssertLinter 'clangd', ale#Escape('clangd')
+
+Execute(The project root should be detected correctly):
+ call ale#test#SetFilename(tempname() . '/dummy.c')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/clangd/with_compile_commands/dummy.c')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/clangd/with_compile_commands')
+
+Execute(The executable should be configurable):
+ let g:ale_c_clangd_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+
+Execute(The options should be configurable):
+ let b:ale_c_clangd_options = '-compile-commands-dir=foo'
+
+ AssertLinter 'clangd', ale#Escape('clangd') . ' ' . b:ale_c_clangd_options
+
+Execute(The compile command database should be detected correctly):
+ call ale#test#SetFilename('../test-files/clangd/with_build_dir/dummy_src/dummy.c')
+
+ let b:ale_c_clangd_options = ''
+ let b:ale_c_build_dir = ''
+ let b:ale_c_build_dir_names = ['unusual_build_dir_name']
+ let b:ale_c_parse_compile_commands = 1
+
+ AssertLinter 'clangd', ale#Escape('clangd')
+ \ . ' -compile-commands-dir='
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/clangd/with_build_dir/unusual_build_dir_name'))
diff --git a/test/linter/test_c_cppcheck.vader b/test/linter/test_c_cppcheck.vader
new file mode 100644
index 00000000..c84053f8
--- /dev/null
+++ b/test/linter/test_c_cppcheck.vader
@@ -0,0 +1,46 @@
+Before:
+ call ale#assert#SetUpLinterTest('c', 'cppcheck')
+ let b:command_tail = ' -q --language=c --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}') . ' --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
+
+After:
+ unlet! b:command_tail
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'cppcheck', ale#Escape('cppcheck') . b:command_tail
+
+ let b:ale_c_cppcheck_executable = 'foobar'
+
+ AssertLinterCwd ''
+ AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail
+
+Execute(cppcheck for C should detect compile_commands.json files):
+ call ale#test#SetFilename('../test-files/cppcheck/one/foo.c')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/cppcheck/one')
+ AssertLinter 'cppcheck', ale#Escape('cppcheck')
+ \ . ' -q --language=c'
+ \ . ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
+ \ . ' --project=' . ale#Escape('compile_commands.json')
+ \ . ' --enable=style %t'
+
+Execute(cppcheck for C should detect compile_commands.json files in build directories):
+ call ale#test#SetFilename('../test-files/cppcheck/with_build_dir/foo.cpp')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/cppcheck/with_build_dir')
+ AssertLinter 'cppcheck', ale#Escape('cppcheck')
+ \ . ' -q --language=c'
+ \ . ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
+ \ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json'))
+ \ . ' --enable=style %t'
+
+Execute(cppcheck for C should include file dir if compile_commands.json file is not found):
+ call ale#test#SetFilename('../test-files/cppcheck/foo.cpp')
+
+ AssertLinter 'cppcheck',
+ \ ale#Escape('cppcheck')
+ \ . ' -q --language=c'
+ \ . ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
+ \ . ' --enable=style'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/cppcheck'))
+ \ . ' %t'
diff --git a/test/linter/test_c_cquery.vader b/test/linter/test_c_cquery.vader
new file mode 100644
index 00000000..bca0dbbc
--- /dev/null
+++ b/test/linter/test_c_cquery.vader
@@ -0,0 +1,37 @@
+Before:
+ call ale#assert#SetUpLinterTest('c', 'cquery')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The project root should be detected correctly using compile_commands.json file):
+ call ale#test#SetFilename(tempname() . '/dummy.c')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/cquery/dummy.c')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/cquery')
+
+Execute(The project root should be detected correctly using .cquery file):
+ call ale#test#SetFilename(tempname() . '/dummy.c')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/cquery/with_cquery/dummy.c')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/cquery/with_cquery')
+
+Execute(The executable should be configurable):
+ AssertLinter 'cquery', ale#Escape('cquery')
+
+ let b:ale_c_cquery_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+
+Execute(The cache directory should be configurable):
+ AssertLSPOptions {'cacheDirectory': expand('$HOME/.cache/cquery')}
+
+ let b:ale_c_cquery_cache_directory = '/foo/bar'
+
+ AssertLSPOptions {'cacheDirectory': '/foo/bar'}
diff --git a/test/linter/test_c_flawfinder.vader b/test/linter/test_c_flawfinder.vader
new file mode 100644
index 00000000..38385e2b
--- /dev/null
+++ b/test/linter/test_c_flawfinder.vader
@@ -0,0 +1,24 @@
+Before:
+ call ale#assert#SetUpLinterTest('c', 'flawfinder')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The flawfinder command should be correct):
+ AssertLinter 'flawfinder', ale#Escape('flawfinder') . ' -CDQS --minlevel=1 %t'
+
+Execute(The minlevel of flawfinder should be configurable):
+ let b:ale_c_flawfinder_minlevel = 8
+
+ AssertLinter 'flawfinder', ale#Escape('flawfinder') . ' -CDQS --minlevel=8 %t'
+
+Execute(Additional flawfinder options should be configurable):
+ let b:ale_c_flawfinder_options = '--foobar'
+
+ AssertLinter 'flawfinder',
+ \ ale#Escape('flawfinder') . ' -CDQS --foobar --minlevel=1 %t'
+
+Execute(The flawfinder exectable should be configurable):
+ let b:ale_c_flawfinder_executable = 'foo/bar'
+
+ AssertLinter 'foo/bar', ale#Escape('foo/bar') . ' -CDQS --minlevel=1 %t'
diff --git a/test/linter/test_c_import_paths.vader b/test/linter/test_c_import_paths.vader
new file mode 100644
index 00000000..19e39915
--- /dev/null
+++ b/test/linter/test_c_import_paths.vader
@@ -0,0 +1,162 @@
+Before:
+ " Make sure the c.vim file is loaded first.
+ call ale#c#FindProjectRoot(bufnr(''))
+
+ Save g:ale_c_parse_compile_commands
+ Save g:ale_c_parse_makefile
+ Save g:__ale_c_project_filenames
+
+ let g:original_project_filenames = g:__ale_c_project_filenames
+ let g:executable_map = {}
+
+ " Remove the .git/HEAD dir for C import paths for these tests.
+ " The tests run inside of a git repo.
+ let g:__ale_c_project_filenames = filter(
+ \ copy(g:__ale_c_project_filenames),
+ \ 'v:val isnot# ''.git/HEAD'''
+ \)
+
+ let g:ale_c_parse_compile_commands = 0
+ let g:ale_c_parse_makefile = 0
+
+ runtime autoload/ale/engine.vim
+
+ function! ale#engine#IsExecutable(buffer, executable) abort
+ return has_key(g:executable_map, a:executable)
+ endfunction
+
+After:
+ Restore
+
+ unlet! g:original_project_filenames
+ unlet! g:executable_map
+
+ runtime autoload/ale/engine.vim
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The C cc linter should include 'include' directories for projects with a Makefile):
+ call ale#assert#SetUpLinterTest('c', 'cc')
+ call ale#test#SetFilename('../test-files/c/makefile_project/subdir/file.c')
+ let g:ale_c_cc_options = ''
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc')
+ \ . ' -S -x c -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/makefile_project/include'))
+ \ . ' -'
+
+Execute(The C cc linter should include 'include' directories for projects with a configure file):
+ call ale#assert#SetUpLinterTest('c', 'cc')
+ call ale#test#SetFilename('../test-files/c/configure_project/subdir/file.c')
+ let g:ale_c_cc_options = ''
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc')
+ \ . ' -S -x c -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/configure_project/include'))
+ \ . ' -'
+
+Execute(The C cc linter should include root directories for projects with .h files in them):
+ call ale#assert#SetUpLinterTest('c', 'cc')
+ call ale#test#SetFilename('../test-files/c/h_file_project/subdir/file.c')
+ let g:ale_c_cc_options = ''
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc')
+ \ . ' -S -x c -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/h_file_project'))
+ \ . ' -'
+
+Execute(The C cc linter should include root directories for projects with .hpp files in them):
+ call ale#assert#SetUpLinterTest('c', 'cc')
+ call ale#test#SetFilename('../test-files/c/hpp_file_project/subdir/file.c')
+ let g:ale_c_cc_options = ''
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc')
+ \ . ' -S -x c -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/hpp_file_project'))
+ \ . ' -'
+
+Execute(The C ClangTidy handler should include 'include' directories for projects with a Makefile):
+ call ale#assert#SetUpLinterTest('c', 'clangtidy')
+ call ale#test#SetFilename('../test-files/c/makefile_project/subdir/file.cpp')
+ let g:ale_c_clangtidy_options = ''
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' %s '
+ \ . '-- -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/makefile_project/include'))
+
+Execute(The C++ cc linter should include 'include' directories for projects with a Makefile):
+ call ale#assert#SetUpLinterTest('cpp', 'cc')
+ call ale#test#SetFilename('../test-files/c/makefile_project/subdir/file.cpp')
+ let g:ale_cpp_cc_options = ''
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc')
+ \ . ' -S -x c++ -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/makefile_project/include'))
+ \ . ' -'
+
+Execute(The C++ cc linter should include 'include' directories for projects with a configure file):
+ call ale#assert#SetUpLinterTest('cpp', 'cc')
+ call ale#test#SetFilename('../test-files/c/configure_project/subdir/file.cpp')
+ let g:ale_cpp_cc_options = ''
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc')
+ \ . ' -S -x c++ -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/configure_project/include'))
+ \ . ' -'
+
+Execute(The C++ cc linter should include root directories for projects with .h files in them):
+ call ale#assert#SetUpLinterTest('cpp', 'cc')
+ call ale#test#SetFilename('../test-files/c/h_file_project/subdir/file.cpp')
+ let g:ale_cpp_cc_options = ''
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc')
+ \ . ' -S -x c++ -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/h_file_project'))
+ \ . ' -'
+
+Execute(The C++ cc linter should include root directories for projects with .hpp files in them):
+ call ale#assert#SetUpLinterTest('cpp', 'cc')
+ call ale#test#SetFilename('../test-files/c/hpp_file_project/subdir/file.cpp')
+ let g:ale_cpp_cc_options = ''
+
+ AssertLinter 'gcc',
+ \ ale#Escape('gcc')
+ \ . ' -S -x c++ -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/hpp_file_project'))
+ \ . ' -'
+
+Execute(The C++ ClangTidy handler should include json folders for projects with suitable build directory in them):
+ call ale#assert#SetUpLinterTest('cpp', 'clangtidy')
+ call ale#test#SetFilename('../test-files/c/json_project/subdir/file.cpp')
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' %s '
+ \ . '-p ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/json_project/build'))
+
+Execute(The C++ ClangTidy handler should include 'include' directories for projects with a Makefile):
+ call ale#assert#SetUpLinterTest('cpp', 'clangtidy')
+ call ale#test#SetFilename('../test-files/c/makefile_project/subdir/file.cpp')
+ let g:ale_cpp_clangtidy_options = ''
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' %s '
+ \ . '-- -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/c/makefile_project/include'))
+
diff --git a/test/linter/test_cargo.vader b/test/linter/test_cargo.vader
new file mode 100644
index 00000000..25dd0253
--- /dev/null
+++ b/test/linter/test_cargo.vader
@@ -0,0 +1,222 @@
+Before:
+ call ale#assert#SetUpLinterTest('rust', 'cargo')
+ call ale#test#SetFilename('../test-files/cargo/test.rs')
+
+ let g:cd = 'cd ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/cargo')) . ' && '
+ let g:suffix = ' --frozen --message-format=json -q'
+ let g:ale_rust_cargo_avoid_whole_workspace = 0
+
+ " Test with version 0.22.0 by default.
+ GivenCommandOutput ['cargo 0.22.0 (3423351a5 2017-10-06)']
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+ unlet! g:cd
+ unlet! g:suffix
+
+Execute(The linter should not be executed when there's no Cargo.toml file):
+ call ale#test#SetFilename('../foo.rs')
+ AssertLinterNotExecuted
+
+Execute(The linter should be executed when there is a Cargo.toml file):
+ GivenCommandOutput []
+ AssertLinter 'cargo', 'cargo build --frozen --message-format=json -q'
+
+Execute(`cargo check` should be used when the version is new enough):
+ GivenCommandOutput ['cargo 0.17.0 (3423351a5 2017-10-06)']
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo check' . g:suffix,
+ \]
+
+ " We should cache the version check
+ GivenCommandOutput []
+ AssertLinter 'cargo', ['cargo check' . g:suffix]
+
+Execute(`cargo build` should be used when cargo is too old):
+ GivenCommandOutput ['cargo 0.16.0 (3423351a5 2017-10-06)']
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo build' . g:suffix,
+ \]
+
+ GivenCommandOutput []
+ AssertLinter 'cargo', ['cargo build' . g:suffix]
+
+Execute(`cargo build` should be used when g:ale_rust_cargo_use_check is set to 0):
+ let g:ale_rust_cargo_use_check = 0
+
+ GivenCommandOutput ['cargo 0.24.0 (3423351a5 2017-10-06)']
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo build' . g:suffix,
+ \]
+
+ " We should cache the version check
+ GivenCommandOutput []
+ AssertLinter 'cargo', ['cargo build' . g:suffix]
+
+Execute(`cargo check` should be used when the version is new enough):
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo check' . g:suffix,
+ \]
+
+ " We should cache the version check
+ GivenCommandOutput []
+ AssertLinter 'cargo', ['cargo check' . g:suffix]
+
+Execute(--all-targets should be used when g:ale_rust_cargo_check_all_targets is set to 1):
+ let g:ale_rust_cargo_check_all_targets = 1
+
+ AssertLinter 'cargo', [ale#Escape('cargo') . ' --version', 'cargo check --all-targets' . g:suffix]
+ " We should cache the version check
+ AssertLinter 'cargo', ['cargo check --all-targets' . g:suffix]
+
+Execute(--tests should be used when g:ale_rust_cargo_check_tests is set to 1):
+ let g:ale_rust_cargo_check_tests = 1
+
+ AssertLinter 'cargo', [ale#Escape('cargo') . ' --version', 'cargo check --tests' . g:suffix]
+
+ " We should cache the version check
+ GivenCommandOutput []
+ AssertLinter 'cargo', ['cargo check --tests' . g:suffix]
+
+Execute(--examples should be used when g:ale_rust_cargo_check_examples is set to 1):
+ let g:ale_rust_cargo_check_examples = 1
+
+ AssertLinter 'cargo', [ale#Escape('cargo') . ' --version', 'cargo check --examples' . g:suffix]
+
+ " We should cache the version check
+ GivenCommandOutput []
+ AssertLinter 'cargo', ['cargo check --examples' . g:suffix]
+
+Execute(--no-default-features should be used when g:ale_rust_cargo_default_feature_behavior is none):
+ let b:ale_rust_cargo_default_feature_behavior = 'none'
+
+ AssertLinter 'cargo', [ale#Escape('cargo') . ' --version', 'cargo check --frozen --message-format=json -q --no-default-features']
+
+Execute(g:ale_rust_cargo_include_features added when g:ale_rust_cargo_default_feature_behavior is none):
+ let b:ale_rust_cargo_default_feature_behavior = 'none'
+ let b:ale_rust_cargo_include_features = 'foo bar'
+
+ AssertLinter 'cargo', [ale#Escape('cargo') . ' --version', 'cargo check --frozen --message-format=json -q --no-default-features --features ' . ale#Escape('foo bar')]
+
+Execute(g:ale_rust_cargo_include_features added and escaped):
+ let b:ale_rust_cargo_default_feature_behavior = 'default'
+ let b:ale_rust_cargo_include_features = "foo bar baz"
+
+ AssertLinter 'cargo', [ale#Escape('cargo') . ' --version', 'cargo check --frozen --message-format=json -q --features ' . ale#Escape('foo bar baz')]
+
+Execute(--all-features should be used when g:ale_rust_cargo_default_feature_behavior is all):
+ let b:ale_rust_cargo_default_feature_behavior = 'all'
+ " When all features are enabled we should ignore extra features to add
+ " since it won't do anything
+ let b:ale_rust_cargo_include_features = 'foo bar'
+
+ GivenCommandOutput ['cargo 0.22.0 (3423351a5 2017-10-06)']
+ AssertLinter 'cargo', [ale#Escape('cargo') . ' --version', 'cargo check --frozen --message-format=json -q --all-features']
+
+Execute(Cargo should run from the crate directory when set to avoid the workspace):
+ let g:ale_rust_cargo_avoid_whole_workspace = 1
+ call ale#test#SetFilename('../test-files/cargo/workspace_paths/subpath/test.rs')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/cargo/workspace_paths/subpath')
+ call ale#semver#ResetVersionCache()
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo check --frozen --message-format=json -q',
+ \]
+
+Execute(Cargo should not run from the crate directory when not set to avoid the workspace):
+ let g:ale_rust_cargo_avoid_whole_workspace = 0
+ call ale#test#SetFilename('../test-files/cargo/workspace_paths/subpath/test.rs')
+
+ AssertLinterCwd ''
+ call ale#semver#ResetVersionCache()
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo check --frozen --message-format=json -q',
+ \]
+
+Execute(When ale_rust_cargo_use_clippy is set, cargo-clippy is used as linter):
+ let b:ale_rust_cargo_use_clippy = 1
+
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo clippy --frozen --message-format=json -q',
+ \]
+
+Execute(When ale_rust_cargo_clippy_options is set, cargo-clippy appends it to commandline):
+ let b:ale_rust_cargo_use_clippy = 1
+ let b:ale_rust_cargo_clippy_options = '-- -D warnings'
+
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo clippy --frozen --message-format=json -q -- -D warnings',
+ \]
+
+Execute(Clippy options work without prepending --):
+ let b:ale_rust_cargo_use_clippy = 1
+ let b:ale_rust_cargo_clippy_options = '-D warnings'
+
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo clippy --frozen --message-format=json -q -- -D warnings',
+ \]
+
+Execute(Build supports all cargo flags):
+ let g:ale_rust_cargo_use_check = 0
+ let g:ale_rust_cargo_check_all_targets = 1
+ let g:ale_rust_cargo_check_tests = 1
+ let g:ale_rust_cargo_check_examples = 1
+ let b:ale_rust_cargo_default_feature_behavior = 'all'
+ let b:ale_rust_cargo_target_dir = 'target/ale'
+
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo build --all-targets --examples --tests --target-dir ' . ale#Escape('target/ale') . ' --frozen --message-format=json -q --all-features',
+ \]
+
+Execute(Clippy supports all cargo flags):
+ let b:ale_rust_cargo_use_clippy = 1
+ let g:ale_rust_cargo_check_all_targets = 1
+ let g:ale_rust_cargo_check_tests = 1
+ let g:ale_rust_cargo_check_examples = 1
+ let b:ale_rust_cargo_default_feature_behavior = 'all'
+ let b:ale_rust_cargo_clippy_options = '-D warnings'
+ let b:ale_rust_cargo_target_dir = 'target/ale'
+
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo clippy --all-targets --examples --tests --target-dir ' . ale#Escape('target/ale') . ' --frozen --message-format=json -q --all-features -- -D warnings',
+ \]
+
+Execute(cargo-check does not refer ale_rust_cargo_clippy_options):
+ let b:ale_rust_cargo_use_clippy = 0
+ let b:ale_rust_cargo_use_check = 1
+ let b:ale_rust_cargo_clippy_options = '-- -D warnings'
+
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo check --frozen --message-format=json -q',
+ \]
+
+Execute(`cargo --target-dir` should be used when the version is new enough and it is set):
+ let b:ale_rust_cargo_target_dir = 'target/ale'
+
+ GivenCommandOutput ['cargo 0.17.0 (3423351a5 2017-10-06)']
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo check --target-dir ' . ale#Escape('target/ale') . g:suffix,
+ \]
+
+Execute(`cargo --target-dir` should not be used when the version is not new enough and it is set):
+ let b:ale_rust_cargo_target_dir = 'target/ale'
+
+ GivenCommandOutput ['cargo 0.16.0 (3423351a5 2017-10-06)']
+ AssertLinter 'cargo', [
+ \ ale#Escape('cargo') . ' --version',
+ \ 'cargo build' . g:suffix,
+ \]
diff --git a/test/linter/test_checkstyle.vader b/test/linter/test_checkstyle.vader
new file mode 100644
index 00000000..8197e6b5
--- /dev/null
+++ b/test/linter/test_checkstyle.vader
@@ -0,0 +1,72 @@
+Before:
+ call ale#assert#SetUpLinterTest('java', 'checkstyle')
+ call ale#test#SetFilename('dummy.java')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The checkstyle callback should return the correct default value):
+ AssertLinter 'checkstyle',
+ \ ale#Escape('checkstyle')
+ \ . ' -c ' . ale#Escape('/google_checks.xml')
+ \ . ' %s'
+
+Execute(The checkstyle executable should be configurable):
+ let b:ale_java_checkstyle_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar')
+ \ . ' -c ' . ale#Escape('/google_checks.xml')
+ \ . ' %s'
+
+Execute(Custom options should be supported):
+ let b:ale_java_checkstyle_options = '--foobar -cp -classpath /path/to/checkstyle-8.7-all.jar'
+
+ AssertLinter 'checkstyle',
+ \ ale#Escape('checkstyle')
+ \ . ' --foobar -cp -classpath /path/to/checkstyle-8.7-all.jar'
+ \ . ' -c ' . ale#Escape('/google_checks.xml')
+ \ . ' %s'
+
+Execute(configuration files set in _config should be supported):
+ let b:ale_java_checkstyle_config = ale#path#Simplify(g:dir . '/../test-files/checkstyle/other_config.xml')
+
+ AssertLinter 'checkstyle',
+ \ ale#Escape('checkstyle')
+ \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/checkstyle/other_config.xml'))
+ \ . ' %s'
+
+Execute(configuration files set in _options should be preferred over _config):
+ let b:ale_java_checkstyle_config = '/foo.xml'
+ let b:ale_java_checkstyle_options = '-c /bar.xml'
+
+ AssertLinter 'checkstyle', ale#Escape('checkstyle') . ' -c /bar.xml %s'
+
+ let b:ale_java_checkstyle_options = '-x -c /bar.xml'
+
+ AssertLinter 'checkstyle', ale#Escape('checkstyle') . ' -x -c /bar.xml %s'
+
+Execute(google_checks.xml should be used by default):
+ call ale#test#SetFilename('../test-files/checkstyle/test.java')
+
+ AssertLinter 'checkstyle',
+ \ ale#Escape('checkstyle')
+ \ . ' -c ' . ale#Escape('/google_checks.xml')
+ \ . ' %s'
+
+Execute(Other relative paths should be supported):
+ let b:ale_java_checkstyle_config = '../test-files/checkstyle/other_config.xml'
+
+ AssertLinter 'checkstyle',
+ \ ale#Escape('checkstyle')
+ \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/checkstyle/other_config.xml'))
+ \ . ' %s'
+
+ call ale#test#SetFilename('../test-files/checkstyle/test.java')
+
+ let b:ale_java_checkstyle_config = 'other_config.xml'
+
+ AssertLinter 'checkstyle',
+ \ ale#Escape('checkstyle')
+ \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/checkstyle/other_config.xml'))
+ \ . ' %s'
diff --git a/test/linter/test_clang_tidy.vader b/test/linter/test_clang_tidy.vader
new file mode 100644
index 00000000..eb1220be
--- /dev/null
+++ b/test/linter/test_clang_tidy.vader
@@ -0,0 +1,84 @@
+Before:
+ Save g:ale_c_parse_makefile
+ let g:ale_c_parse_makefile = 0
+
+ call ale#assert#SetUpLinterTest('cpp', 'clangtidy')
+ call ale#test#SetFilename('test.cpp')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The clangtidy command default should be correct):
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy') . ' %s'
+
+Execute(You should be able to remove the -checks option for clang-tidy):
+ let b:ale_cpp_clangtidy_checks = []
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy') . ' %s'
+
+Execute(You should be able to set other checks for clang-tidy):
+ let b:ale_cpp_clangtidy_checks = ['-*', 'clang-analyzer-*']
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s'
+
+Execute(You should be able to manually set compiler flags for clang-tidy):
+ let b:ale_cpp_clangtidy_checks = ['*']
+ let b:ale_cpp_clangtidy_options = '-Wall'
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall'
+
+Execute(You should be able to manually set flags for clang-tidy):
+ let b:ale_cpp_clangtidy_extra_options = '-config='
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy') . ' ' . ale#Escape('-config=') . ' %s'
+
+Execute(The build directory should be configurable):
+ let b:ale_cpp_clangtidy_checks = ['*']
+ let b:ale_c_build_dir = '/foo/bar'
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('*') . ' %s'
+ \ . ' -p ' . ale#Escape('/foo/bar')
+
+Execute(The build directory setting should override the options):
+ let b:ale_cpp_clangtidy_checks = ['*']
+ let b:ale_c_build_dir = '/foo/bar'
+ let b:ale_cpp_clangtidy_options = '-Wall'
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('*') . ' %s'
+ \ . ' -p ' . ale#Escape('/foo/bar')
+
+Execute(The build directory should be used for header files):
+ call ale#test#SetFilename('test.h')
+
+ let b:ale_cpp_clangtidy_checks = ['*']
+ let b:ale_c_build_dir = '/foo/bar'
+ let b:ale_cpp_clangtidy_options = '-Wall'
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('*') . ' %s'
+ \ . ' -p ' . ale#Escape('/foo/bar')
+
+ call ale#test#SetFilename('test.hpp')
+
+ AssertLinter 'clang-tidy',
+ \ ale#Escape('clang-tidy')
+ \ . ' -checks=' . ale#Escape('*') . ' %s'
+ \ . ' -p ' . ale#Escape('/foo/bar')
+
+Execute(The executable should be configurable):
+ let b:ale_cpp_clangtidy_checks = ['*']
+ let b:ale_cpp_clangtidy_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -checks=' . ale#Escape('*') . ' %s'
diff --git a/test/linter/test_cookstyle.vader b/test/linter/test_cookstyle.vader
new file mode 100644
index 00000000..ad7391cc
--- /dev/null
+++ b/test/linter/test_cookstyle.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('chef', 'cookstyle')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'cookstyle', ale#Escape('cookstyle') . ' --force-exclusion --format json --stdin %s'
+
+Execute(The executable path should be configurable):
+ let b:ale_chef_cookstyle_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --force-exclusion --format json --stdin %s'
+
+Execute(The linter options should be configurable):
+ let b:ale_chef_cookstyle_options = '--parallel'
+
+ AssertLinter 'cookstyle', ale#Escape('cookstyle') . ' --parallel --force-exclusion --format json --stdin %s'
+
diff --git a/test/linter/test_cpp_cc.vader b/test/linter/test_cpp_cc.vader
new file mode 100644
index 00000000..dec3a07c
--- /dev/null
+++ b/test/linter/test_cpp_cc.vader
@@ -0,0 +1,55 @@
+Before:
+ Save g:ale_c_parse_makefile
+ Save g:ale_history_enabled
+
+ let g:ale_c_parse_makefile = 0
+ let g:ale_history_enabled = 0
+
+ let g:get_cflags_return_value = ''
+ let g:executable_map = {}
+
+ runtime autoload/ale/c.vim
+ runtime autoload/ale/engine.vim
+
+ function! ale#engine#IsExecutable(buffer, executable) abort
+ return has_key(g:executable_map, a:executable)
+ endfunction
+
+ function! ale#c#GetCFlags(buffer, output) abort
+ return g:get_cflags_return_value
+ endfunction
+
+ call ale#assert#SetUpLinterTest('cpp', 'cc')
+
+ let b:command_tail = ' -S -x c++'
+ \ . ' -o ' . (has('win32') ? 'nul': '/dev/null')
+ \ . ' -iquote %s:h'
+ \ . ' -std=c++14 -Wall -'
+
+After:
+ unlet! g:get_cflags_return_value
+ unlet! g:executable_map
+ unlet! b:command_tail
+
+ runtime autoload/ale/c.vim
+ runtime autoload/ale/engine.vim
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(clang++ should be used instead of gcc, if available):
+ let g:executable_map = {'clang++': 1}
+
+ AssertLinter 'clang++', [ale#Escape('clang++') . b:command_tail]
+
+Execute(The executable should be configurable):
+ AssertLinter 'gcc', [ale#Escape('gcc') . b:command_tail]
+
+ let b:ale_cpp_cc_executable = 'foobar'
+
+ AssertLinter 'foobar', [ale#Escape('foobar') . b:command_tail]
+
+Execute(The -std flag should be replaced by parsed C flags):
+ let b:command_tail = substitute(b:command_tail, 'c++14', 'c++11 ', '')
+ let g:get_cflags_return_value = '-std=c++11'
+
+ AssertLinter 'gcc', ale#Escape('gcc') . b:command_tail
diff --git a/test/linter/test_cpp_ccls.vader b/test/linter/test_cpp_ccls.vader
new file mode 100644
index 00000000..12aa30e3
--- /dev/null
+++ b/test/linter/test_cpp_ccls.vader
@@ -0,0 +1,69 @@
+" Author: Ye Jingchen <ye.jingchen@gmail.com>, Ben Falconer <ben@falconers.me.uk>
+" Description: A language server for C++
+
+Before:
+ call ale#assert#SetUpLinterTest('cpp', 'ccls')
+
+ Save b:ale_c_build_dir_names
+ Save b:ale_cpp_ccls_executable
+ Save b:ale_cpp_ccls_init_options
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The project root should be detected correctly using compile_commands.json file):
+ call ale#test#SetFilename(tempname() . '/dummy.cpp')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_compile_commands_json/dummy.cpp')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_compile_commands_json')
+
+Execute(The project root should be detected correctly using .ccls file):
+ call ale#test#SetFilename(tempname() . '/dummy.cpp')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_ccls/dummy.cpp')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_ccls')
+
+Execute(The project root should be detected correctly using .ccls-root file):
+ call ale#test#SetFilename(tempname() . '/dummy.cpp')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_ccls-root/dummy.cpp')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_ccls-root')
+
+Execute(The executable should be configurable):
+ AssertLinter 'ccls', ale#Escape('ccls')
+
+ let b:ale_cpp_ccls_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+
+Execute(The initialization options should be configurable):
+ AssertLSPOptions {}
+
+ let b:ale_cpp_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' }
+
+ AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' }
+
+Execute(The compile command database should be detected correctly):
+ call ale#test#SetFilename('../test-files/ccls/with_ccls/dummy.c')
+
+ AssertLSPOptions {}
+
+ call ale#test#SetFilename('../test-files/ccls/with_compile_commands_json/dummy.c')
+
+ AssertLSPOptions { 'compilationDatabaseDirectory':
+ \ ale#path#Simplify(g:dir . '/../test-files/ccls/with_compile_commands_json') }
+
+ call ale#test#SetFilename('../test-files/ccls/with_build_dir/dummy.c')
+ let b:ale_c_build_dir_names = ['unusual_build_dir_name']
+
+ AssertLSPOptions { 'compilationDatabaseDirectory':
+ \ ale#path#Simplify(g:dir . '/../test-files/ccls/with_build_dir/unusual_build_dir_name') }
diff --git a/test/linter/test_cpp_clangcheck.vader b/test/linter/test_cpp_clangcheck.vader
new file mode 100644
index 00000000..188141d5
--- /dev/null
+++ b/test/linter/test_cpp_clangcheck.vader
@@ -0,0 +1,35 @@
+Before:
+ call ale#assert#SetUpLinterTest('cpp', 'clangcheck')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'clang-check',
+ \ ale#Escape('clang-check')
+ \ . ' -analyze %s --extra-arg=-Xclang --extra-arg=-analyzer-output=text --extra-arg=-fno-color-diagnostics'
+
+ let b:ale_cpp_clangcheck_executable = 'foobar'
+
+ " The extra arguments in the command are used to prevent .plist files from
+ " being generated.
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar')
+ \ . ' -analyze %s --extra-arg=-Xclang --extra-arg=-analyzer-output=text --extra-arg=-fno-color-diagnostics'
+
+Execute(The options should be configurable):
+ let b:ale_cpp_clangcheck_options = '--something'
+
+ AssertLinter 'clang-check',
+ \ ale#Escape('clang-check')
+ \ . ' -analyze %s'
+ \ . ' --extra-arg=-Xclang --extra-arg=-analyzer-output=text --extra-arg=-fno-color-diagnostics'
+ \ . ' --something'
+
+Execute(The build directory should be used when set):
+ let b:ale_cpp_clangcheck_options = '--something'
+ let b:ale_c_build_dir = '/foo/bar'
+
+ AssertLinter 'clang-check',
+ \ ale#Escape('clang-check')
+ \ . ' -analyze %s --something -p ' . ale#Escape('/foo/bar')
diff --git a/test/linter/test_cpp_clazy.vader b/test/linter/test_cpp_clazy.vader
new file mode 100644
index 00000000..e5a81b8f
--- /dev/null
+++ b/test/linter/test_cpp_clazy.vader
@@ -0,0 +1,56 @@
+Before:
+ call ale#assert#SetUpLinterTest('cpp', 'clazy')
+ call ale#test#SetFilename('test.cpp')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The clazy command default should be correct):
+ AssertLinter 'clazy-standalone',
+ \ ale#Escape('clazy-standalone') . ' -checks=' . ale#Escape('level1') . ' %s'
+
+Execute(You should be able to remove the -checks option for clazy-standalone):
+ let b:ale_cpp_clazy_checks = []
+
+ AssertLinter 'clazy-standalone', ale#Escape('clazy-standalone') . ' %s'
+
+Execute(You should be able to set other checks for clazy-standalone):
+ let b:ale_cpp_clazy_checks = ['level2', 'level3']
+
+ AssertLinter 'clazy-standalone',
+ \ ale#Escape('clazy-standalone')
+ \ . ' -checks=' . ale#Escape('level2,level3') . ' %s'
+
+Execute(You should be able to manually set compiler flags for clazy-standalone):
+ let b:ale_cpp_clazy_options = '-qt4-compat'
+
+ AssertLinter 'clazy-standalone',
+ \ ale#Escape('clazy-standalone') . ' -checks=' . ale#Escape('level1') . ' -qt4-compat' . ' %s'
+ \
+Execute(The build directory should be configurable):
+ let b:ale_c_build_dir = '/foo/bar'
+
+ AssertLinter 'clazy-standalone',
+ \ ale#Escape('clazy-standalone')
+ \ . ' -checks=' . ale#Escape('level1') . ' -p ' . ale#Escape('/foo/bar') . ' %s'
+
+Execute(The build directory should be used for header files):
+ call ale#test#SetFilename('test.h')
+
+ let b:ale_c_build_dir = '/foo/bar'
+
+ AssertLinter 'clazy-standalone',
+ \ ale#Escape('clazy-standalone')
+ \ . ' -checks=' . ale#Escape('level1') . ' -p ' . ale#Escape('/foo/bar') . ' %s'
+
+ call ale#test#SetFilename('test.hpp')
+
+ AssertLinter 'clazy-standalone',
+ \ ale#Escape('clazy-standalone')
+ \ . ' -checks=' . ale#Escape('level1') . ' -p ' . ale#Escape('/foo/bar') . ' %s'
+
+Execute(The executable should be configurable):
+ let b:ale_cpp_clazy_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -checks=' . ale#Escape('level1') . ' %s'
diff --git a/test/linter/test_cpp_cppcheck.vader b/test/linter/test_cpp_cppcheck.vader
new file mode 100644
index 00000000..62195803
--- /dev/null
+++ b/test/linter/test_cpp_cppcheck.vader
@@ -0,0 +1,66 @@
+Before:
+ call ale#assert#SetUpLinterTest('cpp', 'cppcheck')
+ let b:command_tail = ' -q --language=c++ --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}') . ' --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
+
+After:
+ " Remove a test file we might open for some tests.
+ if &buftype != 'nofile'
+ :q!
+ set buftype=nofile
+ endif
+
+ unlet! b:command_tail
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'cppcheck', ale#Escape('cppcheck') . b:command_tail
+
+ let b:ale_cpp_cppcheck_executable = 'foobar'
+
+ AssertLinterCwd ''
+ AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail
+
+Execute(cppcheck for C++ should detect compile_commands.json files):
+ call ale#test#SetFilename('../test-files/cppcheck/one/foo.cpp')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/cppcheck/one')
+ AssertLinter 'cppcheck', ale#Escape('cppcheck')
+ \ . ' -q --language=c++'
+ \ . ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
+ \ . ' --project=' . ale#Escape('compile_commands.json')
+ \ . ' --enable=style %t'
+
+Execute(cppcheck for C++ should detect compile_commands.json files in build directories):
+ call ale#test#SetFilename('../test-files/cppcheck/with_build_dir/foo.cpp')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/cppcheck/with_build_dir')
+ AssertLinter 'cppcheck', ale#Escape('cppcheck')
+ \ . ' -q --language=c++'
+ \ . ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
+ \ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json'))
+ \ . ' --enable=style %t'
+
+Execute(cppcheck for C++ should include file dir if compile_commands.json file is not found):
+ call ale#test#SetFilename('../test-files/cppcheck/foo.cpp')
+
+ AssertLinter 'cppcheck',
+ \ ale#Escape('cppcheck')
+ \ . ' -q --language=c++'
+ \ . ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
+ \ . ' --enable=style'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/cppcheck'))
+ \ . ' %t'
+
+Execute(cppcheck for C++ should ignore compile_commands.json file if buffer is modified):
+ call ale#test#SetFilename('../test-files/cppcheck/one/foo.cpp')
+
+ set buftype=
+ set modified
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/cppcheck/one')
+ AssertLinter 'cppcheck', ale#Escape('cppcheck')
+ \ . ' -q --language=c++'
+ \ . ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
+ \ . ' --enable=style'
+ \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/cppcheck/one'))
+ \ . ' %t'
diff --git a/test/linter/test_cpp_cquery.vader b/test/linter/test_cpp_cquery.vader
new file mode 100644
index 00000000..f638e401
--- /dev/null
+++ b/test/linter/test_cpp_cquery.vader
@@ -0,0 +1,40 @@
+" Author: Ben Falconer <ben@falconers.me.uk>
+" Description: A language server for C++
+
+Before:
+ call ale#assert#SetUpLinterTest('cpp', 'cquery')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The project root should be detected correctly using compile_commands.json file):
+ call ale#test#SetFilename(tempname() . '/dummy.cpp')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/cquery/dummy.cpp')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/cquery')
+
+Execute(The project root should be detected correctly using .cquery file):
+ call ale#test#SetFilename(tempname() . '/dummy.cpp')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/cquery/with_cquery/dummy.cpp')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/cquery/with_cquery')
+
+Execute(The executable should be configurable):
+ AssertLinter 'cquery', ale#Escape('cquery')
+
+ let b:ale_cpp_cquery_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+
+Execute(The cache directory should be configurable):
+ AssertLSPOptions {'cacheDirectory': expand('$HOME/.cache/cquery')}
+
+ let b:ale_cpp_cquery_cache_directory = '/foo/bar'
+
+ AssertLSPOptions {'cacheDirectory': '/foo/bar'}
diff --git a/test/linter/test_cpp_flawfinder.vader b/test/linter/test_cpp_flawfinder.vader
new file mode 100644
index 00000000..3f4067ea
--- /dev/null
+++ b/test/linter/test_cpp_flawfinder.vader
@@ -0,0 +1,26 @@
+Before:
+ call ale#assert#SetUpLinterTest('cpp', 'flawfinder')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The flawfinder command should be correct):
+ AssertLinter 'flawfinder',
+ \ ale#Escape('flawfinder') . ' -CDQS --minlevel=1 %t'
+
+Execute(The minlevel of flawfinder should be configurable):
+ let b:ale_cpp_flawfinder_minlevel = 8
+
+ AssertLinter 'flawfinder',
+ \ ale#Escape('flawfinder') . ' -CDQS --minlevel=8 %t'
+
+Execute(Additional flawfinder options should be configurable):
+ let b:ale_cpp_flawfinder_options = ' --foobar'
+
+ AssertLinter 'flawfinder',
+ \ ale#Escape('flawfinder') . ' -CDQS --foobar --minlevel=1 %t'
+
+Execute(The flawfinder exectable should be configurable):
+ let b:ale_cpp_flawfinder_executable = 'foo/bar'
+
+ AssertLinter 'foo/bar', ale#Escape('foo/bar') . ' -CDQS --minlevel=1 %t'
diff --git a/test/linter/test_cpplint.vader b/test/linter/test_cpplint.vader
new file mode 100644
index 00000000..d5fd457b
--- /dev/null
+++ b/test/linter/test_cpplint.vader
@@ -0,0 +1,17 @@
+Before:
+ call ale#assert#SetUpLinterTest('cpp', 'cpplint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'cpplint', ale#Escape('cpplint') . ' %s'
+
+ let b:ale_cpp_cpplint_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' %s'
+
+Execute(The options should be configurable):
+ let b:ale_cpp_cpplint_options = '--something'
+
+ AssertLinter 'cpplint', ale#Escape('cpplint') . ' --something %s'
diff --git a/test/linter/test_cs_csc.vader b/test/linter/test_cs_csc.vader
new file mode 100644
index 00000000..28d0304a
--- /dev/null
+++ b/test/linter/test_cs_csc.vader
@@ -0,0 +1,42 @@
+Before:
+ call ale#assert#SetUpLinterTest('cs', 'csc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The csc linter should return the correct default command):
+ AssertLinterCwd expand('%:p:h')
+ AssertLinter 'csc', 'csc /unsafe /out:TEMP /t:module /recurse:' . ale#Escape('*.cs')
+
+Execute(The options should be be used in the command):
+ let g:ale_cs_csc_options = ''
+
+ AssertLinter 'csc', 'csc /unsafe /out:TEMP /t:module /recurse:' . ale#Escape('*.cs')
+
+Execute(The souce path should be be used in the command):
+ let g:ale_cs_csc_source = '../foo/bar'
+
+ AssertLinterCwd '../foo/bar'
+ AssertLinter 'csc', 'csc /unsafe /out:TEMP /t:module /recurse:' . ale#Escape('*.cs')
+
+Execute(The list of search pathes for assemblies should be be used in the command if not empty):
+ let g:ale_cs_csc_assembly_path = ['/usr/lib/mono', '../foo/bar']
+
+ AssertLinter 'csc', 'csc /unsafe'
+ \ . ' /lib:' . ale#Escape('/usr/lib/mono') . ',' . ale#Escape('../foo/bar')
+ \ . ' /out:TEMP /t:module /recurse:' . ale#Escape('*.cs')
+
+ let g:ale_cs_csc_assembly_path = []
+
+ AssertLinter 'csc', 'csc /unsafe /out:TEMP /t:module /recurse:' . ale#Escape('*.cs')
+
+Execute(The list of assemblies should be be used in the command if not empty):
+ let g:ale_cs_csc_assemblies = ['foo.dll', 'bar.dll']
+
+ AssertLinter 'csc', 'csc /unsafe'
+ \ . ' /r:' . ale#Escape('foo.dll') . ',' . ale#Escape('bar.dll')
+ \ . ' /out:TEMP /t:module /recurse:' . ale#Escape('*.cs')
+
+ let g:ale_cs_csc_assemblies = []
+
+ AssertLinter 'csc', 'csc /unsafe /out:TEMP /t:module /recurse:' . ale#Escape('*.cs')
diff --git a/test/linter/test_cs_mcs.vader b/test/linter/test_cs_mcs.vader
new file mode 100644
index 00000000..dbebd106
--- /dev/null
+++ b/test/linter/test_cs_mcs.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('cs', 'mcs')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'mcs', 'mcs -unsafe --parse %t'
+
+Execute(The options should be be used in the command):
+ let b:ale_cs_mcs_options = '-pkg:dotnet'
+
+ AssertLinter 'mcs', 'mcs -unsafe --parse -pkg:dotnet %t'
diff --git a/test/linter/test_cs_mcsc.vader b/test/linter/test_cs_mcsc.vader
new file mode 100644
index 00000000..e784cf15
--- /dev/null
+++ b/test/linter/test_cs_mcsc.vader
@@ -0,0 +1,42 @@
+Before:
+ call ale#assert#SetUpLinterTest('cs', 'mcsc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The mcsc linter should return the correct default command):
+ AssertLinterCwd expand('%:p:h')
+ AssertLinter 'mcs', 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs')
+
+Execute(The options should be be used in the command):
+ let g:ale_cs_mcsc_options = '-pkg:dotnet'
+
+ AssertLinter 'mcs', 'mcs -unsafe -pkg:dotnet -out:TEMP -t:module -recurse:' . ale#Escape('*.cs')
+
+Execute(The souce path should be be used in the command):
+ let g:ale_cs_mcsc_source = '../foo/bar'
+
+ AssertLinterCwd '../foo/bar'
+ AssertLinter 'mcs', 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs')
+
+Execute(The list of search pathes for assemblies should be be used in the command if not empty):
+ let g:ale_cs_mcsc_assembly_path = ['/usr/lib/mono', '../foo/bar']
+
+ AssertLinter 'mcs', 'mcs -unsafe'
+ \ . ' -lib:' . ale#Escape('/usr/lib/mono') . ',' . ale#Escape('../foo/bar')
+ \ . ' -out:TEMP -t:module -recurse:' . ale#Escape('*.cs')
+
+ let g:ale_cs_mcsc_assembly_path = []
+
+ AssertLinter 'mcs', 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs')
+
+Execute(The list of assemblies should be be used in the command if not empty):
+ let g:ale_cs_mcsc_assemblies = ['foo.dll', 'bar.dll']
+
+ AssertLinter 'mcs', 'mcs -unsafe'
+ \ . ' -r:' . ale#Escape('foo.dll') . ',' . ale#Escape('bar.dll')
+ \ . ' -out:TEMP -t:module -recurse:' . ale#Escape('*.cs')
+
+ let g:ale_cs_mcsc_assemblies = []
+
+ AssertLinter 'mcs', 'mcs -unsafe -out:TEMP -t:module -recurse:' . ale#Escape('*.cs')
diff --git a/test/linter/test_cucumber.vader b/test/linter/test_cucumber.vader
new file mode 100644
index 00000000..6a7851ef
--- /dev/null
+++ b/test/linter/test_cucumber.vader
@@ -0,0 +1,18 @@
+Before:
+ call ale#assert#SetUpLinterTest('cucumber', 'cucumber')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Should require the nearest features dir, if one is found):
+ call ale#test#SetFilename('../test-files/cucumber/features/cuke.feature')
+
+ AssertLinter 'cucumber',
+ \ 'cucumber --dry-run --quiet --strict --format=json '
+ \ . '-r ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/cucumber/features/')) . ' %t'
+
+Execute(Should require nothing if no features dir is found):
+ call ale#test#SetFilename('something/without/a/features/dir')
+
+ AssertLinter 'cucumber',
+ \ 'cucumber --dry-run --quiet --strict --format=json %t'
diff --git a/test/linter/test_cuda_nvcc.vader b/test/linter/test_cuda_nvcc.vader
new file mode 100644
index 00000000..4578d052
--- /dev/null
+++ b/test/linter/test_cuda_nvcc.vader
@@ -0,0 +1,20 @@
+Before:
+ call ale#assert#SetUpLinterTest('cuda', 'nvcc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'nvcc',
+ \ ale#Escape('nvcc') . ' -cuda -std=c++11 %s -o ' . g:ale#util#nul_file
+
+ let b:ale_cuda_nvcc_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -cuda -std=c++11 %s -o ' . g:ale#util#nul_file
+
+Execute(The options should be configurable):
+ let g:ale_cuda_nvcc_options = '--foobar'
+
+ AssertLinter 'nvcc',
+ \ ale#Escape('nvcc') . ' -cuda --foobar %s -o ' . g:ale#util#nul_file
diff --git a/test/linter/test_cypher_cypher_lint.vader b/test/linter/test_cypher_cypher_lint.vader
new file mode 100644
index 00000000..6b64dc1f
--- /dev/null
+++ b/test/linter/test_cypher_cypher_lint.vader
@@ -0,0 +1,8 @@
+Before:
+ call ale#assert#SetUpLinterTest('cypher', 'cypher_lint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command and executable should be correct):
+ AssertLinter 'cypher-lint', 'cypher-lint'
diff --git a/test/linter/test_d_dls.vader b/test/linter/test_d_dls.vader
new file mode 100644
index 00000000..156ebf66
--- /dev/null
+++ b/test/linter/test_d_dls.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('d', 'dls')
+
+ Save &filetype
+ let &filetype = 'd'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The language string should be correct):
+ AssertLSPLanguage 'd'
+
+Execute(The default executable should be correct):
+ AssertLinter 'dls', 'dls'
+
+Execute(The executable should be configurable):
+ let g:ale_d_dls_executable = 'foobar'
+
+ AssertLinter 'foobar', 'foobar'
diff --git a/test/linter/test_dart_analysis_server.vader b/test/linter/test_dart_analysis_server.vader
new file mode 100644
index 00000000..1754109a
--- /dev/null
+++ b/test/linter/test_dart_analysis_server.vader
@@ -0,0 +1,15 @@
+Before:
+ call ale#assert#SetUpLinterTest('dart', 'analysis_server')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'dart', ale#Escape('dart')
+ \ . ' ./snapshots/analysis_server.dart.snapshot --lsp'
+
+Execute(The executable should be configurable):
+ let g:ale_dart_analysis_server_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+ \ . ' ./snapshots/analysis_server.dart.snapshot --lsp'
diff --git a/test/linter/test_dart_language_server.vader b/test/linter/test_dart_language_server.vader
new file mode 100644
index 00000000..5567f271
--- /dev/null
+++ b/test/linter/test_dart_language_server.vader
@@ -0,0 +1,8 @@
+Before:
+ call ale#assert#SetUpLinterTest('dart', 'language_server')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'dart_language_server', ale#Escape('dart_language_server')
diff --git a/test/linter/test_dartanalyzer.vader b/test/linter/test_dartanalyzer.vader
new file mode 100644
index 00000000..7275b187
--- /dev/null
+++ b/test/linter/test_dartanalyzer.vader
@@ -0,0 +1,20 @@
+Before:
+ call ale#assert#SetUpLinterTest('dart', 'dartanalyzer')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command and executable should be correct):
+ AssertLinter 'dartanalyzer', ale#Escape('dartanalyzer') . ' %s'
+
+Execute(The executable should be configurable):
+ let g:ale_dart_dartanalyzer_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' %s'
+
+Execute(The .packages file should be set if detected):
+ call ale#test#SetFilename('../test-files/dart/foo')
+
+ AssertLinter 'dartanalyzer', ale#Escape('dartanalyzer')
+ \ . ' --packages ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/dart/.packages'))
+ \ . ' %s'
diff --git a/test/linter/test_desktop_file_validate.vader b/test/linter/test_desktop_file_validate.vader
new file mode 100644
index 00000000..4a49057b
--- /dev/null
+++ b/test/linter/test_desktop_file_validate.vader
@@ -0,0 +1,15 @@
+Before:
+ call ale#assert#SetUpLinterTest('desktop', 'desktop_file_validate')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'desktop-file-validate',
+ \ ale#Escape('desktop-file-validate') . ' %t'
+
+Execute(Extra options should work):
+ let b:ale_desktop_desktop_file_validate_options = '--warn-kde'
+
+ AssertLinter 'desktop-file-validate',
+ \ ale#Escape('desktop-file-validate') . ' --warn-kde %t'
diff --git a/test/linter/test_dialyxir.vader b/test/linter/test_dialyxir.vader
new file mode 100644
index 00000000..250ffefd
--- /dev/null
+++ b/test/linter/test_dialyxir.vader
@@ -0,0 +1,16 @@
+Before:
+ call ale#assert#SetUpLinterTest('elixir', 'dialyxir')
+ call ale#test#SetFilename('../test-files/elixir/mix_project/lib/app.ex')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Builds dialyxir command with a normal project):
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elixir/mix_project')
+ AssertLinter 'mix', 'mix help dialyzer && mix dialyzer'
+
+Execute(Builds dialyxir command with an umbrella project):
+ call ale#test#SetFilename('../test-files/elixir/umbrella_project/apps/mix_project/lib/app.ex')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elixir/umbrella_project')
+ AssertLinter 'mix', 'mix help dialyzer && mix dialyzer'
diff --git a/test/linter/test_dockerfile_lint.vader b/test/linter/test_dockerfile_lint.vader
new file mode 100644
index 00000000..abc32e0d
--- /dev/null
+++ b/test/linter/test_dockerfile_lint.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('dockerfile', 'dockerfile_lint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'dockerfile_lint', ale#Escape('dockerfile_lint') . ' -p -j -f %t'
+
+Execute(The executable should be configurable):
+ let b:ale_dockerfile_dockerfile_lint_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' -p -j -f %t'
+
+Execute(The options should be configurable):
+ let b:ale_dockerfile_dockerfile_lint_options = '-r additional.yaml'
+
+ AssertLinter 'dockerfile_lint', ale#Escape('dockerfile_lint') . ' -r additional.yaml -p -j -f %t'
+
diff --git a/test/linter/test_dogma.vader b/test/linter/test_dogma.vader
new file mode 100644
index 00000000..c8b599af
--- /dev/null
+++ b/test/linter/test_dogma.vader
@@ -0,0 +1,16 @@
+Before:
+ call ale#assert#SetUpLinterTest('elixir', 'dogma')
+ call ale#test#SetFilename('../test-files/elixir/mix_project/lib/app.ex')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Builds dogma command with a normal project):
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elixir/mix_project')
+ AssertLinter 'mix', 'mix help dogma && mix dogma %s --format=flycheck'
+
+Execute(Builds dogma command with an umbrella project):
+ call ale#test#SetFilename('../test-files/elixir/umbrella_project/apps/mix_project/lib/app.ex')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elixir/umbrella_project')
+ AssertLinter 'mix', 'mix help dogma && mix dogma %s --format=flycheck'
diff --git a/test/linter/test_eclipselsp.vader b/test/linter/test_eclipselsp.vader
new file mode 100644
index 00000000..6bbc4053
--- /dev/null
+++ b/test/linter/test_eclipselsp.vader
@@ -0,0 +1,111 @@
+Before:
+ call ale#assert#SetUpLinterTest('java', 'eclipselsp')
+ call ale#test#SetFilename('dummy.java')
+
+ let b:ale_java_eclipselsp_path = '/home/user/eclipse.dst.ls'
+
+ let b:cfg = ale#path#Simplify(g:dir . '/../config_linux')
+
+ if has('win32')
+ let b:cfg = ale#path#Simplify(g:dir . '/../config_win')
+ elseif has('macunix')
+ let b:cfg = ale#path#Simplify(g:dir . '/../config_mac')
+ endif
+
+After:
+ unlet! b:ale_java_eclipselsp_path
+ unlet! b:cfg
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(VersionCheck should return correct version):
+
+ " OpenJDK Java 1.8
+ AssertEqual [1, 8, 0], ale_linters#java#eclipselsp#VersionCheck([
+ \ 'openjdk version "1.8.0_191"',
+ \ 'OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-0ubuntu0.18.04.1-b12)',
+ \ 'OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)'
+ \])
+
+ " OpenJDK Java 10
+ AssertEqual [10, 0, 2], ale_linters#java#eclipselsp#VersionCheck([
+ \ 'openjdk version "10.0.2" 2018-07-17',
+ \ 'OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4)',
+ \ 'OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4, mixed mode)'
+ \])
+
+ " Oracle Java 1.8
+ AssertEqual [1, 8, 0], ale_linters#java#eclipselsp#VersionCheck([
+ \ 'java version "1.8.0_161"',
+ \ 'Java(TM) SE Runtime Environment (build 1.8.0_161-b12)',
+ \ 'Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)'
+ \])
+
+ " Oracle Java 10
+ AssertEqual [10, 0, 1], ale_linters#java#eclipselsp#VersionCheck([
+ \ 'java version "10.0.1" 2018-04-17',
+ \ 'Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)',
+ \ 'Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)'
+ \])
+
+ AssertEqual [], ale_linters#java#eclipselsp#VersionCheck(['x'])
+
+ AssertEqual [], ale_linters#java#eclipselsp#VersionCheck([])
+
+Execute(The eclipselsp callback should return the correct default value):
+ let cmd = [ ale#Escape('java'),
+ \ '',
+ \ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
+ \ '-Dosgi.bundles.defaultStartLevel=4',
+ \ '-Declipse.product=org.eclipse.jdt.ls.core.product',
+ \ '-Dlog.level=ALL',
+ \ '-noverify',
+ \ '-Xmx1G',
+ \ '-jar',
+ \ ale#Escape(''),
+ \ '-configuration',
+ \ ale#Escape(b:cfg),
+ \ '-data',
+ \ ale#Escape(ale#path#Simplify(''))
+ \]
+ AssertLinter 'java', join(cmd, ' ')
+
+Execute(The eclipselsp callback should allow custom executable):
+ let b:ale_java_eclipselsp_executable='/bin/foobar'
+ let cmd = [ ale#Escape('/bin/foobar'),
+ \ '',
+ \ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
+ \ '-Dosgi.bundles.defaultStartLevel=4',
+ \ '-Declipse.product=org.eclipse.jdt.ls.core.product',
+ \ '-Dlog.level=ALL',
+ \ '-noverify',
+ \ '-Xmx1G',
+ \ '-jar',
+ \ ale#Escape(''),
+ \ '-configuration',
+ \ ale#Escape(b:cfg),
+ \ '-data',
+ \ ale#Escape(ale#path#Simplify(''))
+ \]
+ AssertLinter '/bin/foobar', join(cmd, ' ')
+
+Execute(The eclipselsp callback should allow custom configuration path and javaagent):
+ let b:ale_java_eclipselsp_config_path = '/home/config'
+ let b:ale_java_eclipselsp_javaagent = '/home/lombok.jar /home/lombok2.jar'
+ let cmd = [ ale#Escape('java'),
+ \ ale#Escape('-javaagent:/home/lombok.jar'),
+ \ ale#Escape('-javaagent:/home/lombok2.jar'),
+ \ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
+ \ '-Dosgi.bundles.defaultStartLevel=4',
+ \ '-Declipse.product=org.eclipse.jdt.ls.core.product',
+ \ '-Dlog.level=ALL',
+ \ '-noverify',
+ \ '-Xmx1G',
+ \ '-jar',
+ \ ale#Escape(''),
+ \ '-configuration',
+ \ ale#Escape(ale#path#Simplify('/home/config')),
+ \ '-data',
+ \ ale#Escape(ale#path#Simplify(''))
+ \]
+ AssertLinter 'java', join(cmd, ' ')
diff --git a/test/linter/test_elixir_credo.vader b/test/linter/test_elixir_credo.vader
new file mode 100644
index 00000000..9c639c57
--- /dev/null
+++ b/test/linter/test_elixir_credo.vader
@@ -0,0 +1,43 @@
+Before:
+ call ale#assert#SetUpLinterTest('elixir', 'credo')
+ call ale#test#SetFilename('../test-files/elixir/mix_project/lib/app.ex')
+
+
+After:
+ unlet! g:ale_elixir_credo_strict
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(Builds credo command with normal project):
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elixir/mix_project')
+ AssertLinter 'mix',
+ \ 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s'
+
+Execute(Builds credo command with umbrella project):
+ call ale#test#SetFilename('../test-files/elixir/umbrella_project/apps/mix_project/lib/app.ex')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elixir/umbrella_project')
+ AssertLinter 'mix',
+ \ 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s'
+
+Execute(Builds credo command with --strict mode when set to 1):
+ let g:ale_elixir_credo_strict = 1
+
+ AssertLinter 'mix',
+ \ 'mix help credo && mix credo --strict --format=flycheck --read-from-stdin %s'
+
+Execute(Builds credo command with suggest mode by default):
+ AssertLinter 'mix',
+ \ 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s'
+
+Execute(Builds credo command with suggest mode when set to 0):
+ let g:ale_elixir_credo_strict = 0
+
+ AssertLinter 'mix',
+ \ 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s'
+
+Execute(Builds credo command with a custom config file):
+ let g:ale_elixir_credo_config_file = '/home/user/custom_credo.exs'
+
+ AssertLinter 'mix',
+ \ 'mix help credo && mix credo suggest --config-file /home/user/custom_credo.exs --format=flycheck --read-from-stdin %s'
diff --git a/test/linter/test_elixir_ls.vader b/test/linter/test_elixir_ls.vader
new file mode 100644
index 00000000..84e805ba
--- /dev/null
+++ b/test/linter/test_elixir_ls.vader
@@ -0,0 +1,34 @@
+Before:
+ call ale#assert#SetUpLinterTest('elixir', 'elixir_ls')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set correct defaults):
+ if has('win32')
+ AssertLinter 'elixir-ls\language_server.bat', 'elixir-ls\language_server.bat'
+ else
+ AssertLinter 'elixir-ls/language_server.sh', 'elixir-ls/language_server.sh'
+ endif
+
+Execute(should configure elixir-ls release location):
+ let b:ale_elixir_elixir_ls_release = 'boo'
+
+ if has('win32')
+ AssertLinter 'boo\language_server.bat', 'boo\language_server.bat'
+ else
+ AssertLinter 'boo/language_server.sh', 'boo/language_server.sh'
+ endif
+
+Execute(should set correct LSP values):
+ call ale#test#SetFilename('../test-files/elixir/umbrella_project/apps/app1/lib/app.ex')
+
+ AssertLSPLanguage 'elixir'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/elixir/umbrella_project')
+
+Execute(should accept configuration settings):
+ AssertLSPConfig {}
+ let b:ale_elixir_elixir_ls_config = {'elixirLS': {'dialyzerEnabled': v:false}}
+ AssertLSPConfig {'elixirLS': {'dialyzerEnabled': v:false}}
diff --git a/test/linter/test_elixir_mix.vader b/test/linter/test_elixir_mix.vader
new file mode 100644
index 00000000..a04bee55
--- /dev/null
+++ b/test/linter/test_elixir_mix.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('elixir', 'mix')
+ call ale#test#SetFilename('../test-files/elixir/mix_project/lib/app.ex')
+ let g:env_prefix = ale#Env('MIX_BUILD_PATH', 'TEMP_DIR')
+
+After:
+ unlet! g:env_prefix
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default mix command should be correct):
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elixir/mix_project')
+ AssertLinter 'mix', g:env_prefix . 'mix compile %s'
+
+Execute(Build mix commands with an umbrella root):
+ call ale#test#SetFilename('../test-files/elixir/umbrella_project/apps/mix_project/lib/app.ex')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elixir/umbrella_project')
+ AssertLinter 'mix', g:env_prefix . 'mix compile %s'
diff --git a/test/linter/test_elm_ls.vader b/test/linter/test_elm_ls.vader
new file mode 100644
index 00000000..98b01c96
--- /dev/null
+++ b/test/linter/test_elm_ls.vader
@@ -0,0 +1,29 @@
+Before:
+ call ale#assert#SetUpLinterTest('elm', 'elm_ls')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ call ale#test#SetFilename('../test-files/elm/newapp/src/Main.elm')
+
+ AssertLinter 'elm-language-server', ale#Escape('elm-language-server') . ' --stdio'
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/elm/newapp/src/Main.elm')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/elm/newapp')
+
+Execute(Should let users configure a global executable and override local paths):
+ call ale#test#SetFilename('../test-files/elm/newapp/src/Main.elm')
+
+ let g:ale_elm_ls_executable = '/path/to/custom/elm-language-server'
+ let g:ale_elm_ls_use_global = 1
+
+ AssertLinter '/path/to/custom/elm-language-server',
+ \ ale#Escape('/path/to/custom/elm-language-server') . ' --stdio'
+
+Execute(The language should be correct):
+ AssertLSPLanguage 'elm'
diff --git a/test/linter/test_elm_make.vader b/test/linter/test_elm_make.vader
new file mode 100644
index 00000000..90e0c920
--- /dev/null
+++ b/test/linter/test_elm_make.vader
@@ -0,0 +1,63 @@
+Before:
+ call ale#assert#SetUpLinterTest('elm', 'make')
+
+After:
+ unlet! g:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(should get valid executable with default params):
+ call ale#test#SetFilename('../test-files/elm/newapp/src/Main.elm')
+
+ let g:executable = ale#path#Simplify(g:dir . '/../test-files/elm/newapp/node_modules/.bin/elm')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elm/newapp')
+ AssertLinter g:executable,
+ \ ale#Escape(g:executable) . ' make --report=json --output=/dev/null %t'
+
+Execute(should get elm-test executable for test code with elm >= 0.19):
+ call ale#test#SetFilename('../test-files/elm/newapp/tests/TestSuite.elm')
+
+ let g:executable = ale#path#Simplify(g:dir . '/../test-files/elm/newapp/node_modules/.bin/elm-test')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elm/newapp')
+ AssertLinter g:executable,
+ \ ale#Escape(g:executable) . ' make --report=json --output=/dev/null --compiler '
+ \ . ale#path#Simplify(g:dir . '/../test-files/elm/newapp/node_modules/.bin/elm') . ' %t'
+
+Execute(should fallback to elm executable with elm >= 0.19):
+ call ale#test#SetFilename('../test-files/elm/newapp-notests/tests/TestMain.elm')
+
+ let g:executable = ale#path#Simplify(g:dir . '/../test-files/elm/newapp-notests/node_modules/.bin/elm')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elm/newapp-notests')
+ AssertLinter g:executable,
+ \ ale#Escape(g:executable) . ' make --report=json --output=/dev/null %t'
+
+Execute(should get plain elm executable for test code with elm < 0.19):
+ call ale#test#SetFilename('../test-files/elm/oldapp/tests/TestSuite.elm')
+
+ let g:executable = ale#path#Simplify(g:dir . '/../test-files/elm/oldapp/node_modules/.bin/elm')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elm/oldapp')
+ AssertLinter g:executable,
+ \ ale#Escape(g:executable) . ' make --report=json --output=/dev/null %t'
+
+Execute(should get valid executable with 'use_global' params):
+ let g:ale_elm_make_use_global = 1
+
+ call ale#test#SetFilename('../test-files/elm/newapp/src/Main.elm')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elm/newapp')
+ AssertLinter 'elm',
+ \ ale#Escape('elm') . ' make --report=json --output=/dev/null %t'
+
+Execute(should get valid executable with 'use_global' and 'executable' params):
+ let g:ale_elm_make_executable = 'other-elm'
+ let g:ale_elm_make_use_global = 1
+
+ call ale#test#SetFilename('../test-files/elm/newapp/src/Main.elm')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/elm/newapp')
+ AssertLinter 'other-elm',
+ \ ale#Escape('other-elm') . ' make --report=json --output=/dev/null %t'
diff --git a/test/linter/test_embertemplatelint.vader b/test/linter/test_embertemplatelint.vader
new file mode 100644
index 00000000..97687d29
--- /dev/null
+++ b/test/linter/test_embertemplatelint.vader
@@ -0,0 +1,17 @@
+Before:
+ call ale#assert#SetUpLinterTest('handlebars', 'embertemplatelint')
+
+ GivenCommandOutput ['1.6.0']
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(ember-template-lint executables runs the right command):
+ AssertLinter 'ember-template-lint',
+ \ ale#Escape('ember-template-lint') . ' --json --filename %s'
+
+Execute(old ember-template-lint executables runs the right command):
+ GivenCommandOutput []
+
+ AssertLinter 'ember-template-lint',
+ \ ale#Escape('ember-template-lint') . ' --json %t'
diff --git a/test/linter/test_erb.vader b/test/linter/test_erb.vader
new file mode 100644
index 00000000..c64c7ba5
--- /dev/null
+++ b/test/linter/test_erb.vader
@@ -0,0 +1,16 @@
+Before:
+ call ale#assert#SetUpLinterTest('eruby', 'erb')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should not contain any filter code by default):
+ call ale#test#SetFilename('../test-files/ruby/not_a_rails_app/file.rb')
+
+ AssertLinter 'erb', 'erb -P -T - -x %t | ruby -c'
+
+Execute(Executable should filter invalid eRuby when inside a Rails project):
+ call ale#test#SetFilename('../test-files/ruby/valid_rails_app/app/views/my_great_view.html.erb')
+
+ AssertLinter 'erb',
+ \ 'ruby -r erb -e ' . ale#Escape('puts ERB.new($stdin.read.gsub(%{<%=},%{<%}), nil, %{-}).src') . '< %t | ruby -c'
diff --git a/test/linter/test_erlang_dialyzer.vader b/test/linter/test_erlang_dialyzer.vader
new file mode 100644
index 00000000..5e818d7f
--- /dev/null
+++ b/test/linter/test_erlang_dialyzer.vader
@@ -0,0 +1,45 @@
+Before:
+ call ale#assert#SetUpLinterTest('erlang', 'dialyzer')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct.):
+ AssertLinter 'dialyzer',
+ \ ale#Escape('dialyzer')
+ \ . ' -n --plt ' . ale#Escape(expand('$HOME/.dialyzer_plt'))
+ \ . ' -Wunmatched_returns'
+ \ . ' -Werror_handling'
+ \ . ' -Wrace_conditions'
+ \ . ' -Wunderspecs'
+ \ . ' %s'
+
+Execute(The command should accept configured executable.):
+ let b:ale_erlang_dialyzer_executable = '/usr/bin/dialyzer'
+ AssertLinter '/usr/bin/dialyzer',
+ \ ale#Escape('/usr/bin/dialyzer')
+ \ . ' -n --plt ' . ale#Escape(expand('$HOME/.dialyzer_plt'))
+ \ . ' -Wunmatched_returns'
+ \ . ' -Werror_handling'
+ \ . ' -Wrace_conditions'
+ \ . ' -Wunderspecs'
+ \ . ' %s'
+
+Execute(The command should accept configured options.):
+ let b:ale_erlang_dialyzer_options = '-r ' . expand('$HOME')
+ AssertLinter 'dialyzer',
+ \ ale#Escape('dialyzer')
+ \ . ' -n --plt ' . ale#Escape(expand('$HOME/.dialyzer_plt'))
+ \ . ' -r ' . expand('$HOME')
+ \ . ' %s'
+
+Execute(The command should accept configured PLT file.):
+ let b:ale_erlang_dialyzer_plt_file = 'custom-plt'
+ AssertLinter 'dialyzer',
+ \ ale#Escape('dialyzer')
+ \ . ' -n --plt ' . ale#Escape(expand('custom-plt'))
+ \ . ' -Wunmatched_returns'
+ \ . ' -Werror_handling'
+ \ . ' -Wrace_conditions'
+ \ . ' -Wunderspecs'
+ \ . ' %s'
diff --git a/test/linter/test_erlang_elvis.vader b/test/linter/test_erlang_elvis.vader
new file mode 100644
index 00000000..4aab49d6
--- /dev/null
+++ b/test/linter/test_erlang_elvis.vader
@@ -0,0 +1,16 @@
+Before:
+ let b:file = fnamemodify(bufname(''), ':.')
+ call ale#assert#SetUpLinterTest('erlang', 'elvis')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Default command should be correct):
+ AssertLinter 'elvis',
+ \ ale#Escape('elvis') . ' rock --output-format=parsable ' . ale#Escape(b:file)
+
+Execute(Executable should be configurable):
+ let b:ale_erlang_elvis_executable = '/path/to/elvis'
+
+ AssertLinter '/path/to/elvis',
+ \ ale#Escape('/path/to/elvis') . ' rock --output-format=parsable ' . ale#Escape(b:file)
diff --git a/test/linter/test_erlang_erlc.vader b/test/linter/test_erlang_erlc.vader
new file mode 100644
index 00000000..7d659a07
--- /dev/null
+++ b/test/linter/test_erlang_erlc.vader
@@ -0,0 +1,40 @@
+Before:
+ call ale#assert#SetUpLinterTest('erlang', 'erlc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct.):
+ let g:cmd = ale_linters#erlang#erlc#GetCommand(bufnr(''))
+ let g:regex = 'erlc.\+-o.\+%t'
+ let g:matched = match(g:cmd, g:regex)
+
+ " match returns -1 if not found
+ AssertNotEqual
+ \ g:matched,
+ \ -1,
+ \ 'Command error: expected [' . g:cmd . '] to match [' . g:regex . ']'
+
+Execute(The command should accept configured executable.):
+ let b:ale_erlang_erlc_executable = '/usr/bin/erlc'
+ let g:cmd = ale_linters#erlang#erlc#GetCommand(bufnr(''))
+ let g:regex = '/usr/bin/erlc.\+-o.\+%t'
+ let g:matched = match(g:cmd, g:regex)
+
+ " match returns -1 if not found
+ AssertNotEqual
+ \ g:matched,
+ \ -1,
+ \ 'Command error: expected [' . g:cmd . '] to match [' . g:regex . ']'
+
+Execute(The command should accept configured options.):
+ let b:ale_erlang_erlc_options = '-I include'
+ let g:cmd = ale_linters#erlang#erlc#GetCommand(bufnr(''))
+ let g:regex = 'erlc.\+-o.\+-I include.\+%t'
+ let g:matched = match(g:cmd, g:regex)
+
+ " match returns -1 if not found
+ AssertNotEqual
+ \ g:matched,
+ \ -1,
+ \ 'Command error: expected [' . g:cmd . '] to match [' . g:regex . ']'
diff --git a/test/linter/test_erlang_syntaxerl.vader b/test/linter/test_erlang_syntaxerl.vader
new file mode 100644
index 00000000..e7cc26ea
--- /dev/null
+++ b/test/linter/test_erlang_syntaxerl.vader
@@ -0,0 +1,45 @@
+Before:
+ call ale#assert#SetUpLinterTest('erlang', 'syntaxerl')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute (The default commands should be correct):
+ AssertLinter 'syntaxerl', [
+ \ ale#Escape('syntaxerl') . ' -h',
+ \ ale#Escape('syntaxerl') . ' %t',
+ \]
+
+Execute (The executable should be configurable):
+ let b:ale_erlang_syntaxerl_executable = 'foobar'
+
+ AssertLinter 'foobar', [
+ \ ale#Escape('foobar') . ' -h',
+ \ ale#Escape('foobar') . ' %t',
+ \]
+
+Execute (The -b option should be used when available):
+ GivenCommandOutput [
+ \ 'Syntax checker for Erlang (0.14.0)',
+ \ 'Usage: syntaxerl [-d | --debug] <FILENAME>',
+ \ ' syntaxerl <-h | --help>',
+ \ ' -d, --debug Enable debug output',
+ \ ' -h, --help Show this message',
+ \]
+ AssertLinter 'syntaxerl', [
+ \ ale#Escape('syntaxerl') . ' -h',
+ \ ale#Escape('syntaxerl') . ' %t',
+ \]
+
+ GivenCommandOutput [
+ \ 'Syntax checker for Erlang (0.14.0)',
+ \ 'Usage: syntaxerl [-b | --base <FILENAME>] [-d | --debug] <FILENAME>',
+ \ ' syntaxerl <-h | --help>',
+ \ ' -b, --base Set original filename',
+ \ ' -d, --debug Enable debug output',
+ \ ' -h, --help Show this message',
+ \]
+ AssertLinter 'syntaxerl', [
+ \ ale#Escape('syntaxerl') . ' -h',
+ \ ale#Escape('syntaxerl') . ' -b %s %t',
+ \]
diff --git a/test/linter/test_erubi.vader b/test/linter/test_erubi.vader
new file mode 100644
index 00000000..cd4a0b68
--- /dev/null
+++ b/test/linter/test_erubi.vader
@@ -0,0 +1,32 @@
+Before:
+ call ale#assert#SetUpLinterTest('eruby', 'erubi')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should not contain any filter code by default):
+ call ale#test#SetFilename('../test-files/ruby/not_a_rails_app/file.rb')
+
+ AssertLinter 'ruby', [
+ \ 'ruby -r erubi/capture_end -e ' . ale#Escape('""'),
+ \ 'ruby -r erubi/capture_end -e ' . ale#Escape('puts Erubi::CaptureEndEngine.new($stdin.read).src') . '< %t | ruby -c',
+ \]
+
+Execute(Executable should filter invalid eRuby when inside a Rails project):
+ call ale#test#SetFilename('../test-files/ruby/valid_rails_app/app/views/my_great_view.html.erb')
+
+ AssertLinter 'ruby', [
+ \ 'ruby -r erubi/capture_end -e ' . ale#Escape('""'),
+ \ 'ruby -r erubi/capture_end -e ' . ale#Escape('puts Erubi::CaptureEndEngine.new($stdin.read.gsub(%{<%=},%{<%}), nil, %{-}).src') . '< %t | ruby -c',
+ \]
+
+Execute(Command should be blank if the first command in the chain returns output):
+ GivenCommandOutput [
+ \ "/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- erubi/capture_end (LoadError)",
+ \ " from /usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'",
+ \]
+
+ AssertLinter 'ruby', [
+ \ 'ruby -r erubi/capture_end -e ' . ale#Escape('""'),
+ \ '',
+ \]
diff --git a/test/linter/test_erubis.vader b/test/linter/test_erubis.vader
new file mode 100644
index 00000000..cfca54a2
--- /dev/null
+++ b/test/linter/test_erubis.vader
@@ -0,0 +1,16 @@
+Before:
+ call ale#assert#SetUpLinterTest('eruby', 'erubis')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should not contain any filter code by default):
+ call ale#test#SetFilename('../test-files/ruby/not_a_rails_app/file.rb')
+
+ AssertLinter 'erubis', 'erubis -x %t | ruby -c'
+
+Execute(Executable should filter invalid eRuby when inside a Rails project):
+ call ale#test#SetFilename('../test-files/ruby/valid_rails_app/app/views/my_great_view.html.erb')
+
+ AssertLinter 'erubis',
+ \ 'ruby -r erubis -e ' . ale#Escape('puts Erubis::Eruby.new($stdin.read.gsub(%{<%=},%{<%})).src') . '< %t | ruby -c'
diff --git a/test/linter/test_eslint.vader b/test/linter/test_eslint.vader
new file mode 100644
index 00000000..81518af9
--- /dev/null
+++ b/test/linter/test_eslint.vader
@@ -0,0 +1,76 @@
+Before:
+ call ale#assert#SetUpLinterTest('javascript', 'eslint')
+ runtime autoload/ale/handlers/eslint.vim
+
+ let b:args = ' -f json --stdin --stdin-filename %s'
+
+After:
+ unlet! b:args
+ unlet! b:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinterCwd ''
+ AssertLinter 'eslint', ale#Escape('eslint') . b:args
+
+Execute(create-react-app directories should be detected correctly):
+ call ale#test#SetFilename('../test-files/eslint/react-app/subdir/testfile.js')
+
+ let b:executable = ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js')
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/eslint/react-app')
+ AssertLinter b:executable,
+ \ (has('win32') ? ale#Escape('node.exe') . ' ' : '')
+ \ . ale#Escape(b:executable) . b:args
+
+Execute(use-global should override create-react-app detection):
+ call ale#test#SetFilename('../test-files/eslint/react-app/subdir/testfile.js')
+
+ let g:ale_javascript_eslint_use_global = 1
+ let g:ale_javascript_eslint_executable = 'eslint_d'
+
+ let b:executable = 'eslint_d'
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/eslint/react-app')
+ AssertLinter b:executable, ale#Escape(b:executable) . b:args
+
+Execute(other app directories should be detected correctly):
+ call ale#test#SetFilename('../test-files/eslint/other-app/subdir/testfile.js')
+
+ let b:executable = ale#path#Simplify(g:dir . '/../test-files/eslint/node_modules/.bin/eslint')
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/eslint')
+ AssertLinter b:executable, ale#Escape(b:executable) . b:args
+
+Execute(use-global should override other app directories):
+ call ale#test#SetFilename('../test-files/eslint/other-app/subdir/testfile.js')
+
+ let g:ale_javascript_eslint_use_global = 1
+ let g:ale_javascript_eslint_executable = 'eslint_d'
+
+ let b:executable = 'eslint_d'
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/eslint')
+ AssertLinter b:executable, ale#Escape(b:executable) . b:args
+
+Execute(eslint_d should be detected correctly):
+ call ale#test#SetFilename('../test-files/eslint/app-with-eslint-d/testfile.js')
+
+ let b:executable = ale#path#Simplify(g:dir . '/../test-files/eslint/app-with-eslint-d/node_modules/.bin/eslint_d')
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/eslint/app-with-eslint-d')
+ AssertLinter b:executable, ale#Escape(b:executable) . b:args
+
+Execute(eslint.js executables should be run with node on Windows):
+ call ale#test#SetFilename('../test-files/eslint/react-app/subdir/testfile.js')
+
+ let b:executable = ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js')
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/eslint/react-app')
+ AssertLinter b:executable,
+ \ (has('win32') ? ale#Escape('node.exe') . ' ' : '')
+ \ . ale#Escape(b:executable) . b:args
+
+Execute(eslint.js should be run from a containing project with eslint):
+ call ale#test#SetFilename('../test-files/eslint/react-app/subdir-with-package-json/testfile.js')
+
+ let b:executable = ale#path#Simplify(g:dir . '/../test-files/eslint/react-app/node_modules/eslint/bin/eslint.js')
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/eslint/react-app')
+ AssertLinter b:executable,
+ \ (has('win32') ? ale#Escape('node.exe') . ' ' : '')
+ \ . ale#Escape(b:executable) . b:args
diff --git a/test/linter/test_fecs.vader b/test/linter/test_fecs.vader
new file mode 100644
index 00000000..4287d324
--- /dev/null
+++ b/test/linter/test_fecs.vader
@@ -0,0 +1,9 @@
+Before:
+ call ale#assert#SetUpLinterTest('javascript', 'fecs')
+ runtime autoload/ale/handlers/fecs.vim
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'fecs', ale#Escape('fecs') . ' check --colors=false --rule=true %t'
diff --git a/test/linter/test_flake8.vader b/test/linter/test_flake8.vader
new file mode 100644
index 00000000..81efe497
--- /dev/null
+++ b/test/linter/test_flake8.vader
@@ -0,0 +1,201 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'flake8')
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+ GivenCommandOutput ['3.0.0']
+
+After:
+ unlet! b:executable
+ unlet! b:bin_dir
+ call ale#assert#TearDownLinterTest()
+
+Execute(The flake8 callbacks should return the correct default values):
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+ " The version check should be cached.
+ GivenCommandOutput []
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+ " Try with older versions.
+ call ale#semver#ResetVersionCache()
+ GivenCommandOutput ['2.9.9']
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#Escape('flake8') . ' --format=default -',
+ \]
+
+Execute(The option for disabling changing directories should work):
+ let g:ale_python_flake8_change_directory = 'off'
+
+ AssertLinterCwd ['', '']
+ call ale#semver#ResetVersionCache()
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+ let g:ale_python_flake8_change_directory = 0
+
+ AssertLinterCwd ['']
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+ " Invalid options should be considered the same as turning the setting off.
+ let g:ale_python_flake8_change_directory = 'xxx'
+
+ AssertLinterCwd ['']
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+Execute(The option for changing directory to project root should work):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/namespace_package_tox/namespace/foo/bar.py')
+
+ AssertLinterCwd ale#python#FindProjectRootIni(bufnr(''))
+ call ale#semver#ResetVersionCache()
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+Execute(The option for changing directory to file dir should work):
+ let g:ale_python_flake8_change_directory = 'file'
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/namespace_package_tox/namespace/foo/bar.py')
+
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+ let g:ale_python_flake8_change_directory = 1
+
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+Execute(The flake8 command callback should let you set options):
+ let g:ale_python_flake8_options = '--some-option'
+
+ GivenCommandOutput ['3.0.4']
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#Escape('flake8') . ' --some-option'
+ \ . ' --format=default --stdin-display-name %s -',
+ \]
+
+ call ale#semver#ResetVersionCache()
+ GivenCommandOutput ['2.9.9']
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#Escape('flake8') . ' --some-option --format=default -',
+ \]
+
+Execute(You should be able to set a custom executable and it should be escaped):
+ let g:ale_python_flake8_executable = 'executable with spaces'
+
+ AssertLinterCwd ['%s:h', '%s:h']
+ call ale#semver#ResetVersionCache()
+ AssertLinter 'executable with spaces', [
+ \ ale#Escape('executable with spaces') . ' --version',
+ \ ale#Escape('executable with spaces')
+ \ . ' --format=default'
+ \ . ' --stdin-display-name %s -',
+ \]
+
+Execute(The flake8 callbacks should detect virtualenv directories):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/flake8'
+ \)
+
+ AssertLinter b:executable, [
+ \ ale#Escape(b:executable) . ' --version',
+ \ ale#Escape(b:executable)
+ \ . ' --format=default'
+ \ . ' --stdin-display-name %s -',
+ \]
+
+Execute(The FindProjectRoot should detect the project root directory for namespace package via Manifest.in):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/namespace_package_manifest/namespace/foo/bar.py')
+
+ AssertEqual
+ \ ale#path#Simplify(g:dir . '/../test-files/python/namespace_package_manifest'),
+ \ ale#python#FindProjectRoot(bufnr(''))
+
+Execute(The FindProjectRoot should detect the project root directory for namespace package via setup.cf):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/namespace_package_setup/namespace/foo/bar.py')
+
+ AssertEqual
+ \ ale#path#Simplify(g:dir . '/../test-files/python/namespace_package_setup'),
+ \ ale#python#FindProjectRoot(bufnr(''))
+
+Execute(The FindProjectRoot should detect the project root directory for namespace package via pytest.ini):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/namespace_package_pytest/namespace/foo/bar.py')
+
+ AssertEqual
+ \ ale#path#Simplify(g:dir . '/../test-files/python/namespace_package_pytest'),
+ \ ale#python#FindProjectRoot(bufnr(''))
+
+Execute(The FindProjectRoot should detect the project root directory for namespace package via tox.ini):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/namespace_package_tox/namespace/foo/bar.py')
+
+ AssertEqual
+ \ ale#path#Simplify(g:dir . '/../test-files/python/namespace_package_tox'),
+ \ ale#python#FindProjectRoot(bufnr(''))
+
+Execute(The FindProjectRoot should detect the project root directory for non-namespace package):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/no_virtualenv/subdir/foo/bar.py')
+
+ AssertEqual
+ \ ale#path#Simplify(g:dir . '/../test-files/python/no_virtualenv/subdir'),
+ \ ale#python#FindProjectRoot(bufnr(''))
+
+" Some users currently run flake8 this way, so we should support it.
+Execute(Using `python -m flake8` should be supported for running flake8):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let g:ale_python_flake8_executable = 'python'
+ let g:ale_python_flake8_options = '-m flake8 --some-option'
+
+ GivenCommandOutput ['2.9.9']
+ AssertLinter 'python', [
+ \ ale#Escape('python') . ' -m flake8 --version',
+ \ ale#Escape('python')
+ \ . ' -m flake8 --some-option --format=default -'
+ \]
+
+ call ale#semver#ResetVersionCache()
+
+ " Leading spaces shouldn't matter
+ let g:ale_python_flake8_options = ' -m flake8 --some-option'
+
+ GivenCommandOutput ['2.9.9']
+ AssertLinter 'python', [
+ \ ale#Escape('python') . ' -m flake8 --version',
+ \ ale#Escape('python')
+ \ . ' -m flake8 --some-option --format=default -'
+ \]
+
+Execute(Setting executable to 'pipenv' should append 'run flake8'):
+ let g:ale_python_flake8_executable = 'path/to/pipenv'
+
+ " FIXME: pipenv should check the version with flake8.
+ GivenCommandOutput []
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv') . ' run flake8 --format=default -'
+
+Execute(Pipenv is detected when python_flake8_auto_pipenv is set):
+ let g:ale_python_flake8_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinterCwd ale#python#FindProjectRootIni(bufnr(''))
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv') . ' run flake8 --format=default --stdin-display-name %s -'
diff --git a/test/linter/test_flow.vader b/test/linter/test_flow.vader
new file mode 100644
index 00000000..8488a2e9
--- /dev/null
+++ b/test/linter/test_flow.vader
@@ -0,0 +1,42 @@
+Before:
+ call ale#assert#SetUpLinterTest('javascript', 'flow')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(flow should return a command to run if a .flowconfig file exists):
+ call ale#test#SetFilename('../test-files/flow/a/sub/dummy')
+
+ AssertLinter 'flow',
+ \ ale#Escape('flow')
+ \ . ' check-contents --respect-pragma --json --from ale %s < %t'
+ \ . (!has('win32') ? '; echo' : '')
+
+Execute(flow should not use the respect pragma argument if the option is off):
+ call ale#test#SetFilename('../test-files/flow/a/sub/dummy')
+
+ let b:ale_javascript_flow_use_respect_pragma = 0
+
+ AssertLinter 'flow',
+ \ ale#Escape('flow')
+ \ . ' check-contents --json --from ale %s < %t'
+ \ . (!has('win32') ? '; echo' : '')
+
+Execute(flow should should not use --respect-pragma for old versions):
+ call ale#test#SetFilename('../test-files/flow/a/sub/dummy')
+
+ GivenCommandOutput [
+ \ 'Warning: `flow --version` is deprecated in favor of `flow version`',
+ \ 'Flow, a static type checker for JavaScript, version 0.27.0',
+ \]
+ AssertLinter 'flow', [
+ \ ale#Escape('flow') . ' --version',
+ \ ale#Escape('flow')
+ \ . ' check-contents --json --from ale %s < %t'
+ \ . (!has('win32') ? '; echo' : ''),
+ \]
+
+Execute(flow should not return a command to run if no .flowconfig file exists):
+ call ale#test#SetFilename('../test-files/flow/b/sub/dummy')
+
+ AssertLinterNotExecuted
diff --git a/test/linter/test_foodcritic.vader b/test/linter/test_foodcritic.vader
new file mode 100644
index 00000000..c5564cb1
--- /dev/null
+++ b/test/linter/test_foodcritic.vader
@@ -0,0 +1,18 @@
+Before:
+ call ale#assert#SetUpLinterTest('chef', 'foodcritic')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'foodcritic', ale#Escape('foodcritic') . ' %s'
+
+Execute(Extra options should be included with escapeed tildes (~)):
+ let b:ale_chef_foodcritic_options = '-t ~F011'
+
+ AssertLinter 'foodcritic', ale#Escape('foodcritic') . ' -t \~F011 %s'
+
+Execute(The executable should be configurable):
+ let b:ale_chef_foodcritic_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' %s'
diff --git a/test/linter/test_fortran_fortls.vader b/test/linter/test_fortran_fortls.vader
new file mode 100644
index 00000000..581f94ba
--- /dev/null
+++ b/test/linter/test_fortran_fortls.vader
@@ -0,0 +1,18 @@
+Before:
+ call ale#assert#SetUpLinterTest('fortran', 'language_server')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'fortls', ale#Escape('fortls')
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/fortls-project/test.F90')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/fortls-project')
+
+Execute(The language should be correct):
+ AssertLSPLanguage 'fortran'
diff --git a/test/linter/test_fsc.vader b/test/linter/test_fsc.vader
new file mode 100644
index 00000000..278e7c16
--- /dev/null
+++ b/test/linter/test_fsc.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('scala', 'fsc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Given scala(An empty Scala file):
+Execute(The default executable and command should be correct):
+ AssertLinter 'fsc', ale#Escape('fsc') . ' -Ystop-after:parser %t'
+
+Given scala.sbt(An empty SBT file):
+Execute(fsc should not be run for sbt files):
+ AssertLinterNotExecuted
diff --git a/test/linter/test_fusionlint.vader b/test/linter/test_fusionlint.vader
new file mode 100644
index 00000000..1c63b811
--- /dev/null
+++ b/test/linter/test_fusionlint.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('fuse', 'fusionlint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The fuse fusionlint command callback should return the correct default string):
+ AssertLinter 'fusion-lint', ale#Escape('fusion-lint') . ' --filename %s -i'
+
+Execute(The fuse fusionlint command callback should let you set options):
+ let g:ale_fuse_fusionlint_options = '--example-option argument'
+
+ AssertLinter 'fusion-lint',
+ \ ale#Escape('fusion-lint') . ' --example-option argument --filename %s -i'
+
+Execute(The fusionlint executable should be configurable):
+ let g:ale_fuse_fusionlint_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --filename %s -i'
diff --git a/test/linter/test_gawk.vader b/test/linter/test_gawk.vader
new file mode 100644
index 00000000..ba9f59ab
--- /dev/null
+++ b/test/linter/test_gawk.vader
@@ -0,0 +1,25 @@
+Before:
+ call ale#assert#SetUpLinterTest('awk', 'gawk')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'gawk',
+ \ ale#Escape('gawk') . ' --source ' . ale#Escape('BEGIN { exit } END { exit 1 }')
+ \ . ' -f %t --lint /dev/null'
+
+Execute(The executable should be configurable):
+ let b:ale_awk_gawk_executable = '/other/gawk'
+
+ AssertLinter '/other/gawk',
+ \ ale#Escape('/other/gawk') . ' --source ' . ale#Escape('BEGIN { exit } END { exit 1 }')
+ \ . ' -f %t --lint /dev/null'
+
+Execute(The options should be configurable):
+ let b:ale_awk_gawk_executable = 'gawk'
+ let b:ale_awk_gawk_options = '--something'
+
+ AssertLinter 'gawk',
+ \ ale#Escape('gawk') . ' --source ' . ale#Escape('BEGIN { exit } END { exit 1 }')
+ \ . ' --something -f %t --lint /dev/null'
diff --git a/test/linter/test_gfortran.vader b/test/linter/test_gfortran.vader
new file mode 100644
index 00000000..3e6ef951
--- /dev/null
+++ b/test/linter/test_gfortran.vader
@@ -0,0 +1,24 @@
+Before:
+ call ale#assert#SetUpLinterTest('fortran', 'gcc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The fortran gcc command callback should return the correct default string):
+ AssertLinter 'gcc', ale#Escape('gcc') . ' -S -x f95 -fsyntax-only -ffree-form -Wall -'
+
+Execute(The fortran gcc command callback should let you set options):
+ let g:ale_fortran_gcc_options = '-Wotherthings'
+
+ AssertLinter 'gcc', ale#Escape('gcc') . ' -S -x f95 -fsyntax-only -ffree-form -Wotherthings -'
+
+Execute(The fortran gcc command callback should let you use -ffixed-form):
+ let g:ale_fortran_gcc_use_free_form = 0
+
+ AssertLinter 'gcc', ale#Escape('gcc') . ' -S -x f95 -fsyntax-only -ffixed-form -Wall -'
+
+Execute(The fortran executable should be configurable):
+ let g:ale_fortran_gcc_executable = 'gfortran'
+
+ AssertLinter 'gfortran',
+ \ ale#Escape('gfortran') . ' -S -x f95 -fsyntax-only -ffree-form -Wall -'
diff --git a/test/linter/test_ghdl.vader b/test/linter/test_ghdl.vader
new file mode 100644
index 00000000..f254e11f
--- /dev/null
+++ b/test/linter/test_ghdl.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('vhdl', 'ghdl')
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'ghdl', ale#Escape('ghdl') . ' -s --std=08 %t'
+
+ let b:ale_vhdl_ghdl_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' -s --std=08 %t'
+
+Execute(The options should be configurable):
+ let b:ale_vhdl_ghdl_options = '--something'
+
+ AssertLinter 'ghdl', ale#Escape('ghdl') . ' -s --something %t'
diff --git a/test/linter/test_gitlint.vader b/test/linter/test_gitlint.vader
new file mode 100644
index 00000000..4df675f3
--- /dev/null
+++ b/test/linter/test_gitlint.vader
@@ -0,0 +1,43 @@
+Before:
+ call ale#assert#SetUpLinterTest('gitcommit', 'gitlint')
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The gitlint callbacks should return the correct default values):
+ AssertLinter 'gitlint', ale#Escape('gitlint') . ' lint'
+
+Execute(The gitlint executable should be configurable, and escaped properly):
+ let g:ale_gitcommit_gitlint_executable = 'executable with spaces'
+
+ AssertLinter 'executable with spaces',
+ \ ale#Escape('executable with spaces') . ' lint'
+
+Execute(The gitlint command callback should let you set options):
+ let g:ale_gitcommit_gitlint_options = '--some-option'
+
+ AssertLinter 'gitlint', ale#Escape('gitlint') . ' --some-option lint'
+
+Execute(The gitlint callbacks shouldn't detect virtualenv directories where they don't exist):
+ call ale#test#SetFilename('../test-files/python/no_virtualenv/subdir/foo/COMMIT_EDITMSG')
+
+ AssertLinter 'gitlint', ale#Escape('gitlint') . ' lint'
+
+Execute(The gitlint callbacks should detect virtualenv directories):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/COMMIT_EDITMSG')
+ let b:executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/gitlint'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' lint'
+
+Execute(You should able able to use the global gitlint instead):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/COMMIT_EDITMSG')
+ let g:ale_gitcommit_gitlint_use_global = 1
+
+ AssertLinter 'gitlint', ale#Escape('gitlint') . ' lint'
diff --git a/test/linter/test_glslang.vader b/test/linter/test_glslang.vader
new file mode 100644
index 00000000..980406af
--- /dev/null
+++ b/test/linter/test_glslang.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('glsl', 'glslang')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'glslangValidator', ale#Escape('glslangValidator') . ' -C %t'
+
+Execute(The executable should be configurable):
+ let b:ale_glsl_glslang_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' -C %t'
+
+Execute(Options should work):
+ let g:ale_glsl_glslang_options = '--test'
+
+ AssertLinter 'glslangValidator',
+ \ ale#Escape('glslangValidator') . ' --test -C %t'
diff --git a/test/linter/test_glslls.vader b/test/linter/test_glslls.vader
new file mode 100644
index 00000000..133c2a2f
--- /dev/null
+++ b/test/linter/test_glslls.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('glsl', 'glslls')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'glslls', ale#Escape('glslls') . ' --stdin'
+
+Execute(Executable should be configurable):
+ let b:ale_glsl_glslls_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin'
+
+Execute(Setting logfile should work):
+ let b:ale_glsl_glslls_logfile = '/tmp/test.log'
+
+ AssertLinter 'glslls',
+ \ ale#Escape('glslls') . ' --verbose -l /tmp/test.log --stdin'
diff --git a/test/linter/test_gobuild.vader b/test/linter/test_gobuild.vader
new file mode 100644
index 00000000..bac4d74e
--- /dev/null
+++ b/test/linter/test_gobuild.vader
@@ -0,0 +1,33 @@
+Before:
+ Save g:ale_go_go_executable
+
+ call ale#assert#SetUpLinterTest('go', 'gobuild')
+
+ GivenCommandOutput ['/foo/bar', '/foo/baz']
+
+After:
+ Restore
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'go', 'go test -c -o /dev/null ./'
+
+Execute(Go environment variables should be supported):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'go', ale#Env('GO111MODULE', 'on') . 'go test -c -o /dev/null ./'
+
+ unlet! b:ale_go_go111module
+
+Execute(Extra options should be supported):
+ let g:ale_go_gobuild_options = '--foo-bar'
+
+ AssertLinter 'go', 'go test --foo-bar -c -o /dev/null ./'
+
+ let g:ale_go_gobuild_options = ''
+
+Execute(The executable should be configurable):
+ let g:ale_go_go_executable = 'foobar'
+
+ AssertLinter 'foobar', 'foobar test -c -o /dev/null ./'
diff --git a/test/linter/test_gofmt.vader b/test/linter/test_gofmt.vader
new file mode 100644
index 00000000..b056a659
--- /dev/null
+++ b/test/linter/test_gofmt.vader
@@ -0,0 +1,26 @@
+Before:
+ Save g:ale_go_go111module
+ Save b:ale_go_go111module
+
+ let b:ale_go_go111module = ''
+
+ call ale#assert#SetUpLinterTest('go', 'gofmt')
+ call ale#test#SetFilename('../test-files/go/testfile2.go')
+
+After:
+ Restore
+
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default gofmt command should be correct):
+ AssertLinter 'gofmt',
+ \ ale#Escape('gofmt') . ' -e %t'
+
+Execute(The gofmt command should support Go environment variables):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'gofmt',
+ \ ale#Env('GO111MODULE', 'on')
+ \ . ale#Escape('gofmt') . ' -e %t'
diff --git a/test/linter/test_golangci_lint.vader b/test/linter/test_golangci_lint.vader
new file mode 100644
index 00000000..ee754bba
--- /dev/null
+++ b/test/linter/test_golangci_lint.vader
@@ -0,0 +1,50 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'golangci_lint')
+ call ale#test#SetFilename('test.go')
+
+After:
+ Restore
+
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The golangci-lint defaults should be correct):
+ AssertLinterCwd '%s:h',
+ AssertLinter 'golangci-lint',
+ \ ale#Escape('golangci-lint')
+ \ . ' run ' . ale#Escape(expand('%' . ':t'))
+ \ . ' --enable-all'
+
+Execute(The golangci-lint callback should use a configured executable):
+ let b:ale_go_golangci_lint_executable = 'something else'
+
+ AssertLinter 'something else',
+ \ ale#Escape('something else')
+ \ . ' run ' . ale#Escape(expand('%' . ':t'))
+ \ . ' --enable-all'
+
+Execute(The golangci-lint callback should use configured options):
+ let b:ale_go_golangci_lint_options = '--foobar'
+
+ AssertLinter 'golangci-lint',
+ \ ale#Escape('golangci-lint')
+ \ . ' run ' . ale#Escape(expand('%' . ':t'))
+ \ . ' --foobar'
+
+Execute(The golangci-lint callback should support environment variables):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'golangci-lint',
+ \ ale#Env('GO111MODULE', 'on')
+ \ . ale#Escape('golangci-lint')
+ \ . ' run ' . ale#Escape(expand('%' . ':t'))
+ \ . ' --enable-all'
+
+Execute(The golangci-lint `lint_package` option should use the correct command):
+ let b:ale_go_golangci_lint_package = 1
+
+ AssertLinter 'golangci-lint',
+ \ ale#Escape('golangci-lint') . ' run --enable-all'
diff --git a/test/linter/test_golangserver.vader b/test/linter/test_golangserver.vader
new file mode 100644
index 00000000..b31d8dc8
--- /dev/null
+++ b/test/linter/test_golangserver.vader
@@ -0,0 +1,76 @@
+Before:
+ Save $GOPATH
+ Save g:ale_completion_enabled
+ Save g:ale_go_go111module
+
+ let g:ale_completion_enabled = 0
+ let g:sep = has('win32') ? ';' : ':'
+
+ call ale#assert#SetUpLinterTest('go', 'langserver')
+ let $GOPATH = ale#path#Simplify(g:dir . '/../test-files/go/go1')
+ \ . g:sep
+ \ . ale#path#Simplify(g:dir . '/../test-files/go/go2')
+
+After:
+ Restore
+
+ unlet! b:ale_completion_enabled
+ unlet! b:ale_go_go111module
+ unlet! g:sep
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set correct defaults):
+ AssertLinter 'go-langserver', ale#Escape('go-langserver')
+
+Execute(should configure go-langserver callback executable):
+ let b:ale_go_langserver_executable = 'boo'
+
+ AssertLinter 'boo', ale#Escape('boo')
+
+Execute(should set go-langserver options):
+ call ale#test#SetFilename('../test-files/go/go1/prj1/file.go')
+ let b:ale_completion_enabled = 1
+ let b:ale_go_langserver_options = ''
+
+ AssertLinter 'go-langserver',
+ \ ale#Escape('go-langserver') . ' -gocodecompletion'
+
+ let b:ale_go_langserver_options = '-trace'
+
+ AssertLinter 'go-langserver',
+ \ ale#Escape('go-langserver') . ' -gocodecompletion -trace'
+
+Execute(should ignore go-langserver -gocodecompletion option):
+ call ale#test#SetFilename('../test-files/go/go1/prj1/file.go')
+
+ let b:ale_go_langserver_options = '-trace -gocodecompletion'
+ let b:ale_completion_enabled = 1
+
+ AssertLinter 'go-langserver',
+ \ ale#Escape('go-langserver') . ' -gocodecompletion -trace'
+
+ let b:ale_completion_enabled = 0
+
+ AssertLinter 'go-langserver', ale#Escape('go-langserver') . ' -trace'
+
+Execute(should support Go environment variables):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'go-langserver',
+ \ ale#Env('GO111MODULE', 'on') . ale#Escape('go-langserver')
+
+Execute(should set go-langserver for go app1):
+ call ale#test#SetFilename('../test-files/go/go1/prj1/file.go')
+
+ AssertLSPLanguage 'go'
+ AssertLSPConfig {}
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/go/go1')
+
+Execute(should set go-langserver for go app2):
+ call ale#test#SetFilename('../test-files/go/go2/prj1/file.go')
+
+ AssertLSPLanguage 'go'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/go/go2')
diff --git a/test/linter/test_golint.vader b/test/linter/test_golint.vader
new file mode 100644
index 00000000..64916707
--- /dev/null
+++ b/test/linter/test_golint.vader
@@ -0,0 +1,30 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'golint')
+
+After:
+ Restore
+
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default golint command should be correct):
+ AssertLinter 'golint', ale#Escape('golint') . ' %t'
+
+Execute(The golint executable should be configurable):
+ let b:ale_go_golint_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' %t'
+
+Execute(The golint options should be configurable):
+ let b:ale_go_golint_options = '--foo'
+
+ AssertLinter 'golint', ale#Escape('golint') . ' --foo %t'
+
+Execute(The golint command should support Go environment variables):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'golint',
+ \ ale#Env('GO111MODULE', 'on') . ale#Escape('golint') . ' %t'
diff --git a/test/linter/test_gometalinter.vader b/test/linter/test_gometalinter.vader
new file mode 100644
index 00000000..5ff744f5
--- /dev/null
+++ b/test/linter/test_gometalinter.vader
@@ -0,0 +1,49 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'gometalinter')
+ call ale#test#SetFilename('test.go')
+
+After:
+ Restore
+
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The gometalinter defaults should be correct):
+ AssertLinterCwd '%s:h',
+ AssertLinter 'gometalinter',
+ \ ale#Escape('gometalinter')
+ \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t')))
+ \ . ' .'
+
+Execute(The gometalinter callback should use a configured executable):
+ let b:ale_go_gometalinter_executable = 'something else'
+
+ AssertLinter 'something else',
+ \ ale#Escape('something else')
+ \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t')))
+ \ . ' .'
+
+Execute(The gometalinter callback should use configured options):
+ let b:ale_go_gometalinter_options = '--foobar'
+
+ AssertLinter 'gometalinter',
+ \ ale#Escape('gometalinter')
+ \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t')))
+ \ . ' --foobar' . ' .'
+
+Execute(The gometalinter should use configured environment variables):
+ let b:ale_go_go111module = 'off'
+
+ AssertLinter 'gometalinter',
+ \ ale#Env('GO111MODULE', 'off')
+ \ . ale#Escape('gometalinter')
+ \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%' . ':t')))
+ \ . ' .'
+
+Execute(The gometalinter `lint_package` option should use the correct command):
+ let b:ale_go_gometalinter_lint_package = 1
+
+ AssertLinter 'gometalinter', ale#Escape('gometalinter') . ' .'
diff --git a/test/linter/test_gopls.vader b/test/linter/test_gopls.vader
new file mode 100644
index 00000000..0f1558e9
--- /dev/null
+++ b/test/linter/test_gopls.vader
@@ -0,0 +1,77 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'gopls')
+
+After:
+ if isdirectory(g:dir . '/.git')
+ call delete(g:dir . '/.git', 'd')
+ endif
+
+ unlet! b:ale_go_go111module
+ unlet! b:ale_go_go111module
+ unlet! b:ale_completion_enabled
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set correct defaults):
+ AssertLinter 'gopls', ale#Escape('gopls') . ' --mode stdio'
+
+Execute(should configure gopls callback executable):
+ let b:ale_go_gopls_executable = 'boo'
+ let b:ale_go_gopls_options = ''
+
+ AssertLinter 'boo', ale#Escape('boo')
+
+Execute(should set gopls options):
+ call ale#test#SetFilename('../test-files/go/go1/prj1/file.go')
+ " let b:ale_completion_enabled = 1
+ let b:ale_go_gopls_options = ''
+
+ AssertLinter 'gopls',
+ \ ale#Escape('gopls') . ''
+
+ let b:ale_go_gopls_options = '--mode stdio --trace'
+
+ AssertLinter 'gopls',
+ \ ale#Escape('gopls') . ' --mode stdio --trace'
+
+ let b:ale_go_gopls_init_options = {'ui.diagnostic.analyses': {'composites': v:false}}
+ AssertLSPOptions {'ui.diagnostic.analyses': {'composites': v:false}}
+
+Execute(should support go environment variables):
+ let b:ale_go_go111module = 'off'
+
+ AssertLinter 'gopls',
+ \ ale#Env('GO111MODULE', 'off') . ale#Escape('gopls') . ' --mode stdio'
+
+Execute(Should return directory for 'go.mod' if found in parent directory):
+ call ale#test#SetFilename('../test-files/go/test.go')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/go')
+
+Execute(Should return nearest directory with '.git' if found in parent directory):
+ call ale#test#SetFilename('test.go')
+
+ if !isdirectory(g:dir . '/.git')
+ call mkdir(g:dir . '/.git')
+ endif
+
+ AssertLSPProject g:dir
+
+Execute(Should ignore 'go.mod' and return '.git' dir if modules off):
+ call ale#test#SetFilename('../test-files/go/test.go')
+
+ let b:ale_go_go111module = 'off'
+ let b:parent_dir = ale#path#Simplify(g:dir . '/..')
+ let b:git_dir = b:parent_dir . '/.git'
+
+ if !isdirectory(b:git_dir)
+ call mkdir(b:git_dir)
+ endif
+
+ AssertLSPProject b:parent_dir
+
+ call delete(b:git_dir, 'd')
+ unlet! b:parent_dir
+ unlet! b:git_dir
diff --git a/test/linter/test_gosimple.vader b/test/linter/test_gosimple.vader
new file mode 100644
index 00000000..960f8ee9
--- /dev/null
+++ b/test/linter/test_gosimple.vader
@@ -0,0 +1,19 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'gosimple')
+ call ale#test#SetFilename('../test-files/go/testfile2.go')
+
+After:
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default gosimple command should be correct):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'gosimple', 'gosimple .'
+
+Execute(The gosimple command should support Go environment variables):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'gosimple', ale#Env('GO111MODULE', 'on') . 'gosimple .'
diff --git a/test/linter/test_gotype.vader b/test/linter/test_gotype.vader
new file mode 100644
index 00000000..22829a17
--- /dev/null
+++ b/test/linter/test_gotype.vader
@@ -0,0 +1,24 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'gotype')
+ call ale#test#SetFilename('../test-files/go/testfile2.go')
+
+After:
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default gotype command should be correct):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'gotype', 'gotype -e .'
+
+Execute(The gotype callback should ignore test files):
+ call ale#test#SetFilename('bla_test.go')
+
+ AssertLinterNotExecuted
+
+Execute(The gotype callback should support Go environment variables):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'gotype', ale#Env('GO111MODULE', 'on') . 'gotype -e .'
diff --git a/test/linter/test_govet.vader b/test/linter/test_govet.vader
new file mode 100644
index 00000000..12ec168a
--- /dev/null
+++ b/test/linter/test_govet.vader
@@ -0,0 +1,32 @@
+Before:
+ Save g:ale_go_go_executable
+ Save g:ale_go_govet_options
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'govet')
+
+After:
+ Restore
+
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'go', 'go vet .'
+
+Execute(Extra options should be supported):
+ let g:ale_go_govet_options = '--foo-bar'
+
+ AssertLinterCwd '%s:h'
+ AssertLinter 'go', 'go vet --foo-bar .'
+
+Execute(The executable should be configurable):
+ let g:ale_go_go_executable = 'foobar'
+
+ AssertLinter 'foobar', 'foobar vet .'
+
+Execute(Go environment variables should be supported):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'go', ale#Env('GO111MODULE', 'on') . 'go vet .'
diff --git a/test/linter/test_graphql_gqlint.vader b/test/linter/test_graphql_gqlint.vader
new file mode 100644
index 00000000..22c05a6a
--- /dev/null
+++ b/test/linter/test_graphql_gqlint.vader
@@ -0,0 +1,9 @@
+Before:
+ call ale#assert#SetUpLinterTest('graphql', 'gqlint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The linter should run from the directory of the file in the buffer):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'gqlint', 'gqlint --reporter=simple %t'
diff --git a/test/linter/test_haml_hamllint.vader b/test/linter/test_haml_hamllint.vader
new file mode 100644
index 00000000..9d81179b
--- /dev/null
+++ b/test/linter/test_haml_hamllint.vader
@@ -0,0 +1,41 @@
+Before:
+ call ale#assert#SetUpLinterTest('haml', 'hamllint')
+
+ let g:default_command = 'haml-lint %t'
+
+After:
+ unlet! b:conf
+ unlet! b:conf_hamllint
+ unlet! b:conf_rubocop
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'haml-lint', 'haml-lint %t'
+
+Execute(The command should have the .rubocop.yml prepended as an env var if one exists):
+ call ale#test#SetFilename('../test-files/hamllint/rubocop-yml/subdir/file.haml')
+ let b:conf = ale#path#Simplify(g:dir . '/../test-files/hamllint/rubocop-yml/.rubocop.yml')
+
+ AssertLinter 'haml-lint',
+ \ ale#Env('HAML_LINT_RUBOCOP_CONF', b:conf) . 'haml-lint %t'
+
+Execute(The command should have the nearest .haml-lint.yml set as --config if it exists):
+ call ale#test#SetFilename('../test-files/hamllint/haml-lint-yml/subdir/file.haml')
+ let b:conf = ale#path#Simplify(g:dir . '/../test-files/hamllint/haml-lint-yml/.haml-lint.yml')
+
+ AssertLinter 'haml-lint',
+ \ 'haml-lint --config ' . ale#Escape(b:conf) . ' %t',
+
+Execute(The command should include a .rubocop.yml and a .haml-lint if both are found):
+ call ale#test#SetFilename('../test-files/hamllint/haml-lint-and-rubocop/subdir/file.haml')
+ let b:conf_hamllint = ale#path#Simplify(g:dir . '/../test-files/hamllint/haml-lint-and-rubocop/.haml-lint.yml')
+ let b:conf_rubocop = ale#path#Simplify(g:dir . '/../test-files/hamllint/haml-lint-and-rubocop/.rubocop.yml')
+
+ AssertLinter 'haml-lint',
+ \ ale#Env('HAML_LINT_RUBOCOP_CONF', b:conf_rubocop)
+ \ . 'haml-lint --config ' . ale#Escape(b:conf_hamllint) . ' %t'
+
+Execute(The executable can be overridden):
+ let b:ale_haml_hamllint_executable = 'bin/haml-lint'
+ AssertLinter 'bin/haml-lint', 'bin/haml-lint %t'
diff --git a/test/linter/test_haskell_cabal_ghc.vader b/test/linter/test_haskell_cabal_ghc.vader
new file mode 100644
index 00000000..b4976b34
--- /dev/null
+++ b/test/linter/test_haskell_cabal_ghc.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('haskell', 'cabal_ghc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The options should be used in the command):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'cabal', 'cabal exec -- ghc -fno-code -v0 %t'
+
+ let b:ale_haskell_cabal_ghc_options = 'foobar'
+
+ AssertLinter 'cabal', 'cabal exec -- ghc foobar %t'
diff --git a/test/linter/test_haskell_ghc.vader b/test/linter/test_haskell_ghc.vader
new file mode 100644
index 00000000..2f33477d
--- /dev/null
+++ b/test/linter/test_haskell_ghc.vader
@@ -0,0 +1,12 @@
+Before:
+ call ale#assert#SetUpLinterTest('haskell', 'ghc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The options should be used in the command):
+ AssertLinter 'ghc', 'ghc -fno-code -v0 %t'
+
+ let b:ale_haskell_ghc_options = 'foobar'
+
+ AssertLinter 'ghc', 'ghc foobar %t'
diff --git a/test/linter/test_haskell_ghc_mod.vader b/test/linter/test_haskell_ghc_mod.vader
new file mode 100644
index 00000000..c1cc8597
--- /dev/null
+++ b/test/linter/test_haskell_ghc_mod.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/linter/test_haskell_hdevtools.vader b/test/linter/test_haskell_hdevtools.vader
new file mode 100644
index 00000000..0ef2f0e3
--- /dev/null
+++ b/test/linter/test_haskell_hdevtools.vader
@@ -0,0 +1,16 @@
+Before:
+ call ale#assert#SetUpLinterTest('haskell', 'hdevtools')
+
+ let b:command_tail = ' check -g -Wall -p %s %t'
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'hdevtools', ale#Escape('hdevtools') . b:command_tail
+
+ let b:ale_haskell_hdevtools_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . b:command_tail
diff --git a/test/linter/test_haskell_hie.vader b/test/linter/test_haskell_hie.vader
new file mode 100644
index 00000000..5bd2794c
--- /dev/null
+++ b/test/linter/test_haskell_hie.vader
@@ -0,0 +1,27 @@
+Before:
+ call ale#assert#SetUpLinterTest('haskell', 'hie')
+
+ Save &filetype
+ let &filetype = 'haskell'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The language string should be correct):
+ AssertLSPLanguage 'haskell'
+
+Execute(The default executable should be correct):
+ AssertLinter 'hie',
+ \ ale#Escape('hie') . ' --lsp'
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject g:dir
+
+ call ale#test#SetFilename('hie_paths/file.hs')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/hie_paths')
+
+Execute(The executable should be configurable):
+ let g:ale_haskell_hie_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --lsp'
diff --git a/test/linter/test_haskell_hlint.vader b/test/linter/test_haskell_hlint.vader
new file mode 100644
index 00000000..6d227c9d
--- /dev/null
+++ b/test/linter/test_haskell_hlint.vader
@@ -0,0 +1,17 @@
+Before:
+ call ale#assert#SetUpLinterTest('haskell', 'hlint')
+
+ let b:base_opts = '--color=never --json -'
+
+After:
+ unlet! b:base_opts
+ call ale#assert#TearDownLinterTest()
+
+Execute(executable should be configurable):
+ AssertLinter 'hlint', ale#Escape('hlint') . ' ' . b:base_opts
+ let b:ale_haskell_hlint_executable = 'myHlint'
+ AssertLinter 'myHlint', ale#Escape('myHlint') . ' ' . b:base_opts
+
+Execute(should accept options):
+ let b:ale_haskell_hlint_options= '-h myhlintfile.yaml'
+ AssertLinter 'hlint', ale#Escape('hlint') . ' -h myhlintfile.yaml ' . b:base_opts
diff --git a/test/linter/test_haskell_hls.vader b/test/linter/test_haskell_hls.vader
new file mode 100644
index 00000000..e64aab6f
--- /dev/null
+++ b/test/linter/test_haskell_hls.vader
@@ -0,0 +1,27 @@
+Before:
+ call ale#assert#SetUpLinterTest('haskell', 'hls')
+
+ Save &filetype
+ let &filetype = 'haskell'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The language string should be correct):
+ AssertLSPLanguage 'haskell'
+
+Execute(The default executable should be correct):
+ AssertLinter 'haskell-language-server-wrapper',
+ \ ale#Escape('haskell-language-server-wrapper') . ' --lsp'
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject g:dir
+
+ call ale#test#SetFilename('hls_paths/file.hs')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/hls_paths')
+
+Execute(The executable should be configurable):
+ let g:ale_haskell_hls_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --lsp'
diff --git a/test/linter/test_haskell_stack_build.vader b/test/linter/test_haskell_stack_build.vader
new file mode 100644
index 00000000..8b5b0971
--- /dev/null
+++ b/test/linter/test_haskell_stack_build.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('haskell', 'stack_build')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The linter should not be executed when there's no stack.yaml file):
+ AssertLinterNotExecuted
+
+Execute(The linter should be executed when there is a stack.yaml file):
+ call ale#test#SetFilename('../test-files/stack/test.hs')
+
+ AssertLinter 'stack', 'stack build --fast'
diff --git a/test/linter/test_haskell_stack_ghc.vader b/test/linter/test_haskell_stack_ghc.vader
new file mode 100644
index 00000000..04bd23f5
--- /dev/null
+++ b/test/linter/test_haskell_stack_ghc.vader
@@ -0,0 +1,18 @@
+Before:
+ call ale#assert#SetUpLinterTest('haskell', 'stack_ghc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The linter should not be executed when there's no stack.yaml file):
+ AssertLinterNotExecuted
+
+Execute(The linter should be executed when there is a stack.yaml file):
+ call ale#test#SetFilename('../test-files/stack/test.hs')
+
+ AssertLinterCwd '%s:h'
+ AssertLinter 'stack', 'stack ghc -- -fno-code -v0 %t'
+
+ let b:ale_haskell_stack_ghc_options = 'foobar'
+
+ AssertLinter 'stack', 'stack ghc -- foobar %t'
diff --git a/test/linter/test_hdl_checker_options.vader b/test/linter/test_hdl_checker_options.vader
new file mode 100644
index 00000000..6e7eef46
--- /dev/null
+++ b/test/linter/test_hdl_checker_options.vader
@@ -0,0 +1,86 @@
+Before:
+ call ale#assert#SetUpLinterTest('vhdl', 'hdl_checker')
+
+ Save g:ale_hdl_checker_executable
+ Save g:ale_hdl_checker_config_file
+ Save g:ale_hdl_checker_options
+
+ let g:default_config_file = has('unix') ? '.hdl_checker.config' : '_hdl_checker.config'
+
+ runtime autoload/ale/handlers/hdl_checker.vim
+
+After:
+ Restore
+
+ call ale#assert#TearDownLinterTest()
+
+ unlet! g:default_config_file
+ unlet! g:call_count
+
+ runtime autoload/ale/handlers/hdl_checker.vim
+
+Execute(Get default initialization dict):
+ AssertEqual
+ \ {'project_file': g:default_config_file},
+ \ ale#handlers#hdl_checker#GetInitOptions(bufnr(''))
+
+Execute(Get custom initialization dict):
+ let g:ale_hdl_checker_config_file = 'some_file_name'
+
+ AssertEqual
+ \ {'project_file': 'some_file_name'},
+ \ ale#handlers#hdl_checker#GetInitOptions(bufnr(''))
+
+Execute(Get the checker command without extra user parameters):
+ AssertEqual
+ \ ale#Escape('hdl_checker') . ' --lsp',
+ \ ale#handlers#hdl_checker#GetCommand(bufnr(''))
+
+Execute(Get the checker command with user configured parameters):
+ let g:ale_hdl_checker_options = '--log-level DEBUG'
+
+ AssertEqual
+ \ ale#Escape('hdl_checker') . ' --lsp --log-level DEBUG',
+ \ ale#handlers#hdl_checker#GetCommand(bufnr(''))
+
+Execute(Customize executable):
+ let g:ale_hdl_checker_executable = '/some/other/path'
+ AssertEqual
+ \ ale#Escape('/some/other/path') . ' --lsp',
+ \ ale#handlers#hdl_checker#GetCommand(bufnr(''))
+
+Execute(Get project root based on .git):
+ call ale#test#SetFilename('../test-files/hdl_server/with_git/files/foo.vhd')
+ " Create .git file
+ silent! call mkdir(g:dir . '/../test-files/hdl_server/with_git/.git')
+ AssertNotEqual '', glob(g:dir . '/../test-files/hdl_server/with_git/.git')
+
+ AssertEqual
+ \ ale#path#Simplify(g:dir . '/../test-files/hdl_server/with_git'),
+ \ ale#handlers#hdl_checker#GetProjectRoot(bufnr(''))
+
+Execute(Get project root based on config file):
+ call ale#test#SetFilename('../test-files/hdl_server/with_config_file/foo.vhd')
+
+ AssertEqual
+ \ ale#path#Simplify(g:dir . '/../test-files/hdl_server/with_config_file'),
+ \ ale#handlers#hdl_checker#GetProjectRoot(bufnr(''))
+
+Execute(Return no project root if neither .git or config file are found):
+ let g:call_count = 0
+
+ " Mock this command to avoid the test to find ale's own .git folder
+ function! ale#handlers#hdl_checker#IsDotGit(path) abort
+ let g:call_count += 1
+ return 0
+ endfunction
+
+ call ale#test#SetFilename('../test-files/hdl_server/foo.vhd')
+
+ AssertEqual
+ \ '',
+ \ ale#handlers#hdl_checker#GetProjectRoot(bufnr(''))
+
+ AssertEqual g:call_count, 1
+
+ unlet! g:call_count
diff --git a/test/linter/test_html_stylelint.vader b/test/linter/test_html_stylelint.vader
new file mode 100644
index 00000000..c5ac1b98
--- /dev/null
+++ b/test/linter/test_html_stylelint.vader
@@ -0,0 +1,60 @@
+Before:
+ Save g:ale_html_stylelint_executable
+ Save g:ale_html_stylelint_use_global
+ Save g:ale_html_stylelint_options
+
+ unlet! b:executable
+
+ unlet! g:ale_html_stylelint_executable
+ unlet! g:ale_html_stylelint_use_global
+ unlet! g:ale_html_stylelint_options
+
+ call ale#test#SetDirectory('/testplugin/test/linter')
+ call ale#test#SetFilename('testfile.html')
+
+ runtime ale_linters/html/stylelint.vim
+
+After:
+ Restore
+
+ unlet! b:executable
+ unlet! b:ale_html_stylelint_executable
+ unlet! b:ale_html_stylelint_use_global
+ unlet! b:ale_html_stylelint_options
+
+ call ale#test#SetFilename('test.txt')
+
+ call ale#test#RestoreDirectory()
+ call ale#linter#Reset()
+
+Execute(node_modules directories should be discovered):
+ call ale#test#SetFilename('../test-files/stylelint/nested/testfile.html')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/stylelint/node_modules/.bin/stylelint'
+ \)
+
+ AssertEqual b:executable, ale_linters#html#stylelint#GetExecutable(bufnr(''))
+ AssertEqual
+ \ ale#Escape(b:executable) . ' --stdin-filename %s',
+ \ ale_linters#html#stylelint#GetCommand(bufnr(''))
+
+Execute(The global override should work):
+ let b:ale_html_stylelint_executable = 'foobar'
+ let b:ale_html_stylelint_use_global = 1
+
+ call ale#test#SetFilename('../test-files/stylelint/nested/testfile.html')
+
+ AssertEqual 'foobar', ale_linters#html#stylelint#GetExecutable(bufnr(''))
+ AssertEqual
+ \ ale#Escape('foobar') . ' --stdin-filename %s',
+ \ ale_linters#html#stylelint#GetCommand(bufnr(''))
+
+Execute(Extra options should be configurable):
+ let b:ale_html_stylelint_options = '--whatever'
+
+ AssertEqual 'stylelint', ale_linters#html#stylelint#GetExecutable(bufnr(''))
+ AssertEqual
+ \ ale#Escape('stylelint') . ' --whatever --stdin-filename %s',
+ \ ale_linters#html#stylelint#GetCommand(bufnr(''))
diff --git a/test/linter/test_htmlhint.vader b/test/linter/test_htmlhint.vader
new file mode 100644
index 00000000..df5797af
--- /dev/null
+++ b/test/linter/test_htmlhint.vader
@@ -0,0 +1,51 @@
+Before:
+ call ale#assert#SetUpLinterTest('html', 'htmlhint')
+ call ale#test#SetFilename('../test-files/htmlhint/test.html')
+
+ let g:node_executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/htmlhint/node_modules/.bin/htmlhint'
+ \)
+ let g:config_path = ale#path#Simplify(
+ \ g:dir . '/../test-files/htmlhint/with_config/.htmlhintrc'
+ \)
+
+After:
+ unlet! g:node_executable
+ unlet! g:config_path
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter g:node_executable,
+ \ ale#Escape(g:node_executable) . ' --format=unix %t'
+
+Execute(The global executable should be uesd if the option is set):
+ let g:ale_html_htmlhint_executable = 'foo'
+ let g:ale_html_htmlhint_use_global = 1
+
+ AssertLinter 'foo', ale#Escape('foo') . ' --format=unix %t',
+
+" This is so old configurations which might include this still work.
+Execute(--format=unix should be removed from the options if added):
+ let g:ale_html_htmlhint_options = '--format=unix'
+
+ AssertLinter g:node_executable,
+ \ ale#Escape(g:node_executable) . ' --format=unix %t'
+
+Execute(The configuration file should be automatically detected):
+ call ale#test#SetFilename('../test-files/htmlhint/with_config/test.html')
+
+ AssertLinter g:node_executable,
+ \ ale#Escape(g:node_executable)
+ \ . ' --config ' . ale#Escape(g:config_path)
+ \ . ' --format=unix %t'
+
+" This is so old configurations which might include the config will work.
+Execute(The configuration file should be configurable through the options variable):
+ call ale#test#SetFilename('../test-files/htmlhint/with_config/test.html')
+ let g:ale_html_htmlhint_options = '--config=/foo/bar/.htmlhintrc'
+
+ AssertLinter g:node_executable,
+ \ ale#Escape(g:node_executable)
+ \ . ' --config=/foo/bar/.htmlhintrc'
+ \ . ' --format=unix %t'
diff --git a/test/linter/test_ibm_openapi_validator.vader b/test/linter/test_ibm_openapi_validator.vader
new file mode 100644
index 00000000..3484cc09
--- /dev/null
+++ b/test/linter/test_ibm_openapi_validator.vader
@@ -0,0 +1,15 @@
+Before:
+ call ale#assert#SetUpLinterTest('openapi', 'ibm_validator')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The yaml ibm-openapi-validator command callback should return the correct default string):
+ AssertLinter 'lint-openapi', ale#Escape('lint-openapi') . ' %t'
+
+Execute(The yaml ibm-openapi-validator command callback should be configurable):
+ let g:ale_openapi_ibm_validator_executable = '~/.local/bin/lint-openapi'
+ let g:ale_openapi_ibm_validator_options = '-c ~/.config'
+
+ AssertLinter '~/.local/bin/lint-openapi', ale#Escape('~/.local/bin/lint-openapi')
+ \ . ' -c ~/.config %t'
diff --git a/test/linter/test_idris.vader b/test/linter/test_idris.vader
new file mode 100644
index 00000000..ce7cd270
--- /dev/null
+++ b/test/linter/test_idris.vader
@@ -0,0 +1,21 @@
+Before:
+ call ale#assert#SetUpLinterTest('idris', 'idris')
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be used in the command):
+ AssertLinter 'idris',
+ \ ale#Escape('idris') . ' --total --warnpartial --warnreach --warnipkg --check %s'
+
+ let b:ale_idris_idris_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' --total --warnpartial --warnreach --warnipkg --check %s'
+
+Execute(The options should be configurable):
+ let b:ale_idris_idris_options = '--something'
+
+ AssertLinter 'idris', ale#Escape('idris') . ' --something --check %s'
diff --git a/test/linter/test_ink_ls.vader b/test/linter/test_ink_ls.vader
new file mode 100644
index 00000000..a832a250
--- /dev/null
+++ b/test/linter/test_ink_ls.vader
@@ -0,0 +1,22 @@
+Before:
+ call ale#assert#SetUpLinterTest('ink', 'ls')
+ set ft=ink
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set correct defaults):
+ AssertLinter 'ink-language-server', ale#Escape('ink-language-server') . ' --stdio'
+
+Execute(should set correct LSP values):
+ call ale#test#SetFilename('../test-files/ink/story/main.ink')
+
+ AssertLSPLanguage 'ink'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ink/story')
+
+Execute(should accept configuration settings):
+ AssertLSPConfig {}
+ let b:ale_ink_ls_initialization_options = {'ink': {'runThroughMono': v:true}}
+ AssertLSPOptions {'ink': {'runThroughMono': v:true}}
diff --git a/test/linter/test_inko_inko.vader b/test/linter/test_inko_inko.vader
new file mode 100644
index 00000000..c08cbed4
--- /dev/null
+++ b/test/linter/test_inko_inko.vader
@@ -0,0 +1,20 @@
+Before:
+ call ale#assert#SetUpLinterTest('inko', 'inko')
+ call ale#test#SetFilename('../test-files/inko/test.inko')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'inko', ale#Escape('inko') . ' build --check --format=json %s'
+
+Execute(The inko callback should include tests/ for test paths):
+ call ale#engine#Cleanup(bufnr(''))
+ noautocmd e! ../test-files/inko/tests/test/test_foo.inko
+ call ale#engine#InitBufferInfo(bufnr(''))
+
+ AssertLinter 'inko',
+ \ ale#Escape('inko')
+ \ . ' build --check --format=json --include '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/inko/tests/'))
+ \ . ' %s'
diff --git a/test/linter/test_ispc_ispc.vader b/test/linter/test_ispc_ispc.vader
new file mode 100644
index 00000000..f1aeb2f8
--- /dev/null
+++ b/test/linter/test_ispc_ispc.vader
@@ -0,0 +1,20 @@
+Before:
+ call ale#assert#SetUpLinterTest('ispc', 'ispc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'ispc',
+ \ ale#Escape('ispc') . ' --nowrap %s'
+
+ let b:ale_ispc_ispc_executable = 'foo'
+
+ AssertLinter 'foo',
+ \ ale#Escape('foo') . ' --nowrap %s'
+
+Execute(The options should be configurable):
+ let g:ale_ispc_ispc_options = '--foo'
+
+ AssertLinter 'ispc',
+ \ ale#Escape('ispc') . ' --nowrap --foo' . ' %s'
diff --git a/test/linter/test_iverilog.vader b/test/linter/test_iverilog.vader
new file mode 100644
index 00000000..d7a29f05
--- /dev/null
+++ b/test/linter/test_iverilog.vader
@@ -0,0 +1,14 @@
+Before:
+ call ale#assert#SetUpLinterTest('verilog', 'iverilog')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default iverilog command should be correct):
+ AssertLinter 'iverilog', 'iverilog -t null -Wall %t'
+
+Execute(iverilog options should be configurable):
+ " Additional args for the linter
+ let g:ale_verilog_iverilog_options = '-y.'
+
+ AssertLinter 'iverilog', 'iverilog -t null -Wall -y. %t'
diff --git a/test/linter/test_javac.vader b/test/linter/test_javac.vader
new file mode 100644
index 00000000..85a76e6a
--- /dev/null
+++ b/test/linter/test_javac.vader
@@ -0,0 +1,326 @@
+Before:
+ call ale#assert#SetUpLinterTest('java', 'javac')
+ call ale#test#SetFilename('dummy.java')
+
+ let g:cp_sep = has('unix') ? ':' : ';'
+ let g:prefix = ale#Escape('javac') . ' -Xlint'
+
+ function! GetCommand(previous_output) abort
+ let l:command = ale_linters#java#javac#GetCommand(
+ \ bufnr(''),
+ \ a:previous_output
+ \)
+
+ let l:split_command = split(l:command)
+ let l:index = index(l:split_command, '-d')
+
+ let l:split_command[l:index + 1] = 'TEMP'
+
+ return join(l:split_command)
+ endfunction
+
+After:
+ unlet! g:cp_sep
+ unlet! g:prefix
+
+ delfunction GetCommand
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The javac callback should return the correct default value):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'javac', g:prefix . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback should use string type g:ale_java_javac_classpath correctly):
+ let g:ale_java_javac_classpath = 'foo.jar'
+
+ AssertLinter 'javac',
+ \ g:prefix
+ \ . ' -cp ' . ale#Escape('foo.jar')
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback should use list type g:ale_java_javac_classpath correctly):
+ let g:ale_java_javac_classpath = ['foo.jar']
+
+ AssertLinter 'javac',
+ \ g:prefix
+ \ . ' -cp ' . ale#Escape('foo.jar')
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The executable should be configurable):
+ let g:ale_java_javac_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -Xlint'
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback should include discovered classpaths):
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [
+ \ '[DEBUG] Ignore this.',
+ \ '[INFO] Something we should ignore.',
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \], {})
+
+ AssertEqual
+ \ g:prefix
+ \ . ' -cp '
+ \ . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+Execute(The javac callback should combine discovered classpaths and manual ones):
+ let g:ale_java_javac_classpath = 'configured.jar'
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [
+ \ '[DEBUG] Ignore this.',
+ \ '[INFO] Something we should ignore.',
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \], {})
+
+ AssertEqual
+ \ g:prefix
+ \ . ' -cp '
+ \ . ale#Escape(join(
+ \ [
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \ 'configured.jar',
+ \ ],
+ \ g:cp_sep
+ \ ))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+ let g:ale_java_javac_classpath = 'configured.jar' . g:cp_sep . 'configured2.jar'
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [
+ \ '[DEBUG] Ignore this.',
+ \ '[INFO] Something we should ignore.',
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \], {})
+
+ AssertEqual
+ \ g:prefix
+ \ . ' -cp '
+ \ . ale#Escape(join(
+ \ [
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \ 'configured.jar',
+ \ 'configured2.jar',
+ \ ],
+ \ g:cp_sep
+ \ ))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+ let g:ale_java_javac_classpath = ['configured.jar']
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [
+ \ '[DEBUG] Ignore this.',
+ \ '[INFO] Something we should ignore.',
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \], {})
+
+ AssertEqual
+ \ g:prefix
+ \ . ' -cp '
+ \ . ale#Escape(join(
+ \ [
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \ 'configured.jar',
+ \ ],
+ \ g:cp_sep
+ \ ))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+ let g:ale_java_javac_classpath = ['configured.jar', 'configured2.jar']
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [
+ \ '[DEBUG] Ignore this.',
+ \ '[INFO] Something we should ignore.',
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \], {})
+
+ AssertEqual
+ \ g:prefix
+ \ . ' -cp '
+ \ . ale#Escape(join(
+ \ [
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \ 'configured.jar',
+ \ 'configured2.jar',
+ \ ],
+ \ g:cp_sep
+ \ ))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+Execute(The javac callback should use string type g:ale_java_javac_sourcepath correctly):
+ let g:ale_java_javac_sourcepath = '../test-files/java/with_main/build/gen/main'
+
+ AssertLinter 'javac',
+ \ g:prefix
+ \ . ' -sourcepath ' . ale#Escape(
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/build/gen/main/')
+ \ )
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback should use list type g:ale_java_javac_sourcepath correctly):
+ let g:ale_java_javac_sourcepath = ['../test-files/java/with_main/build/gen/main']
+
+ AssertLinter 'javac',
+ \ g:prefix
+ \ . ' -sourcepath ' . ale#Escape(
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/build/gen/main/')
+ \ )
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback shouldn't add -sourcepath when g:ale_java_javac_sourcepath variable path doesn't exist):
+ let g:ale_java_javac_sourcepath = '../test-files/java/with_main/build/gen3/main'
+
+ AssertLinter 'javac',
+ \ g:prefix
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback should combine discovered sourcepath and manual ones):
+ call ale#engine#Cleanup(bufnr(''))
+ call ale#test#SetFilename('../test-files/java/with_main/src/main/java/com/something/dummy.java')
+ call ale#engine#InitBufferInfo(bufnr(''))
+
+ let g:ale_java_javac_sourcepath = '../test-files/java/with_main/build/gen/main'
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {})
+
+ AssertEqual
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -sourcepath ' . ale#Escape(join([
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/src/main/java/'),
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/build/gen/main/'),
+ \ ], g:cp_sep))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+ let g:ale_java_javac_sourcepath = '../test-files/java/with_main/build/gen/main'
+ \ . g:cp_sep . '../test-files/java/with_main/build/gen2/main'
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {})
+
+ AssertEqual
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -sourcepath ' . ale#Escape(join([
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/src/main/java/'),
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/build/gen/main/'),
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/build/gen2/main/')
+ \ ], g:cp_sep))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+ let g:ale_java_javac_sourcepath = ['../test-files/java/with_main/build/gen/main']
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {})
+
+ AssertEqual
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -sourcepath ' . ale#Escape(join([
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/src/main/java/'),
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/build/gen/main/')
+ \ ], g:cp_sep))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+ let g:ale_java_javac_sourcepath = [
+ \ '../test-files/java/with_main/build/gen/main',
+ \ '../test-files/java/with_main/build/gen2/main'
+ \ ]
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {})
+
+ AssertEqual
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -sourcepath ' . ale#Escape(join([
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/src/main/java/'),
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/build/gen/main/'),
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/build/gen2/main/')
+ \ ], g:cp_sep))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+Execute(The javac callback should detect source directories):
+ call ale#engine#Cleanup(bufnr(''))
+ noautocmd e! ../test-files/java/with_main/src/main/java/com/something/dummy
+ call ale#engine#InitBufferInfo(bufnr(''))
+
+ AssertLinter 'javac',
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -sourcepath ' . ale#Escape(
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/src/main/java/')
+ \ )
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback should combine detected source directories and classpaths):
+ call ale#engine#Cleanup(bufnr(''))
+ call ale#test#SetFilename('../test-files/java/with_main/src/main/java/com/something/dummy.java')
+ call ale#engine#InitBufferInfo(bufnr(''))
+
+ let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [
+ \ '[DEBUG] Ignore this.',
+ \ '[INFO] Something we should ignore.',
+ \ '/foo/bar.jar',
+ \ '/xyz/abc.jar',
+ \], {})
+
+ AssertEqual
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -cp ' . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep))
+ \ . ' -sourcepath ' . ale#Escape(
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/src/main/java/')
+ \ )
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
+ \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
+
+Execute(The javac callback should use g:ale_java_javac_options correctly):
+ let g:ale_java_javac_options = '--anything --else'
+
+ AssertLinter 'javac',
+ \ g:prefix . ' -d ' . ale#Escape('TEMP_DIR') . ' --anything --else %t'
+
+Execute(The javac callback should include src/test/java for test paths):
+ call ale#engine#Cleanup(bufnr(''))
+ " The test path is only included for test files.
+ " Regular Java files shouldn't import from tests.
+ noautocmd e! ../test-files/java/with_main/src/test/java/com/something/dummy
+ call ale#engine#InitBufferInfo(bufnr(''))
+
+ AssertLinter 'javac',
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -sourcepath ' . ale#Escape(join([
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/src/main/java/'),
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_main/src/test/java/'),
+ \ ], g:cp_sep))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback should include src/main/jaxb when available):
+ call ale#engine#Cleanup(bufnr(''))
+ noautocmd e! ../test-files/java/with_jaxb/src/main/java/com/something/dummy
+ call ale#engine#InitBufferInfo(bufnr(''))
+
+ AssertLinter 'javac',
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -sourcepath ' . ale#Escape(join([
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_jaxb/src/main/java/'),
+ \ ale#path#Simplify(g:dir . '/../test-files/java/with_jaxb/src/main/jaxb/'),
+ \ ], g:cp_sep))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
+
+Execute(The javac callback should add -sourcepath even if src/java/main doesn't exist):
+ call ale#engine#Cleanup(bufnr(''))
+ call ale#test#SetFilename('../test-files/java/no_main/src/test/java/com/something/dummy.java')
+ call ale#engine#InitBufferInfo(bufnr(''))
+
+ AssertLinter 'javac',
+ \ ale#Escape('javac') . ' -Xlint'
+ \ . ' -sourcepath ' . ale#Escape(join([
+ \ ale#path#Simplify(g:dir . '/../test-files/java/no_main/src/test/java/'),
+ \ ], g:cp_sep))
+ \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
diff --git a/test/linter/test_javalsp.vader b/test/linter/test_javalsp.vader
new file mode 100644
index 00000000..122f409b
--- /dev/null
+++ b/test/linter/test_javalsp.vader
@@ -0,0 +1,80 @@
+
+Before:
+ call ale#assert#SetUpLinterTest('java', 'javalsp')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The javalsp callback should return the correct default value):
+ AssertLinter '', ale#Escape('')
+
+Execute(The javalsp java executable should be configurable):
+ let b:ale_java_javalsp_executable = '/bin/foobar'
+
+ AssertLinter '/bin/foobar', ale#Escape('/bin/foobar')
+
+Execute(The javalsp callback should return backward compatible value):
+ let b:ale_java_javalsp_executable = '/bin/java'
+ let cmd = [
+ \ ale#Escape('/bin/java'),
+ \ '--add-exports jdk.compiler/com.sun.tools.javac.api=javacs',
+ \ '--add-exports jdk.compiler/com.sun.tools.javac.code=javacs',
+ \ '--add-exports jdk.compiler/com.sun.tools.javac.comp=javacs',
+ \ '--add-exports jdk.compiler/com.sun.tools.javac.main=javacs',
+ \ '--add-exports jdk.compiler/com.sun.tools.javac.tree=javacs',
+ \ '--add-exports jdk.compiler/com.sun.tools.javac.model=javacs',
+ \ '--add-exports jdk.compiler/com.sun.tools.javac.util=javacs',
+ \ '--add-opens jdk.compiler/com.sun.tools.javac.api=javacs',
+ \ '-m javacs/org.javacs.Main',
+ \]
+ AssertLinter '/bin/java', join(cmd, ' ')
+
+Execute(The javalsp should have default config):
+ AssertEqual
+ \ {
+ \ 'java': {
+ \ 'classPath': [],
+ \ 'externalDependencies': []
+ \ }
+ \ },
+ \ ale_linters#java#javalsp#Config(bufnr(''))
+
+Execute(The javalsp should have default config if user sets empty hash):
+ let b:ale_java_javalsp_config = {}
+
+ AssertEqual
+ \ {
+ \ 'java': {
+ \ 'classPath': [],
+ \ 'externalDependencies': []
+ \ }
+ \ },
+ \ ale_linters#java#javalsp#Config(bufnr(''))
+
+Execute(The javalsp should have add missing config):
+ let b:ale_java_javalsp_config = { 'java': { 'classPath': ['aaa.jar'] } }
+
+ AssertEqual
+ \ {
+ \ 'java': {
+ \ 'classPath': ['aaa.jar'],
+ \ 'externalDependencies': []
+ \ }
+ \ },
+ \ ale_linters#java#javalsp#Config(bufnr(''))
+
+ let b:ale_java_javalsp_config =
+ \ {
+ \ 'java': {
+ \ 'externalDependencies': ['unit-test:2.0.0']
+ \ }
+ \ }
+
+ AssertEqual
+ \ {
+ \ 'java': {
+ \ 'classPath': [],
+ \ 'externalDependencies': ['unit-test:2.0.0']
+ \ }
+ \ },
+ \ ale_linters#java#javalsp#Config(bufnr(''))
diff --git a/test/linter/test_javascript_tsserver.vader b/test/linter/test_javascript_tsserver.vader
new file mode 100644
index 00000000..1c29c8fd
--- /dev/null
+++ b/test/linter/test_javascript_tsserver.vader
@@ -0,0 +1,16 @@
+Before:
+ call ale#assert#SetUpLinterTest('javascript', 'tsserver')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'tsserver', ale#Escape('tsserver')
+
+Execute(should resolve correct path when nested 1):
+ call ale#test#SetFilename('../test-files/tsserver/src/level-1/level-2/file3.ts')
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/tsserver/src/level-1')
+
+Execute(should resolve correct path when nested 2):
+ call ale#test#SetFilename('../test-files/tsserver/src/file1.ts')
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/tsserver')
diff --git a/test/linter/test_jq.vader b/test/linter/test_jq.vader
new file mode 100644
index 00000000..20c3db5b
--- /dev/null
+++ b/test/linter/test_jq.vader
@@ -0,0 +1,8 @@
+Before:
+ call ale#assert#SetUpLinterTest('json', 'jq')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'jq', ale#Escape('jq')
diff --git a/test/linter/test_jscs.vader b/test/linter/test_jscs.vader
new file mode 100644
index 00000000..7cdf5467
--- /dev/null
+++ b/test/linter/test_jscs.vader
@@ -0,0 +1,15 @@
+Before:
+ call ale#assert#SetUpLinterTest('javascript', 'jscs')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Should return the correct default values):
+ AssertLinter 'jscs',
+ \ ale#Escape('jscs') . ' --reporter inline --no-colors -'
+
+Execute(Should allow using a custom executable):
+ let g:ale_javascript_jscs_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' --reporter inline --no-colors -'
diff --git a/test/linter/test_jshint.vader b/test/linter/test_jshint.vader
new file mode 100644
index 00000000..517c957c
--- /dev/null
+++ b/test/linter/test_jshint.vader
@@ -0,0 +1,17 @@
+Before:
+ Save g:ale_jshint_config_loc
+
+ unlet! g:ale_jshint_config_loc
+
+ call ale#assert#SetUpLinterTest('javascript', 'jshint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'jshint', ale#Escape('jshint') . ' --reporter unix --extract auto --filename %s -'
+
+Execute(Setting a config location should add the config parameter):
+ let g:ale_jshint_config_loc = '/some/file'
+
+ AssertLinter 'jshint', ale#Escape('jshint') . ' --reporter unix --extract auto --config ' . ale#Escape('/some/file') . ' --filename %s -'
diff --git a/test/linter/test_julia_languageserver.vader b/test/linter/test_julia_languageserver.vader
new file mode 100644
index 00000000..d75665a0
--- /dev/null
+++ b/test/linter/test_julia_languageserver.vader
@@ -0,0 +1,30 @@
+Before:
+ Save g:ale_julia_executable
+
+ call ale#assert#SetUpLinterTest('julia', 'languageserver')
+
+After:
+ Restore
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'julia',
+ \ ale#Escape('julia') .
+ \' --project=@. --startup-file=no --history-file=no -e ' .
+ \ ale#Escape('using LanguageServer; using Pkg; import StaticLint; import SymbolServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, dirname(Pkg.Types.Context().env.project_file)); server.runlinter = true; run(server);')
+
+Execute(The executable should be configurable):
+ let g:ale_julia_executable = 'julia-new'
+
+ AssertLinter 'julia-new',
+ \ ale#Escape('julia-new') .
+ \' --project=@. --startup-file=no --history-file=no -e ' .
+ \ ale#Escape('using LanguageServer; using Pkg; import StaticLint; import SymbolServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, dirname(Pkg.Types.Context().env.project_file)); server.runlinter = true; run(server);')
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/julia/test.jl')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/julia')
diff --git a/test/linter/test_kotlin_languageserver.vader b/test/linter/test_kotlin_languageserver.vader
new file mode 100644
index 00000000..97b867ab
--- /dev/null
+++ b/test/linter/test_kotlin_languageserver.vader
@@ -0,0 +1,23 @@
+Before:
+ call ale#assert#SetUpLinterTest('kotlin', 'languageserver')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'kotlin-language-server', ale#Escape('kotlin-language-server')
+
+Execute(Gradle project roots with build.gradle should be detected correctly):
+ call ale#test#SetFilename('../test-files/gradle/build-gradle-project/src/main/kotlin/dummy.kt')
+
+ AssertLSPProject ale#test#GetFilename('../test-files/gradle/build-gradle-project')
+
+Execute(Maven project roots with pom.xml should be detected correctly):
+ call ale#test#SetFilename('../test-files/maven/maven-kotlin-project/src/main/kotlin/dummy.kt')
+
+ AssertLSPProject ale#test#GetFilename('../test-files/maven/maven-kotlin-project')
+
+Execute(No root should be detected if configuration files can't be found):
+ call ale#test#SetFilename('../test-files/gradle/non-gradle-project/src/main/kotlin/dummy.kt')
+
+ AssertLSPProject ''
diff --git a/test/linter/test_kotlinc.vader b/test/linter/test_kotlinc.vader
new file mode 100644
index 00000000..fe94bffa
--- /dev/null
+++ b/test/linter/test_kotlinc.vader
@@ -0,0 +1,9 @@
+Before:
+ call ale#assert#SetUpLinterTest('kotlin', 'kotlinc')
+ call ale#test#SetFilename('test.kt')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'kotlinc', 'kotlinc ' . ale#Escape(expand('%:p'))
diff --git a/test/linter/test_languagetool.vader b/test/linter/test_languagetool.vader
new file mode 100644
index 00000000..ff6b2064
--- /dev/null
+++ b/test/linter/test_languagetool.vader
@@ -0,0 +1,22 @@
+Before:
+ call ale#assert#SetUpLinterTest('text', 'languagetool')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'languagetool', ale#Escape('languagetool')
+ \ . ' --autoDetect %s'
+
+Execute(Should be able to set a custom executable):
+ let g:ale_languagetool_executable = 'foobar'
+
+ AssertLinter 'foobar' , ale#Escape('foobar')
+ \ . ' --autoDetect %s'
+
+Execute(Should be able to include custom languagetool options):
+ let g:ale_languagetool_options = '--language en'
+
+ " is now 'foobar' based on above global
+ AssertLinter 'foobar', ale#Escape('foobar')
+ \ . ' --language en %s'
diff --git a/test/linter/test_less_stylelint.vader b/test/linter/test_less_stylelint.vader
new file mode 100644
index 00000000..cbe7d23c
--- /dev/null
+++ b/test/linter/test_less_stylelint.vader
@@ -0,0 +1,31 @@
+Before:
+ call ale#assert#SetUpLinterTest('less', 'stylelint')
+ unlet! b:executable
+
+After:
+ unlet! b:executable
+ call ale#assert#TearDownLinterTest()
+
+Execute(node_modules directories should be discovered):
+ call ale#test#SetFilename('../test-files/stylelint/nested/testfile.less')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/stylelint/node_modules/.bin/stylelint'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin-filename %s'
+
+Execute(The global override should work):
+ let b:ale_less_stylelint_executable = 'foobar'
+ let b:ale_less_stylelint_use_global = 1
+
+ call ale#test#SetFilename('../test-files/stylelint/nested/testfile.less')
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin-filename %s'
+
+Execute(Extra options should be configurable):
+ let b:ale_less_stylelint_options = '--whatever'
+
+ AssertLinter 'stylelint',
+ \ ale#Escape('stylelint') . ' --whatever --stdin-filename %s'
diff --git a/test/linter/test_lessc.vader b/test/linter/test_lessc.vader
new file mode 100644
index 00000000..b7d664c6
--- /dev/null
+++ b/test/linter/test_lessc.vader
@@ -0,0 +1,46 @@
+Before:
+ call ale#assert#SetUpLinterTest('less', 'lessc')
+ call ale#test#SetFilename('testfile.less')
+
+ unlet! b:executable
+
+After:
+ unlet! b:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(node_modules directories should be discovered):
+ call ale#test#SetFilename('../test-files/lessc/nested/testfile.less')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/lessc/node_modules/.bin/lessc'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable)
+ \ . ' --no-color --lint'
+ \ . ' --include-path='
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/lessc/nested'))
+ \ . ' -'
+
+Execute(The global override should work):
+ let b:ale_less_lessc_executable = 'foobar'
+ let b:ale_less_lessc_use_global = 1
+
+ call ale#test#SetFilename('../test-files/lessc/nested/testfile.less')
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+ \ . ' --no-color --lint'
+ \ . ' --include-path='
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/lessc/nested'))
+ \ . ' -'
+
+Execute(Extra options should be configurable):
+ let b:ale_less_lessc_options = '--whatever'
+
+ AssertLinter 'lessc', ale#Escape('lessc')
+ \ . ' --no-color --lint'
+ \ . ' --include-path='
+ \ . ale#Escape(ale#path#Simplify(g:dir))
+ \ . ' --whatever'
+ \ . ' -'
diff --git a/test/linter/test_lintr.vader b/test/linter/test_lintr.vader
new file mode 100644
index 00000000..a2791c4d
--- /dev/null
+++ b/test/linter/test_lintr.vader
@@ -0,0 +1,34 @@
+Before:
+ call ale#assert#SetUpLinterTest('r', 'lintr')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default lintr command should be correct):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'Rscript',
+ \ 'Rscript --vanilla -e '
+ \ . ale#Escape('suppressPackageStartupMessages(library(lintr));'
+ \ . 'lint(cache = FALSE, commandArgs(TRUE), '
+ \ . 'with_defaults())')
+ \ . ' %t'
+
+Execute(The lintr options should be configurable):
+ let b:ale_r_lintr_options = 'with_defaults(object_usage_linter = NULL)'
+
+ AssertLinter 'Rscript',
+ \ 'Rscript --vanilla -e '
+ \ . ale#Escape('suppressPackageStartupMessages(library(lintr));'
+ \ . 'lint(cache = FALSE, commandArgs(TRUE), '
+ \ . 'with_defaults(object_usage_linter = NULL))')
+ \ . ' %t'
+
+Execute(If the lint_package flag is set, lintr::lint_package should be called):
+ let b:ale_r_lintr_lint_package = 1
+
+ AssertLinter 'Rscript',
+ \ 'Rscript --vanilla -e '
+ \ . ale#Escape('suppressPackageStartupMessages(library(lintr));'
+ \ . 'lint_package(cache = FALSE, '
+ \ . 'linters = with_defaults())')
+ \ . ' %t'
diff --git a/test/linter/test_llc.vader b/test/linter/test_llc.vader
new file mode 100644
index 00000000..a0caaa48
--- /dev/null
+++ b/test/linter/test_llc.vader
@@ -0,0 +1,21 @@
+Before:
+ call ale#assert#SetUpLinterTest('llvm', 'llc')
+
+ function! AssertHasPrefix(str, prefix) abort
+ let msg = printf("'%s' is expected to be prefixed with '%s'", a:str, a:prefix)
+ AssertEqual stridx(a:str, a:prefix), 0, msg
+ endfunction
+
+After:
+ delfunction AssertHasPrefix
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The llc command should be customizable):
+ AssertLinter 'llc',
+ \ ale#Escape('llc') . ' -filetype=null -o=' . g:ale#util#nul_file
+
+ let g:ale_llvm_llc_executable = 'llc-5.0'
+
+ AssertLinter 'llc-5.0',
+ \ ale#Escape('llc-5.0') . ' -filetype=null -o=' . g:ale#util#nul_file
diff --git a/test/linter/test_luac.vader b/test/linter/test_luac.vader
new file mode 100644
index 00000000..55f39cba
--- /dev/null
+++ b/test/linter/test_luac.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('lua', 'luac')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'luac', ale#Escape('luac') . ' -p -'
+
+Execute(The luac executable should be configurable):
+ let g:ale_lua_luac_executable = 'luac.sh'
+
+ AssertLinter 'luac.sh', ale#Escape('luac.sh') . ' -p -'
diff --git a/test/linter/test_luacheck.vader b/test/linter/test_luacheck.vader
new file mode 100644
index 00000000..f0ef221c
--- /dev/null
+++ b/test/linter/test_luacheck.vader
@@ -0,0 +1,23 @@
+Before:
+ call ale#assert#SetUpLinterTest('lua', 'luacheck')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The lua luacheck command callback should return the correct default string):
+ AssertLinter 'luacheck',
+ \ ale#Escape('luacheck') . ' --formatter plain --codes --filename %s -'
+
+Execute(The lua luacheck command callback should let you set options):
+ let g:ale_lua_luacheck_options = '--config filename'
+
+ AssertLinter 'luacheck',
+ \ ale#Escape('luacheck')
+ \ . ' --config filename'
+ \ . ' --formatter plain --codes --filename %s -'
+
+Execute(The luacheck executable should be configurable):
+ let g:ale_lua_luacheck_executable = 'luacheck.sh'
+
+ AssertLinter 'luacheck.sh',
+ \ ale#Escape('luacheck.sh') . ' --formatter plain --codes --filename %s -'
diff --git a/test/linter/test_markdown_markdownlint.vader b/test/linter/test_markdown_markdownlint.vader
new file mode 100644
index 00000000..12766cfd
--- /dev/null
+++ b/test/linter/test_markdown_markdownlint.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('markdown', 'markdownlint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'markdownlint', ale#Escape('markdownlint') . ' %s'
+
+Execute(The options should be configurable):
+ let g:ale_markdown_markdownlint_options = '--config ~/custom/.markdownlintrc'
+
+ AssertLinter 'markdownlint', ale#Escape('markdownlint') . ' --config ~/custom/.markdownlintrc %s'
diff --git a/test/linter/test_markdown_mdl.vader b/test/linter/test_markdown_mdl.vader
new file mode 100644
index 00000000..1ce4db1a
--- /dev/null
+++ b/test/linter/test_markdown_mdl.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('markdown', 'mdl')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'mdl', ale#Escape('mdl') . ' -j'
+
+Execute(The executable and options should be configurable):
+ let g:ale_markdown_mdl_executable = 'foo bar'
+ let g:ale_markdown_mdl_options = '--wat'
+
+ AssertLinter 'foo bar', ale#Escape('foo bar') . ' -j --wat'
+
+Execute(Setting bundle appends 'exec mdl'):
+ let g:ale_markdown_mdl_executable = 'path to/bundle'
+
+ AssertLinter 'path to/bundle', ale#Escape('path to/bundle') . ' exec mdl -j'
diff --git a/test/linter/test_markdown_vale.vader b/test/linter/test_markdown_vale.vader
new file mode 100644
index 00000000..5300805b
--- /dev/null
+++ b/test/linter/test_markdown_vale.vader
@@ -0,0 +1,32 @@
+Before:
+ call ale#assert#SetUpLinterTest('markdown', 'vale')
+ call ale#test#SetFilename('dummy.md')
+
+ let g:ale_markdown_vale_executable = 'vale'
+ let g:ale_markdown_vale_input_file = '%t'
+ let g:ale_markdown_vale_options = ''
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to vale):
+ AssertLinter 'vale', ale#Escape('vale')
+ \ . ' --output=JSON %t'
+
+Execute(Should be able to set a custom executable):
+ let g:ale_markdown_vale_executable = 'bin/vale'
+
+ AssertLinter 'bin/vale' , ale#Escape('bin/vale')
+ \ . ' --output=JSON %t'
+
+Execute(Should be able to set custom options):
+ let g:ale_markdown_vale_options = '--foo --bar'
+
+ AssertLinter 'vale', ale#Escape('vale')
+ \ . ' --output=JSON --foo --bar %t'
+
+Execute(Should be able to set a custom input file):
+ let g:ale_markdown_vale_input_file = '%s'
+
+ AssertLinter 'vale', ale#Escape('vale')
+ \ . ' --output=JSON %s'
diff --git a/test/linter/test_mercury_mmc.vader b/test/linter/test_mercury_mmc.vader
new file mode 100644
index 00000000..5ab5e74f
--- /dev/null
+++ b/test/linter/test_mercury_mmc.vader
@@ -0,0 +1,22 @@
+Before:
+ call ale#assert#SetUpLinterTest('mercury', 'mmc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'mmc',
+ \ ale#Escape('mmc') . ' --errorcheck-only --make --output-compile-error-lines 100 %s:t:r'
+
+Execute(The executable should be configurable):
+ let b:ale_mercury_mmc_executable = 'foo'
+
+ AssertLinter 'foo',
+ \ ale#Escape('foo') . ' --errorcheck-only --make --output-compile-error-lines 100 %s:t:r'
+
+Execute(The options should be configurable):
+ let b:ale_mercury_mmc_options = '--bar'
+
+ AssertLinter 'mmc',
+ \ ale#Escape('mmc') . ' --errorcheck-only --bar %s:t:r'
diff --git a/test/linter/test_mypy.vader b/test/linter/test_mypy.vader
new file mode 100644
index 00000000..8c1e5e9c
--- /dev/null
+++ b/test/linter/test_mypy.vader
@@ -0,0 +1,90 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'mypy')
+ call ale#test#SetFilename('test.py')
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The mypy callbacks should return the correct default values):
+ AssertLinterCwd g:dir
+ AssertLinter 'mypy',
+ \ ale#Escape('mypy')
+ \ . ' --show-column-numbers'
+ \ . ' --shadow-file %s %t %s'
+
+Execute(The mypy executable should be configurable, and escaped properly):
+ let g:ale_python_mypy_executable = 'executable with spaces'
+
+ AssertLinter 'executable with spaces',
+ \ ale#Escape('executable with spaces')
+ \ . ' --show-column-numbers'
+ \ . ' --shadow-file %s %t %s'
+
+Execute(The mypy command callback should let you set options):
+ let g:ale_python_mypy_options = '--some-option'
+
+ AssertLinter 'mypy',
+ \ ale#Escape('mypy')
+ \ . ' --some-option'
+ \ . ' --show-column-numbers'
+ \ . ' --shadow-file %s %t %s'
+
+Execute(The mypy command should switch directories to the detected project root):
+ call ale#test#SetFilename('../test-files/python/no_virtualenv/subdir/foo/bar.py')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/no_virtualenv/subdir')
+ AssertLinter 'mypy',
+ \ ale#Escape('mypy')
+ \ . ' --show-column-numbers'
+ \ . ' --shadow-file %s %t %s'
+
+Execute(The mypy callbacks should detect virtualenv directories and switch to the project root):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let b:executable = ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/mypy')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
+ AssertLinter b:executable,
+ \ ale#Escape(b:executable)
+ \ . ' --show-column-numbers'
+ \ . ' --shadow-file %s %t %s'
+
+Execute(The mypy callbacks should cd to directory containing mypy.ini if found):
+ call ale#test#SetFilename('../test-files/python/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_mypy_ini_and_pytest_ini')
+ AssertLinter 'mypy',
+ \ ale#Escape('mypy')
+ \ . ' --show-column-numbers'
+ \ . ' --shadow-file %s %t %s'
+
+Execute(You should able able to use the global mypy instead):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+ let g:ale_python_mypy_use_global = 1
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
+ AssertLinter 'mypy',
+ \ ale#Escape('mypy')
+ \ . ' --show-column-numbers'
+ \ . ' --shadow-file %s %t %s'
+
+Execute(Setting executable to 'pipenv' appends 'run mypy'):
+ let g:ale_python_mypy_executable = 'path/to/pipenv'
+
+ AssertLinterCwd expand('#' . bufnr('') . ':p:h')
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv') . ' run mypy'
+ \ . ' --show-column-numbers --shadow-file %s %t %s'
+
+Execute(Pipenv is detected when python_mypy_auto_pipenv is set):
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+ let g:ale_python_mypy_auto_pipenv = 1
+
+ AssertLinterCwd expand('#' . bufnr('') . ':p:h')
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv') . ' run mypy --show-column-numbers --shadow-file %s %t %s'
diff --git a/test/linter/test_nagelfar.vader b/test/linter/test_nagelfar.vader
new file mode 100644
index 00000000..94bb1d53
--- /dev/null
+++ b/test/linter/test_nagelfar.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('tcl', 'nagelfar')
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'nagelfar.tcl', ale#Escape('nagelfar.tcl') . ' %s'
+
+ let b:ale_tcl_nagelfar_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' %s'
+
+Execute(The options should be configurable):
+ let b:ale_tcl_nagelfar_options = '--something'
+
+ AssertLinter 'nagelfar.tcl', ale#Escape('nagelfar.tcl') . ' --something %s'
diff --git a/test/linter/test_nasm_nasm.vader b/test/linter/test_nasm_nasm.vader
new file mode 100644
index 00000000..2bfe2b0d
--- /dev/null
+++ b/test/linter/test_nasm_nasm.vader
@@ -0,0 +1,32 @@
+Before:
+ call ale#assert#SetUpLinterTest('nasm', 'nasm')
+
+ let b:command_tail =
+ \ ' -X gnu -I %s:h' . (has('win32') ? '\' : '/') . ' %s -o ' . (has('win32') ? 'NUL' : '/dev/null')
+ let b:command_tail_opt =
+ \ ' -X gnu -I %s:h' . (has('win32') ? '\' : '/') . ' -w+orphan-labels %s -o ' . (has('win32') ? 'NUL' : '/dev/null')
+
+After:
+ unlet! b:command_tail
+ unlet! b:command_tail_opt
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'nasm', ale#Escape('nasm') . b:command_tail,
+
+ let b:ale_nasm_nasm_executable = '~/nasm'
+
+ AssertLinter '~/nasm', ale#Escape('~/nasm') . b:command_tail
+
+Execute(The options should be configurable):
+ let b:ale_nasm_nasm_options = '-w-macro-params'
+
+ AssertLinter 'nasm', ale#Escape('nasm')
+ \ . ' -X gnu -I %s:h' . (has('win32') ? '\' : '/')
+ \ . ' -w-macro-params %s -o ' . (has('win32') ? 'NUL' : '/dev/null')
+
+Execute(The options should be used in command):
+ let b:ale_nasm_nasm_options = '-w+orphan-labels'
+
+ AssertLinter 'nasm', ale#Escape('nasm') . b:command_tail_opt
diff --git a/test/linter/test_nimlsp.vader b/test/linter/test_nimlsp.vader
new file mode 100644
index 00000000..c109deef
--- /dev/null
+++ b/test/linter/test_nimlsp.vader
@@ -0,0 +1,12 @@
+Before:
+ call ale#assert#SetUpLinterTest('nim', 'nimlsp')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(It does not set nim sources by default):
+ AssertLinter 'nimlsp', ale#Escape('nimlsp')
+
+Execute(Sets nimlsp and escapes sources from g:ale_nim_nimlsp_nim_sources):
+ let g:ale_nim_nimlsp_nim_sources = '/path/to /Nim'
+ AssertLinter 'nimlsp', ale#Escape('nimlsp') . ' ' . ale#Escape('/path/to /Nim')
diff --git a/test/linter/test_objc_ccls.vader b/test/linter/test_objc_ccls.vader
new file mode 100644
index 00000000..58d824c5
--- /dev/null
+++ b/test/linter/test_objc_ccls.vader
@@ -0,0 +1,66 @@
+Before:
+ call ale#assert#SetUpLinterTest('objc', 'ccls')
+
+ Save b:ale_c_build_dir_names
+ Save b:ale_objc_ccls_executable
+ Save b:ale_objc_ccls_init_options
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The project root should be detected correctly using compile_commands.json file):
+ call ale#test#SetFilename(tempname() . '/dummy.m')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_compile_commands_json/dummy.m')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_compile_commands_json')
+
+Execute(The project root should be detected correctly using .ccls file):
+ call ale#test#SetFilename(tempname() . '/dummy.m')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_ccls/dummy.m')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_ccls')
+
+Execute(The project root should be detected correctly using .ccls-root file):
+ call ale#test#SetFilename(tempname() . '/dummy.m')
+
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ccls/with_ccls-root/dummy.m')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ccls/with_ccls-root')
+
+Execute(The executable should be configurable):
+ AssertLinter 'ccls', ale#Escape('ccls')
+
+ let b:ale_objc_ccls_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+
+Execute(The initialization options should be configurable):
+ AssertLSPOptions {}
+
+ let b:ale_objc_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' }
+
+ AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' }
+
+Execute(The compile command database should be detected correctly):
+ call ale#test#SetFilename('../test-files/ccls/with_ccls/dummy.c')
+
+ AssertLSPOptions {}
+
+ call ale#test#SetFilename('../test-files/ccls/with_compile_commands_json/dummy.c')
+
+ AssertLSPOptions { 'compilationDatabaseDirectory':
+ \ ale#path#Simplify(g:dir . '/../test-files/ccls/with_compile_commands_json') }
+
+ call ale#test#SetFilename('../test-files/ccls/with_build_dir/dummy.c')
+ let b:ale_c_build_dir_names = ['unusual_build_dir_name']
+
+ AssertLSPOptions { 'compilationDatabaseDirectory':
+ \ ale#path#Simplify(g:dir . '/../test-files/ccls/with_build_dir/unusual_build_dir_name') }
diff --git a/test/linter/test_ocaml_ocamllsp.vader b/test/linter/test_ocaml_ocamllsp.vader
new file mode 100644
index 00000000..4f33af18
--- /dev/null
+++ b/test/linter/test_ocaml_ocamllsp.vader
@@ -0,0 +1,29 @@
+Before:
+ call ale#assert#SetUpLinterTest('ocaml', 'ocamllsp')
+
+ Save &filetype
+ let &filetype = 'ocaml'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The language string should be correct):
+ AssertLSPLanguage 'ocaml'
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ocamllsp/file.ml')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ocamllsp')
+
+Execute(The executable should be run using opam exec by default):
+ call ale#test#SetFilename('../test-files/ocamllsp/file.ml')
+
+ AssertLinter 'ocamllsp', 'opam config exec -- ocamllsp'
+
+Execute(The executable should be run directly if use_opam flag is disabled):
+ let g:ale_ocaml_ocamllsp_use_opam = 0
+ call ale#test#SetFilename('../test-files/ocamllsp/file.ml')
+
+ AssertLinter 'ocamllsp', 'ocamllsp'
diff --git a/test/linter/test_ocaml_ols.vader b/test/linter/test_ocaml_ols.vader
new file mode 100644
index 00000000..bf9ae65b
--- /dev/null
+++ b/test/linter/test_ocaml_ols.vader
@@ -0,0 +1,40 @@
+Before:
+ call ale#assert#SetUpLinterTest('ocaml', 'ols')
+
+ Save &filetype
+ let &filetype = 'ocaml'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The language string should be correct):
+ AssertLSPLanguage 'ocaml'
+
+Execute(The default executable should be correct):
+ AssertLinter 'ocaml-language-server',
+ \ ale#Escape('ocaml-language-server') . ' --stdio'
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ols/file.ml')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ols')
+
+Execute(The local executable should be used when available):
+ call ale#test#SetFilename('../test-files/ols/file.ml')
+
+ AssertLinter ale#path#Simplify(g:dir . '/../test-files/ols/node_modules/.bin/ocaml-language-server'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/ols/node_modules/.bin/ocaml-language-server')) . ' --stdio'
+
+Execute(The gloabl executable should always be used when use_global is set):
+ let g:ale_ocaml_ols_use_global = 1
+ call ale#test#SetFilename('../test-files/ols/file.ml')
+
+ AssertLinter 'ocaml-language-server',
+ \ ale#Escape('ocaml-language-server') . ' --stdio'
+
+Execute(The executable should be configurable):
+ let g:ale_ocaml_ols_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio'
diff --git a/test/linter/test_perl.vader b/test/linter/test_perl.vader
new file mode 100644
index 00000000..3c4b661c
--- /dev/null
+++ b/test/linter/test_perl.vader
@@ -0,0 +1,14 @@
+Before:
+ call ale#assert#SetUpLinterTest('perl', 'perl')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default Perl command callback should be correct):
+ AssertLinter 'perl', ale#Escape('perl') . ' -c -Mwarnings -Ilib %t'
+
+Execute(Overriding the executable and command should work):
+ let b:ale_perl_perl_executable = 'foobar'
+ let b:ale_perl_perl_options = '-w'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' -w %t'
diff --git a/test/linter/test_perl6.vader b/test/linter/test_perl6.vader
new file mode 100644
index 00000000..d3ec6e17
--- /dev/null
+++ b/test/linter/test_perl6.vader
@@ -0,0 +1,14 @@
+Before:
+ call ale#assert#SetUpLinterTest('perl6', 'perl6')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default Perl6 command callback should be correct):
+ AssertLinter 'perl6', 'perl6' . ' -c -Ilib %t'
+
+Execute(Overriding the executable and command should work):
+ let b:ale_perl6_perl6_executable = 'foobar'
+ let b:ale_perl6_perl6_options = '-w'
+
+ AssertLinter 'foobar', 'foobar' . ' -w %t'
diff --git a/test/linter/test_perlcritic.vader b/test/linter/test_perlcritic.vader
new file mode 100644
index 00000000..0f1e2856
--- /dev/null
+++ b/test/linter/test_perlcritic.vader
@@ -0,0 +1,36 @@
+Before:
+ call ale#assert#SetUpLinterTest('perl', 'perlcritic')
+ call ale#test#SetFilename('test.pl')
+ let g:ale_perl_perlcritic_profile = ''
+
+After:
+ unlet! b:readme_path
+ call ale#assert#TearDownLinterTest()
+
+Execute(The command should be correct with g:ale_perl_perlcritic_showrules off):
+ let b:ale_perl_perlcritic_showrules = 0
+
+ AssertLinter 'perlcritic', ale#Escape('perlcritic')
+ \ . ' --verbose ' . ale#Escape('%l:%c %m\n') . ' --nocolor'
+
+Execute(The command should be correct with g:ale_perl_perlcritic_showrules on):
+ let b:ale_perl_perlcritic_showrules = 1
+
+ AssertLinter 'perlcritic', ale#Escape('perlcritic')
+ \ . ' --verbose ' . ale#Escape('%l:%c %m [%p]\n') . ' --nocolor'
+
+Execute(The command search for the profile file when set):
+ let b:ale_perl_perlcritic_profile = 'README.md'
+
+ let b:readme_path = ale#path#Simplify(expand('%:p:h:h:h') . '/README.md')
+
+ AssertLinter 'perlcritic', ale#Escape('perlcritic')
+ \ . ' --verbose ' . ale#Escape('%l:%c %m\n') . ' --nocolor'
+ \ . ' --profile ' . ale#Escape(b:readme_path)
+
+Execute(Extra options should be set appropriately):
+ let b:ale_perl_perlcritic_options = 'beep boop'
+
+ AssertLinter 'perlcritic', ale#Escape('perlcritic')
+ \ . ' --verbose ' . ale#Escape('%l:%c %m\n') . ' --nocolor'
+ \ . ' beep boop'
diff --git a/test/linter/test_php.vader b/test/linter/test_php.vader
new file mode 100644
index 00000000..670d7196
--- /dev/null
+++ b/test/linter/test_php.vader
@@ -0,0 +1,15 @@
+Before:
+ call ale#assert#SetUpLinterTest('php', 'php')
+ let b:command_tail = ' -l -d error_reporting=E_ALL -d display_errors=1'
+ \ . ' -d log_errors=0 --'
+
+After:
+ unlet! b:command_tail
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'php', ale#Escape('php') . b:command_tail
+
+ let b:ale_php_php_executable = '/path/to/php'
+
+ AssertLinter '/path/to/php', ale#Escape('/path/to/php') . b:command_tail
diff --git a/test/linter/test_php_intelephense.vader b/test/linter/test_php_intelephense.vader
new file mode 100644
index 00000000..d6e2469d
--- /dev/null
+++ b/test/linter/test_php_intelephense.vader
@@ -0,0 +1,26 @@
+Before:
+ call ale#assert#SetUpLinterTest('php', 'intelephense')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'intelephense',
+ \ ale#Escape('intelephense') . ' --stdio'
+
+Execute(The project path should be correct for .git directories):
+ call ale#test#SetFilename('../test-files/php/with-git/test.php')
+ silent! call mkdir('../test-files/php/with-git/.git', 'p')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/php/with-git')
+
+Execute(The project path should be correct for composer.json file):
+ call ale#test#SetFilename('../test-files/php/with-composer/test.php')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/php/with-composer')
+
+Execute(The project cache should be saved in a temp dir):
+ call ale#test#SetFilename('../test-files/php/with-composer/test.php')
+ let g:ale_php_intelephense_config = { 'storagePath': '/tmp/intelephense' }
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/php/with-composer')
diff --git a/test/linter/test_php_langserver.vader b/test/linter/test_php_langserver.vader
new file mode 100644
index 00000000..7fe20b82
--- /dev/null
+++ b/test/linter/test_php_langserver.vader
@@ -0,0 +1,30 @@
+Before:
+ call ale#assert#SetUpLinterTest('php', 'langserver')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'php-language-server.php',
+ \ 'php ' . ale#Escape('php-language-server.php')
+
+Execute(Vendor executables should be detected):
+ call ale#test#SetFilename('../test-files/php/test.php')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/php/vendor/bin/php-language-server.php'),
+ \ 'php ' . ale#Escape(ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/php/vendor/bin/php-language-server.php'
+ \ ))
+
+Execute(The project path should be correct for .git directories):
+ call ale#test#SetFilename('../test-files/php/with-git/test.php')
+ silent! call mkdir('../test-files/php/with-git/.git')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/php/with-git')
+
+Execute(The project path should be correct for composer.json file):
+ call ale#test#SetFilename('../test-files/php/with-composer/test.php')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/php/with-composer')
diff --git a/test/linter/test_phpcs.vader b/test/linter/test_phpcs.vader
new file mode 100644
index 00000000..afb88e32
--- /dev/null
+++ b/test/linter/test_phpcs.vader
@@ -0,0 +1,42 @@
+Before:
+ call ale#assert#SetUpLinterTest('php', 'phpcs')
+
+After:
+ unlet! g:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The local phpcs executable should be used):
+ call ale#test#SetFilename('../test-files/phpcs/project-with-phpcs/foo/test.php')
+
+ let g:executable = ale#path#Simplify(g:dir . '/../test-files/phpcs/project-with-phpcs/vendor/bin/phpcs')
+
+ AssertLinterCwd '%s:h'
+ AssertLinter g:executable, ale#Escape(g:executable)
+ \ . ' -s --report=emacs --stdin-path=%s'
+
+Execute(use_global should override local executable detection):
+ let g:ale_php_phpcs_use_global = 1
+
+ call ale#test#SetFilename('../test-files/phpcs/project-with-phpcs/foo/test.php')
+
+ AssertLinter 'phpcs', ale#Escape('phpcs')
+ \ . ' -s --report=emacs --stdin-path=%s'
+
+Execute(Projects without local executables should use the global one):
+ call ale#test#SetFilename('../test-files/phpcs/project-without-phpcs/foo/test.php')
+
+ AssertLinter 'phpcs', ale#Escape('phpcs')
+ \ . ' -s --report=emacs --stdin-path=%s'
+
+Execute(User provided options should be used):
+ let g:ale_php_phpcs_options = '--my-user-provided-option my-value'
+
+ AssertLinter 'phpcs', ale#Escape('phpcs')
+ \ . ' -s --report=emacs --stdin-path=%s --my-user-provided-option my-value'
+
+Execute(The _standard option should be used):
+ let g:ale_php_phpcs_standard = 'foobar'
+
+ AssertLinter 'phpcs', ale#Escape('phpcs')
+ \ . ' -s --report=emacs --stdin-path=%s --standard=' . ale#Escape('foobar')
diff --git a/test/linter/test_phpmd.vader b/test/linter/test_phpmd.vader
new file mode 100644
index 00000000..64922820
--- /dev/null
+++ b/test/linter/test_phpmd.vader
@@ -0,0 +1,12 @@
+Before:
+ call ale#assert#SetUpLinterTest('php', 'phpmd')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Custom executables should be used for the executable and command):
+ let g:ale_php_phpmd_executable = 'phpmd_test'
+
+ AssertLinter 'phpmd_test',
+ \ ale#Escape('phpmd_test')
+ \ . ' %s text cleancode,codesize,controversial,design,naming,unusedcode --ignore-violations-on-exit %t'
diff --git a/test/linter/test_phpstan.vader b/test/linter/test_phpstan.vader
new file mode 100644
index 00000000..813fe448
--- /dev/null
+++ b/test/linter/test_phpstan.vader
@@ -0,0 +1,85 @@
+Before:
+ call ale#assert#SetUpLinterTest('php', 'phpstan')
+
+ let g:old_dir = g:dir
+
+ " Create a temporary directory and work within it, otherwise these tests
+ " cannot be run in parallel.
+ let g:dir = tempname()
+ call mkdir(g:dir, '', 0750)
+ silent! execute 'cd ' . fnameescape(g:dir)
+ silent! noautocmd execute 'file ' . fnameescape(ale#path#Simplify(g:dir . '/test.php'))
+
+ call delete('./phpstan.neon')
+
+ GivenCommandOutput ['0.10.2']
+
+After:
+ silent! execute 'cd ' . fnameescape(g:old_dir)
+ call delete(g:dir, 'rf')
+ let g:dir = g:old_dir
+ unlet! g:old_dir
+ call ale#assert#TearDownLinterTest()
+
+Execute(Custom executables should be used for the executable and command):
+ let g:ale_php_phpstan_executable = 'phpstan_test'
+
+ AssertLinter 'phpstan_test',
+ \ ale#Escape('phpstan_test') . ' analyze --no-progress --errorFormat raw -l ' . ale#Escape('4') . ' %s'
+
+Execute(project with level set to 3):
+ call ale#test#SetFilename('phpstan-test-files/foo/test.php')
+ let g:ale_php_phpstan_level = 3
+
+ AssertLinter 'phpstan',
+ \ ale#Escape('phpstan') . ' analyze --no-progress --errorFormat raw -l ' . ale#Escape('3') . ' %s'
+
+Execute(Custom phpstan configuration file):
+ let g:ale_php_phpstan_configuration = 'phpstan_config'
+
+ AssertLinter 'phpstan',
+ \ ale#Escape('phpstan') . ' analyze --no-progress --errorFormat raw -c ' . ale#Escape('phpstan_config') . ' -l ' . ale#Escape('4') . ' %s'
+
+Execute(Choose the right format for error format param):
+ GivenCommandOutput ['0.10.3']
+
+ AssertLinter 'phpstan', [
+ \ ale#Escape('phpstan') . ' --version',
+ \ ale#Escape('phpstan') . ' analyze --no-progress --error-format raw -l ' . ale#Escape('4') . ' %s'
+ \ ]
+
+Execute(Configuration file exists in current directory):
+ call writefile(['parameters:', ' level: 7'], './phpstan.neon')
+ let g:ale_php_phpstan_level = ''
+ let g:ale_php_phpstan_configuration = ''
+
+ AssertLinter 'phpstan', [
+ \ ale#Escape('phpstan') . ' --version',
+ \ ale#Escape('phpstan') . ' analyze --no-progress --errorFormat raw %s'
+ \ ]
+
+Execute(Configuration file exists in current directory, but force phpstan level):
+ call writefile(['parameters:', ' level: 7'], './phpstan.neon')
+ let g:ale_php_phpstan_configuration = ''
+ let g:ale_php_phpstan_level = '7'
+
+ AssertLinter 'phpstan', [
+ \ ale#Escape('phpstan') . ' --version',
+ \ ale#Escape('phpstan') . ' analyze --no-progress --errorFormat raw -l ' . ale#Escape('7') . ' %s'
+ \ ]
+
+Execute(Configuration file exists in current directory, but force phpstan configuration):
+ call writefile(['parameters:', ' level: 7'], './phpstan.neon')
+ let g:ale_php_phpstan_level = ''
+ let g:ale_php_phpstan_configuration = 'phpstan.custom.neon'
+
+ AssertLinter 'phpstan', [
+ \ ale#Escape('phpstan') . ' --version',
+ \ ale#Escape('phpstan') . ' analyze --no-progress --errorFormat raw -c ' . ale#Escape('phpstan.custom.neon') . ' %s'
+ \ ]
+
+Execute(Autoload parameter is added to the command):
+ let g:ale_php_phpstan_autoload = 'autoload.php'
+
+ AssertLinter 'phpstan',
+ \ ale#Escape('phpstan') . ' analyze --no-progress --errorFormat raw -a ' . ale#Escape('autoload.php') . ' -l ' . ale#Escape('4') . ' %s'
diff --git a/test/linter/test_pony_ponyc.vader b/test/linter/test_pony_ponyc.vader
new file mode 100644
index 00000000..3a3b32ec
--- /dev/null
+++ b/test/linter/test_pony_ponyc.vader
@@ -0,0 +1,12 @@
+Before:
+ call ale#assert#SetUpLinterTest('pony', 'ponyc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The options should be used in the command):
+ AssertLinter 'ponyc', ale#Escape('ponyc') . ' --pass paint'
+
+ let b:ale_pony_ponyc_options = 'foobar'
+
+ AssertLinter 'ponyc', ale#Escape('ponyc') . ' foobar'
diff --git a/test/linter/test_prospector.vader b/test/linter/test_prospector.vader
new file mode 100644
index 00000000..d6f84308
--- /dev/null
+++ b/test/linter/test_prospector.vader
@@ -0,0 +1,20 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'prospector')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Setting executable to 'pipenv' appends 'run prospector'):
+ let g:ale_python_prospector_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv') . ' run prospector'
+ \ . ' --messages-only --absolute-paths --zero-exit --output-format json %s'
+
+Execute(Pipenv is detected when python_prospector_auto_pipenv is set):
+ let g:ale_python_prospector_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv') . ' run prospector'
+ \ . ' --messages-only --absolute-paths --zero-exit --output-format json %s'
diff --git a/test/linter/test_proto.vader b/test/linter/test_proto.vader
new file mode 100644
index 00000000..726588c0
--- /dev/null
+++ b/test/linter/test_proto.vader
@@ -0,0 +1,16 @@
+Before:
+ call ale#assert#SetUpLinterTest('proto', 'protoc_gen_lint')
+ call ale#test#SetFilename('test.proto')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'protoc',
+ \ 'protoc' . ' -I ' . ale#Escape(getcwd()) . ' --lint_out=. ' . '%s'
+
+Execute(The callback should include any additional options):
+ let b:ale_proto_protoc_gen_lint_options = '--some-option'
+
+ AssertLinter 'protoc',
+ \ 'protoc' . ' -I ' . ale#Escape(getcwd()) . ' --some-option --lint_out=. ' . '%s'
diff --git a/test/linter/test_psalm.vader b/test/linter/test_psalm.vader
new file mode 100644
index 00000000..4edb95c8
--- /dev/null
+++ b/test/linter/test_psalm.vader
@@ -0,0 +1,38 @@
+Before:
+ call ale#assert#SetUpLinterTest('php', 'psalm')
+
+After:
+ unlet! g:i
+ unlet! g:matched
+
+ if isdirectory(g:dir . '/.git')
+ call delete(g:dir . '/.git', 'd')
+ endif
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'psalm',
+ \ ale#Escape('psalm') . ' --language-server'
+
+Execute(Vendor executables should be detected):
+ call ale#test#SetFilename('../test-files/psalm/test.php')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/psalm/vendor/bin/psalm'),
+ \ ale#Escape(ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/psalm/vendor/bin/psalm'
+ \ )) . ' --language-server'
+
+ let g:ale_php_psalm_use_global = 1
+
+ AssertLinter 'psalm',
+ \ ale#Escape('psalm') . ' --language-server'
+
+Execute(User provided options should be used):
+ let g:ale_php_psalm_options = '--my-user-provided-option my-value'
+
+ AssertLinter 'psalm',
+ \ ale#Escape('psalm')
+ \ . ' --language-server --my-user-provided-option my-value'
diff --git a/test/linter/test_puglint.vader b/test/linter/test_puglint.vader
new file mode 100644
index 00000000..8a445408
--- /dev/null
+++ b/test/linter/test_puglint.vader
@@ -0,0 +1,48 @@
+Before:
+ call ale#assert#SetUpLinterTest('pug', 'puglint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(puglint should detect local executables and package.json):
+ call ale#test#SetFilename('../test-files/puglint/test.pug')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/puglint/node_modules/.bin/pug-lint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/node_modules/.bin/pug-lint'))
+ \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/package.json'))
+ \ . ' -r inline %t'
+
+Execute(puglint should use global executables if configured):
+ let g:ale_pug_puglint_use_global = 1
+
+ call ale#test#SetFilename('../test-files/puglint/test.pug')
+
+ AssertLinter 'pug-lint',
+ \ ale#Escape('pug-lint')
+ \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/package.json'))
+ \ . ' -r inline %t'
+
+Execute(puglint should detect .pug-lintrc):
+ call ale#test#SetFilename('../test-files/puglint/puglint_rc_dir/subdir/test.pug')
+
+ AssertLinter ale#path#Simplify(g:dir . '/../test-files/puglint/node_modules/.bin/pug-lint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/node_modules/.bin/pug-lint'))
+ \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/puglint_rc_dir/.pug-lintrc'))
+ \ . ' -r inline %t'
+
+Execute(puglint should detect .pug-lintrc.js):
+ call ale#test#SetFilename('../test-files/puglint/puglint_rc_js_dir/subdir/test.pug')
+
+ AssertLinter ale#path#Simplify(g:dir . '/../test-files/puglint/node_modules/.bin/pug-lint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/node_modules/.bin/pug-lint'))
+ \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/puglint_rc_js_dir/.pug-lintrc.js'))
+ \ . ' -r inline %t'
+
+Execute(puglint should detect .pug-lintrc.json):
+ call ale#test#SetFilename('../test-files/puglint/puglint_rc_json_dir/subdir/test.pug')
+
+ AssertLinter ale#path#Simplify(g:dir . '/../test-files/puglint/node_modules/.bin/pug-lint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/node_modules/.bin/pug-lint'))
+ \ . ' -c ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/puglint/puglint_rc_json_dir/.pug-lintrc.json'))
+ \ . ' -r inline %t'
diff --git a/test/linter/test_purescript_ls.vader b/test/linter/test_purescript_ls.vader
new file mode 100644
index 00000000..3ef9707a
--- /dev/null
+++ b/test/linter/test_purescript_ls.vader
@@ -0,0 +1,31 @@
+Before:
+ call ale#assert#SetUpLinterTest('purescript', 'ls')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set correct defaults):
+ AssertLinter 'purescript-language-server', ale#Escape('purescript-language-server') . ' --stdio'
+
+Execute(should set correct LSP values):
+ call ale#test#SetFilename('../test-files/purescript/spago/Foo.purs')
+
+ AssertLSPLanguage 'purescript'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/purescript/spago')
+
+Execute(should set correct project for bower):
+ call ale#test#SetFilename('../test-files/purescript/bower/Foo.purs')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/purescript/bower')
+
+Execute(should set correct project for psc-package):
+ call ale#test#SetFilename('../test-files/purescript/psc-package/Foo.purs')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/purescript/psc-package')
+
+Execute(should accept configuration settings):
+ AssertLSPConfig {}
+ let b:ale_purescript_ls_config = {'purescript': {'addSpagoSources': v:true}}
+ AssertLSPConfig {'purescript': {'addSpagoSources': v:true}}
diff --git a/test/linter/test_pycodestyle.vader b/test/linter/test_pycodestyle.vader
new file mode 100644
index 00000000..9260913c
--- /dev/null
+++ b/test/linter/test_pycodestyle.vader
@@ -0,0 +1,33 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'pycodestyle')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The pycodestyle command callback should return default string):
+ AssertLinter 'pycodestyle', ale#Escape('pycodestyle') . ' -'
+
+Execute(The pycodestyle command callback should allow options):
+ let g:ale_python_pycodestyle_options = '--exclude=test*.py'
+
+ AssertLinter 'pycodestyle',
+ \ ale#Escape('pycodestyle') . ' --exclude=test*.py -'
+
+Execute(The pycodestyle executable should be configurable):
+ let g:ale_python_pycodestyle_executable = '~/.local/bin/pycodestyle'
+
+ AssertLinter '~/.local/bin/pycodestyle',
+ \ ale#Escape('~/.local/bin/pycodestyle') . ' -'
+
+Execute(Setting executable to 'pipenv' appends 'run pycodestyle'):
+ let g:ale_python_pycodestyle_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv') . ' run pycodestyle -'
+
+Execute(Pipenv is detected when python_pycodestyle_auto_pipenv is set):
+ let g:ale_python_pycodestyle_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv') . ' run pycodestyle -'
diff --git a/test/linter/test_pydocstyle.vader b/test/linter/test_pydocstyle.vader
new file mode 100644
index 00000000..b24cb0d9
--- /dev/null
+++ b/test/linter/test_pydocstyle.vader
@@ -0,0 +1,33 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'pydocstyle')
+ call ale#test#SetFilename('test.py')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The pydocstyle command callback should return default string):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'pydocstyle', ale#Escape('pydocstyle') . ' %s:t'
+
+Execute(The pydocstyle command callback should allow options):
+ let g:ale_python_pydocstyle_options = '--verbose'
+
+ AssertLinter 'pydocstyle', ale#Escape('pydocstyle') . ' --verbose %s:t'
+
+Execute(The pydocstyle executable should be configurable):
+ let g:ale_python_pydocstyle_executable = '~/.local/bin/pydocstyle'
+
+ AssertLinter '~/.local/bin/pydocstyle',
+ \ ale#Escape('~/.local/bin/pydocstyle') . ' %s:t'
+
+Execute(Setting executable to 'pipenv' appends 'run pydocstyle'):
+ let g:ale_python_pydocstyle_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv') . ' run pydocstyle %s:t'
+
+Execute(Pipenv is detected when python_pydocstyle_auto_pipenv is set):
+ let g:ale_python_pydocstyle_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinter 'pipenv', ale#Escape('pipenv') . ' run pydocstyle %s:t'
diff --git a/test/linter/test_pyflakes.vader b/test/linter/test_pyflakes.vader
new file mode 100644
index 00000000..bbb7b74c
--- /dev/null
+++ b/test/linter/test_pyflakes.vader
@@ -0,0 +1,46 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'pyflakes')
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+ call ale#assert#TearDownLinterTest()
+
+Execute(The pyflakes command callback should return default string):
+ AssertLinter 'pyflakes', ale#Escape('pyflakes') . ' %t'
+
+Execute(The pyflakes executable should be configurable):
+ let g:ale_python_pyflakes_executable = '~/.local/bin/pyflakes'
+
+ AssertLinter '~/.local/bin/pyflakes',
+ \ ale#Escape('~/.local/bin/pyflakes') . ' %t'
+
+Execute(The pyflakes executable should be run from the virtualenv path):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/pyflakes'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' %t'
+
+Execute(You should be able to override the pyflakes virtualenv lookup):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let g:ale_python_pyflakes_use_global = 1
+
+ AssertLinter 'pyflakes', ale#Escape('pyflakes') . ' %t'
+
+Execute(Setting executable to 'pipenv' appends 'run pyflakes'):
+ let g:ale_python_pyflakes_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv') . ' run pyflakes %t',
+
+Execute(Pipenv is detected when python_pyflakes_auto_pipenv is set):
+ let g:ale_python_pyflakes_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv') . ' run pyflakes %t'
diff --git a/test/linter/test_pylama.vader b/test/linter/test_pylama.vader
new file mode 100644
index 00000000..29fa971b
--- /dev/null
+++ b/test/linter/test_pylama.vader
@@ -0,0 +1,76 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'pylama')
+ call ale#test#SetFilename('test.py')
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+ let b:command_tail = ' %s'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default pylama command should be correct):
+ AssertLinterCwd ale#path#Simplify(g:dir)
+ AssertLinter 'pylama', ale#Escape('pylama') . b:command_tail
+
+Execute(The option for disabling changing directories should work):
+ let g:ale_python_pylama_change_directory = 0
+
+ AssertLinterCwd ''
+ AssertLinter 'pylama', ale#Escape('pylama') . b:command_tail
+
+Execute(The pylama executable should be configurable, and escaped properly):
+ let g:ale_python_pylama_executable = 'executable with spaces'
+
+ AssertLinterCwd ale#path#Simplify(g:dir)
+ AssertLinter 'executable with spaces',
+ \ ale#Escape('executable with spaces') . b:command_tail
+
+Execute(The pylama command callback should let you set options):
+ let g:ale_python_pylama_options = '--some-option'
+
+ AssertLinterCwd ale#path#Simplify(g:dir)
+ AssertLinter 'pylama', ale#Escape('pylama') . ' --some-option' . b:command_tail
+
+Execute(The pylama command callback should switch directories to the detected project root):
+ silent execute 'file ' . fnameescape(g:dir . '/../test-files/python/no_virtualenv/subdir/foo/bar.py')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/no_virtualenv/subdir')
+ AssertLinter 'pylama', ale#Escape('pylama') . b:command_tail
+
+Execute(The pylama command callback shouldn't detect virtualenv directories where they don't exist):
+ call ale#test#SetFilename('../test-files/python/no_virtualenv/subdir/foo/bar.py')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/no_virtualenv/subdir')
+ AssertLinter 'pylama', ale#Escape('pylama') . b:command_tail
+
+Execute(The pylama command callback should detect virtualenv directories and switch to the project root):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+ let b:executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/pylama'
+ \)
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
+ AssertLinter b:executable, ale#Escape(b:executable) . b:command_tail
+
+Execute(You should able able to use the global pylama instead):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+ let g:ale_python_pylama_use_global = 1
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
+ AssertLinter 'pylama', ale#Escape('pylama') . b:command_tail
+
+Execute(Setting executable to 'pipenv' appends 'run pylama'):
+ let g:ale_python_pylama_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv') . ' run pylama' . b:command_tail
+
+Execute(Pipenv is detected when python_pylama_auto_pipenv is set):
+ let g:ale_python_pylama_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinter 'pipenv', ale#Escape('pipenv') . ' run pylama' . b:command_tail
diff --git a/test/linter/test_pylint.vader b/test/linter/test_pylint.vader
new file mode 100644
index 00000000..e581915f
--- /dev/null
+++ b/test/linter/test_pylint.vader
@@ -0,0 +1,81 @@
+Before:
+ Save g:ale_python_auto_pipenv
+
+ let g:ale_python_auto_pipenv = 0
+
+ call ale#assert#SetUpLinterTest('python', 'pylint')
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+ let b:command_tail = ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n %s'
+
+ GivenCommandOutput ['pylint 2.3.0']
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The pylint callbacks should return the correct default values):
+ AssertLinterCwd expand('%:p:h')
+ AssertLinter 'pylint', ale#Escape('pylint') . b:command_tail
+
+Execute(Pylint should run with the --from-stdin in new enough versions):
+ GivenCommandOutput ['pylint 2.4.0']
+
+ AssertLinterCwd expand('%:p:h')
+ AssertLinter 'pylint', ale#Escape('pylint') . b:command_tail[:-3] . '--from-stdin %s'
+
+Execute(The option for disabling changing directories should work):
+ let g:ale_python_pylint_change_directory = 0
+
+ AssertLinterCwd ''
+ AssertLinter 'pylint', ale#Escape('pylint') . b:command_tail
+
+Execute(The pylint executable should be configurable, and escaped properly):
+ let g:ale_python_pylint_executable = 'executable with spaces'
+
+ AssertLinter 'executable with spaces', ale#Escape('executable with spaces') . b:command_tail
+
+Execute(The pylint command callback should let you set options):
+ let g:ale_python_pylint_options = '--some-option'
+
+ AssertLinter 'pylint', ale#Escape('pylint') . ' --some-option' . b:command_tail
+
+Execute(The pylint callbacks shouldn't detect virtualenv directories where they don't exist):
+ call ale#test#SetFilename('../test-files/python/no_virtualenv/subdir/foo/bar.py')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/no_virtualenv/subdir')
+ AssertLinter 'pylint', ale#Escape('pylint') . b:command_tail
+
+Execute(The pylint callbacks should detect virtualenv directories):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+ let b:executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/pylint'
+ \)
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
+ AssertLinter b:executable, ale#Escape(b:executable) . b:command_tail
+
+Execute(You should able able to use the global pylint instead):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+ let g:ale_python_pylint_use_global = 1
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
+ AssertLinter 'pylint', ale#Escape('pylint') . b:command_tail
+
+Execute(Setting executable to 'pipenv' appends 'run pylint'):
+ let g:ale_python_pylint_executable = 'path/to/pipenv'
+ let g:ale_python_pylint_use_global = 1
+
+ AssertLinter 'path/to/pipenv', ale#Escape('path/to/pipenv') . ' run pylint'
+ \ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n %s'
+
+Execute(Pipenv is detected when python_pylint_auto_pipenv is set):
+ let g:ale_python_pylint_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinterCwd expand('%:p:h')
+ AssertLinter 'pipenv', ale#Escape('pipenv') . ' run pylint'
+ \ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n %s'
diff --git a/test/linter/test_pyls.vader b/test/linter/test_pyls.vader
new file mode 100644
index 00000000..74a86ccb
--- /dev/null
+++ b/test/linter/test_pyls.vader
@@ -0,0 +1,57 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'pyls')
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The pyls command callback should return default string):
+ AssertLinter 'pyls', ale#Escape('pyls')
+
+Execute(The pyls executable should be configurable):
+ let g:ale_python_pyls_executable = '~/.local/bin/pyls'
+
+ AssertLinter '~/.local/bin/pyls' , ale#Escape('~/.local/bin/pyls')
+
+Execute(The pyls command callback should let you set options):
+ let g:ale_python_pyls_options = '--some-option'
+
+ AssertLinter 'pyls', ale#Escape('pyls') . ' --some-option'
+
+Execute(The pyls executable should be run from the virtualenv path):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/pyls'
+ \)
+
+ AssertEqual ale#Escape(b:executable),
+ \ ale_linters#python#pyls#GetCommand(bufnr(''))
+
+Execute(You should be able to override the pyls virtualenv lookup):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let g:ale_python_pyls_use_global = 1
+
+ AssertLinter 'pyls', ale#Escape('pyls')
+
+Execute(Setting executable to 'pipenv' appends 'run pyls'):
+ let g:ale_python_pyls_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv', ale#Escape('path/to/pipenv') . ' run pyls'
+
+Execute(Pipenv is detected when python_pyls_auto_pipenv is set):
+ let g:ale_python_pyls_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv') . ' run pyls'
+
+Execute(Should accept configuration settings):
+ AssertLSPConfig {}
+ let b:ale_python_pyls_config = {'pyls': {'plugins': {'preload': {'enabled': v:false}}}}
+ AssertLSPConfig {'pyls': {'plugins': {'preload': {'enabled': v:false}}}}
diff --git a/test/linter/test_pyre.vader b/test/linter/test_pyre.vader
new file mode 100644
index 00000000..d3e5fe9d
--- /dev/null
+++ b/test/linter/test_pyre.vader
@@ -0,0 +1,46 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'pyre')
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+ call ale#assert#TearDownLinterTest()
+
+Execute(The pyre command callback should return default string):
+ AssertLinter 'pyre', ale#Escape('pyre') . ' persistent'
+
+Execute(The pyre executable should be configurable):
+ let g:ale_python_pyre_executable = '~/.local/bin/pyre'
+
+ AssertLinter '~/.local/bin/pyre',
+ \ ale#Escape('~/.local/bin/pyre') . ' persistent'
+
+Execute(The pyre executable should be run from the virtualenv path):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/pyre'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' persistent'
+
+Execute(You should be able to override the pyre virtualenv lookup):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let g:ale_python_pyre_use_global = 1
+
+ AssertLinter 'pyre', ale#Escape('pyre') . ' persistent'
+
+Execute(Setting executable to 'pipenv' appends 'run pyre'):
+ let g:ale_python_pyre_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv') . ' run pyre persistent'
+
+Execute(Pipenv is detected when python_pyre_auto_pipenv is set):
+ let g:ale_python_pyre_auto_pipenv = 1
+ call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')
+
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv') . ' run pyre persistent'
diff --git a/test/linter/test_pyrex_cython.vader b/test/linter/test_pyrex_cython.vader
new file mode 100644
index 00000000..af86366a
--- /dev/null
+++ b/test/linter/test_pyrex_cython.vader
@@ -0,0 +1,30 @@
+Before:
+ call ale#assert#SetUpLinterTest('pyrex', 'cython')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default cython command should be correct):
+ AssertLinter 'cython', ale#Escape('cython')
+ \ . ' --working %s:h'
+ \ . ' --include-dir %s:h'
+ \ . ' --warning-extra'
+ \ . ' --output-file ' . g:ale#util#nul_file . ' %t'
+
+Execute(The cython executable should be configurable):
+ let b:ale_pyrex_cython_executable = 'cython_foobar'
+
+ AssertLinter 'cython_foobar', ale#Escape('cython_foobar')
+ \ . ' --working %s:h'
+ \ . ' --include-dir %s:h'
+ \ . ' --warning-extra'
+ \ . ' --output-file ' . g:ale#util#nul_file . ' %t'
+
+Execute(Additional cython options should be configurable):
+ let b:ale_pyrex_cython_options = '--foobar'
+
+ AssertLinter 'cython', ale#Escape('cython')
+ \ . ' --working %s:h'
+ \ . ' --include-dir %s:h'
+ \ . ' --foobar'
+ \ . ' --output-file ' . g:ale#util#nul_file . ' %t'
diff --git a/test/linter/test_pyright.vader b/test/linter/test_pyright.vader
new file mode 100644
index 00000000..51510cf2
--- /dev/null
+++ b/test/linter/test_pyright.vader
@@ -0,0 +1,116 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'pyright')
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The command callback should return the correct default string):
+ AssertLinter
+ \ 'pyright-langserver',
+ \ ale#Escape('pyright-langserver') . ' --stdio'
+
+Execute(The executable should be configurable):
+ let g:ale_python_pyright_executable = '/bin/foo-bar'
+
+ AssertLinter
+ \ '/bin/foo-bar',
+ \ ale#Escape('/bin/foo-bar') . ' --stdio'
+
+Execute(The default configuration should be mostly empty):
+ " The default configuration needs to have at least one key in it,
+ " or the server won't start up properly.
+ AssertLSPConfig {'python': {}}
+
+ let b:ale_python_pyright_config = {}
+
+ AssertLSPConfig {'python': {}}
+
+Execute(virtualenv paths should be set in configuration by default):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ AssertLSPConfig {
+ \ 'python': {
+ \ 'pythonPath': ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/python'),
+ \ 'venvPath': ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env'),
+ \ },
+ \}
+
+Execute(The pythonPath should be set based on whatever the ovveride for the venvPath is set to):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ " This overrides the default detection of the path.
+ let b:ale_python_pyright_config = {
+ \ 'python': {
+ \ 'venvPath': '/foo/bar',
+ \ },
+ \}
+
+ AssertLSPConfig {
+ \ 'python': {
+ \ 'pythonPath': ale#path#Simplify('/foo/bar/' . b:bin_dir . '/python'),
+ \ 'venvPath': '/foo/bar',
+ \ },
+ \}
+
+Execute(You should be able to override pythonPath when venvPath is detected):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ " This overrides the default detection of the path.
+ let b:ale_python_pyright_config = {
+ \ 'python': {
+ \ 'pythonPath': '/bin/python',
+ \ },
+ \}
+
+ AssertLSPConfig {
+ \ 'python': {
+ \ 'pythonPath': '/bin/python',
+ \ 'venvPath': ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env'),
+ \ },
+ \}
+
+Execute(You should be able to override both pythonPath and venvPath):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ " This overrides the default detection of the path.
+ let b:ale_python_pyright_config = {
+ \ 'python': {
+ \ 'pythonPath': '/bin/python',
+ \ 'venvPath': '/other/dir',
+ \ },
+ \}
+
+ AssertLSPConfig {
+ \ 'python': {
+ \ 'pythonPath': '/bin/python',
+ \ 'venvPath': '/other/dir',
+ \ },
+ \}
+
+Execute(You should be able to define other settings):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let b:ale_python_pyright_config = {
+ \ 'python': {
+ \ 'analysis': {'logLevel': 'warning'},
+ \ },
+ \ 'pyright': {
+ \ 'disableLanguageServices': v:true,
+ \ },
+ \}
+
+ AssertLSPConfig {
+ \ 'python': {
+ \ 'analysis': {'logLevel': 'warning'},
+ \ 'pythonPath': ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/python'),
+ \ 'venvPath': ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/env'),
+ \ },
+ \ 'pyright': {
+ \ 'disableLanguageServices': v:true,
+ \ },
+ \}
diff --git a/test/linter/test_qmlfmt.vader b/test/linter/test_qmlfmt.vader
new file mode 100644
index 00000000..53502f4d
--- /dev/null
+++ b/test/linter/test_qmlfmt.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('qml', 'qmlfmt')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The qml qmlfmt command callback should return the correct default string):
+ AssertLinter 'qmlfmt', ale#Escape('qmlfmt') . ' -e',
+
+Execute(The qmlfmt executable should be configurable):
+ let g:ale_qml_qmlfmt_executable = '~/.local/bin/qmlfmt'
+
+ AssertLinter '~/.local/bin/qmlfmt', ale#Escape('~/.local/bin/qmlfmt') . ' -e'
diff --git a/test/linter/test_r_languageserver.vader b/test/linter/test_r_languageserver.vader
new file mode 100644
index 00000000..b5be0396
--- /dev/null
+++ b/test/linter/test_r_languageserver.vader
@@ -0,0 +1,22 @@
+Before:
+ call ale#assert#SetUpLinterTest('r', 'languageserver')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'Rscript', 'Rscript --vanilla -e ' . ale#Escape('languageserver::run()')
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject '.'
+
+ call ale#test#SetFilename('../test-files/r/dummy/test.R')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/r')
+
+Execute(Should accept configuration settings):
+ AssertLSPConfig {}
+
+ let b:ale_r_languageserver_config = {'r': {'lsp': {'debug': 'true', 'diagnostics': 'true'}}}
+
+ AssertLSPConfig {'r': {'lsp': {'debug': 'true', 'diagnostics': 'true'}}}
diff --git a/test/linter/test_racket_raco.vader b/test/linter/test_racket_raco.vader
new file mode 100644
index 00000000..fb83ffa1
--- /dev/null
+++ b/test/linter/test_racket_raco.vader
@@ -0,0 +1,10 @@
+Before:
+ call ale#assert#SetUpLinterTest('racket', 'raco')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command and executable should be correct):
+ AssertLinter 'raco', 'raco expand %s'
+
+
diff --git a/test/linter/test_rails_best_practices.vader b/test/linter/test_rails_best_practices.vader
new file mode 100644
index 00000000..6a6f7a53
--- /dev/null
+++ b/test/linter/test_rails_best_practices.vader
@@ -0,0 +1,42 @@
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'rails_best_practices')
+ call ale#test#SetFilename('../test-files/ruby/valid_rails_app/db/test.rb')
+
+ let b:args = '--silent -f json'
+ \ . ' --output-file ' . (has('win32') ? '%t' : '/dev/stdout')
+ let b:app_path = ale#path#Simplify(g:dir . '/../test-files/ruby/valid_rails_app')
+ let b:suffix = has('win32') ? '; type %t' : ''
+
+After:
+ unlet! b:args
+ unlet! b:app_path
+ unlet! b:suffix
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to rails_best_practices):
+ AssertLinter 'rails_best_practices', ale#Escape('rails_best_practices')
+ \ . ' ' . b:args
+ \ . ' ' . ale#Escape(b:app_path)
+ \ . b:suffix
+
+Execute(Should be able to set a custom executable):
+ let g:ale_ruby_rails_best_practices_executable = 'bin/rails_best_practices'
+
+ AssertLinter 'bin/rails_best_practices', ale#Escape('bin/rails_best_practices')
+ \ . ' ' . b:args
+ \ . ' ' . ale#Escape(b:app_path)
+ \ . b:suffix
+
+Execute(Setting bundle appends 'exec rails_best_practices'):
+ let g:ale_ruby_rails_best_practices_executable = 'path to/bundle'
+
+ AssertLinter 'path to/bundle', ale#Escape('path to/bundle')
+ \ . ' exec rails_best_practices'
+ \ . ' ' . b:args
+ \ . ' ' . ale#Escape(b:app_path)
+ \ . b:suffix
+
+Execute(Command callback should be empty when not in a valid Rails app):
+ call ale#test#SetFilename('../test-files/ruby/not_a_rails_app/test.rb')
+
+ AssertLinter 'rails_best_practices', ''
diff --git a/test/linter/test_reason_ls.vader b/test/linter/test_reason_ls.vader
new file mode 100644
index 00000000..57ea7302
--- /dev/null
+++ b/test/linter/test_reason_ls.vader
@@ -0,0 +1,21 @@
+Before:
+ call ale#assert#SetUpLinterTest('reason', 'ls')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The linter should not be run by default):
+ AssertLinterNotExecuted
+
+Execute(The executable should be configurable):
+ let b:ale_reason_ls_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+
+Execute(There should be no default project root):
+ AssertLSPProject ''
+
+Execute(The project root should be detected using bsconfig.json):
+ call ale#test#SetFilename('../test-files/reasonml/test.ml')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/reasonml')
diff --git a/test/linter/test_reason_ols.vader b/test/linter/test_reason_ols.vader
new file mode 100644
index 00000000..752bd05b
--- /dev/null
+++ b/test/linter/test_reason_ols.vader
@@ -0,0 +1,41 @@
+Before:
+ call ale#assert#SetUpLinterTest('reason', 'ols')
+
+ Save &filetype
+ let &filetype = 'reason'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The language string should be correct):
+ AssertLSPLanguage 'reason'
+
+Execute(The default executable should be correct):
+ AssertLinter 'ocaml-language-server',
+ \ ale#Escape('ocaml-language-server') . ' --stdio'
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/ols/file.re')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/ols')
+
+Execute(The local executable should be used when available):
+ call ale#test#SetFilename('../test-files/ols/file.re')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/ols/node_modules/.bin/ocaml-language-server'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/ols/node_modules/.bin/ocaml-language-server')) . ' --stdio'
+
+Execute(The gloabl executable should always be used when use_global is set):
+ let g:ale_reason_ols_use_global = 1
+ call ale#test#SetFilename('../test-files/ols/file.re')
+
+ AssertLinter 'ocaml-language-server',
+ \ ale#Escape('ocaml-language-server') . ' --stdio'
+
+Execute(The executable should be configurable):
+ let g:ale_reason_ols_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio'
diff --git a/test/linter/test_reek.vader b/test/linter/test_reek.vader
new file mode 100644
index 00000000..798c3314
--- /dev/null
+++ b/test/linter/test_reek.vader
@@ -0,0 +1,49 @@
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'reek')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The reek callbacks should return the correct default values):
+ GivenCommandOutput ['reek 5.0.0']
+ AssertLinter 'reek', [
+ \ ale#Escape('reek') . ' --version',
+ \ ale#Escape('reek') . ' -f json --no-progress --no-color --force-exclusion --stdin-filename %s',
+ \]
+
+ " Try with older versions.
+ call ale#semver#ResetVersionCache()
+
+ GivenCommandOutput ['reek 4.8.2']
+ AssertLinter 'reek', [
+ \ ale#Escape('reek') . ' --version',
+ \ ale#Escape('reek') . ' -f json --no-progress --no-color --force-exclusion',
+ \]
+
+Execute(Setting bundle appends 'exec reek'):
+ let g:ale_ruby_reek_executable = 'bundle'
+
+ GivenCommandOutput ['reek 5.0.0']
+ AssertLinter 'bundle', ale#Escape('bundle')
+ \ . ' exec reek'
+ \ . ' -f json --no-progress --no-color --force-exclusion --stdin-filename %s',
+
+ " Try with older versions.
+ call ale#semver#ResetVersionCache()
+
+ GivenCommandOutput ['reek 4.8.2']
+ AssertLinter 'bundle', ale#Escape('bundle')
+ \ . ' exec reek'
+ \ . ' -f json --no-progress --no-color --force-exclusion'
+
+Execute(The reek version check should be cached):
+ GivenCommandOutput ['reek 5.0.0']
+ AssertLinter 'reek', [
+ \ ale#Escape('reek') . ' --version',
+ \ ale#Escape('reek') . ' -f json --no-progress --no-color --force-exclusion --stdin-filename %s',
+ \]
+
+ GivenCommandOutput []
+ AssertLinter 'reek', [
+ \ ale#Escape('reek') . ' -f json --no-progress --no-color --force-exclusion --stdin-filename %s',
+ \]
diff --git a/test/linter/test_remark_lint.vader b/test/linter/test_remark_lint.vader
new file mode 100644
index 00000000..a34f0a90
--- /dev/null
+++ b/test/linter/test_remark_lint.vader
@@ -0,0 +1,37 @@
+Before:
+ " This is just one language for the linter.
+ call ale#assert#SetUpLinterTest('markdown', 'remark_lint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'remark',
+ \ ale#Escape('remark') . ' --no-stdout --no-color'
+
+Execute(The executable should be configurable):
+ let b:ale_markdown_remark_lint_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' --no-stdout --no-color'
+
+Execute(The options should be configurable):
+ let b:ale_markdown_remark_lint_options = '--something'
+
+ AssertLinter 'remark',
+ \ ale#Escape('remark') . ' --something --no-stdout --no-color'
+
+Execute(The local executable from .bin should be used if available):
+ call ale#test#SetFilename('../test-files/remark_lint/with_bin_path/foo.md')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/remark_lint/with_bin_path/node_modules/.bin/remark'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/remark_lint/with_bin_path/node_modules/.bin/remark'))
+ \ . ' --no-stdout --no-color'
+
+Execute(The global executable should be uesd if the option is set):
+ let b:ale_markdown_remark_lint_use_global = 1
+ call ale#test#SetFilename('../test-files/remark_lint/with_bin_path/foo.md')
+
+ AssertLinter 'remark', ale#Escape('remark')
+ \ . ' --no-stdout --no-color'
diff --git a/test/linter/test_revive.vader b/test/linter/test_revive.vader
new file mode 100644
index 00000000..172294f3
--- /dev/null
+++ b/test/linter/test_revive.vader
@@ -0,0 +1,30 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'revive')
+
+After:
+ Restore
+
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default revive command should be correct):
+ AssertLinter 'revive', ale#Escape('revive') . ' %t'
+
+Execute(The revive executable should be configurable):
+ let b:ale_go_revive_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' %t'
+
+Execute(The revive options should be configurable):
+ let b:ale_go_revive_options = '--foo'
+
+ AssertLinter 'revive', ale#Escape('revive') . ' --foo %t'
+
+Execute(The revive command should support Go environment variables):
+ let b:ale_go_go111module = 'on'
+
+ AssertLinter 'revive',
+ \ ale#Env('GO111MODULE', 'on') . ale#Escape('revive') . ' %t'
diff --git a/test/linter/test_rnix.vader b/test/linter/test_rnix.vader
new file mode 100644
index 00000000..8970ee99
--- /dev/null
+++ b/test/linter/test_rnix.vader
@@ -0,0 +1,12 @@
+" Author: jD91mZM2 <me@krake.one>
+" Description: Tests for rnix-lsp language client
+Before:
+ call ale#assert#SetUpLinterTest('nix', 'rnix_lsp')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(should start rnix-lsp):
+ AssertLSPLanguage 'nix'
+ AssertLSPOptions {}
+ AssertLSPProject ale#path#Simplify('.')
diff --git a/test/linter/test_rst_textlint.vader b/test/linter/test_rst_textlint.vader
new file mode 100644
index 00000000..b2d99636
--- /dev/null
+++ b/test/linter/test_rst_textlint.vader
@@ -0,0 +1,65 @@
+" Author: januswel, w0rp
+
+Before:
+ " This is just one language for the linter.
+ call ale#assert#SetUpLinterTest('rst', 'textlint')
+
+ " The configuration is shared between many languages.
+ Save g:ale_textlint_executable
+ Save g:ale_textlint_use_global
+ Save g:ale_textlint_options
+
+ let g:ale_textlint_executable = 'textlint'
+ let g:ale_textlint_use_global = 0
+ let g:ale_textlint_options = ''
+
+ unlet! b:ale_textlint_executable
+ unlet! b:ale_textlint_use_global
+ unlet! b:ale_textlint_options
+
+After:
+ unlet! b:command_tail
+ unlet! b:ale_textlint_executable
+ unlet! b:ale_textlint_use_global
+ unlet! b:ale_textlint_options
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'textlint',
+ \ ale#Escape('textlint') . ' -f json --stdin --stdin-filename %s'
+
+Execute(The executable should be configurable):
+ let b:ale_textlint_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -f json --stdin --stdin-filename %s'
+
+Execute(The options should be configurable):
+ let b:ale_textlint_options = '--something'
+
+ AssertLinter 'textlint',
+ \ ale#Escape('textlint') . ' --something -f json --stdin --stdin-filename %s'
+
+Execute(The local executable from .bin should be used if available):
+ call ale#test#SetFilename('../test-files/textlint/with_bin_path/foo.txt')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_bin_path/node_modules/.bin/textlint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_bin_path/node_modules/.bin/textlint'))
+ \ . ' -f json --stdin --stdin-filename %s'
+
+Execute(The local executable from textlint/bin should be used if available):
+ call ale#test#SetFilename('../test-files/textlint/with_textlint_bin_path/foo.txt')
+
+ if has('win32')
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'),
+ \ ale#Escape('node.exe') . ' ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'))
+ \ . ' -f json --stdin --stdin-filename %s'
+ else
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'))
+ \ . ' -f json --stdin --stdin-filename %s'
+ endif
diff --git a/test/linter/test_rubocop.vader b/test/linter/test_rubocop.vader
new file mode 100644
index 00000000..e7cc32e8
--- /dev/null
+++ b/test/linter/test_rubocop.vader
@@ -0,0 +1,26 @@
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'rubocop')
+ call ale#test#SetFilename('dummy.rb')
+
+ let g:ale_ruby_rubocop_executable = 'rubocop'
+ let g:ale_ruby_rubocop_options = ''
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to rubocop):
+ AssertLinter 'rubocop', ale#Escape('rubocop')
+ \ . ' --format json --force-exclusion --stdin %s'
+
+Execute(Should be able to set a custom executable):
+ let g:ale_ruby_rubocop_executable = 'bin/rubocop'
+
+ AssertLinter 'bin/rubocop' , ale#Escape('bin/rubocop')
+ \ . ' --format json --force-exclusion --stdin %s'
+
+Execute(Setting bundle appends 'exec rubocop'):
+ let g:ale_ruby_rubocop_executable = 'path to/bundle'
+
+ AssertLinter 'path to/bundle', ale#Escape('path to/bundle')
+ \ . ' exec rubocop'
+ \ . ' --format json --force-exclusion --stdin %s'
diff --git a/test/linter/test_ruby.vader b/test/linter/test_ruby.vader
new file mode 100644
index 00000000..b6bac14f
--- /dev/null
+++ b/test/linter/test_ruby.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'ruby')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'ruby', ale#Escape('ruby') . ' -w -c -T1 %t'
+
+Execute(The executable should be configurable):
+ let g:ale_ruby_ruby_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' -w -c -T1 %t'
diff --git a/test/linter/test_ruby_debride.vader b/test/linter/test_ruby_debride.vader
new file mode 100644
index 00000000..f7628432
--- /dev/null
+++ b/test/linter/test_ruby_debride.vader
@@ -0,0 +1,8 @@
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'debride')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'debride', ale#Escape('debride') . ' %s'
diff --git a/test/linter/test_ruby_solargraph.vader b/test/linter/test_ruby_solargraph.vader
new file mode 100644
index 00000000..1ae67f50
--- /dev/null
+++ b/test/linter/test_ruby_solargraph.vader
@@ -0,0 +1,43 @@
+" Author: Horacio Sanson <https://github.com/hsanson>
+" Description: Tests for solargraph lsp linter.
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'solargraph')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(command callback should return default string):
+ AssertLinter 'solargraph', ale#Escape('solargraph') . ' stdio'
+
+Execute(command callback executable can be overridden):
+ let g:ale_ruby_solargraph_executable = 'foobar'
+ AssertLinter 'foobar', ale#Escape('foobar') . ' stdio'
+
+Execute(should set solargraph for rails app):
+ call ale#test#SetFilename('../test-files/ruby/valid_rails_app/app/models/thing.rb')
+ AssertLSPLanguage 'ruby'
+ AssertLSPOptions {}
+ AssertLSPProject ale#test#GetFilename('../test-files/ruby/valid_rails_app')
+
+Execute(should set solargraph for ruby app1):
+ call ale#test#SetFilename('../test-files/ruby/valid_ruby_app1/lib/file.rb')
+ AssertLSPLanguage 'ruby'
+ AssertLSPOptions {}
+ AssertLSPProject ale#test#GetFilename('../test-files/ruby/valid_ruby_app1')
+
+Execute(should set solargraph for ruby app2):
+ call ale#test#SetFilename('../test-files/ruby/valid_ruby_app2/lib/file.rb')
+ AssertLSPLanguage 'ruby'
+ AssertLSPOptions {}
+ AssertLSPProject ale#test#GetFilename('../test-files/ruby/valid_ruby_app2')
+
+Execute(should set solargraph for ruby app3):
+ call ale#test#SetFilename('../test-files/ruby/valid_ruby_app3/lib/file.rb')
+ AssertLSPLanguage 'ruby'
+ AssertLSPOptions {}
+ AssertLSPProject ale#test#GetFilename('../test-files/ruby/valid_ruby_app3')
+
+Execute(should accept initialization options):
+ AssertLSPOptions {}
+ let b:ale_ruby_solargraph_options = { 'diagnostics': 'true' }
+ AssertLSPOptions { 'diagnostics': 'true' }
diff --git a/test/linter/test_rust_analyzer.vader b/test/linter/test_rust_analyzer.vader
new file mode 100644
index 00000000..82a3adfb
--- /dev/null
+++ b/test/linter/test_rust_analyzer.vader
@@ -0,0 +1,20 @@
+Before:
+ call ale#assert#SetUpLinterTest('rust', 'analyzer')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'rust-analyzer', ale#Escape('rust-analyzer')
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/rust/test.rs')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/rust')
+
+Execute(Should accept configuration settings):
+ AssertLSPConfig {}
+ let b:ale_rust_analyzer_config = {'diagnostics': {'disabled': ['unresolved-import']}}
+ AssertLSPOptions {'diagnostics': {'disabled': ['unresolved-import']}}
diff --git a/test/linter/test_rust_rls.vader b/test/linter/test_rust_rls.vader
new file mode 100644
index 00000000..9ca25619
--- /dev/null
+++ b/test/linter/test_rust_rls.vader
@@ -0,0 +1,30 @@
+Before:
+ call ale#assert#SetUpLinterTest('rust', 'rls')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'rls', ale#Escape('rls')
+
+Execute(The toolchain should be configurable):
+ let g:ale_rust_rls_toolchain = 'stable'
+
+ AssertLinter 'rls', ale#Escape('rls') . ' +' . ale#Escape('stable')
+
+Execute(The toolchain should be ommitted if not given):
+ let g:ale_rust_rls_toolchain = ''
+
+ AssertLinter 'rls', ale#Escape('rls')
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/rust/test.rs')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/rust')
+
+Execute(Should accept configuration settings):
+ AssertLSPConfig {}
+ let b:ale_rust_rls_config = {'rust': {'clippy_preference': 'on'}}
+ AssertLSPConfig {'rust': {'clippy_preference': 'on'}}
diff --git a/test/linter/test_rustc.vader b/test/linter/test_rustc.vader
new file mode 100644
index 00000000..4bceb180
--- /dev/null
+++ b/test/linter/test_rustc.vader
@@ -0,0 +1,21 @@
+Before:
+ call ale#assert#SetUpLinterTest('rust', 'rustc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'rustc', 'rustc --error-format=json -Z no-codegen -'
+
+Execute(The options should be configurable):
+ let b:ale_rust_rustc_options = '--foo'
+
+ AssertLinter 'rustc', 'rustc --error-format=json --foo -'
+
+Execute(Some default paths should be included when the project is a Cargo project):
+ call ale#test#SetFilename('../test-files/cargo/test.rs')
+
+ AssertLinter 'rustc', 'rustc --error-format=json -Z no-codegen'
+ \ . ' -L ' . ale#Escape(ale#path#GetAbsPath(g:dir, '../test-files/cargo/target/debug/deps'))
+ \ . ' -L ' . ale#Escape(ale#path#GetAbsPath(g:dir, '../test-files/cargo/target/release/deps'))
+ \ . ' -'
diff --git a/test/linter/test_ruumba.vader b/test/linter/test_ruumba.vader
new file mode 100644
index 00000000..9fa48903
--- /dev/null
+++ b/test/linter/test_ruumba.vader
@@ -0,0 +1,26 @@
+Before:
+ call ale#assert#SetUpLinterTest('eruby', 'ruumba')
+ call ale#test#SetFilename('dummy.html.erb')
+
+ let g:ale_eruby_ruumba_executable = 'ruumba'
+ let g:ale_eruby_ruumba_options = ''
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to ruumba):
+ AssertLinter 'ruumba', ale#Escape('ruumba')
+ \ . ' --format json --force-exclusion --stdin %s'
+
+Execute(Should be able to set a custom executable):
+ let g:ale_eruby_ruumba_executable = 'bin/ruumba'
+
+ AssertLinter 'bin/ruumba' , ale#Escape('bin/ruumba')
+ \ . ' --format json --force-exclusion --stdin %s'
+
+Execute(Setting bundle appends 'exec ruumba'):
+ let g:ale_eruby_ruumba_executable = 'path to/bundle'
+
+ AssertLinter 'path to/bundle', ale#Escape('path to/bundle')
+ \ . ' exec ruumba'
+ \ . ' --format json --force-exclusion --stdin %s'
diff --git a/test/linter/test_sass_sasslint.vader b/test/linter/test_sass_sasslint.vader
new file mode 100644
index 00000000..87f0c8ad
--- /dev/null
+++ b/test/linter/test_sass_sasslint.vader
@@ -0,0 +1,43 @@
+Before:
+ call ale#assert#SetUpLinterTest('sass', 'sasslint')
+ call ale#test#SetFilename('test.sass')
+ unlet! b:executable
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(should default to source, bin/sass-lint.js):
+ call ale#test#SetFilename('../test-files/sasslint/with-source/test.sass')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/sasslint/with-source/node_modules/sass-lint/bin/sass-lint.js'
+ \)
+
+ AssertLinter b:executable,
+ \ (has('win32') ? 'node.exe ' : '')
+ \ . ale#Escape(b:executable)
+ \ . ' -v -q -f compact %t'
+
+Execute(should fallback to bin, .bin/sass-lint):
+ call ale#test#SetFilename('../test-files/sasslint/with-bin/test.sass')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/sasslint/with-bin/node_modules/.bin/sass-lint'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' -v -q -f compact %t'
+
+Execute(should fallback to global bin):
+ AssertLinter 'sass-lint', ale#Escape('sass-lint') . ' -v -q -f compact %t'
+
+Execute(The global executable should be configurable):
+ let b:ale_sass_sasslint_executable = 'foo'
+
+ AssertLinter 'foo', ale#Escape('foo') . ' -v -q -f compact %t'
+
+Execute(The options should be configurable):
+ let b:ale_sass_sasslint_options = '--bar'
+
+ AssertLinter 'sass-lint', ale#Escape('sass-lint') . ' --bar -v -q -f compact %t'
diff --git a/test/linter/test_scala_metals.vader b/test/linter/test_scala_metals.vader
new file mode 100644
index 00000000..b14e3e02
--- /dev/null
+++ b/test/linter/test_scala_metals.vader
@@ -0,0 +1,21 @@
+" Author: Jeffrey Lau https://github.com/zoonfafer
+" Description: Tests for the Scala Metals linter
+Before:
+ call ale#assert#SetUpLinterTest('scala', 'metals')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set metals for sbt project with build.sbt):
+ call ale#test#SetFilename('../test-files/scala/valid_sbt_project/Main.scala')
+ AssertLSPLanguage 'scala'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ale#test#GetFilename('../test-files/scala/valid_sbt_project')
+
+Execute(should not set metals for sbt project without build.sbt):
+ call ale#test#SetFilename('../test-files/scala/invalid_sbt_project/Main.scala')
+ AssertLSPLanguage 'scala'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ''
diff --git a/test/linter/test_scala_sbtserver.vader b/test/linter/test_scala_sbtserver.vader
new file mode 100644
index 00000000..118e090f
--- /dev/null
+++ b/test/linter/test_scala_sbtserver.vader
@@ -0,0 +1,23 @@
+" Author: ophirr33 <coghlan.ty@gmail.com>
+" Description: Tests for the sbt Server lsp linter
+Before:
+ call ale#assert#SetUpLinterTest('scala', 'sbtserver')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set sbtserver for sbt project with build.sbt):
+ call ale#test#SetFilename('../test-files/scala/valid_sbt_project/Main.scala')
+ AssertLSPLanguage 'scala'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ale#test#GetFilename('../test-files/scala/valid_sbt_project')
+ AssertLSPAddress '127.0.0.1:4273'
+
+Execute(should not set sbtserver for sbt project without build.sbt):
+ call ale#test#SetFilename('../test-files/scala/invalid_sbt_project/Main.scala')
+ AssertLSPLanguage 'scala'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ''
+ AssertLSPAddress '127.0.0.1:4273'
diff --git a/test/linter/test_scalac.vader b/test/linter/test_scalac.vader
new file mode 100644
index 00000000..ea5ae109
--- /dev/null
+++ b/test/linter/test_scalac.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('scala', 'scalac')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Given scala(An empty Scala file):
+Execute(The default executable and command should be correct):
+ AssertLinter 'scalac', ale#Escape('scalac') . ' -Ystop-after:parser %t'
+
+Given scala.sbt(An empty SBT file):
+Execute(scalac should not be run for sbt files):
+ AssertLinterNotExecuted
diff --git a/test/linter/test_scalastyle.vader b/test/linter/test_scalastyle.vader
new file mode 100644
index 00000000..3c28f7a3
--- /dev/null
+++ b/test/linter/test_scalastyle.vader
@@ -0,0 +1,34 @@
+Before:
+ call ale#assert#SetUpLinterTest('scala', 'scalastyle')
+
+After:
+ unlet! g:ale_scalastyle_config_loc
+ call ale#linter#Reset()
+
+Execute(Should return the correct default command):
+ AssertLinter 'scalastyle', 'scalastyle %t'
+
+Execute(Should allow using a custom config file):
+ let b:ale_scala_scalastyle_config = '/dooper/config.xml'
+
+ AssertLinter 'scalastyle', 'scalastyle'
+ \ . ' --config ' . ale#Escape('/dooper/config.xml')
+ \ . ' %t'
+
+Execute(Should support a legacy option for the scalastyle config):
+ unlet! g:ale_scala_scalastyle_config
+ let g:ale_scalastyle_config_loc = '/dooper/config.xml'
+
+ call ale#linter#Reset()
+ runtime ale_linters/scala/scalastyle.vim
+
+ AssertLinter 'scalastyle', 'scalastyle'
+ \ . ' --config ' . ale#Escape('/dooper/config.xml')
+ \ . ' %t'
+
+Execute(Should allow using custom options):
+ let b:ale_scala_scalastyle_options = '--warnings false --quiet true'
+
+ AssertLinter 'scalastyle', 'scalastyle'
+ \ . ' --warnings false --quiet true'
+ \ . ' %t'
diff --git a/test/linter/test_scss_sasslint.vader b/test/linter/test_scss_sasslint.vader
new file mode 100644
index 00000000..839761c2
--- /dev/null
+++ b/test/linter/test_scss_sasslint.vader
@@ -0,0 +1,43 @@
+Before:
+ call ale#assert#SetUpLinterTest('scss', 'sasslint')
+ call ale#test#SetFilename('test.scss')
+ unlet! b:executable
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(should default to source, bin/sass-lint.js):
+ call ale#test#SetFilename('../test-files/sasslint/with-source/test.scss')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/sasslint/with-source/node_modules/sass-lint/bin/sass-lint.js'
+ \)
+
+ AssertLinter b:executable,
+ \ (has('win32') ? 'node.exe ' : '')
+ \ . ale#Escape(b:executable)
+ \ . ' -v -q -f compact %t'
+
+Execute(should fallback to bin, .bin/sass-lint):
+ call ale#test#SetFilename('../test-files/sasslint/with-bin/test.scss')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/sasslint/with-bin/node_modules/.bin/sass-lint'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' -v -q -f compact %t'
+
+Execute(should fallback to global bin):
+ AssertLinter 'sass-lint', ale#Escape('sass-lint') . ' -v -q -f compact %t'
+
+Execute(The global executable should be configurable):
+ let b:ale_scss_sasslint_executable = 'foo'
+
+ AssertLinter 'foo', ale#Escape('foo') . ' -v -q -f compact %t'
+
+Execute(The options should be configurable):
+ let b:ale_scss_sasslint_options = '--bar'
+
+ AssertLinter 'sass-lint', ale#Escape('sass-lint') . ' --bar -v -q -f compact %t'
diff --git a/test/linter/test_scss_stylelint.vader b/test/linter/test_scss_stylelint.vader
new file mode 100644
index 00000000..5a1e71c6
--- /dev/null
+++ b/test/linter/test_scss_stylelint.vader
@@ -0,0 +1,31 @@
+Before:
+ call ale#assert#SetUpLinterTest('scss', 'stylelint')
+ unlet! b:executable
+
+After:
+ unlet! b:executable
+ call ale#assert#TearDownLinterTest()
+
+Execute(node_modules directories should be discovered):
+ call ale#test#SetFilename('../test-files/stylelint/nested/testfile.scss')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/stylelint/node_modules/.bin/stylelint'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin-filename %s'
+
+Execute(The global override should work):
+ let b:ale_scss_stylelint_executable = 'foobar'
+ let b:ale_scss_stylelint_use_global = 1
+
+ call ale#test#SetFilename('../test-files/stylelint/nested/testfile.scss')
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin-filename %s'
+
+Execute(Extra options should be configurable):
+ let b:ale_scss_stylelint_options = '--configFile ''/absolute/path/to/file'''
+
+ AssertLinter 'stylelint',
+ \ ale#Escape('stylelint') . ' --configFile ''/absolute/path/to/file'' --stdin-filename %s'
diff --git a/test/linter/test_shellcheck.vader b/test/linter/test_shellcheck.vader
new file mode 100644
index 00000000..40995755
--- /dev/null
+++ b/test/linter/test_shellcheck.vader
@@ -0,0 +1,106 @@
+Before:
+ call ale#assert#SetUpLinterTest('sh', 'shellcheck')
+ call ale#test#SetFilename('test.sh')
+
+ let b:suffix = ' -f gcc -'
+
+After:
+ unlet! b:is_bash
+ unlet! b:suffix
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default shellcheck command should be correct):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'shellcheck', ale#Escape('shellcheck') . b:suffix
+
+Execute(The option disabling changing directories should work):
+ let g:ale_sh_shellcheck_change_directory = 0
+
+ AssertLinterCwd ''
+ AssertLinter 'shellcheck', ale#Escape('shellcheck') . b:suffix
+
+Execute(The shellcheck command should accept options):
+ let b:ale_sh_shellcheck_options = '--foobar'
+
+ AssertLinter 'shellcheck', ale#Escape('shellcheck') . ' --foobar' . b:suffix
+
+Execute(The shellcheck command should accept options and exclusions):
+ let b:ale_sh_shellcheck_options = '--foobar'
+ let b:ale_sh_shellcheck_exclusions = 'foo,bar'
+
+ AssertLinter 'shellcheck',
+ \ ale#Escape('shellcheck') . ' --foobar -e foo,bar' . b:suffix
+
+Execute(The shellcheck command should include the dialect):
+ let b:is_bash = 1
+
+ AssertLinter 'shellcheck', ale#Escape('shellcheck') . ' -s bash' . b:suffix
+
+Execute(The shellcheck command should use ale_sh_shellcheck_dialect):
+ let b:ale_sh_shellcheck_dialect = 'ksh93'
+
+ AssertLinter 'shellcheck', ale#Escape('shellcheck') . ' -s ksh93' . b:suffix
+
+Execute(The shellcheck command should allow unspecified dialect):
+ let b:ale_sh_shellcheck_dialect = ''
+
+ AssertLinter 'shellcheck', ale#Escape('shellcheck') . b:suffix
+
+Execute(The shellcheck command should include the dialect before options and exclusions):
+ let b:is_bash = 1
+ let b:ale_sh_shellcheck_options = '--foobar'
+ let b:ale_sh_shellcheck_exclusions = 'foo,bar'
+
+ AssertLinter 'shellcheck', ale#Escape('shellcheck')
+ \ . ' -s bash --foobar -e foo,bar'
+ \ . b:suffix
+
+Execute(The -x option should be added when the version is new enough):
+ AssertLinter 'shellcheck', [
+ \ ale#Escape('shellcheck') . ' --version',
+ \ ale#Escape('shellcheck') . b:suffix,
+ \]
+
+ GivenCommandOutput [
+ \ 'ShellCheck - shell script analysis tool',
+ \ 'version: 0.4.4',
+ \ 'license: GNU General Public License, version 3',
+ \ 'website: http://www.shellcheck.net',
+ \]
+ AssertLinter 'shellcheck', [
+ \ ale#Escape('shellcheck') . ' --version',
+ \ ale#Escape('shellcheck') . ' -x' . b:suffix,
+ \]
+
+ " We should cache the version check
+ GivenCommandOutput []
+ AssertLinter 'shellcheck', [
+ \ ale#Escape('shellcheck') . ' -x' . b:suffix,
+ \]
+
+Execute(The -x option should not be added when the version is too old):
+ GivenCommandOutput [
+ \ 'ShellCheck - shell script analysis tool',
+ \ 'version: 0.3.9',
+ \ 'license: GNU General Public License, version 3',
+ \ 'website: http://www.shellcheck.net',
+ \]
+ AssertLinter 'shellcheck', [
+ \ ale#Escape('shellcheck') . ' --version',
+ \ ale#Escape('shellcheck') . b:suffix,
+ \]
+
+Execute(The version check shouldn't be run again for old versions):
+ GivenCommandOutput [
+ \ 'ShellCheck - shell script analysis tool',
+ \ 'version: 0.3.9',
+ \ 'license: GNU General Public License, version 3',
+ \ 'website: http://www.shellcheck.net',
+ \]
+ AssertLinter 'shellcheck', [
+ \ ale#Escape('shellcheck') . ' --version',
+ \ ale#Escape('shellcheck') . b:suffix,
+ \]
+ AssertLinter 'shellcheck', [
+ \ ale#Escape('shellcheck') . b:suffix,
+ \]
diff --git a/test/linter/test_slimlint.vader b/test/linter/test_slimlint.vader
new file mode 100644
index 00000000..33df9ac0
--- /dev/null
+++ b/test/linter/test_slimlint.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('slim', 'slimlint')
+ let g:default_command = 'slim-lint %t'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'slim-lint', 'slim-lint %t'
+
+Execute(The command should have the .rubocop.yml prepended as an env var if one exists):
+ call ale#test#SetFilename('../test-files/slimlint/subdir/file.slim')
+
+ AssertLinter 'slim-lint',
+ \ ale#Env(
+ \ 'SLIM_LINT_RUBOCOP_CONF',
+ \ ale#path#Simplify(g:dir . '/../test-files/slimlint/.rubocop.yml')
+ \ )
+ \ . 'slim-lint %t'
diff --git a/test/linter/test_solc.vader b/test/linter/test_solc.vader
new file mode 100644
index 00000000..23521f6a
--- /dev/null
+++ b/test/linter/test_solc.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('solidity', 'solc')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'solc', 'solc %s'
+
+Execute(The options should be configurable):
+ let g:ale_solidity_solc_options = '--foobar'
+
+ AssertLinter 'solc', 'solc --foobar %s'
diff --git a/test/linter/test_sorbet.vader b/test/linter/test_sorbet.vader
new file mode 100644
index 00000000..fe758635
--- /dev/null
+++ b/test/linter/test_sorbet.vader
@@ -0,0 +1,34 @@
+
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'sorbet')
+ call ale#test#SetFilename('dummy.rb')
+
+ let g:ale_ruby_sorbet_executable = 'srb'
+ let g:ale_ruby_sorbet_options = ''
+ let g:ale_ruby_sorbet_enable_watchman = 0
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to srb):
+ AssertLinter 'srb', ale#Escape('srb')
+ \ . ' tc --lsp --disable-watchman'
+
+Execute(Able to enable watchman):
+ let g:ale_ruby_sorbet_enable_watchman = 1
+
+ AssertLinter 'srb', ale#Escape('srb')
+ \ . ' tc --lsp'
+
+Execute(Should be able to set a custom executable):
+ let g:ale_ruby_sorbet_executable = 'bin/srb'
+
+ AssertLinter 'bin/srb' , ale#Escape('bin/srb')
+ \ . ' tc --lsp --disable-watchman'
+
+Execute(Setting bundle appends 'exec srb tc'):
+ let g:ale_ruby_sorbet_executable = 'path to/bundle'
+
+ AssertLinter 'path to/bundle', ale#Escape('path to/bundle')
+ \ . ' exec srb'
+ \ . ' tc --lsp --disable-watchman'
diff --git a/test/linter/test_spectral.vader b/test/linter/test_spectral.vader
new file mode 100644
index 00000000..cfcf0987
--- /dev/null
+++ b/test/linter/test_spectral.vader
@@ -0,0 +1,31 @@
+Before:
+ call ale#assert#SetUpLinterTest('yaml', 'spectral')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The yaml spectral command callback should return the correct default string):
+ AssertLinter 'spectral', ale#Escape('spectral') . ' lint --ignore-unknown-format -q -f text %t'
+
+Execute(The yaml spectral command callback should be configurable):
+ let g:ale_yaml_spectral_executable = '~/.local/bin/spectral'
+
+ AssertLinter '~/.local/bin/spectral',
+ \ ale#Escape('~/.local/bin/spectral')
+ \ . ' lint --ignore-unknown-format -q -f text %t'
+
+Execute(The yaml spectral command callback should allow a global installation to be used):
+ let g:ale_yaml_spectral_executable = '/usr/local/bin/spectral'
+ let g:ale_yaml_spectral_use_global = 1
+
+ AssertLinter '/usr/local/bin/spectral',
+ \ ale#Escape('/usr/local/bin/spectral')
+ \ . ' lint --ignore-unknown-format -q -f text %t'
+
+Execute(The yaml spectral command callback should allow a local installation to be used):
+ call ale#test#SetFilename('../test-files/spectral/openapi.yaml')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/spectral/node_modules/.bin/spectral'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/spectral/node_modules/.bin/spectral'))
+ \ . ' lint --ignore-unknown-format -q -f text %t'
diff --git a/test/linter/test_sqllint.vader b/test/linter/test_sqllint.vader
new file mode 100644
index 00000000..eea9b4e0
--- /dev/null
+++ b/test/linter/test_sqllint.vader
@@ -0,0 +1,12 @@
+Before:
+ " Load the linter and set up a series of commands, reset linter variables,
+ " clear caches, etc.
+ "
+ " Vader's 'Save' command will be called here for linter variables.
+ call ale#assert#SetUpLinterTest('sql', 'sqllint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'sql-lint', ['sql-lint']
diff --git a/test/linter/test_standard.vader b/test/linter/test_standard.vader
new file mode 100644
index 00000000..4722cd4a
--- /dev/null
+++ b/test/linter/test_standard.vader
@@ -0,0 +1,43 @@
+Before:
+ call ale#assert#SetUpLinterTest('javascript', 'standard')
+ call ale#test#SetFilename('testfile.js')
+ unlet! b:executable
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(bin/cmd.js paths should be preferred):
+ call ale#test#SetFilename('../test-files/standard/with-cmd/testfile.js')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/standard/with-cmd/node_modules/standard/bin/cmd.js'
+ \)
+
+ AssertLinter b:executable,
+ \ (has('win32') ? 'node.exe ' : '')
+ \ . ale#Escape(b:executable)
+ \ . ' --stdin %s'
+
+Execute(.bin directories should be used too):
+ call ale#test#SetFilename('../test-files/standard/with-bin/testfile.js')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/standard/with-bin/node_modules/.bin/standard'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin %s'
+
+Execute(The global executable should be used otherwise):
+ AssertLinter 'standard', ale#Escape('standard') . ' --stdin %s'
+
+Execute(The global executable should be configurable):
+ let b:ale_javascript_standard_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin %s'
+
+Execute(The options should be configurable):
+ let b:ale_javascript_standard_options = '--wat'
+
+ AssertLinter 'standard', ale#Escape('standard') . ' --wat --stdin %s'
diff --git a/test/linter/test_standardrb.vader b/test/linter/test_standardrb.vader
new file mode 100644
index 00000000..108dd870
--- /dev/null
+++ b/test/linter/test_standardrb.vader
@@ -0,0 +1,26 @@
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'standardrb')
+ call ale#test#SetFilename('dummy.rb')
+
+ let g:ale_ruby_standardrb_executable = 'standardrb'
+ let g:ale_ruby_standardrb_options = ''
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to standardrb):
+ AssertLinter 'standardrb', ale#Escape('standardrb')
+ \ . ' --format json --force-exclusion --stdin %s'
+
+Execute(Should be able to set a custom executable):
+ let g:ale_ruby_standardrb_executable = 'bin/standardrb'
+
+ AssertLinter 'bin/standardrb' , ale#Escape('bin/standardrb')
+ \ . ' --format json --force-exclusion --stdin %s'
+
+Execute(Setting bundle appends 'exec standardrb'):
+ let g:ale_ruby_standardrb_executable = 'path to/bundle'
+
+ AssertLinter 'path to/bundle', ale#Escape('path to/bundle')
+ \ . ' exec standardrb'
+ \ . ' --format json --force-exclusion --stdin %s'
diff --git a/test/linter/test_standardts.vader b/test/linter/test_standardts.vader
new file mode 100644
index 00000000..33ca8b25
--- /dev/null
+++ b/test/linter/test_standardts.vader
@@ -0,0 +1,43 @@
+Before:
+ call ale#assert#SetUpLinterTest('typescript', 'standard')
+ call ale#test#SetFilename('testfile.js')
+ unlet! b:executable
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(bin/cmd.js paths should be preferred):
+ call ale#test#SetFilename('../test-files/standard/with-cmd/testfile.js')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/standard/with-cmd/node_modules/standard/bin/cmd.js'
+ \)
+
+ AssertLinter b:executable,
+ \ (has('win32') ? 'node.exe ' : '')
+ \ . ale#Escape(b:executable)
+ \ . ' --stdin %s'
+
+Execute(.bin directories should be used too):
+ call ale#test#SetFilename('../test-files/standard/with-bin/testfile.js')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/standard/with-bin/node_modules/.bin/standard'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin %s'
+
+Execute(The global executable should be used otherwise):
+ AssertLinter 'standard', ale#Escape('standard') . ' --stdin %s'
+
+Execute(The global executable should be configurable):
+ let b:ale_typescript_standard_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin %s'
+
+Execute(The options should be configurable):
+ let b:ale_typescript_standard_options = '--wat'
+
+ AssertLinter 'standard', ale#Escape('standard') . ' --wat --stdin %s'
diff --git a/test/linter/test_staticcheck.vader b/test/linter/test_staticcheck.vader
new file mode 100644
index 00000000..993d9491
--- /dev/null
+++ b/test/linter/test_staticcheck.vader
@@ -0,0 +1,35 @@
+Before:
+ Save g:ale_go_go111module
+
+ call ale#assert#SetUpLinterTest('go', 'staticcheck')
+ call ale#test#SetFilename('test.go')
+
+After:
+ unlet! b:ale_go_go111module
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The staticcheck callback should return the right defaults):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'staticcheck', 'staticcheck %s:t'
+
+Execute(The staticcheck callback should use configured options):
+ let b:ale_go_staticcheck_options = '-test'
+
+ AssertLinter 'staticcheck', 'staticcheck -test %s:t'
+
+Execute(The staticcheck `lint_package` option should use the correct command):
+ let b:ale_go_staticcheck_lint_package = 1
+
+ AssertLinterCwd '%s:h'
+ AssertLinter 'staticcheck', 'staticcheck .'
+
+Execute(The staticcheck callback should use the `GO111MODULE` option if set):
+ let b:ale_go_go111module = 'off'
+
+ AssertLinter 'staticcheck', ale#Env('GO111MODULE', 'off') . 'staticcheck %s:t'
+
+ " Test with lint_package option set
+ let b:ale_go_staticcheck_lint_package = 1
+
+ AssertLinter 'staticcheck', ale#Env('GO111MODULE', 'off') . 'staticcheck .'
diff --git a/test/linter/test_sugarss_stylelint.vader b/test/linter/test_sugarss_stylelint.vader
new file mode 100644
index 00000000..ba42eaf8
--- /dev/null
+++ b/test/linter/test_sugarss_stylelint.vader
@@ -0,0 +1,31 @@
+Before:
+ call ale#assert#SetUpLinterTest('sugarss', 'stylelint')
+ unlet! b:executable
+
+After:
+ unlet! b:executable
+ call ale#assert#TearDownLinterTest()
+
+Execute(node_modules directories should be discovered):
+ call ale#test#SetFilename('../test-files/stylelint/nested/testfile.sss')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/../test-files/stylelint/node_modules/.bin/stylelint'
+ \)
+
+ AssertLinter b:executable, ale#Escape(b:executable) . ' --syntax=sugarss --stdin-filename %s'
+
+Execute(The global override should work):
+ let b:ale_sugarss_stylelint_executable = 'foobar'
+ let b:ale_sugarss_stylelint_use_global = 1
+
+ call ale#test#SetFilename('../test-files/stylelint/nested/testfile.sss')
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --syntax=sugarss --stdin-filename %s'
+
+Execute(Extra options should be configurable):
+ let b:ale_sugarss_stylelint_options = '--configFile ''/absolute/path/to/file'''
+
+ AssertLinter 'stylelint',
+ \ ale#Escape('stylelint') . ' --configFile ''/absolute/path/to/file'' --syntax=sugarss --stdin-filename %s'
diff --git a/test/linter/test_svelteserver.vader b/test/linter/test_svelteserver.vader
new file mode 100644
index 00000000..c09f1682
--- /dev/null
+++ b/test/linter/test_svelteserver.vader
@@ -0,0 +1,8 @@
+Before:
+ call ale#assert#SetUpLinterTest('svelte', 'svelteserver')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'svelteserver', ale#Escape('svelteserver') . ' --stdio'
diff --git a/test/linter/test_swaglint.vader b/test/linter/test_swaglint.vader
new file mode 100644
index 00000000..98f0c594
--- /dev/null
+++ b/test/linter/test_swaglint.vader
@@ -0,0 +1,29 @@
+Before:
+ call ale#assert#SetUpLinterTest('yaml', 'swaglint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The yaml swaglint command callback should return the correct default string):
+ AssertLinter 'swaglint', ale#Escape('swaglint') . ' -r compact --stdin'
+
+Execute(The yaml swaglint command callback should be configurable):
+ let g:ale_yaml_swaglint_executable = '~/.local/bin/swaglint'
+
+ AssertLinter '~/.local/bin/swaglint',
+ \ ale#Escape('~/.local/bin/swaglint') . ' -r compact --stdin'
+
+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
+
+ AssertLinter '/usr/local/bin/swaglint',
+ \ ale#Escape('/usr/local/bin/swaglint') . ' -r compact --stdin'
+
+Execute(The yaml swaglint command callback should allow a local installation to be used):
+ call ale#test#SetFilename('../test-files/swaglint/docs/swagger.yaml')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/swaglint/node_modules/.bin/swaglint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/swaglint/node_modules/.bin/swaglint'))
+ \ . ' -r compact --stdin'
diff --git a/test/linter/test_swift_sourcekitlsp.vader b/test/linter/test_swift_sourcekitlsp.vader
new file mode 100644
index 00000000..1040d590
--- /dev/null
+++ b/test/linter/test_swift_sourcekitlsp.vader
@@ -0,0 +1,21 @@
+Before:
+ call ale#assert#SetUpLinterTest('swift', 'sourcekitlsp')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ call ale#test#SetFilename('../test-files/swift/swift-package-project/src/folder/dummy.swift')
+
+ AssertLinter 'sourcekit-lsp', ale#Escape('sourcekit-lsp')
+
+Execute(Should let users configure a global executable and override local paths):
+ call ale#test#SetFilename('../test-files/swift/swift-package-project/src/folder/dummy.swift')
+
+ let g:ale_sourcekit_lsp_executable = '/path/to/custom/sourcekitlsp'
+
+ AssertLinter '/path/to/custom/sourcekitlsp',
+ \ ale#Escape('/path/to/custom/sourcekitlsp')
+
+Execute(The language should be correct):
+ AssertLSPLanguage 'swift'
diff --git a/test/linter/test_swift_swiftformat.vader b/test/linter/test_swift_swiftformat.vader
new file mode 100644
index 00000000..9f6ee62e
--- /dev/null
+++ b/test/linter/test_swift_swiftformat.vader
@@ -0,0 +1,25 @@
+Before:
+ call ale#assert#SetUpLinterTest('swift', 'swiftformat')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Should use default command when not in a swift package):
+ call ale#test#SetFilename('../test-files/swift/non-swift-package-project/src/folder/dummy.swift')
+
+ AssertLinter 'swift-format',
+ \ ale#Escape('swift-format') . ' --mode lint %t'
+
+Execute(Should use swift run when in a swift package):
+ call ale#test#SetFilename('../test-files/swift/swift-package-project/src/folder/dummy.swift')
+
+ AssertLinter 'swift',
+ \ ale#Escape('swift') . ' run swift-format --mode lint %t'
+
+Execute(Should let users configure a global executable and override local paths):
+ call ale#test#SetFilename('../test-files/swift/swift-package-project/src/folder/dummy.swift')
+
+ let g:ale_swift_swiftformat_executable = '/path/to/custom/swift-format'
+
+ AssertLinter '/path/to/custom/swift-format',
+ \ ale#Escape('/path/to/custom/swift-format') . ' --mode lint %t'
diff --git a/test/linter/test_swiftlint.vader b/test/linter/test_swiftlint.vader
new file mode 100644
index 00000000..d2442b0a
--- /dev/null
+++ b/test/linter/test_swiftlint.vader
@@ -0,0 +1,43 @@
+Before:
+ call ale#assert#SetUpLinterTest('swift', 'swiftlint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Global installation should be the default executable):
+ call ale#test#SetFilename('../test-files/swiftlint/global/testfile.swift')
+
+ AssertEqual
+ \ 'swiftlint',
+ \ ale_linters#swift#swiftlint#GetExecutable(bufnr(''))
+
+Execute(React Native apps using CocoaPods should take precedence over the default executable):
+ call ale#test#SetFilename('../test-files/swiftlint/react-native/testfile.swift')
+
+ AssertEqual
+ \ tolower(ale#test#GetFilename('../test-files/swiftlint/react-native/ios/Pods/SwiftLint/swiftlint')),
+ \ tolower(ale_linters#swift#swiftlint#GetExecutable(bufnr('')))
+
+Execute(CocoaPods installation should take precedence over the default executable):
+ call ale#test#SetFilename('../test-files/swiftlint/cocoapods/testfile.swift')
+
+ AssertEqual
+ \ tolower(ale#test#GetFilename('../test-files/swiftlint/cocoapods/Pods/SwiftLint/swiftlint')),
+ \ tolower(ale_linters#swift#swiftlint#GetExecutable(bufnr('')))
+
+Execute(Top level CocoaPods installation should take precedence over React Native installation):
+ call ale#test#SetFilename('../test-files/swiftlint/cocoapods-and-react-native/testfile.swift')
+
+ AssertEqual
+ \ tolower(ale#test#GetFilename('../test-files/swiftlint/cocoapods-and-react-native/Pods/SwiftLint/swiftlint')),
+ \ tolower(ale_linters#swift#swiftlint#GetExecutable(bufnr('')))
+
+Execute(use-global should override other versions):
+ let g:ale_swift_swiftlint_use_global = 1
+ let g:ale_swift_swiftlint_executable = 'swiftlint_d'
+
+ call ale#test#SetFilename('../test-files/swiftlint/cocoapods-and-react-native/testfile.swift')
+
+ AssertEqual
+ \ 'swiftlint_d',
+ \ ale_linters#swift#swiftlint#GetExecutable(bufnr(''))
diff --git a/test/linter/test_systemd_analyze.vader b/test/linter/test_systemd_analyze.vader
new file mode 100644
index 00000000..d97c87be
--- /dev/null
+++ b/test/linter/test_systemd_analyze.vader
@@ -0,0 +1,9 @@
+Before:
+ call ale#assert#SetUpLinterTest('systemd', 'systemd_analyze')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'systemd-analyze',
+ \ 'SYSTEMD_LOG_COLOR=0 ' . ale#Escape('systemd-analyze') . ' --user verify %s'
diff --git a/test/linter/test_terraform_ls.vader b/test/linter/test_terraform_ls.vader
new file mode 100644
index 00000000..9f7d3450
--- /dev/null
+++ b/test/linter/test_terraform_ls.vader
@@ -0,0 +1,61 @@
+Before:
+ call ale#assert#SetUpLinterTest('terraform', 'terraform_ls')
+
+After:
+ if isdirectory(g:dir . '/.terraform')
+ call delete(g:dir . '/.terraform', 'd')
+ endif
+
+ unlet! b:ale_terraform_terraform_executable
+ unlet! b:ale_terraform_ls_executable
+ unlet! b:ale_terraform_ls_options
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(Should send correct LSP language):
+ AssertLSPLanguage 'terraform'
+
+Execute(Should load default executable):
+ AssertLinter 'terraform-ls',
+ \ ale#Escape('terraform-ls') . ' serve'
+
+Execute(Should configure custom executable):
+ let b:ale_terraform_ls_executable = 'foo'
+ AssertLinter 'foo',
+ \ ale#Escape('foo') . ' serve'
+
+Execute(Should ignore non-absolute custom terraform executable):
+ let b:ale_terraform_terraform_executable = 'terraform'
+ AssertLinter 'terraform-ls',
+ \ ale#Escape('terraform-ls') . ' serve'
+
+Execute(Should set absolute custom terraform executable):
+ let b:ale_terraform_terraform_executable = '/bin/terraform'
+ AssertLinter 'terraform-ls',
+ \ ale#Escape('terraform-ls') . ' serve -tf-exec /bin/terraform'
+
+Execute(Should set custom options):
+ let b:ale_terraform_ls_options = '--bar'
+
+ AssertLinter 'terraform-ls',
+ \ ale#Escape('terraform-ls') . ' serve --bar'
+
+Execute(Should return current directory if it contains .terraform directory):
+ call mkdir(g:dir . '/.terraform')
+ AssertLSPProject g:dir
+
+Execute(Should return nearest directory with .terraform if found in parent directory):
+ call ale#test#SetFilename('../test-files/terraform/main.tf')
+
+ let b:parent_dir = ale#path#Simplify(g:dir . '/..')
+ let b:tf_dir = b:parent_dir . '/.terraform'
+
+ if !isdirectory(b:tf_dir)
+ call mkdir(b:tf_dir)
+ endif
+
+ AssertLSPProject b:parent_dir
+
+ call delete(b:tf_dir, 'd')
+ unlet!b:parent_dir
+ unlet!b:tf_dir
diff --git a/test/linter/test_terraform_lsp.vader b/test/linter/test_terraform_lsp.vader
new file mode 100644
index 00000000..a292fca0
--- /dev/null
+++ b/test/linter/test_terraform_lsp.vader
@@ -0,0 +1,48 @@
+Before:
+ call ale#assert#SetUpLinterTest('terraform', 'terraform_lsp')
+
+After:
+ if isdirectory(g:dir . '/.terraform')
+ call delete(g:dir . '/.terraform', 'd')
+ endif
+
+ unlet! b:ale_terraform_langserver_executable
+ unlet! b:ale_terraform_langserver_options
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(Should send correct LSP language):
+ AssertLSPLanguage 'terraform'
+
+Execute(Should load default executable):
+ AssertLinter 'terraform-lsp', ale#Escape('terraform-lsp')
+
+Execute(Should configure custom executable):
+ let b:ale_terraform_langserver_executable = 'foo'
+ AssertLinter 'foo', ale#Escape('foo')
+
+Execute(Should set custom options):
+ let b:ale_terraform_langserver_options = '--bar'
+
+ AssertLinter 'terraform-lsp',
+ \ ale#Escape('terraform-lsp') . ' --bar'
+
+Execute(Should return current directory if it contains .terraform directory):
+ call mkdir(g:dir . '/.terraform')
+ AssertLSPProject g:dir
+
+Execute(Should return nearest directory with .terraform if found in parent directory):
+ call ale#test#SetFilename('../test-files/terraform/main.tf')
+
+ let b:parent_dir = ale#path#Simplify(g:dir . '/..')
+ let b:tf_dir = b:parent_dir . '/.terraform'
+
+ if !isdirectory(b:tf_dir)
+ call mkdir(b:tf_dir)
+ endif
+
+ AssertLSPProject b:parent_dir
+
+ call delete(b:tf_dir, 'd')
+ unlet!b:parent_dir
+ unlet!b:tf_dir
diff --git a/test/linter/test_terraform_terraform.vader b/test/linter/test_terraform_terraform.vader
new file mode 100644
index 00000000..25ca652a
--- /dev/null
+++ b/test/linter/test_terraform_terraform.vader
@@ -0,0 +1,15 @@
+" Based upon :help ale-development
+Before:
+ call ale#assert#SetUpLinterTest('terraform', 'terraform')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'terraform',
+ \ ale#Escape('terraform') . ' validate -no-color -json '
+
+Execute(The default command should be overriden):
+ let b:ale_terraform_terraform_executable = '/bin/other/terraform'
+ AssertLinter '/bin/other/terraform',
+ \ ale#Escape('/bin/other/terraform') . ' validate -no-color -json '
diff --git a/test/linter/test_terraform_tflint.vader b/test/linter/test_terraform_tflint.vader
new file mode 100644
index 00000000..96811e81
--- /dev/null
+++ b/test/linter/test_terraform_tflint.vader
@@ -0,0 +1,28 @@
+Before:
+ call ale#assert#SetUpLinterTest('terraform', 'tflint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'tflint', ale#Escape('tflint') . ' -f json %t'
+
+Execute(The default executable should be configurable):
+ let b:ale_terraform_tflint_executable = 'asdf'
+
+ AssertLinter 'asdf', ale#Escape('asdf') . ' -f json %t'
+
+Execute(Overriding options should work):
+ let g:ale_terraform_tflint_executable = 'fnord'
+ let g:ale_terraform_tflint_options = '--whatever'
+
+ AssertLinter 'fnord', ale#Escape('fnord') . ' --whatever -f json %t'
+
+Execute(Configuration files should be found):
+ call ale#test#SetFilename('../test-files/tflint/foo/bar.tf')
+
+ AssertLinter 'tflint',
+ \ ale#Escape('tflint')
+ \ . ' --config '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/tflint/foo/.tflint.hcl'))
+ \ . ' -f json %t'
diff --git a/test/linter/test_tex_lacheck.vader b/test/linter/test_tex_lacheck.vader
new file mode 100644
index 00000000..b404cc78
--- /dev/null
+++ b/test/linter/test_tex_lacheck.vader
@@ -0,0 +1,13 @@
+Before:
+ call ale#assert#SetUpLinterTest('tex', 'lacheck')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to lacheck):
+ AssertLinter 'lacheck', ale#Escape('lacheck') . ' %t'
+
+Execute(Should be able to set a custom executable):
+ let g:ale_tex_lacheck_executable = 'bin/foo'
+
+ AssertLinter 'bin/foo' , ale#Escape('bin/foo') . ' %t'
diff --git a/test/linter/test_tex_textlint.vader b/test/linter/test_tex_textlint.vader
new file mode 100644
index 00000000..f99e0fd0
--- /dev/null
+++ b/test/linter/test_tex_textlint.vader
@@ -0,0 +1,65 @@
+" Author: januswel, w0rp
+
+Before:
+ " This is just one language for the linter.
+ call ale#assert#SetUpLinterTest('tex', 'textlint')
+
+ " The configuration is shared between many languages.
+ Save g:ale_textlint_executable
+ Save g:ale_textlint_use_global
+ Save g:ale_textlint_options
+
+ let g:ale_textlint_executable = 'textlint'
+ let g:ale_textlint_use_global = 0
+ let g:ale_textlint_options = ''
+
+ unlet! b:ale_textlint_executable
+ unlet! b:ale_textlint_use_global
+ unlet! b:ale_textlint_options
+
+After:
+ unlet! b:command_tail
+ unlet! b:ale_textlint_executable
+ unlet! b:ale_textlint_use_global
+ unlet! b:ale_textlint_options
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'textlint',
+ \ ale#Escape('textlint') . ' -f json --stdin --stdin-filename %s'
+
+Execute(The executable should be configurable):
+ let b:ale_textlint_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -f json --stdin --stdin-filename %s'
+
+Execute(The options should be configurable):
+ let b:ale_textlint_options = '--something'
+
+ AssertLinter 'textlint',
+ \ ale#Escape('textlint') . ' --something -f json --stdin --stdin-filename %s'
+
+Execute(The local executable from .bin should be used if available):
+ call ale#test#SetFilename('../test-files/textlint/with_bin_path/foo.txt')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_bin_path/node_modules/.bin/textlint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_bin_path/node_modules/.bin/textlint'))
+ \ . ' -f json --stdin --stdin-filename %s'
+
+Execute(The local executable from textlint/bin should be used if available):
+ call ale#test#SetFilename('../test-files/textlint/with_textlint_bin_path/foo.txt')
+
+ if has('win32')
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'),
+ \ ale#Escape('node.exe') . ' ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'))
+ \ . ' -f json --stdin --stdin-filename %s'
+ else
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'))
+ \ . ' -f json --stdin --stdin-filename %s'
+ endif
diff --git a/test/linter/test_texlab.vader b/test/linter/test_texlab.vader
new file mode 100644
index 00000000..75fc2f25
--- /dev/null
+++ b/test/linter/test_texlab.vader
@@ -0,0 +1,30 @@
+Before:
+ call ale#assert#SetUpLinterTest('tex', 'texlab')
+
+ Save &filetype
+ let &filetype = 'tex'
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The language string should be correct):
+ AssertLSPLanguage 'tex'
+
+Execute(The default executable path should be correct):
+ AssertLinter 'texlab', ale#Escape('texlab')
+
+Execute(The project root should be detected correctly):
+ call ale#test#SetFilename('../test-files/tex/sample1.tex')
+ silent! call mkdir('../test-files/tex/.git')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/tex')
+
+Execute(The executable should be configurable):
+ let b:ale_tex_texlab_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
+
+Execute(The options should be configurable):
+ let b:ale_tex_texlab_options = '-v'
+
+ AssertLinter 'texlab', ale#Escape('texlab') . ' ' . b:ale_tex_texlab_options
diff --git a/test/linter/test_textlint.vader b/test/linter/test_textlint.vader
new file mode 100644
index 00000000..6ec42b2d
--- /dev/null
+++ b/test/linter/test_textlint.vader
@@ -0,0 +1,65 @@
+" Author: januswel, w0rp
+
+Before:
+ " This is just one language for the linter.
+ call ale#assert#SetUpLinterTest('markdown', 'textlint')
+
+ " The configuration is shared between many languages.
+ Save g:ale_textlint_executable
+ Save g:ale_textlint_use_global
+ Save g:ale_textlint_options
+
+ let g:ale_textlint_executable = 'textlint'
+ let g:ale_textlint_use_global = 0
+ let g:ale_textlint_options = ''
+
+ unlet! b:ale_textlint_executable
+ unlet! b:ale_textlint_use_global
+ unlet! b:ale_textlint_options
+
+After:
+ unlet! b:command_tail
+ unlet! b:ale_textlint_executable
+ unlet! b:ale_textlint_use_global
+ unlet! b:ale_textlint_options
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'textlint',
+ \ ale#Escape('textlint') . ' -f json --stdin --stdin-filename %s'
+
+Execute(The executable should be configurable):
+ let b:ale_textlint_executable = 'foobar'
+
+ AssertLinter 'foobar',
+ \ ale#Escape('foobar') . ' -f json --stdin --stdin-filename %s'
+
+Execute(The options should be configurable):
+ let b:ale_textlint_options = '--something'
+
+ AssertLinter 'textlint',
+ \ ale#Escape('textlint') . ' --something -f json --stdin --stdin-filename %s'
+
+Execute(The local executable from .bin should be used if available):
+ call ale#test#SetFilename('../test-files/textlint/with_bin_path/foo.txt')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_bin_path/node_modules/.bin/textlint'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_bin_path/node_modules/.bin/textlint'))
+ \ . ' -f json --stdin --stdin-filename %s'
+
+Execute(The local executable from textlint/bin should be used if available):
+ call ale#test#SetFilename('../test-files/textlint/with_textlint_bin_path/foo.txt')
+
+ if has('win32')
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'),
+ \ ale#Escape('node.exe') . ' ' . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'))
+ \ . ' -f json --stdin --stdin-filename %s'
+ else
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/textlint/with_textlint_bin_path/node_modules/textlint/bin/textlint.js'))
+ \ . ' -f json --stdin --stdin-filename %s'
+ endif
diff --git a/test/linter/test_thrift.vader b/test/linter/test_thrift.vader
new file mode 100644
index 00000000..cbada818
--- /dev/null
+++ b/test/linter/test_thrift.vader
@@ -0,0 +1,53 @@
+Before:
+ call ale#assert#SetUpLinterTest('thrift', 'thrift')
+ let b:suffix = ' -out ' . ale#Escape('TEMP_DIR') . ' %t'
+
+ function! GetCommand(buffer) abort
+ call ale#engine#InitBufferInfo(a:buffer)
+ let l:command = ale_linters#thrift#thrift#GetCommand(a:buffer)
+ call ale#engine#Cleanup(a:buffer)
+
+ let l:split_command = split(l:command)
+ let l:index = index(l:split_command, '-out')
+
+ if l:index >= 0
+ let l:split_command[l:index + 1] = 'TEMP'
+ endif
+
+ return join(l:split_command)
+ endfunction
+
+After:
+ unlet! b:suffix
+ delfunction GetCommand
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'thrift', ale#Escape('thrift') . ' --gen cpp -I . -strict' . b:suffix
+
+Execute(The executable should be configurable):
+ let b:ale_thrift_thrift_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --gen cpp -I . -strict' . b:suffix
+
+Execute(The list of generators should be configurable):
+ let b:ale_thrift_thrift_generators = ['java', 'py:dynamic']
+
+ AssertLinter 'thrift', ale#Escape('thrift')
+ \ . ' --gen java --gen py:dynamic -I . -strict' . b:suffix
+
+ let b:ale_thrift_thrift_generators = []
+
+ AssertLinter 'thrift', ale#Escape('thrift') . ' --gen cpp -I . -strict' . b:suffix
+
+Execute(The list of include paths should be configurable):
+ let b:ale_thrift_thrift_includes = ['included/path']
+
+ AssertLinter 'thrift', ale#Escape('thrift')
+ \ . ' --gen cpp -I included/path -strict' . b:suffix
+
+Execute(The string of compiler options should be configurable):
+ let b:ale_thrift_thrift_options = '-strict --allow-64bit-consts'
+
+ AssertLinter 'thrift', ale#Escape('thrift')
+ \ . ' --gen cpp -I . -strict --allow-64bit-consts' . b:suffix
diff --git a/test/linter/test_tslint.vader b/test/linter/test_tslint.vader
new file mode 100644
index 00000000..1b291d9f
--- /dev/null
+++ b/test/linter/test_tslint.vader
@@ -0,0 +1,23 @@
+Before:
+ call ale#assert#SetUpLinterTest('typescript', 'tslint')
+ call ale#test#SetFilename('test.ts')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default tslint command should be correct):
+ AssertLinterCwd '%s:h'
+ AssertLinter 'tslint', ale#Escape('tslint') . ' --format json %t'
+
+Execute(The rules directory option should be included if set):
+ let b:ale_typescript_tslint_rules_dir = '/foo/bar'
+
+ AssertLinter 'tslint',
+ \ ale#Escape('tslint') . ' --format json'
+ \ . ' -r ' . ale#Escape('/foo/bar')
+ \ . ' %t'
+
+Execute(The executable should be configurable and escaped):
+ let b:ale_typescript_tslint_executable = 'foo bar'
+
+ AssertLinter 'foo bar', ale#Escape('foo bar') . ' --format json %t'
diff --git a/test/linter/test_typescript_deno_lsp.vader b/test/linter/test_typescript_deno_lsp.vader
new file mode 100644
index 00000000..88b2e036
--- /dev/null
+++ b/test/linter/test_typescript_deno_lsp.vader
@@ -0,0 +1,43 @@
+Before:
+ let g:ale_deno_unstable = 0
+ let g:ale_deno_executable = 'deno'
+ let g:ale_deno_lsp_project_root = ''
+
+ runtime autoload/ale/handlers/deno.vim
+ call ale#assert#SetUpLinterTest('typescript', 'deno')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Should set deno lsp for TypeScript projects using stable Deno API):
+ AssertLSPOptions {
+ \ 'enable': v:true,
+ \ 'lint': v:true,
+ \ 'unstable': v:false
+ \}
+
+Execute(Should set deno lsp using unstable Deno API if enabled by user):
+ let g:ale_deno_unstable = 1
+
+ AssertLSPOptions {
+ \ 'enable': v:true,
+ \ 'lint': v:true,
+ \ 'unstable': v:true
+ \}
+
+Execute(Should find project root containing tsconfig.json):
+ call ale#test#SetFilename('../test-files/typescript/test.ts')
+
+ AssertLSPLanguage 'typescript'
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/typescript')
+
+Execute(Should use user-specified project root):
+ let g:ale_deno_lsp_project_root = '/'
+
+ call ale#test#SetFilename('../test-files/typescript/test.ts')
+
+ AssertLSPLanguage 'typescript'
+ AssertLSPProject '/'
+
+Execute(Check Deno LSP command):
+ AssertLinter 'deno', ale#Escape('deno') . ' lsp'
diff --git a/test/linter/test_typescript_tsserver.vader b/test/linter/test_typescript_tsserver.vader
new file mode 100644
index 00000000..719ac184
--- /dev/null
+++ b/test/linter/test_typescript_tsserver.vader
@@ -0,0 +1,8 @@
+Before:
+ call ale#assert#SetUpLinterTest('typescript', 'tsserver')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'tsserver', ale#Escape('tsserver')
diff --git a/test/linter/test_vcom.vader b/test/linter/test_vcom.vader
new file mode 100644
index 00000000..77218f74
--- /dev/null
+++ b/test/linter/test_vcom.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('vhdl', 'vcom')
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'vcom', ale#Escape('vcom') . ' -2008 -quiet -lint %t'
+
+ let b:ale_vhdl_vcom_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' -2008 -quiet -lint %t'
+
+Execute(The options should be configurable):
+ let b:ale_vhdl_vcom_options = '--something'
+
+ AssertLinter 'vcom', ale#Escape('vcom') . ' --something %t'
diff --git a/test/linter/test_verilator.vader b/test/linter/test_verilator.vader
new file mode 100644
index 00000000..b65f3459
--- /dev/null
+++ b/test/linter/test_verilator.vader
@@ -0,0 +1,14 @@
+Before:
+ call ale#assert#SetUpLinterTest('verilog', 'verilator')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default verilator command should be correct):
+ AssertLinter 'verilator', 'verilator --lint-only -Wall -Wno-DECLFILENAME -I%s:h %t'
+
+Execute(verilator options should be configurable):
+ " Additional args for the linter
+ let g:ale_verilog_verilator_options = '-sv --default-language "1800-2012"'
+
+ AssertLinter 'verilator', 'verilator --lint-only -Wall -Wno-DECLFILENAME -I%s:h -sv --default-language "1800-2012" %t'
diff --git a/test/linter/test_vim_vimls.vader b/test/linter/test_vim_vimls.vader
new file mode 100644
index 00000000..47826a1a
--- /dev/null
+++ b/test/linter/test_vim_vimls.vader
@@ -0,0 +1,76 @@
+" Author: Jeffrey Lau https://github.com/zoonfafer
+" Description: Tests for the Vim vimls linter
+
+Before:
+ call ale#assert#SetUpLinterTest('vim', 'vimls')
+
+After:
+ if isdirectory(g:dir . '/.git')
+ call delete(g:dir . '/.git', 'd')
+ endif
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(should set correct defaults):
+ AssertLinter 'vim-language-server', ale#Escape('vim-language-server') . ' --stdio'
+
+Execute(should set correct LSP values):
+ call ale#test#SetFilename('../test-files/vim/path_with_autoload/test.vim')
+ AssertLSPLanguage 'vim'
+ AssertLSPOptions {}
+ AssertLSPConfig {}
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/vim/path_with_autoload')
+
+Execute(should set correct project for .git/):
+ let b:parent_dir = ale#path#Simplify(g:dir . '/..')
+ let b:git_dir = b:parent_dir . '/.git'
+
+ call ale#test#SetFilename('../test-files/vim/test.vim')
+
+ if !isdirectory(b:git_dir)
+ call mkdir(b:git_dir)
+ endif
+
+ AssertLSPProject ale#path#Simplify(b:parent_dir)
+
+ call delete(b:git_dir, 'd')
+ unlet! b:git_dir
+
+Execute(should set correct project for plugin/):
+ call ale#test#SetFilename('../test-files/vim/path_with_plugin/test.vim')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/vim/path_with_plugin')
+
+Execute(should accept configuration settings):
+ AssertLSPConfig {}
+
+ let b:ale_vim_vimls_config = {'vim': {'foobar': v:true}}
+ AssertLSPConfig {'vim': {'foobar': v:true}}
+
+Execute(should set correct project for .vimrc):
+ call ale#test#SetFilename('../test-files/vim/path_with_vimrc/.vimrc')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/vim/path_with_vimrc')
+
+Execute(should set correct project for init.vim):
+ call ale#test#SetFilename('../test-files/vim/path_with_initvim/init.vim')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/vim/path_with_initvim')
+
+Execute(should use the local executable when available):
+ call ale#test#SetFilename('../test-files/vim/file.vim')
+
+ AssertLinter ale#path#Simplify(g:dir . '/../test-files/vim/node_modules/.bin/vim-language-server'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/vim/node_modules/.bin/vim-language-server')) . ' --stdio'
+
+Execute(should let the global executable to be used):
+ let g:ale_vim_vimls_use_global = 1
+ call ale#test#SetFilename('../test-files/vim/file.vim')
+
+ AssertLinter 'vim-language-server',
+ \ ale#Escape('vim-language-server') . ' --stdio'
+
+Execute(should let the executable to be configured):
+ let g:ale_vim_vimls_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio'
diff --git a/test/linter/test_vint.vader b/test/linter/test_vint.vader
new file mode 100644
index 00000000..4a224d01
--- /dev/null
+++ b/test/linter/test_vint.vader
@@ -0,0 +1,34 @@
+Before:
+ call ale#assert#SetUpLinterTest('vim', 'vint')
+ let b:common_flags = (has('nvim') ? ' --enable-neovim' : '')
+ \ . ' -f "{file_path}:{line_number}:{column_number}: {severity}: {policy_name} - {description} (see {reference})"'
+
+After:
+ unlet! b:common_flags
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'vint', [
+ \ ale#Escape('vint') .' --version',
+ \ ale#Escape('vint') .' -s --no-color' . b:common_flags . ' %t',
+ \]
+
+Execute(The executable should be configurable):
+ let g:ale_vim_vint_executable = 'foobar'
+
+ AssertLinter 'foobar', [
+ \ ale#Escape('foobar') .' --version',
+ \ ale#Escape('foobar') .' -s --no-color' . b:common_flags . ' %t',
+ \]
+
+Execute(The --no-color flag should not be used for older Vint versions):
+ GivenCommandOutput ['v0.3.5']
+
+ AssertLinter 'vint', ale#Escape('vint') .' -s' . b:common_flags . ' %t'
+
+Execute(--stdin-display-name should be used in newer versions):
+ GivenCommandOutput ['v0.4.0']
+
+ AssertLinter 'vint', ale#Escape('vint') .' -s --no-color' . b:common_flags
+ \ . ' --stdin-display-name %s -'
diff --git a/test/linter/test_vlog.vader b/test/linter/test_vlog.vader
new file mode 100644
index 00000000..a07944f7
--- /dev/null
+++ b/test/linter/test_vlog.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('verilog', 'vlog')
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'vlog', ale#Escape('vlog') . ' -quiet -lint %t'
+
+ let b:ale_verilog_vlog_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' -quiet -lint %t'
+
+Execute(The options should be configurable):
+ let b:ale_verilog_vlog_options = '--something'
+
+ AssertLinter 'vlog', ale#Escape('vlog') . ' --something %t'
diff --git a/test/linter/test_vulture.vader b/test/linter/test_vulture.vader
new file mode 100644
index 00000000..74709c9e
--- /dev/null
+++ b/test/linter/test_vulture.vader
@@ -0,0 +1,58 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'vulture')
+ call ale#test#SetFilename('test.py')
+
+ let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+After:
+ unlet! b:bin_dir
+ unlet! b:executable
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The vulture command callback should lint file directory by default):
+ AssertLinterCwd expand('#' . bufnr('') . ':p:h')
+ AssertLinter 'vulture', ale#Escape('vulture') . ' .'
+
+Execute(The vulture command callback should lint project root, when present):
+ call ale#test#SetFilename('../test-files/python/no_virtualenv/subdir/foo/bar.py')
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/no_virtualenv/subdir')
+ AssertLinter 'vulture', ale#Escape('vulture') . ' .'
+
+Execute(The option for disabling change directory works and only lints file):
+ let g:ale_python_vulture_change_directory = 0
+
+ AssertLinterCwd ''
+ AssertLinter 'vulture', ale#Escape('vulture') . ' %s'
+
+Execute(The vulture executable should be configurable, and escaped properly):
+ let g:ale_python_vulture_executable = 'executable with spaces'
+
+ AssertLinter 'executable with spaces', ale#Escape('executable with spaces') . ' .'
+
+Execute(The vulture command callback should let you set options):
+ let g:ale_python_vulture_options = '--some-option'
+
+ AssertLinter 'vulture', ale#Escape('vulture') . ' --some-option .'
+
+Execute(The vulture command callback should detect virtualenv directories and switch to the project root):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir . '/../test-files/python/with_virtualenv/env/' . b:bin_dir . '/vulture'
+ \)
+
+ AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
+ AssertLinter b:executable, ale#Escape(b:executable) . ' .'
+
+Execute(You should able able to use the global vulture instead):
+ call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
+ let g:ale_python_vulture_use_global = 1
+
+ AssertLinter 'vulture', ale#Escape('vulture') . ' .'
+
+Execute(Setting executable to 'pipenv' appends 'run vulture'):
+ let g:ale_python_vulture_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv', ale#Escape('path/to/pipenv') . ' run vulture' . ' .'
diff --git a/test/linter/test_write_good.vader b/test/linter/test_write_good.vader
new file mode 100644
index 00000000..8958dd6a
--- /dev/null
+++ b/test/linter/test_write_good.vader
@@ -0,0 +1,55 @@
+Before:
+ " This is just one example of a language using the linter.
+ call ale#assert#SetUpLinterTest('markdown', 'writegood')
+
+ " The options are shared between many languages.
+ Save g:ale_writegood_options
+ Save g:ale_writegood_executable
+ Save g:ale_writegood_use_global
+
+ unlet! g:ale_writegood_options
+ unlet! g:ale_writegood_executable
+ unlet! g:ale_writegood_use_global
+
+ call ale#test#SetFilename('testfile.txt')
+ call ale#handlers#writegood#ResetOptions()
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The global executable should be used when the local one cannot be found):
+ AssertLinter
+ \ 'write-good',
+ \ ale#Escape('write-good') . ' %t',
+
+Execute(The options should be used in the command):
+ let g:ale_writegood_options = '--foo --bar'
+
+ AssertLinter
+ \ 'write-good',
+ \ ale#Escape('write-good') . ' --foo --bar %t',
+
+Execute(Should use the node_modules/.bin executable, if available):
+ call ale#test#SetFilename('../test-files/write-good/node-modules/test.txt')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/write-good/node-modules/node_modules/.bin/write-good'),
+ \ ale#Escape(ale#path#Simplify(g:dir . '/../test-files/write-good/node-modules/node_modules/.bin/write-good'))
+ \ . ' %t',
+
+Execute(Should use the node_modules/write-good executable, if available):
+ call ale#test#SetFilename('../test-files/write-good/node-modules-2/test.txt')
+
+ AssertLinter
+ \ ale#path#Simplify(g:dir . '/../test-files/write-good/node-modules-2/node_modules/write-good/bin/write-good.js'),
+ \ (has('win32') ? 'node.exe ' : '')
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/../test-files/write-good/node-modules-2/node_modules/write-good/bin/write-good.js'))
+ \ . ' %t',
+
+Execute(Should let users configure a global executable and override local paths):
+ call ale#test#SetFilename('../test-files/write-good/node-modules-2/test.txt')
+
+ let g:ale_writegood_executable = 'foo-bar'
+ let g:ale_writegood_use_global = 1
+
+ AssertLinter 'foo-bar', ale#Escape('foo-bar') . ' %t'
diff --git a/test/linter/test_xmllint.vader b/test/linter/test_xmllint.vader
new file mode 100644
index 00000000..5a2377c2
--- /dev/null
+++ b/test/linter/test_xmllint.vader
@@ -0,0 +1,20 @@
+Before:
+ call ale#assert#SetUpLinterTest('xml', 'xmllint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The xml xmllint command callback should return the correct default string):
+ AssertLinter 'xmllint', ale#Escape('xmllint') . ' --noout -'
+
+Execute(The xml xmllint command callback should let you set options):
+ let g:ale_xml_xmllint_options = '--xinclude --postvalid'
+
+ AssertLinter 'xmllint',
+ \ ale#Escape('xmllint') . ' --xinclude --postvalid --noout -'
+
+Execute(The xmllint executable should be configurable):
+ let g:ale_xml_xmllint_executable = '~/.local/bin/xmllint'
+
+ AssertLinter '~/.local/bin/xmllint',
+ \ ale#Escape('~/.local/bin/xmllint') . ' --noout -'
diff --git a/test/linter/test_xo.vader b/test/linter/test_xo.vader
new file mode 100644
index 00000000..1aa4c3f1
--- /dev/null
+++ b/test/linter/test_xo.vader
@@ -0,0 +1,23 @@
+Before:
+ call ale#assert#SetUpLinterTest('javascript', 'xo')
+ call ale#test#SetFilename('testfile.jsx')
+ unlet! b:executable
+
+ set filetype=javascriptreact
+ runtime autoload/ale/handlers/xo.vim
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The XO executable should be called):
+ AssertLinter 'xo', ale#Escape('xo') . ' --reporter json --stdin --stdin-filename %s'
+
+Execute(The XO executable should be configurable):
+ let b:ale_javascript_xo_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --reporter json --stdin --stdin-filename %s'
+
+Execute(The XO options should be configurable):
+ let b:ale_javascript_xo_options = '--wat'
+
+ AssertLinter 'xo', ale#Escape('xo') . ' --wat --reporter json --stdin --stdin-filename %s'
diff --git a/test/linter/test_xots.vader b/test/linter/test_xots.vader
new file mode 100644
index 00000000..cc38ff02
--- /dev/null
+++ b/test/linter/test_xots.vader
@@ -0,0 +1,23 @@
+Before:
+ call ale#assert#SetUpLinterTest('typescript', 'xo')
+ call ale#test#SetFilename('testfile.tsx')
+ unlet! b:executable
+
+ set filetype=typescriptreact
+ runtime autoload/ale/handlers/xo.vim
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The XO executable should be called):
+ AssertLinter 'xo', ale#Escape('xo') . ' --reporter json --stdin --stdin-filename %s'
+
+Execute(The XO executable should be configurable):
+ let b:ale_typescript_xo_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --reporter json --stdin --stdin-filename %s'
+
+Execute(The XO options should be configurable):
+ let b:ale_typescript_xo_options = '--wat'
+
+ AssertLinter 'xo', ale#Escape('xo') . ' --wat --reporter json --stdin --stdin-filename %s'
diff --git a/test/linter/test_xvhdl.vader b/test/linter/test_xvhdl.vader
new file mode 100644
index 00000000..86f9a32d
--- /dev/null
+++ b/test/linter/test_xvhdl.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('vhdl', 'xvhdl')
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'xvhdl', ale#Escape('xvhdl') . ' --2008 %t'
+
+ let b:ale_vhdl_xvhdl_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' --2008 %t'
+
+Execute(The options should be configurable):
+ let b:ale_vhdl_xvhdl_options = '--something'
+
+ AssertLinter 'xvhdl', ale#Escape('xvhdl') . ' --something %t'
diff --git a/test/linter/test_xvlog.vader b/test/linter/test_xvlog.vader
new file mode 100644
index 00000000..564ac979
--- /dev/null
+++ b/test/linter/test_xvlog.vader
@@ -0,0 +1,19 @@
+Before:
+ call ale#assert#SetUpLinterTest('verilog', 'xvlog')
+
+After:
+ unlet! b:command_tail
+
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'xvlog', ale#Escape('xvlog') . ' %t'
+
+ let b:ale_verilog_xvlog_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar') . ' %t'
+
+Execute(The options should be configurable):
+ let b:ale_verilog_xvlog_options = '--something'
+
+ AssertLinter 'xvlog', ale#Escape('xvlog') . ' --something %t'
diff --git a/test/linter/test_yang_lsp.vader b/test/linter/test_yang_lsp.vader
new file mode 100644
index 00000000..5be7501f
--- /dev/null
+++ b/test/linter/test_yang_lsp.vader
@@ -0,0 +1,12 @@
+Before:
+ call ale#assert#SetUpLinterTest('yang', 'yang_lsp')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The executable should be configurable):
+ AssertLinter 'yang-language-server', ale#Escape('yang-language-server')
+
+ let b:ale_yang_lsp_executable = 'foobar'
+
+ AssertLinter 'foobar', ale#Escape('foobar')
diff --git a/test/linter/test_zig_zls.vader b/test/linter/test_zig_zls.vader
new file mode 100644
index 00000000..6d814be4
--- /dev/null
+++ b/test/linter/test_zig_zls.vader
@@ -0,0 +1,15 @@
+Before:
+ call ale#assert#SetUpLinterTest('zig', 'zls')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default executable path should be correct):
+ AssertLinter 'zls', ale#Escape('zls')
+
+Execute(The project root should be detected correctly):
+ AssertLSPProject ''
+
+ call ale#test#SetFilename('../test-files/zig/main.zig')
+
+ AssertLSPProject ale#path#Simplify(g:dir . '/../test-files/zig')