mirror of
https://github.com/dense-analysis/ale.git
synced 2025-12-07 13:14:29 +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',
|
\ 'name': 'pylsp',
|
||||||
\ 'project_root': function('ale#python#FindProjectRoot'),
|
\ '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
|
return !empty(l:root) ? l:root : v:null
|
||||||
endfunction
|
endfunction
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function! ale_linters#python#pyright#GetCwd(buffer) abort
|
|||||||
\ 'name': 'pyright',
|
\ 'name': 'pyright',
|
||||||
\ 'project_root': function('ale#python#FindProjectRoot'),
|
\ '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
|
return !empty(l:root) ? l:root : v:null
|
||||||
endfunction
|
endfunction
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ endfunction
|
|||||||
function! ale#assert#LSPProject(expected_root) abort
|
function! ale#assert#LSPProject(expected_root) abort
|
||||||
let l:buffer = bufnr('')
|
let l:buffer = bufnr('')
|
||||||
let l:linter = s:GetLinter()
|
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
|
AssertEqual a:expected_root, l:root
|
||||||
endfunction
|
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
|
return type(l:Address) is v:t_func ? l:Address(a:buffer) : l:Address
|
||||||
endfunction
|
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 {}
|
return {}
|
||||||
endfunction
|
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.
|
" This function is accessible so tests can call it.
|
||||||
function! ale#lsp_linter#OnInit(linter, details, Callback) abort
|
function! ale#lsp_linter#OnInit(linter, details, Callback) abort
|
||||||
@@ -504,7 +466,7 @@ endfunction
|
|||||||
function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
|
function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
|
||||||
let l:command = ''
|
let l:command = ''
|
||||||
let l:address = ''
|
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 empty(l:root) && a:linter.lsp isnot# 'tsserver'
|
||||||
" If there's no project root, then we can't check files with LSP,
|
" 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
|
" through paths, including the current directory, until no __init__.py files
|
||||||
" is found.
|
" is found.
|
||||||
function! ale#python#FindProjectRoot(buffer) abort
|
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)
|
let l:ini_root = ale#python#FindProjectRootIni(a:buffer)
|
||||||
|
|
||||||
if !empty(l:ini_root)
|
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
|
files in directories on or above where a file being checked is. ALE applies
|
||||||
the following methods, in order:
|
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.
|
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
|
2. If no configuration file can be found, use the first directory which does
|
||||||
not contain a readable file named `__init__.py`.
|
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|
|
Type: |Dictionary| or |String|
|
||||||
Default: `{}`
|
Default: `{}`
|
||||||
|
|
||||||
This option is used to determine the project root for a linter. If the value
|
This option is used to determine the project root for a linter. When set to a
|
||||||
is a |Dictionary|, it maps a linter to either a |String| containing the
|
|String| it will be used for all linters. When set to a |Dictionary|, the
|
||||||
project root or a |Funcref| to call to look up the root. The |Funcref| is
|
keys are linter names and the values are either |Strings| containing project
|
||||||
provided the buffer number as its argument.
|
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.
|
project root itself.
|
||||||
|
|
||||||
If neither variable yields a result, a linter-specific function is invoked to
|
If a value can be found from either variable, ALE uses it directly and skips
|
||||||
detect a project root. If this, too, yields no result, and the linter is an
|
searching for a project root. If no value is found, a linter-specific
|
||||||
LSP linter, it will not run.
|
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*
|
*ale-options.save_hidden*
|
||||||
*g:ale_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',
|
\ '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):
|
Execute(PreProcess should `project_root` be set as a Function):
|
||||||
let g:linter = ale#linter#PreProcess('testft', {
|
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'},
|
\ '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):
|
Execute(PreProcess should complain when `project_root` is invalid):
|
||||||
AssertThrows call ale#linter#PreProcess('testft', {
|
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