mirror of
1
0
Fork 0

update plugins

ran the plugin update script
This commit is contained in:
Geezus 2019-05-31 13:39:36 -05:00
parent f83dc94c4a
commit c3c74ec7e3
70 changed files with 1120 additions and 486 deletions

View File

@ -5,7 +5,10 @@ call ale#Set('asm_gcc_executable', 'gcc')
call ale#Set('asm_gcc_options', '-Wall')
function! ale_linters#asm#gcc#GetCommand(buffer) abort
return '%e -x assembler -fsyntax-only '
" `-o /dev/null` or `-o null` is needed to catch all errors,
" -fsyntax-only doesn't catch everything.
return '%e -x assembler'
\ . ' -o ' . g:ale#util#nul_file
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -'
endfunction

View File

@ -4,12 +4,6 @@
call ale#Set('c_clangd_executable', 'clangd')
call ale#Set('c_clangd_options', '')
function! ale_linters#c#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction
function! ale_linters#c#clangd#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'c_clangd_options'))
endfunction
@ -19,5 +13,5 @@ call ale#linter#Define('c', {
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'c_clangd_executable')},
\ 'command': function('ale_linters#c#clangd#GetCommand'),
\ 'project_root': function('ale_linters#c#clangd#GetProjectRoot'),
\ 'project_root': function('ale#c#FindProjectRoot'),
\})

View File

@ -9,19 +9,16 @@ function! ale_linters#c#cppcheck#GetCommand(buffer) abort
"
" If we find it, we'll `cd` to where the compile_commands.json file is,
" then use the file to set up import paths, etc.
let l:compile_commmands_path = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
let l:cd_command = !empty(l:compile_commmands_path)
\ ? ale#path#CdString(fnamemodify(l:compile_commmands_path, ':h'))
\ : ''
let l:compile_commands_option = !empty(l:compile_commmands_path)
\ ? '--project=compile_commands.json '
let [l:dir, l:json_path] = ale#c#FindCompileCommands(a:buffer)
let l:cd_command = !empty(l:dir) ? ale#path#CdString(l:dir) : ''
let l:compile_commands_option = !empty(l:json_path)
\ ? '--project=' . ale#Escape(l:json_path[len(l:dir) + 1: ])
\ : ''
return l:cd_command
\ . '%e -q --language=c '
\ . l:compile_commands_option
\ . ale#Var(a:buffer, 'c_cppcheck_options')
\ . '%e -q --language=c'
\ . ale#Pad(l:compile_commands_option)
\ . ale#Pad(ale#Var(a:buffer, 'c_cppcheck_options'))
\ . ' %t'
endfunction

View File

@ -5,13 +5,15 @@ call ale#Set('c_cquery_executable', 'cquery')
call ale#Set('c_cquery_cache_directory', expand('~/.cache/cquery'))
function! ale_linters#c#cquery#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
" Try to find cquery configuration files first.
let l:config = ale#path#FindNearestFile(a:buffer, '.cquery')
if empty(l:project_root)
let l:project_root = ale#path#FindNearestFile(a:buffer, '.cquery')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
" Fall back on default project root detection.
return ale#c#FindProjectRoot(a:buffer)
endfunction
function! ale_linters#c#cquery#GetInitializationOptions(buffer) abort

View File

@ -9,7 +9,11 @@ function! ale_linters#c#gcc#GetCommand(buffer, output) abort
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
return '%e -S -x c -fsyntax-only'
"
" `-o /dev/null` or `-o null` is needed to catch all errors,
" -fsyntax-only doesn't catch everything.
return '%e -S -x c'
\ . ' -o ' . g:ale#util#nul_file
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#Pad(l:cflags)
\ . ale#Pad(ale#Var(a:buffer, 'c_gcc_options')) . ' -'

View File

@ -12,7 +12,8 @@ function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort
let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
if empty(l:build_dir)
let l:build_dir = ale#path#Dirname(ale#c#FindCompileCommands(a:buffer))
let [l:root, l:json_file] = ale#c#FindCompileCommands(a:buffer)
let l:build_dir = ale#path#Dirname(l:json_file)
endif
" The extra arguments in the command are used to prevent .plist files from

View File

@ -4,12 +4,6 @@
call ale#Set('cpp_clangd_executable', 'clangd')
call ale#Set('cpp_clangd_options', '')
function! ale_linters#cpp#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction
function! ale_linters#cpp#clangd#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'cpp_clangd_options'))
endfunction
@ -19,5 +13,5 @@ call ale#linter#Define('cpp', {
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'cpp_clangd_executable')},
\ 'command': function('ale_linters#cpp#clangd#GetCommand'),
\ 'project_root': function('ale_linters#cpp#clangd#GetProjectRoot'),
\ 'project_root': function('ale#c#FindProjectRoot'),
\})

View File

@ -9,19 +9,16 @@ function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
"
" If we find it, we'll `cd` to where the compile_commands.json file is,
" then use the file to set up import paths, etc.
let l:compile_commmands_path = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
let l:cd_command = !empty(l:compile_commmands_path)
\ ? ale#path#CdString(fnamemodify(l:compile_commmands_path, ':h'))
\ : ''
let l:compile_commands_option = !empty(l:compile_commmands_path)
\ ? '--project=compile_commands.json '
let [l:dir, l:json_path] = ale#c#FindCompileCommands(a:buffer)
let l:cd_command = !empty(l:dir) ? ale#path#CdString(l:dir) : ''
let l:compile_commands_option = !empty(l:json_path)
\ ? '--project=' . ale#Escape(l:json_path[len(l:dir) + 1: ])
\ : ''
return l:cd_command
\ . '%e -q --language=c++ '
\ . l:compile_commands_option
\ . ale#Var(a:buffer, 'cpp_cppcheck_options')
\ . '%e -q --language=c++'
\ . ale#Pad(l:compile_commands_option)
\ . ale#Pad(ale#Var(a:buffer, 'cpp_cppcheck_options'))
\ . ' %t'
endfunction

View File

@ -5,13 +5,15 @@ call ale#Set('cpp_cquery_executable', 'cquery')
call ale#Set('cpp_cquery_cache_directory', expand('~/.cache/cquery'))
function! ale_linters#cpp#cquery#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
" Try to find cquery configuration files first.
let l:config = ale#path#FindNearestFile(a:buffer, '.cquery')
if empty(l:project_root)
let l:project_root = ale#path#FindNearestFile(a:buffer, '.cquery')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
" Fall back on default project root detection.
return ale#c#FindProjectRoot(a:buffer)
endfunction
function! ale_linters#cpp#cquery#GetInitializationOptions(buffer) abort

View File

@ -9,7 +9,11 @@ function! ale_linters#cpp#gcc#GetCommand(buffer, output) abort
" -iquote with the directory the file is in makes #include work for
" headers in the same directory.
return '%e -S -x c++ -fsyntax-only'
"
" `-o /dev/null` or `-o null` is needed to catch all errors,
" -fsyntax-only doesn't catch everything.
return '%e -S -x c++'
\ . ' -o ' . g:ale#util#nul_file
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#Pad(l:cflags)
\ . ale#Pad(ale#Var(a:buffer, 'cpp_gcc_options')) . ' -'

View File

@ -0,0 +1,93 @@
" Author: Autoine Gagne - https://github.com/AntoineGagne
" Description: Define a checker that runs dialyzer on Erlang files.
let g:ale_erlang_dialyzer_executable =
\ get(g:, 'ale_erlang_dialyzer_executable', 'dialyzer')
let g:ale_erlang_dialyzer_plt_file =
\ get(g:, 'ale_erlang_dialyzer_plt_file', '')
let g:ale_erlang_dialyzer_rebar3_profile =
\ get(g:, 'ale_erlang_dialyzer_rebar3_profile', 'default')
function! ale_linters#erlang#dialyzer#GetRebar3Profile(buffer) abort
return ale#Var(a:buffer, 'erlang_dialyzer_rebar3_profile')
endfunction
function! ale_linters#erlang#dialyzer#FindPlt(buffer) abort
let l:plt_file = ''
let l:rebar3_profile = ale_linters#erlang#dialyzer#GetRebar3Profile(a:buffer)
let l:plt_file_directory = ale#path#FindNearestDirectory(a:buffer, '_build' . l:rebar3_profile)
if !empty(l:plt_file_directory)
let l:plt_file = split(globpath(l:plt_file_directory, '/*_plt'), '\n')
endif
if !empty(l:plt_file)
return l:plt_file[0]
endif
if !empty($REBAR_PLT_DIR)
return expand('$REBAR_PLT_DIR/dialyzer/plt')
endif
return expand('$HOME/.dialyzer_plt')
endfunction
function! ale_linters#erlang#dialyzer#GetPlt(buffer) abort
let l:plt_file = ale#Var(a:buffer, 'erlang_dialyzer_plt_file')
if !empty(l:plt_file)
return l:plt_file
endif
return ale_linters#erlang#dialyzer#FindPlt(a:buffer)
endfunction
function! ale_linters#erlang#dialyzer#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'erlang_dialyzer_executable')
endfunction
function! ale_linters#erlang#dialyzer#GetCommand(buffer) abort
let l:command = ale#Escape(ale_linters#erlang#dialyzer#GetExecutable(a:buffer))
\ . ' -n'
\ . ' --plt ' . ale#Escape(ale_linters#erlang#dialyzer#GetPlt(a:buffer))
\ . ' -Wunmatched_returns'
\ . ' -Werror_handling'
\ . ' -Wrace_conditions'
\ . ' -Wunderspecs'
\ . ' %s'
return l:command
endfunction
function! ale_linters#erlang#dialyzer#Handle(buffer, lines) abort
" Match patterns like the following:
"
" erl_tidy_prv_fmt.erl:3: Callback info about the provider behaviour is not available
let l:pattern = '^\S\+:\(\d\+\): \(.\+\)$'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) != 0
let l:code = l:match[2]
call add(l:output, {
\ 'lnum': str2nr(l:match[1]),
\ 'lcol': 0,
\ 'text': l:code,
\ 'type': 'W'
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('erlang', {
\ 'name': 'dialyzer',
\ 'executable': function('ale_linters#erlang#dialyzer#GetExecutable'),
\ 'command': function('ale_linters#erlang#dialyzer#GetCommand'),
\ 'callback': function('ale_linters#erlang#dialyzer#Handle'),
\ 'lint_file': 1
\})

View File

@ -17,6 +17,10 @@ function! ale_linters#java#checkstyle#Handle(buffer, lines) abort
\})
endfor
if !empty(l:output)
return l:output
endif
" old checkstyle versions
let l:pattern = '\v(.+):(\d+): ([^:]+): (.+)$'

View File

@ -4,6 +4,8 @@
let s:version_cache = {}
call ale#Set('java_eclipselsp_path', ale#path#Simplify($HOME . '/eclipse.jdt.ls'))
call ale#Set('java_eclipselsp_config_path', '')
call ale#Set('java_eclipselsp_workspace_path', '')
call ale#Set('java_eclipselsp_executable', 'java')
function! ale_linters#java#eclipselsp#Executable(buffer) abort
@ -32,11 +34,23 @@ function! ale_linters#java#eclipselsp#JarPath(buffer) abort
return l:files[0]
endif
" Search jar file within system package path
let l:files = globpath('/usr/share/java/jdtls/plugins', 'org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
if len(l:files) == 1
return l:files[0]
endif
return ''
endfunction
function! ale_linters#java#eclipselsp#ConfigurationPath(buffer) abort
let l:path = fnamemodify(ale_linters#java#eclipselsp#JarPath(a:buffer), ':p:h:h')
let l:config_path = ale#Var(a:buffer, 'java_eclipselsp_config_path')
if !empty(l:config_path)
return ale#path#Simplify(l:config_path)
endif
if has('win32')
let l:path = l:path . '/config_win'
@ -76,6 +90,16 @@ function! ale_linters#java#eclipselsp#CommandWithVersion(buffer, version_lines,
return ale_linters#java#eclipselsp#Command(a:buffer, l:version)
endfunction
function! ale_linters#java#eclipselsp#WorkspacePath(buffer) abort
let l:wspath = ale#Var(a:buffer, 'java_eclipselsp_workspace_path')
if !empty(l:wspath)
return l:wspath
endif
return ale#path#Dirname(ale#java#FindProjectRoot(a:buffer))
endfunction
function! ale_linters#java#eclipselsp#Command(buffer, version) abort
let l:path = ale#Var(a:buffer, 'java_eclipselsp_path')
@ -89,11 +113,11 @@ function! ale_linters#java#eclipselsp#Command(buffer, version) abort
\ '-noverify',
\ '-Xmx1G',
\ '-jar',
\ ale_linters#java#eclipselsp#JarPath(a:buffer),
\ ale#Escape(ale_linters#java#eclipselsp#JarPath(a:buffer)),
\ '-configuration',
\ ale_linters#java#eclipselsp#ConfigurationPath(a:buffer),
\ ale#Escape(ale_linters#java#eclipselsp#ConfigurationPath(a:buffer)),
\ '-data',
\ ale#java#FindProjectRoot(a:buffer)
\ ale#Escape(ale_linters#java#eclipselsp#WorkspacePath(a:buffer))
\ ]
if ale#semver#GTE(a:version, [1, 9])

View File

@ -4,12 +4,6 @@
call ale#Set('objc_clangd_executable', 'clangd')
call ale#Set('objc_clangd_options', '')
function! ale_linters#objc#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction
function! ale_linters#objc#clangd#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'objc_clangd_options'))
endfunction
@ -19,5 +13,5 @@ call ale#linter#Define('objc', {
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'objc_clangd_executable')},
\ 'command': function('ale_linters#objc#clangd#GetCommand'),
\ 'project_root': function('ale_linters#objc#clangd#GetProjectRoot'),
\ 'project_root': function('ale#c#FindProjectRoot'),
\})

