Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ruff use json-lines output format #4656

Merged
merged 3 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions ale_linters/python/ruff.vim
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,25 @@ function! ale_linters#python#ruff#GetCommand(buffer, version) abort

" NOTE: ruff version `0.0.69` supports liniting input from stdin
" NOTE: ruff version `0.1.0` deprecates `--format text`
return ale#Escape(l:executable) . l:exec_args
return ale#Escape(l:executable) . l:exec_args . ' -q'
\ . ale#Pad(ale#Var(a:buffer, 'python_ruff_options'))
\ . (ale#semver#GTE(a:version, [0, 1, 0]) ? ' --output-format text' : ' --format text')
\ . (ale#semver#GTE(a:version, [0, 1, 0]) ? ' --output-format json-lines' : ' --format json-lines')
\ . (ale#semver#GTE(a:version, [0, 0, 69]) ? ' --stdin-filename %s -' : ' %s')
endfunction

function! ale_linters#python#ruff#Handle(buffer, lines) abort
"Example: path/to/file.py:10:5: E999 SyntaxError: unexpected indent
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.+)$'
let l:output = []

for l:match in ale#util#GetMatches(a:lines, l:pattern)
for l:line in a:lines
let l:item = json_decode(l:line)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\ 'lnum': l:item.location.row,
\ 'col': l:item.location.column,
\ 'end_lnum': l:item.end_location.row,
\ 'end_col': l:item.end_location.column - 1,
\ 'code': l:item.code,
\ 'text': l:item.message,
\ 'type': l:item.code =~? '\vE\d+' ? 'E' : 'W',
\})
endfor

Expand Down
35 changes: 18 additions & 17 deletions test/linter/test_ruff.vader
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Before:
call ale#assert#SetUpLinterTest('python', 'ruff')

let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
let b:command_tail = ' --format text --stdin-filename %s -'
let b:command_head = ale#Escape('ruff') . ' -q'
let b:command_tail = ' --format json-lines --stdin-filename %s -'

GivenCommandOutput ['ruff 0.0.83']

Expand All @@ -19,93 +20,93 @@ After:

Execute(The ruff callbacks should return the correct default values):
AssertLinterCwd expand('%:p:h')
AssertLinter 'ruff', ale#Escape('ruff') . b:command_tail
AssertLinter 'ruff', b:command_head . b:command_tail

Execute(ruff should run with the file path of buffer in old versions):
" version `0.0.69` supports liniting input from stdin
GivenCommandOutput ['ruff 0.0.68']

AssertLinterCwd expand('%:p:h')
AssertLinter 'ruff', ale#Escape('ruff') . b:command_tail[:-23] . ' %s'
AssertLinter 'ruff', b:command_head . b:command_tail[:-23] . ' %s'

Execute(ruff should run with the --output-format flag in new versions):
GivenCommandOutput ['ruff 0.1.0']

AssertLinterCwd expand('%:p:h')
AssertLinter 'ruff', ale#Escape('ruff') . ' --output-format text --stdin-filename %s -'
AssertLinter 'ruff', b:command_head . ' --output-format json-lines --stdin-filename %s -'

Execute(ruff should run with the stdin in new enough versions):
GivenCommandOutput ['ruff 0.0.83']

AssertLinterCwd expand('%:p:h')
AssertLinter 'ruff', ale#Escape('ruff') . b:command_tail[:-3] . ' -'
" AssertLinter 'ruff', ale#Escape('ruff') . b:command_tail[:-3] . '--format text -'
AssertLinter 'ruff', b:command_head . b:command_tail[:-3] . ' -'
" AssertLinter 'ruff', b:command_head . b:command_tail[:-3] . '--format json-lines -'

Execute(The option for disabling changing directories should work):
let g:ale_python_ruff_change_directory = 0

AssertLinterCwd ''
AssertLinter 'ruff', ale#Escape('ruff') . b:command_tail
AssertLinter 'ruff', b:command_head . b:command_tail

Execute(The ruff executable should be configurable, and escaped properly):
let g:ale_python_ruff_executable = 'executable with spaces'

AssertLinter 'executable with spaces', ale#Escape('executable with spaces') . b:command_tail
AssertLinter 'executable with spaces', ale#Escape('executable with spaces') . ' -q' . b:command_tail

Execute(The ruff command callback should let you set options):
let g:ale_python_ruff_options = '--some-flag'
AssertLinter 'ruff', ale#Escape('ruff') . ' --some-flag' . b:command_tail
AssertLinter 'ruff', b:command_head . ' --some-flag' . b:command_tail

let g:ale_python_ruff_options = '--some-option value'
AssertLinter 'ruff', ale#Escape('ruff') . ' --some-option value' . b:command_tail
AssertLinter 'ruff', b:command_head . ' --some-option value' . b:command_tail

Execute(The ruff 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 'ruff', ale#Escape('ruff') . b:command_tail
AssertLinter 'ruff', b:command_head . b:command_tail

Execute(The ruff 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 . '/ruff'
\)
AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
AssertLinter b:executable, ale#Escape(b:executable) . b:command_tail
AssertLinter b:executable, ale#Escape(b:executable) . ' -q' . b:command_tail

Execute(You should able able to use the global ruff instead):
call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py')
let g:ale_python_ruff_use_global = 1

AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/with_virtualenv/subdir')
AssertLinter 'ruff', ale#Escape('ruff') . b:command_tail
AssertLinter 'ruff', b:command_head . b:command_tail

Execute(Setting executable to 'pipenv' appends 'run ruff'):
let g:ale_python_ruff_executable = 'path/to/pipenv'
let g:ale_python_ruff_use_global = 1

AssertLinter 'path/to/pipenv', ale#Escape('path/to/pipenv') . ' run ruff'
AssertLinter 'path/to/pipenv', ale#Escape('path/to/pipenv') . ' run ruff -q'
\ . b:command_tail

Execute(Pipenv is detected when python_ruff_auto_pipenv is set):
let g:ale_python_ruff_auto_pipenv = 1
call ale#test#SetFilename('../test-files/python/pipenv/whatever.py')

AssertLinterCwd expand('%:p:h')
AssertLinter 'pipenv', ale#Escape('pipenv') . ' run ruff'
AssertLinter 'pipenv', ale#Escape('pipenv') . ' run ruff -q'
\ . b:command_tail

Execute(Setting executable to 'poetry' appends 'run ruff'):
let g:ale_python_ruff_executable = 'path/to/poetry'
let g:ale_python_ruff_use_global = 1

AssertLinter 'path/to/poetry', ale#Escape('path/to/poetry') . ' run ruff'
AssertLinter 'path/to/poetry', ale#Escape('path/to/poetry') . ' run ruff -q'
\ . b:command_tail

Execute(poetry is detected when python_ruff_auto_poetry is set):
let g:ale_python_ruff_auto_poetry = 1
call ale#test#SetFilename('../test-files/python/poetry/whatever.py')

AssertLinterCwd expand('%:p:h')
AssertLinter 'poetry', ale#Escape('poetry') . ' run ruff'
AssertLinter 'poetry', ale#Escape('poetry') . ' run ruff -q'
\ . b:command_tail