summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ale_linters/v/v.vim82
-rw-r--r--autoload/ale/fix/registry.vim5
-rw-r--r--autoload/ale/fixers/vfmt.vim13
-rw-r--r--autoload/ale/linter.vim1
-rw-r--r--doc/ale-supported-languages-and-tools.txt3
-rw-r--r--doc/ale-v.txt45
-rw-r--r--doc/ale.txt4
-rw-r--r--supported-tools.md3
-rw-r--r--test/fixers/test_vfmt_fixer_callback.vader44
-rw-r--r--test/handler/test_v_handler.vader54
-rw-r--r--test/linter/test_v_command_callback.vader25
-rw-r--r--test/v_files/testfile.v0
12 files changed, 279 insertions, 0 deletions
diff --git a/ale_linters/v/v.vim b/ale_linters/v/v.vim
new file mode 100644
index 00000000..afa98c56
--- /dev/null
+++ b/ale_linters/v/v.vim
@@ -0,0 +1,82 @@
+" Author: fiatjaf <fiatjaf@alhur.es>
+" Description: v build for V files
+
+call ale#Set('v_v_executable', 'v')
+call ale#Set('v_v_options', '')
+
+function! ale_linters#v#v#GetCommand(buffer) abort
+ let l:options = ale#Var(a:buffer, 'v_v_options')
+
+ " Run v in local directory with relative path
+ let l:command = ale#Var(a:buffer, 'v_v_executable')
+ \ . ale#Pad(l:options)
+ \ . ' .' . ' -o /tmp/vim-ale-v'
+
+ return l:command
+endfunction
+
+function! ale_linters#v#v#Handler(buffer, lines) abort
+ let l:dir = expand('#' . a:buffer . ':p:h')
+ let l:output = []
+
+ " Matches patterns like the following:
+ "
+ " ./const.v:4:3: warning: const names cannot contain uppercase letters, use snake_case instead
+ " 2 |
+ " 3 | const (
+ " 4 | BUTTON_TEXT = 'OK'
+ " | ~~~~~~~~~~~
+ " 5 | )
+ " ./main.v:4:8: warning: module 'os' is imported but never used
+ " 2 |
+ " 3 | import ui
+ " 4 | import os
+ " | ~~
+ " 5 |
+ " 6 | const (
+ " ./main.v:20:10: error: undefined ident: `win_widt`
+ " 18 | mut app := &App{}
+ " 19 | app.window = ui.window({
+ " 20 | width: win_widt
+ " | ~~~~~~~~
+ " 21 | height: win_height
+ " 22 | title: 'Counter'
+ let l:current = {}
+
+ for l:line in a:lines
+ " matches basic error description
+ let l:match = matchlist(l:line,
+ \ '\([^:]\+\):\([^:]\+\):\([^:]\+\): \([^:]\+\): \(.*\)')
+
+ if !empty(l:match)
+ let l:current = {
+ \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
+ \ 'lnum': l:match[2] + 0,
+ \ 'col': l:match[3] + 0,
+ \ 'text': l:match[5],
+ \ 'type': l:match[4] is# 'error' ? 'E' : 'W',
+ \}
+ call add(l:output, l:current)
+ continue
+ endif
+
+ " try to get information about the ending column
+ let l:tildematch = matchstr(l:line, '\~\+')
+
+ if !empty(l:tildematch)
+ let l:current['end_col'] = l:current['col'] + len(l:tildematch)
+ endif
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('v', {
+\ 'name': 'v',
+\ 'aliases': [],
+\ 'executable': {b -> ale#Var(b, 'v_v_executable')},
+\ 'command': function('ale_linters#v#v#GetCommand'),
+\ 'output_stream': 'stderr',
+\ 'callback': 'ale_linters#v#v#Handler',
+\ 'lint_file': 1,
+\})
diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim
index 632bc890..0cf866dc 100644
--- a/autoload/ale/fix/registry.vim
+++ b/autoload/ale/fix/registry.vim
@@ -440,6 +440,11 @@ let s:default_registry = {
\ 'function': 'ale#fixers#ptop#Fix',
\ 'suggested_filetypes': ['pascal'],
\ 'description': 'Fix Pascal files with ptop.',
+\ },
+\ 'vfmt': {
+\ 'function': 'ale#fixers#vfmt#Fix',
+\ 'suggested_filetypes': ['v'],
+\ 'description': 'A formatter for V source code.',
\ }
\}
diff --git a/autoload/ale/fixers/vfmt.vim b/autoload/ale/fixers/vfmt.vim
new file mode 100644
index 00000000..2e780318
--- /dev/null
+++ b/autoload/ale/fixers/vfmt.vim
@@ -0,0 +1,13 @@
+" Author: fiatjaf <fiatjaf@alhur.es>
+" Description: Integration of `v fmt` with ALE.
+
+call ale#Set('v_vfmt_options', '')
+
+function! ale#fixers#vfmt#Fix(buffer) abort
+ let l:executable = ale#Var(a:buffer, 'v_v_executable')
+ let l:options = ale#Var(a:buffer, 'v_vfmt_options')
+
+ return {
+ \ 'command': ale#Escape(l:executable) . ' fmt' . ale#Pad(l:options)
+ \}
+endfunction
diff --git a/autoload/ale/linter.vim b/autoload/ale/linter.vim
index d7b6a1ac..d26b9443 100644
--- a/autoload/ale/linter.vim
+++ b/autoload/ale/linter.vim
@@ -53,6 +53,7 @@ let s:default_ale_linters = {
\ 'text': [],
\ 'vue': ['eslint', 'vls'],
\ 'zsh': ['shell'],
+\ 'v': ['v'],
\}
" Testing/debugging helper to unload all linters.
diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt
index fe19ae63..e0e0a6a3 100644
--- a/doc/ale-supported-languages-and-tools.txt
+++ b/doc/ale-supported-languages-and-tools.txt
@@ -534,6 +534,9 @@ Notes:
* `tslint`
* `tsserver`
* `typecheck`
+* V
+ * `v`
+ * `vfmt`
* VALA
* `uncrustify`
* `vala_lint`!!
diff --git a/doc/ale-v.txt b/doc/ale-v.txt
new file mode 100644
index 00000000..8c641447
--- /dev/null
+++ b/doc/ale-v.txt
@@ -0,0 +1,45 @@
+===============================================================================
+ALE V Integration *ale-v-options*
+
+
+===============================================================================
+Integration Information
+
+`v` is V's build tool. `vfmt` (called as `v fmt` from the same
+executable that does the builds) is the autoformatter/fixer.
+
+g:ale_v_v_executable *g:ale_v_v_executable*
+ *b:ale_v_v_executable*
+
+ Type: |String|
+ Default: `'v'`
+
+ The executable that will be run for the `v` linter and the `vfmt` fixer.
+
+
+===============================================================================
+v *ale-v-v*
+
+g:ale_v_v_options *g:ale_v_v_options*
+ *b:ale_v_v_options*
+ Type: |String|
+ Default: `''`
+
+ This variable can be set to pass additional options to the v linter.
+ They are injected directly after "v .".
+
+
+===============================================================================
+vfmt *ale-v-vfmt*
+
+g:ale_v_vfmt_options *g:ale_v_vfmt_options*
+ *b:ale_v_vfmt_options*
+ Type: |String|
+ Default: `''`
+
+ This variable can be set to pass additional options to the vfmt fixer.
+ They are injected directly after "v fmt".
+
+
+===============================================================================
+ vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
diff --git a/doc/ale.txt b/doc/ale.txt
index 81162348..84d4b096 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -1593,6 +1593,7 @@ g:ale_linters *g:ale_linters*
\ 'text': [],
\ 'vue': ['eslint', 'vls'],
\ 'zsh': ['shell'],
+ \ 'v': ['v'],
\}
<
This option can be used to enable only a particular set of linters for a
@@ -3051,6 +3052,9 @@ documented in additional help files.
tslint................................|ale-typescript-tslint|
tsserver..............................|ale-typescript-tsserver|
xo....................................|ale-typescript-xo|
+ v.......................................|ale-v-options|
+ v.....................................|ale-v-v|
+ vfmt..................................|ale-v-vfmt|
vala....................................|ale-vala-options|
uncrustify............................|ale-vala-uncrustify|
verilog/systemverilog...................|ale-verilog-options|
diff --git a/supported-tools.md b/supported-tools.md
index 4a557538..da0222d1 100644
--- a/supported-tools.md
+++ b/supported-tools.md
@@ -543,6 +543,9 @@ formatting.
* [tslint](https://github.com/palantir/tslint)
* [tsserver](https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29)
* typecheck
+* V
+ * [v](https://github.com/vlang/v/)
+ * [vfmt](https://github.com/vlang/v/)
* VALA
* [uncrustify](https://github.com/uncrustify/uncrustify)
* [vala_lint](https://github.com/vala-lang/vala-lint) :floppy_disk:
diff --git a/test/fixers/test_vfmt_fixer_callback.vader b/test/fixers/test_vfmt_fixer_callback.vader
new file mode 100644
index 00000000..cbab1189
--- /dev/null
+++ b/test/fixers/test_vfmt_fixer_callback.vader
@@ -0,0 +1,44 @@
+Before:
+ Save g:ale_v_v_executable
+ Save g:ale_v_vfmt_options
+
+ " Use an invalid global executable, so we don't match it.
+ let g:ale_v_v_executable = 'xxxinvalid'
+ let g:ale_v_vfmt_options = ''
+
+ call ale#test#SetDirectory('/testplugin/test/fixers')
+
+After:
+ Restore
+
+ call ale#test#RestoreDirectory()
+
+Execute(The vfmt callback should return the correct default values):
+ call ale#test#SetFilename('../v_files/testfile.v')
+
+ AssertEqual
+ \ {
+ \ 'command': ale#Escape('xxxinvalid') . ' fmt',
+ \ },
+ \ ale#fixers#vfmt#Fix(bufnr(''))
+
+Execute(The vfmt callback should include custom vfmt options):
+ let g:ale_v_vfmt_options = "-r '(a) -> a'"
+
+ call ale#test#SetFilename('../v_files/testfile.v')
+
+ AssertEqual
+ \ {
+ \ 'command': ale#Escape('xxxinvalid')
+ \ . ' fmt ' . g:ale_v_vfmt_options,
+ \ },
+ \ ale#fixers#vfmt#Fix(bufnr(''))
+
+Execute(The vfmt callback should support Go environment variables):
+ call ale#test#SetFilename('../v_files/testfile.v')
+
+ AssertEqual
+ \ {
+ \ 'command': ale#Escape('xxxinvalid') . ' fmt',
+ \ },
+ \ ale#fixers#vfmt#Fix(bufnr(''))
diff --git a/test/handler/test_v_handler.vader b/test/handler/test_v_handler.vader
new file mode 100644
index 00000000..4d6e3d9b
--- /dev/null
+++ b/test/handler/test_v_handler.vader
@@ -0,0 +1,54 @@
+Before:
+ runtime ale_linters/v/v.vim
+
+After:
+ call ale#linter#Reset()
+
+Execute (The v handler should correctly parse error messages):
+ AssertEqual
+ \ [{
+ \ 'lnum': 4,
+ \ 'col': 3,
+ \ 'filename': ale#path#GetAbsPath(expand('%:p:h'), 'const ants.v'),
+ \ 'type': 'W',
+ \ 'end_col': 14,
+ \ 'text': 'const names cannot contain uppercase letters, use snake_case instead'
+ \ },
+ \ {
+ \ 'lnum': 4,
+ \ 'col': 8,
+ \ 'filename': ale#path#GetAbsPath(expand('%:p:h'), 'main.v'),
+ \ 'type': 'W',
+ \ 'end_col': 10,
+ \ 'text': 'module "os" is imported but never used'
+ \ },
+ \ {
+ \ 'lnum': 20,
+ \ 'col': 10,
+ \ 'filename': ale#path#GetAbsPath(expand('%:p:h'), 'main.v'),
+ \ 'type': 'E',
+ \ 'end_col': 18,
+ \ 'text': 'undefined ident: `win_widt`'
+ \ }],
+ \ ale_linters#v#v#Handler('', [
+ \ './const ants.v:4:3: warning: const names cannot contain uppercase letters, use snake_case instead',
+ \ ' 2 |',
+ \ ' 3 | const (',
+ \ ' 4 | BUTTON_TEXT = "OK"',
+ \ ' | ~~~~~~~~~~~',
+ \ ' 5 | )',
+ \ './main.v:4:8: warning: module "os" is imported but never used',
+ \ ' 2 |',
+ \ ' 3 | import ui',
+ \ ' 4 | import os',
+ \ ' | ~~',
+ \ ' 5 |',
+ \ ' 6 | const (',
+ \ './main.v:20:10: error: undefined ident: `win_widt`',
+ \ ' 18 | mut app := &App{}',
+ \ ' 19 | app.window = ui.window({',
+ \ ' 20 | width: win_widt',
+ \ ' | ~~~~~~~~',
+ \ ' 21 | height: win_height',
+ \ ' 22 | title: "Counter"',
+ \ ])
diff --git a/test/linter/test_v_command_callback.vader b/test/linter/test_v_command_callback.vader
new file mode 100644
index 00000000..17f24ad7
--- /dev/null
+++ b/test/linter/test_v_command_callback.vader
@@ -0,0 +1,25 @@
+Before:
+ Save g:ale_v_v_executable
+
+ call ale#assert#SetUpLinterTest('v', 'v')
+
+ GivenCommandOutput ['/foo/bar', '/foo/baz']
+
+After:
+ Restore
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command should be correct):
+ AssertLinter 'v', 'v . -o /tmp/vim-ale-v'
+
+Execute(Extra options should be supported):
+ let g:ale_v_v_options = '--foo-bar'
+
+ AssertLinter 'v', 'v --foo-bar . -o /tmp/vim-ale-v'
+
+ let g:ale_v_vbuild_options = ''
+
+Execute(The executable should be configurable):
+ let g:ale_v_v_executable = 'foobar'
+
+ AssertLinter 'foobar', 'foobar . -o /tmp/vim-ale-v'
diff --git a/test/v_files/testfile.v b/test/v_files/testfile.v
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/v_files/testfile.v