diff --git a/ale_linters/typescript/tslint.vim b/ale_linters/typescript/tslint.vim index 0e4149a..34499fe 100644 --- a/ale_linters/typescript/tslint.vim +++ b/ale_linters/typescript/tslint.vim @@ -12,27 +12,19 @@ function! ale_linters#typescript#tslint#GetExecutable(buffer) abort endfunction function! ale_linters#typescript#tslint#Handle(buffer, lines) abort - " Matches patterns like the following: - " - " WARNING: hello.ts[113, 6]: Unnecessary semicolon - " ERROR: hello.ts[133, 10]: Missing semicolon - - let l:ext = '.' . fnamemodify(bufname(a:buffer), ':e') - let l:pattern = '\<\(WARNING\|ERROR\)\>: .\+' . l:ext . '\[\(\d\+\), \(\d\+\)\]: \(.\+\)' let l:output = [] - for l:match in ale#util#GetMatches(a:lines, l:pattern) - let l:type = l:match[1] - let l:line = l:match[2] + 0 - let l:column = l:match[3] + 0 - let l:text = l:match[4] - - call add(l:output, { - \ 'type': (l:type ==# 'WARNING' ? 'W' : 'E'), - \ 'lnum': l:line, - \ 'col': l:column, - \ 'text': l:text, - \}) + for l:error in json_decode(join(a:lines, '')) + if ale#path#IsBufferPath(a:buffer, l:error.name) + call add(l:output, { + \ 'type': (l:error.ruleSeverity ==# 'WARNING' ? 'W' : 'E'), + \ 'text': l:error.failure, + \ 'lnum': l:error.startPosition.line + 1, + \ 'col': l:error.startPosition.position + 1, + \ 'end_lnum': l:error.endPosition.line + 1, + \ 'end_col': l:error.endPosition.position + 1, + \}) + endif endfor return l:output @@ -46,11 +38,12 @@ function! ale_linters#typescript#tslint#BuildLintCommand(buffer) abort \) let l:tslint_config_option = !empty(l:tslint_config_path) - \ ? '-c ' . ale#Escape(l:tslint_config_path) + \ ? ' -c ' . ale#Escape(l:tslint_config_path) \ : '' return ale_linters#typescript#tslint#GetExecutable(a:buffer) - \ . ' ' . l:tslint_config_option + \ . ' --format json' + \ . l:tslint_config_option \ . ' %t' endfunction diff --git a/autoload/ale/path.vim b/autoload/ale/path.vim index e8a5de2..2c1d513 100644 --- a/autoload/ale/path.vim +++ b/autoload/ale/path.vim @@ -78,6 +78,16 @@ function! ale#path#IsBufferPath(buffer, complex_filename) abort let l:test_filename = l:test_filename[2:] endif + if l:test_filename[:1] ==# '..' + " Remove ../../ etc. from the front of the path. + let l:test_filename = substitute(l:test_filename, '\v^(\.\.[/\\])+', '/', '') + endif + + " Use the basename for files in /tmp, as they are likely our files. + if l:test_filename[:len($TMPDIR) - 1] ==# $TMPDIR + let l:test_filename = fnamemodify(l:test_filename, ':t') + endif + let l:buffer_filename = expand('#' . a:buffer . ':p') return l:buffer_filename ==# l:test_filename diff --git a/test/handler/test_tslint_handler.vader b/test/handler/test_tslint_handler.vader index 92ed705..cf6ea4e 100644 --- a/test/handler/test_tslint_handler.vader +++ b/test/handler/test_tslint_handler.vader @@ -1,41 +1,99 @@ Before: runtime ale_linters/typescript/tslint.vim + silent! cd /testplugin/test/handler + let g:dir = getcwd() + +After: + silent execute 'cd ' . fnameescape(g:dir) + unlet! g:dir + + call ale#linter#Reset() + Execute(The tslint handler should parse lines correctly): + call ale#test#SetFilename('app/test.ts') + AssertEqual \ [ \ { - \ 'lnum': 235, - \ 'col': 21, - \ 'text': 'unused expression, expected an assignment or function call', - \ 'type': 'W', - \ }, - \ { - \ 'lnum': 35, - \ 'col': 6, + \ 'lnum': 1, + \ 'col': 15, + \ 'end_lnum': 1, + \ 'end_col': 15, \ 'text': 'Missing semicolon', \ 'type': 'E', \ }, \ { - \ 'lnum': 147, - \ 'col': 10, - \ 'text': 'Unnecessary semicolon', + \ 'lnum': 2, + \ 'col': 15, + \ 'end_lnum': 3, + \ 'end_col': 23, + \ 'text': 'Something else', \ 'type': 'W', \ }, - \ { - \ 'lnum': 101, - \ 'col': 25, - \ 'text': 'Unnecessary trailing comma', - \ 'type': 'E', - \ }, \ ], - \ ale_linters#typescript#tslint#Handle(347, [ - \ 'This line should be ignored completely', - \ 'WARNING: hello.ts[235, 21]: unused expression, expected an assignment or function call', - \ 'ERROR: hello.ts[35, 6]: Missing semicolon', - \ 'WARNING: hello.ts[147, 10]: Unnecessary semicolon', - \ 'ERROR: hello.ts[101, 25]: Unnecessary trailing comma' - \ ]) - -After: - call ale#linter#Reset() + \ ale_linters#typescript#tslint#Handle(bufnr(''), [json_encode([ + \ { + \ 'endPosition': { + \ 'character': 14, + \ 'line': 0, + \ 'position': 14 + \ }, + \ 'failure': 'Missing semicolon', + \ 'fix': { + \ 'innerLength': 0, + \ 'innerStart': 14, + \ 'innerText': ';' + \ }, + \ 'name': 'app/test.ts', + \ 'ruleName': 'semicolon', + \ 'ruleSeverity': 'ERROR', + \ 'startPosition': { + \ 'character': 14, + \ 'line': 0, + \ 'position': 14 + \ } + \ }, + \ { + \ 'endPosition': { + \ 'character': 11, + \ 'line': 2, + \ 'position': 22 + \ }, + \ 'failure': 'Something else', + \ 'fix': { + \ 'innerLength': 0, + \ 'innerStart': 14, + \ 'innerText': ';' + \ }, + \ 'name': 'app/test.ts', + \ 'ruleName': 'something', + \ 'ruleSeverity': 'WARNING', + \ 'startPosition': { + \ 'character': 7, + \ 'line': 1, + \ 'position': 14 + \ } + \ }, + \ { + \ 'endPosition': { + \ 'character': 11, + \ 'line': 2, + \ 'position': 22 + \ }, + \ 'failure': 'Something else', + \ 'fix': { + \ 'innerLength': 0, + \ 'innerStart': 14, + \ 'innerText': ';' + \ }, + \ 'name': 'app/something-else.ts', + \ 'ruleName': 'something', + \ 'ruleSeverity': 'WARNING', + \ 'startPosition': { + \ 'character': 7, + \ 'line': 1, + \ 'position': 14 + \ } + \ }, + \])]) diff --git a/test/test_path_equality.vader b/test/test_path_equality.vader index 7043eb5..78af562 100644 --- a/test/test_path_equality.vader +++ b/test/test_path_equality.vader @@ -1,8 +1,13 @@ Execute(ale#path#IsBufferPath should match simple relative paths): - silent file! foo.txt + call ale#test#SetFilename('app/foo.txt') - Assert ale#path#IsBufferPath(bufnr(''), 'foo.txt'), 'No match for foo.txt' - Assert !ale#path#IsBufferPath(bufnr(''), 'bar.txt'), 'Bad match for bar.txt' + Assert ale#path#IsBufferPath(bufnr(''), 'app/foo.txt'), 'No match for foo.txt' + Assert !ale#path#IsBufferPath(bufnr(''), 'app/bar.txt'), 'Bad match for bar.txt' + +Execute(ale#path#IsBufferPath should match relative paths with dots): + call ale#test#SetFilename('app/foo.txt') + + Assert ale#path#IsBufferPath(bufnr(''), '../../app/foo.txt'), 'No match for ../../app/foo.txt' Execute(ale#path#IsBufferPath should match absolute paths): silent file! foo.txt @@ -30,3 +35,9 @@ Execute(ale#path#IsBufferPath should accept various names for stdin): Assert ale#path#IsBufferPath(bufnr(''), 'stdin') Assert ale#path#IsBufferPath(bufnr(''), '') Assert ale#path#IsBufferPath(bufnr(''), '') + +Execute(ale#path#IsBufferPath should match files in /tmp): + call ale#test#SetFilename('app/test.ts') + + Assert ale#path#IsBufferPath(bufnr(''), '../../../../../../../../tmp/vG0hKyD/1/test.ts') + Assert ale#path#IsBufferPath(bufnr(''), '/tmp/vG0hKyD/1/test.ts')