Adds hdl_checker LSP support (#2804)
* Added hdl_checker support * Added hdl_checker tests HDL Checker searches for files when no config file is found, which could lead to very long searches when the user is not really on a project setting
This commit is contained in:
parent
711c90c523
commit
5b3da60cea
13 changed files with 250 additions and 7 deletions
5
ale_linters/verilog/hdl_checker.vim
Normal file
5
ale_linters/verilog/hdl_checker.vim
Normal file
|
@ -0,0 +1,5 @@
|
|||
" Author: suoto <andre820@gmail.com>
|
||||
" Description: Adds support for HDL Code Checker, which wraps vcom/vlog, ghdl
|
||||
" or xvhdl. More info on https://github.com/suoto/hdl_checker
|
||||
|
||||
call ale#handlers#hdl_checker#DefineLinter('verilog')
|
5
ale_linters/vhdl/hdl_checker.vim
Normal file
5
ale_linters/vhdl/hdl_checker.vim
Normal file
|
@ -0,0 +1,5 @@
|
|||
" Author: suoto <andre820@gmail.com>
|
||||
" Description: Adds support for HDL Code Checker, which wraps vcom/vlog, ghdl
|
||||
" or xvhdl. More info on https://github.com/suoto/hdl_checker
|
||||
|
||||
call ale#handlers#hdl_checker#DefineLinter('vhdl')
|
71
autoload/ale/handlers/hdl_checker.vim
Normal file
71
autoload/ale/handlers/hdl_checker.vim
Normal file
|
@ -0,0 +1,71 @@
|
|||
" Author: suoto <andre820@gmail.com>
|
||||
" Description: Adds support for HDL Code Checker, which wraps vcom/vlog, ghdl
|
||||
" or xvhdl. More info on https://github.com/suoto/hdl_checker
|
||||
|
||||
call ale#Set('hdl_checker_executable', 'hdl_checker')
|
||||
call ale#Set('hdl_checker_config_file', has('unix') ? '.hdl_checker.config' : '_hdl_checker.config')
|
||||
call ale#Set('hdl_checker_options', '')
|
||||
|
||||
" Use this as a function so we can mock it on testing. Need to do this because
|
||||
" test files are inside /testplugin (which refers to the ale repo), which will
|
||||
" always have a .git folder
|
||||
function! ale#handlers#hdl_checker#IsDotGit(path) abort
|
||||
return ! empty(a:path) && isdirectory(a:path)
|
||||
endfunction
|
||||
|
||||
" Sould return (in order of preference)
|
||||
" 1. Nearest config file
|
||||
" 2. Nearest .git directory
|
||||
" 3. The current path
|
||||
function! ale#handlers#hdl_checker#GetProjectRoot(buffer) abort
|
||||
let l:project_root = ale#path#FindNearestFile(
|
||||
\ a:buffer,
|
||||
\ ale#Var(a:buffer, 'hdl_checker_config_file'))
|
||||
|
||||
if !empty(l:project_root)
|
||||
return fnamemodify(l:project_root, ':h')
|
||||
endif
|
||||
|
||||
" Search for .git to use as root
|
||||
let l:project_root = ale#path#FindNearestDirectory(a:buffer, '.git')
|
||||
|
||||
if ale#handlers#hdl_checker#IsDotGit(l:project_root)
|
||||
return fnamemodify(l:project_root, ':h:h')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! ale#handlers#hdl_checker#GetExecutable(buffer) abort
|
||||
return ale#Var(a:buffer, 'hdl_checker_executable')
|
||||
endfunction
|
||||
|
||||
function! ale#handlers#hdl_checker#GetCommand(buffer) abort
|
||||
let l:command = ale#Escape(ale#handlers#hdl_checker#GetExecutable(a:buffer)) . ' --lsp'
|
||||
|
||||
" Add extra parameters only if config has been set
|
||||
let l:options = ale#Var(a:buffer, 'hdl_checker_options')
|
||||
|
||||
if ! empty(l:options)
|
||||
let l:command = l:command . ' ' . l:options
|
||||
endif
|
||||
|
||||
return l:command
|
||||
endfunction
|
||||
|
||||
" To allow testing
|
||||
function! ale#handlers#hdl_checker#GetInitOptions(buffer) abort
|
||||
return {'project_file': ale#Var(a:buffer, 'hdl_checker_config_file')}
|
||||
endfunction
|
||||
|
||||
" Define the hdl_checker linter for a given filetype.
|
||||
function! ale#handlers#hdl_checker#DefineLinter(filetype) abort
|
||||
call ale#linter#Define(a:filetype, {
|
||||
\ 'name': 'hdl-checker',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'language': a:filetype,
|
||||
\ 'executable': function('ale#handlers#hdl_checker#GetExecutable'),
|
||||
\ 'command': function('ale#handlers#hdl_checker#GetCommand'),
|
||||
\ 'project_root': function('ale#handlers#hdl_checker#GetProjectRoot'),
|
||||
\ 'initialization_options': function('ale#handlers#hdl_checker#GetInitOptions'),
|
||||
\ })
|
||||
endfunction
|
||||
|
|
@ -3,7 +3,10 @@ ALE Verilog/SystemVerilog Integration *ale-verilog-options*
|
|||
|
||||
|
||||
===============================================================================
|
||||
ALE can use four different linters for Verilog HDL:
|
||||
ALE can use five different linters for Verilog HDL:
|
||||
|
||||
HDL Checker
|
||||
Using `hdl_checker --lsp`
|
||||
|
||||
iverilog:
|
||||
Using `iverilog -t null -Wall`
|
||||
|
@ -26,6 +29,9 @@ defining 'g:ale_linters' variable:
|
|||
\ let g:ale_linters = {'systemverilog' : ['verilator'],}
|
||||
<
|
||||
|
||||
===============================================================================
|
||||
General notes
|
||||
|
||||
Linters/compilers that utilize a "work" directory for analyzing designs- such
|
||||
as ModelSim and Vivado- can be passed the location of these directories as
|
||||
part of their respective option strings listed below. This is useful for
|
||||
|
@ -40,6 +46,16 @@ changing. This can happen in the form of hangs or crashes. To help prevent
|
|||
this when using these linters, it may help to run linting less frequently; for
|
||||
example, only when a file is saved.
|
||||
|
||||
HDL Checker is an alternative for some of the issues described above. It wraps
|
||||
around ghdl, Vivado and ModelSim/Questa and, when using the latter, it can
|
||||
handle mixed language (VHDL, Verilog, SystemVerilog) designs.
|
||||
|
||||
===============================================================================
|
||||
hdl-checker *ale-verilog-hdl-checker*
|
||||
|
||||
See |ale-vhdl-hdl-checker|
|
||||
|
||||
|
||||
===============================================================================
|
||||
iverilog *ale-verilog-iverilog*
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ ALE VHDL Integration *ale-vhdl-options*
|
|||
|
||||
|
||||
===============================================================================
|
||||
ALE can use three different linters for VHDL:
|
||||
ALE can use four different linters for VHDL:
|
||||
|
||||
iverilog:
|
||||
Using `iverilog -t null -Wall`
|
||||
ghdl:
|
||||
Using `ghdl --std=08`
|
||||
|
||||
ModelSim/Questa
|
||||
Using `vcom -2008 -quiet -lint`
|
||||
|
@ -14,8 +14,15 @@ ALE can use three different linters for VHDL:
|
|||
Vivado
|
||||
Using `xvhdl --2008`
|
||||
|
||||
Note all linters default to VHDL-2008 support. This, and other options, can be
|
||||
changed with each linter's respective option variable.
|
||||
HDL Checker
|
||||
Using `hdl_checker --lsp`
|
||||
|
||||
===============================================================================
|
||||
General notes
|
||||
|
||||
ghdl, ModelSim/Questa and Vivado linters default to VHDL-2008 support. This,
|
||||
and other options, can be changed with each linter's respective option
|
||||
variable.
|
||||
|
||||
Linters/compilers that utilize a "work" directory for analyzing designs- such
|
||||
as ModelSim and Vivado- can be passed the location of these directories as
|
||||
|
@ -31,6 +38,10 @@ changing. This can happen in the form of hangs or crashes. To help prevent
|
|||
this when using these linters, it may help to run linting less frequently; for
|
||||
example, only when a file is saved.
|
||||
|
||||
HDL Checker is an alternative for some of the issues described above. It wraps
|
||||
around ghdl, Vivado and ModelSim/Questa and, when using the latter, it can
|
||||
handle mixed language (VHDL, Verilog, SystemVerilog) designs.
|
||||
|
||||
===============================================================================
|
||||
ghdl *ale-vhdl-ghdl*
|
||||
|
||||
|
@ -50,6 +61,60 @@ g:ale_vhdl_ghdl_options *g:ale_vhdl_ghdl_options*
|
|||
This variable can be changed to modify the flags/options passed to 'ghdl'.
|
||||
|
||||
|
||||
===============================================================================
|
||||
hdl-checker *ale-vhdl-hdl-checker*
|
||||
|
||||
HDL Checker is a wrapper for VHDL/Verilg/SystemVerilog tools that aims to
|
||||
reduce the boilerplate code needed to set things up. It can automatically
|
||||
infer libraries for VHDL sources, determine the compilation order and provide
|
||||
some static checks.
|
||||
|
||||
You can install it using pip:
|
||||
>
|
||||
$ pip install hdl-checker
|
||||
|
||||
`hdl-checker` will be run from a detected project root, determined by the
|
||||
following methods, in order:
|
||||
|
||||
1. Find the first directory containing a configuration file (see
|
||||
|g:ale_hdl_checker_config_file|)
|
||||
2. If no configuration file can be found, find the first directory containing
|
||||
a folder named `'.git'
|
||||
3. If no such folder is found, use the directory of the current buffer
|
||||
|
||||
|
||||
g:ale_hdl_checker_executable
|
||||
*g:ale_hdl_checker_executable*
|
||||
*b:ale_hdl_checker_executable*
|
||||
Type: |String|
|
||||
Default: `'hdl_checker'`
|
||||
|
||||
This variable can be changed to the path to the 'hdl_checker' executable.
|
||||
|
||||
|
||||
g:ale_hdl_checker_options *g:ale_hdl_checker_options*
|
||||
*b:ale_hdl_checker_options*
|
||||
Type: |String|
|
||||
Default: `''`
|
||||
|
||||
This variable can be changed to modify the flags/options passed to the
|
||||
'hdl_checker' server startup command.
|
||||
|
||||
|
||||
g:ale_hdl_checker_config_file *g:ale_hdl_checker_config_file*
|
||||
*b:ale_hdl_checker_config_file*
|
||||
Type: |String|
|
||||
Default: `'.hdl_checker.config'` (Unix),
|
||||
`'_hdl_checker.config'` (Windows)
|
||||
|
||||
This variable can be changed to modify the config file HDL Checker will try
|
||||
to look for. It will also affect how the project's root directory is
|
||||
determined (see |ale-vhdl-hdl-checker|).
|
||||
|
||||
More info on the configuration file format can be found at:
|
||||
https://github.com/suoto/hdl_checker/wiki/Setting-up-a-project
|
||||
|
||||
|
||||
===============================================================================
|
||||
vcom *ale-vhdl-vcom*
|
||||
|
||||
|
|
|
@ -2675,12 +2675,14 @@ documented in additional help files.
|
|||
vala....................................|ale-vala-options|
|
||||
uncrustify............................|ale-vala-uncrustify|
|
||||
verilog/systemverilog...................|ale-verilog-options|
|
||||
hdl-checker...........................|ale-verilog-hdl-checker|
|
||||
iverilog..............................|ale-verilog-iverilog|
|
||||
verilator.............................|ale-verilog-verilator|
|
||||
vlog..................................|ale-verilog-vlog|
|
||||
xvlog.................................|ale-verilog-xvlog|
|
||||
vhdl....................................|ale-vhdl-options|
|
||||
ghdl..................................|ale-vhdl-ghdl|
|
||||
hdl-checker...........................|ale-vhdl-hdl-checker|
|
||||
vcom..................................|ale-vhdl-vcom|
|
||||
xvhdl.................................|ale-vhdl-xvhdl|
|
||||
vim.....................................|ale-vim-options|
|
||||
|
|
0
test/command_callback/hdl_server/foo.vhd
Normal file
0
test/command_callback/hdl_server/foo.vhd
Normal file
1
test/command_callback/hdl_server/with_git/files/foo.vhd
Normal file
1
test/command_callback/hdl_server/with_git/files/foo.vhd
Normal file
|
@ -0,0 +1 @@
|
|||
|
|
@ -61,7 +61,7 @@ Execute(The defaults for the zsh filetype should be correct):
|
|||
Execute(The defaults for the verilog filetype should be correct):
|
||||
" This filetype isn't configured with default, so we can test loading all
|
||||
" available linters with this.
|
||||
AssertEqual ['iverilog', 'verilator', 'vlog', 'xvlog'], GetLinterNames('verilog')
|
||||
AssertEqual ['hdl-checker', 'iverilog', 'verilator', 'vlog', 'xvlog'], GetLinterNames('verilog')
|
||||
|
||||
let g:ale_linters_explicit = 1
|
||||
|
||||
|
|
78
test/test_hdl_checker_options.vader
Normal file
78
test/test_hdl_checker_options.vader
Normal file
|
@ -0,0 +1,78 @@
|
|||
Before:
|
||||
call ale#assert#SetUpLinterTest('vhdl', 'hdl_checker')
|
||||
|
||||
Save g:ale_hdl_checker_config_file
|
||||
Save g:ale_hdl_checker_options
|
||||
|
||||
let g:default_config_file = has('unix') ? '.hdl_checker.config' : '_hdl_checker.config'
|
||||
|
||||
After:
|
||||
Restore
|
||||
call ale#assert#TearDownLinterTest()
|
||||
unlet! g:default_config_file
|
||||
|
||||
Execute(Get default initialization dict):
|
||||
AssertEqual
|
||||
\ {'project_file': g:default_config_file},
|
||||
\ ale#handlers#hdl_checker#GetInitOptions(bufnr(''))
|
||||
|
||||
Execute(Get custom initialization dict):
|
||||
let g:ale_hdl_checker_config_file = 'some_file_name'
|
||||
|
||||
AssertEqual
|
||||
\ {'project_file': 'some_file_name'},
|
||||
\ ale#handlers#hdl_checker#GetInitOptions(bufnr(''))
|
||||
|
||||
Execute(Get the checker command without extra user parameters):
|
||||
AssertEqual
|
||||
\ ale#Escape('hdl_checker') . ' --lsp',
|
||||
\ ale#handlers#hdl_checker#GetCommand(bufnr(''))
|
||||
|
||||
Execute(Get the checker command with user configured parameters):
|
||||
let g:ale_hdl_checker_options = '--log-level DEBUG'
|
||||
|
||||
AssertEqual
|
||||
\ ale#Escape('hdl_checker') . ' --lsp --log-level DEBUG',
|
||||
\ ale#handlers#hdl_checker#GetCommand(bufnr(''))
|
||||
|
||||
Execute(Customize executable):
|
||||
let g:ale_hdl_checker_executable = '/some/other/path'
|
||||
AssertEqual
|
||||
\ ale#Escape('/some/other/path') . ' --lsp',
|
||||
\ ale#handlers#hdl_checker#GetCommand(bufnr(''))
|
||||
|
||||
Execute(Get project root based on .git):
|
||||
call ale#test#SetFilename('hdl_server/with_git/files/foo.vhd')
|
||||
" Create .git file
|
||||
silent! call mkdir(g:dir . '/hdl_server/with_git/.git')
|
||||
AssertNotEqual '', glob(g:dir . '/hdl_server/with_git/.git')
|
||||
|
||||
AssertEqual
|
||||
\ ale#path#Simplify(g:dir . '/hdl_server/with_git'),
|
||||
\ ale#handlers#hdl_checker#GetProjectRoot(bufnr(''))
|
||||
|
||||
Execute(Get project root based on config file):
|
||||
call ale#test#SetFilename('hdl_server/with_config_file/foo.vhd')
|
||||
|
||||
AssertEqual
|
||||
\ ale#path#Simplify(g:dir . '/hdl_server/with_config_file'),
|
||||
\ ale#handlers#hdl_checker#GetProjectRoot(bufnr(''))
|
||||
|
||||
Execute(Return no project root if neither .git or config file are found):
|
||||
let g:call_count = 0
|
||||
|
||||
" Mock this command to avoid the test to find ale's own .git folder
|
||||
function! ale#handlers#hdl_checker#IsDotGit(path) abort
|
||||
let g:call_count += 1
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
call ale#test#SetFilename('hdl_server/foo.vhd')
|
||||
|
||||
AssertEqual
|
||||
\ '',
|
||||
\ ale#handlers#hdl_checker#GetProjectRoot(bufnr(''))
|
||||
|
||||
AssertEqual g:call_count, 1
|
||||
|
||||
unlet! g:call_count
|
Reference in a new issue