View File

@ -4,12 +4,6 @@
call ale#Set('objcpp_clangd_executable', 'clangd')
call ale#Set('objcpp_clangd_options', '')
function! ale_linters#objcpp#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction
function! ale_linters#objcpp#clangd#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'objcpp_clangd_options'))
endfunction
@ -19,5 +13,5 @@ call ale#linter#Define('objcpp', {
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'objcpp_clangd_executable')},
\ 'command': function('ale_linters#objcpp#clangd#GetCommand'),
\ 'project_root': function('ale_linters#objcpp#clangd#GetProjectRoot'),
\ 'project_root': function('ale#c#FindProjectRoot'),
\})

View File

@ -10,13 +10,13 @@ call ale#Set('php_phpcs_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#php#phpcs#GetCommand(buffer) abort
let l:standard = ale#Var(a:buffer, 'php_phpcs_standard')
let l:standard_option = !empty(l:standard)
\ ? '--standard=' . l:standard
\ ? '--standard=' . ale#Escape(l:standard)
\ : ''
let l:options = ale#Var(a:buffer, 'php_phpcs_options')
return '%e -s --report=emacs --stdin-path=%s'
\ . ale#Pad(l:standard_option)
\ . ale#Pad(l:options)
return ale#path#BufferCdString(a:buffer)
\ . '%e -s --report=emacs --stdin-path=%s'
\ . ale#Pad(l:standard_option)
\ . ale#Pad(ale#Var(a:buffer, 'php_phpcs_options'))
endfunction
function! ale_linters#php#phpcs#Handle(buffer, lines) abort

View File

@ -0,0 +1,49 @@
" Author: Keith Maxwell <keith.maxwell@gmail.com>
" Description: terraform fmt to check for errors
call ale#Set('terraform_terraform_executable', 'terraform')
function! ale_linters#terraform#terraform#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'terraform_terraform_executable')
endfunction
function! ale_linters#terraform#terraform#GetCommand(buffer) abort
return ale#Escape(ale_linters#terraform#terraform#GetExecutable(a:buffer))
\ . ' fmt -no-color --check=true -'
endfunction
function! ale_linters#terraform#terraform#Handle(buffer, lines) abort
let l:head = '^Error running fmt: In <standard input>: '
let l:output = []
let l:patterns = [
\ l:head.'At \(\d\+\):\(\d\+\): \(.*\)$',
\ l:head.'\(.*\)$'
\]
for l:match in ale#util#GetMatches(a:lines, l:patterns)
if len(l:match[2]) > 0
call add(l:output, {
\ 'lnum': str2nr(l:match[1]),
\ 'col': str2nr(l:match[2]),
\ 'text': l:match[3],
\ 'type': 'E',
\})
else
call add(l:output, {
\ 'lnum': line('$'),
\ 'text': l:match[1],
\ 'type': 'E',
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('terraform', {
\ 'name': 'terraform',
\ 'output_stream': 'stderr',
\ 'executable': function('ale_linters#terraform#terraform#GetExecutable'),
\ 'command': function('ale_linters#terraform#terraform#GetCommand'),
\ 'callback': 'ale_linters#terraform#terraform#Handle',
\})

View File

@ -96,6 +96,13 @@ function! ale#assert#Fixer(expected_result) abort
AssertEqual a:expected_result, l:result
endfunction
function! ale#assert#FixerNotExecuted() abort
let l:buffer = bufnr('')
let l:result = s:ProcessDeferredCommands(s:FixerFunction(l:buffer))[-1]
Assert empty(l:result), "The fixer will be executed when it shouldn't be"
endfunction
function! ale#assert#LinterNotExecuted() abort
let l:buffer = bufnr('')
let l:linter = s:GetLinter()
@ -158,6 +165,7 @@ endfunction
function! ale#assert#SetUpFixerTestCommands() abort
command! -nargs=+ GivenCommandOutput :call ale#assert#GivenCommandOutput(<args>)
command! -nargs=+ AssertFixer :call ale#assert#Fixer(<args>)
command! -nargs=0 AssertFixerNotExecuted :call ale#assert#FixerNotExecuted()
endfunction
" A dummy function for making sure this module is loaded.
@ -316,4 +324,8 @@ function! ale#assert#TearDownFixerTest() abort
if exists(':AssertFixer')
delcommand AssertFixer
endif
if exists(':AssertFixerNotExecuted')
delcommand AssertFixerNotExecuted
endif
endfunction

View File

@ -23,27 +23,9 @@ function! ale#c#GetBuildDirectory(buffer) abort
return l:build_dir
endif
return ale#path#Dirname(ale#c#FindCompileCommands(a:buffer))
endfunction
let [l:root, l:json_file] = ale#c#FindCompileCommands(a:buffer)
function! ale#c#FindProjectRoot(buffer) abort
for l:project_filename in g:__ale_c_project_filenames
let l:full_path = ale#path#FindNearestFile(a:buffer, l:project_filename)
if !empty(l:full_path)
let l:path = fnamemodify(l:full_path, ':h')
" Correct .git path detection.
if fnamemodify(l:path, ':t') is# '.git'
let l:path = fnamemodify(l:path, ':h')
endif
return l:path
endif
endfor
return ''
return ale#path#Dirname(l:json_file)
endfunction
function! ale#c#AreSpecialCharsBalanced(option) abort
@ -120,7 +102,7 @@ endfunction
function! ale#c#ParseCFlagsFromMakeOutput(buffer, make_output) abort
if !g:ale_c_parse_makefile
return ''
return v:null
endif
let l:buffer_filename = expand('#' . a:buffer . ':t')
@ -140,14 +122,17 @@ function! ale#c#ParseCFlagsFromMakeOutput(buffer, make_output) abort
return ale#c#ParseCFlags(l:makefile_dir, l:cflag_line)
endfunction
" Given a buffer number, find the build subdirectory with compile commands
" The subdirectory is returned without the trailing /
" Given a buffer number, find the project directory containing
" compile_commands.json, and the path to the compile_commands.json file.
"
" If compile_commands.json cannot be found, two empty strings will be
" returned.
function! ale#c#FindCompileCommands(buffer) abort
" Look above the current source file to find compile_commands.json
let l:json_file = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
if !empty(l:json_file)
return l:json_file
return [fnamemodify(l:json_file, ':h'), l:json_file]
endif
" Search in build directories if we can't find it in the project.
@ -157,12 +142,42 @@ function! ale#c#FindCompileCommands(buffer) abort
let l:json_file = l:c_build_dir . s:sep . 'compile_commands.json'
if filereadable(l:json_file)
return l:json_file
return [l:path, l:json_file]
endif
endfor
endfor
return ''
return ['', '']
endfunction
" Find the project root for C/C++ projects.
"
" The location of compile_commands.json will be used to find project roots.
"
" If compile_commands.json cannot be found, other common configuration files
" will be used to detect the project root.
function! ale#c#FindProjectRoot(buffer) abort
let [l:root, l:json_file] = ale#c#FindCompileCommands(a:buffer)
" Fall back on detecting the project root based on other filenames.
if empty(l:root)
for l:project_filename in g:__ale_c_project_filenames
let l:full_path = ale#path#FindNearestFile(a:buffer, l:project_filename)
if !empty(l:full_path)
let l:path = fnamemodify(l:full_path, ':h')
" Correct .git path detection.
if fnamemodify(l:path, ':t') is# '.git'
let l:path = fnamemodify(l:path, ':h')
endif
return l:path
endif
endfor
endif
return l:root
endfunction
" Cache compile_commands.json data in a Dictionary, so we don't need to read
@ -194,10 +209,14 @@ function! s:GetLookupFromCompileCommandsFile(compile_commands_file) abort
let l:raw_data = []
silent! let l:raw_data = json_decode(join(readfile(a:compile_commands_file), ''))
if type(l:raw_data) isnot v:t_list
let l:raw_data = []
endif
let l:file_lookup = {}
let l:dir_lookup = {}
for l:entry in l:raw_data
for l:entry in (type(l:raw_data) is v:t_list ? l:raw_data : [])
let l:basename = tolower(fnamemodify(l:entry.file, ':t'))
let l:file_lookup[l:basename] = get(l:file_lookup, l:basename, []) + [l:entry]
@ -274,25 +293,25 @@ function! ale#c#FlagsFromCompileCommands(buffer, compile_commands_file) abort
endfunction
function! ale#c#GetCFlags(buffer, output) abort
let l:cflags = ' '
let l:cflags = v:null
if ale#Var(a:buffer, 'c_parse_makefile') && !empty(a:output)
let l:cflags = ale#c#ParseCFlagsFromMakeOutput(a:buffer, a:output)
endif
if ale#Var(a:buffer, 'c_parse_compile_commands')
let l:json_file = ale#c#FindCompileCommands(a:buffer)
let [l:root, l:json_file] = ale#c#FindCompileCommands(a:buffer)
if !empty(l:json_file)
let l:cflags = ale#c#FlagsFromCompileCommands(a:buffer, l:json_file)
endif
endif
if l:cflags is# ' '
if l:cflags is v:null
let l:cflags = ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer))
endif
return l:cflags
return l:cflags isnot v:null ? l:cflags : ''
endfunction
function! ale#c#GetMakeCommand(buffer) abort

View File

@ -169,7 +169,7 @@ function! s:ReplaceCompletionOptions() abort
let b:ale_old_omnifunc = &l:omnifunc
endif
let &l:omnifunc = 'ale#completion#OmniFunc'
let &l:omnifunc = 'ale#completion#AutomaticOmniFunc'
endif
if l:source is# 'ale-automatic'
@ -216,18 +216,6 @@ function! ale#completion#GetCompletionPosition() abort
endfunction
function! ale#completion#GetCompletionResult() abort
" Parse a new response if there is one.
if exists('b:ale_completion_response')
\&& exists('b:ale_completion_parser')
let l:response = b:ale_completion_response
let l:parser = b:ale_completion_parser
unlet b:ale_completion_response
unlet b:ale_completion_parser
let b:ale_completion_result = function(l:parser)(l:response)
endif
if exists('b:ale_completion_result')
return b:ale_completion_result
endif
@ -235,7 +223,7 @@ function! ale#completion#GetCompletionResult() abort
return v:null
endfunction
function! ale#completion#OmniFunc(findstart, base) abort
function! ale#completion#AutomaticOmniFunc(findstart, base) abort
if a:findstart
return ale#completion#GetCompletionPosition()
else
@ -247,15 +235,20 @@ function! ale#completion#OmniFunc(findstart, base) abort
endif
endfunction
function! ale#completion#Show(response, completion_parser) abort
function! ale#completion#Show(result) abort
if ale#util#Mode() isnot# 'i'
return
endif
" Set the list in the buffer, temporarily replace omnifunc with our
" function, and then start omni-completion.
let b:ale_completion_response = a:response
let b:ale_completion_parser = a:completion_parser
let b:ale_completion_result = a:result
" Don't try to open the completion menu if there's nothing to show.
if empty(b:ale_completion_result)
return
endif
" Replace completion options shortly before opening the menu.
call s:ReplaceCompletionOptions()
@ -279,6 +272,7 @@ function! s:CompletionStillValid(request_id) abort
\&& (
\ b:ale_completion_info.column == l:column
\ || b:ale_completion_info.source is# 'deoplete'
\ || b:ale_completion_info.source is# 'ale-omnifunc'
\)
endfunction
@ -474,8 +468,7 @@ function! ale#completion#HandleTSServerResponse(conn_id, response) abort
endif
elseif l:command is# 'completionEntryDetails'
call ale#completion#Show(
\ a:response,
\ 'ale#completion#ParseTSServerCompletionEntryDetails',
\ ale#completion#ParseTSServerCompletionEntryDetails(a:response),
\)
endif
endfunction
@ -487,8 +480,7 @@ function! ale#completion#HandleLSPResponse(conn_id, response) abort
endif
call ale#completion#Show(
\ a:response,
\ 'ale#completion#ParseLSPCompletions',
\ ale#completion#ParseLSPCompletions(a:response),
\)
endfunction
@ -529,10 +521,7 @@ function! s:OnReady(linter, lsp_details) abort
let l:message = ale#lsp#message#Completion(
\ l:buffer,
\ b:ale_completion_info.line,
\ min([
\ b:ale_completion_info.line_length,
\ b:ale_completion_info.column,
\ ]) + 1,
\ b:ale_completion_info.column,
\ ale#completion#GetTriggerCharacter(&filetype, b:ale_completion_info.prefix),
\)
endif
@ -570,7 +559,7 @@ function! ale#completion#GetCompletions(source) abort
let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column)
if a:source is# 'ale-automatic' && empty(l:prefix)
return
return 0
endif
let l:line_length = len(getline('.'))
@ -589,11 +578,40 @@ function! ale#completion#GetCompletions(source) abort
let l:buffer = bufnr('')
let l:Callback = function('s:OnReady')
let l:started = 0
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
if ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
let l:started = 1
endif
endif
endfor
return l:started
endfunction
function! ale#completion#OmniFunc(findstart, base) abort
if a:findstart
let l:started = ale#completion#GetCompletions('ale-omnifunc')
if !l:started
" This is the special value for cancelling completions silently.
" See :help complete-functions
return -3
endif
return ale#completion#GetCompletionPosition()
else
let l:result = ale#completion#GetCompletionResult()
while l:result is v:null && !complete_check()
sleep 2ms
let l:result = ale#completion#GetCompletionResult()
endwhile
return l:result isnot v:null ? l:result : []
endif
endfunction
function! s:TimerHandler(...) abort

