forked from github-mirrors/ale
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
973c4ea053
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2016-2019, w0rp <devw0rp@gmail.com>
|
||||
Copyright (c) 2016-2020, w0rp <devw0rp@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -102,7 +102,7 @@ programs for checking the syntax and semantics of your programs. By default,
|
|||
linters will be re-run in the background to check your syntax when you open
|
||||
new buffers or as you make edits to your files.
|
||||
|
||||
The behaviour of linting can be configured with a variety of options,
|
||||
The behavior of linting can be configured with a variety of options,
|
||||
documented in [the Vim help file](doc/ale.txt). For more information on the
|
||||
options ALE offers, consult `:help ale-options` for global options and `:help
|
||||
ale-integration-options` for options specified to particular linters.
|
||||
|
@ -231,6 +231,9 @@ ALE supports "hover" information for printing brief information about symbols at
|
|||
the cursor taken from Language Server Protocol linters and `tsserver` with the
|
||||
`ALEHover` command.
|
||||
|
||||
Truncated information will be displayed when the cursor rests on a symbol by
|
||||
default, as long as there are no problems on the same line.
|
||||
|
||||
The information can be displayed in a `balloon` tooltip in Vim or GVim by
|
||||
hovering your mouse over symbols. Mouse hovering is enabled by default in GVim,
|
||||
and needs to be configured for Vim 8.1+ in terminals.
|
||||
|
@ -735,7 +738,7 @@ while you type. ALE uses a timeout which is cancelled and reset every time you
|
|||
type, and this delay can be increased so linters are run less often. See
|
||||
`:help g:ale_lint_delay` for more information.
|
||||
|
||||
If you don't wish to run linters while you type, you can disable that behaviour.
|
||||
If you don't wish to run linters while you type, you can disable that behavior.
|
||||
Set `g:ale_lint_on_text_changed` to `never`. You won't get as frequent error
|
||||
checking, but ALE shouldn't block your ability to edit a document after you save
|
||||
a file, so the asynchronous nature of the plugin will still be an advantage.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
call ale#Set('c_ccls_executable', 'ccls')
|
||||
call ale#Set('c_ccls_init_options', {})
|
||||
call ale#Set('c_build_dir', '')
|
||||
|
||||
call ale#linter#Define('c', {
|
||||
\ 'name': 'ccls',
|
||||
|
@ -10,5 +11,5 @@ call ale#linter#Define('c', {
|
|||
\ 'executable': {b -> ale#Var(b, 'c_ccls_executable')},
|
||||
\ 'command': '%e',
|
||||
\ 'project_root': function('ale#handlers#ccls#GetProjectRoot'),
|
||||
\ 'initialization_options': {b -> ale#Var(b, 'c_ccls_init_options')},
|
||||
\ 'initialization_options': {b -> ale#handlers#ccls#GetInitOpts(b, 'c_ccls_init_options')},
|
||||
\})
|
||||
|
|
|
@ -10,9 +10,11 @@ function! ale_linters#c#cppcheck#GetCommand(buffer) abort
|
|||
let l:buffer_path_include = empty(l:compile_commands_option)
|
||||
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer)
|
||||
\ : ''
|
||||
let l:template = ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
|
||||
return l:cd_command
|
||||
\ . '%e -q --language=c'
|
||||
\ . l:template
|
||||
\ . ale#Pad(l:compile_commands_option)
|
||||
\ . ale#Pad(ale#Var(a:buffer, 'c_cppcheck_options'))
|
||||
\ . l:buffer_path_include
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
call ale#Set('cpp_ccls_executable', 'ccls')
|
||||
call ale#Set('cpp_ccls_init_options', {})
|
||||
call ale#Set('c_build_dir', '')
|
||||
|
||||
call ale#linter#Define('cpp', {
|
||||
\ 'name': 'ccls',
|
||||
|
@ -10,5 +11,5 @@ call ale#linter#Define('cpp', {
|
|||
\ 'executable': {b -> ale#Var(b, 'cpp_ccls_executable')},
|
||||
\ 'command': '%e',
|
||||
\ 'project_root': function('ale#handlers#ccls#GetProjectRoot'),
|
||||
\ 'initialization_options': {b -> ale#Var(b, 'cpp_ccls_init_options')},
|
||||
\ 'initialization_options': {b -> ale#handlers#ccls#GetInitOpts(b, 'cpp_ccls_init_options')},
|
||||
\})
|
||||
|
|
|
@ -10,9 +10,11 @@ function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
|
|||
let l:buffer_path_include = empty(l:compile_commands_option)
|
||||
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer)
|
||||
\ : ''
|
||||
let l:template = ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
|
||||
return l:cd_command
|
||||
\ . '%e -q --language=c++'
|
||||
\ . l:template
|
||||
\ . ale#Pad(l:compile_commands_option)
|
||||
\ . ale#Pad(ale#Var(a:buffer, 'cpp_cppcheck_options'))
|
||||
\ . l:buffer_path_include
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
call ale#Set('objc_ccls_executable', 'ccls')
|
||||
call ale#Set('objc_ccls_init_options', {})
|
||||
call ale#Set('c_build_dir', '')
|
||||
|
||||
call ale#linter#Define('objc', {
|
||||
\ 'name': 'ccls',
|
||||
|
@ -10,5 +11,5 @@ call ale#linter#Define('objc', {
|
|||
\ 'executable': {b -> ale#Var(b, 'objc_ccls_executable')},
|
||||
\ 'command': '%e',
|
||||
\ 'project_root': function('ale#handlers#ccls#GetProjectRoot'),
|
||||
\ 'initialization_options': {b -> ale#Var(b, 'objc_ccls_init_options')},
|
||||
\ 'initialization_options': {b -> ale#handlers#ccls#GetInitOpts(b, 'objc_ccls_init_options')},
|
||||
\})
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
call ale#Set('python_pyright_executable', 'pyright-langserver')
|
||||
call ale#Set('python_pyright_config', {})
|
||||
|
||||
function! ale_linters#python#pyright#GetConfig(buffer) abort
|
||||
let l:config = deepcopy(ale#Var(a:buffer, 'python_pyright_config'))
|
||||
|
||||
if !has_key(l:config, 'python')
|
||||
let l:config.python = {}
|
||||
endif
|
||||
|
||||
if type(l:config.python) is v:t_dict
|
||||
" Automatically detect the virtualenv path and use it.
|
||||
if !has_key(l:config.python, 'venvPath')
|
||||
let l:venv = ale#python#FindVirtualenv(a:buffer)
|
||||
|
||||
if !empty(l:venv)
|
||||
let l:config.python.venvPath = l:venv
|
||||
endif
|
||||
endif
|
||||
|
||||
" Automatically use the version of Python in virtualenv.
|
||||
if type(get(l:config.python, 'venvPath')) is v:t_string
|
||||
\&& !empty(l:config.python.venvPath)
|
||||
\&& !has_key(l:config.python, 'pythonPath')
|
||||
let l:config.python.pythonPath = ale#path#Simplify(
|
||||
\ l:config.python.venvPath
|
||||
\ . (has('win32') ? '/Scripts/python' : '/bin/python')
|
||||
\)
|
||||
endif
|
||||
endif
|
||||
|
||||
return l:config
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('python', {
|
||||
\ 'name': 'pyright',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'executable': {b -> ale#Var(b, 'python_pyright_executable')},
|
||||
\ 'command': '%e --stdio',
|
||||
\ 'project_root': function('ale#python#FindProjectRoot'),
|
||||
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
|
||||
\ 'lsp_config': function('ale_linters#python#pyright#GetConfig'),
|
||||
\})
|
|
@ -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')
|
|
@ -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')
|
|
@ -523,13 +523,46 @@ function! ale#completion#ParseLSPCompletions(response) abort
|
|||
let l:doc = l:doc.value
|
||||
endif
|
||||
|
||||
call add(l:results, {
|
||||
let l:result = {
|
||||
\ 'word': l:word,
|
||||
\ 'kind': ale#completion#GetCompletionSymbols(get(l:item, 'kind', '')),
|
||||
\ 'icase': 1,
|
||||
\ 'menu': get(l:item, 'detail', ''),
|
||||
\ 'info': (type(l:doc) is v:t_string ? l:doc : ''),
|
||||
\})
|
||||
\}
|
||||
|
||||
if has_key(l:item, 'additionalTextEdits')
|
||||
let l:text_changes = []
|
||||
|
||||
for l:edit in l:item.additionalTextEdits
|
||||
let l:range = l:edit.range
|
||||
call add(l:text_changes, {
|
||||
\ 'start': {
|
||||
\ 'line': l:range.start.line + 1,
|
||||
\ 'offset': l:range.start.character + 1,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': l:range.end.line + 1,
|
||||
\ 'offset': l:range.end.character + 1,
|
||||
\ },
|
||||
\ 'newText': l:edit.newText,
|
||||
\})
|
||||
endfor
|
||||
|
||||
let l:changes = [{
|
||||
\ 'fileName': expand('#' . l:buffer . ':p'),
|
||||
\ 'textChanges': l:text_changes,
|
||||
\}]
|
||||
\
|
||||
let l:result.user_data = json_encode({
|
||||
\ 'codeActions': [{
|
||||
\ 'description': 'completion',
|
||||
\ 'changes': l:changes,
|
||||
\ }],
|
||||
\ })
|
||||
endif
|
||||
|
||||
call add(l:results, l:result)
|
||||
endfor
|
||||
|
||||
if has_key(l:info, 'prefix')
|
||||
|
|
|
@ -147,6 +147,10 @@ function! ale#events#Init() abort
|
|||
autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#virtualtext#ShowCursorWarning() | endif
|
||||
endif
|
||||
|
||||
if g:ale_hover_cursor
|
||||
autocmd CursorHold * if exists('*ale#lsp#Send') | call ale#hover#ShowTruncatedMessageAtCursor() | endif
|
||||
endif
|
||||
|
||||
if g:ale_close_preview_on_insert
|
||||
autocmd InsertEnter * if exists('*ale#preview#CloseIfTypeMatches') | call ale#preview#CloseIfTypeMatches('ale-preview') | endif
|
||||
endif
|
||||
|
|
|
@ -49,7 +49,7 @@ endfunction
|
|||
function! ale#fixers#astyle#Fix(buffer) abort
|
||||
let l:executable = ale#fixers#astyle#Var(a:buffer, 'executable')
|
||||
let l:proj_options = ale#fixers#astyle#FindProjectOptions(a:buffer)
|
||||
let l:command = ' --stdin='
|
||||
let l:command = ' --stdin=' . ale#Escape(expand('#' . a:buffer))
|
||||
|
||||
return {
|
||||
\ 'command': ale#Escape(l:executable)
|
||||
|
|
|
@ -17,3 +17,10 @@ function! ale#handlers#ccls#GetProjectRoot(buffer) abort
|
|||
" Fall back on default project root detection.
|
||||
return ale#c#FindProjectRoot(a:buffer)
|
||||
endfunction
|
||||
|
||||
function! ale#handlers#ccls#GetInitOpts(buffer, init_options_var) abort
|
||||
let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
|
||||
let l:init_options = empty(l:build_dir) ? {} : {'compilationDatabaseDirectory': l:build_dir}
|
||||
|
||||
return extend(l:init_options, ale#Var(a:buffer, a:init_options_var))
|
||||
endfunction
|
||||
|
|
|
@ -44,16 +44,21 @@ endfunction
|
|||
function! ale#handlers#cppcheck#HandleCppCheckFormat(buffer, lines) abort
|
||||
" Look for lines like the following.
|
||||
"
|
||||
" [test.cpp:5]: (error) Array 'a[10]' accessed at index 10, which is out of bounds
|
||||
let l:pattern = '\v^\[(.+):(\d+)\]: \(([a-z]+)\) (.+)$'
|
||||
"test.cpp:974:6: error: Array 'n[3]' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\
|
||||
" n[3]=3;
|
||||
" ^
|
||||
let l:pattern = '\v^(\f+):(\d+):(\d+): (\w+): (.*) \[(\w+)\]\'
|
||||
let l:output = []
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
if ale#path#IsBufferPath(a:buffer, l:match[1])
|
||||
call add(l:output, {
|
||||
\ 'lnum': str2nr(l:match[2]),
|
||||
\ 'type': l:match[3] is# 'error' ? 'E' : 'W',
|
||||
\ 'text': l:match[4],
|
||||
\ 'lnum': str2nr(l:match[2]),
|
||||
\ 'col': str2nr(l:match[3]),
|
||||
\ 'type': l:match[4] is# 'error' ? 'E' : 'W',
|
||||
\ 'sub_type': l:match[4] is# 'style' ? 'style' : '',
|
||||
\ 'text': l:match[5],
|
||||
\ 'code': l:match[6]
|
||||
\})
|
||||
endif
|
||||
endfor
|
||||
|
|
|
@ -6,9 +6,12 @@
|
|||
"
|
||||
" Author: Ben Paxton <ben@gn32.uk>
|
||||
" Description: moved to generic Golang file from govet
|
||||
"
|
||||
" Author: mostfunkyduck <mostfunkyduck@protonmail.com>
|
||||
" Description: updated to work with go 1.14
|
||||
|
||||
function! ale#handlers#go#Handler(buffer, lines) abort
|
||||
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? ?(.+)$'
|
||||
let l:pattern = '\v^%(vet: )?([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? ?(.+)$'
|
||||
let l:output = []
|
||||
let l:dir = expand('#' . a:buffer . ':p:h')
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
" Description: Adds support for markdownlint
|
||||
|
||||
function! ale#handlers#markdownlint#Handle(buffer, lines) abort
|
||||
let l:pattern=': \?\(\d\+\)\(:\(\d\+\)\?\)\? \(MD\d\{3}/[A-Za-z0-9-]\+\) \(.*\)$'
|
||||
let l:pattern=': \?\(\d\+\)\(:\(\d\+\)\?\)\? \(MD\d\{3}/[A-Za-z0-9-/]\+\) \(.*\)$'
|
||||
let l:output=[]
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
|
|
|
@ -42,6 +42,8 @@ function! ale#hover#HandleTSServerResponse(conn_id, response) abort
|
|||
\&& exists('*balloon_show')
|
||||
\&& ale#Var(l:options.buffer, 'set_balloons')
|
||||
call balloon_show(a:response.body.displayString)
|
||||
elseif get(l:options, 'truncated_echo', 0)
|
||||
call ale#cursor#TruncatedEcho(split(a:response.body.displayString, "\n")[0])
|
||||
elseif g:ale_hover_to_preview
|
||||
call ale#preview#Show(split(a:response.body.displayString, "\n"), {
|
||||
\ 'filetype': 'ale-preview.message',
|
||||
|
@ -89,11 +91,12 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
|
|||
|
||||
if type(l:result) is v:t_dict
|
||||
" If the result is an object, then it's markup content.
|
||||
let l:result = [l:result.value]
|
||||
let l:result = has_key(l:result, 'value') ? [l:result.value] : []
|
||||
endif
|
||||
|
||||
if type(l:result) is v:t_list
|
||||
" Replace objects with text values.
|
||||
call filter(l:result, '!(type(v:val) is v:t_dict && !has_key(v:val, ''value''))')
|
||||
call map(l:result, 'type(v:val) is v:t_string ? v:val : v:val.value')
|
||||
let l:str = join(l:result, "\n")
|
||||
let l:str = substitute(l:str, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||
|
@ -103,6 +106,8 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
|
|||
\&& exists('*balloon_show')
|
||||
\&& ale#Var(l:options.buffer, 'set_balloons')
|
||||
call balloon_show(l:str)
|
||||
elseif get(l:options, 'truncated_echo', 0)
|
||||
call ale#cursor#TruncatedEcho(split(l:str, "\n")[0])
|
||||
elseif g:ale_hover_to_preview
|
||||
call ale#preview#Show(split(l:str, "\n"), {
|
||||
\ 'filetype': 'ale-preview.message',
|
||||
|
@ -156,6 +161,7 @@ function! s:OnReady(line, column, opt, linter, lsp_details) abort
|
|||
\ 'column': l:column,
|
||||
\ 'hover_from_balloonexpr': get(a:opt, 'called_from_balloonexpr', 0),
|
||||
\ 'show_documentation': get(a:opt, 'show_documentation', 0),
|
||||
\ 'truncated_echo': get(a:opt, 'truncated_echo', 0),
|
||||
\}
|
||||
endfunction
|
||||
|
||||
|
@ -189,6 +195,16 @@ function! ale#hover#ShowAtCursor() abort
|
|||
call ale#hover#Show(l:buffer, l:pos[1], l:pos[2], {})
|
||||
endfunction
|
||||
|
||||
function! ale#hover#ShowTruncatedMessageAtCursor() abort
|
||||
let l:buffer = bufnr('')
|
||||
let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer)
|
||||
|
||||
if empty(l:loc)
|
||||
let l:pos = getpos('.')
|
||||
call ale#hover#Show(l:buffer, l:pos[1], l:pos[2], {'truncated_echo': 1})
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" This function implements the :ALEDocumentation command.
|
||||
function! ale#hover#ShowDocumentationAtCursor() abort
|
||||
let l:buffer = bufnr('')
|
||||
|
|
|
@ -44,7 +44,7 @@ let s:default_ale_linters = {
|
|||
\ 'help': [],
|
||||
\ 'perl': ['perlcritic'],
|
||||
\ 'perl6': [],
|
||||
\ 'python': ['flake8', 'mypy', 'pylint'],
|
||||
\ 'python': ['flake8', 'mypy', 'pylint', 'pyright'],
|
||||
\ 'rust': ['cargo'],
|
||||
\ 'spec': [],
|
||||
\ 'text': [],
|
||||
|
|
|
@ -196,14 +196,26 @@ function! s:UpdateCapabilities(conn, capabilities) abort
|
|||
let a:conn.capabilities.hover = 1
|
||||
endif
|
||||
|
||||
if type(get(a:capabilities, 'hoverProvider')) is v:t_dict
|
||||
let a:conn.capabilities.hover = 1
|
||||
endif
|
||||
|
||||
if get(a:capabilities, 'referencesProvider') is v:true
|
||||
let a:conn.capabilities.references = 1
|
||||
endif
|
||||
|
||||
if type(get(a:capabilities, 'referencesProvider')) is v:t_dict
|
||||
let a:conn.capabilities.references = 1
|
||||
endif
|
||||
|
||||
if get(a:capabilities, 'renameProvider') is v:true
|
||||
let a:conn.capabilities.rename = 1
|
||||
endif
|
||||
|
||||
if type(get(a:capabilities, 'renameProvider')) is v:t_dict
|
||||
let a:conn.capabilities.rename = 1
|
||||
endif
|
||||
|
||||
if !empty(get(a:capabilities, 'completionProvider'))
|
||||
let a:conn.capabilities.completion = 1
|
||||
endif
|
||||
|
@ -220,13 +232,25 @@ function! s:UpdateCapabilities(conn, capabilities) abort
|
|||
let a:conn.capabilities.definition = 1
|
||||
endif
|
||||
|
||||
if type(get(a:capabilities, 'definitionProvider')) is v:t_dict
|
||||
let a:conn.capabilities.definition = 1
|
||||
endif
|
||||
|
||||
if get(a:capabilities, 'typeDefinitionProvider') is v:true
|
||||
let a:conn.capabilities.typeDefinition = 1
|
||||
endif
|
||||
|
||||
if type(get(a:capabilities, 'typeDefinitionProvider')) is v:t_dict
|
||||
let a:conn.capabilities.typeDefinition = 1
|
||||
endif
|
||||
|
||||
if get(a:capabilities, 'workspaceSymbolProvider') is v:true
|
||||
let a:conn.capabilities.symbol_search = 1
|
||||
endif
|
||||
|
||||
if type(get(a:capabilities, 'workspaceSymbolProvider')) is v:t_dict
|
||||
let a:conn.capabilities.symbol_search = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Update a connection's configuration dictionary and notify LSP servers
|
||||
|
|
|
@ -83,6 +83,31 @@ function! ale#rename#HandleTSServerResponse(conn_id, response) abort
|
|||
\}, v:true)
|
||||
endfunction
|
||||
|
||||
function! s:getChanges(workspace_edit) abort
|
||||
let l:changes = {}
|
||||
|
||||
if has_key(a:workspace_edit, 'changes') && !empty(a:workspace_edit.changes)
|
||||
return a:workspace_edit.changes
|
||||
elseif has_key(a:workspace_edit, 'documentChanges')
|
||||
let l:document_changes = []
|
||||
|
||||
if type(a:workspace_edit.documentChanges) is v:t_dict
|
||||
\ && has_key(a:workspace_edit.documentChanges, 'edits')
|
||||
call add(l:document_changes, a:workspace_edit.documentChanges)
|
||||
elseif type(a:workspace_edit.documentChanges) is v:t_list
|
||||
let l:document_changes = a:workspace_edit.documentChanges
|
||||
endif
|
||||
|
||||
for l:text_document_edit in l:document_changes
|
||||
let l:filename = l:text_document_edit.textDocument.uri
|
||||
let l:edits = l:text_document_edit.edits
|
||||
let l:changes[l:filename] = l:edits
|
||||
endfor
|
||||
endif
|
||||
|
||||
return l:changes
|
||||
endfunction
|
||||
|
||||
function! ale#rename#HandleLSPResponse(conn_id, response) abort
|
||||
if has_key(a:response, 'id')
|
||||
\&& has_key(s:rename_map, a:response.id)
|
||||
|
@ -94,9 +119,9 @@ function! ale#rename#HandleLSPResponse(conn_id, response) abort
|
|||
return
|
||||
endif
|
||||
|
||||
let l:workspace_edit = a:response.result
|
||||
let l:changes_map = s:getChanges(a:response.result)
|
||||
|
||||
if !has_key(l:workspace_edit, 'changes') || empty(l:workspace_edit.changes)
|
||||
if empty(l:changes_map)
|
||||
call s:message('No changes received from server')
|
||||
|
||||
return
|
||||
|
@ -104,8 +129,8 @@ function! ale#rename#HandleLSPResponse(conn_id, response) abort
|
|||
|
||||
let l:changes = []
|
||||
|
||||
for l:file_name in keys(l:workspace_edit.changes)
|
||||
let l:text_edits = l:workspace_edit.changes[l:file_name]
|
||||
for l:file_name in keys(l:changes_map)
|
||||
let l:text_edits = l:changes_map[l:file_name]
|
||||
let l:text_changes = []
|
||||
|
||||
for l:edit in l:text_edits
|
||||
|
|
|
@ -138,7 +138,7 @@ g:ale_javascript_flow_use_respect_pragma
|
|||
|
||||
By default, ALE will use the `--respect-pragma` option for `flow`, so only
|
||||
files with the `@flow` pragma are checked by ALE. This option can be set to
|
||||
`0` to disable that behaviour, so all files can be checked by `flow`.
|
||||
`0` to disable that behavior, so all files can be checked by `flow`.
|
||||
|
||||
|
||||
===============================================================================
|
||||
|
|
|
@ -598,6 +598,7 @@ g:ale_python_pylint_use_msg_id *g:ale_python_pylint_use_msg_id*
|
|||
Use message for output (e.g. I0011) instead of symbolic name of the message
|
||||
(e.g. locally-disabled).
|
||||
|
||||
|
||||
===============================================================================
|
||||
pyls *ale-python-pyls*
|
||||
|
||||
|
@ -682,6 +683,65 @@ g:ale_python_pyre_auto_pipenv *g:ale_python_pyre_auto_pipenv*
|
|||
if true. This is overridden by a manually-set executable.
|
||||
|
||||
|
||||
===============================================================================
|
||||
pyright *ale-python-pyright*
|
||||
|
||||
The `pyrlight` linter requires a recent version of `pyright` which includes
|
||||
the `pyright-langserver` executable. You can install `pyright` on your system
|
||||
through `npm` with `sudo npm install -g pyright` or similar.
|
||||
|
||||
Refer to their README for installation instructions:
|
||||
https://github.com/Microsoft/pyright
|
||||
|
||||
`pyright` needs to know the path to your Python executable and probably a
|
||||
virtualenv to run. ALE will try to detect these automatically.
|
||||
See |g:ale_python_pyright_config|.
|
||||
|
||||
|
||||
g:ale_python_pyright_executable *g:ale_python_pyright_executable*
|
||||
*b:ale_python_pyright_executable*
|
||||
Type: |String|
|
||||
Default: `'pyright-langserver'`
|
||||
|
||||
The executable for running `pyright`, which is typically installed globally.
|
||||
|
||||
|
||||
g:ale_python_pyright_config *g:ale_python_pyright_config*
|
||||
*b:ale_python_pyright_config*
|
||||
Type: |Dictionary|
|
||||
Default: `{}`
|
||||
|
||||
Settings for configuring the `pyright` language server.
|
||||
|
||||
See pyright's documentation for a full list of options:
|
||||
https://github.com/microsoft/pyright/blob/master/docs/settings.md
|
||||
|
||||
ALE will automatically try to set defaults for `venvPath` and `pythonPath`
|
||||
so your project can automatically be checked with the right libraries.
|
||||
You can override these settings with whatever you want in your ftplugin
|
||||
file like so: >
|
||||
|
||||
let b:ale_python_pyright_config = {
|
||||
\ 'python': {
|
||||
\ 'pythonPath': '/bin/python',
|
||||
\ 'venvPath': '/other/dir',
|
||||
\ },
|
||||
\}
|
||||
<
|
||||
If `venvPath` is set, but `pythonPath` is not,
|
||||
ALE will use `venvPath . '/bin/python'` or similar as `pythonPath`.
|
||||
|
||||
A commonly used setting for `pyright` is disabling language services
|
||||
apart from type checking and "hover" (|ale-hover|), you can set this
|
||||
setting like so, or use whatever other settings you want: >
|
||||
|
||||
let b:ale_python_pyright_config = {
|
||||
\ 'pyright': {
|
||||
\ 'disableLanguageServices': v:true,
|
||||
\ },
|
||||
\}
|
||||
<
|
||||
|
||||
===============================================================================
|
||||
reorder-python-imports *ale-python-reorder_python_imports*
|
||||
|
||||
|
|
|
@ -373,6 +373,7 @@ Notes:
|
|||
* `pylint`!!
|
||||
* `pyls`
|
||||
* `pyre`
|
||||
* `pyright`
|
||||
* `reorder-python-imports`
|
||||
* `vulture`!!
|
||||
* `yapf`
|
||||
|
@ -484,6 +485,7 @@ Notes:
|
|||
* VALA
|
||||
* `uncrustify`
|
||||
* Verilog
|
||||
* `hdl-checker`
|
||||
* `iverilog`
|
||||
* `verilator`
|
||||
* `vlog`
|
||||
|
|
|
@ -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*
|
||||
|
||||
|
|
36
doc/ale.txt
36
doc/ale.txt
|
@ -127,7 +127,7 @@ their relevant options.
|
|||
* By showing balloons for your mouse cursor - |g:ale_set_balloons|
|
||||
|
||||
Please consult the documentation for each option, which can reveal some other
|
||||
ways of tweaking the behaviour of each way of displaying problems. You can
|
||||
ways of tweaking the behavior of each way of displaying problems. You can
|
||||
disable or enable whichever options you prefer.
|
||||
|
||||
Most settings can be configured for each buffer. (|b:| instead of |g:|),
|
||||
|
@ -516,6 +516,10 @@ at the cursor taken from LSP linters. The following commands are supported:
|
|||
|
||||
|ALEHover| - Print information about the symbol at the cursor.
|
||||
|
||||
Truncated information will be displayed when the cursor rests on a symbol by
|
||||
default, as long as there are no problems on the same line. You can disable
|
||||
this behavior by setting |g:ale_hover_cursor| to `0`.
|
||||
|
||||
If |g:ale_set_balloons| is set to `1` and your version of Vim supports the
|
||||
|balloon_show()| function, then "hover" information also show up when you move
|
||||
the mouse over a symbol in a buffer. Diagnostic information will take priority
|
||||
|
@ -1048,9 +1052,27 @@ g:ale_history_log_output *g:ale_history_log_output*
|
|||
if you want to save on some memory usage.
|
||||
|
||||
|
||||
g:ale_hover_cursor *g:ale_hover_cursor*
|
||||
|
||||
Type: |Number|
|
||||
Default: `1`
|
||||
|
||||
If set to `1`, ALE will show truncated information in the echo line about
|
||||
the symbol at the cursor automatically when the |CursorHold| event is fired.
|
||||
The delay before requesting hover information is based on 'updatetime', as
|
||||
with all |CursorHold| events.
|
||||
|
||||
If there's a problem on the line where the cursor is resting, ALE will not
|
||||
show any hover information.
|
||||
|
||||
See |ale-hover| for more information on hover information.
|
||||
|
||||
This setting must be set to `1` before ALE is loaded for this behavior
|
||||
to be enabled. See |ale-lint-settings-on-startup|.
|
||||
|
||||
|
||||
g:ale_hover_to_preview *g:ale_hover_to_preview*
|
||||
*b:ale_hover_to_preview*
|
||||
|
||||
Type: |Number|
|
||||
Default: `0`
|
||||
|
||||
|
@ -1268,7 +1290,7 @@ g:ale_linters *g:ale_linters*
|
|||
\ 'help': [],
|
||||
\ 'perl': ['perlcritic'],
|
||||
\ 'perl6': [],
|
||||
\ 'python': ['flake8', 'mypy', 'pylint'],
|
||||
\ 'python': ['flake8', 'mypy', 'pylint', 'pyright'],
|
||||
\ 'rust': ['cargo'],
|
||||
\ 'spec': [],
|
||||
\ 'text': [],
|
||||
|
@ -2557,6 +2579,7 @@ documented in additional help files.
|
|||
pylint................................|ale-python-pylint|
|
||||
pyls..................................|ale-python-pyls|
|
||||
pyre..................................|ale-python-pyre|
|
||||
pyright...............................|ale-python-pyright|
|
||||
reorder-python-imports................|ale-python-reorder_python_imports|
|
||||
vulture...............................|ale-python-vulture|
|
||||
yapf..................................|ale-python-yapf|
|
||||
|
@ -2654,12 +2677,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|
|
||||
|
@ -2864,7 +2889,7 @@ ALELast *ALELast*
|
|||
the last or first warning or error in the file, respectively.
|
||||
|
||||
`ALEPrevious` and `ALENext` take optional flags arguments to custom their
|
||||
behaviour :
|
||||
behavior :
|
||||
`-wrap` enable wrapping around the file
|
||||
`-error`, `-warning` and `-info` enable jumping to errors, warnings or infos
|
||||
respectively, ignoring anything else. They are mutually exclusive and if
|
||||
|
@ -3506,7 +3531,7 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
|
|||
contents of the buffer being checked. All occurrences of `%t` in command
|
||||
strings will reference the one temporary file. The temporary file will be
|
||||
created inside a temporary directory, and the entire temporary directory
|
||||
will be automatically deleted, following the behaviour of
|
||||
will be automatically deleted, following the behavior of
|
||||
|ale#command#ManageDirectory|. This option can be used for some linters which
|
||||
do not support reading from stdin.
|
||||
|
||||
|
@ -3531,7 +3556,6 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
|
|||
be used to replace those characters to avoid formatting issues.
|
||||
|
||||
*ale-linter-loading-behavior*
|
||||
*ale-linter-loading-behaviour*
|
||||
|
||||
Linters for ALE will be loaded by searching |runtimepath| in the following
|
||||
format: >
|
||||
|
|
|
@ -121,6 +121,9 @@ let g:ale_cursor_detail = get(g:, 'ale_cursor_detail', 0)
|
|||
" This flag can be set to 1 to enable virtual text when the cursor moves.
|
||||
let g:ale_virtualtext_cursor = get(g:, 'ale_virtualtext_cursor', 0)
|
||||
|
||||
" This flag can be set to 1 to enable LSP hover messages at the cursor.
|
||||
let g:ale_hover_cursor = get(g:, 'ale_hover_cursor', 1)
|
||||
|
||||
" This flag can be set to 1 to automatically close the preview window upon
|
||||
" entering Insert Mode.
|
||||
let g:ale_close_preview_on_insert = get(g:, 'ale_close_preview_on_insert', 0)
|
||||
|
|
|
@ -382,6 +382,7 @@ formatting.
|
|||
* [pylint](https://www.pylint.org/) :floppy_disk:
|
||||
* [pyls](https://github.com/palantir/python-language-server) :warning:
|
||||
* [pyre](https://github.com/facebook/pyre-check) :warning:
|
||||
* [pyright](https://github.com/microsoft/pyright)
|
||||
* [reorder-python-imports](https://github.com/asottile/reorder_python_imports)
|
||||
* [vulture](https://github.com/jendrikseipp/vulture) :warning: :floppy_disk:
|
||||
* [yapf](https://github.com/google/yapf)
|
||||
|
@ -493,6 +494,7 @@ formatting.
|
|||
* VALA
|
||||
* [uncrustify](https://github.com/uncrustify/uncrustify)
|
||||
* Verilog
|
||||
* [hdl-checker](https://pypi.org/project/hdl-checker)
|
||||
* [iverilog](https://github.com/steveicarus/iverilog)
|
||||
* [verilator](http://www.veripool.org/projects/verilator/wiki/Intro)
|
||||
* [vlog](https://www.mentor.com/products/fv/questa/)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -4,6 +4,10 @@
|
|||
Before:
|
||||
call ale#assert#SetUpLinterTest('c', 'ccls')
|
||||
|
||||
Save b:ale_c_build_dir_names
|
||||
Save b:ale_c_ccls_executable
|
||||
Save b:ale_c_ccls_init_options
|
||||
|
||||
After:
|
||||
call ale#assert#TearDownLinterTest()
|
||||
|
||||
|
@ -47,3 +51,19 @@ Execute(The initialization options should be configurable):
|
|||
let b:ale_c_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' }
|
||||
|
||||
AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' }
|
||||
|
||||
Execute(The compile command database should be detected correctly):
|
||||
call ale#test#SetFilename('ccls_paths/with_ccls/dummy.c')
|
||||
|
||||
AssertLSPOptions {}
|
||||
|
||||
call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.c')
|
||||
|
||||
AssertLSPOptions { 'compilationDatabaseDirectory':
|
||||
\ ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') }
|
||||
|
||||
call ale#test#SetFilename('ccls_paths/with_build_dir/dummy.c')
|
||||
let b:ale_c_build_dir_names = ['unusual_build_dir_name']
|
||||
|
||||
AssertLSPOptions { 'compilationDatabaseDirectory':
|
||||
\ ale#path#Simplify(g:dir . '/ccls_paths/with_build_dir/unusual_build_dir_name') }
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
Before:
|
||||
call ale#assert#SetUpLinterTest('c', 'cppcheck')
|
||||
|
||||
let b:command_tail = ' -q --language=c --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
|
||||
let b:command_tail = ' -q --language=c --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'' --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
|
||||
|
||||
After:
|
||||
" Remove a test file we might open for some tests.
|
||||
|
@ -10,9 +9,8 @@ After:
|
|||
set buftype=nofile
|
||||
endif
|
||||
|
||||
call ale#assert#TearDownLinterTest()
|
||||
|
||||
unlet! b:command_tail
|
||||
call ale#assert#TearDownLinterTest()
|
||||
|
||||
Execute(The executable should be configurable):
|
||||
AssertLinter 'cppcheck', ale#Escape('cppcheck') . b:command_tail
|
||||
|
@ -28,6 +26,7 @@ Execute(cppcheck for C should detect compile_commands.json files):
|
|||
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
|
||||
\ . ale#Escape('cppcheck')
|
||||
\ . ' -q --language=c'
|
||||
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
\ . ' --project=' . ale#Escape('compile_commands.json')
|
||||
\ . ' --enable=style %t'
|
||||
|
||||
|
@ -38,6 +37,7 @@ Execute(cppcheck for C should detect compile_commands.json files in build direct
|
|||
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/with_build_dir'))
|
||||
\ . ale#Escape('cppcheck')
|
||||
\ . ' -q --language=c'
|
||||
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
\ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json'))
|
||||
\ . ' --enable=style %t'
|
||||
|
||||
|
@ -47,6 +47,7 @@ Execute(cppcheck for C should include file dir if compile_commands.json file is
|
|||
AssertLinter 'cppcheck',
|
||||
\ ale#Escape('cppcheck')
|
||||
\ . ' -q --language=c'
|
||||
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
\ . ' --enable=style'
|
||||
\ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths'))
|
||||
\ . ' %t'
|
||||
|
@ -61,6 +62,7 @@ Execute(cppcheck for C should ignore compile_commands.json file if buffer is mod
|
|||
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
|
||||
\ . ale#Escape('cppcheck')
|
||||
\ . ' -q --language=c'
|
||||
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
\ . ' --enable=style'
|
||||
\ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
|
||||
\ . ' %t'
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
Before:
|
||||
call ale#assert#SetUpLinterTest('cpp', 'ccls')
|
||||
|
||||
Save b:ale_c_build_dir_names
|
||||
Save b:ale_cpp_ccls_executable
|
||||
Save b:ale_cpp_ccls_init_options
|
||||
|
||||
After:
|
||||
call ale#assert#TearDownLinterTest()
|
||||
|
||||
|
@ -47,3 +51,19 @@ Execute(The initialization options should be configurable):
|
|||
let b:ale_cpp_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' }
|
||||
|
||||
AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' }
|
||||
|
||||
Execute(The compile command database should be detected correctly):
|
||||
call ale#test#SetFilename('ccls_paths/with_ccls/dummy.c')
|
||||
|
||||
AssertLSPOptions {}
|
||||
|
||||
call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.c')
|
||||
|
||||
AssertLSPOptions { 'compilationDatabaseDirectory':
|
||||
\ ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') }
|
||||
|
||||
call ale#test#SetFilename('ccls_paths/with_build_dir/dummy.c')
|
||||
let b:ale_c_build_dir_names = ['unusual_build_dir_name']
|
||||
|
||||
AssertLSPOptions { 'compilationDatabaseDirectory':
|
||||
\ ale#path#Simplify(g:dir . '/ccls_paths/with_build_dir/unusual_build_dir_name') }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Before:
|
||||
call ale#assert#SetUpLinterTest('cpp', 'cppcheck')
|
||||
let b:command_tail = ' -q --language=c++ --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
|
||||
let b:command_tail = ' -q --language=c++ --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'' --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
|
||||
|
||||
After:
|
||||
" Remove a test file we might open for some tests.
|
||||
|
@ -26,6 +26,7 @@ Execute(cppcheck for C++ should detect compile_commands.json files):
|
|||
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
|
||||
\ . ale#Escape('cppcheck')
|
||||
\ . ' -q --language=c++'
|
||||
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
\ . ' --project=' . ale#Escape('compile_commands.json')
|
||||
\ . ' --enable=style %t'
|
||||
|
||||
|
@ -36,6 +37,7 @@ Execute(cppcheck for C++ should detect compile_commands.json files in build dire
|
|||
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/with_build_dir'))
|
||||
\ . ale#Escape('cppcheck')
|
||||
\ . ' -q --language=c++'
|
||||
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
\ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json'))
|
||||
\ . ' --enable=style %t'
|
||||
|
||||
|
@ -45,6 +47,7 @@ Execute(cppcheck for C++ should include file dir if compile_commands.json file i
|
|||
AssertLinter 'cppcheck',
|
||||
\ ale#Escape('cppcheck')
|
||||
\ . ' -q --language=c++'
|
||||
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
\ . ' --enable=style'
|
||||
\ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths'))
|
||||
\ . ' %t'
|
||||
|
@ -59,6 +62,7 @@ Execute(cppcheck for C++ should ignore compile_commands.json file if buffer is m
|
|||
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
|
||||
\ . ale#Escape('cppcheck')
|
||||
\ . ' -q --language=c++'
|
||||
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
|
||||
\ . ' --enable=style'
|
||||
\ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
|
||||
\ . ' %t'
|
||||
|
|
|
@ -49,7 +49,10 @@ Execute(Should return directory for 'go.mod' if found in parent directory):
|
|||
|
||||
Execute(Should return nearest directory with '.git' if found in parent directory):
|
||||
call ale#test#SetFilename('test.go')
|
||||
call mkdir(g:dir . '/.git')
|
||||
|
||||
if !isdirectory(g:dir . '/.git')
|
||||
call mkdir(g:dir . '/.git')
|
||||
endif
|
||||
|
||||
AssertLSPProject g:dir
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
Before:
|
||||
call ale#assert#SetUpLinterTest('objc', 'ccls')
|
||||
|
||||
Save b:ale_c_build_dir_names
|
||||
Save b:ale_objc_ccls_executable
|
||||
Save b:ale_objc_ccls_init_options
|
||||
|
||||
After:
|
||||
call ale#assert#TearDownLinterTest()
|
||||
|
||||
|
@ -44,3 +48,19 @@ Execute(The initialization options should be configurable):
|
|||
let b:ale_objc_ccls_init_options = { 'cacheDirectory': '/tmp/ccls' }
|
||||
|
||||
AssertLSPOptions { 'cacheDirectory': '/tmp/ccls' }
|
||||
|
||||
Execute(The compile command database should be detected correctly):
|
||||
call ale#test#SetFilename('ccls_paths/with_ccls/dummy.c')
|
||||
|
||||
AssertLSPOptions {}
|
||||
|
||||
call ale#test#SetFilename('ccls_paths/with_compile_commands_json/dummy.c')
|
||||
|
||||
AssertLSPOptions { 'compilationDatabaseDirectory':
|
||||
\ ale#path#Simplify(g:dir . '/ccls_paths/with_compile_commands_json') }
|
||||
|
||||
call ale#test#SetFilename('ccls_paths/with_build_dir/dummy.c')
|
||||
let b:ale_c_build_dir_names = ['unusual_build_dir_name']
|
||||
|
||||
AssertLSPOptions { 'compilationDatabaseDirectory':
|
||||
\ ale#path#Simplify(g:dir . '/ccls_paths/with_build_dir/unusual_build_dir_name') }
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
Before:
|
||||
call ale#assert#SetUpLinterTest('python', 'pyright')
|
||||
|
||||
let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
|
||||
|
||||
After:
|
||||
unlet! b:bin_dir
|
||||
unlet! b:executable
|
||||
|
||||
call ale#assert#TearDownLinterTest()
|
||||
|
||||
Execute(The command callback should return the correct default string):
|
||||
AssertLinter
|
||||
\ 'pyright-langserver',
|
||||
\ ale#Escape('pyright-langserver') . ' --stdio'
|
||||
|
||||
Execute(The executable should be configurable):
|
||||
let g:ale_python_pyright_executable = '/bin/foo-bar'
|
||||
|
||||
AssertLinter
|
||||
\ '/bin/foo-bar',
|
||||
\ ale#Escape('/bin/foo-bar') . ' --stdio'
|
||||
|
||||
Execute(The default configuration should be mostly empty):
|
||||
" The default configuration needs to have at least one key in it,
|
||||
" or the server won't start up properly.
|
||||
AssertLSPConfig {'python': {}}
|
||||
|
||||
let b:ale_python_pyright_config = {}
|
||||
|
||||
AssertLSPConfig {'python': {}}
|
||||
|
||||
Execute(virtualenv paths should be set in configuration by default):
|
||||
call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py')
|
||||
|
||||
AssertLSPConfig {
|
||||
\ 'python': {
|
||||
\ 'pythonPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/python'),
|
||||
\ 'venvPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env'),
|
||||
\ },
|
||||
\}
|
||||
|
||||
Execute(The pythonPath should be set based on whatever the ovveride for the venvPath is set to):
|
||||
call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py')
|
||||
|
||||
" This overrides the default detection of the path.
|
||||
let b:ale_python_pyright_config = {
|
||||
\ 'python': {
|
||||
\ 'venvPath': '/foo/bar',
|
||||
\ },
|
||||
\}
|
||||
|
||||
AssertLSPConfig {
|
||||
\ 'python': {
|
||||
\ 'pythonPath': ale#path#Simplify('/foo/bar/' . b:bin_dir . '/python'),
|
||||
\ 'venvPath': '/foo/bar',
|
||||
\ },
|
||||
\}
|
||||
|
||||
Execute(You should be able to override pythonPath when venvPath is detected):
|
||||
call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py')
|
||||
|
||||
" This overrides the default detection of the path.
|
||||
let b:ale_python_pyright_config = {
|
||||
\ 'python': {
|
||||
\ 'pythonPath': '/bin/python',
|
||||
\ },
|
||||
\}
|
||||
|
||||
AssertLSPConfig {
|
||||
\ 'python': {
|
||||
\ 'pythonPath': '/bin/python',
|
||||
\ 'venvPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env'),
|
||||
\ },
|
||||
\}
|
||||
|
||||
Execute(You should be able to override both pythonPath and venvPath):
|
||||
call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py')
|
||||
|
||||
" This overrides the default detection of the path.
|
||||
let b:ale_python_pyright_config = {
|
||||
\ 'python': {
|
||||
\ 'pythonPath': '/bin/python',
|
||||
\ 'venvPath': '/other/dir',
|
||||
\ },
|
||||
\}
|
||||
|
||||
AssertLSPConfig {
|
||||
\ 'python': {
|
||||
\ 'pythonPath': '/bin/python',
|
||||
\ 'venvPath': '/other/dir',
|
||||
\ },
|
||||
\}
|
||||
|
||||
Execute(You should be able to define other settings):
|
||||
call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py')
|
||||
|
||||
let b:ale_python_pyright_config = {
|
||||
\ 'python': {
|
||||
\ 'analysis': {'logLevel': 'warning'},
|
||||
\ },
|
||||
\ 'pyright': {
|
||||
\ 'disableLanguageServices': v:true,
|
||||
\ },
|
||||
\}
|
||||
|
||||
AssertLSPConfig {
|
||||
\ 'python': {
|
||||
\ 'analysis': {'logLevel': 'warning'},
|
||||
\ 'pythonPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/python'),
|
||||
\ 'venvPath': ale#path#Simplify(g:dir . '/python_paths/with_virtualenv/env'),
|
||||
\ },
|
||||
\ 'pyright': {
|
||||
\ 'disableLanguageServices': v:true,
|
||||
\ },
|
||||
\}
|
|
@ -526,3 +526,73 @@ Execute(Should handle completion messages with the deprecated insertText attribu
|
|||
\ ],
|
||||
\ },
|
||||
\ })
|
||||
|
||||
Execute(Should handle completion messages with additionalTextEdits):
|
||||
AssertEqual
|
||||
\ [
|
||||
\ {
|
||||
\ 'word': 'next_callback',
|
||||
\ 'menu': 'PlayTimeCallback',
|
||||
\ 'info': '',
|
||||
\ 'kind': 'v',
|
||||
\ 'icase': 1,
|
||||
\ 'user_data': json_encode({
|
||||
\ 'codeActions': [
|
||||
\ {
|
||||
\ 'description': 'completion',
|
||||
\ 'changes': [
|
||||
\ {
|
||||
\ 'fileName': expand('#' . bufnr('') . ':p'),
|
||||
\ 'textChanges': [
|
||||
\ {
|
||||
\ 'start': {
|
||||
\ 'line': 11,
|
||||
\ 'offset': 2,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 13,
|
||||
\ 'offset': 4,
|
||||
\ },
|
||||
\ 'newText': 'from "module" import next_callback',
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\ ],
|
||||
\ }),
|
||||
\ },
|
||||
\ ],
|
||||
\ ale#completion#ParseLSPCompletions({
|
||||
\ 'id': 226,
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ 'result': {
|
||||
\ 'isIncomplete': v:false,
|
||||
\ 'items': [
|
||||
\ {
|
||||
\ 'detail': 'PlayTimeCallback',
|
||||
\ 'filterText': 'next_callback',
|
||||
\ 'insertText': 'next_callback',
|
||||
\ 'insertTextFormat': 1,
|
||||
\ 'kind': 6,
|
||||
\ 'label': ' next_callback',
|
||||
\ 'sortText': '3ee19999next_callback',
|
||||
\ 'additionalTextEdits': [
|
||||
\ {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 10,
|
||||
\ 'character': 1,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 12,
|
||||
\ 'character': 3,
|
||||
\ },
|
||||
\ },
|
||||
\ 'newText': 'from "module" import next_callback',
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\ })
|
||||
|
|
|
@ -37,6 +37,7 @@ Execute(ale#completion#GetCompletionPositionForDeoplete() should return the posi
|
|||
AssertEqual 4, ale#completion#GetCompletionPositionForDeoplete('foo bar')
|
||||
|
||||
Execute(ale#completion#CanProvideCompletions should return 0 when no completion sources are available):
|
||||
let b:ale_linters = ['flake8']
|
||||
AssertEqual 0, ale#completion#CanProvideCompletions()
|
||||
|
||||
Execute(ale#completion#CanProvideCompletions should return 1 when at least one completion source is available):
|
||||
|
|
|
@ -20,11 +20,12 @@ Execute(The astyle callback should return the correct default values):
|
|||
" Because this file doesn't exist, no astylrc config
|
||||
" exists near it. Therefore, project_options is empty.
|
||||
call ale#test#SetFilename('../c_files/testfile.c')
|
||||
let targetfile = bufname(bufnr('%'))
|
||||
|
||||
AssertEqual
|
||||
\ {
|
||||
\ 'command': ale#Escape(g:ale_c_astyle_executable)
|
||||
\ . ' --stdin='
|
||||
\ . ' --stdin=' . ale#Escape(targetfile)
|
||||
\ },
|
||||
\ ale#fixers#astyle#Fix(bufnr(''))
|
||||
|
||||
|
@ -33,46 +34,63 @@ Execute(The astyle callback should support cpp files):
|
|||
" exists near it. Therefore, project_options is empty.
|
||||
call ale#test#SetFilename('../cpp_files/dummy.cpp')
|
||||
set filetype=cpp " The test fails without this
|
||||
let targetfile = bufname(bufnr('%'))
|
||||
|
||||
AssertEqual
|
||||
\ {
|
||||
\ 'command': ale#Escape(g:ale_cpp_astyle_executable)
|
||||
\ . ' --stdin='
|
||||
\ . ' --stdin=' . ale#Escape(targetfile)
|
||||
\ },
|
||||
\ ale#fixers#astyle#Fix(bufnr(''))
|
||||
|
||||
Execute(The astyle callback should support cpp files with option file set):
|
||||
call ale#test#SetFilename('../cpp_files/dummy.cpp')
|
||||
let g:ale_cpp_astyle_project_options = '.astylerc_cpp'
|
||||
let targetfile = bufname(bufnr('%'))
|
||||
set filetype=cpp " The test fails without this
|
||||
|
||||
AssertEqual
|
||||
\ {
|
||||
\ 'command': ale#Escape('invalidpp')
|
||||
\ . ' --project=' . g:ale_cpp_astyle_project_options
|
||||
\ . ' --stdin='
|
||||
\ . ' --stdin=' . ale#Escape(targetfile)
|
||||
\ },
|
||||
\ ale#fixers#astyle#Fix(bufnr(''))
|
||||
|
||||
Execute(The astyle callback should return the correct default values with an option file set):
|
||||
Execute(The astyle callback should return the correct default values with a specified option file):
|
||||
call ale#test#SetFilename('../c_files/testfile.c')
|
||||
let g:ale_c_astyle_project_options = '.astylerc_c'
|
||||
let targetfile = bufname(bufnr('%'))
|
||||
|
||||
AssertEqual
|
||||
\ {
|
||||
\ 'command': ale#Escape('xxxinvalid')
|
||||
\ . ' --project=' . g:ale_c_astyle_project_options
|
||||
\ . ' --stdin='
|
||||
\ . ' --stdin=' . ale#Escape(targetfile)
|
||||
\ },
|
||||
\ ale#fixers#astyle#Fix(bufnr(''))
|
||||
|
||||
Execute(The astyle callback should find nearest default option file _astylrc):
|
||||
call ale#test#SetFilename('../test_c_projects/makefile_project/subdir/file.c')
|
||||
let targetfile = bufname(bufnr('%'))
|
||||
|
||||
AssertEqual
|
||||
\ {
|
||||
\ 'command': ale#Escape('xxxinvalid')
|
||||
\ . ' --project=_astylerc'
|
||||
\ . ' --stdin='
|
||||
\ . ' --stdin=' . ale#Escape(targetfile)
|
||||
\ },
|
||||
\ ale#fixers#astyle#Fix(bufnr(''))
|
||||
|
||||
Execute(The astyle callback should find .astylrc in the same directory as src):
|
||||
call ale#test#SetFilename('../test_cpp_project/dummy.cpp')
|
||||
set filetype=cpp " The test fails without this
|
||||
let targetfile = bufname(bufnr('%'))
|
||||
|
||||
AssertEqual
|
||||
\ {
|
||||
\ 'command': ale#Escape('invalidpp')
|
||||
\ . ' --project=.astylerc'
|
||||
\ . ' --stdin=' . ale#Escape(targetfile)
|
||||
\ },
|
||||
\ ale#fixers#astyle#Fix(bufnr(''))
|
||||
|
|
|
@ -10,19 +10,29 @@ Execute(Basic errors should be handled by cppcheck):
|
|||
AssertEqual
|
||||
\ [
|
||||
\ {
|
||||
\ 'lnum': 5,
|
||||
\ 'lnum': 974,
|
||||
\ 'col' : 6,
|
||||
\ 'type': 'E',
|
||||
\ 'text': 'Array ''a[10]'' accessed at index 10, which is out of bounds',
|
||||
\ 'sub_type': '',
|
||||
\ 'text': 'Array ''n[3]'' accessed at index 3, which is out of bounds.',
|
||||
\ 'code': 'arrayIndexOutOfBounds'
|
||||
\ },
|
||||
\ {
|
||||
\ 'lnum': 7,
|
||||
\ 'lnum': 1185,
|
||||
\ 'col' : 10,
|
||||
\ 'type': 'W',
|
||||
\ 'text': 'Some other problem',
|
||||
\ 'sub_type': 'style',
|
||||
\ 'text': 'The scope of the variable ''indxStr'' can be reduced.',
|
||||
\ 'code': 'variableScope'
|
||||
\ },
|
||||
\ ],
|
||||
\ ale#handlers#cppcheck#HandleCppCheckFormat(bufnr(''), [
|
||||
\ '[test.cpp:5]: (error) Array ''a[10]'' accessed at index 10, which is out of bounds',
|
||||
\ '[test.cpp:7]: (warning) Some other problem',
|
||||
\ 'test.cpp:974:6: error: Array ''n[3]'' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\',
|
||||
\ ' n[3]=3;',
|
||||
\ ' ^',
|
||||
\ 'test.cpp:1185:10: style: The scope of the variable ''indxStr'' can be reduced. [variableScope]\',
|
||||
\ ' char indxStr[16];',
|
||||
\ ' ^',
|
||||
\ ])
|
||||
|
||||
Execute(Problems from other files should be ignored by cppcheck):
|
||||
|
@ -32,5 +42,7 @@ Execute(Problems from other files should be ignored by cppcheck):
|
|||
\ [
|
||||
\ ],
|
||||
\ ale#handlers#cppcheck#HandleCppCheckFormat(bufnr(''), [
|
||||
\ '[bar.cpp:5]: (error) Array ''a[10]'' accessed at index 10, which is out of bounds',
|
||||
\ 'bar.cpp:974:6: error: Array ''n[3]'' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\',
|
||||
\ ' n[3]=3;',
|
||||
\ ' ^',
|
||||
\ ])
|
||||
|
|
|
@ -15,8 +15,24 @@ Execute(The golang handler should return the correct filenames):
|
|||
\ 'type': 'E',
|
||||
\ 'filename': ale#path#Simplify(expand('%:p:h') . '/other.go'),
|
||||
\ },
|
||||
\ {
|
||||
\ 'lnum': 18,
|
||||
\ 'col': 0,
|
||||
\ 'text': 'random error',
|
||||
\ 'type': 'E',
|
||||
\ 'filename': ale#path#Simplify(expand('%:p:h') . '/go1.14.go'),
|
||||
\ },
|
||||
\ {
|
||||
\ 'lnum': 36,
|
||||
\ 'col': 2,
|
||||
\ 'text': 'another random error',
|
||||
\ 'type': 'E',
|
||||
\ 'filename': ale#path#Simplify(expand('%:p:h') . '/anothergo1.14.go'),
|
||||
\ },
|
||||
\ ],
|
||||
\ ale#handlers#go#Handler(bufnr(''), [
|
||||
\ 'test.go:27: some error',
|
||||
\ 'other.go:27:5: some error with a column',
|
||||
\ 'vet: go1.14.go:18:0: random error',
|
||||
\ 'vet: anothergo1.14.go:36:2: another random error',
|
||||
\ ])
|
||||
|
|
|
@ -75,3 +75,17 @@ Execute(The Markdownlint handler should parse post v0.22.0 output with column co
|
|||
\ ale#handlers#markdownlint#Handle(0, [
|
||||
\ 'README.md:10:20 MD013/line-length Line length [Expected: 80; Actual: 114]'
|
||||
\ ])
|
||||
|
||||
Execute(The Markdownlint handler should parse output with multiple slashes in rule name correctly):
|
||||
AssertEqual
|
||||
\ [
|
||||
\ {
|
||||
\ 'lnum': 10,
|
||||
\ 'code': 'MD022/blanks-around-headings/blanks-around-headers',
|
||||
\ 'text': 'Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Above] [Context: "### something"]',
|
||||
\ 'type': 'W'
|
||||
\ }
|
||||
\ ],
|
||||
\ ale#handlers#markdownlint#Handle(0, [
|
||||
\ 'README.md:10 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Above] [Context: "### something"]'
|
||||
\ ])
|
||||
|
|
|
@ -131,7 +131,7 @@ Execute(Disabled capabilities should be recognised correctly):
|
|||
\ },
|
||||
\ 'definitionProvider': v:false,
|
||||
\ 'experimental': {},
|
||||
\ 'documentHighlightProvider': v:true
|
||||
\ 'documentHighlightProvider': v:true,
|
||||
\ },
|
||||
\ },
|
||||
\})
|
||||
|
@ -150,6 +150,57 @@ Execute(Disabled capabilities should be recognised correctly):
|
|||
\ b:conn.capabilities
|
||||
AssertEqual [[1, 'initialized', {}]], g:message_list
|
||||
|
||||
Execute(Capabilities should be enabled when send as Dictionaries):
|
||||
call ale#lsp#HandleInitResponse(b:conn, {
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ 'id': 1,
|
||||
\ 'result': {
|
||||
\ 'capabilities': {
|
||||
\ 'renameProvider': {},
|
||||
\ 'executeCommandProvider': {
|
||||
\ 'commands': [],
|
||||
\ },
|
||||
\ 'hoverProvider': {},
|
||||
\ 'documentSymbolProvider': v:true,
|
||||
\ 'documentRangeFormattingProvider': v:true,
|
||||
\ 'codeLensProvider': {
|
||||
\ 'resolveProvider': v:false
|
||||
\ },
|
||||
\ 'completionProvider': {
|
||||
\ 'triggerCharacters': ['.'],
|
||||
\ 'resolveProvider': v:false
|
||||
\ },
|
||||
\ 'referencesProvider': {},
|
||||
\ 'textDocumentSync': 2,
|
||||
\ 'documentFormattingProvider': v:true,
|
||||
\ 'codeActionProvider': v:true,
|
||||
\ 'signatureHelpProvider': {
|
||||
\ 'triggerCharacters': ['(', ','],
|
||||
\ },
|
||||
\ 'definitionProvider': {},
|
||||
\ 'typeDefinitionProvider': {},
|
||||
\ 'experimental': {},
|
||||
\ 'documentHighlightProvider': v:true,
|
||||
\ 'workspaceSymbolProvider': {}
|
||||
\ },
|
||||
\ },
|
||||
\})
|
||||
|
||||
AssertEqual 1, b:conn.initialized
|
||||
AssertEqual
|
||||
\ {
|
||||
\ 'completion_trigger_characters': ['.'],
|
||||
\ 'completion': 1,
|
||||
\ 'references': 1,
|
||||
\ 'hover': 1,
|
||||
\ 'definition': 1,
|
||||
\ 'typeDefinition': 1,
|
||||
\ 'symbol_search': 1,
|
||||
\ 'rename': 1,
|
||||
\ },
|
||||
\ b:conn.capabilities
|
||||
AssertEqual [[1, 'initialized', {}]], g:message_list
|
||||
|
||||
Execute(Results that are not dictionaries should be handled correctly):
|
||||
call ale#lsp#HandleInitResponse(b:conn, {
|
||||
\ 'jsonrpc': '2.0',
|
||||
|
|
|
@ -49,6 +49,7 @@ Before:
|
|||
Save g:ale_lint_on_save
|
||||
Save g:ale_lint_on_text_changed
|
||||
Save g:ale_pattern_options_enabled
|
||||
Save g:ale_hover_cursor
|
||||
|
||||
" Turn everything on by defaul for these tests.
|
||||
let g:ale_completion_enabled = 1
|
||||
|
@ -61,6 +62,7 @@ Before:
|
|||
let g:ale_lint_on_save = 1
|
||||
let g:ale_lint_on_text_changed = 1
|
||||
let g:ale_pattern_options_enabled = 1
|
||||
let g:ale_hover_cursor = 1
|
||||
|
||||
After:
|
||||
delfunction CheckAutocmd
|
||||
|
@ -84,6 +86,7 @@ Execute (All events should be set up when everything is on):
|
|||
\ 'BufWinEnter * call ale#events#LintOnEnter(str2nr(expand(''<abuf>'')))',
|
||||
\ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))',
|
||||
\ 'CursorHold * if exists(''*ale#engine#Cleanup'') | call ale#cursor#EchoCursorWarningWithDelay() | endif',
|
||||
\ 'CursorHold if exists(''*ale#lsp#Send'') | call ale#hover#ShowTruncatedMessageAtCursor() | endif',
|
||||
\ 'CursorMoved * if exists(''*ale#engine#Cleanup'') | call ale#cursor#EchoCursorWarningWithDelay() | endif',
|
||||
\ 'FileChangedShellPost * call ale#events#FileChangedEvent(str2nr(expand(''<abuf>'')))',
|
||||
\ 'FileType * call ale#events#FileTypeEvent( str2nr(expand(''<abuf>'')), expand(''<amatch>''))',
|
||||
|
@ -95,9 +98,9 @@ Execute (All events should be set up when everything is on):
|
|||
\ CheckAutocmd('ALEEvents')
|
||||
|
||||
Execute (Only the required events should be bound even if various settings are off):
|
||||
let g:ale_enabled = 1
|
||||
let g:ale_completion_enabled = 0
|
||||
let g:ale_echo_cursor = 0
|
||||
let g:ale_enabled = 0
|
||||
let g:ale_fix_on_save = 0
|
||||
let g:ale_lint_on_enter = 0
|
||||
let g:ale_lint_on_filetype_changed = 0
|
||||
|
@ -105,6 +108,7 @@ Execute (Only the required events should be bound even if various settings are o
|
|||
let g:ale_lint_on_save = 0
|
||||
let g:ale_lint_on_text_changed = 0
|
||||
let g:ale_pattern_options_enabled = 0
|
||||
let g:ale_hover_cursor = 0
|
||||
|
||||
AssertEqual
|
||||
\ [
|
||||
|
@ -114,6 +118,28 @@ Execute (Only the required events should be bound even if various settings are o
|
|||
\ ],
|
||||
\ CheckAutocmd('ALEEvents')
|
||||
|
||||
Execute (The cursor hoever event should be enabled with g:ale_hover_cursor = 1):
|
||||
let g:ale_enabled = 1
|
||||
let g:ale_completion_enabled = 0
|
||||
let g:ale_echo_cursor = 0
|
||||
let g:ale_fix_on_save = 0
|
||||
let g:ale_lint_on_enter = 0
|
||||
let g:ale_lint_on_filetype_changed = 0
|
||||
let g:ale_lint_on_insert_leave = 0
|
||||
let g:ale_lint_on_save = 0
|
||||
let g:ale_lint_on_text_changed = 0
|
||||
let g:ale_pattern_options_enabled = 0
|
||||
let g:ale_hover_cursor = 1
|
||||
|
||||
AssertEqual
|
||||
\ [
|
||||
\ 'BufEnter * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))',
|
||||
\ 'BufReadPost * call ale#events#ReadOrEnterEvent(str2nr(expand(''<abuf>'')))',
|
||||
\ 'BufWritePost * call ale#events#SaveEvent(str2nr(expand(''<abuf>'')))',
|
||||
\ 'CursorHold * if exists(''*ale#lsp#Send'') | call ale#hover#ShowTruncatedMessageAtCursor() | endif',
|
||||
\ ],
|
||||
\ CheckAutocmd('ALEEvents')
|
||||
|
||||
Execute (g:ale_lint_on_text_changed = 1 bind both events):
|
||||
let g:ale_lint_on_text_changed = 1
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ Execute(The defaults for the help filetype should be correct):
|
|||
AssertEqual [], GetLinterNames('help')
|
||||
|
||||
Execute(The defaults for the python filetype should be correct):
|
||||
AssertEqual ['flake8', 'mypy', 'pylint'], GetLinterNames('python')
|
||||
AssertEqual ['flake8', 'mypy', 'pylint', 'pyright'], GetLinterNames('python')
|
||||
|
||||
let g:ale_linters_explicit = 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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -133,6 +133,12 @@ Execute(LSP hover responses with markup content should be handled):
|
|||
AssertEqual ['markup'], g:echo_list
|
||||
AssertEqual {}, ale#hover#GetMap()
|
||||
|
||||
Execute(LSP hover responses with markup content missing values should be handled):
|
||||
call HandleValidLSPResult({'contents': {'kind': 'something'}})
|
||||
|
||||
AssertEqual [], g:echo_list
|
||||
AssertEqual {}, ale#hover#GetMap()
|
||||
|
||||
Execute(LSP hover response with lists of strings should be handled):
|
||||
call HandleValidLSPResult({'contents': [
|
||||
\ "foo\n",
|
||||
|
@ -145,6 +151,7 @@ Execute(LSP hover response with lists of strings should be handled):
|
|||
Execute(LSP hover response with lists of strings and marked strings should be handled):
|
||||
call HandleValidLSPResult({'contents': [
|
||||
\ {'language': 'rust', 'value': 'foo'},
|
||||
\ {'language': 'foobar'},
|
||||
\ "bar\n",
|
||||
\]})
|
||||
|
||||
|
|
|
@ -327,6 +327,115 @@ Execute(Code actions from LSP should be handled):
|
|||
\ ],
|
||||
\ g:code_actions
|
||||
|
||||
Execute(DocumentChanges from LSP should be handled):
|
||||
call ale#rename#HandleLSPResponse(1, {
|
||||
\ 'id': 3,
|
||||
\ 'result': {
|
||||
\ 'documentChanges': [
|
||||
\ {
|
||||
\ 'textDocument': {
|
||||
\ 'version': 1.0,
|
||||
\ 'uri': 'file:///foo/bar/file1.ts',
|
||||
\ },
|
||||
\ 'edits': [
|
||||
\ {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 2,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 3,
|
||||
\ 'character': 4,
|
||||
\ },
|
||||
\ },
|
||||
\ 'newText': 'bla123',
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\})
|
||||
|
||||
AssertEqual
|
||||
\ [
|
||||
\ {
|
||||
\ 'description': 'rename',
|
||||
\ 'changes': [
|
||||
\ {
|
||||
\ 'fileName': '/foo/bar/file1.ts',
|
||||
\ 'textChanges': [
|
||||
\ {
|
||||
\ 'start': {
|
||||
\ 'line': 2,
|
||||
\ 'offset': 3,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 4,
|
||||
\ 'offset': 5,
|
||||
\ },
|
||||
\ 'newText': 'bla123',
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\ ],
|
||||
\ }
|
||||
\ ],
|
||||
\ g:code_actions
|
||||
|
||||
Execute(Single DocumentChange from LSP should be handled):
|
||||
call ale#rename#HandleLSPResponse(1, {
|
||||
\ 'id': 3,
|
||||
\ 'result': {
|
||||
\ 'documentChanges': {
|
||||
\ 'textDocument': {
|
||||
\ 'version': 1.0,
|
||||
\ 'uri': 'file:///foo/bar/file1.ts',
|
||||
\ },
|
||||
\ 'edits': [
|
||||
\ {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 2,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 3,
|
||||
\ 'character': 4,
|
||||
\ },
|
||||
\ },
|
||||
\ 'newText': 'bla123',
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\ },
|
||||
\})
|
||||
|
||||
AssertEqual
|
||||
\ [
|
||||
\ {
|
||||
\ 'description': 'rename',
|
||||
\ 'changes': [
|
||||
\ {
|
||||
\ 'fileName': '/foo/bar/file1.ts',
|
||||
\ 'textChanges': [
|
||||
\ {
|
||||
\ 'start': {
|
||||
\ 'line': 2,
|
||||
\ 'offset': 3,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 4,
|
||||
\ 'offset': 5,
|
||||
\ },
|
||||
\ 'newText': 'bla123',
|
||||
\ },
|
||||
\ ],
|
||||
\ },
|
||||
\ ],
|
||||
\ }
|
||||
\ ],
|
||||
\ g:code_actions
|
||||
Execute(LSP should perform no action when no result):
|
||||
call ale#rename#HandleLSPResponse(1, {
|
||||
\ 'id': 3,
|
||||
|
|
Loading…
Reference in New Issue