mirror of
https://github.com/dense-analysis/ale.git
synced 2025-12-06 12:44:23 +08:00
Prefer ale_root setting for project roots
This commit is contained in:
@@ -36,7 +36,7 @@ function! ale_linters#python#pylsp#GetCwd(buffer) abort
|
||||
\ 'name': 'pylsp',
|
||||
\ 'project_root': function('ale#python#FindProjectRoot'),
|
||||
\}
|
||||
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, l:fake_linter)
|
||||
let l:root = ale#linter#GetRoot(a:buffer, l:fake_linter)
|
||||
|
||||
return !empty(l:root) ? l:root : v:null
|
||||
endfunction
|
||||
|
||||
@@ -13,7 +13,7 @@ function! ale_linters#python#pyright#GetCwd(buffer) abort
|
||||
\ 'name': 'pyright',
|
||||
\ 'project_root': function('ale#python#FindProjectRoot'),
|
||||
\}
|
||||
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, l:fake_linter)
|
||||
let l:root = ale#linter#GetRoot(a:buffer, l:fake_linter)
|
||||
|
||||
return !empty(l:root) ? l:root : v:null
|
||||
endfunction
|
||||
|
||||
@@ -216,7 +216,7 @@ endfunction
|
||||
function! ale#assert#LSPProject(expected_root) abort
|
||||
let l:buffer = bufnr('')
|
||||
let l:linter = s:GetLinter()
|
||||
let l:root = ale#lsp_linter#FindProjectRoot(l:buffer, l:linter)
|
||||
let l:root = ale#linter#GetRoot(l:buffer, l:linter)
|
||||
|
||||
AssertEqual a:expected_root, l:root
|
||||
endfunction
|
||||
|
||||
@@ -447,3 +447,32 @@ function! ale#linter#GetAddress(buffer, linter) abort
|
||||
|
||||
return type(l:Address) is v:t_func ? l:Address(a:buffer) : l:Address
|
||||
endfunction
|
||||
|
||||
" Get the project root for a linter.
|
||||
" If |b:ale_root| or |g:ale_root| is set to either a String or a Dict mapping
|
||||
" linter names to roots or callbacks, return that value immediately. When no
|
||||
" value is available, fall back to the linter-specific configuration.
|
||||
function! ale#linter#GetRoot(buffer, linter) abort
|
||||
let l:buffer_ale_root = getbufvar(a:buffer, 'ale_root', {})
|
||||
|
||||
if type(l:buffer_ale_root) is v:t_string
|
||||
return l:buffer_ale_root
|
||||
endif
|
||||
|
||||
if has_key(l:buffer_ale_root, a:linter.name)
|
||||
let l:Root = l:buffer_ale_root[a:linter.name]
|
||||
return type(l:Root) is v:t_func ? l:Root(a:buffer) : l:Root
|
||||
endif
|
||||
|
||||
if has_key(g:ale_root, a:linter.name)
|
||||
let l:Root = g:ale_root[a:linter.name]
|
||||
return type(l:Root) is v:t_func ? l:Root(a:buffer) : l:Root
|
||||
endif
|
||||
|
||||
if has_key(a:linter, 'project_root')
|
||||
let l:Root = a:linter.project_root
|
||||
return type(l:Root) is v:t_func ? l:Root(a:buffer) : l:Root
|
||||
endif
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
@@ -296,44 +296,6 @@ function! ale#lsp_linter#GetConfig(buffer, linter) abort
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
function! ale#lsp_linter#FindProjectRoot(buffer, linter) abort
|
||||
let l:buffer_ale_root = getbufvar(a:buffer, 'ale_root', {})
|
||||
|
||||
if type(l:buffer_ale_root) is v:t_string
|
||||
return l:buffer_ale_root
|
||||
endif
|
||||
|
||||
" Try to get a buffer-local setting for the root
|
||||
if has_key(l:buffer_ale_root, a:linter.name)
|
||||
let l:Root = l:buffer_ale_root[a:linter.name]
|
||||
|
||||
if type(l:Root) is v:t_func
|
||||
return l:Root(a:buffer)
|
||||
else
|
||||
return l:Root
|
||||
endif
|
||||
endif
|
||||
|
||||
" Try to get a global setting for the root
|
||||
if has_key(g:ale_root, a:linter.name)
|
||||
let l:Root = g:ale_root[a:linter.name]
|
||||
|
||||
if type(l:Root) is v:t_func
|
||||
return l:Root(a:buffer)
|
||||
else
|
||||
return l:Root
|
||||
endif
|
||||
endif
|
||||
|
||||
" Fall back to the linter-specific configuration
|
||||
if has_key(a:linter, 'project_root')
|
||||
let l:Root = a:linter.project_root
|
||||
|
||||
return type(l:Root) is v:t_func ? l:Root(a:buffer) : l:Root
|
||||
endif
|
||||
|
||||
return ale#util#GetFunction(a:linter.project_root_callback)(a:buffer)
|
||||
endfunction
|
||||
|
||||
" This function is accessible so tests can call it.
|
||||
function! ale#lsp_linter#OnInit(linter, details, Callback) abort
|
||||
@@ -504,7 +466,7 @@ endfunction
|
||||
function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
|
||||
let l:command = ''
|
||||
let l:address = ''
|
||||
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, a:linter)
|
||||
let l:root = ale#linter#GetRoot(a:buffer, a:linter)
|
||||
|
||||
if empty(l:root) && a:linter.lsp isnot# 'tsserver'
|
||||
" If there's no project root, then we can't check files with LSP,
|
||||
|
||||
@@ -61,6 +61,12 @@ endfunction
|
||||
" through paths, including the current directory, until no __init__.py files
|
||||
" is found.
|
||||
function! ale#python#FindProjectRoot(buffer) abort
|
||||
let l:root = ale#linter#GetRoot(a:buffer, {'name': 'python'})
|
||||
|
||||
if !empty(l:root)
|
||||
return l:root
|
||||
endif
|
||||
|
||||
let l:ini_root = ale#python#FindProjectRootIni(a:buffer)
|
||||
|
||||
if !empty(l:ini_root)
|
||||
|
||||
@@ -55,6 +55,9 @@ For some linters, ALE will search for a Python project root by looking at the
|
||||
files in directories on or above where a file being checked is. ALE applies
|
||||
the following methods, in order:
|
||||
|
||||
If |g:ale_root| or |b:ale_root| provides a value, that value is used as the
|
||||
project root instead and the searching described below is skipped.
|
||||
|
||||
1. Find the first directory containing a common Python configuration file.
|
||||
2. If no configuration file can be found, use the first directory which does
|
||||
not contain a readable file named `__init__.py`.
|
||||
|
||||
17
doc/ale.txt
17
doc/ale.txt
@@ -2297,17 +2297,18 @@ g:ale_root
|
||||
Type: |Dictionary| or |String|
|
||||
Default: `{}`
|
||||
|
||||
This option is used to determine the project root for a linter. If the value
|
||||
is a |Dictionary|, it maps a linter to either a |String| containing the
|
||||
project root or a |Funcref| to call to look up the root. The |Funcref| is
|
||||
provided the buffer number as its argument.
|
||||
This option is used to determine the project root for a linter. When set to a
|
||||
|String| it will be used for all linters. When set to a |Dictionary|, the
|
||||
keys are linter names and the values are either |Strings| containing project
|
||||
roots or |Funcref|s which are passed the buffer number.
|
||||
|
||||
The buffer-specific variable may additionally be a string containing the
|
||||
The buffer-specific variable may additionally be a |String| containing the
|
||||
project root itself.
|
||||
|
||||
If neither variable yields a result, a linter-specific function is invoked to
|
||||
detect a project root. If this, too, yields no result, and the linter is an
|
||||
LSP linter, it will not run.
|
||||
If a value can be found from either variable, ALE uses it directly and skips
|
||||
searching for a project root. If no value is found, a linter-specific
|
||||
function is invoked to detect a project root. If this, too, yields no result
|
||||
and the linter is an LSP linter, it will not run.
|
||||
|
||||
*ale-options.save_hidden*
|
||||
*g:ale_save_hidden*
|
||||
|
||||
@@ -407,7 +407,7 @@ Execute(PreProcess should allow the `project_root` to be set as a String):
|
||||
\ 'project_root': '/foo/bar',
|
||||
\})
|
||||
|
||||
AssertEqual '/foo/bar', ale#lsp_linter#FindProjectRoot(0, g:linter)
|
||||
AssertEqual '/foo/bar', ale#linter#GetRoot(0, g:linter)
|
||||
|
||||
Execute(PreProcess should `project_root` be set as a Function):
|
||||
let g:linter = ale#linter#PreProcess('testft', {
|
||||
@@ -418,7 +418,7 @@ Execute(PreProcess should `project_root` be set as a Function):
|
||||
\ 'project_root': {-> '/foo/bar'},
|
||||
\})
|
||||
|
||||
AssertEqual '/foo/bar', ale#lsp_linter#FindProjectRoot(0, g:linter)
|
||||
AssertEqual '/foo/bar', ale#linter#GetRoot(0, g:linter)
|
||||
|
||||
Execute(PreProcess should complain when `project_root` is invalid):
|
||||
AssertThrows call ale#linter#PreProcess('testft', {
|
||||
|
||||
27
test/test_python_root_option.vader
Normal file
27
test/test_python_root_option.vader
Normal file
@@ -0,0 +1,27 @@
|
||||
Before:
|
||||
Save g:ale_root
|
||||
Save b:ale_root
|
||||
call ale#test#SetDirectory('/testplugin/test')
|
||||
|
||||
After:
|
||||
Restore
|
||||
call ale#test#RestoreDirectory()
|
||||
|
||||
Execute(The global setting is used as the project root):
|
||||
let g:ale_root = '/foo/python'
|
||||
call ale#test#SetFilename('test-files/python/no_virtualenv/subdir/foo/bar.py')
|
||||
AssertEqual '/foo/python', ale#python#FindProjectRoot(bufnr(''))
|
||||
|
||||
Execute(The buffer setting overrides the global setting):
|
||||
let g:ale_root = '/foo/python'
|
||||
let b:ale_root = '/bar/python'
|
||||
call ale#test#SetFilename('test-files/python/no_virtualenv/subdir/foo/bar.py')
|
||||
AssertEqual '/bar/python', ale#python#FindProjectRoot(bufnr(''))
|
||||
|
||||
Execute(Fallback to searching when no setting is used):
|
||||
unlet! g:ale_root
|
||||
unlet! b:ale_root
|
||||
call ale#test#SetFilename('test-files/python/no_virtualenv/subdir/foo/bar.py')
|
||||
AssertEqual \
|
||||
\ ale#path#Simplify(g:dir . '/../test-files/python/no_virtualenv/subdir'),
|
||||
\ ale#python#FindProjectRoot(bufnr(''))
|
||||
Reference in New Issue
Block a user