View File

@ -238,6 +238,12 @@ function! ale#debugging#Info() abort
endfunction
function! ale#debugging#InfoToClipboard() abort
if !has('clipboard')
call s:Echo('clipboard not available. Try :ALEInfoToFile instead.')
return
endif
redir => l:output
silent call ale#debugging#Info()
redir END

View File

@ -2,47 +2,60 @@ call ale#Set('fix_on_save_ignore', {})
" Apply fixes queued up for buffers which may be hidden.
" Vim doesn't let you modify hidden buffers.
function! ale#fix#ApplyQueuedFixes() abort
let l:buffer = bufnr('')
let l:data = get(g:ale_fix_buffer_data, l:buffer, {'done': 0})
function! ale#fix#ApplyQueuedFixes(buffer) abort
let l:data = get(g:ale_fix_buffer_data, a:buffer, {'done': 0})
let l:has_bufline_api = exists('*deletebufline') && exists('*setbufline')
if !l:data.done
if !l:data.done || (!l:has_bufline_api && a:buffer isnot bufnr(''))
return
endif
call remove(g:ale_fix_buffer_data, l:buffer)
call remove(g:ale_fix_buffer_data, a:buffer)
if l:data.changes_made
let l:start_line = len(l:data.output) + 1
let l:end_line = len(l:data.lines_before)
if l:end_line >= l:start_line
let l:save = winsaveview()
silent execute l:start_line . ',' . l:end_line . 'd_'
call winrestview(l:save)
endif
" If the file is in DOS mode, we have to remove carriage returns from
" the ends of lines before calling setline(), or we will see them
" twice.
let l:lines_to_set = getbufvar(l:buffer, '&fileformat') is# 'dos'
let l:new_lines = getbufvar(a:buffer, '&fileformat') is# 'dos'
\ ? map(copy(l:data.output), 'substitute(v:val, ''\r\+$'', '''', '''')')
\ : l:data.output
let l:first_line_to_remove = len(l:new_lines) + 1
call setline(1, l:lines_to_set)
" Use a Vim API for setting lines in other buffers, if available.
if l:has_bufline_api
call setbufline(a:buffer, 1, l:new_lines)
call deletebufline(a:buffer, l:first_line_to_remove, '$')
" Fall back on setting lines the old way, for the current buffer.
else
let l:old_line_length = len(l:data.lines_before)
if l:old_line_length >= l:first_line_to_remove
let l:save = winsaveview()
silent execute
\ l:first_line_to_remove . ',' . l:old_line_length . 'd_'
call winrestview(l:save)
endif
call setline(1, l:new_lines)
endif
if l:data.should_save
if empty(&buftype)
noautocmd :w!
if a:buffer is bufnr('')
if empty(&buftype)
noautocmd :w!
else
set nomodified
endif
else
set nomodified
call writefile(l:new_lines, expand(a:buffer . ':p')) " no-custom-checks
call setbufvar(a:buffer, '&modified', 0)
endif
endif
endif
if l:data.should_save
let l:should_lint = g:ale_fix_on_save
\ && ale#Var(l:buffer, 'lint_on_save')
\ && ale#Var(a:buffer, 'lint_on_save')
else
let l:should_lint = l:data.changes_made
endif
@ -53,7 +66,7 @@ function! ale#fix#ApplyQueuedFixes() abort
" fixing problems.
if g:ale_enabled
\&& l:should_lint
\&& !ale#events#QuitRecently(l:buffer)
\&& !ale#events#QuitRecently(a:buffer)
call ale#Queue(0, l:data.should_save ? 'lint_file' : '')
endif
endfunction
@ -84,7 +97,7 @@ function! ale#fix#ApplyFixes(buffer, output) abort
" We can only change the lines of a buffer which is currently open,
" so try and apply the fixes to the current buffer.
call ale#fix#ApplyQueuedFixes()
call ale#fix#ApplyQueuedFixes(a:buffer)
endfunction
function! s:HandleExit(job_info, buffer, job_output, data) abort
@ -400,5 +413,4 @@ endfunction
" Set up an autocmd command to try and apply buffer fixes when available.
augroup ALEBufferFixGroup
autocmd!
autocmd BufEnter * call ale#fix#ApplyQueuedFixes()
augroup END
autocmd BufEnter * call ale#fix#ApplyQueuedFixes(str2nr(expand('<abuf>')))

View File

@ -305,6 +305,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['tex'],
\ 'description' : 'Indent code within environments, commands, after headings and within special code blocks.',
\ },
\ 'pgformatter': {
\ 'function': 'ale#fixers#pgformatter#Fix',
\ 'suggested_filetypes': ['sql'],
\ 'description': 'A PostgreSQL SQL syntax beautifier',
\ },
\}
" Reset the function registry to the default entries.

View File

@ -35,9 +35,18 @@ endfunction
function! ale#fixers#eslint#ApplyFixForVersion(buffer, version) abort
let l:executable = ale#handlers#eslint#GetExecutable(a:buffer)
let l:config = ale#handlers#eslint#FindConfig(a:buffer)
let l:options = ale#Var(a:buffer, 'javascript_eslint_options')
if empty(l:config)
" Use the configuration file from the options, if configured.
if l:options =~# '\v(^| )-c|(^| )--config'
let l:config = ''
let l:has_config = 1
else
let l:config = ale#handlers#eslint#FindConfig(a:buffer)
let l:has_config = !empty(l:config)
endif
if !l:has_config
return 0
endif
@ -45,6 +54,7 @@ function! ale#fixers#eslint#ApplyFixForVersion(buffer, version) abort
if l:executable =~# 'eslint_d$' && ale#semver#GTE(a:version, [3, 19, 0])
return {
\ 'command': ale#node#Executable(a:buffer, l:executable)
\ . ale#Pad(l:options)
\ . ' --stdin-filename %s --stdin --fix-to-stdout',
\ 'process_with': 'ale#fixers#eslint#ProcessEslintDOutput',
\}
@ -54,6 +64,7 @@ function! ale#fixers#eslint#ApplyFixForVersion(buffer, version) abort
if ale#semver#GTE(a:version, [4, 9, 0])
return {
\ 'command': ale#node#Executable(a:buffer, l:executable)
\ . ale#Pad(l:options)
\ . ' --stdin-filename %s --stdin --fix-dry-run --format=json',
\ 'process_with': 'ale#fixers#eslint#ProcessFixDryRunOutput',
\}
@ -61,7 +72,8 @@ function! ale#fixers#eslint#ApplyFixForVersion(buffer, version) abort
return {
\ 'command': ale#node#Executable(a:buffer, l:executable)
\ . ' -c ' . ale#Escape(l:config)
\ . ale#Pad(l:options)
\ . (!empty(l:config) ? ' -c ' . ale#Escape(l:config) : '')
\ . ' --fix %t',
\ 'read_temporary_file': 1,
\}

View File

@ -0,0 +1,12 @@
call ale#Set('sql_pgformatter_executable', 'pg_format')
call ale#Set('sql_pgformatter_options', '')
function! ale#fixers#pgformatter#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'sql_pgformatter_executable')
let l:options = ale#Var(a:buffer, 'sql_pgformatter_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (empty(l:options) ? '' : ' ' . l:options),
\}
endfunction

View File

@ -3,15 +3,17 @@ scriptencoding utf-8
" Description: Utilities for ccls
function! ale#handlers#ccls#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, '.ccls-root')
" Try to find ccls configuration files first.
let l:config = ale#path#FindNearestFile(a:buffer, '.ccls-root')
if empty(l:project_root)
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
if empty(l:config)
let l:config = ale#path#FindNearestFile(a:buffer, '.ccls')
endif
if empty(l:project_root)
let l:project_root = ale#path#FindNearestFile(a:buffer, '.ccls')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
" Fall back on default project root detection.
return ale#c#FindProjectRoot(a:buffer)
endfunction

View File

@ -11,6 +11,7 @@ let s:pragma_error = '#pragma once in main file'
" <stdin>:10:27: error: invalid operands to binary - (have int and char *)
" -:189:7: note: $/${} is unnecessary on arithmetic variables. [SC2004]
let s:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+)$'
let s:inline_pattern = '\v inlined from .* at \<stdin\>:(\d+):(\d+):$'
function! s:IsHeaderFile(filename) abort
return a:filename =~? '\v\.(h|hpp)$'
@ -25,6 +26,28 @@ function! s:RemoveUnicodeQuotes(text) abort
return l:text
endfunction
function! s:ParseInlinedFunctionProblems(buffer, lines) abort
let l:output = []
let l:pos_match = []
for l:line in a:lines
let l:match = matchlist(l:line, s:pattern)
if !empty(l:match) && !empty(l:pos_match)
call add(l:output, {
\ 'lnum': str2nr(l:pos_match[1]),
\ 'col': str2nr(l:pos_match[2]),
\ 'type': (l:match[4] is# 'error' || l:match[4] is# 'fatal error') ? 'E' : 'W',
\ 'text': s:RemoveUnicodeQuotes(l:match[5]),
\})
endif
let l:pos_match = matchlist(l:line, s:inline_pattern)
endfor
return l:output
endfunction
" Report problems inside of header files just for gcc and clang
function! s:ParseProblemsInHeaders(buffer, lines) abort
let l:output = []
@ -129,6 +152,7 @@ endfunction
function! ale#handlers#gcc#HandleGCCFormatWithIncludes(buffer, lines) abort
let l:output = ale#handlers#gcc#HandleGCCFormat(a:buffer, a:lines)
call extend(l:output, s:ParseInlinedFunctionProblems(a:buffer, a:lines))
call extend(l:output, s:ParseProblemsInHeaders(a:buffer, a:lines))
return l:output

View File

@ -26,41 +26,6 @@ endif
let s:MAX_POS_VALUES = 8
let s:MAX_COL_SIZE = 1073741824 " pow(2, 30)
" Check if we have neovim's buffer highlight API
"
" Below we define some functions' implementation conditionally if this API
" exists or not.
"
" The API itself is more ergonomic and neovim performs highlights positions
" rebases during edits so we see less stalled highlights.
let s:nvim_api = exists('*nvim_buf_add_highlight') && exists('*nvim_buf_clear_namespace')
function! ale#highlight#HasNeovimApi() abort
return s:nvim_api
endfunction
function! ale#highlight#nvim_buf_clear_namespace(...) abort
return call('nvim_buf_clear_namespace', a:000)
endfunction
function! ale#highlight#nvim_buf_add_highlight(...) abort
return call('nvim_buf_add_highlight', a:000)
endfunction
function! s:ale_nvim_highlight_id(bufnr) abort
let l:id = getbufvar(a:bufnr, 'ale_nvim_highlight_id', -1)
if l:id is -1
" NOTE: This will highlight nothing but will allocate new id
let l:id = ale#highlight#nvim_buf_add_highlight(
\ a:bufnr, 0, '', 0, 0, -1
\)
call setbufvar(a:bufnr, 'ale_nvim_highlight_id', l:id)
endif
return l:id
endfunction
function! ale#highlight#CreatePositions(line, col, end_line, end_col) abort
if a:line >= a:end_line
" For single lines, just return the one position.
@ -86,88 +51,11 @@ endfunction
" except these which have matching loclist item entries.
function! ale#highlight#RemoveHighlights() abort
if ale#highlight#HasNeovimApi()
if get(b:, 'ale_nvim_highlight_id', 0)
let l:bufnr = bufnr('%')
" NOTE: 0, -1 means from 0 line till the end of buffer
call ale#highlight#nvim_buf_clear_namespace(
\ l:bufnr,
\ b:ale_nvim_highlight_id,
\ 0, -1
\)
for l:match in getmatches()
if l:match.group =~# '^ALE'
call matchdelete(l:match.id)
endif
else
for l:match in getmatches()
if l:match.group =~# '^ALE'
call matchdelete(l:match.id)
endif
endfor
endif
endfunction
function! s:highlight_line(bufnr, lnum, group) abort
if ale#highlight#HasNeovimApi()
let l:highlight_id = s:ale_nvim_highlight_id(a:bufnr)
call ale#highlight#nvim_buf_add_highlight(
\ a:bufnr, l:highlight_id, a:group,
\ a:lnum - 1, 0, -1
\)
else
call matchaddpos(a:group, [a:lnum])
endif
endfunction
function! s:highlight_range(bufnr, range, group) abort
if ale#highlight#HasNeovimApi()
let l:highlight_id = s:ale_nvim_highlight_id(a:bufnr)
" NOTE: lines and columns indicies are 0-based in nvim_buf_* API.
let l:lnum = a:range.lnum - 1
let l:end_lnum = a:range.end_lnum - 1
let l:col = a:range.col - 1
let l:end_col = a:range.end_col
if l:lnum >= l:end_lnum
" For single lines, just return the one position.
call ale#highlight#nvim_buf_add_highlight(
\ a:bufnr, l:highlight_id, a:group,
\ l:lnum, l:col, l:end_col
\)
else
" highlight first line from start till the line end
call ale#highlight#nvim_buf_add_highlight(
\ a:bufnr, l:highlight_id, a:group,
\ l:lnum, l:col, -1
\)
" highlight all lines between the first and last entirely
let l:cur = l:lnum + 1
while l:cur < l:end_lnum
call ale#highlight#nvim_buf_add_highlight(
\ a:bufnr, l:highlight_id, a:group,
\ l:cur, 0, -1
\ )
let l:cur += 1
endwhile
call ale#highlight#nvim_buf_add_highlight(
\ a:bufnr, l:highlight_id, a:group,
\ l:end_lnum, 0, l:end_col
\)
endif
else
" Set all of the positions, which are chunked into Lists which
" are as large as will be accepted by matchaddpos.
call map(
\ ale#highlight#CreatePositions(
\ a:range.lnum,
\ a:range.col,
\ a:range.end_lnum,
\ a:range.end_col
\ ),
\ 'matchaddpos(a:group, v:val)'
\)
endif
endfor
endfunction
function! s:highlight_line(bufnr, lnum, group) abort

