summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorw0rp <devw0rp@gmail.com>2018-04-08 17:17:30 +0100
committerw0rp <devw0rp@gmail.com>2018-04-08 17:17:46 +0100
commit91d7e81ebc08581fc0339c939c0adecaa590f2f7 (patch)
tree3773dfccbeb678de38c75923e30654f7e67711e2
parent121e806423830fa9e6bc1c7833f0624bd06903ff (diff)
downloadale-91d7e81ebc08581fc0339c939c0adecaa590f2f7.zip
Fix #605 - Support `vcol: 1` for multi-byte character positions
-rw-r--r--autoload/ale/engine.vim16
-rw-r--r--autoload/ale/util.vim10
-rw-r--r--doc/ale.txt7
-rw-r--r--test/test_loclist_corrections.vader32
4 files changed, 63 insertions, 2 deletions
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim
index dd871c36..0704fd5b 100644
--- a/autoload/ale/engine.vim
+++ b/autoload/ale/engine.vim
@@ -393,7 +393,7 @@ function! ale#engine#FixLocList(buffer, linter_name, loclist) abort
\ 'text': l:old_item.text,
\ 'lnum': str2nr(l:old_item.lnum),
\ 'col': str2nr(get(l:old_item, 'col', 0)),
- \ 'vcol': get(l:old_item, 'vcol', 0),
+ \ 'vcol': 0,
\ 'type': get(l:old_item, 'type', 'E'),
\ 'nr': get(l:old_item, 'nr', -1),
\ 'linter_name': a:linter_name,
@@ -453,6 +453,20 @@ function! ale#engine#FixLocList(buffer, linter_name, loclist) abort
" When errors go beyond the end of the file, put them at the end.
" This is only done for the current buffer.
let l:item.lnum = l:last_line_number
+ elseif get(l:old_item, 'vcol', 0)
+ " Convert virtual column positions to byte positions.
+ " The positions will be off if the buffer has changed recently.
+ let l:line = getbufline(a:buffer, l:item.lnum)[0]
+
+ let l:item.col = ale#util#Col(l:line, l:item.col)
+
+ if has_key(l:item, 'end_col')
+ let l:end_line = get(l:item, 'end_lnum', l:line) != l:line
+ \ ? getbufline(a:buffer, l:item.end_lnum)[0]
+ \ : l:line
+
+ let l:item.end_col = ale#util#Col(l:end_line, l:item.end_col)
+ endif
endif
call add(l:new_loclist, l:item)
diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim
index b94a11b7..e0b31e2c 100644
--- a/autoload/ale/util.vim
+++ b/autoload/ale/util.vim
@@ -311,3 +311,13 @@ function! ale#util#StopPartialTimer(timer_id) abort
call remove(s:partial_timers, a:timer_id)
endif
endfunction
+
+" Given a possibly multi-byte string and a 1-based character position on a
+" line, return the 1-based byte position on that line.
+function! ale#util#Col(str, chr) abort
+ if a:chr < 2
+ return a:chr
+ endif
+
+ return strlen(join(split(a:str, '\zs')[0:a:chr - 2], '')) + 1
+endfunction
diff --git a/doc/ale.txt b/doc/ale.txt
index 2e5c5e47..97f1b594 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -2072,6 +2072,13 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
key is also set with a valid number for some other
buffer.
`vcol` - Defaults to `0`.
+
+ If set to `1`, ALE will convert virtual column
+ positions for `col` and `end_col` to byte column
+ positions. If the buffer is changed in-between
+ checking it and displaying the results, the
+ calculated byte column positions will probably be
+ wrong.
`type` - Defaults to `'E'`.
`nr` - Defaults to `-1`.
diff --git a/test/test_loclist_corrections.vader b/test/test_loclist_corrections.vader
index 46c7e272..48aa1f78 100644
--- a/test/test_loclist_corrections.vader
+++ b/test/test_loclist_corrections.vader
@@ -52,7 +52,7 @@ Execute(FixLocList should use the values we supply):
\ 'lnum': 3,
\ 'col': 4,
\ 'bufnr': 10000,
- \ 'vcol': 1,
+ \ 'vcol': 0,
\ 'type': 'W',
\ 'nr': 42,
\ 'linter_name': 'foobar',
@@ -348,3 +348,33 @@ Execute(The error code should be passed on):
\ 'foobar',
\ [{'text': 'a', 'lnum': 11, 'code': 'some-code'}],
\ )
+
+Given(A file with Japanese multi-byte text):
+ はじめまして!
+ -私はワープです。
+Execute(character positions should be converted to byte positions):
+ AssertEqual
+ \ [
+ \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 0, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'},
+ \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 1, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'},
+ \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 4, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'},
+ \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'},
+ \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'end_col': 13, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'},
+ \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'end_col': 13, 'end_lnum': 1, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'},
+ \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 7, 'end_col': 17, 'end_lnum': 2, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'},
+ \ {'lnum': 2, 'bufnr': bufnr(''), 'col': 17, 'linter_name': 'foobar', 'nr': -1, 'type': 'E', 'vcol': 0, 'text': 'a'},
+ \],
+ \ ale#engine#FixLocList(
+ \ bufnr('%'),
+ \ 'foobar',
+ \ [
+ \ {'text': 'a', 'lnum': 1, 'col': 0, 'vcol': 1},
+ \ {'text': 'a', 'lnum': 1, 'col': 1, 'vcol': 1},
+ \ {'text': 'a', 'lnum': 1, 'col': 2, 'vcol': 1},
+ \ {'text': 'a', 'lnum': 1, 'col': 3, 'vcol': 1},
+ \ {'text': 'a', 'lnum': 1, 'col': 3, 'end_col': 5, 'vcol': 1},
+ \ {'text': 'a', 'lnum': 1, 'col': 3, 'end_col': 5, 'end_lnum': 1, 'vcol': 1},
+ \ {'text': 'a', 'lnum': 1, 'col': 3, 'end_col': 7, 'end_lnum': 2, 'vcol': 1},
+ \ {'text': 'a', 'lnum': 2, 'col': 7, 'vcol': 1},
+ \ ],
+ \ )