Skip to content

Commit

Permalink
Set working directory for Elvis linter (#4726)
Browse files Browse the repository at this point in the history
Most of the time it works to assume that the current working
directory is the root of the project.  However, this is not the case
for Rebar3 checked out dependencies, for example.

It's also worth noting that because of the way Elvis handles file
patterns, and because directories in configuration are relative to the
project root, the path supplied to command must be also relative.
  • Loading branch information
dmitrivereshchagin committed Feb 24, 2024
1 parent 5e8904c commit b74cd02
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 5 deletions.
23 changes: 21 additions & 2 deletions ale_linters/erlang/elvis.vim
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,34 @@ function! s:AbbreviateMessage(text) abort
endfunction

function! s:GetCommand(buffer) abort
let l:file = ale#Escape(expand('#' . a:buffer . ':.'))
let l:cwd = s:GetCwd(a:buffer)

return '%e rock --output-format=parsable ' . l:file
let l:file = !empty(l:cwd)
\ ? expand('#' . a:buffer . ':p')[len(l:cwd) + 1:]
\ : expand('#' . a:buffer . ':.')

return '%e rock --output-format=parsable ' . ale#Escape(l:file)
endfunction

function! s:GetCwd(buffer) abort
let l:markers = ['elvis.config', 'rebar.lock', 'erlang.mk']

for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
for l:marker in l:markers
if filereadable(l:path . '/' . l:marker)
return l:path
endif
endfor
endfor

return ''
endfunction

call ale#linter#Define('erlang', {
\ 'name': 'elvis',
\ 'callback': 'ale_linters#erlang#elvis#Handle',
\ 'executable': {b -> ale#Var(b, 'erlang_elvis_executable')},
\ 'command': function('s:GetCommand'),
\ 'cwd': function('s:GetCwd'),
\ 'lint_file': 1,
\})
42 changes: 39 additions & 3 deletions test/linter/test_erlang_elvis.vader
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@
Before:
let b:file = fnamemodify(bufname(''), ':.')
call ale#assert#SetUpLinterTest('erlang', 'elvis')

After:
unlet! b:root

call ale#assert#TearDownLinterTest()

Execute(Default command should be correct):
AssertLinter 'elvis',
\ ale#Escape('elvis') . ' rock --output-format=parsable ' . ale#Escape(b:file)
\ ale#Escape('elvis') . ' rock --output-format=parsable '
\ . ale#Escape(expand('%:.'))

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)
\ ale#Escape('/path/to/elvis') . ' rock --output-format=parsable '
\ . ale#Escape(expand('%:.'))

Execute(Project root should be detected using elvis.config):
let b:root = '../test-files/erlang/app_with_elvis_config'

call ale#test#SetFilename(b:root . '/src/app.erl')
AssertLinter 'elvis',
\ ale#Escape('elvis') . ' rock --output-format=parsable '
\ . ale#Escape(ale#path#Simplify('src/app.erl'))
AssertLinterCwd ale#test#GetFilename(b:root)

Execute(Root of Rebar3 project should be detected):
let b:root = '../test-files/erlang/rebar3_app'

call ale#test#SetFilename(b:root . '/src/app.erl')
AssertLinter 'elvis',
\ ale#Escape('elvis') . ' rock --output-format=parsable '
\ . ale#Escape(ale#path#Simplify('src/app.erl'))
AssertLinterCwd ale#test#GetFilename(b:root)

call ale#test#SetFilename(b:root . '/_checkouts/dep/src/dep.erl')
AssertLinter 'elvis',
\ ale#Escape('elvis') . ' rock --output-format=parsable '
\ . ale#Escape(ale#path#Simplify('src/dep.erl'))
AssertLinterCwd ale#test#GetFilename(b:root . '/_checkouts/dep')

Execute(Root of Erlang.mk project should be detected):
let b:root = '../test-files/erlang/erlang_mk_app'

call ale#test#SetFilename(b:root . '/src/app.erl')
AssertLinter 'elvis',
\ ale#Escape('elvis') . ' rock --output-format=parsable '
\ . ale#Escape(ale#path#Simplify('src/app.erl'))
AssertLinterCwd ale#test#GetFilename(b:root)
Empty file.

0 comments on commit b74cd02

Please sign in to comment.