View File

@ -111,7 +111,7 @@ function! ale#loclist_jumping#Jump(direction, ...) abort
if !empty(l:nearest)
normal! m`
call cursor(l:nearest)
call cursor([l:nearest[0], max([l:nearest[1], 1])])
endif
endfunction

View File

@ -321,7 +321,69 @@ endfunction
function! s:SendInitMessage(conn) abort
let [l:init_id, l:init_data] = ale#lsp#CreateMessageData(
\ ale#lsp#message#Initialize(a:conn.root, a:conn.init_options),
\ ale#lsp#message#Initialize(
\ a:conn.root,
\ a:conn.init_options,
\ {
\ 'workspace': {
\ 'applyEdit': v:false,
\ 'didChangeConfiguration': {
\ 'dynamicRegistration': v:false,
\ },
\ 'symbol': {
\ 'dynamicRegistration': v:false,
\ },
\ 'workspaceFolders': v:false,
\ 'configuration': v:false,
\ },
\ 'textDocument': {
\ 'synchronization': {
\ 'dynamicRegistration': v:false,
\ 'willSave': v:false,
\ 'willSaveWaitUntil': v:false,
\ 'didSave': v:true,
\ },
\ 'completion': {
\ 'dynamicRegistration': v:false,
\ 'completionItem': {
\ 'snippetSupport': v:false,
\ 'commitCharactersSupport': v:false,
\ 'documentationFormat': ['plaintext'],
\ 'deprecatedSupport': v:false,
\ 'preselectSupport': v:false,
\ },
\ 'contextSupport': v:false,
\ },
\ 'hover': {
\ 'dynamicRegistration': v:false,
\ 'contentFormat': ['plaintext'],
\ },
\ 'references': {
\ 'dynamicRegistration': v:false,
\ },
\ 'documentSymbol': {
\ 'dynamicRegistration': v:false,
\ 'hierarchicalDocumentSymbolSupport': v:false,
\ },
\ 'definition': {
\ 'dynamicRegistration': v:false,
\ 'linkSupport': v:false,
\ },
\ 'typeDefinition': {
\ 'dynamicRegistration': v:false,
\ },
\ 'publishDiagnostics': {
\ 'relatedInformation': v:true,
\ },
\ 'codeAction': {
\ 'dynamicRegistration': v:false,
\ },
\ 'rename': {
\ 'dynamicRegistration': v:false,
\ },
\ },
\ },
\ ),
\)
let a:conn.init_request_id = l:init_id
call s:SendMessageData(a:conn, l:init_data)

View File

@ -28,14 +28,13 @@ function! ale#lsp#message#GetNextVersionID() abort
return l:id
endfunction
function! ale#lsp#message#Initialize(root_path, initialization_options) abort
" TODO: Define needed capabilities.
function! ale#lsp#message#Initialize(root_path, options, capabilities) abort
" NOTE: rootPath is deprecated in favour of rootUri
return [0, 'initialize', {
\ 'processId': getpid(),
\ 'rootPath': a:root_path,
\ 'capabilities': {},
\ 'initializationOptions': a:initialization_options,
\ 'capabilities': a:capabilities,
\ 'initializationOptions': a:options,
\ 'rootUri': ale#path#ToURI(a:root_path),
\}]
endfunction

View File

@ -31,7 +31,7 @@ endfunction
function! s:HandleLSPDiagnostics(conn_id, response) abort
let l:linter_name = s:lsp_linter_map[a:conn_id]
let l:filename = ale#path#FromURI(a:response.params.uri)
let l:buffer = bufnr(l:filename)
let l:buffer = bufnr('^' . l:filename . '$')
let l:info = get(g:ale_buffer_info, l:buffer, {})
if empty(l:info)
@ -49,7 +49,7 @@ endfunction
function! s:HandleTSServerDiagnostics(response, error_type) abort
let l:linter_name = 'tsserver'
let l:buffer = bufnr(a:response.body.file)
let l:buffer = bufnr('^' . a:response.body.file . '$')
let l:info = get(g:ale_buffer_info, l:buffer, {})
if empty(l:info)

View File

@ -25,7 +25,7 @@ function! ale#python#FindProjectRootIni(buffer) abort
\|| filereadable(l:path . '/tox.ini')
\|| filereadable(l:path . '/mypy.ini')
\|| filereadable(l:path . '/pycodestyle.cfg')
\|| filereadable(l:path . '/flake8.cfg')
\|| filereadable(l:path . '/.flake8')
\|| filereadable(l:path . '/.flake8rc')
\|| filereadable(l:path . '/pylama.ini')
\|| filereadable(l:path . '/pylintrc')

View File

@ -151,9 +151,9 @@ ALE is tested with a suite of tests executed in Travis CI and AppVeyor. ALE
runs tests with the following versions of Vim in the following environments.
1. Vim 8.0.0027 on Linux via Travis CI.
2. Vim 8.1.0204 on Linux via Travis CI.
2. Vim 8.1.0519 on Linux via Travis CI.
3. NeoVim 0.2.0 on Linux via Travis CI.
4. NeoVim 0.3.0 on Linux via Travis CI.
4. NeoVim 0.3.5 on Linux via Travis CI.
5. Vim 8 (stable builds) on Windows via AppVeyor.
If you are developing ALE code on Linux, Mac OSX, or BSD, you can run ALEs
@ -351,6 +351,7 @@ given the above setup are as follows.
`GivenCommandOutput [...]` - Define output for ale#command#Run.
`AssertFixer results` - Check the fixer results
`AssertFixerNotExecuted` - Check that fixers will not be executed.
===============================================================================

View File

@ -3,6 +3,35 @@ ALE Erlang Integration *ale-erlang-options*
===============================================================================
dialyzer *ale-erlang-dialyzer*
g:ale_erlang_dialyzer_executable *g:ale_erlang_dialyzer_executable*
*b:ale_erlang_dialyzer_executable*
Type: |String|
Default: `'dialyzer'`
This variable can be changed to specify the dialyzer executable.
g:ale_erlang_dialyzer_plt_file *g:ale_erlang_dialyzer_plt_file*
*b:ale_erlang_dialyzer_plt_file*
Type: |String|
This variable can be changed to specify the path to the PLT file. By
default, it will search for the PLT file inside the `_build` directory. If
there isn't one, it will fallback to the path `$REBAR_PLT_DIR/dialyzer/plt`.
Otherwise, it will default to `$HOME/.dialyzer_plt`.
g:ale_erlang_dialyzer_rebar3_profile *g:ale_erlang_dialyzer_rebar3_profile*
*b:ale_erlang_dialyzer_rebar3_profile*
Type: |String|
Default: `'default'`
This variable can be changed to specify the profile that is used to
run dialyzer with rebar3.
-------------------------------------------------------------------------------
erlc *ale-erlang-erlc*
g:ale_erlang_erlc_options *g:ale_erlang_erlc_options*

View File

@ -5,7 +5,7 @@ ALE HCL Integration *ale-hcl-options*
===============================================================================
terraform-fmt *ale-hcl-terraform-fmt*
See |ale-terraform-fmt| for information about the available options.
See |ale-terraform-fmt-fixer| for information about the available options.
===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

View File

@ -130,7 +130,7 @@ g:ale_java_eclipselsp_path *g:ale_java_eclipselsp_path*
Absolute path to the location of the eclipse.jdt.ls repository folder. Or if
you have VSCode extension installed the absolute path to the VSCode extensions
folder (e.g. $HOME/.vscode/extensions in Linux).
folder (e.g. $HOME/.vscode/extensions/redhat.java-0.4x.0 in Linux).
g:ale_java_eclipselsp_executable *g:ale_java_eclipse_executable*
@ -141,6 +141,31 @@ g:ale_java_eclipselsp_executable *g:ale_java_eclipse_executable*
This variable can be set to change the executable path used for java.
g:ale_java_eclipselsp_config_path *g:ale_java_eclipse_config_path*
*b:ale_java_eclipse_config_path*
Type: |String|
Default: `''`
Set this variable to change the configuration directory path used by
eclipselsp (e.g. `$HOME/.jdtls` in Linux).
By default ALE will attempt to use the configuration within the installation
directory.
This setting is particularly useful when eclipselsp is installed in a
non-writable directory like `/usr/share/java/jdtls`, as is the case when
installed via system package.
g:ale_java_eclipselsp_workspace_path *g:ale_java_eclipselsp_workspace_path*
*b:ale_java_eclipselsp_workspace_path*
Type: |String|
Default: `''`
If you have Eclipse installed is good idea to set this variable to the
absolute path of the Eclipse workspace. If not set this value will be set to
the parent folder of the project root.
===============================================================================
uncrustify *ale-java-uncrustify*

View File

@ -29,7 +29,7 @@ ALE will look for configuration files with the following filenames. >
tox.ini
mypy.ini
pycodestyle.cfg
flake8.cfg
.flake8
.flake8rc
pylama.ini
pylintrc

View File

@ -2,6 +2,24 @@
ALE SQL Integration *ale-sql-options*
===============================================================================
pgformatter *ale-sql-pgformatter*
g:ale_sql_pgformatter_executable *g:ale_sql_pgformatter_executable*
*b:ale_sql_pgformatter_executable*
Type: |String|
Default: `'pg_format'`
This variable sets executable used for pgformatter.
g:ale_sql_pgformatter_options *g:ale_sql_pgformatter_options*
*b:ale_sql_pgformatter_options*
Type: |String|
Default: `''`
This variable can be set to pass additional options to the pgformatter fixer.
===============================================================================
sqlfmt *ale-sql-sqlfmt*

View File

@ -415,6 +415,7 @@ Notes:
* `solhint`
* `solium`
* SQL
* `pgformatter`
* `sqlfmt`
* `sqlint`
* Stylus

View File

@ -3,7 +3,7 @@ ALE Terraform Integration *ale-terraform-options*
===============================================================================
fmt *ale-terraform-fmt*
terraform-fmt-fixer *ale-terraform-fmt-fixer*
g:ale_terraform_fmt_executable *g:ale_terraform_fmt_executable*
*b:ale_terraform_fmt_executable*
@ -20,6 +20,18 @@ g:ale_terraform_fmt_options *g:ale_terraform_fmt_options*
Default: `''`
===============================================================================
terraform *ale-terraform-terraform*
g:ale_terraform_terraform_executable *g:ale_terraform_terraform_executable*
*b:ale_terraform_terraform_executable*
Type: |String|
Default: `'terraform'`
This variable can be changed to use a different executable for terraform.
===============================================================================
tflint *ale-terraform-tflint*

View File

@ -53,5 +53,25 @@ g:ale_tex_latexindent_options *g:ale_tex_latexindent_options*
===============================================================================
texlab *ale-tex-texlab*
g:ale_tex_texlab_executable *g:ale_tex_texlab_executable*
*b:ale_tex_texlab_executable*
Type: |String|
Default: `'texlab'`
This variable can be changed to change the path to texlab.
g:ale_tex_texlab_options *g:ale_tex_texlab_options*
*b:ale_tex_texlab_options*
Type: |String|
Default: `''`
This variable can be changed to modify flags given to texlab.
===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

View File

@ -349,6 +349,12 @@ is loaded. The delay for completion can be configured with
|g:ale_completion_delay|. This setting should not be enabled if you wish to
use ALE as a completion source for other plugins.
ALE provides an 'omnifunc' function |ale#completion#OmniFunc| for triggering
completion manually with CTRL-X CTRL-O. |i_CTRL-X_CTRL-O| >
" Use ALE's function for omnicompletion.
set omnifunc=ale#completion#OmniFunc
<
ALE will only suggest so many possible matches for completion. The maximum
number of items can be controlled with |g:ale_completion_max_suggestions|.
@ -1991,6 +1997,7 @@ documented in additional help files.
elm-lsp...............................|ale-elm-elm-lsp|
elm-make..............................|ale-elm-elm-make|
erlang..................................|ale-erlang-options|
dialyzer..............................|ale-erlang-dialyzer|
erlc..................................|ale-erlang-erlc|
syntaxerl.............................|ale-erlang-syntaxerl|
eruby...................................|ale-eruby-options|
@ -2229,6 +2236,7 @@ documented in additional help files.
spec....................................|ale-spec-options|
rpmlint...............................|ale-spec-rpmlint|
sql.....................................|ale-sql-options|
pgformatter...........................|ale-sql-pgformatter|
sqlfmt................................|ale-sql-sqlfmt|
stylus..................................|ale-stylus-options|
stylelint.............................|ale-stylus-stylelint|
@ -2239,12 +2247,14 @@ documented in additional help files.
tcl.....................................|ale-tcl-options|
nagelfar..............................|ale-tcl-nagelfar|
terraform...............................|ale-terraform-options|
fmt...................................|ale-terraform-fmt|
terraform-fmt-fixer...................|ale-terraform-fmt-fixer|
terraform.............................|ale-terraform-terraform|
tflint................................|ale-terraform-tflint|
tex.....................................|ale-tex-options|
chktex................................|ale-tex-chktex|
lacheck...............................|ale-tex-lacheck|
latexindent...........................|ale-tex-latexindent|
texlab................................|ale-tex-texlab|
texinfo.................................|ale-texinfo-options|
write-good............................|ale-texinfo-write-good|
text....................................|ale-text-options|
@ -2797,6 +2807,13 @@ ale#command#ManageFile(buffer, filename) *ale#command#ManageFile()*
manages directories separately with the |ale#command#ManageDirectory| function.
ale#completion#OmniFunc(findstart, base) *ale#completion#OmniFunc()*
A completion function to use with 'omnifunc'.
See |ale-completion|.
ale#engine#GetLoclist(buffer) *ale#engine#GetLoclist()*
Given a buffer number, this function will return the list of problems

View File

@ -424,6 +424,7 @@ formatting.
* [solhint](https://github.com/protofire/solhint)
* [solium](https://github.com/duaraghav8/Solium)
* SQL
* [pgformatter](https://github.com/darold/pgFormatter)
* [sqlfmt](https://github.com/jackc/sqlfmt)
* [sqlint](https://github.com/purcell/sqlint)
* Stylus

View File

@ -170,66 +170,101 @@ endfun
" [-- <ELEMENT ? - - ...> --]
call <SID>HtmlIndentPush('a')
call <SID>HtmlIndentPush('abbr')
call <SID>HtmlIndentPush('acronym')
call <SID>HtmlIndentPush('address')
call <SID>HtmlIndentPush('applet')
call <SID>HtmlIndentPush('article')
call <SID>HtmlIndentPush('aside')
call <SID>HtmlIndentPush('audio')
call <SID>HtmlIndentPush('b')
call <SID>HtmlIndentPush('bdi')
call <SID>HtmlIndentPush('bdo')
call <SID>HtmlIndentPush('big')
call <SID>HtmlIndentPush('blockquote')
call <SID>HtmlIndentPush('button')
call <SID>HtmlIndentPush('canvas')
call <SID>HtmlIndentPush('caption')
call <SID>HtmlIndentPush('center')
call <SID>HtmlIndentPush('cite')
call <SID>HtmlIndentPush('code')
call <SID>HtmlIndentPush('colgroup')
call <SID>HtmlIndentPush('content')
call <SID>HtmlIndentPush('data')
call <SID>HtmlIndentPush('datalist')
call <SID>HtmlIndentPush('del')
call <SID>HtmlIndentPush('details')
call <SID>HtmlIndentPush('dfn')
call <SID>HtmlIndentPush('dialog')
call <SID>HtmlIndentPush('dir')
call <SID>HtmlIndentPush('div')
call <SID>HtmlIndentPush('dl')
call <SID>HtmlIndentPush('element')
call <SID>HtmlIndentPush('em')
call <SID>HtmlIndentPush('fieldset')
call <SID>HtmlIndentPush('font')
call <SID>HtmlIndentPush('figcaption')
call <SID>HtmlIndentPush('figure')
call <SID>HtmlIndentPush('footer')
call <SID>HtmlIndentPush('form')
call <SID>HtmlIndentPush('frameset')
call <SID>HtmlIndentPush('h1')
call <SID>HtmlIndentPush('h2')
call <SID>HtmlIndentPush('h3')
call <SID>HtmlIndentPush('h4')
call <SID>HtmlIndentPush('h5')
call <SID>HtmlIndentPush('h6')
call <SID>HtmlIndentPush('header')
call <SID>HtmlIndentPush('hgroup')
call <SID>HtmlIndentPush('i')
call <SID>HtmlIndentPush('iframe')
call <SID>HtmlIndentPush('ins')
call <SID>HtmlIndentPush('kbd')
call <SID>HtmlIndentPush('label')
call <SID>HtmlIndentPush('legend')
call <SID>HtmlIndentPush('li')
call <SID>HtmlIndentPush('main')
call <SID>HtmlIndentPush('map')
call <SID>HtmlIndentPush('mark')
call <SID>HtmlIndentPush('MediaStream')
call <SID>HtmlIndentPush('menu')
call <SID>HtmlIndentPush('noframes')
call <SID>HtmlIndentPush('menuitem')
call <SID>HtmlIndentPush('meter')
call <SID>HtmlIndentPush('nav')
call <SID>HtmlIndentPush('noembed')
call <SID>HtmlIndentPush('noscript')
call <SID>HtmlIndentPush('object')
call <SID>HtmlIndentPush('ol')
call <SID>HtmlIndentPush('optgroup')
call <SID>HtmlIndentPush('option')
call <SID>HtmlIndentPush('output')
call <SID>HtmlIndentPush('picture')
call <SID>HtmlIndentPush('pre')
call <SID>HtmlIndentPush('progress')
call <SID>HtmlIndentPush('q')
call <SID>HtmlIndentPush('rb')
call <SID>HtmlIndentPush('rp')
call <SID>HtmlIndentPush('rt')
call <SID>HtmlIndentPush('rtc')
call <SID>HtmlIndentPush('ruby')
call <SID>HtmlIndentPush('s')
call <SID>HtmlIndentPush('samp')
call <SID>HtmlIndentPush('script')
call <SID>HtmlIndentPush('section')
call <SID>HtmlIndentPush('select')
call <SID>HtmlIndentPush('shadow')
call <SID>HtmlIndentPush('slot')
call <SID>HtmlIndentPush('small')
call <SID>HtmlIndentPush('span')
call <SID>HtmlIndentPush('strong')
call <SID>HtmlIndentPush('style')
call <SID>HtmlIndentPush('sub')
call <SID>HtmlIndentPush('summary')
call <SID>HtmlIndentPush('sup')
call <SID>HtmlIndentPush('table')
call <SID>HtmlIndentPush('template')
call <SID>HtmlIndentPush('textarea')
call <SID>HtmlIndentPush('time')
call <SID>HtmlIndentPush('title')
call <SID>HtmlIndentPush('tt')
call <SID>HtmlIndentPush('u')
call <SID>HtmlIndentPush('ul')
call <SID>HtmlIndentPush('var')
call <SID>HtmlIndentPush('video')
" For some reason the default HTML indentation script doesn't consider these
" elements to be worthy of indentation.
@ -256,6 +291,44 @@ if !exists('g:html_indent_strict_table')
call <SID>HtmlIndentPush('thead')
endif
" [-- <OBSOLETE ELEMENTS ? - - ...> --]
call <SID>HtmlIndentPush('abbr')
call <SID>HtmlIndentPush('acronym')
call <SID>HtmlIndentPush('applet')
call <SID>HtmlIndentPush('audio')
call <SID>HtmlIndentPush('basefont')
call <SID>HtmlIndentPush('bgsound')
call <SID>HtmlIndentPush('big')
call <SID>HtmlIndentPush('blink')
call <SID>HtmlIndentPush('center')
call <SID>HtmlIndentPush('command')
call <SID>HtmlIndentPush('content')
call <SID>HtmlIndentPush('dir')
call <SID>HtmlIndentPush('element')
call <SID>HtmlIndentPush('embed')
call <SID>HtmlIndentPush('font')
call <SID>HtmlIndentPush('frame')
call <SID>HtmlIndentPush('frameset')
call <SID>HtmlIndentPush('image')
call <SID>HtmlIndentPush('img')
call <SID>HtmlIndentPush('isindex')
call <SID>HtmlIndentPush('keygen')
call <SID>HtmlIndentPush('listing')
call <SID>HtmlIndentPush('marquee')
call <SID>HtmlIndentPush('menuitem')
call <SID>HtmlIndentPush('multicol')
call <SID>HtmlIndentPush('nextid')
call <SID>HtmlIndentPush('nobr')
call <SID>HtmlIndentPush('noembed')
call <SID>HtmlIndentPush('noframes')
call <SID>HtmlIndentPush('object')
call <SID>HtmlIndentPush('plaintext')
call <SID>HtmlIndentPush('shadow')
call <SID>HtmlIndentPush('spacer')
call <SID>HtmlIndentPush('strike')
call <SID>HtmlIndentPush('tt')
call <SID>HtmlIndentPush('xmp')
" [-- <Mako Elements> --]
call <SID>MakoIndentPush('%def')
call <SID>MakoIndentPush('%block')

View File

@ -3159,6 +3159,7 @@ function! s:Open(cmd, bang, mods, arg, args) abort
silent! execute '!' . escape(git . ' --no-pager ' . args, '!#%') .
\ (&shell =~# 'csh' ? ' >& ' . temp : ' > ' . temp . ' 2>&1')
finally
redraw!
execute cdback
endtry
let temp = s:Resolve(temp)
@ -3168,7 +3169,7 @@ function! s:Open(cmd, bang, mods, arg, args) abort
endif
silent execute mods a:cmd temp
call fugitive#ReloadStatus()
return 'redraw|echo ' . string(':!' . git . ' ' . args)
return 'echo ' . string(':!' . git . ' ' . args)
endif
let [file, pre] = s:OpenParse(a:args)

View File

@ -10,7 +10,6 @@ function! gitgutter#all(force) abort
let file = expand('#'.bufnr.':p')
if !empty(file)
if index(visible, bufnr) != -1
call gitgutter#init_buffer(bufnr)
call gitgutter#process_buffer(bufnr, a:force)
elseif a:force
call s:reset_tick(bufnr)
@ -21,22 +20,23 @@ function! gitgutter#all(force) abort
endfunction
" Finds the file's path relative to the repo root.
function! gitgutter#init_buffer(bufnr)
if gitgutter#utility#is_active(a:bufnr)
let p = gitgutter#utility#repo_path(a:bufnr, 0)
if type(p) != s:t_string || empty(p)
call gitgutter#utility#set_repo_path(a:bufnr)
call s:setup_maps()
endif
endif
endfunction
function! gitgutter#process_buffer(bufnr, force) abort
" NOTE a:bufnr is not necessarily the current buffer.
if gitgutter#utility#is_active(a:bufnr)
call s:setup_maps(a:bufnr)
if has('patch-7.4.1559')
let l:Callback = function('gitgutter#process_buffer', [a:bufnr, a:force])
else
let l:Callback = {'function': 'gitgutter#process_buffer', 'arguments': [a:bufnr, a:force]}
endif
let how = s:setup_path(a:bufnr, l:Callback)
if [how] == ['async'] " avoid string-to-number conversion if how is a number
return
endif
if a:force || s:has_fresh_changes(a:bufnr)
let diff = ''
@ -108,11 +108,15 @@ endfunction
" }}}
function! s:setup_maps()
function! s:setup_maps(bufnr)
if !g:gitgutter_map_keys
return
endif
if gitgutter#utility#getbufvar(a:bufnr, 'mapped', 0)
return
endif
if !hasmapto('<Plug>GitGutterPrevHunk') && maparg('[c', 'n') ==# ''
nmap <buffer> [c <Plug>GitGutterPrevHunk
endif
@ -142,6 +146,18 @@ function! s:setup_maps()
if !hasmapto('<Plug>GitGutterTextObjectOuterVisual') && maparg('ac', 'x') ==# ''
xmap <buffer> ac <Plug>GitGutterTextObjectOuterVisual
endif
call gitgutter#utility#setbufvar(a:bufnr, 'mapped', 1)
endfunction
function! s:setup_path(bufnr, continuation)
let p = gitgutter#utility#repo_path(a:bufnr, 0)
if type(p) == s:t_string && !empty(p) " if path is known
return
endif
return gitgutter#utility#set_repo_path(a:bufnr, a:continuation)
endfunction
function! s:has_fresh_changes(bufnr) abort

View File

@ -68,9 +68,9 @@ let s:counter = 0
" the hunk headers (@@ -x,y +m,n @@); only possible if
" grep is available.
function! gitgutter#diff#run_diff(bufnr, from, preserve_full_diff) abort
while gitgutter#utility#repo_path(a:bufnr, 0) == -1
sleep 5m
endwhile
if gitgutter#utility#repo_path(a:bufnr, 0) == -1
throw 'gitgutter author fail'
endif
if gitgutter#utility#repo_path(a:bufnr, 0) == -2
throw 'gitgutter not tracked'

View File

@ -114,7 +114,29 @@ function! gitgutter#utility#repo_path(bufnr, shellesc) abort
return a:shellesc ? gitgutter#utility#shellescape(p) : p
endfunction
function! gitgutter#utility#set_repo_path(bufnr) abort
let s:set_path_handler = {}
function! s:set_path_handler.out(buffer, path) abort
let path = s:strip_trailing_new_line(a:path)
call gitgutter#utility#setbufvar(a:buffer, 'path', path)
if type(self.continuation) == type(function('tr'))
call self.continuation()
else
call call(self.continuation.function, self.continuation.arguments)
endif
endfunction
function! s:set_path_handler.err(buffer) abort
call gitgutter#utility#setbufvar(a:buffer, 'path', -2)
endfunction
" continuation - a funcref or hash to call after setting the repo path asynchronously.
"
" Returns 'async' if the the path is set asynchronously, 0 otherwise.
function! gitgutter#utility#set_repo_path(bufnr, continuation) abort
" Values of path:
" * non-empty string - path
" * -1 - pending
@ -124,48 +146,20 @@ function! gitgutter#utility#set_repo_path(bufnr) abort
let cmd = gitgutter#utility#cd_cmd(a:bufnr, g:gitgutter_git_executable.' ls-files --error-unmatch --full-name -z -- '.gitgutter#utility#shellescape(s:filename(a:bufnr)))
if g:gitgutter_async && gitgutter#async#available()
if has('lambda')
call gitgutter#async#execute(cmd, a:bufnr, {
\ 'out': {bufnr, path -> gitgutter#utility#setbufvar(bufnr, 'path', s:strip_trailing_new_line(path))},
\ 'err': {bufnr -> gitgutter#utility#setbufvar(bufnr, 'path', -2)},
\ })
else
if has('nvim') && !has('nvim-0.2.0')
call gitgutter#async#execute(cmd, a:bufnr, {
\ 'out': function('s:set_path'),
\ 'err': function('s:not_tracked_by_git')
\ })
else
call gitgutter#async#execute(cmd, a:bufnr, {
\ 'out': function('s:set_path'),
\ 'err': function('s:set_path', [-2])
\ })
endif
endif
let handler = copy(s:set_path_handler)
let handler.continuation = a:continuation
call gitgutter#async#execute(cmd, a:bufnr, handler)
return 'async'
endif
let path = gitgutter#utility#system(cmd)
if v:shell_error
call gitgutter#utility#setbufvar(a:bufnr, 'path', -2)
else
let path = gitgutter#utility#system(cmd)
if v:shell_error
call gitgutter#utility#setbufvar(a:bufnr, 'path', -2)
else
call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(path))
endif
call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(path))
endif
endfunction
if has('nvim') && !has('nvim-0.2.0')
function! s:not_tracked_by_git(bufnr)
call s:set_path(a:bufnr, -2)
endfunction
endif
function! s:set_path(bufnr, path)
if a:bufnr == -2
let [bufnr, path] = [a:path, a:bufnr]
call gitgutter#utility#setbufvar(bufnr, 'path', path)
else
call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(a:path))
endif
endfunction
function! gitgutter#utility#cd_cmd(bufnr, cmd) abort
let cd = s:unc_path(a:bufnr) ? 'pushd' : (gitgutter#utility#windows() ? 'cd /d' : 'cd')

View File

@ -190,7 +190,6 @@ function! s:on_bufenter()
let t:gitgutter_didtabenter = 0
call gitgutter#all(!g:gitgutter_terminal_reports_focus)
else
call gitgutter#init_buffer(bufnr(''))
call gitgutter#process_buffer(bufnr(''), !g:gitgutter_terminal_reports_focus)
endif
endfunction

View File

@ -71,7 +71,7 @@ function Test_add_lines()
normal ggo*
call s:trigger_gitgutter()
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
let expected = ["line=2 id=3000 name=GitGutterLineAdded priority=10"]
call assert_equal(expected, s:signs('fixture.txt'))
endfunction
@ -83,7 +83,7 @@ function Test_add_lines_fish()
normal ggo*
call s:trigger_gitgutter()
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
let expected = ["line=2 id=3000 name=GitGutterLineAdded priority=10"]
call assert_equal(expected, s:signs('fixture.txt'))
let &shell = _shell
@ -94,7 +94,7 @@ function Test_modify_lines()
normal ggi*
call s:trigger_gitgutter()
let expected = ["line=1 id=3000 name=GitGutterLineModified"]
let expected = ["line=1 id=3000 name=GitGutterLineModified priority=10"]
call assert_equal(expected, s:signs('fixture.txt'))
endfunction
@ -103,7 +103,7 @@ function Test_remove_lines()
execute '5d'
call s:trigger_gitgutter()
let expected = ["line=4 id=3000 name=GitGutterLineRemoved"]
let expected = ["line=4 id=3000 name=GitGutterLineRemoved priority=10"]
call assert_equal(expected, s:signs('fixture.txt'))
endfunction
@ -112,7 +112,7 @@ function Test_remove_first_lines()
execute '1d'
call s:trigger_gitgutter()
let expected = ["line=1 id=3000 name=GitGutterLineRemovedFirstLine"]
let expected = ["line=1 id=3000 name=GitGutterLineRemovedFirstLine priority=10"]
call assert_equal(expected, s:signs('fixture.txt'))
endfunction
@ -122,7 +122,7 @@ function Test_overlapping_hunks()
execute '1d'
call s:trigger_gitgutter()
let expected = ["line=1 id=3000 name=GitGutterLineRemovedAboveAndBelow"]
let expected = ["line=1 id=3000 name=GitGutterLineRemovedAboveAndBelow priority=10"]
call assert_equal(expected, s:signs('fixture.txt'))
endfunction
@ -132,7 +132,7 @@ function Test_edit_file_with_same_name_as_a_branch()
call system('git checkout -b fixture.txt')
call s:trigger_gitgutter()
let expected = ["line=5 id=3000 name=GitGutterLineModified"]
let expected = ["line=5 id=3000 name=GitGutterLineModified priority=10"]
call assert_equal(expected, s:signs('fixture.txt'))
endfunction
@ -144,7 +144,7 @@ function Test_file_added_to_git()
normal ihello
call s:trigger_gitgutter()
let expected = ["line=1 id=3000 name=GitGutterLineAdded"]
let expected = ["line=1 id=3000 name=GitGutterLineAdded priority=10"]
call assert_equal(expected, s:signs('fileAddedToGit.tmp'))
endfunction
@ -156,8 +156,8 @@ function Test_filename_with_equals()
call s:trigger_gitgutter()
let expected = [
\ 'line=1 id=3000 name=GitGutterLineAdded',
\ 'line=2 id=3001 name=GitGutterLineAdded'
\ 'line=1 id=3000 name=GitGutterLineAdded priority=10',
\ 'line=2 id=3001 name=GitGutterLineAdded priority=10'
\ ]
call assert_equal(expected, s:signs('=fixture=.txt'))
endfunction
@ -170,8 +170,8 @@ function Test_filename_with_square_brackets()
call s:trigger_gitgutter()
let expected = [
\ 'line=1 id=3000 name=GitGutterLineAdded',
\ 'line=2 id=3001 name=GitGutterLineAdded'
\ 'line=1 id=3000 name=GitGutterLineAdded priority=10',
\ 'line=2 id=3001 name=GitGutterLineAdded priority=10'
\ ]
call assert_equal(expected, s:signs('fix[tu]re.txt'))
endfunction
@ -184,8 +184,8 @@ function Test_filename_leading_dash()
call s:trigger_gitgutter()
let expected = [
\ 'line=1 id=3000 name=GitGutterLineAdded',
\ 'line=2 id=3001 name=GitGutterLineAdded'
\ 'line=1 id=3000 name=GitGutterLineAdded priority=10',
\ 'line=2 id=3001 name=GitGutterLineAdded priority=10'
\ ]
call assert_equal(expected, s:signs('-fixture.txt'))
endfunction
@ -198,8 +198,8 @@ function Test_filename_umlaut()
call s:trigger_gitgutter()
let expected = [
\ 'line=1 id=3000 name=GitGutterLineAdded',
\ 'line=2 id=3001 name=GitGutterLineAdded'
\ 'line=1 id=3000 name=GitGutterLineAdded priority=10',
\ 'line=2 id=3001 name=GitGutterLineAdded priority=10'
\ ]
call assert_equal(expected, s:signs('fixtüre.txt'))
endfunction
@ -213,7 +213,7 @@ function Test_follow_symlink()
6d
call s:trigger_gitgutter()
let expected = ['line=5 id=3000 name=GitGutterLineRemoved']
let expected = ['line=5 id=3000 name=GitGutterLineRemoved priority=10']
call assert_equal(expected, s:signs('symlink'))
endfunction
@ -265,7 +265,7 @@ function Test_orphaned_signs()
6d
call s:trigger_gitgutter()
let expected = ['line=6 id=3001 name=GitGutterLineAdded']
let expected = ['line=6 id=3001 name=GitGutterLineAdded priority=10']
call assert_equal(expected, s:signs('fixture.txt'))
endfunction
@ -372,9 +372,9 @@ function Test_hunk_stage_nearby_hunk()
GitGutterStageHunk
let expected = [
\ 'line=3 id=3000 name=GitGutterLineAdded',
\ 'line=4 id=3001 name=GitGutterLineAdded',
\ 'line=5 id=3002 name=GitGutterLineAdded'
\ 'line=3 id=3000 name=GitGutterLineAdded priority=10',
\ 'line=4 id=3001 name=GitGutterLineAdded priority=10',
\ 'line=5 id=3002 name=GitGutterLineAdded priority=10'
\ ]
call assert_equal(expected, s:signs('fixture.txt'))
@ -442,9 +442,9 @@ function Test_undo_nearby_hunk()
call s:trigger_gitgutter()
let expected = [
\ 'line=3 id=3000 name=GitGutterLineAdded',
\ 'line=4 id=3001 name=GitGutterLineAdded',
\ 'line=5 id=3002 name=GitGutterLineAdded'
\ 'line=3 id=3000 name=GitGutterLineAdded priority=10',
\ 'line=4 id=3001 name=GitGutterLineAdded priority=10',
\ 'line=5 id=3002 name=GitGutterLineAdded priority=10'
\ ]
call assert_equal(expected, s:signs('fixture.txt'))
@ -486,7 +486,7 @@ function Test_overlapping_hunk_op()
call s:trigger_gitgutter()
let expected = [
\ 'line=2 id=3000 name=GitGutterLineRemoved',
\ 'line=2 id=3000 name=GitGutterLineRemoved priority=10',
\ ]
call assert_equal(expected, s:signs('fixture.txt'))
@ -500,7 +500,7 @@ function Test_overlapping_hunk_op()
call s:trigger_gitgutter()
let expected = [
\ 'line=1 id=3000 name=GitGutterLineRemovedFirstLine',
\ 'line=1 id=3000 name=GitGutterLineRemovedFirstLine priority=10',
\ ]
call assert_equal(expected, s:signs('fixture.txt'))
endfunction
@ -512,7 +512,7 @@ function Test_write_option()
normal ggo*
call s:trigger_gitgutter()
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
let expected = ["line=2 id=3000 name=GitGutterLineAdded priority=10"]
call assert_equal(expected, s:signs('fixture.txt'))
set write

View File

@ -0,0 +1 @@
patreon: bhcleek

View File

@ -6,10 +6,8 @@ If possible, please provide clear steps for reproducing the problem.
### What did you expect to happen?
### What happened instead?
### Configuration (**MUST** fill this out):
#### vim-go version:
@ -20,10 +18,13 @@ If possible, please provide clear steps for reproducing the problem.
</pre></details>
#### Vim version (first three lines from `:version`):
<!-- :version -->
#### Go version (`go version`):
#### Go version (`go version`):
<!-- go version -->
#### Go environment
<details><summary><code>go env</code> Output:</summary><br><pre>
<!-- go env -->
</pre></details>

View File

@ -8,6 +8,17 @@ IMPROVEMENTS:
[[GH-2261]](https://github.com/fatih/vim-go/pull/2261)
* Allow debugging of packages outside of GOPATH without a go.mod file.
[[GH-2269]](https://github.com/fatih/vim-go/pull/2269)
* Show which example failed when Example tests fail
[[GH-2277]](https://github.com/fatih/vim-go/pull/2277)
* Show function signature and return types in preview window when autocompleting functions and methods.
[[GH-2289]](https://github.com/fatih/vim-go/pull/2289)
* Improve the user experience when using null modules.
[[GH-2300]](https://github.com/fatih/vim-go/pull/2300)
* Add option, `g:go_null_module_warning` to silence the warning when trying to
use gopls with a null module.
[[GH-2309]](https://github.com/fatih/vim-go/pull/2309)
* Modify `:GoReportGitHubIssue` to include vim-go configuration values
[[GH-2323]](https://github.com/fatih/vim-go/pull/2323)
BUG FIXES:
* display info about function and function types whose parameters are
@ -26,6 +37,22 @@ BUG FIXES:
[[GH-2268]](https://github.com/fatih/vim-go/pull/2268)
* Set the anchor for method documentation correctly.
[[GH-2276]](https://github.com/fatih/vim-go/pull/2276)
* Respect the LSP information for determining where candidate matches start.
[[GH-2291]](https://github.com/fatih/vim-go/pull/2291)
* Restore environment variables with backslashes correctly.
[[GH-2292]](https://github.com/fatih/vim-go/pull/2292)
* Modify handling of gopls output for `:GoInfo` to ensure the value will be
displayed.
[[GH-2311]](https://github.com/fatih/vim-go/pull/2311)
* Run `:GoLint` successfully in null modules.
[[GH-2318]](https://github.com/fatih/vim-go/pull/2318)
* Ensure actions on save work in new buffers that have not yet been persisted to disk.
[[GH-2319]](https://github.com/fatih/vim-go/pull/2319)
* Restore population of information in `:GoReportGitHubIssue`.
[[GH-2312]](https://github.com/fatih/vim-go/pull/2312)
* Do not jump back to the originating window when jumping to definitions with
`g:go_def_mode='gopls'`.
[[GH-2327]](https://github.com/fatih/vim-go/pull/2327)
## 1.20 - (April 22, 2019)

View File

@ -68,7 +68,16 @@ Depending on your installation method, you may have to generate the plugin's
[`help tags`](http://vimhelp.appspot.com/helphelp.txt.html#%3Ahelptags)
manually (e.g. `:helptags ALL`).
We also have an [official vim-go tutorial](https://github.com/fatih/vim-go-tutorial).
We also have an [official vim-go tutorial](https://github.com/fatih/vim-go/wiki).
## FAQ and troubleshooting
The FAQ and troubleshooting tips are in the documentation and can be quickly
accessed using `:help go-troubleshooting`. If you believe you've found a bug or
shortcoming in vim-go that is neither addressed by help nor in [existing
issues](https://github.com/fatih/vim-go/issues), please open an issue with
clear reproduction steps. `:GoReportGitHubIssue` can be used pre-populate a lot
of the information needed when creating a new issue.
## License

View File

@ -33,7 +33,7 @@ function! go#auto#echo_go_info()
endfunction
function! go#auto#auto_type_info()
if !go#config#AutoTypeInfo() || !filereadable(expand('%:p'))
if !go#config#AutoTypeInfo() || !isdirectory(expand('%:p:h'))
return
endif
@ -42,7 +42,7 @@ function! go#auto#auto_type_info()
endfunction
function! go#auto#auto_sameids()
if !go#config#AutoSameids() || !filereadable(expand('%:p'))
if !go#config#AutoSameids() || !isdirectory(expand('%:p:h'))
return
endif
@ -51,7 +51,7 @@ function! go#auto#auto_sameids()
endfunction
function! go#auto#fmt_autosave()
if !go#config#FmtAutosave() || !filereadable(expand('%:p'))
if !go#config#FmtAutosave() || !isdirectory(expand('%:p:h'))
return
endif
@ -60,7 +60,7 @@ function! go#auto#fmt_autosave()
endfunction
function! go#auto#metalinter_autosave()
if !go#config#MetalinterAutosave() || !filereadable(expand('%:p'))
if !go#config#MetalinterAutosave() || !isdirectory(expand('%:p:h'))
return
endif
@ -69,7 +69,7 @@ function! go#auto#metalinter_autosave()
endfunction
function! go#auto#modfmt_autosave()
if !go#config#ModFmtAutosave() || !filereadable(expand('%:p'))
if !go#config#ModFmtAutosave() || !isdirectory(expand('%:p:h'))
return
endif
@ -78,7 +78,7 @@ function! go#auto#modfmt_autosave()
endfunction
function! go#auto#asmfmt_autosave()
if !go#config#AsmfmtAutosave() || !filereadable(expand('%:p'))
if !go#config#AsmfmtAutosave() || !isdirectory(expand('%:p:h'))
return
endif

View File

@ -9,8 +9,8 @@ function! go#cmd#autowrite() abort
for l:nr in range(0, bufnr('$'))
if buflisted(l:nr) && getbufvar(l:nr, '&modified')
" Sleep one second to make sure people see the message. Otherwise it is
" often immediacy overwritten by the async messages (which also don't
" invoke the "hit ENTER" prompt).
" often immediately overwritten by the async messages (which also
" doesn't invoke the "hit ENTER" prompt).
call go#util#EchoWarning('[No write since last change]')
sleep 1
return

View File

@ -216,6 +216,7 @@ function! s:info_complete(echo, result) abort
endfunction
function! s:trim_bracket(val) abort
echom a:val
let a:val.word = substitute(a:val.word, '[(){}\[\]]\+$', '', '')
return a:val
endfunction
@ -240,7 +241,7 @@ function! go#complete#GocodeComplete(findstart, base) abort
else
let s = getline(".")[col('.') - 1]
if s =~ '[(){}\{\}]'
return map(copy(s:completions[1]), 's:trim_bracket(v:val)')
return map(copy(s:completions), 's:trim_bracket(v:val)')
endif
return s:completions
endif
@ -257,7 +258,10 @@ function! go#complete#Complete(findstart, base) abort
"findstart = 1 when we need to get the start of the match
if a:findstart == 1
call go#lsp#Completion(expand('%:p'), line('.'), col('.'), funcref('s:handler', [l:state]))
let l:completion = go#lsp#Completion(expand('%:p'), line('.'), col('.'), funcref('s:handler', [l:state]))
if l:completion
return -3
endif
while !l:state.done
sleep 10m

View File

@ -14,6 +14,10 @@ function! go#config#VersionWarning() abort
return get(g:, 'go_version_warning', 1)
endfunction
function! go#config#NullModuleWarning() abort
return get(g:, 'go_null_module_warning', 1)
endfunction
function! go#config#BuildTags() abort
return get(g:, 'go_build_tags', '')
endfunction

View File

@ -18,20 +18,30 @@ function! s:issuebody() abort
for l in lines
let body = add(body, l)
if l =~ '^\* Vim version'
if l =~ '^<!-- :version'
redir => out
silent version
redir END
let body = extend(body, split(out, "\n")[0:2])
elseif l =~ '^\* Go version'
elseif l =~ '^<!-- go version -->'
let [out, err] = go#util#Exec(['go', 'version'])
let body = add(body, substitute(l:out, rtrimpat, '', ''))
elseif l =~ '^\* Go environment'
elseif l =~ '^<!-- go env -->'
let [out, err] = go#util#Exec(['go', 'env'])
let body = add(body, substitute(l:out, rtrimpat, '', ''))
endif
endfor
let body = add(body, "#### vim-go configuration:\n<details><summary>vim-go configuration</summary><br><pre>")
for k in keys(g:)
if k =~ '^go_'
let body = add(body, 'g:' . k . ' = ' . string(get(g:, k)))
endif
endfor
let body = add(body, '</pre></details>')
return join(body, "\n")
endfunction

View File

@ -101,11 +101,10 @@ function! go#lint#Gometa(bang, autosave, ...) abort
endif
endfunction
" Golint calls 'golint' on the current directory. Any warnings are populated in
" the location list
" Golint calls 'golint'.
function! go#lint#Golint(bang, ...) abort
if a:0 == 0
let [l:out, l:err] = go#util#Exec([go#config#GolintBin(), go#package#ImportPath()])
let [l:out, l:err] = go#util#ExecInDir([go#config#GolintBin(), '.'])
else
let [l:out, l:err] = go#util#Exec([go#config#GolintBin()] + a:000)
endif

View File

@ -7,7 +7,7 @@ scriptencoding utf-8
let s:lspfactory = {}
function! s:lspfactory.get() dict abort
if !has_key(self, 'current') || empty(self.current)
if !has_key(self, 'current') || empty(self.current) || !has_key(self.current, 'job') || empty(self.current.job)
let self.current = s:newlsp()
endif
@ -22,9 +22,17 @@ endfunction
function! s:newlsp() abort
if !go#util#has_job()
let l:oldshortmess=&shortmess
if has('nvim')
set shortmess-=F
endif
" TODO(bc): start the server in the background using a shell that waits for the right output before returning.
call go#util#EchoError('This feature requires either Vim 8.0.0087 or newer with +job or Neovim.')
return
call go#util#EchoWarning('Features that rely on gopls will not work without either Vim 8.0.0087 or newer with +job or Neovim')
" Sleep one second to make sure people see the message. Otherwise it is
" often immediately overwritten by an async message.
sleep 1
let &shortmess=l:oldshortmess
return {'sendMessage': funcref('s:noop')}
endif
" job is the job used to talk to the backing instance of gopls.
@ -133,8 +141,17 @@ function! s:newlsp() abort
return
endif
call l:handler.requestComplete(1)
let l:winidBeforeHandler = l:handler.winid
call call(l:handler.handleResult, [l:response.result])
call win_gotoid(l:winid)
" change the window back to the window that was active when
" starting to handle the response _only_ if the handler didn't
" update the winid, so that handlers can set the winid if needed
" (e.g. :GoDef).
if l:handler.winid == l:winidBeforeHandler
call win_gotoid(l:winid)
endif
finally
call remove(self.handlers, l:response.id)
endtry
@ -162,13 +179,32 @@ function! s:newlsp() abort
let l:wd = go#util#ModuleRoot()
if l:wd == -1
call go#util#EchoError('could not determine appropriate working directory for gopls')
return
return -1
endif
if l:wd == ''
let l:wd = getcwd()
endif
" do not attempt to send a message to gopls when using neither GOPATH
" mode nor module mode.
if go#package#FromPath(l:wd) == -2
if go#config#NullModuleWarning() && (!has_key(self, 'warned') || !self.warned)
let l:oldshortmess=&shortmess
if has('nvim')
set shortmess-=F
endif
call go#util#EchoWarning('Features that rely on gopls will not work correctly outside of GOPATH or a module.')
let self.warned = 1
" Sleep one second to make sure people see the message. Otherwise it is
" often immediately overwritten by an async message.
sleep 1
let &shortmess=l:oldshortmess
endif
return -1
endif
let l:msg = self.newMessage(go#lsp#message#Initialize(l:wd))
let l:state = s:newHandlerState('')
@ -351,7 +387,7 @@ function! go#lsp#Definition(fname, line, col, handler) abort
let l:state = s:newHandlerState('definition')
let l:state.handleResult = funcref('s:definitionHandler', [function(a:handler, [], l:state)], l:state)
let l:msg = go#lsp#message#Definition(fnamemodify(a:fname, ':p'), a:line, a:col)
call l:lsp.sendMessage(l:msg, l:state)
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:definitionHandler(next, msg) abort dict
@ -373,7 +409,7 @@ function! go#lsp#TypeDef(fname, line, col, handler) abort
let l:state = s:newHandlerState('type definition')
let l:msg = go#lsp#message#TypeDefinition(fnamemodify(a:fname, ':p'), a:line, a:col)
let l:state.handleResult = funcref('s:typeDefinitionHandler', [function(a:handler, [], l:state)], l:state)
call l:lsp.sendMessage(l:msg, l:state)
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:typeDefinitionHandler(next, msg) abort dict
@ -396,9 +432,13 @@ function! go#lsp#DidOpen(fname) abort
let l:msg = go#lsp#message#DidOpen(fnamemodify(a:fname, ':p'), join(go#util#GetLines(), "\n") . "\n")
let l:state = s:newHandlerState('')
let l:state.handleResult = funcref('s:noop')
call l:lsp.sendMessage(l:msg, l:state)
" TODO(bc): setting a buffer level variable here assumes that a:fname is the
" current buffer. Change to a:fname first before setting it and then change
" back to active buffer.
let b:go_lsp_did_open = 1
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! go#lsp#DidChange(fname) abort
@ -419,7 +459,7 @@ function! go#lsp#DidChange(fname) abort
let l:msg = go#lsp#message#DidChange(fnamemodify(a:fname, ':p'), join(go#util#GetLines(), "\n") . "\n")
let l:state = s:newHandlerState('')
let l:state.handleResult = funcref('s:noop')
call l:lsp.sendMessage(l:msg, l:state)
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! go#lsp#DidClose(fname) abort
@ -435,9 +475,12 @@ function! go#lsp#DidClose(fname) abort
let l:msg = go#lsp#message#DidClose(fnamemodify(a:fname, ':p'))
let l:state = s:newHandlerState('')
let l:state.handleResult = funcref('s:noop')
call l:lsp.sendMessage(l:msg, l:state)
" TODO(bc): setting a buffer level variable here assumes that a:fname is the
" current buffer. Change to a:fname first before setting it and then change
" back to active buffer.
let b:go_lsp_did_open = 0
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! go#lsp#Completion(fname, line, col, handler) abort
@ -448,7 +491,7 @@ function! go#lsp#Completion(fname, line, col, handler) abort
let l:state = s:newHandlerState('completion')
let l:state.handleResult = funcref('s:completionHandler', [function(a:handler, [], l:state)], l:state)
let l:state.error = funcref('s:completionErrorHandler', [function(a:handler, [], l:state)], l:state)
call l:lsp.sendMessage(l:msg, l:state)
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:completionHandler(next, msg) abort dict
@ -462,6 +505,9 @@ function! s:completionHandler(next, msg) abort dict
let l:match = {'abbr': l:item.label, 'word': l:item.textEdit.newText, 'info': '', 'kind': go#lsp#completionitemkind#Vim(l:item.kind)}
if has_key(l:item, 'detail')
let l:match.info = l:item.detail
if go#lsp#completionitemkind#IsFunction(l:item.kind) || go#lsp#completionitemkind#IsMethod(l:item.kind)
let l:match.info = printf('func %s %s', l:item.label, l:item.detail)
endif
endif
if has_key(l:item, 'documentation')
@ -475,7 +521,7 @@ function! s:completionHandler(next, msg) abort dict
endfunction
function! s:completionErrorHandler(next, error) abort dict
call call(a:next, [[]])
call call(a:next, [-1, []])
endfunction
function! go#lsp#Hover(fname, line, col, handler) abort
@ -486,7 +532,7 @@ function! go#lsp#Hover(fname, line, col, handler) abort
let l:state = s:newHandlerState('')
let l:state.handleResult = funcref('s:hoverHandler', [function(a:handler, [], l:state)], l:state)
let l:state.error = funcref('s:noop')
call l:lsp.sendMessage(l:msg, l:state)
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:hoverHandler(next, msg) abort dict
@ -515,13 +561,13 @@ function! go#lsp#Info(showstatus)
let l:state = s:newHandlerState('')
endif
let l:state.handleResult = funcref('s:infoDefinitionHandler', [function('s:info', []), a:showstatus], l:state)
let l:state.handleResult = funcref('s:infoDefinitionHandler', [a:showstatus], l:state)
let l:state.error = funcref('s:noop')
let l:msg = go#lsp#message#Definition(l:fname, l:line, l:col)
call l:lsp.sendMessage(l:msg, l:state)
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:infoDefinitionHandler(next, showstatus, msg) abort dict
function! s:infoDefinitionHandler(showstatus, msg) abort dict
" gopls returns a []Location; just take the first one.
let l:msg = a:msg[0]
@ -540,11 +586,15 @@ function! s:infoDefinitionHandler(next, showstatus, msg) abort dict
let l:state.handleResult = funcref('s:hoverHandler', [function('s:info', [], l:state)], l:state)
let l:state.error = funcref('s:noop')
call l:lsp.sendMessage(l:msg, l:state)
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:info(content) abort dict
let l:content = a:content[0]
" strip godoc summary
let l:content = substitute(l:content, '^[^\n]\+\n', '', '')
" strip off the method set and fields of structs and interfaces.
if l:content =~# '^type [^ ]\+ \(struct\|interface\)'
let l:content = substitute(l:content, '{.*', '', '')

View File

@ -144,12 +144,19 @@ function! go#package#FromPath(arg) abort
let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let l:dir = getcwd()
let l:path = a:arg
let l:path = fnamemodify(a:arg, ':p')
if !isdirectory(l:path)
let l:path = fnamemodify(l:path, ':h')
endif
execute l:cd fnameescape(l:path)
if glob("*.go") == ""
" There's no Go code in this directory. We might be in a module directory
" which doesn't have any code at this level.
if !empty(s:module())
return -1
endif
endif
let [l:out, l:err] = go#util#Exec(['go', 'list'])
execute l:cd fnameescape(l:dir)
if l:err != 0

View File

@ -66,9 +66,9 @@ endfunc
func! Test_GoTestShowName() abort
let expected = [
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestHelloWorld'},
\ {'lnum': 6, 'bufnr': 7, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'so long'},
\ {'lnum': 6, 'bufnr': 8, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'so long'},
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestHelloWorld/sub'},
\ {'lnum': 9, 'bufnr': 7, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'thanks for all the fish'},
\ {'lnum': 9, 'bufnr': 8, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'thanks for all the fish'},
\ ]
let g:go_test_show_name=1
@ -78,14 +78,14 @@ endfunc
func! Test_GoTestVet() abort
let expected = [
\ {'lnum': 6, 'bufnr': 10, 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'Errorf format %v reads arg #1, but call has 0 args'},
\ {'lnum': 6, 'bufnr': 11, 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'Errorf format %v reads arg #1, but call has 0 args'},
\ ]
call s:test('veterror/veterror.go', expected)
endfunc
func! Test_GoTestTestCompilerError() abort
let expected = [
\ {'lnum': 10, 'bufnr': 8, 'col': 16, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'cannot use r (type struct {}) as type io.Reader in argument to ioutil.ReadAll:'},
\ {'lnum': 10, 'bufnr': 9, 'col': 16, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'cannot use r (type struct {}) as type io.Reader in argument to ioutil.ReadAll:'},
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'struct {} does not implement io.Reader (missing Read method)'}
\ ]

View File

@ -557,7 +557,9 @@ function! go#util#SetEnv(name, value) abort
let l:remove = 1
endif
call execute('let $' . a:name . ' = "' . a:value . '"')
" wrap the value in single quotes so that it will work on windows when there
" are backslashes present in the value (e.g. $PATH).
call execute('let $' . a:name . " = '" . a:value . "'")
if l:remove
function! s:remove(name) abort

View File

@ -1204,6 +1204,22 @@ balloonexpr`.
==============================================================================
SETTINGS *go-settings*
*'g:go_version_warning'*
Enable warning when using an unsupported version of Vim. By default it is
enabled.
>
let g:go_version_warning = 1
<
*'g:go_null_module_warning'*
Enable warning when trying to use lsp features in a null module. By default it
is enabled.
>
let g:go_null_module_warning = 1
<
*'g:go_code_completion_enabled'*
Enable code completion with |'omnifunc'|. By default it is enabled.
@ -2183,6 +2199,24 @@ Highlight the current line and breakpoints in the debugger.
==============================================================================
FAQ TROUBLESHOOTING *go-troubleshooting*
How do I troubleshoot problems?~
One of the best ways to understand what vim-go is doing and the output from
the tools to which it delegates is to use leverage the features described in
|'g:go_debug'|.
Completion and other functions that use `gopls` don't work~
Vim-go is heavily reliant on `gopls` for completion and other functionality.
`gopls` requires either module mode or GOPATH mode; files that are neither in
GOPATH nor in a Go module will not be analyzed by `gopls`. Many of the
features that use `gopls` (e.g. completion, jumping to definitions, showing
identifier information, et al.) can be configured to delegate to other tools.
e.g. completion via |'omnifunc'|, |'g:go_info_mode'| and |'g:go_def_mode'| can
be set to use other tools for now (though some of the alternatives to `gopls`
are effectively at their end of life and support for them from within vim-go
may be removed soon).
I get "Unknown function: go#config#..." error when I open a Go file.~
This often happens to vim-polyglot users when new config options are added to

View File

@ -42,11 +42,24 @@ snippet pt
static propTypes = {
${1}: React.PropTypes.${2:type},
}
snippet rfc
const ${1:ComponentName} = (${2:props}) => {
return (
<div>
$1
</div>
);
}
snippet rcc
class ${1:ClassName} extends React.Component {
state = {
}
render() {
return (
${0:<div />}
<div>
$1
</div>
);
}
}

View File

@ -0,0 +1,37 @@
snippet ist
import { createStore } from 'redux';
snippet con
connect(${1:mapStateToProps}, ${2:mapDispatchToProps})(<${3:VISUAL}/>);
snippet act
const ${1:actionName} = (${2:arg}) => {
return {
type: ${3:VISUAL},
$2
};
};
snippet rdc
const ${1:reducerName} = (state={}, action) => {
switch(action.type) {
case ${1:action}:
return {
...state,
$2
};
default:
return state;
};
};
snippet mstp
const mapStateToProps = (state) => {
return {
${1:propName}: state.$1,
};
};
snippet mdtp
const mapDispatchToProps = (dispatch) => {
return {
${1:propName}: () => {
dispatch(${2:actionName}());
},
};
};

View File

@ -1,55 +0,0 @@
snippet const
const ${1} = ${0};
snippet let
let ${1} = ${0};
snippet im "import xyz from 'xyz'"
import ${1} from '${2:$1}';
snippet imas "import * as xyz from 'xyz'"
import * as ${1} from '${2:$1}';
snippet imm "import { member } from 'xyz'"
import { ${1} } from '${2}';
snippet cla
class ${1} {
${0:${VISUAL}}
}
snippet clax
class ${1} extends ${2} {
${0:${VISUAL}}
}
snippet clac
class ${1} {
constructor(${2}) {
${0:${VISUAL}}
}
}
snippet foro "for (const prop of object}) { ... }"
for (const ${1:prop} of ${2:object}) {
${0:$1}
}
# Generator
snippet fun*
function* ${1:function_name}(${2}) {
${0:${VISUAL}}
}
snippet c=>
const ${1:function_name} = (${2}) => {
${0:${VISUAL}}
}
snippet caf
const ${1:function_name} = (${2}) => {
${0:${VISUAL}}
}
snippet =>
(${1}) => {
${0:${VISUAL}}
}
snippet af
(${1}) => {
${0:${VISUAL}}
}
snippet sym
const ${1} = Symbol('${0}');
snippet ed
export default ${0}
snippet ${
${${1}}${0}

View File

@ -5,10 +5,14 @@ snippet proto
${0:${VISUAL}}
};
# Function
snippet fun
snippet fun "function"
function ${1:function_name}(${2}) {
${0:${VISUAL}}
}
snippet fun "async function"
async function ${1:function_name}(${2}) {
${0:${VISUAL}}
}
# Anonymous Function
snippet anf "" w
function(${1}) {
@ -202,8 +206,6 @@ snippet @par
@param {${1:type}} ${2:name} ${0:description}
snippet @ret
@return {${1:type}} ${0:description}
# JSON
# JSON.parse
snippet jsonp
JSON.parse(${0:jstr});
@ -273,9 +275,64 @@ snippet cprof "console.profile"
snippet ctable "console.table"
console.table(${1:"${2:value}"});
# Misc
# 'use strict';
snippet us
'use strict';
# setTimeout function
snippet timeout
setTimeout(function () {${0}}${2}, ${1:10});
snippet const
const ${1} = ${0};
snippet let
let ${1} = ${0};
snippet im "import xyz from 'xyz'"
import ${1} from '${2:$1}';
snippet imas "import * as xyz from 'xyz'"
import * as ${1} from '${2:$1}';
snippet imm "import { member } from 'xyz'"
import { ${1} } from '${2}';
snippet cla
class ${1} {
${0:${VISUAL}}
}
snippet clax
class ${1} extends ${2} {
${0:${VISUAL}}
}
snippet clac
class ${1} {
constructor(${2}) {
${0:${VISUAL}}
}
}
snippet foro "for (const prop of object}) { ... }"
for (const ${1:prop} of ${2:object}) {
${0:$1}
}
snippet fun*
function* ${1:function_name}(${2}) {
${0:${VISUAL}}
}
snippet c=>
const ${1:function_name} = (${2}) => {
${0:${VISUAL}}
}
snippet caf
const ${1:function_name} = (${2}) => {
${0:${VISUAL}}
}
snippet =>
(${1}) => {
${0:${VISUAL}}
}
snippet af
(${1}) => {
${0:${VISUAL}}
}
snippet sym
const ${1} = Symbol('${0}');
snippet ed
export default ${0}
snippet ${
${${1}}${0}
snippet aw "await"
await ${0:${VISUAL}}