Created
December 20, 2021 18:34
-
-
Save avegancafe/919ddd0a078673abcfec8480aa20c104 to your computer and use it in GitHub Desktop.
vim-go issue reproduction
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/dashboard-nvim/autoload/sessions/session.vim | |
Sourced 1 time | |
Total time: 0.001254 | |
Self time: 0.001254 | |
count total (s) self (s) | |
" Plugin: https://github.com/hardcoreplayers/dashboard-nvim | |
" Description: A fancy start screen for Vim. | |
" Maintainer: Glepnir <http://github.com/glepnir> | |
1 0.000007 function! sessions#session#session_save(name) | |
if ! isdirectory(g:session_directory) | |
call mkdir(g:session_directory, 'p') | |
endif | |
let file_name = empty(a:name) ? s:project_name() : a:name | |
let file_path = g:session_directory.'/'.file_name.'.vim' | |
execute 'mksession! '.fnameescape(file_path) | |
let v:this_session = file_path | |
echohl MoreMsg | |
echo 'Session `'.file_name.'` is now persistent' | |
echohl None | |
endfunction | |
1 0.000003 function! sessions#session#session_load(name) | |
let file_name = empty(a:name) ? s:project_name() : a:name | |
let file_path = g:session_directory.'/'.file_name.'.vim' | |
if ! empty(v:this_session) && ! exists('g:SessionLoad') | |
\ | execute 'mksession! '.fnameescape(v:this_session) | |
\ | endif | |
if filereadable(file_path) | |
noautocmd silent! %bwipeout! | |
execute 'silent! source '.file_path | |
if &laststatus == 0 | |
set laststatus=2 | |
endif | |
echomsg 'Loaded "'.file_path.'" session' | |
else | |
echohl ErrorMsg | |
echomsg 'The session "'.file_path.'" doesn''t exist' | |
echohl None | |
endif | |
endfunction | |
1 0.000003 function! sessions#session#session_list(A, C, P) | |
return map( | |
\ split(glob(g:session_directory.'/*.vim'), '\n'), | |
\ "fnamemodify(v:val, ':t:r')" | |
\ ) | |
endfunction | |
1 0.000003 function! s:project_name() | |
let l:cwd = resolve(getcwd()) | |
let l:cwd = substitute(l:cwd, '^'.$HOME.'/', '', '') | |
let l:cwd = fnamemodify(l:cwd, ':p:gs?/?_?') | |
let l:cwd = substitute(l:cwd, '^\.', '', '') | |
return l:cwd | |
endfunction | |
" vim: et sw=2 sts=2 | |
SCRIPT /Users/kyle/.cache/vim/session/workspace_api-v2-backend.vim | |
Sourced 1 time | |
Total time: 0.496258 | |
Self time: 0.059121 | |
count total (s) self (s) | |
1 0.000022 let SessionLoad = 1 | |
1 0.000119 0.000050 let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1 | |
1 0.000022 let v:this_session=expand("<sfile>:p") | |
1 0.000019 silent only | |
1 0.000006 silent tabonly | |
1 0.001135 0.000812 cd ~/workspace/api-v2-backend | |
1 0.000024 if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' | |
1 0.000008 let s:wipebuf = bufnr('%') | |
1 0.000001 endif | |
1 0.000025 0.000016 set shortmess=aoO | |
1 0.001586 badd +159 apps/parking/web/reservations.go | |
1 0.000007 argglobal | |
1 0.000004 %argdel | |
1 0.462601 0.026069 edit apps/parking/web/reservations.go | |
1 0.000005 argglobal | |
1 0.000015 0.000011 setlocal fdm=syntax | |
1 0.000003 0.000002 setlocal fde=0 | |
1 0.000003 0.000002 setlocal fmr={{{,}}} | |
1 0.000002 0.000002 setlocal fdi=# | |
1 0.012575 0.012573 setlocal fdl=20 | |
1 0.000010 0.000009 setlocal fml=1 | |
1 0.000003 0.000002 setlocal fdn=20 | |
1 0.000003 0.000002 setlocal fen | |
1 0.000009 let s:l = 165 - ((28 * winheight(0) + 21) / 43) | |
1 0.000003 if s:l < 1 | let s:l = 1 | endif | |
1 0.000009 keepjumps exe s:l | |
1 0.017227 normal! zt | |
1 0.000005 keepjumps 165 | |
1 0.000016 normal! 03| | |
1 0.000002 tabnext 1 | |
1 0.000014 if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0&& getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' | |
1 0.000195 0.000094 silent exe 'bwipe ' . s:wipebuf | |
1 0.000001 endif | |
1 0.000003 unlet! s:wipebuf | |
1 0.000014 0.000011 set winheight=1 winwidth=20 shortmess=filnxtToOFIs | |
1 0.000028 let s:sx = expand("<sfile>:p:r")."x.vim" | |
1 0.000349 if filereadable(s:sx) | |
exe "source " . fnameescape(s:sx) | |
1 0.000001 endif | |
1 0.000035 0.000029 let &g:so = s:so_save | let &g:siso = s:siso_save | |
1 0.000011 0.000010 set hlsearch | |
1 0.000001 nohlsearch | |
1 0.000090 0.000007 doautoall SessionLoadPost | |
1 0.000008 unlet SessionLoad | |
" vim: set ft=vim : | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/ftplugin/go.vim | |
Sourced 2 times | |
Total time: 0.007462 | |
Self time: 0.006547 | |
count total (s) self (s) | |
" Copyright 2013 The Go Authors. All rights reserved. | |
" Use of this source code is governed by a BSD-style | |
" license that can be found in the LICENSE file. | |
" | |
" go.vim: Vim filetype plugin for Go. | |
2 0.000012 if exists("b:did_ftplugin") | |
1 0.000000 finish | |
1 0.000001 endif | |
1 0.000004 let b:did_ftplugin = 1 | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000009 let s:cpo_save = &cpo | |
1 0.000014 set cpo&vim | |
1 0.000007 let b:undo_ftplugin = "setl fo< com< cms<" | |
\ . "| exe 'au! vim-go-buffer * <buffer>'" | |
1 0.000005 setlocal formatoptions-=t | |
1 0.000005 setlocal comments=s1:/*,mb:*,ex:*/,:// | |
1 0.000002 setlocal commentstring=//\ %s | |
1 0.000006 setlocal noexpandtab | |
1 0.006612 0.005714 compiler go | |
1 0.000033 0.000024 if go#config#CodeCompletionEnabled() | |
" Set autocompletion | |
1 0.000005 setlocal omnifunc=go#complete#Complete | |
1 0.000001 endif | |
1 0.000004 if get(g:, "go_doc_keywordprg_enabled", 1) | |
" keywordprg doesn't allow to use vim commands, override it | |
1 0.000023 nnoremap <buffer> <silent> K :GoDoc<cr> | |
1 0.000001 endif | |
1 0.000002 if get(g:, "go_def_mapping_enabled", 1) | |
" these are default Vim mappings, we're overriding them to make them | |
" useful again for Go source code | |
1 0.000008 nnoremap <buffer> <silent> gd :GoDef<cr> | |
1 0.000007 nnoremap <buffer> <silent> <C-]> :GoDef<cr> | |
1 0.000009 nnoremap <buffer> <silent> <C-LeftMouse> <LeftMouse>:GoDef<cr> | |
1 0.000007 nnoremap <buffer> <silent> g<LeftMouse> <LeftMouse>:GoDef<cr> | |
1 0.000008 nnoremap <buffer> <silent> <C-w><C-]> :<C-u>call go#def#Jump("split", 0)<CR> | |
1 0.000006 nnoremap <buffer> <silent> <C-w>] :<C-u>call go#def#Jump("split", 0)<CR> | |
1 0.000007 nnoremap <buffer> <silent> <C-t> :<C-U>call go#def#StackPop(v:count1)<cr> | |
1 0.000001 endif | |
1 0.000003 if get(g:, "go_textobj_enabled", 1) | |
1 0.000008 onoremap <buffer> <silent> af :<c-u>call go#textobj#Function('a')<cr> | |
1 0.000007 xnoremap <buffer> <silent> af :<c-u>call go#textobj#Function('a')<cr> | |
1 0.000006 onoremap <buffer> <silent> if :<c-u>call go#textobj#Function('i')<cr> | |
1 0.000006 xnoremap <buffer> <silent> if :<c-u>call go#textobj#Function('i')<cr> | |
1 0.000006 onoremap <buffer> <silent> ac :<c-u>call go#textobj#Comment('a')<cr> | |
1 0.000005 xnoremap <buffer> <silent> ac :<c-u>call go#textobj#Comment('a')<cr> | |
1 0.000005 onoremap <buffer> <silent> ic :<c-u>call go#textobj#Comment('i')<cr> | |
1 0.000005 xnoremap <buffer> <silent> ic :<c-u>call go#textobj#Comment('i')<cr> | |
" Remap ]] and [[ to jump betweeen functions as they are useless in Go | |
1 0.000011 nnoremap <buffer> <silent> ]] :<c-u>call go#textobj#FunctionJump('n', 'next')<cr> | |
1 0.000007 nnoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('n', 'prev')<cr> | |
1 0.000007 onoremap <buffer> <silent> ]] :<c-u>call go#textobj#FunctionJump('o', 'next')<cr> | |
1 0.000006 onoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('o', 'prev')<cr> | |
1 0.000006 xnoremap <buffer> <silent> ]] :<c-u>call go#textobj#FunctionJump('v', 'next')<cr> | |
1 0.000006 xnoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('v', 'prev')<cr> | |
1 0.000001 endif | |
" Autocommands | |
" ============================================================================ | |
" | |
1 0.000010 augroup vim-go-buffer | |
1 0.000108 autocmd! * <buffer> | |
" The file is registered (textDocument/DidOpen) with gopls in plugin/go.vim | |
" on the FileType event. | |
1 0.000017 0.000008 if go#util#has_job() | |
1 0.000009 autocmd BufWritePost,FileChangedShellPost <buffer> call go#lsp#DidChange(expand('<afile>:p')) | |
1 0.000003 autocmd BufDelete <buffer> call go#lsp#DidClose(expand('<afile>:p')) | |
1 0.000001 endif | |
" send the textDocument/didChange notification when idle. go#lsp#DidChange | |
" will not send an event if the buffer hasn't changed since the last | |
" notification. | |
1 0.000004 autocmd CursorHold,CursorHoldI <buffer> call go#lsp#DidChange(expand('<afile>:p')) | |
1 0.000003 autocmd BufEnter,CursorHold <buffer> call go#auto#update_autocmd() | |
" Echo the identifier information when completion is done. Useful to see | |
" the signature of a function, etc... | |
1 0.000002 if exists('##CompleteDone') | |
1 0.000003 autocmd CompleteDone <buffer> call go#auto#complete_done() | |
1 0.000001 endif | |
1 0.000003 autocmd BufWritePre <buffer> call go#auto#fmt_autosave() | |
1 0.000002 autocmd BufWritePost <buffer> call go#auto#metalinter_autosave() | |
" TODO(bc): autocmd BufWinLeave call go#lsp#DidChange(expand('<afile>:p')) | |
1 0.000003 if !has('textprop') | |
"TODO(bc): how to clear sameids and diagnostics when a non-go buffer is | |
" loaded into a window and the previously loaded buffer is still loaded in | |
" another window? | |
" TODO(bc): only clear when the new buffer isn't the old buffer | |
" clear SameIds when the buffer is unloaded from its last window so that | |
" loading another buffer (especially of a different filetype) in the same | |
" window doesn't highlight the most recently matched identifier's positions. | |
1 0.000003 autocmd BufWinLeave <buffer> call go#guru#ClearSameIds() | |
" clear SameIds when a new buffer is loaded in the window so that the | |
" previous buffer's highlighting isn't used. | |
1 0.000002 autocmd BufWinEnter <buffer> call go#guru#ClearSameIds() | |
" clear diagnostics when the buffer is unloaded from its last window so that | |
" loading another buffer (especially of a different filetype) in the same | |
" window doesn't highlight the previously loaded buffer's diagnostics. | |
1 0.000002 autocmd BufWinLeave <buffer> call go#lsp#ClearDiagnosticHighlights() | |
" clear diagnostics when a new buffer is loaded in the window so that the | |
" previous buffer's diagnostics aren't used. | |
"autocmd BufWinEnter <buffer> call go#lsp#ClearDiagnosticHighlights() | |
1 0.000001 endif | |
1 0.000001 augroup end | |
" restore Vi compatibility settings | |
1 0.000008 let &cpo = s:cpo_save | |
1 0.000002 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/compiler/go.vim | |
Sourced 1 time | |
Total time: 0.000363 | |
Self time: 0.000363 | |
count total (s) self (s) | |
" Copyright 2013 The Go Authors. All rights reserved. | |
" Use of this source code is governed by a BSD-style | |
" license that can be found in the LICENSE file. | |
" | |
" compiler/go.vim: Vim compiler file for Go. | |
1 0.000006 if exists("g:current_compiler") | |
finish | |
1 0.000001 endif | |
1 0.000003 let g:current_compiler = "go" | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000005 let s:cpo_save = &cpo | |
1 0.000007 set cpo&vim | |
1 0.000005 if exists(":CompilerSet") != 2 | |
command -nargs=* CompilerSet setlocal <args> | |
1 0.000001 endif | |
1 0.000004 let s:save_cpo = &cpo | |
1 0.000005 set cpo-=C | |
1 0.000053 if filereadable("makefile") || filereadable("Makefile") | |
CompilerSet makeprg=make | |
1 0.000001 else | |
1 0.000008 CompilerSet makeprg=go\ build | |
1 0.000001 endif | |
" Define the patterns that will be recognized by QuickFix when parsing the | |
" output of Go command that use this errorforamt (when called make, cexpr or | |
" lmake, lexpr). This is the global errorformat, however some command might | |
" use a different output, for those we define them directly and modify the | |
" errorformat ourselves. More information at: | |
" http://vimdoc.sourceforge.net/htmldoc/quickfix.html#errorformat | |
1 0.000011 CompilerSet errorformat =%-G#\ %.%# " Ignore lines beginning with '#' ('# command-line-arguments' line sometimes appears?) | |
1 0.000006 CompilerSet errorformat+=%-G%.%#panic:\ %m " Ignore lines containing 'panic: message' | |
1 0.000006 CompilerSet errorformat+=%Ecan\'t\ load\ package:\ %m " Start of multiline error string is 'can\'t load package' | |
1 0.000006 CompilerSet errorformat+=%A%\\%%(%[%^:]%\\+:\ %\\)%\\?%f:%l:%c:\ %m " Start of multiline unspecified string is 'filename:linenumber:columnnumber:' | |
1 0.000005 CompilerSet errorformat+=%A%\\%%(%[%^:]%\\+:\ %\\)%\\?%f:%l:\ %m " Start of multiline unspecified string is 'filename:linenumber:' | |
1 0.000004 CompilerSet errorformat+=%C%*\\s%m " Continuation of multiline error message is indented | |
1 0.000004 CompilerSet errorformat+=%-G%.%# " All lines not matching any of the above patterns are ignored | |
1 0.000005 let &cpo = s:save_cpo | |
1 0.000003 unlet s:save_cpo | |
" restore Vi compatibility settings | |
1 0.000004 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /opt/homebrew/Cellar/neovim/0.5.1_1/share/nvim/runtime/compiler/go.vim | |
Sourced 1 time | |
Total time: 0.000396 | |
Self time: 0.000396 | |
count total (s) self (s) | |
" Vim compiler file | |
" Compiler: Go | |
" Maintainer: David Barnett (https://github.com/google/vim-ft-go) | |
" Last Change: 2014 Aug 16 | |
1 0.000005 if exists('current_compiler') | |
1 0.000002 finish | |
endif | |
let current_compiler = 'go' | |
if exists(':CompilerSet') != 2 | |
command -nargs=* CompilerSet setlocal <args> | |
endif | |
let s:save_cpo = &cpo | |
set cpo-=C | |
CompilerSet makeprg=go\ build | |
CompilerSet errorformat= | |
\%-G#\ %.%#, | |
\%A%f:%l:%c:\ %m, | |
\%A%f:%l:\ %m, | |
\%C%*\\s%m, | |
\%-G%.%# | |
let &cpo = s:save_cpo | |
unlet s:save_cpo | |
" vim: sw=2 sts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/ftplugin/go/commands.vim | |
Sourced 1 time | |
Total time: 0.286915 | |
Self time: 0.002260 | |
count total (s) self (s) | |
" -- gorename | |
1 0.000012 command! -nargs=? -complete=customlist,go#rename#Complete GoRename call go#rename#Rename(<bang>0, <f-args>) | |
" -- guru | |
" do not configure commands that _require_ guru when not in GOPATH mode. | |
"if go#package#InGOPATH() | |
1 0.000006 command! -nargs=* -complete=customlist,go#package#Complete GoGuruScope call go#guru#Scope(<f-args>) | |
1 0.000005 command! -range=% GoPointsTo call go#guru#PointsTo(<count>) | |
1 0.000004 command! -range=% GoWhicherrs call go#guru#Whicherrs(<count>) | |
1 0.000004 command! -range=% GoCallees call go#guru#Callees(<count>) | |
1 0.000004 command! -range=% GoDescribe call go#guru#Describe(<count>) | |
1 0.000004 command! -range=% GoCallstack call go#guru#Callstack(<count>) | |
1 0.000004 command! -range=% GoFreevars call go#guru#Freevars(<count>) | |
1 0.000004 command! -range=% GoChannelPeers call go#guru#ChannelPeers(<count>) | |
"endif | |
1 0.000004 command! -range=% GoImplements call go#implements#Implements(<count>) | |
1 0.000005 command! -range=% GoReferrers call go#referrers#Referrers(<count>) | |
1 0.000004 command! -range=0 GoSameIds call go#guru#SameIds(1) | |
1 0.000003 command! -range=0 GoSameIdsClear call go#guru#ClearSameIds() | |
1 0.000007 command! -range=0 GoSameIdsToggle call go#guru#ToggleSameIds() | |
1 0.000004 command! -range=0 GoSameIdsAutoToggle call go#guru#AutoToggleSameIds() | |
" -- calls | |
1 0.000003 command! -nargs=0 GoCallers call go#calls#Callers() | |
" -- tags | |
1 0.000018 command! -nargs=* -range GoAddTags call go#tags#Add(<line1>, <line2>, <count>, <f-args>) | |
1 0.000007 command! -nargs=* -range GoRemoveTags call go#tags#Remove(<line1>, <line2>, <count>, <f-args>) | |
" -- mod | |
1 0.000003 command! -nargs=0 -range GoModFmt call go#mod#Format() | |
" -- tool | |
1 0.000004 command! -nargs=* -complete=customlist,go#tool#ValidFiles GoFiles echo go#tool#Files(<f-args>) | |
1 0.000003 command! -nargs=0 GoDeps echo go#tool#Deps() | |
1 0.000003 command! -nargs=0 GoInfo call go#tool#Info(1) | |
1 0.000004 command! -nargs=0 GoAutoTypeInfoToggle call go#complete#ToggleAutoTypeInfo() | |
" -- cmd | |
1 0.000005 command! -nargs=* -bang GoBuild call go#cmd#Build(<bang>0,<f-args>) | |
1 0.000005 command! -nargs=? -bang GoBuildTags call go#cmd#BuildTags(<bang>0, <f-args>) | |
1 0.000005 command! -nargs=* -bang GoGenerate call go#cmd#Generate(<bang>0,<f-args>) | |
1 0.000005 command! -nargs=* -bang -complete=file GoRun call go#cmd#Run(<bang>0,<f-args>) | |
1 0.000005 command! -nargs=* -bang GoInstall call go#cmd#Install(<bang>0, <f-args>) | |
" -- test | |
1 0.000005 command! -nargs=* -bang GoTest call go#test#Test(<bang>0, 0, <f-args>) | |
1 0.000005 command! -nargs=* -bang GoTestFunc call go#test#Func(<bang>0, <f-args>) | |
1 0.000005 command! -nargs=* -bang GoTestCompile call go#test#Test(<bang>0, 1, <f-args>) | |
" -- cover | |
1 0.000004 command! -nargs=* -bang GoCoverage call go#coverage#Buffer(<bang>0, <f-args>) | |
1 0.000003 command! -nargs=* -bang GoCoverageClear call go#coverage#Clear() | |
1 0.000005 command! -nargs=* -bang GoCoverageToggle call go#coverage#BufferToggle(<bang>0, <f-args>) | |
1 0.000020 command! -nargs=* -bang GoCoverageBrowser call go#coverage#Browser(<bang>0, <f-args>) | |
" -- play | |
1 0.000007 command! -nargs=0 -range=% GoPlay call go#play#Share(<count>, <line1>, <line2>) | |
" -- def | |
1 0.000003 command! -nargs=* -range GoDef :call go#def#Jump('', 0) | |
1 0.000003 command! -nargs=* -range GoDefType :call go#def#Jump('', 1) | |
1 0.000003 command! -nargs=? GoDefPop :call go#def#StackPop(<f-args>) | |
1 0.000003 command! -nargs=? GoDefStack :call go#def#Stack(<f-args>) | |
1 0.000004 command! -nargs=? GoDefStackClear :call go#def#StackClear(<f-args>) | |
" -- doc | |
1 0.000005 command! -nargs=* -range -complete=customlist,go#package#Complete GoDoc call go#doc#Open('new', 'split', <f-args>) | |
1 0.000004 command! -nargs=* -range -complete=customlist,go#package#Complete GoDocBrowser call go#doc#OpenBrowser(<f-args>) | |
" -- fmt | |
1 0.000003 command! -nargs=0 GoFmt call go#fmt#Format(0) | |
1 0.000004 command! -nargs=0 GoFmtAutoSaveToggle call go#fmt#ToggleFmtAutoSave() | |
1 0.000003 command! -nargs=0 GoImports call go#fmt#Format(1) | |
" -- asmfmt | |
1 0.000004 command! -nargs=0 GoAsmFmtAutoSaveToggle call go#asmfmt#ToggleAsmFmtAutoSave() | |
" -- import | |
1 0.000006 command! -nargs=? -complete=customlist,go#package#Complete GoDrop call go#import#SwitchImport(0, '', <f-args>, '') | |
1 0.000007 command! -nargs=1 -bang -complete=customlist,go#package#Complete GoImport call go#import#SwitchImport(1, '', <f-args>, '<bang>') | |
1 0.000006 command! -nargs=* -bang -complete=customlist,go#package#Complete GoImportAs call go#import#SwitchImport(1, <f-args>, '<bang>') | |
" -- linters | |
1 0.000005 command! -nargs=* -bang GoMetaLinter call go#lint#Gometa(<bang>0, 0, <f-args>) | |
1 0.000005 command! -nargs=0 GoMetaLinterAutoSaveToggle call go#lint#ToggleMetaLinterAutoSave() | |
1 0.000005 command! -nargs=* -bang GoLint call go#lint#Golint(<bang>0, <f-args>) | |
1 0.000005 command! -nargs=* -bang GoVet call go#lint#Vet(<bang>0, <f-args>) | |
1 0.000005 command! -nargs=* -bang -complete=customlist,go#package#Complete GoErrCheck call go#lint#Errcheck(<bang>0, <f-args>) | |
" -- alternate | |
1 0.000005 command! -bang GoAlternate call go#alternate#Switch(<bang>0, '') | |
" -- decls | |
1 0.000004 command! -nargs=? -complete=file GoDecls call go#decls#Decls(0, <q-args>) | |
1 0.000005 command! -nargs=? -complete=dir GoDeclsDir call go#decls#Decls(1, <q-args>) | |
" -- impl | |
1 0.000004 command! -nargs=* -complete=customlist,go#impl#Complete GoImpl call go#impl#Impl(<f-args>) | |
" -- template | |
1 0.000004 command! -nargs=0 GoTemplateAutoCreateToggle call go#template#ToggleAutoCreate() | |
" -- keyify | |
1 0.286353 0.001698 if go#package#InGOPATH() | |
command! -nargs=0 GoKeyify call go#keyify#Keyify() | |
1 0.000000 endif | |
" -- fillstruct | |
1 0.000006 command! -nargs=0 GoFillStruct call go#fillstruct#FillStruct() | |
" -- debug | |
1 0.000003 if !exists(':GoDebugStart') | |
1 0.000004 command! -nargs=* -complete=customlist,go#package#Complete GoDebugStart call go#debug#Start('debug', <f-args>) | |
1 0.000004 command! -nargs=* -complete=customlist,go#package#Complete GoDebugTest call go#debug#Start('test', <f-args>) | |
1 0.000003 command! -nargs=* GoDebugTestFunc call go#debug#TestFunc(<f-args>) | |
1 0.000002 command! -nargs=1 GoDebugAttach call go#debug#Start('attach', <f-args>) | |
1 0.000002 command! -nargs=? GoDebugConnect call go#debug#Start('connect', <f-args>) | |
1 0.000002 command! -nargs=? GoDebugBreakpoint call go#debug#Breakpoint(<f-args>) | |
1 0.000000 endif | |
" -- issue | |
1 0.000002 command! -nargs=0 GoReportGitHubIssue call go#issue#New() | |
" -- iferr | |
1 0.000003 command! -nargs=0 GoIfErr call go#iferr#Generate() | |
" -- lsp | |
1 0.000006 command! -nargs=+ -complete=dir GoAddWorkspace call go#lsp#AddWorkspaceDirectory(<f-args>) | |
1 0.000002 command! -nargs=0 GoLSPDebugBrowser call go#lsp#DebugBrowser() | |
1 0.000003 command! -nargs=* -bang GoDiagnostics call go#lint#Diagnostics(<bang>0, <f-args>) | |
" -- term | |
1 0.000002 command! GoToggleTermCloseOnExit call go#term#ToggleCloseOnExit() | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/package.vim | |
Sourced 1 time | |
Total time: 0.000565 | |
Self time: 0.000565 | |
count total (s) self (s) | |
" Copyright 2011 The Go Authors. All rights reserved. | |
" Use of this source code is governed by a BSD-style | |
" license that can be found in the LICENSE file. | |
" | |
" This file provides a utility function that performs auto-completion of | |
" package names, for use by other commands. | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000006 let s:cpo_save = &cpo | |
1 0.000005 set cpo&vim | |
1 0.000007 let s:goos = $GOOS | |
1 0.000003 let s:goarch = $GOARCH | |
1 0.000004 if len(s:goos) == 0 | |
1 0.000003 if exists('g:golang_goos') | |
let s:goos = g:golang_goos | |
1 0.000005 elseif has('win32') || has('win64') | |
let s:goos = 'windows' | |
1 0.000002 elseif has('macunix') | |
1 0.000002 let s:goos = 'darwin' | |
else | |
let s:goos = '*' | |
1 0.000001 endif | |
1 0.000001 endif | |
1 0.000002 if len(s:goarch) == 0 | |
1 0.000002 if exists('g:golang_goarch') | |
let s:goarch = g:golang_goarch | |
1 0.000001 else | |
1 0.000001 let s:goarch = '*' | |
1 0.000001 endif | |
1 0.000001 endif | |
1 0.000005 function! s:paths() abort | |
let dirs = [] | |
if !exists("s:goroot") | |
if executable('go') | |
let s:goroot = go#util#env("goroot") | |
if go#util#ShellError() != 0 | |
call go#util#EchoError('`go env GOROOT` failed') | |
endif | |
else | |
let s:goroot = $GOROOT | |
endif | |
endif | |
if len(s:goroot) != 0 && isdirectory(s:goroot) | |
let dirs += [s:goroot] | |
endif | |
let workspaces = split(go#path#Default(), go#util#PathListSep()) | |
if workspaces != [] | |
let dirs += workspaces | |
endif | |
return dirs | |
endfunction | |
1 0.000001 function! s:module() abort | |
let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-m', '-f', '{{.Dir}}']) | |
if l:err != 0 | |
return {} | |
endif | |
let l:dir = split(l:out, '\n')[0] | |
let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-m', '-f', '{{.Path}}']) | |
if l:err != 0 | |
return {} | |
endif | |
let l:path = split(l:out, '\n')[0] | |
return {'dir': l:dir, 'path': l:path} | |
endfunction | |
1 0.000002 function! s:vendordirs() abort | |
let l:vendorsuffix = go#util#PathSep() . 'vendor' | |
let l:module = s:module() | |
if empty(l:module) | |
let [l:root, l:err] = go#util#ExecInDir(['go', 'list', '-f', '{{.Root}}']) | |
if l:err != 0 | |
return [] | |
endif | |
if empty(l:root) | |
return [] | |
endif | |
let l:root = split(l:root, '\n')[0] . go#util#PathSep() . 'src' | |
let [l:dir, l:err] = go#util#ExecInDir(['go', 'list', '-f', '{{.Dir}}']) | |
if l:err != 0 | |
return [] | |
endif | |
let l:dir = split(l:dir, '\n')[0] | |
let l:vendordirs = [] | |
while l:dir != l:root | |
let l:vendordir = l:dir . l:vendorsuffix | |
if isdirectory(l:vendordir) | |
let l:vendordirs = add(l:vendordirs, l:vendordir) | |
endif | |
let l:dir = fnamemodify(l:dir, ':h') | |
endwhile | |
return l:vendordirs | |
endif | |
let l:vendordir = l:module.dir . l:vendorsuffix | |
if !isdirectory(l:vendordir) | |
return [] | |
endif | |
return [l:vendordir] | |
endfunction | |
1 0.000003 let s:import_paths = {} | |
" ImportPath returns the import path of the package for current buffer. It | |
" returns -1 if the import path cannot be determined. | |
1 0.000002 function! go#package#ImportPath() abort | |
let l:dir = expand("%:p:h") | |
if has_key(s:import_paths, dir) | |
return s:import_paths[l:dir] | |
endif | |
let l:importpath = go#package#FromPath(l:dir) | |
if type(l:importpath) == type(0) | |
return -1 | |
endif | |
let s:import_paths[l:dir] = l:importpath | |
return l:importpath | |
endfunction | |
1 0.000002 let s:in_gopath = {} | |
" InGOPATH returns TRUE when the package of the current buffer is within | |
" GOPATH. | |
1 0.000002 function! go#package#InGOPATH() abort | |
let l:dir = expand("%:p:h") | |
if has_key(s:in_gopath, dir) | |
return s:in_gopath[l:dir][0] !=# '_' | |
endif | |
try | |
" turn off module support so that `go list` will report the package name | |
" with a leading '_' when the current buffer is not within GOPATH. | |
let Restore_modules = go#util#SetEnv('GO111MODULE', 'off') | |
let [l:out, l:err] = go#util#ExecInDir(['go', 'list']) | |
if l:err != 0 | |
return 0 | |
endif | |
let l:importpath = split(l:out, '\n')[0] | |
if len(l:importpath) > 0 | |
let s:in_gopath[l:dir] = l:importpath | |
endif | |
finally | |
call call(Restore_modules, []) | |
endtry | |
return len(l:importpath) > 0 && l:importpath[0] !=# '_' | |
endfunction | |
" go#package#FromPath returns the import path of arg. -1 is returned when arg | |
" does not specify a package. -2 is returned when arg is a relative path | |
" outside of GOPATH, not in a module, and not below the current working | |
" directory. A relative path is returned when in a null module at or below the | |
" current working directory.. | |
1 0.000002 function! go#package#FromPath(arg) abort | |
let l:path = fnamemodify(a:arg, ':p') | |
if !isdirectory(l:path) | |
let l:path = fnamemodify(l:path, ':h') | |
endif | |
let l:dir = go#util#Chdir(l:path) | |
try | |
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. To avoid `go list` making a | |
" bunch of HTTP requests to fetch dependencies, short-circuit `go list` | |
" and return -1 immediately. | |
if !empty(s:module()) | |
return -1 | |
endif | |
endif | |
let [l:out, l:err] = go#util#Exec(['go', 'list']) | |
if l:err != 0 | |
return -1 | |
endif | |
let l:importpath = split(l:out, '\n')[0] | |
finally | |
call go#util#Chdir(l:dir) | |
endtry | |
" go list returns '_CURRENTDIRECTORY' if the directory is in a null module | |
" (i.e. neither in GOPATH nor in a module). Return a relative import path | |
" if possible or an error if that is the case. | |
if l:importpath[0] ==# '_' | |
let l:relativeimportpath = fnamemodify(l:importpath[1:], ':.') | |
if go#util#IsWin() | |
let l:relativeimportpath = substitute(l:relativeimportpath, '\\', '/', 'g') | |
endif | |
if l:relativeimportpath == l:importpath[1:] | |
return '.' | |
endif | |
if l:relativeimportpath[0] == '/' | |
return -2 | |
endif | |
let l:importpath= printf('./%s', l:relativeimportpath) | |
endif | |
return l:importpath | |
endfunction | |
1 0.000003 function! go#package#CompleteMembers(package, member) abort | |
let [l:content, l:err] = go#util#Exec(['go', 'doc', a:package]) | |
if l:err || !len(content) | |
return [] | |
endif | |
let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'") | |
try | |
let mx1 = '^\s\+\(\S+\)\s\+=\s\+.*' | |
let mx2 = '^\%(const\|var\|type\|func\) \([A-Z][^ (]\+\).*' | |
let candidates = map(filter(copy(lines), 'v:val =~ mx1'), | |
\ 'substitute(v:val, mx1, "\\1", "")') | |
\ + map(filter(copy(lines), 'v:val =~ mx2'), | |
\ 'substitute(v:val, mx2, "\\1", "")') | |
return filter(candidates, '!stridx(v:val, a:member)') | |
catch | |
return [] | |
endtry | |
endfunction | |
1 0.000003 function! go#package#Complete(ArgLead, CmdLine, CursorPos) abort | |
let words = split(a:CmdLine, '\s\+', 1) | |
" do not complete package members for these commands | |
let neglect_commands = ["GoImportAs", "GoGuruScope"] | |
if len(words) > 2 && index(neglect_commands, words[0]) == -1 | |
" Complete package members | |
return go#package#CompleteMembers(words[1], words[2]) | |
endif | |
let dirs = s:paths() | |
let module = s:module() | |
if len(dirs) == 0 && empty(module) | |
" should not happen | |
return [] | |
endif | |
let vendordirs = s:vendordirs() | |
let l:modcache = go#util#env('gomodcache') | |
let ret = {} | |
for dir in dirs | |
" this may expand to multiple lines | |
let root = split(expand(dir . '/pkg/' . s:goos . '_' . s:goarch), "\n") | |
if l:modcache != '' | |
let root = add(root, l:modcache) | |
else | |
let root = add(root, expand(dir . '/pkg/mod')) | |
endif | |
let root = add(root, expand(dir . '/src'), ) | |
let root = extend(root, vendordirs) | |
let root = add(root, module) | |
for item in root | |
" item may be a dictionary when operating in a module. | |
if type(item) == type({}) | |
if empty(item) | |
continue | |
endif | |
let dir = item.dir | |
let path = item.path | |
else | |
let dir = item | |
let path = item | |
endif | |
if !empty(module) && dir ==# module.dir | |
if stridx(a:ArgLead, module.path) == 0 | |
if len(a:ArgLead) != len(module.path) | |
let glob = globpath(module.dir, substitute(a:ArgLead, module.path . '/\?', '', '').'*') | |
else | |
let glob = module.dir | |
endif | |
elseif stridx(module.path, a:ArgLead) == 0 && stridx(module.path, '/', len(a:ArgLead)) < 0 | |
" use the module directory when module.path begins wih a:ArgLead and | |
" module.path does not have any path segments after a:ArgLead. | |
let glob = module.dir | |
else | |
continue | |
endif | |
else | |
let glob = globpath(dir, a:ArgLead.'*') | |
endif | |
for candidate in split(glob) | |
if isdirectory(candidate) | |
" TODO(bc): use wildignore instead of filtering out vendor | |
" directories manually? | |
if fnamemodify(candidate, ':t') == 'vendor' | |
continue | |
endif | |
" if path contains version info, strip it out | |
let vidx = strridx(candidate, '@') | |
if vidx >= 0 | |
let candidate = strpart(candidate, 0, vidx) | |
endif | |
let candidate .= '/' | |
elseif candidate !~ '\.a$' | |
continue | |
endif | |
if dir !=# path | |
let candidate = substitute(candidate, '^' . dir, path, 'g') | |
else | |
let candidate = candidate[len(dir)+1:] | |
endif | |
" replace a backslash with a forward slash and drop .a suffixes | |
let candidate = substitute(substitute(candidate, '[\\]', '/', 'g'), | |
\ '\.a$', '', 'g') | |
" without this the result can have duplicates in form of | |
" 'encoding/json' and '/encoding/json/' | |
let candidate = go#util#StripPathSep(candidate) | |
let ret[candidate] = candidate | |
endfor | |
endfor | |
endfor | |
return sort(keys(ret)) | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000005 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/path.vim | |
Sourced 1 time | |
Total time: 0.000306 | |
Self time: 0.000306 | |
count total (s) self (s) | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000003 let s:cpo_save = &cpo | |
1 0.000003 set cpo&vim | |
" initial_go_path is used to store the initial GOPATH that was set when Vim | |
" was started. It's used with :GoPathClear to restore the GOPATH when the user | |
" changed it explicitly via :GoPath. Initially it's empty. It's being set when | |
" :GoPath is used | |
1 0.000001 let s:initial_go_path = "" | |
" GoPath sets or echos the current GOPATH. If no arguments are passed it | |
" echoes the current GOPATH, if an argument is passed it replaces the current | |
" GOPATH with it. If two double quotes are passed (the empty string in go), | |
" it'll clear the GOPATH and will restore to the initial GOPATH. | |
1 0.000001 function! go#path#GoPath(...) abort | |
" no argument, show GOPATH | |
if len(a:000) == 0 | |
echo go#path#Default() | |
return | |
endif | |
" we have an argument, replace GOPATH | |
" clears the current manually set GOPATH and restores it to the | |
" initial GOPATH, which was set when Vim was started. | |
if len(a:000) == 1 && a:1 == '""' | |
if !empty(s:initial_go_path) | |
let $GOPATH = s:initial_go_path | |
let s:initial_go_path = "" | |
endif | |
call go#util#EchoInfo("GOPATH restored to ". $GOPATH) | |
return | |
endif | |
call go#util#EchoInfo("GOPATH changed to ". a:1) | |
let s:initial_go_path = $GOPATH | |
let $GOPATH = a:1 | |
endfunction | |
" Default returns the default GOPATH. If GOPATH is not set, it uses the | |
" default GOPATH set starting with Go 1.8. This GOPATH can be retrieved via | |
" 'go env GOPATH' | |
1 0.000002 function! go#path#Default() abort | |
if $GOPATH == "" | |
" use default GOPATH via go env | |
return go#util#env("gopath") | |
endif | |
return $GOPATH | |
endfunction | |
" s:HasPath checks whether the given path exists in GOPATH environment variable | |
" or not | |
1 0.000001 function! s:HasPath(path) abort | |
let go_paths = split(go#path#Default(), go#util#PathListSep()) | |
let last_char = strlen(a:path) - 1 | |
" check cases of '/foo/bar/' and '/foo/bar' | |
if a:path[last_char] == go#util#PathSep() | |
let withSep = a:path | |
let noSep = strpart(a:path, 0, last_char) | |
else | |
let withSep = a:path . go#util#PathSep() | |
let noSep = a:path | |
endif | |
let hasA = index(go_paths, withSep) != -1 | |
let hasB = index(go_paths, noSep) != -1 | |
return hasA || hasB | |
endfunction | |
" BinPath returns the binary path of installed go tools. | |
1 0.000002 function! go#path#BinPath() abort | |
let l:bin_path = go#config#BinPath() | |
if l:bin_path isnot "" | |
return l:bin_path | |
endif | |
" check if our global custom path is set, if not check if GOBIN is set so | |
" we can use it, otherwise use default GOPATH | |
let l:bin_path = go#util#env('gobin') | |
if l:bin_path isnot '' | |
let l:bin_path = $GOBIN | |
else | |
let l:go_paths = split(go#path#Default(), go#util#PathListSep()) | |
if len(l:go_paths) == 0 | |
return '' "nothing found | |
endif | |
let l:bin_path = expand(l:go_paths[0] . '/bin/') | |
endif | |
return l:bin_path | |
endfunction | |
" CheckBinPath checks whether the given binary exists or not and returns the | |
" path of the binary, respecting the go_bin_path and go_search_bin_path_first | |
" settings. It returns an empty string if the binary doesn't exist. | |
1 0.000001 function! go#path#CheckBinPath(binpath) abort | |
" remove whitespaces if user applied something like 'goimports ' | |
let binpath = substitute(a:binpath, '^\s*\(.\{-}\)\s*$', '\1', '') | |
" save original path | |
let old_path = $PATH | |
" check if we have an appropriate bin_path | |
let go_bin_path = go#path#BinPath() | |
if !empty(go_bin_path) | |
" append our GOBIN and GOPATH paths and be sure they can be found there... | |
" let us search in our GOBIN and GOPATH paths | |
" respect the ordering specified by go_search_bin_path_first | |
if go#config#SearchBinPathFirst() | |
let $PATH = go_bin_path . go#util#PathListSep() . $PATH | |
else | |
let $PATH = $PATH . go#util#PathListSep() . go_bin_path | |
endif | |
endif | |
" if it's in PATH just return it | |
if executable(binpath) | |
if exists('*exepath') | |
let binpath = exepath(binpath) | |
endif | |
let $PATH = old_path | |
if go#util#IsUsingCygwinShell() == 1 | |
return s:CygwinPath(binpath) | |
endif | |
return binpath | |
endif | |
" just get the basename | |
let basename = fnamemodify(binpath, ":t") | |
if !executable(basename) | |
call go#util#EchoError(printf("could not find '%s'. Run :GoInstallBinaries to fix it", basename)) | |
" restore back! | |
let $PATH = old_path | |
return "" | |
endif | |
let $PATH = old_path | |
if go#util#IsUsingCygwinShell() == 1 | |
return s:CygwinPath(a:binpath) | |
endif | |
return go_bin_path . go#util#PathSep() . basename | |
endfunction | |
1 0.000001 function! s:CygwinPath(path) | |
return substitute(a:path, '\\', '/', "g") | |
endfunction | |
" go#path#ToURI converts path to a file URI. path should be an absolute path. | |
" Relative paths cannot be properly converted to a URI; when path is a | |
" relative path, the file scheme will not be prepended. | |
1 0.000001 function! go#path#ToURI(path) | |
let l:absolute = !go#util#IsWin() && a:path[0] is# '/' | |
let l:prefix = '' | |
let l:path = a:path | |
if go#util#IsWin() && l:path[1:2] is# ':\' | |
let l:absolute = 1 | |
let l:prefix = '/' . l:path[0:1] | |
let l:path = l:path[2:] | |
endif | |
return substitute( | |
\ (l:absolute ? 'file://' : '') . l:prefix . go#uri#EncodePath(l:path), | |
\ '\\', | |
\ '/', | |
\ 'g', | |
\) | |
endfunction | |
1 0.000001 function! go#path#FromURI(uri) abort | |
let l:i = len('file://') | |
let l:encoded_path = a:uri[: l:i - 1] is# 'file://' ? a:uri[l:i :] : a:uri | |
let l:path = go#uri#Decode(l:encoded_path) | |
" If the path is like /C:/foo/bar, it should be C:\foo\bar instead. | |
if go#util#IsWin() && l:path =~# '^/[a-zA-Z]:' | |
let l:path = substitute(l:path[1:], '/', '\\', 'g') | |
endif | |
return l:path | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000003 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/ftplugin/go/mappings.vim | |
Sourced 1 time | |
Total time: 0.000499 | |
Self time: 0.000499 | |
count total (s) self (s) | |
" go_jump_to_error defines whether we should pass the bang attribute to the | |
" command or not. This is only used for mappings, because the user can't pass | |
" the bang attribute to the plug mappings below. So instead of hardcoding it | |
" as 0 (no '!' attribute) or 1 (with '!' attribute) we pass the user setting, | |
" which by default is enabled. For commands the user has the ability to pass | |
" the '!', such as :GoBuild or :GoBuild! | |
1 0.000006 if !exists("g:go_jump_to_error") | |
1 0.000003 let g:go_jump_to_error = 1 | |
1 0.000001 endif | |
" Some handy plug mappings | |
1 0.000014 nnoremap <silent> <Plug>(go-run) :<C-u>call go#cmd#Run(!g:go_jump_to_error)<CR> | |
1 0.000002 if has("nvim") || has("terminal") | |
1 0.000007 nnoremap <silent> <Plug>(go-run-vertical) :<C-u>call go#cmd#RunTerm(!g:go_jump_to_error, 'vsplit', [])<CR> | |
1 0.000005 nnoremap <silent> <Plug>(go-run-split) :<C-u>call go#cmd#RunTerm(!g:go_jump_to_error, 'split', [])<CR> | |
1 0.000005 nnoremap <silent> <Plug>(go-run-tab) :<C-u>call go#cmd#RunTerm(!g:go_jump_to_error, 'tabe', [])<CR> | |
1 0.000000 endif | |
1 0.000003 nnoremap <silent> <Plug>(go-build) :<C-u>call go#cmd#Build(!g:go_jump_to_error)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-generate) :<C-u>call go#cmd#Generate(!g:go_jump_to_error)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-install) :<C-u>call go#cmd#Install(!g:go_jump_to_error)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-test) :<C-u>call go#test#Test(!g:go_jump_to_error, 0)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-test-func) :<C-u>call go#test#Func(!g:go_jump_to_error)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-test-compile) :<C-u>call go#test#Test(!g:go_jump_to_error, 1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-coverage) :<C-u>call go#coverage#Buffer(!g:go_jump_to_error)<CR> | |
1 0.000012 nnoremap <silent> <Plug>(go-coverage-clear) :<C-u>call go#coverage#Clear()<CR> | |
1 0.000004 nnoremap <silent> <Plug>(go-coverage-toggle) :<C-u>call go#coverage#BufferToggle(!g:go_jump_to_error)<CR> | |
1 0.000005 nnoremap <silent> <Plug>(go-coverage-browser) :<C-u>call go#coverage#Browser(!g:go_jump_to_error)<CR> | |
1 0.000004 nnoremap <silent> <Plug>(go-files) :<C-u>call go#tool#Files()<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-deps) :<C-u>call go#tool#Deps()<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-info) :<C-u>call go#tool#Info(1)<CR> | |
1 0.000004 nnoremap <silent> <Plug>(go-import) :<C-u>call go#import#SwitchImport(1, '', expand('<cword>'), '')<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-imports) :<C-u>call go#fmt#Format(1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-fmt) :<C-u>call go#fmt#Format(0)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-implements) :<C-u>call go#implements#Implements(-1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-callees) :<C-u>call go#guru#Callees(-1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-callers) :<C-u>call go#calls#Callers()<CR> | |
1 0.000004 nnoremap <silent> <Plug>(go-describe) :<C-u>call go#guru#Describe(-1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-callstack) :<C-u>call go#guru#Callstack(-1)<CR> | |
1 0.000003 xnoremap <silent> <Plug>(go-freevars) :<C-u>call go#guru#Freevars(0)<CR> | |
1 0.000004 nnoremap <silent> <Plug>(go-channelpeers) :<C-u>call go#guru#ChannelPeers(-1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-referrers) :<C-u>call go#referrers#Referrers(-1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-sameids) :<C-u>call go#guru#SameIds(1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-pointsto) :<C-u>call go#guru#PointsTo(-1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-whicherrs) :<C-u>call go#guru#Whicherrs(-1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-sameids-toggle) :<C-u>call go#guru#ToggleSameIds()<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-rename) :<C-u>call go#rename#Rename(!g:go_jump_to_error)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-decls) :<C-u>call go#decls#Decls(0, '')<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-decls-dir) :<C-u>call go#decls#Decls(1, '')<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def) :<C-u>call go#def#Jump('', 0)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-vertical) :<C-u>call go#def#Jump("vsplit", 0)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-split) :<C-u>call go#def#Jump("split", 0)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-tab) :<C-u>call go#def#Jump("tab", 0)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-type) :<C-u>call go#def#Jump('', 1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-type-vertical) :<C-u>call go#def#Jump("vsplit", 1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-type-split) :<C-u>call go#def#Jump("split", 1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-type-tab) :<C-u>call go#def#Jump("tab", 1)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-pop) :<C-u>call go#def#StackPop()<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-stack) :<C-u>call go#def#Stack()<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-def-stack-clear) :<C-u>call go#def#StackClear()<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-doc) :<C-u>call go#doc#Open("new", "split")<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-doc-tab) :<C-u>call go#doc#Open("tabnew", "tabe")<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-doc-vertical) :<C-u>call go#doc#Open("vnew", "vsplit")<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-doc-split) :<C-u>call go#doc#Open("new", "split")<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-doc-browser) :<C-u>call go#doc#OpenBrowser()<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-metalinter) :<C-u>call go#lint#Gometa(!g:go_jump_to_error, 0)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-lint) :<C-u>call go#lint#Golint(!g:go_jump_to_error)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-vet) :<C-u>call go#lint#Vet(!g:go_jump_to_error)<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-alternate-edit) :<C-u>call go#alternate#Switch(0, "edit")<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-alternate-vertical) :<C-u>call go#alternate#Switch(0, "vsplit")<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-alternate-split) :<C-u>call go#alternate#Switch(0, "split")<CR> | |
1 0.000003 nnoremap <silent> <Plug>(go-iferr) :<C-u>call go#iferr#Generate()<CR> | |
1 0.000004 nnoremap <silent> <Plug>(go-diagnostics) :<C-u>call go#lint#Diagnostics(!g:go_jump_to_error)<CR> | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/ftplugin/go/snippets.vim | |
Sourced 1 time | |
Total time: 0.000171 | |
Self time: 0.000161 | |
count total (s) self (s) | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000004 let s:cpo_save = &cpo | |
1 0.000005 set cpo&vim | |
1 0.000002 if exists("g:go_loaded_gosnippets") | |
finish | |
1 0.000000 endif | |
1 0.000001 let g:go_loaded_gosnippets = 1 | |
1 0.000002 function! s:GoUltiSnips() abort | |
if get(g:, 'did_plugin_ultisnips') isnot 1 | |
return | |
endif | |
if !exists("g:UltiSnipsSnippetDirectories") | |
let g:UltiSnipsSnippetDirectories = ["gosnippets/UltiSnips"] | |
else | |
let g:UltiSnipsSnippetDirectories += ["gosnippets/UltiSnips"] | |
endif | |
endfunction | |
1 0.000001 function! s:GoNeosnippet() abort | |
if get(g:, 'loaded_neosnippet') isnot 1 | |
return | |
endif | |
let g:neosnippet#enable_snipmate_compatibility = 1 | |
let l:gosnippets_dir = globpath(&rtp, 'gosnippets/snippets') | |
if type(g:neosnippet#snippets_directory) == type([]) | |
let g:neosnippet#snippets_directory += [l:gosnippets_dir] | |
elseif type(g:neosnippet#snippets_directory) == type("") | |
if strlen(g:neosnippet#snippets_directory) > 0 | |
let g:neosnippet#snippets_directory = g:neosnippet#snippets_directory . "," . l:gosnippets_dir | |
else | |
let g:neosnippet#snippets_directory = l:gosnippets_dir | |
endif | |
endif | |
endfunction | |
1 0.000001 function! s:GoMinisnip() abort | |
if get(g:, 'loaded_minisnip') isnot 1 | |
return | |
endif | |
if exists('g:minisnip_dir') | |
let g:minisnip_dir .= go#util#PathListSep() . globpath(&rtp, 'gosnippets/minisnip') | |
else | |
let g:minisnip_dir = globpath(&rtp, 'gosnippets/minisnip') | |
endif | |
endfunction | |
1 0.000016 0.000006 let s:engine = go#config#SnippetEngine() | |
1 0.000001 if s:engine is? 'ultisnips' | |
call s:GoUltiSnips() | |
1 0.000001 elseif s:engine is? 'neosnippet' | |
call s:GoNeosnippet() | |
1 0.000001 elseif s:engine is? 'minisnip' | |
call s:GoMinisnip() | |
1 0.000000 endif | |
" restore Vi compatibility settings | |
1 0.000002 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/ftplugin/go/tagbar.vim | |
Sourced 1 time | |
Total time: 0.000755 | |
Self time: 0.000755 | |
count total (s) self (s) | |
" Check if tagbar is installed under plugins or is directly under rtp | |
" this covers pathogen + Vundle/Bundle | |
" | |
" Also make sure the ctags command exists | |
" | |
1 0.000263 if !executable('ctags') | |
finish | |
1 0.000461 elseif globpath(&rtp, 'plugin/tagbar.vim') == "" | |
1 0.000001 finish | |
endif | |
" don't spam the user when Vim is started in Vi compatibility mode | |
let s:cpo_save = &cpo | |
set cpo&vim | |
if !exists("g:go_gotags_bin") | |
let g:go_gotags_bin = "gotags" | |
endif | |
function! s:SetTagbar() | |
let bin_path = go#path#CheckBinPath(g:go_gotags_bin) | |
if empty(bin_path) | |
return | |
endif | |
if !exists("g:tagbar_type_go") | |
let g:tagbar_type_go = { | |
\ 'ctagstype' : 'go', | |
\ 'kinds' : [ | |
\ 'p:package', | |
\ 'i:imports', | |
\ 'c:constants', | |
\ 'v:variables', | |
\ 't:types', | |
\ 'n:interfaces', | |
\ 'w:fields', | |
\ 'e:embedded', | |
\ 'm:methods', | |
\ 'r:constructor', | |
\ 'f:functions' | |
\ ], | |
\ 'sro' : '.', | |
\ 'kind2scope' : { | |
\ 't' : 'ctype', | |
\ 'n' : 'ntype' | |
\ }, | |
\ 'scope2kind' : { | |
\ 'ctype' : 't', | |
\ 'ntype' : 'n' | |
\ }, | |
\ 'ctagsbin' : bin_path, | |
\ 'ctagsargs' : '-sort -silent' | |
\ } | |
endif | |
endfunction | |
call s:SetTagbar() | |
" restore Vi compatibility settings | |
let &cpo = s:cpo_save | |
unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /opt/homebrew/Cellar/neovim/0.5.1_1/share/nvim/runtime/ftplugin/go.vim | |
Sourced 1 time | |
Total time: 0.000246 | |
Self time: 0.000246 | |
count total (s) self (s) | |
" Vim filetype plugin file | |
" Language: Go | |
" Maintainer: David Barnett (https://github.com/google/vim-ft-go) | |
" Last Change: 2014 Aug 16 | |
1 0.000002 if exists('b:did_ftplugin') | |
1 0.000000 finish | |
endif | |
let b:did_ftplugin = 1 | |
setlocal formatoptions-=t | |
setlocal comments=s1:/*,mb:*,ex:*/,:// | |
setlocal commentstring=//\ %s | |
let b:undo_ftplugin = 'setl fo< com< cms<' | |
" vim: sw=2 sts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/indent/go.vim | |
Sourced 2 times | |
Total time: 0.000213 | |
Self time: 0.000213 | |
count total (s) self (s) | |
" Copyright 2011 The Go Authors. All rights reserved. | |
" Use of this source code is governed by a BSD-style | |
" license that can be found in the LICENSE file. | |
" | |
" indent/go.vim: Vim indent file for Go. | |
" | |
" TODO: | |
" - function invocations split across lines | |
" - general line splits (line ends in an operator) | |
2 0.000004 if exists("b:did_indent") | |
1 0.000001 finish | |
1 0.000000 endif | |
1 0.000001 let b:did_indent = 1 | |
" C indentation is too far off useful, mainly due to Go's := operator. | |
" Let's just define our own. | |
1 0.000014 setlocal nolisp | |
1 0.000001 setlocal autoindent | |
1 0.000003 setlocal indentexpr=GoIndent(v:lnum) | |
1 0.000003 setlocal indentkeys+=<:>,0=},0=) | |
1 0.000001 if exists("*GoIndent") | |
finish | |
1 0.000000 endif | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000002 let s:cpo_save = &cpo | |
1 0.000002 set cpo&vim | |
1 0.000001 function! GoIndent(lnum) abort | |
let prevlnum = prevnonblank(a:lnum-1) | |
if prevlnum == 0 | |
" top of file | |
return 0 | |
endif | |
" grab the previous and current line, stripping comments. | |
let prevl = substitute(getline(prevlnum), '//.*$', '', '') | |
let thisl = substitute(getline(a:lnum), '//.*$', '', '') | |
let previ = indent(prevlnum) | |
let ind = previ | |
for synid in synstack(a:lnum, 1) | |
if synIDattr(synid, 'name') == 'goRawString' | |
if prevl =~ '\%(\%(:\?=\)\|(\|,\)\s*`[^`]*$' | |
" previous line started a multi-line raw string | |
return 0 | |
endif | |
" return -1 to keep the current indent. | |
return -1 | |
endif | |
endfor | |
if prevl =~ '[({]\s*$' | |
" previous line opened a block | |
let ind += shiftwidth() | |
endif | |
if prevl =~# '^\s*\(case .*\|default\):$' | |
" previous line is part of a switch statement | |
let ind += shiftwidth() | |
endif | |
" TODO: handle if the previous line is a label. | |
if thisl =~ '^\s*[)}]' | |
" this line closed a block | |
let ind -= shiftwidth() | |
endif | |
" Colons are tricky. | |
" We want to outdent if it's part of a switch ("case foo:" or "default:"). | |
" We ignore trying to deal with jump labels because (a) they're rare, and | |
" (b) they're hard to disambiguate from a composite literal key. | |
if thisl =~# '^\s*\(case .*\|default\):$' | |
let ind -= shiftwidth() | |
endif | |
return ind | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000002 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /opt/homebrew/Cellar/neovim/0.5.1_1/share/nvim/runtime/indent/go.vim | |
Sourced 1 time | |
Total time: 0.000145 | |
Self time: 0.000145 | |
count total (s) self (s) | |
" Vim indent file | |
" Language: Go | |
" Maintainer: David Barnett (https://github.com/google/vim-ft-go) | |
" Last Change: 2017 Jun 13 | |
" | |
" TODO: | |
" - function invocations split across lines | |
" - general line splits (line ends in an operator) | |
1 0.000002 if exists('b:did_indent') | |
1 0.000000 finish | |
endif | |
let b:did_indent = 1 | |
" C indentation is too far off useful, mainly due to Go's := operator. | |
" Let's just define our own. | |
setlocal nolisp | |
setlocal autoindent | |
setlocal indentexpr=GoIndent(v:lnum) | |
setlocal indentkeys+=<:>,0=},0=) | |
if exists('*GoIndent') | |
finish | |
endif | |
function! GoIndent(lnum) | |
let l:prevlnum = prevnonblank(a:lnum-1) | |
if l:prevlnum == 0 | |
" top of file | |
return 0 | |
endif | |
" grab the previous and current line, stripping comments. | |
let l:prevl = substitute(getline(l:prevlnum), '//.*$', '', '') | |
let l:thisl = substitute(getline(a:lnum), '//.*$', '', '') | |
let l:previ = indent(l:prevlnum) | |
let l:ind = l:previ | |
if l:prevl =~ '[({]\s*$' | |
" previous line opened a block | |
let l:ind += shiftwidth() | |
endif | |
if l:prevl =~# '^\s*\(case .*\|default\):$' | |
" previous line is part of a switch statement | |
let l:ind += shiftwidth() | |
endif | |
" TODO: handle if the previous line is a label. | |
if l:thisl =~ '^\s*[)}]' | |
" this line closed a block | |
let l:ind -= shiftwidth() | |
endif | |
" Colons are tricky. | |
" We want to outdent if it's part of a switch ("case foo:" or "default:"). | |
" We ignore trying to deal with jump labels because (a) they're rare, and | |
" (b) they're hard to disambiguate from a composite literal key. | |
if l:thisl =~# '^\s*\(case .*\|default\):$' | |
let l:ind -= shiftwidth() | |
endif | |
return l:ind | |
endfunction | |
" vim: sw=2 sts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/syntax/go.vim | |
Sourced 2 times | |
Total time: 0.001445 | |
Self time: 0.001282 | |
count total (s) self (s) | |
" Copyright 2009 The Go Authors. All rights reserved. | |
" Use of this source code is governed by a BSD-style | |
" license that can be found in the LICENSE file. | |
" | |
" go.vim: Vim syntax file for Go. | |
" Quit when a (custom) syntax file was already loaded | |
2 0.000003 if exists("b:current_syntax") | |
1 0.000001 finish | |
1 0.000000 endif | |
1 0.000001 syn case match | |
1 0.000017 syn keyword goPackage package | |
1 0.000004 syn keyword goImport import contained | |
1 0.000004 syn keyword goVar var contained | |
1 0.000004 syn keyword goConst const contained | |
1 0.000004 hi def link goPackage Statement | |
1 0.000003 hi def link goImport Statement | |
1 0.000003 hi def link goVar Keyword | |
1 0.000003 hi def link goConst Keyword | |
1 0.000006 hi def link goDeclaration Keyword | |
" Keywords within functions | |
1 0.000005 syn keyword goStatement defer go goto return break continue fallthrough | |
1 0.000004 syn keyword goConditional if else switch select | |
1 0.000004 syn keyword goLabel case default | |
1 0.000004 syn keyword goRepeat for range | |
1 0.000003 hi def link goStatement Statement | |
1 0.000003 hi def link goConditional Conditional | |
1 0.000003 hi def link goLabel Label | |
1 0.000003 hi def link goRepeat Repeat | |
" Predefined types | |
1 0.000004 syn keyword goType chan map bool string error | |
1 0.000005 syn keyword goSignedInts int int8 int16 int32 int64 rune | |
1 0.000004 syn keyword goUnsignedInts byte uint uint8 uint16 uint32 uint64 uintptr | |
1 0.000004 syn keyword goFloats float32 float64 | |
1 0.000004 syn keyword goComplexes complex64 complex128 | |
1 0.000003 hi def link goType Type | |
1 0.000003 hi def link goSignedInts Type | |
1 0.000003 hi def link goUnsignedInts Type | |
1 0.000003 hi def link goFloats Type | |
1 0.000003 hi def link goComplexes Type | |
" Predefined functions and values | |
1 0.000007 syn keyword goBuiltins append cap close complex copy delete imag len | |
1 0.000003 syn keyword goBuiltins make new panic print println real recover | |
1 0.000004 syn keyword goBoolean true false | |
1 0.000007 syn keyword goPredefinedIdentifiers nil iota | |
1 0.000005 hi def link goBuiltins Identifier | |
1 0.000003 hi def link goBoolean Boolean | |
1 0.000001 hi def link goPredefinedIdentifiers goBoolean | |
" Comments; their contents | |
1 0.000004 syn keyword goTodo contained TODO FIXME XXX BUG | |
1 0.000002 syn cluster goCommentGroup contains=goTodo | |
1 0.000011 syn region goComment start="//" end="$" contains=goGenerate,@goCommentGroup,@Spell | |
1 0.000018 0.000008 if go#config#FoldEnable('comment') | |
syn region goComment start="/\*" end="\*/" contains=@goCommentGroup,@Spell fold | |
syn match goComment "\v(^\s*//.*\n)+" contains=goGenerate,@goCommentGroup,@Spell fold | |
1 0.000000 else | |
1 0.000002 syn region goComment start="/\*" end="\*/" contains=@goCommentGroup,@Spell | |
1 0.000000 endif | |
1 0.000003 hi def link goComment Comment | |
1 0.000003 hi def link goTodo Todo | |
1 0.000006 0.000004 if go#config#HighlightGenerateTags() | |
syn match goGenerateVariables contained /\%(\$GOARCH\|\$GOOS\|\$GOFILE\|\$GOLINE\|\$GOPACKAGE\|\$DOLLAR\)\>/ | |
syn region goGenerate start="^\s*//go:generate" end="$" contains=goGenerateVariables | |
hi def link goGenerate PreProc | |
hi def link goGenerateVariables Special | |
1 0.000000 endif | |
" Go escapes | |
1 0.000005 syn match goEscapeOctal display contained "\\[0-7]\{3}" | |
1 0.000005 syn match goEscapeC display contained +\\[abfnrtv\\'"]+ | |
1 0.000004 syn match goEscapeX display contained "\\x\x\{2}" | |
1 0.000004 syn match goEscapeU display contained "\\u\x\{4}" | |
1 0.000004 syn match goEscapeBigU display contained "\\U\x\{8}" | |
1 0.000005 syn match goEscapeError display contained +\\[^0-7xuUabfnrtv\\'"]+ | |
1 0.000004 hi def link goEscapeOctal goSpecialString | |
1 0.000001 hi def link goEscapeC goSpecialString | |
1 0.000001 hi def link goEscapeX goSpecialString | |
1 0.000001 hi def link goEscapeU goSpecialString | |
1 0.000001 hi def link goEscapeBigU goSpecialString | |
1 0.000003 hi def link goSpecialString Special | |
1 0.000003 hi def link goEscapeError Error | |
" Strings and their contents | |
1 0.000004 syn cluster goStringGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU,goEscapeError | |
1 0.000006 0.000004 if go#config#HighlightStringSpellcheck() | |
1 0.000007 syn region goString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@goStringGroup,@Spell | |
1 0.000005 syn region goRawString start=+`+ end=+`+ contains=@Spell | |
else | |
syn region goString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@goStringGroup | |
syn region goRawString start=+`+ end=+`+ | |
1 0.000000 endif | |
1 0.000007 syn match goImportString /^\%(\s\+\|import \)\(\h\w* \)\?\zs"[^"]\+"$/ contained containedin=goImport | |
1 0.000005 0.000004 if go#config#HighlightFormatStrings() | |
" [n] notation is valid for specifying explicit argument indexes | |
" 1. Match a literal % not preceded by a %. | |
" 2. Match any number of -, #, 0, space, or + | |
" 3. Match * or [n]* or any number or nothing before a . | |
" 4. Match * or [n]* or any number or nothing after a . | |
" 5. Match [n] or nothing before a verb | |
" 6. Match a formatting verb | |
1 0.000011 syn match goFormatSpecifier /\ | |
\%([^%]\%(%%\)*\)\ | |
\@<=%[-#0 +]*\ | |
\%(\%(\%(\[\d\+\]\)\=\*\)\|\d\+\)\=\ | |
\%(\.\%(\%(\%(\[\d\+\]\)\=\*\)\|\d\+\)\=\)\=\ | |
\%(\[\d\+\]\)\=[vTtbcdoqxXUeEfFgGspw]/ contained containedin=goString,goRawString | |
1 0.000001 hi def link goFormatSpecifier goSpecialString | |
1 0.000000 endif | |
1 0.000003 hi def link goImportString String | |
1 0.000003 hi def link goString String | |
1 0.000003 hi def link goRawString String | |
" Characters; their contents | |
1 0.000003 syn cluster goCharacterGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU | |
1 0.000006 syn region goCharacter start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@goCharacterGroup | |
1 0.000003 hi def link goCharacter Character | |
" Regions | |
1 0.000004 syn region goParen start='(' end=')' transparent | |
1 0.000009 0.000003 if go#config#FoldEnable('block') | |
1 0.000004 syn region goBlock start="{" end="}" transparent fold | |
else | |
syn region goBlock start="{" end="}" transparent | |
1 0.000000 endif | |
" import | |
1 0.000008 0.000003 if go#config#FoldEnable('import') | |
1 0.000004 syn region goImport start='import (' end=')' transparent fold contains=goImport,goImportString,goComment | |
else | |
syn region goImport start='import (' end=')' transparent contains=goImport,goImportString,goComment | |
1 0.000000 endif | |
" var, const | |
1 0.000007 0.000002 if go#config#FoldEnable('varconst') | |
1 0.000031 syn region goVar start='var (' end='^\s*)$' transparent fold | |
\ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator | |
1 0.000007 syn region goConst start='const (' end='^\s*)$' transparent fold | |
\ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator | |
else | |
syn region goVar start='var (' end='^\s*)$' transparent | |
\ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator | |
syn region goConst start='const (' end='^\s*)$' transparent | |
\ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator | |
1 0.000000 endif | |
" Single-line var, const, and import. | |
1 0.000007 syn match goSingleDecl /\%(import\|var\|const\) [^(]\@=/ contains=goImport,goVar,goConst | |
" Integers | |
1 0.000007 syn match goDecimalInt "\<-\=\(0\|[1-9]_\?\(\d\|\d\+_\?\d\+\)*\)\%([Ee][-+]\=\d\+\)\=\>" | |
1 0.000008 syn match goDecimalError "\<-\=\(_\(\d\+_*\)\+\|\([1-9]\d*_*\)\+__\(\d\+_*\)\+\|\([1-9]\d*_*\)\+_\+\)\%([Ee][-+]\=\d\+\)\=\>" | |
1 0.000005 syn match goHexadecimalInt "\<-\=0[xX]_\?\(\x\+_\?\)\+\>" | |
1 0.000006 syn match goHexadecimalError "\<-\=0[xX]_\?\(\x\+_\?\)*\(\([^ \t0-9A-Fa-f_)]\|__\)\S*\|_\)\>" | |
1 0.000005 syn match goOctalInt "\<-\=0[oO]\?_\?\(\o\+_\?\)\+\>" | |
1 0.000008 syn match goOctalError "\<-\=0[0-7oO_]*\(\([^ \t0-7oOxX_/)\]\}\:;]\|[oO]\{2,\}\|__\)\S*\|_\|[oOxX]\)\>" | |
1 0.000005 syn match goBinaryInt "\<-\=0[bB]_\?\([01]\+_\?\)\+\>" | |
1 0.000006 syn match goBinaryError "\<-\=0[bB]_\?[01_]*\([^ \t01_)]\S*\|__\S*\|_\)\>" | |
1 0.000004 hi def link goDecimalInt Integer | |
1 0.000003 hi def link goDecimalError Error | |
1 0.000001 hi def link goHexadecimalInt Integer | |
1 0.000003 hi def link goHexadecimalError Error | |
1 0.000001 hi def link goOctalInt Integer | |
1 0.000003 hi def link goOctalError Error | |
1 0.000001 hi def link goBinaryInt Integer | |
1 0.000003 hi def link goBinaryError Error | |
1 0.000003 hi def link Integer Number | |
" Floating point | |
1 0.000005 syn match goFloat "\<-\=\d\+\.\d*\%([Ee][-+]\=\d\+\)\=\>" | |
1 0.000002 syn match goFloat "\<-\=\.\d\+\%([Ee][-+]\=\d\+\)\=\>" | |
1 0.000003 hi def link goFloat Float | |
" Imaginary literals | |
1 0.000004 syn match goImaginary "\<-\=\d\+i\>" | |
1 0.000002 syn match goImaginary "\<-\=\d\+[Ee][-+]\=\d\+i\>" | |
1 0.000005 syn match goImaginaryFloat "\<-\=\d\+\.\d*\%([Ee][-+]\=\d\+\)\=i\>" | |
1 0.000002 syn match goImaginaryFloat "\<-\=\.\d\+\%([Ee][-+]\=\d\+\)\=i\>" | |
1 0.000003 hi def link goImaginary Number | |
1 0.000003 hi def link goImaginaryFloat Float | |
" Spaces after "[]" | |
1 0.000006 0.000004 if go#config#HighlightArrayWhitespaceError() | |
syn match goSpaceError display "\%(\[\]\)\@<=\s\+" | |
1 0.000000 endif | |
" Spacing errors around the 'chan' keyword | |
1 0.000005 0.000004 if go#config#HighlightChanWhitespaceError() | |
" receive-only annotation on chan type | |
" | |
" \(\<chan\>\)\@<!<- (only pick arrow when it doesn't come after a chan) | |
" this prevents picking up 'chan<- chan<-' but not '<- chan' | |
syn match goSpaceError display "\%(\%(\<chan\>\)\@<!<-\)\@<=\s\+\%(\<chan\>\)\@=" | |
" send-only annotation on chan type | |
" | |
" \(<-\)\@<!\<chan\> (only pick chan when it doesn't come after an arrow) | |
" this prevents picking up '<-chan <-chan' but not 'chan <-' | |
syn match goSpaceError display "\%(\%(<-\)\@<!\<chan\>\)\@<=\s\+\%(<-\)\@=" | |
" value-ignoring receives in a few contexts | |
syn match goSpaceError display "\%(\%(^\|[={(,;]\)\s*<-\)\@<=\s\+" | |
1 0.000000 endif | |
" Extra types commonly seen | |
1 0.000004 0.000003 if go#config#HighlightExtraTypes() | |
syn match goExtraType /\<bytes\.\%(Buffer\)\>/ | |
syn match goExtraType /\<context\.\%(Context\)\>/ | |
syn match goExtraType /\<io\.\%(Reader\|ReadSeeker\|ReadWriter\|ReadCloser\|ReadWriteCloser\|Writer\|WriteCloser\|Seeker\)\>/ | |
syn match goExtraType /\<reflect\.\%(Kind\|Type\|Value\)\>/ | |
syn match goExtraType /\<unsafe\.Pointer\>/ | |
1 0.000000 endif | |
" Space-tab error | |
1 0.000017 0.000015 if go#config#HighlightSpaceTabError() | |
syn match goSpaceError display " \+\t"me=e-1 | |
1 0.000000 endif | |
" Trailing white space error | |
1 0.000005 0.000004 if go#config#HighlightTrailingWhitespaceError() | |
syn match goSpaceError display excludenl "\s\+$" | |
1 0.000000 endif | |
1 0.000006 hi def link goExtraType Type | |
1 0.000006 hi def link goSpaceError Error | |
" included from: https://github.com/athom/more-colorful.vim/blob/master/after/syntax/go.vim | |
" | |
" Comments; their contents | |
1 0.000001 syn keyword goTodo contained NOTE | |
1 0.000003 hi def link goTodo Todo | |
1 0.000005 syn match goVarArgs /\.\.\./ | |
" Operators; | |
1 0.000004 0.000003 if go#config#HighlightOperators() | |
" match single-char operators: - + % < > ! & | ^ * = | |
" and corresponding two-char operators: -= += %= <= >= != &= |= ^= *= == | |
syn match goOperator /[-+%<>!&|^*=]=\?/ | |
" match / and /= | |
syn match goOperator /\/\%(=\|\ze[^/*]\)/ | |
" match two-char operators: << >> &^ | |
" and corresponding three-char operators: <<= >>= &^= | |
syn match goOperator /\%(<<\|>>\|&^\)=\?/ | |
" match remaining two-char operators: := && || <- ++ -- | |
syn match goOperator /:=\|||\|<-\|++\|--/ | |
" match ... | |
hi def link goPointerOperator goOperator | |
hi def link goVarArgs goOperator | |
1 0.000000 endif | |
1 0.000006 hi def link goOperator Operator | |
" Functions; | |
1 0.000010 0.000007 if go#config#HighlightFunctions() || go#config#HighlightFunctionParameters() | |
syn match goDeclaration /\<func\>/ nextgroup=goReceiver,goFunction,goSimpleParams skipwhite skipnl | |
syn match goReceiverDecl /(\s*\zs\%(\%(\w\+\s\+\)\?\*\?\w\+\)\ze\s*)/ contained contains=goReceiverVar,goReceiverType,goPointerOperator | |
syn match goReceiverVar /\w\+\ze\s\+\%(\w\|\*\)/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained | |
syn match goPointerOperator /\*/ nextgroup=goReceiverType contained skipwhite skipnl | |
syn match goFunction /\w\+/ nextgroup=goSimpleParams contained skipwhite skipnl | |
syn match goReceiverType /\w\+\ze\s*)/ contained | |
if go#config#HighlightFunctionParameters() | |
syn match goSimpleParams /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType nextgroup=goFunctionReturn skipwhite skipnl | |
syn match goFunctionReturn /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType skipwhite skipnl | |
syn match goParamName /\w\+\%(\s*,\s*\w\+\)*\ze\s\+\%(\w\|\.\|\*\|\[\)/ contained nextgroup=goParamType skipwhite skipnl | |
syn match goParamType /\%([^,)]\|\_s\)\+,\?/ contained nextgroup=goParamName skipwhite skipnl | |
\ contains=goVarArgs,goType,goSignedInts,goUnsignedInts,goFloats,goComplexes,goDeclType,goBlock | |
hi def link goReceiverVar goParamName | |
hi def link goParamName Identifier | |
endif | |
syn match goReceiver /(\s*\%(\w\+\s\+\)\?\*\?\s*\w\+\s*)\ze\s*\w/ contained nextgroup=goFunction contains=goReceiverDecl skipwhite skipnl | |
1 0.000000 else | |
1 0.000002 syn keyword goDeclaration func | |
1 0.000000 endif | |
1 0.000003 hi def link goFunction Function | |
" Function calls; | |
1 0.000005 0.000003 if go#config#HighlightFunctionCalls() | |
syn match goFunctionCall /\w\+\ze(/ contains=goBuiltins,goDeclaration | |
1 0.000000 endif | |
1 0.000006 hi def link goFunctionCall Type | |
" Fields; | |
1 0.000004 0.000003 if go#config#HighlightFields() | |
" 1. Match a sequence of word characters coming after a '.' | |
" 2. Require the following but dont match it: ( \@= see :h E59) | |
" - The symbols: / - + * % OR | |
" - The symbols: [] {} <> ) OR | |
" - The symbols: \n \r space OR | |
" - The symbols: , : . | |
" 3. Have the start of highlight (hs) be the start of matched | |
" pattern (s) offsetted one to the right (+1) (see :h E401) | |
syn match goField /\.\w\+\ | |
\%(\%([\/\-\+*%]\)\|\ | |
\%([\[\]{}<\>\)]\)\|\ | |
\%([\!=\^|&]\)\|\ | |
\%([\n\r\ ]\)\|\ | |
\%([,\:.]\)\)\@=/hs=s+1 | |
1 0.000000 endif | |
1 0.000006 hi def link goField Identifier | |
" Structs & Interfaces; | |
1 0.000004 0.000003 if go#config#HighlightTypes() | |
syn match goTypeConstructor /\<\w\+{\@=/ | |
syn match goTypeDecl /\<type\>/ nextgroup=goTypeName skipwhite skipnl | |
syn match goTypeName /\w\+/ contained nextgroup=goDeclType skipwhite skipnl | |
syn match goDeclType /\<\%(interface\|struct\)\>/ skipwhite skipnl | |
hi def link goReceiverType Type | |
1 0.000000 else | |
1 0.000003 syn keyword goDeclType struct interface | |
1 0.000002 syn keyword goDeclaration type | |
1 0.000000 endif | |
1 0.000006 hi def link goTypeConstructor Type | |
1 0.000003 hi def link goTypeName Type | |
1 0.000006 hi def link goTypeDecl Keyword | |
1 0.000005 hi def link goDeclType Keyword | |
" Variable Assignments | |
1 0.000005 0.000004 if go#config#HighlightVariableAssignments() | |
syn match goVarAssign /\v[_.[:alnum:]]+(,\s*[_.[:alnum:]]+)*\ze(\s*([-^+|^\/%&]|\*|\<\<|\>\>|\&\^)?\=[^=])/ | |
hi def link goVarAssign Special | |
1 0.000000 endif | |
" Variable Declarations | |
1 0.000005 0.000004 if go#config#HighlightVariableDeclarations() | |
syn match goVarDefs /\v\w+(,\s*\w+)*\ze(\s*:\=)/ | |
hi def link goVarDefs Special | |
1 0.000000 endif | |
" Build Constraints | |
1 0.000005 0.000003 if go#config#HighlightBuildConstraints() | |
syn match goBuildKeyword display contained "+build\|go:build" | |
" Highlight the known values of GOOS, GOARCH, and other +build options. | |
syn keyword goBuildDirectives contained | |
\ android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 | |
\ solaris windows 386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 | |
\ ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc | |
\ s390 s390x sparc sparc64 cgo ignore race | |
" Other words in the build directive are build tags not listed above, so | |
" avoid highlighting them as comments by using a matchgroup just for the | |
" start of the comment. | |
" The rs=s+2 option lets the \s*+build portion be part of the inner region | |
" instead of the matchgroup so it will be highlighted as a goBuildKeyword. | |
syn region goBuildComment matchgroup=goBuildCommentStart | |
\ start="//\(\s*+build\s\|go:build\)"rs=s+2 end="$" | |
\ contains=goBuildKeyword,goBuildDirectives | |
hi def link goBuildCommentStart Comment | |
hi def link goBuildDirectives Type | |
hi def link goBuildKeyword PreProc | |
1 0.000000 endif | |
1 0.000013 0.000006 if go#config#HighlightBuildConstraints() || go#config#FoldEnable('package_comment') | |
" One or more line comments that are followed immediately by a "package" | |
" declaration are treated like package documentation, so these must be | |
" matched as comments to avoid looking like working build constraints. | |
" The he, me, and re options let the "package" itself be highlighted by | |
" the usual rules. | |
1 0.000018 0.000013 exe 'syn region goPackageComment start=/\v(\/\/.*\n)+\s*package/' | |
\ . ' end=/\v\n\s*package/he=e-7,me=e-7,re=e-7' | |
\ . ' contains=@goCommentGroup,@Spell' | |
\ . (go#config#FoldEnable('package_comment') ? ' fold' : '') | |
1 0.000015 0.000010 exe 'syn region goPackageComment start=/\v^\s*\/\*.*\n(.*\n)*\s*\*\/\npackage/' | |
\ . ' end=/\v\*\/\n\s*package/he=e-7,me=e-7,re=e-7' | |
\ . ' contains=@goCommentGroup,@Spell' | |
\ . (go#config#FoldEnable('package_comment') ? ' fold' : '') | |
1 0.000003 hi def link goPackageComment Comment | |
1 0.000000 endif | |
" :GoCoverage commands | |
1 0.000006 hi def link goCoverageNormalText Comment | |
1 0.000001 function! s:hi() | |
hi def link goSameId Search | |
hi def link goDiagnosticError SpellBad | |
hi def link goDiagnosticWarning SpellRare | |
" TODO(bc): is it appropriate to define text properties in a syntax file? | |
" The highlight groups need to be defined before the text properties types | |
" are added, and when users have syntax enabled in their vimrc after | |
" filetype plugin on, the highlight groups won't be defined when | |
" ftplugin/go.vim is executed when the first go file is opened. | |
" See https://github.com/fatih/vim-go/issues/2658. | |
if has('textprop') | |
if empty(prop_type_get('goSameId')) | |
call prop_type_add('goSameId', {'highlight': 'goSameId'}) | |
endif | |
if empty(prop_type_get('goDiagnosticError')) | |
call prop_type_add('goDiagnosticError', {'highlight': 'goDiagnosticError'}) | |
endif | |
if empty(prop_type_get('goDiagnosticWarning')) | |
call prop_type_add('goDiagnosticWarning', {'highlight': 'goDiagnosticWarning'}) | |
endif | |
endif | |
hi def link goDeclsFzfKeyword Keyword | |
hi def link goDeclsFzfFunction Function | |
hi def link goDeclsFzfSpecialComment SpecialComment | |
hi def link goDeclsFzfComment Comment | |
" :GoCoverage commands | |
hi def goCoverageCovered ctermfg=green guifg=#A6E22E | |
hi def goCoverageUncover ctermfg=red guifg=#F92672 | |
" :GoDebug commands | |
if go#config#HighlightDebug() | |
hi def GoDebugBreakpoint term=standout ctermbg=117 ctermfg=0 guibg=#BAD4F5 guifg=Black | |
hi def GoDebugCurrent term=reverse ctermbg=12 ctermfg=7 guibg=DarkBlue guifg=White | |
endif | |
endfunction | |
1 0.000002 augroup vim-go-hi | |
1 0.000032 autocmd! | |
1 0.000002 autocmd ColorScheme * call s:hi() | |
1 0.000000 augroup end | |
1 0.000101 0.000002 call s:hi() | |
" Search backwards for a global declaration to start processing the syntax. | |
"syn sync match goSync grouphere NONE /^\(const\|var\|type\|func\)\>/ | |
" There's a bug in the implementation of grouphere. For now, use the | |
" following as a more expensive/less precise workaround. | |
1 0.000001 syn sync minlines=500 | |
1 0.000001 let b:current_syntax = "go" | |
" vim: sw=2 ts=2 et | |
SCRIPT /opt/homebrew/Cellar/neovim/0.5.1_1/share/nvim/runtime/syntax/go.vim | |
Sourced 1 time | |
Total time: 0.000270 | |
Self time: 0.000270 | |
count total (s) self (s) | |
" Vim syntax file | |
" Language: Go | |
" Maintainer: David Barnett (https://github.com/google/vim-ft-go) | |
" Last Change: 2014 Aug 16 | |
" Options: | |
" There are some options for customizing the highlighting; the recommended | |
" settings are the default values, but you can write: | |
" let OPTION_NAME = 0 | |
" in your ~/.vimrc file to disable particular options. You can also write: | |
" let OPTION_NAME = 1 | |
" to enable particular options. At present, all options default to on. | |
" | |
" - g:go_highlight_array_whitespace_error | |
" Highlights white space after "[]". | |
" - g:go_highlight_chan_whitespace_error | |
" Highlights white space around the communications operator that don't | |
" follow the standard style. | |
" - g:go_highlight_extra_types | |
" Highlights commonly used library types (io.Reader, etc.). | |
" - g:go_highlight_space_tab_error | |
" Highlights instances of tabs following spaces. | |
" - g:go_highlight_trailing_whitespace_error | |
" Highlights trailing white space. | |
" Quit when a (custom) syntax file was already loaded | |
1 0.000002 if exists('b:current_syntax') | |
1 0.000001 finish | |
endif | |
if !exists('g:go_highlight_array_whitespace_error') | |
let g:go_highlight_array_whitespace_error = 1 | |
endif | |
if !exists('g:go_highlight_chan_whitespace_error') | |
let g:go_highlight_chan_whitespace_error = 1 | |
endif | |
if !exists('g:go_highlight_extra_types') | |
let g:go_highlight_extra_types = 1 | |
endif | |
if !exists('g:go_highlight_space_tab_error') | |
let g:go_highlight_space_tab_error = 1 | |
endif | |
if !exists('g:go_highlight_trailing_whitespace_error') | |
let g:go_highlight_trailing_whitespace_error = 1 | |
endif | |
syn case match | |
syn keyword goDirective package import | |
syn keyword goDeclaration var const type | |
syn keyword goDeclType struct interface | |
hi def link goDirective Statement | |
hi def link goDeclaration Keyword | |
hi def link goDeclType Keyword | |
" Keywords within functions | |
syn keyword goStatement defer go goto return break continue fallthrough | |
syn keyword goConditional if else switch select | |
syn keyword goLabel case default | |
syn keyword goRepeat for range | |
hi def link goStatement Statement | |
hi def link goConditional Conditional | |
hi def link goLabel Label | |
hi def link goRepeat Repeat | |
" Predefined types | |
syn keyword goType chan map bool string error | |
syn keyword goSignedInts int int8 int16 int32 int64 rune | |
syn keyword goUnsignedInts byte uint uint8 uint16 uint32 uint64 uintptr | |
syn keyword goFloats float32 float64 | |
syn keyword goComplexes complex64 complex128 | |
hi def link goType Type | |
hi def link goSignedInts Type | |
hi def link goUnsignedInts Type | |
hi def link goFloats Type | |
hi def link goComplexes Type | |
" Treat func specially: it's a declaration at the start of a line, but a type | |
" elsewhere. Order matters here. | |
syn match goType /\<func\>/ | |
syn match goDeclaration /^func\>/ | |
" Predefined functions and values | |
syn keyword goBuiltins append cap close complex copy delete imag len | |
syn keyword goBuiltins make new panic print println real recover | |
syn keyword goConstants iota true false nil | |
hi def link goBuiltins Keyword | |
hi def link goConstants Keyword | |
" Comments; their contents | |
syn keyword goTodo contained TODO FIXME XXX BUG | |
syn cluster goCommentGroup contains=goTodo | |
syn region goComment start="/\*" end="\*/" contains=@goCommentGroup,@Spell | |
syn region goComment start="//" end="$" contains=@goCommentGroup,@Spell | |
hi def link goComment Comment | |
hi def link goTodo Todo | |
" Go escapes | |
syn match goEscapeOctal display contained "\\[0-7]\{3}" | |
syn match goEscapeC display contained +\\[abfnrtv\\'"]+ | |
syn match goEscapeX display contained "\\x\x\{2}" | |
syn match goEscapeU display contained "\\u\x\{4}" | |
syn match goEscapeBigU display contained "\\U\x\{8}" | |
syn match goEscapeError display contained +\\[^0-7xuUabfnrtv\\'"]+ | |
hi def link goEscapeOctal goSpecialString | |
hi def link goEscapeC goSpecialString | |
hi def link goEscapeX goSpecialString | |
hi def link goEscapeU goSpecialString | |
hi def link goEscapeBigU goSpecialString | |
hi def link goSpecialString Special | |
hi def link goEscapeError Error | |
" Strings and their contents | |
syn cluster goStringGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU,goEscapeError | |
syn region goString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@goStringGroup | |
syn region goRawString start=+`+ end=+`+ | |
hi def link goString String | |
hi def link goRawString String | |
" Characters; their contents | |
syn cluster goCharacterGroup contains=goEscapeOctal,goEscapeC,goEscapeX,goEscapeU,goEscapeBigU | |
syn region goCharacter start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=@goCharacterGroup | |
hi def link goCharacter Character | |
" Regions | |
syn region goBlock start="{" end="}" transparent fold | |
syn region goParen start='(' end=')' transparent | |
" Integers | |
syn match goDecimalInt "\<\d\+\([Ee]\d\+\)\?\>" | |
syn match goHexadecimalInt "\<0x\x\+\>" | |
syn match goOctalInt "\<0\o\+\>" | |
syn match goOctalError "\<0\o*[89]\d*\>" | |
hi def link goDecimalInt Integer | |
hi def link goHexadecimalInt Integer | |
hi def link goOctalInt Integer | |
hi def link Integer Number | |
" Floating point | |
syn match goFloat "\<\d\+\.\d*\([Ee][-+]\d\+\)\?\>" | |
syn match goFloat "\<\.\d\+\([Ee][-+]\d\+\)\?\>" | |
syn match goFloat "\<\d\+[Ee][-+]\d\+\>" | |
hi def link goFloat Float | |
" Imaginary literals | |
syn match goImaginary "\<\d\+i\>" | |
syn match goImaginary "\<\d\+\.\d*\([Ee][-+]\d\+\)\?i\>" | |
syn match goImaginary "\<\.\d\+\([Ee][-+]\d\+\)\?i\>" | |
syn match goImaginary "\<\d\+[Ee][-+]\d\+i\>" | |
hi def link goImaginary Number | |
" Spaces after "[]" | |
if go_highlight_array_whitespace_error != 0 | |
syn match goSpaceError display "\(\[\]\)\@<=\s\+" | |
endif | |
" Spacing errors around the 'chan' keyword | |
if go_highlight_chan_whitespace_error != 0 | |
" receive-only annotation on chan type | |
syn match goSpaceError display "\(<-\)\@<=\s\+\(chan\>\)\@=" | |
" send-only annotation on chan type | |
syn match goSpaceError display "\(\<chan\)\@<=\s\+\(<-\)\@=" | |
" value-ignoring receives in a few contexts | |
syn match goSpaceError display "\(\(^\|[={(,;]\)\s*<-\)\@<=\s\+" | |
endif | |
" Extra types commonly seen | |
if go_highlight_extra_types != 0 | |
syn match goExtraType /\<bytes\.\(Buffer\)\>/ | |
syn match goExtraType /\<io\.\(Reader\|Writer\|ReadWriter\|ReadWriteCloser\)\>/ | |
syn match goExtraType /\<reflect\.\(Kind\|Type\|Value\)\>/ | |
syn match goExtraType /\<unsafe\.Pointer\>/ | |
endif | |
" Space-tab error | |
if go_highlight_space_tab_error != 0 | |
syn match goSpaceError display " \+\t"me=e-1 | |
endif | |
" Trailing white space error | |
if go_highlight_trailing_whitespace_error != 0 | |
syn match goSpaceError display excludenl "\s\+$" | |
endif | |
hi def link goExtraType Type | |
hi def link goSpaceError Error | |
" Search backwards for a global declaration to start processing the syntax. | |
"syn sync match goSync grouphere NONE /^\(const\|var\|type\|func\)\>/ | |
" There's a bug in the implementation of grouphere. For now, use the | |
" following as a more expensive/less precise workaround. | |
syn sync minlines=500 | |
let b:current_syntax = 'go' | |
" vim: sw=2 sts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim | |
Sourced 1 time | |
Total time: 0.000890 | |
Self time: 0.000890 | |
count total (s) self (s) | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000003 let s:cpo_save = &cpo | |
1 0.000003 set cpo&vim | |
1 0.000001 scriptencoding utf-8 | |
1 0.000001 let s:lspfactory = {} | |
1 0.000001 function! s:lspfactory.get() dict abort | |
if empty(get(self, 'current', {})) || empty(get(self.current, 'job', {})) | |
let self.current = s:newlsp() | |
endif | |
return self.current | |
endfunction | |
1 0.000001 function! s:lspfactory.reset() dict abort | |
if has_key(self, 'current') | |
call remove(self, 'current') | |
endif | |
endfunction | |
1 0.000001 function! s:newlsp() abort | |
" job is the job used to talk to the backing instance of gopls. | |
" ready is 0 until the initialize response has been received. 1 afterwards. | |
" queue is messages to send after initialization | |
" last_request_id is id of the most recently sent request. | |
" buf is unprocessed/incomplete responses | |
" handlers is a mapping of request ids to dictionaries of functions. | |
" request id -> {start, requestComplete, handleResult, error} | |
" * start is a function that takes no arguments | |
" * requestComplete is a function that takes 1 argument. The parameter will be 1 | |
" if the call was succesful. | |
" * handleResult takes a single argument, the result message received from gopls | |
" * error takes a single argument, the error message received from gopls. | |
" The error method is optional. | |
" workspaceDirectories is an array of named workspaces. | |
" wd is the working directory for gopls | |
" diagnostics is a dictionary whose keys are filenames and each value is a | |
" list of diagnostic messages for the file. | |
" diagnosticsQueue is a queue of diagnostics notifications that have been | |
" received, but not yet processed. | |
" fileVersions is a dictionary of filenames to versions. | |
" notificationQueue is a dictionary of filenames to functions. For a given | |
" filename, each notification will call the first function in the list of | |
" function values and remove it from the list. The functions should accept | |
" two arguments: an absolute path and a list of diagnotics messages for | |
" the file. | |
let l:lsp = { | |
\ 'job': '', | |
\ 'ready': 0, | |
\ 'queue': [], | |
\ 'last_request_id': 0, | |
\ 'buf': '', | |
\ 'handlers': {}, | |
\ 'workspaceDirectories': [], | |
\ 'wd' : '', | |
\ 'diagnosticsQueue': [], | |
\ 'diagnostics': {}, | |
\ 'fileVersions': {}, | |
\ 'notificationQueue': {}, | |
\ } | |
if !go#config#GoplsEnabled() | |
let l:lsp.sendMessage = funcref('s:noop') | |
return l:lsp | |
endif | |
if !go#util#has_job() | |
let l:oldshortmess=&shortmess | |
if has('nvim') | |
set shortmess-=F | |
endif | |
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 l:lsp | |
endif | |
function! l:lsp.readMessage(data) dict abort | |
let l:responses = [] | |
let l:rest = a:data | |
while 1 | |
" Look for the end of the HTTP headers | |
let l:body_start_idx = matchend(l:rest, "\r\n\r\n") | |
if l:body_start_idx < 0 | |
" incomplete header | |
break | |
endif | |
" Parse the Content-Length header. | |
let l:header = l:rest[:l:body_start_idx - 4] | |
let l:length_match = matchlist( | |
\ l:header, | |
\ '\vContent-Length: *(\d+)' | |
\) | |
if empty(l:length_match) | |
" TODO(bc): shutdown gopls? | |
throw "invalid JSON-RPC header:\n" . l:header | |
endif | |
" get the start of the rest | |
let l:next_start_idx = l:body_start_idx + str2nr(l:length_match[1]) | |
if len(l:rest) < l:next_start_idx | |
" incomplete response body | |
break | |
endif | |
call s:debug('received', l:rest[:l:next_start_idx - 1]) | |
let l:body = l:rest[l:body_start_idx : l:next_start_idx - 1] | |
let l:rest = l:rest[l:next_start_idx :] | |
try | |
" add the json body to the list. | |
call add(l:responses, json_decode(l:body)) | |
catch | |
" TODO(bc): log the message and/or show an error message. | |
finally | |
" intentionally left blank. | |
endtry | |
endwhile | |
return [l:rest, l:responses] | |
endfunction | |
function! l:lsp.handleMessage(ch, data) dict abort | |
let self.buf .= a:data | |
let [self.buf, l:messages] = self.readMessage(self.buf) | |
for l:message in l:messages | |
if has_key(l:message, 'method') | |
if has_key(l:message, 'id') | |
call self.handleRequest(l:message) | |
else | |
call self.handleNotification(l:message) | |
endif | |
elseif has_key(l:message, 'result') || has_key(l:message, 'error') | |
call self.handleResponse(l:message) | |
endif | |
endfor | |
endfunction | |
function! l:lsp.handleRequest(req) dict abort | |
if a:req.method == 'workspace/workspaceFolders' | |
let l:resp = go#lsp#message#WorkspaceFoldersResult(self.workspaceDirectories) | |
elseif a:req.method == 'workspace/configuration' && has_key(a:req, 'params') && has_key(a:req.params, 'items') | |
let l:resp = go#lsp#message#ConfigurationResult(a:req.params.items) | |
elseif a:req.method == 'client/registerCapability' && has_key(a:req, 'params') && has_key(a:req.params, 'registrations') | |
let l:resp = v:null | |
elseif a:req.method == 'workspace/applyEdit' | |
try | |
let l:ok = v:true | |
for l:change in a:req.params.edit.documentChanges | |
call s:applyDocumentChanges(a:req.params.edit.documentChanges) | |
endfor | |
catch | |
call go#util#EchoError(printf('could not apply edit: %s', v:exception)) | |
let l:ok = v:false | |
endtry | |
let l:resp = go#lsp#message#ApplyWorkspaceEditResponse(l:ok) | |
else | |
return | |
endif | |
if get(self, 'exited', 0) | |
return | |
endif | |
let l:msg = self.newResponse(a:req.id, l:resp) | |
call self.write(l:msg) | |
endfunction | |
function! l:lsp.handleResponse(resp) dict abort | |
if has_key(a:resp, 'id') && has_key(self.handlers, a:resp.id) | |
try | |
let l:handler = self.handlers[a:resp.id] | |
let l:winid = win_getid(winnr()) | |
" Always set the active window to the window that was active when | |
" the request was sent. Among other things, this makes sure that | |
" the correct window's location list will be populated when the | |
" list type is 'location' and the user has moved windows since | |
" sending the request. | |
call win_gotoid(l:handler.winid) | |
if has_key(a:resp, 'error') | |
call l:handler.requestComplete(0) | |
if has_key(l:handler, 'error') | |
call call(l:handler.error, [a:resp.error.message]) | |
else | |
call go#util#EchoError(a:resp.error.message) | |
endif | |
call win_gotoid(l:winid) | |
return | |
endif | |
call l:handler.requestComplete(1) | |
let l:winidBeforeHandler = l:handler.winid | |
call call(l:handler.handleResult, [a:resp.result]) | |
" change the window back to the window that was active when | |
" starting to handle the message _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, a:resp.id) | |
endtry | |
endif | |
endfunction | |
function! l:lsp.handleNotification(req) dict abort | |
" TODO(bc): handle more notifications (e.g. window/showMessage). | |
if a:req.method == 'textDocument/publishDiagnostics' | |
call self.handleDiagnostics(a:req.params) | |
elseif a:req.method == 'window/showMessage' | |
call self.showMessage(a:req.params) | |
endif | |
endfunction | |
function! l:lsp.handleDiagnostics(data) dict abort | |
let self.diagnosticsQueue = add(self.diagnosticsQueue, a:data) | |
call self.updateDiagnostics() | |
endfunction | |
function! l:lsp.showMessage(data) dict abort | |
let l:msg = a:data.message | |
if a:data.type == 1 | |
call go#util#EchoError(l:msg) | |
elseif a:data.type == 2 | |
call go#util#EchoWarning(l:msg) | |
elseif a:data.type == 3 | |
call go#util#EchoInfo(l:msg) | |
elseif a:data.type == 4 | |
" do nothing for Log messages | |
endif | |
endfunction | |
" TODO(bc): process the queue asynchronously | |
function! l:lsp.updateDiagnostics() dict abort | |
let l:level = go#config#DiagnosticsLevel() | |
for l:data in self.diagnosticsQueue | |
call remove(self.diagnosticsQueue, 0) | |
try | |
let l:diagnostics = [] | |
let l:errorMatches = [] | |
let l:warningMatches = [] | |
let l:fname = go#path#FromURI(l:data.uri) | |
" get the buffer name relative to the current directory, because | |
" Vim says that a buffer name can't be an absolute path. | |
let l:bufname = fnamemodify(l:fname, ':.') | |
if len(l:data.diagnostics) > 0 && (l:level > 0 || bufnr(l:bufname) == bufnr('')) | |
" make sure the buffer is listed and loaded before calling getbufline() on it | |
if !bufexists(l:bufname) | |
call bufadd(l:bufname) | |
endif | |
if !bufloaded(l:bufname) | |
call bufload(l:bufname) | |
endif | |
for l:diag in l:data.diagnostics | |
if l:level < l:diag.severity | |
continue | |
endif | |
let [l:error, l:matchpos] = s:errorFromDiagnostic(l:diag, l:bufname, l:fname) | |
let l:diagnostics = add(l:diagnostics, l:error) | |
if empty(l:matchpos) | |
continue | |
endif | |
if l:diag.severity == 1 | |
let l:errorMatches = add(l:errorMatches, l:matchpos) | |
elseif l:diag.severity == 2 | |
let l:warningMatches = add(l:warningMatches, l:matchpos) | |
endif | |
endfor | |
endif | |
if bufnr(l:bufname) == bufnr('') | |
" only apply highlighting when the diagnostics are for the current | |
" version. | |
let l:lsp = s:lspfactory.get() | |
let l:version = get(l:lsp.fileVersions, l:fname, 0) | |
" it's tempting to only highlight matches when they are for the | |
" current version of the buffer, but that causes problems when the | |
" version number has been updated and the content has not. In such a | |
" case, the diagnostics may not be sent for later versions. | |
call s:highlightMatches(l:errorMatches, l:warningMatches) | |
endif | |
let self.diagnostics[l:fname] = l:diagnostics | |
if has_key(self.notificationQueue, l:fname) && len(self.notificationQueue[l:fname]) > 0 | |
call call(self.notificationQueue[l:fname][0], copy(l:diagnostics)) | |
call remove(self.notificationQueue[l:fname], 0) | |
endif | |
catch | |
"call go#util#EchoError(printf('%s: %s', v:throwpoint, v:exception)) | |
endtry | |
endfor | |
endfunction | |
function! l:lsp.handleInitializeResult(result) dict abort | |
if go#config#EchoCommandInfo() | |
call go#util#EchoProgress("initialized gopls") | |
endif | |
let status = { | |
\ 'desc': '', | |
\ 'type': 'gopls', | |
\ 'state': 'initialized', | |
\ } | |
call go#statusline#Update(self.wd, status) | |
let self.ready = 1 | |
let l:msg = self.newMessage(go#lsp#message#Initialized()) | |
call self.write(l:msg) | |
" send messages queued while waiting for ready. | |
for l:item in self.queue | |
call self.sendMessage(l:item.data, l:item.handler) | |
endfor | |
" reset the queue | |
let self.queue = [] | |
endfunction | |
function! l:lsp.sendMessage(data, handler) dict abort | |
if !self.last_request_id | |
let l:wd = go#util#ModuleRoot() | |
if l:wd == -1 | |
call go#util#EchoError('could not determine appropriate working directory for gopls') | |
return -1 | |
endif | |
if l:wd == '' | |
let l:wd = getcwd() | |
endif | |
let self.wd = l:wd | |
if go#config#EchoCommandInfo() | |
call go#util#EchoProgress("initializing gopls") | |
endif | |
let l:status = { | |
\ 'desc': '', | |
\ 'type': 'gopls', | |
\ 'state': 'initializing', | |
\ } | |
call go#statusline#Update(l:wd, l:status) | |
let self.workspaceDirectories = add(self.workspaceDirectories, l:wd) | |
let l:msg = self.newMessage(go#lsp#message#Initialize(l:wd)) | |
let l:state = s:newHandlerState('') | |
let l:state.handleResult = funcref('self.handleInitializeResult', [], l:self) | |
let self.handlers[l:msg.id] = l:state | |
call l:state.start() | |
call self.write(l:msg) | |
endif | |
if !self.ready | |
call add(self.queue, {'data': a:data, 'handler': a:handler}) | |
return | |
endif | |
let l:msg = self.newMessage(a:data) | |
if has_key(l:msg, 'id') | |
let self.handlers[l:msg.id] = a:handler | |
endif | |
call a:handler.start() | |
call self.write(l:msg) | |
endfunction | |
" newMessage returns a message constructed from data. data should be a dict | |
" with 2 or 3 keys: notification, method, and optionally params. | |
function! l:lsp.newMessage(data) dict abort | |
let l:msg = { | |
\ 'method': a:data.method, | |
\ 'jsonrpc': '2.0', | |
\ } | |
if !a:data.notification | |
let self.last_request_id += 1 | |
let l:msg.id = self.last_request_id | |
endif | |
if has_key(a:data, 'params') | |
let l:msg.params = a:data.params | |
endif | |
return l:msg | |
endfunction | |
function l:lsp.newResponse(id, result) dict abort | |
let l:msg = { | |
\ 'jsonrpc': '2.0', | |
\ 'id': a:id, | |
\ 'result': a:result, | |
\ } | |
return l:msg | |
endfunction | |
function! l:lsp.write(msg) dict abort | |
if empty(get(self, 'job', {})) | |
return | |
endif | |
let l:body = json_encode(a:msg) | |
let l:data = 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body | |
call s:debug('sent', l:data) | |
if has('nvim') | |
call chansend(self.job, l:data) | |
return | |
endif | |
try | |
call ch_sendraw(self.job, l:data) | |
catch | |
call go#util#EchoError(printf('could not send message: %s', v:exception)) | |
endtry | |
endfunction | |
function! l:lsp.exit_cb(job, exit_status) dict | |
let self.exited = 1 | |
if !get(self, 'restarting', 0) | |
return | |
endif | |
let l:queue = self.queue | |
let l:workspaces = self.workspaceDirectories | |
call s:lspfactory.reset() | |
let l:lsp = s:lspfactory.get() | |
" restore workspaces | |
call call('go#lsp#AddWorkspaceDirectory', l:workspaces) | |
" * send DidOpen messages for all buffers that have b:did_lsp_open set | |
" TODO(bc): check modifiable and filetype, too? | |
bufdo if get(b:, 'go_lsp_did_open', 0) | if &modified | call go#lsp#DidOpen(expand('%:p')) | else | call go#lsp#DidChange(expand('%:p')) | endif | endif | |
let l:lsp.queue = extend(l:lsp.queue, l:queue) | |
return | |
endfunction | |
function! l:lsp.close_cb(ch) dict abort | |
" TODO(bc): remove the buffer variables that indicate that gopls has been | |
" informed that the file is open | |
endfunction | |
function! l:lsp.err_cb(ch, msg) dict abort | |
if a:msg =~ '^\d\{4}/\d\d/\d\d\ \d\d:\d\d:\d\d debug server listening on port \d\+$' && !get(self, 'debugport', 0) | |
let self.debugport = substitute(a:msg, '\d\{4}/\d\d/\d\d\ \d\d:\d\d:\d\d debug server listening on port \(\d\+\).*$', '\1', '') | |
endif | |
call s:debug('stderr', a:msg) | |
endfunction | |
" explicitly bind callbacks to l:lsp so that within it, self will always refer | |
" to l:lsp instead of l:opts. See :help Partial for more information. | |
let l:opts = { | |
\ 'in_mode': 'raw', | |
\ 'out_mode': 'raw', | |
\ 'err_mode': 'nl', | |
\ 'noblock': 1, | |
\ 'err_cb': funcref('l:lsp.err_cb', [], l:lsp), | |
\ 'out_cb': funcref('l:lsp.handleMessage', [], l:lsp), | |
\ 'close_cb': funcref('l:lsp.close_cb', [], l:lsp), | |
\ 'exit_cb': funcref('l:lsp.exit_cb', [], l:lsp), | |
\ 'cwd': getcwd(), | |
\} | |
let l:bin_path = go#path#CheckBinPath("gopls") | |
if empty(l:bin_path) | |
let l:lsp.sendMessage = funcref('s:noop') | |
return l:lsp | |
endif | |
let l:cmd = [l:bin_path] | |
let l:cmdopts = go#config#GoplsOptions() | |
if go#util#HasDebug('lsp') | |
" debugging can be enabled either with g:go_debug or with | |
" g:go_gopls_options; use g:go_gopls_options if it's given in case users | |
" are running the gopls debug server on a known port. | |
let l:needsDebug = 1 | |
for l:item in l:cmdopts | |
let l:idx = stridx(l:item, '-debug') | |
if l:idx == 0 || l:idx == 1 | |
let l:needsDebug = 0 | |
endif | |
endfor | |
if l:needsDebug | |
let l:cmd = extend(l:cmd, ['-debug', 'localhost:0']) | |
endif | |
endif | |
let l:lsp.job = go#job#Start(l:cmd+l:cmdopts, l:opts) | |
return l:lsp | |
endfunction | |
1 0.000001 function! s:noop(...) abort | |
endfunction | |
1 0.000003 function! s:newHandlerState(statustype) abort | |
let l:state = { | |
\ 'winid': win_getid(winnr()), | |
\ 'statustype': a:statustype, | |
\ 'jobdir': getcwd(), | |
\ 'handleResult': funcref('s:noop'), | |
\ } | |
" explicitly bind requestComplete to state so that within it, self will | |
" always refer to state. See :help Partial for more information. | |
let l:state.requestComplete = funcref('s:requestComplete', [], l:state) | |
" explicitly bind start to state so that within it, self will | |
" always refer to state. See :help Partial for more information. | |
let l:state.start = funcref('s:start', [], l:state) | |
return l:state | |
endfunction | |
1 0.000001 function! s:requestComplete(ok) abort dict | |
if self.statustype == '' | |
return | |
endif | |
if go#config#EchoCommandInfo() | |
" redraw to avoid messages piling up | |
redraw | |
let prefix = '[' . self.statustype . '] ' | |
if a:ok | |
call go#util#EchoSuccess(prefix . "SUCCESS") | |
else | |
call go#util#EchoError(prefix . "FAIL") | |
endif | |
endif | |
let status = { | |
\ 'desc': 'last status', | |
\ 'type': self.statustype, | |
\ 'state': "success", | |
\ } | |
if !a:ok | |
let status.state = "failed" | |
endif | |
if has_key(self, 'started_at') | |
let elapsed_time = reltimestr(reltime(self.started_at)) | |
" strip whitespace | |
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') | |
let status.state .= printf(" (%ss)", elapsed_time) | |
endif | |
call go#statusline#Update(self.jobdir, status) | |
endfunction | |
1 0.000001 function! s:start() abort dict | |
let self.started_at = reltime() | |
if self.statustype == '' | |
return | |
endif | |
let status = { | |
\ 'desc': 'current status', | |
\ 'type': self.statustype, | |
\ 'state': "started", | |
\ } | |
call go#statusline#Update(self.jobdir, status) | |
endfunction | |
" go#lsp#Definition calls gopls to get the definition of the identifier at | |
" line and col in fname. handler should be a dictionary function that takes a | |
" list of strings in the form 'file:line:col: message'. handler will be | |
" attached to a dictionary that manages state (statuslines, sets the winid, | |
" etc.) | |
1 0.000002 function! go#lsp#Definition(fname, line, col, handler) abort | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
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) | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:definitionHandler(next, msg) abort dict | |
if a:msg is v:null || len(a:msg) == 0 | |
return | |
endif | |
" gopls returns a []Location; just take the first one. | |
let l:msg = a:msg[0] | |
let l:args = [[printf('%s:%d:%d: %s', go#path#FromURI(l:msg.uri), l:msg.range.start.line+1, go#lsp#lsp#PositionOf(getline(l:msg.range.start.line+1), l:msg.range.start.character), 'lsp does not supply a description')]] | |
call call(a:next, l:args) | |
endfunction | |
" go#lsp#Type calls gopls to get the type definition of the identifier at | |
" line and col in fname. handler should be a dictionary function that takes a | |
" list of strings in the form 'file:line:col: message'. handler will be | |
" attached to a dictionary that manages state (statuslines, sets the winid, | |
" etc.) | |
1 0.000001 function! go#lsp#TypeDef(fname, line, col, handler) abort | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
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) | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:typeDefinitionHandler(next, msg) abort dict | |
if a:msg is v:null || len(a:msg) == 0 | |
return | |
endif | |
" gopls returns a []Location; just take the first one. | |
let l:msg = a:msg[0] | |
let l:args = [[printf('%s:%d:%d: %s', go#path#FromURI(l:msg.uri), l:msg.range.start.line+1, go#lsp#lsp#PositionOf(getline(l:msg.range.start.line+1), l:msg.range.start.character), 'lsp does not supply a description')]] | |
call call(a:next, l:args) | |
endfunction | |
" go#lsp#Callers calls gopls to get callers of the identifier at | |
" line and col in fname. handler should be a dictionary function that takes a | |
" list of strings in the form 'file:line:col: message'. handler will be | |
" attached to a dictionary that manages state (statuslines, sets the winid, | |
" etc.) | |
1 0.000001 function! go#lsp#Callers(fname, line, col, handler) abort | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('callers') | |
let l:msg = go#lsp#message#PrepareCallHierarchy(fnamemodify(a:fname, ':p'), a:line, a:col) | |
let l:state.handleResult = funcref('s:prepareCallHierarchyHandler', [function(a:handler, [], l:state)], l:state) | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:prepareCallHierarchyHandler(next, msg) abort dict | |
if a:msg is v:null || len(a:msg) == 0 | |
return | |
endif | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('callers') | |
let l:msg = go#lsp#message#IncomingCalls(a:msg[0]) | |
let l:state.handleResult = funcref('s:incomingCallsHandler', [function(a:next, [], l:state)], l:state) | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000002 function! s:incomingCallsHandler(next, msg) abort dict | |
if a:msg is v:null || len(a:msg) == 0 | |
return | |
endif | |
let l:locations = [] | |
for l:item in a:msg | |
try | |
let l:fname = go#path#FromURI(l:item.from.uri) | |
for l:fromRange in l:item.fromRanges | |
let l:line = l:fromRange.start.line+1 | |
let l:content = s:lineinfile(l:fname, l:line) | |
if l:content is -1 | |
continue | |
endif | |
let l:locations = add(l:locations, printf('%s:%s:%s: %s', l:fname, l:line, go#lsp#lsp#PositionOf(content, l:fromRange.start.character), l:item.from.name)) | |
endfor | |
catch | |
endtry | |
endfor | |
call call(a:next, [l:locations]) | |
return | |
endfunction | |
1 0.000001 function! go#lsp#DidOpen(fname) abort | |
if get(b:, 'go_lsp_did_open', 0) | |
return | |
endif | |
let l:fname = fnamemodify(a:fname, ':p') | |
if !isdirectory(fnamemodify(l:fname, ':h')) | |
return | |
endif | |
let l:lsp = s:lspfactory.get() | |
if !has_key(l:lsp.notificationQueue, l:fname) | |
let l:lsp.notificationQueue[l:fname] = [] | |
endif | |
call s:ensureWorkspace(fnamemodify(l:fname, ':h')) | |
let l:lsp.fileVersions[l:fname] = getbufvar(l:fname, 'changedtick') | |
let l:msg = go#lsp#message#DidOpen(l:fname, join(go#util#GetLines(), "\n") . "\n", l:lsp.fileVersions[l:fname]) | |
let l:state = s:newHandlerState('') | |
" 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 | |
1 0.000001 function! go#lsp#DidChange(fname) abort | |
" DidChange is called even when fname isn't open in a buffer (e.g. via | |
" go#lsp#Info); don't report the file as open or as having changed when it's | |
" not actually a buffer. | |
if bufnr(a:fname) == -1 | |
return | |
endif | |
let l:fname = fnamemodify(a:fname, ':p') | |
if !isdirectory(fnamemodify(l:fname, ':h')) | |
return | |
endif | |
call go#lsp#DidOpen(a:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:version = getbufvar(l:fname, 'changedtick') | |
if has_key(l:lsp.fileVersions, l:fname) && l:lsp.fileVersions[l:fname] == l:version | |
return | |
endif | |
let l:lsp.fileVersions[l:fname] = l:version | |
let l:msg = go#lsp#message#DidChange(l:fname, join(go#util#GetLines(), "\n") . "\n", l:lsp.fileVersions[l:fname]) | |
let l:state = s:newHandlerState('') | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! go#lsp#DidClose(fname) abort | |
let l:fname = fnamemodify(a:fname, ':p') | |
if !isdirectory(fnamemodify(l:fname, ':h')) | |
return | |
endif | |
if !get(b:, 'go_lsp_did_open', 0) | |
return | |
endif | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#DidClose(l:fname) | |
let l:state = s:newHandlerState('') | |
" 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 | |
1 0.000001 function! go#lsp#Completion(fname, line, col, handler) abort | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#Completion(a:fname, a:line, a:col) | |
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) | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:completionHandler(next, msg) abort dict | |
" gopls returns a CompletionList. | |
let l:matches = [] | |
let l:start = -1 | |
for l:item in a:msg.items | |
let l:start = l:item.textEdit.range.start.character | |
let l:match = {'abbr': l:item.label, 'word': l:item.textEdit.newText, 'info': '', 'kind': go#lsp#completionitemkind#Vim(l:item.kind), 'user_data': '', 'icase': go#config#CodeCompletionIcase()} | |
if has_key(l:item, 'detail') | |
let l:match.menu = l:item.detail | |
if go#lsp#completionitemkind#IsFunction(l:item.kind) || go#lsp#completionitemkind#IsMethod(l:item.kind) | |
let l:match.info = printf('%s %s', l:item.label, l:item.detail) | |
" The detail provided by gopls hasn't always provided the the full | |
" signature including the return value. The label used to be the | |
" function signature and the detail was the return value. Handle | |
" that case for backward compatibility. This can be removed in the | |
" future once it's likely that the majority of users are on a recent | |
" version of gopls. | |
if l:item.detail !~ '^func' | |
let l:match.info = printf('func %s %s', l:item.label, l:item.detail) | |
endif | |
endif | |
endif | |
let l:match.user_data = l:match.info | |
if has_key(l:item, 'documentation') | |
let l:match.info .= "\n\n" . l:item.documentation | |
endif | |
let l:matches = add(l:matches, l:match) | |
endfor | |
let l:args = [l:start, l:matches] | |
call call(a:next, l:args) | |
endfunction | |
1 0.000001 function! s:completionErrorHandler(next, error) abort dict | |
call call(a:next, [-1, []]) | |
endfunction | |
" go#lsp#SameIDs calls gopls to get the references to the identifier at line | |
" and col in fname. handler should be a dictionary function that takes a list | |
" of strings in the form 'file:line:col: message'. handler will be attached to | |
" a dictionary that manages state (statuslines, sets the winid, etc.). handler | |
" should take three arguments: an exit_code, a JSON object encoded to a string | |
" that mimics guru's ouput for `what`, and third mode parameter that only | |
" exists for compatibility with the guru implementation of SameIDs. | |
" TODO(bc): refactor to not need the guru adapter. | |
1 0.000001 function! go#lsp#SameIDs(showstatus, fname, line, col, handler) abort | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#References(a:fname, a:line, a:col) | |
if a:showstatus | |
let l:state = s:newHandlerState('same ids') | |
else | |
let l:state = s:newHandlerState('') | |
endif | |
let l:state.handleResult = funcref('s:sameIDsHandler', [function(a:handler, [], l:state)], l:state) | |
let l:state.error = funcref('s:noop') | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:sameIDsHandler(next, msg) abort dict | |
let l:furi = go#path#ToURI(expand('%:p')) | |
let l:result = { | |
\ 'sameids': [], | |
\ 'enclosing': [], | |
\ } | |
let l:msg = a:msg | |
if a:msg is v:null | |
let l:msg = [] | |
endif | |
for l:loc in l:msg | |
if l:loc.uri !=# l:furi | |
continue | |
endif | |
if len(l:result.enclosing) == 0 | |
let l:result.enclosing = [{ | |
\ 'desc': 'identifier', | |
\ 'start': l:loc.range.start.character+1, | |
\ 'end': l:loc.range.end.character+1, | |
\ }] | |
endif | |
let l:result.sameids = add(l:result.sameids, printf('%s:%s:%s', go#path#FromURI(l:loc.uri), l:loc.range.start.line+1, l:loc.range.start.character+1)) | |
endfor | |
call call(a:next, [0, json_encode(l:result), '']) | |
endfunction | |
" go#lsp#Referrers calls gopls to get the references to the identifier at line | |
" and col in fname. handler should be a dictionary function that takes a list | |
" of strings in the form 'file:line:col: message'. handler will be attached to | |
" a dictionary that manages state (statuslines, sets the winid, etc.). handler | |
" should take three arguments: an exit_code, a JSON object encoded to a string | |
" that mimics guru's ouput for `what`, and third mode parameter that only | |
" exists for compatibility with the guru implementation of SameIDs. | |
" TODO(bc): refactor to not need the guru adapter. | |
1 0.000001 function! go#lsp#Referrers(fname, line, col, handler) abort | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#References(a:fname, a:line, a:col) | |
let l:state = s:newHandlerState('referrers') | |
let l:state.handleResult = funcref('s:handleReferences', [function(a:handler, [], l:state)], l:state) | |
let l:state.error = funcref('s:noop') | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:handleReferences(next, msg) abort dict | |
call s:handleLocations(a:next, a:msg) | |
endfunction | |
1 0.000001 function! s:handleLocations(next, msg) abort | |
let l:result = [] | |
let l:msg = a:msg | |
if l:msg is v:null | |
let l:msg = [] | |
endif | |
call sort(l:msg, funcref('s:compareLocations')) | |
for l:loc in l:msg | |
let l:fname = go#path#FromURI(l:loc.uri) | |
let l:line = l:loc.range.start.line+1 | |
let l:content = s:lineinfile(l:fname, l:line) | |
if l:content is -1 | |
continue | |
endif | |
let l:item = printf('%s:%s:%s: %s', l:fname, l:line, go#lsp#lsp#PositionOf(l:content, l:loc.range.start.character), l:content) | |
let l:result = add(l:result, l:item) | |
endfor | |
call call(a:next, [0, l:result, '']) | |
endfunction | |
" go#lsp#Implementations calls gopls to get the implementations to the | |
" identifier at line and col in fname. handler should be a dictionary function | |
" that takes a list of strings in the form 'file:line:col: message'. handler | |
" will be attached to a dictionary that manages state (statuslines, sets the | |
" winid, etc.). handler should take three arguments: an exit_code, a JSON | |
" object encoded to a string that mimics guru's ouput for guru implements, and | |
" a third parameter that only exists for compatibility with guru implements. | |
1 0.000001 function! go#lsp#Implements(fname, line, col, handler) abort | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#Implementation(a:fname, a:line, a:col) | |
let l:state = s:newHandlerState('implements') | |
let l:state.handleResult = funcref('s:handleImplements', [function(a:handler, [], l:state)], l:state) | |
let l:state.error = funcref('s:handleImplementsError', [function(a:handler, [], l:state)], l:state) | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:handleImplements(next, msg) abort dict | |
call s:handleLocations(a:next, a:msg) | |
endfunction | |
1 0.000001 function! s:handleImplementsError(next, error) abort dict | |
call call(a:next, [1, [a:error], '']) | |
endfunction | |
1 0.000001 function! go#lsp#Hover(fname, line, col, handler) abort | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#Hover(a:fname, a:line, a:col) | |
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') | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:hoverHandler(next, msg) abort dict | |
if a:msg is v:null || !has_key(a:msg, 'contents') | |
return | |
endif | |
try | |
let l:value = json_decode(a:msg.contents.value) | |
let l:signature = split(l:value.signature, "\n") | |
let l:msg = l:signature | |
if go#config#DocBalloon() | |
" use synopsis instead of fullDocumentation to keep the hover window | |
" small. | |
let l:doc = l:value.synopsis | |
if len(l:doc) isnot 0 | |
let l:msg = l:signature + ['', l:doc] | |
endif | |
endif | |
call call(a:next, [l:msg]) | |
catch | |
" TODO(bc): log the message and/or show an error message. | |
endtry | |
endfunction | |
1 0.000001 function! go#lsp#Doc() abort | |
let l:fname = expand('%:p') | |
let [l:line, l:col] = go#lsp#lsp#Position() | |
call go#lsp#DidChange(l:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#Hover(l:fname, l:line, l:col) | |
let l:state = s:newHandlerState('doc') | |
let l:resultHandler = go#promise#New(function('s:docFromHoverResult', [], l:state), 10000, '') | |
let l:state.handleResult = l:resultHandler.wrapper | |
let l:state.error = l:resultHandler.wrapper | |
call l:lsp.sendMessage(l:msg, l:state) | |
return l:resultHandler.await() | |
endfunction | |
1 0.000001 function! s:docFromHoverResult(msg) abort dict | |
if type(a:msg) is type('') | |
return [a:msg, 1] | |
endif | |
if a:msg is v:null || !has_key(a:msg, 'contents') | |
return ['Undocumented', 0] | |
endif | |
let l:value = json_decode(a:msg.contents.value) | |
let l:doc = l:value.fullDocumentation | |
if len(l:doc) is 0 | |
let l:doc = 'Undocumented' | |
endif | |
let l:content = printf("%s\n\n%s", l:value.signature, l:doc) | |
return [l:content, 0] | |
endfunction | |
1 0.000000 function! go#lsp#DocLink() abort | |
let l:fname = expand('%:p') | |
let [l:line, l:col] = go#lsp#lsp#Position() | |
call go#lsp#DidChange(l:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#Hover(l:fname, l:line, l:col) | |
let l:state = s:newHandlerState('doc url') | |
let l:resultHandler = go#promise#New(function('s:docLinkFromHoverResult', [], l:state), 10000, '') | |
let l:state.handleResult = l:resultHandler.wrapper | |
let l:state.error = l:resultHandler.wrapper | |
call l:lsp.sendMessage(l:msg, l:state) | |
return l:resultHandler.await() | |
endfunction | |
1 0.000001 function! s:docLinkFromHoverResult(msg) abort dict | |
if type(a:msg) is type('') | |
return [a:msg, 1] | |
endif | |
if a:msg is v:null || !has_key(a:msg, 'contents') | |
return ['', 0] | |
endif | |
let l:doc = json_decode(a:msg.contents.value) | |
" for backward compatibility with older gopls | |
if has_key(l:doc, 'link') | |
let l:link = l:doc.link | |
return [l:doc.link, 0] | |
endif | |
if !has_key(l:doc, 'linkPath') || empty(l:doc.linkPath) | |
return ['', 0] | |
endif | |
let l:link = l:doc.linkPath . "#" . l:doc.linkAnchor | |
return [l:link, 0] | |
endfunction | |
1 0.000001 function! go#lsp#Info(showstatus) | |
let l:fname = expand('%:p') | |
let [l:line, l:col] = go#lsp#lsp#Position() | |
call go#lsp#DidChange(l:fname) | |
let l:lsp = s:lspfactory.get() | |
if a:showstatus | |
let l:state = s:newHandlerState('info') | |
else | |
let l:state = s:newHandlerState('') | |
endif | |
let l:state.handleResult = funcref('s:infoDefinitionHandler', [function('s:info', [1], l:state), a:showstatus], l:state) | |
let l:state.error = funcref('s:noop') | |
let l:msg = go#lsp#message#Definition(l:fname, l:line, l:col) | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000000 function! go#lsp#GetInfo() | |
let l:fname = expand('%:p') | |
let [l:line, l:col] = go#lsp#lsp#Position() | |
call go#lsp#DidChange(l:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('') | |
let l:info = go#promise#New(function('s:info', [0], l:state), 10000, '') | |
let l:state.handleResult = funcref('s:infoDefinitionHandler', [l:info.wrapper, 0], 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:info.await() | |
endfunction | |
1 0.000001 function! s:infoDefinitionHandler(next, showstatus, msg) abort dict | |
" gopls returns a []Location; just take the first one. | |
if a:msg is v:null || len(a:msg) == 0 | |
return | |
endif | |
let l:msg = a:msg[0] | |
let l:fname = go#path#FromURI(l:msg.uri) | |
let l:line = l:msg.range.start.line | |
let l:col = l:msg.range.start.character | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#Hover(l:fname, l:line, l:col) | |
if a:showstatus | |
let l:state = s:newHandlerState('info') | |
else | |
let l:state = s:newHandlerState('') | |
endif | |
let l:state.handleResult = a:next | |
let l:state.error = funcref('s:noop') | |
return l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:info(show, msg) abort dict | |
if a:msg is v:null || !has_key(a:msg, 'contents') | |
return | |
endif | |
let l:value = json_decode(a:msg.contents.value) | |
let l:content = [l:value.singleLine] | |
let l:content = s:infoFromHoverContent(l:content) | |
if a:show | |
call go#util#ShowInfo(l:content) | |
endif | |
return l:content | |
endfunction | |
1 0.000001 function! s:infoFromHoverContent(content) abort | |
if len(a:content) < 1 | |
return '' | |
endif | |
let l:content = a:content[0] | |
" strip off the method set and fields of structs and interfaces. | |
if l:content =~# '^\(type \)\?[^ ]\+ \(struct\|interface\)' | |
let l:content = substitute(l:content, '{.*', '', '') | |
endif | |
return l:content | |
endfunction | |
1 0.000001 function! go#lsp#AddWorkspaceDirectory(...) abort | |
if a:0 == 0 | |
return | |
endif | |
call go#lsp#CleanWorkspaces() | |
let l:workspaces = [] | |
for l:dir in a:000 | |
let l:dir = fnamemodify(l:dir, ':p') | |
if len(l:dir) > 1 && l:dir[-1:] == '/' | |
let l:dir = l:dir[:-2] | |
endif | |
if !isdirectory(l:dir) | |
continue | |
endif | |
let l:workspaces = add(l:workspaces, l:dir) | |
endfor | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('') | |
let l:lsp.workspaceDirectories = s:dedup(extend(l:lsp.workspaceDirectories, l:workspaces)) | |
let l:msg = go#lsp#message#ChangeWorkspaceFolders(l:workspaces, []) | |
call l:lsp.sendMessage(l:msg, l:state) | |
return 0 | |
endfunction | |
1 0.000001 function! go#lsp#CleanWorkspaces() abort | |
let l:workspaces = [] | |
let l:lsp = s:lspfactory.get() | |
let l:i = 0 | |
let l:missing = [] | |
for l:dir in l:lsp.workspaceDirectories | |
if !isdirectory(l:dir) | |
let l:missing = add(l:missing, l:dir) | |
call remove(l:lsp.workspaceDirectories, l:i) | |
continue | |
endif | |
let l:i += 1 | |
endfor | |
if len(l:missing) == 0 | |
return 0 | |
endif | |
let l:state = s:newHandlerState('') | |
let l:msg = go#lsp#message#ChangeWorkspaceFolders([], s:dedup(l:missing)) | |
call l:lsp.sendMessage(l:msg, l:state) | |
return 0 | |
endfunction | |
" go#lsp#ResetWorkspaceDiretories removes and then re-adds all workspace | |
" folders to cause gopls to send configuration requests for all of them again. | |
" This is useful, for instance, when build tags have been added and gopls | |
" needs to use them. | |
1 0.000001 function! go#lsp#ResetWorkspaceDirectories() abort | |
call go#lsp#CleanWorkspaces() | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('') | |
let l:msg = go#lsp#message#ChangeWorkspaceFolders(s:dedup(l:lsp.workspaceDirectories), s:dedup(l:lsp.workspaceDirectories)) | |
call l:lsp.sendMessage(l:msg, l:state) | |
return 0 | |
endfunction | |
1 0.000000 function! go#lsp#DebugBrowser() abort | |
let l:lsp = s:lspfactory.get() | |
let l:port = get(l:lsp, 'debugport', 0) | |
if !l:port | |
call go#util#EchoError("gopls was not started with debugging enabled. See :help g:go_debug.") | |
return | |
endif | |
call go#util#OpenBrowser(printf('http://localhost:%d', l:port)) | |
endfunction | |
1 0.000000 function! go#lsp#Exit() abort | |
call s:exit(0) | |
endfunction | |
1 0.000000 function! go#lsp#Restart() abort | |
call s:exit(1) | |
endfunction | |
1 0.000001 function! s:exit(restart) abort | |
if !go#util#has_job() || len(s:lspfactory) == 0 || !has_key(s:lspfactory, 'current') | |
return | |
endif | |
let l:lsp = s:lspfactory.get() | |
" reset the factory so that future requests don't use the same instance of | |
" gopls. | |
call s:lspfactory.reset() | |
let l:lsp.restarting = a:restart | |
let l:state = s:newHandlerState('exit') | |
let l:msg = go#lsp#message#Shutdown() | |
let l:retval = l:lsp.sendMessage(l:msg, l:state) | |
let l:msg = go#lsp#message#Exit() | |
let l:retval = l:lsp.sendMessage(l:msg, l:state) | |
return l:retval | |
endfunction | |
1 0.000001 let s:log = [] | |
1 0.000001 function! s:debugasync(timer) abort | |
if !go#util#HasDebug('lsp') | |
let s:log = [] | |
return | |
endif | |
let l:winid = win_getid() | |
let l:name = '__GOLSP_LOG__' | |
let l:log_winid = bufwinid(l:name) | |
if l:log_winid == -1 | |
silent keepalt botright 10new | |
silent file `='__GOLSP_LOG__'` | |
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline | |
setlocal filetype=golsplog | |
else | |
call win_gotoid(l:log_winid) | |
endif | |
try | |
setlocal modifiable | |
for [l:event, l:data] in s:log | |
call remove(s:log, 0) | |
if getline(1) == '' | |
call setline('$', printf('===== %s =====', l:event)) | |
else | |
call append('$', printf('===== %s =====', l:event)) | |
endif | |
call append('$', split(l:data, "\r\n")) | |
endfor | |
normal! G | |
setlocal nomodifiable | |
finally | |
call win_gotoid(l:winid) | |
endtry | |
endfunction | |
1 0.000001 function! s:debug(event, data) abort | |
let l:shouldStart = len(s:log) == 0 | |
let s:log = add(s:log, [a:event, a:data]) | |
if l:shouldStart | |
call timer_start(10, function('s:debugasync', [])) | |
endif | |
endfunction | |
1 0.000001 function! s:compareLocations(left, right) abort | |
if a:left.uri < a:right.uri | |
return -1 | |
endif | |
if a:left.uri == a:right.uri && a:left.range.start.line < a:right.range.start.line | |
return -1 | |
endif | |
if a:left.uri == a:right.uri && a:left.range.start.line == a:right.range.start.line && a:left.range.start.character < a:right.range.start.character | |
return -1 | |
endif | |
if a:left.uri == a:right.uri && a:left.range.start.line == a:right.range.start.line && a:left.range.start.character == a:right.range.start.character | |
return 0 | |
endif | |
return 1 | |
endfunction | |
1 0.000000 function! go#lsp#Diagnostics(...) abort | |
if a:0 == 0 | |
return [] | |
endif | |
let l:dirsToPackages = {} | |
let l:lsp = s:lspfactory.get() | |
let l:diagnostics = [] | |
for [l:key, l:val] in items(l:lsp.diagnostics) | |
let l:dir = fnamemodify(l:key, ':h') | |
if !has_key(l:dirsToPackages, l:dir) | |
let l:pkg = go#package#FromPath(l:dir) | |
let l:dirsToPackages[l:dir] = l:pkg | |
else | |
let l:pkg = l:dirsToPackages[l:dir] | |
endif | |
if type(l:pkg) == type(0) | |
continue | |
endif | |
for l:arg in a:000 | |
if l:arg == l:pkg || l:arg == 'all' | |
let l:diagnostics = extend(l:diagnostics, l:val) | |
endif | |
endfor | |
endfor | |
return sort(l:diagnostics) | |
endfunction | |
1 0.000001 function! go#lsp#AnalyzeFile(fname) abort | |
let l:fname = fnamemodify(a:fname, ':p') | |
if !isdirectory(fnamemodify(l:fname, ':h')) | |
return [] | |
endif | |
let l:lsp = s:lspfactory.get() | |
let l:lastdiagnostics = get(l:lsp.diagnostics, l:fname, []) | |
let l:version = get(l:lsp.fileVersions, a:fname, 0) | |
if l:version == getbufvar(a:fname, 'changedtick') | |
return l:lastdiagnostics | |
endif | |
call go#lsp#DidChange(a:fname) | |
let l:diagnostics = go#promise#New(function('s:setDiagnostics', []), 10000, l:lastdiagnostics) | |
let l:lsp.notificationQueue[l:fname] = add(get(l:lsp.notificationQueue, l:fname, []), l:diagnostics.wrapper) | |
return l:diagnostics.await() | |
endfunction | |
1 0.000001 function! s:setDiagnostics(...) abort | |
return a:000 | |
endfunction | |
" s:processDiagnostic converts a diagnostic into an error string. It returns | |
" the errors string and the match position described in the diagnostic. The | |
" match position will be an empty list when bufname is not a valid name for | |
" the current buffer. | |
1 0.000001 function! s:errorFromDiagnostic(diagnostic, bufname, fname) abort | |
let l:range = a:diagnostic.range | |
let l:line = l:range.start.line + 1 | |
let l:buflines = getbufline(a:bufname, l:line) | |
let l:col = '' | |
if len(l:buflines) > 0 | |
let l:col = go#lsp#lsp#PositionOf(l:buflines[0], l:range.start.character) | |
endif | |
let l:error = printf('%s:%s:%s:%s: %s', a:fname, l:line, l:col, go#lsp#lsp#SeverityToErrorType(a:diagnostic.severity), a:diagnostic.message) | |
if !(a:diagnostic.severity == 1 || a:diagnostic.severity == 2) | |
return [l:error, []] | |
endif | |
" return when the diagnostic is not for the current buffer. | |
if bufnr(a:bufname) != bufnr('') | |
return [l:error, []] | |
end | |
let l:endline = l:range.end.line + 1 | |
" don't bother trying to highlight errors or warnings that span | |
" the whole file (e.g when there's missing package documentation). | |
if l:line == 1 && (l:endline) == line('$') | |
return [l:error, []] | |
endif | |
let l:endcol = go#lsp#lsp#PositionOf(getline(l:endline), l:range.end.character) | |
" the length of the match is the number of bytes between the start of | |
" the match and the end of the match. | |
let l:matchLength = line2byte(l:endline) + l:endcol - (line2byte(l:line) + l:col) | |
let l:pos = [l:line, l:col, l:matchLength] | |
return [l:error, l:pos] | |
endfunction | |
1 0.000001 function! s:highlightMatches(errorMatches, warningMatches) abort | |
" set buffer variables for errors and warnings to zero values | |
let b:go_diagnostic_matches = {'errors': [], 'warnings': []} | |
if hlexists('goDiagnosticError') | |
" clear the old matches just before adding the new ones to keep flicker | |
" to a minimum and clear before checking the level so that if the user | |
" changed the level since the last highlighting, the highlighting will be | |
" be properly cleared. | |
call go#util#ClearHighlights('goDiagnosticError') | |
if go#config#DiagnosticsLevel() >= 2 | |
let b:go_diagnostic_matches.errors = copy(a:errorMatches) | |
if go#config#HighlightDiagnosticErrors() | |
call go#util#HighlightPositions('goDiagnosticError', a:errorMatches) | |
endif | |
endif | |
endif | |
if hlexists('goDiagnosticWarning') | |
" clear the old matches just before adding the new ones to keep flicker | |
" to a minimum and clear before checking the level so that if the user | |
" changed the level since the last highlighting, the highlighting will be | |
" be properly cleared. | |
call go#util#ClearHighlights('goDiagnosticWarning') | |
if go#config#DiagnosticsLevel() >= 2 | |
let b:go_diagnostic_matches.warnings = copy(a:warningMatches) | |
if go#config#HighlightDiagnosticWarnings() | |
call go#util#HighlightPositions('goDiagnosticWarning', a:warningMatches) | |
endif | |
endif | |
endif | |
" re-apply matches at the time the buffer is displayed in a new window or | |
" redisplayed in an existing window: e.g. :edit, | |
augroup vim-go-diagnostics | |
autocmd! * <buffer> | |
autocmd BufDelete <buffer> autocmd! vim-go-diagnostics * <buffer=abuf> | |
if has('textprop') | |
autocmd BufReadPost <buffer> nested call s:highlightMatches(b:go_diagnostic_matches.errors, b:go_diagnostic_matches.warnings) | |
else | |
autocmd BufWinEnter <buffer> nested call s:highlightMatches(b:go_diagnostic_matches.errors, b:go_diagnostic_matches.warnings) | |
endif | |
augroup end | |
endfunction | |
" ClearDiagnosticHighlights removes all goDiagnosticError and | |
" goDiagnosticWarning matches. | |
1 0.000001 function! go#lsp#ClearDiagnosticHighlights() abort | |
call go#util#ClearHighlights('goDiagnosticError') | |
call go#util#ClearHighlights('goDiagnosticWarning') | |
endfunction | |
" Format formats the current buffer. | |
1 0.000000 function! go#lsp#Format() abort | |
let l:fname = expand('%:p') | |
" send the current file so that TextEdits will be relative to the current | |
" state of the buffer. | |
call go#lsp#DidChange(l:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('') | |
let l:handleFormat = go#promise#New(function('s:handleFormat', [], l:state), 10000, '') | |
let l:state.handleResult = l:handleFormat.wrapper | |
let l:state.error = l:handleFormat.wrapper | |
let l:state.handleError = function('s:handleFormatError', [l:fname], l:state) | |
let l:msg = go#lsp#message#Format(l:fname) | |
call l:lsp.sendMessage(l:msg, l:state) | |
call go#fmt#CleanErrors() | |
" await the result to avoid any race conditions among autocmds (e.g. | |
" BufWritePre and BufWritePost) | |
call l:handleFormat.await() | |
endfunction | |
" Imports executes the source.organizeImports code action for the current | |
" buffer. | |
1 0.000000 function! go#lsp#Imports() abort | |
let l:fname = expand('%:p') | |
" send the current file so that TextEdits will be relative to the current | |
" state of the buffer. | |
call go#lsp#DidChange(l:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('') | |
let l:handler = go#promise#New(function('s:handleCodeAction', ['source.organizeImports', ''], l:state), 10000, '') | |
let l:state.handleResult = l:handler.wrapper | |
let l:state.error = l:handler.wrapper | |
let l:state.handleError = function('s:handleCodeActionError', [l:fname], l:state) | |
let l:msg = go#lsp#message#CodeActionImports(l:fname) | |
call l:lsp.sendMessage(l:msg, l:state) | |
" await the result to avoid any race conditions among autocmds (e.g. | |
" BufWritePre and BufWritePost) | |
call l:handler.await() | |
endfunction | |
" FillStruct executes the refactor.rewrite code action for the current buffer | |
" and configures the handler to only apply the fillstruct command for the | |
" current location. | |
1 0.000001 function! go#lsp#FillStruct() abort | |
let l:fname = expand('%:p') | |
" send the current file so that TextEdits will be relative to the current | |
" state of the buffer. | |
call go#lsp#DidChange(l:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('') | |
let l:handler = go#promise#New(function('s:handleCodeAction', ['refactor.rewrite', 'apply_fix'], l:state), 10000, '') | |
let l:state.handleResult = l:handler.wrapper | |
let l:state.error = l:handler.wrapper | |
let l:state.handleError = function('s:handleCodeActionError', [l:fname], l:state) | |
let [l:line, l:col] = go#lsp#lsp#Position() | |
let l:msg = go#lsp#message#CodeActionFillStruct(l:fname, l:line, l:col) | |
call l:lsp.sendMessage(l:msg, l:state) | |
" await the result to avoid any race conditions among autocmds (e.g. | |
" BufWritePre and BufWritePost) | |
call l:handler.await() | |
endfunction | |
1 0.000000 function! go#lsp#Rename(newName) abort | |
let l:fname = expand('%:p') | |
let [l:line, l:col] = go#lsp#lsp#Position() | |
call go#lsp#DidChange(l:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#PrepareRename(l:fname, l:line, l:col) | |
let l:state = s:newHandlerState('rename') | |
let l:resultHandler = go#promise#New(function('s:rename', [l:fname, l:line, l:col, a:newName], l:state), 10000, '') | |
let l:state.handleResult = l:resultHandler.wrapper | |
let l:state.error = l:resultHandler.wrapper | |
let l:state.handleError = function('s:handleRenameError', [], l:state) | |
call l:lsp.sendMessage(l:msg, l:state) | |
return l:resultHandler.await() | |
endfunction | |
1 0.000001 function! s:rename(fname, line, col, newName, msg) abort dict | |
if type(a:msg) is type('') | |
call self.handleError(a:msg) | |
return | |
endif | |
if a:msg is v:null | |
call go#util#EchoWarning('cannot rename the identifier at the requested position') | |
return | |
endif | |
call go#lsp#DidChange(a:fname) | |
let l:lsp = s:lspfactory.get() | |
let l:msg = go#lsp#message#Rename(a:fname, a:line, a:col, a:newName) | |
let l:state = s:newHandlerState('rename') | |
let l:resultHandler = go#promise#New(function('s:handleRename', [], l:state), 10000, '') | |
let l:state.handleResult = l:resultHandler.wrapper | |
let l:state.error = l:resultHandler.wrapper | |
let l:state.handleError = function('s:handleRenameError', [], l:state) | |
call l:lsp.sendMessage(l:msg, l:state) | |
return l:resultHandler.await() | |
endfunction | |
1 0.000001 function! s:handleRename(msg) abort dict | |
if type(a:msg) is type('') | |
call self.handleError(a:msg) | |
return | |
endif | |
if a:msg is v:null | |
return | |
endif | |
call s:applyDocumentChanges(a:msg.documentChanges) | |
endfunction | |
1 0.000001 function! s:executeCommand(cmd, args) abort | |
let l:lsp = s:lspfactory.get() | |
let l:state = s:newHandlerState('') | |
let l:msg = go#lsp#message#ExecuteCommand(a:cmd, a:args) | |
call l:lsp.sendMessage(l:msg, l:state) | |
endfunction | |
1 0.000001 function! s:handleFormat(msg) abort dict | |
call go#fmt#CleanErrors() | |
if type(a:msg) is type('') | |
call self.handleError(a:msg) | |
return | |
endif | |
call s:applyTextEdits(bufnr(''), a:msg) | |
endfunction | |
1 0.000001 function! s:handleCodeAction(kind, cmd, msg) abort dict | |
if type(a:msg) is type('') | |
call self.handleError(a:msg) | |
return | |
endif | |
if a:msg is v:null | |
return | |
endif | |
for l:item in a:msg | |
if get(l:item, 'kind', '') is a:kind | |
if !has_key(l:item, 'edit') | |
continue | |
endif | |
if has_key(l:item, 'disabled') && get(l:item.disabled, 'reason', '') isnot '' | |
call go#util#EchoWarning(printf('code action is disabled: %s', l:item.disabled.reason)) | |
continue | |
endif | |
if has_key(l:item, 'command') | |
if has_key(l:item.command, 'command') && (l:item.command.command is a:cmd || l:item.command.command is printf('gopls.%s', a:cmd)) | |
call s:executeCommand(l:item.command.command, l:item.command.arguments) | |
continue | |
endif | |
endif | |
if !has_key(l:item.edit, 'documentChanges') | |
continue | |
endif | |
call s:applyDocumentChanges(l:item.edit.documentChanges) | |
endif | |
endfor | |
endfunction | |
1 0.000001 function s:applyDocumentChanges(changes) | |
let l:bufnr = bufnr('') | |
for l:change in a:changes | |
if !has_key(l:change, 'edits') | |
continue | |
endif | |
let l:fname = go#path#FromURI(l:change.textDocument.uri) | |
" get the buffer name relative to the current directory, because | |
" Vim says that a buffer name can't be an absolute path. | |
let l:bufname = fnamemodify(l:fname, ':.') | |
let l:bufadded = 0 | |
let l:bufloaded = 0 | |
let l:editbufnr = bufnr(l:bufname) | |
if l:editbufnr != bufnr('') | |
" make sure the buffer is listed and loaded before applying text edits | |
if !bufexists(l:bufname) | |
call bufadd(l:bufname) | |
let l:bufadded = 1 | |
endif | |
if !bufloaded(l:bufname) | |
call bufload(l:bufname) | |
let l:bufloaded = 1 | |
endif | |
let l:editbufnr = bufnr(l:bufname) | |
if l:editbufnr == -1 | |
call go#util#EchoWarn(printf('could not apply changes to %s', l:fname)) | |
continue | |
endif | |
" TODO(bc): do not edit the buffer when vim-go drops support for Vim | |
" 8.0. Instead, use the functions to modify a buffer (e.g. | |
" appendbufline, getbufline, deletebufline). | |
execute printf('keepalt keepjumps buffer! %d', l:editbufnr) | |
endif | |
call s:applyTextEdits(l:editbufnr, l:change.edits) | |
" TODO(bc): save the buffer? | |
" TODO(bc): unload and/or delete a buffer that was loaded or added, | |
" respectively? | |
endfor | |
if bufnr('') != l:bufnr | |
execute printf('keepalt keepjumps buffer! %d', l:bufnr) | |
endif | |
endfunction | |
" s:applyTextEdit applies the list of WorkspaceEdit values in msg. | |
1 0.000001 function s:applyTextEdits(bufnr, msg) abort | |
if a:msg is v:null | |
return | |
endif | |
" TODO(bc): start using the functions to modify a buffer (e.g. appendbufline, | |
" deletebufline, etc) instead of operating on the current buffer when vim-go | |
" drops support from Vim 8.0. | |
" process the TextEdit list in reverse order, because the positions are | |
" based on the current line numbers; processing in forward order would | |
" require keeping track of how the proper position of each TextEdit would be | |
" affected by all the TextEdits that came before. | |
call reverse(sort(a:msg, function('s:textEditLess'))) | |
for l:msg in a:msg | |
let l:startline = l:msg.range.start.line+1 | |
let l:endline = l:msg.range.end.line+1 | |
let l:text = l:msg.newText | |
" handle the deletion of whole lines | |
if len(l:text) == 0 && l:msg.range.start.character == 0 && l:msg.range.end.character == 0 && l:startline < l:endline | |
call s:deleteline(l:startline, l:endline-1) | |
continue | |
endif | |
" Assume that l:startcontent will be an empty string. When the replacement | |
" is not at the beginning of the line, then l:startcontent must be what | |
" comes before the start position on the start line. | |
let l:startcontent = '' | |
if l:msg.range.start.character > 0 | |
let l:startcontent = getline(l:startline) | |
let l:preSliceEnd = go#lsp#lsp#PositionOf(l:startcontent, l:msg.range.start.character-1) - 1 | |
let l:startcontent = l:startcontent[:l:preSliceEnd] | |
endif | |
let l:endcontent = getline(l:endline) | |
let l:postSliceStart = 0 | |
if l:msg.range.end.character > 0 | |
let l:postSliceStart = go#lsp#lsp#PositionOf(l:endcontent, l:msg.range.end.character-1) | |
let l:endcontent = l:endcontent[(l:postSliceStart):] | |
endif | |
" There isn't an easy way to replace the text in a byte or character | |
" range, so append to l:text any text on l:endline starting from | |
" l:postSliceStart and prepend to l:text any text on l:startline prior to | |
" l:preSliceEnd, and finally replace the lines with a delete followed by | |
" and append. | |
let l:text = printf('%s%s%s', l:startcontent, l:text, l:endcontent) | |
" TODO(bc): deal with the undo file | |
" TODO(bc): deal with folds | |
" TODO(bc): can we use appendbufline instead of deleting and appending? | |
call s:deleteline(l:startline, l:endline) | |
for l:line in split(l:text, "\n", 1) | |
call append(l:startline-1, l:line) | |
let l:startline += 1 | |
endfor | |
endfor | |
call go#lsp#DidChange(expand('%:p')) | |
return | |
endfunction | |
1 0.000001 function! s:handleFormatError(filename, msg) abort dict | |
if go#config#FmtFailSilently() | |
return | |
endif | |
let l:errors = split(a:msg, '\n') | |
let l:errors = map(l:errors, printf('substitute(v:val, ''^'', ''%s:'', '''')', a:filename)) | |
let l:errors = join(l:errors, "\n") | |
call go#fmt#ShowErrors(l:errors) | |
endfunction | |
1 0.000001 function! s:handleCodeActionError(filename, msg) abort dict | |
" TODO(bc): handle the error? | |
endfunction | |
1 0.000001 function! s:handleRenameError(msg) abort dict | |
call go#util#EchoError(a:msg) | |
endfunction | |
1 0.000001 function! s:textEditLess(left, right) abort | |
" TextEdits in a TextEdit[] never overlap and Vim's sort() is stable. | |
if a:left.range.start.line < a:right.range.start.line | |
return -1 | |
endif | |
if a:left.range.start.line > a:right.range.start.line | |
return 1 | |
endif | |
if a:left.range.start.line == a:right.range.start.line | |
if a:left.range.start.character < a:right.range.start.character | |
return -1 | |
endif | |
if a:left.range.start.character > a:right.range.start.character | |
return 1 | |
endif | |
endif | |
" return 0, because a:left and a:right refer to the same position. | |
return 0 | |
endfunction | |
1 0.000001 function! s:deleteline(start, end) abort | |
if exists('*deletebufline') | |
call deletebufline('', a:start, a:end) | |
else | |
call execute(printf('%d,%d d_', a:start, a:end)) | |
endif | |
endfunction | |
1 0.000001 function! s:ensureWorkspace(dir) | |
let l:modroot = go#util#ModuleRoot(a:dir) | |
if l:modroot is -1 || l:modroot is '' | |
return | |
endif | |
let l:lsp = s:lspfactory.get() | |
for l:dir in l:lsp.workspaceDirectories | |
if l:dir == l:modroot | |
return | |
endif | |
endfor | |
call go#lsp#AddWorkspaceDirectory(l:modroot) | |
endfunction | |
1 0.000001 function! s:dedup(list) | |
let l:dict = {} | |
for l:item in a:list | |
let l:dict[l:item] = 1 | |
endfor | |
return sort(keys(l:dict)) | |
endfunction | |
1 0.000001 function! s:lineinfile(fname, line) abort | |
let l:bufnr = bufnr(a:fname) | |
let l:bufinfo = getbufinfo(a:fname) | |
try | |
if l:bufnr == -1 || len(l:bufinfo) == 0 || l:bufinfo[0].loaded == 0 | |
let l:filecontents = readfile(a:fname, '', a:line) | |
else | |
let l:filecontents = getbufline(a:fname, a:line) | |
endif | |
if len(l:filecontents) == 0 | |
return -1 | |
endif | |
return l:filecontents[-1] | |
catch | |
"call go#util#EchoError(printf('%s (line %s): %s at %s', a:fname, a:line, v:exception, v:throwpoint)) | |
return -1 | |
endtry | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000003 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/job.vim | |
Sourced 1 time | |
Total time: 0.000507 | |
Self time: 0.000507 | |
count total (s) self (s) | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000003 let s:cpo_save = &cpo | |
1 0.000003 set cpo&vim | |
" Spawn starts an asynchronous job. See the description of go#job#Options to | |
" understand the args parameter. | |
" | |
" Spawn returns a job. | |
1 0.000001 function! go#job#Spawn(cmd, args) | |
let l:options = go#job#Options(a:args) | |
return go#job#Start(a:cmd, l:options) | |
endfunction | |
" Options returns callbacks to be used with job_start. It is abstracted to be | |
" used with various go commands, such as build, test, install, etc.. This | |
" allows us to avoid writing the same callback over and over for some | |
" commands. It's fully customizable so each command can change it to its own | |
" logic. | |
" | |
" args is a dictionary with the these keys: | |
" 'bang': | |
" Set to 0 to jump to the first error in the error list. | |
" Defaults to 0. | |
" 'statustype': | |
" The status type to use when updating the status. | |
" See statusline.vim. | |
" 'for': | |
" The g:go_list_type_command key to use to get the error list type to use. | |
" Errors will not be handled when the value is '_'. | |
" Defaults to '_job' | |
" 'errorformat': | |
" The errorformat string to use when parsing errors. Defaults to | |
" &errorformat. | |
" See :help 'errorformat'. | |
" 'complete': | |
" A function to call after the job exits and the channel is closed. The | |
" function will be passed three arguments: the job, its exit code, and the | |
" list of messages received from the channel. The default is a no-op. A | |
" custom value can modify the messages before they are processed by the | |
" returned exit_cb and close_cb callbacks. When the function is called, | |
" the current window will be the window that was hosting the buffer when | |
" the job was started. After it returns, the current window will be | |
" restored to what it was before the function was called. | |
" 'preserveerrors': | |
" A function that will be passed one value, the list type. It should | |
" return a boolean value that indicates whether any errors encountered | |
" should be consider additive to the existing set of errors. This is | |
" mostly useful for a set of commands that are run via autocmds. | |
" | |
" The return value is a dictionary with these keys: | |
" 'callback': | |
" A function suitable to be passed as a job callback handler. See | |
" job-callback. | |
" 'exit_cb': | |
" A function suitable to be passed as a job exit_cb handler. See | |
" job-exit_cb. | |
" 'close_cb': | |
" A function suitable to be passed as a job close_cb handler. See | |
" job-close_cb. | |
" 'cwd': | |
" The path to the directory which contains the current buffer. The | |
" callbacks are configured to expect this directory is the working | |
" directory for the job; it should not be modified by callers. | |
1 0.000001 function! go#job#Options(args) | |
let cbs = {} | |
let state = { | |
\ 'winid': win_getid(winnr()), | |
\ 'dir': getcwd(), | |
\ 'jobdir': expand("%:p:h"), | |
\ 'messages': [], | |
\ 'bang': 0, | |
\ 'for': "_job", | |
\ 'exited': 0, | |
\ 'exit_status': 0, | |
\ 'closed': 0, | |
\ 'errorformat': &errorformat, | |
\ 'statustype' : '', | |
\ } | |
let cbs.cwd = state.jobdir | |
if has_key(a:args, 'bang') | |
let state.bang = a:args.bang | |
endif | |
if has_key(a:args, 'for') | |
let state.for = a:args.for | |
endif | |
if has_key(a:args, 'statustype') | |
let state.statustype = a:args.statustype | |
endif | |
if has_key(a:args, 'errorformat') | |
let state.errorformat = a:args.errorformat | |
endif | |
if has_key(a:args, 'preserveerrors') | |
let state.preserveerrors = a:args.preserveerrors | |
endif | |
function state.complete(job, exit_status, data) | |
if has_key(self, 'custom_complete') | |
let l:winid = win_getid(winnr()) | |
" Always set the active window to the window that was active when the job | |
" was started. Among other things, this makes sure that the correct | |
" window's location list will be populated when the list type is | |
" 'location' and the user has moved windows since starting the job. | |
call win_gotoid(self.winid) | |
call self.custom_complete(a:job, a:exit_status, a:data) | |
call win_gotoid(l:winid) | |
endif | |
call self.show_errors(a:job, a:exit_status, a:data) | |
endfunction | |
function state.show_status(job, exit_status) dict | |
if self.statustype == '' | |
return | |
endif | |
if go#config#EchoCommandInfo() | |
let prefix = '[' . self.statustype . '] ' | |
if a:exit_status == 0 | |
call go#util#EchoSuccess(prefix . "SUCCESS") | |
else | |
call go#util#EchoError(prefix . "FAIL") | |
endif | |
endif | |
let status = { | |
\ 'desc': 'last status', | |
\ 'type': self.statustype, | |
\ 'state': "success", | |
\ } | |
if a:exit_status | |
let status.state = "failed" | |
endif | |
if has_key(self, 'started_at') | |
let elapsed_time = reltimestr(reltime(self.started_at)) | |
" strip whitespace | |
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') | |
let status.state .= printf(" (%ss)", elapsed_time) | |
endif | |
call go#statusline#Update(self.jobdir, status) | |
endfunction | |
if has_key(a:args, 'complete') | |
let state.custom_complete = a:args.complete | |
endif | |
" explicitly bind _start to state so that within it, self will | |
" always refer to state. See :help Partial for more information. | |
" | |
" _start is intended only for internal use and should not be referenced | |
" outside of this file. | |
let cbs._start = function('s:start', [''], state) | |
" explicitly bind callback to state so that within it, self will | |
" always refer to state. See :help Partial for more information. | |
let cbs.callback = function('s:callback', [], state) | |
" explicitly bind exit_cb to state so that within it, self will always refer | |
" to state. See :help Partial for more information. | |
let cbs.exit_cb = function('s:exit_cb', [], state) | |
" explicitly bind close_cb to state so that within it, self will | |
" always refer to state. See :help Partial for more information. | |
let cbs.close_cb = function('s:close_cb', [], state) | |
function state.show_errors(job, exit_status, data) | |
if self.for == '_' | |
return | |
endif | |
let l:winid = win_getid(winnr()) | |
" Always set the active window to the window that was active when the job | |
" was started. Among other things, this makes sure that the correct | |
" window's location list will be populated when the list type is | |
" 'location' and the user has moved windows since starting the job. | |
call win_gotoid(self.winid) | |
let l:listtype = go#list#Type(self.for) | |
let l:preserveerrors = 0 | |
if has_key(self, 'preserveerrors') | |
let l:preserveerrors = self.preserveerrors(l:listtype) | |
endif | |
if a:exit_status == 0 | |
if !l:preserveerrors | |
call go#list#Clean(l:listtype) | |
call win_gotoid(l:winid) | |
endif | |
return | |
endif | |
let l:listtype = go#list#Type(self.for) | |
if len(a:data) == 0 | |
if !l:preserveerrors | |
call go#list#Clean(l:listtype) | |
call win_gotoid(l:winid) | |
endif | |
return | |
endif | |
let out = join(self.messages, "\n") | |
try | |
" parse the errors relative to self.jobdir | |
call go#util#Chdir(self.jobdir) | |
call go#list#ParseFormat(l:listtype, self.errorformat, out, self.for, l:preserveerrors) | |
let errors = go#list#Get(l:listtype) | |
finally | |
call go#util#Chdir(self.dir) | |
endtry | |
if empty(errors) | |
" failed to parse errors, output the original content | |
call go#util#EchoError([self.dir] + self.messages) | |
call win_gotoid(l:winid) | |
return | |
endif | |
" only open the error window if user was still in the window from which | |
" the job was started. | |
if self.winid == l:winid | |
call go#list#Window(l:listtype, len(errors)) | |
if self.bang | |
call win_gotoid(l:winid) | |
else | |
call go#list#JumpToFirst(l:listtype) | |
endif | |
endif | |
endfunction | |
return cbs | |
endfunction | |
1 0.000001 function! s:start(args) dict | |
if go#config#EchoCommandInfo() && self.statustype != "" | |
let prefix = '[' . self.statustype . '] ' | |
call go#util#EchoSuccess(prefix . "dispatched") | |
endif | |
if self.statustype != '' | |
let status = { | |
\ 'desc': 'current status', | |
\ 'type': self.statustype, | |
\ 'state': "started", | |
\ } | |
call go#statusline#Update(self.jobdir, status) | |
endif | |
let self.started_at = reltime() | |
endfunction | |
1 0.000001 function! s:callback(chan, msg) dict | |
call add(self.messages, a:msg) | |
endfunction | |
1 0.000001 function! s:exit_cb(job, exitval) dict | |
let self.exit_status = a:exitval | |
let self.exited = 1 | |
call self.show_status(a:job, a:exitval) | |
if self.closed || has('nvim') | |
call self.complete(a:job, self.exit_status, self.messages) | |
endif | |
endfunction | |
1 0.000001 function! s:close_cb(ch) dict | |
let self.closed = 1 | |
if self.exited | |
let job = ch_getjob(a:ch) | |
call self.complete(job, self.exit_status, self.messages) | |
endif | |
endfunction | |
" go#job#Start runs a job. The options are expected to be the options | |
" suitable for Vim8 jobs. When called from Neovim, Vim8 options will be | |
" transformed to their Neovim equivalents. | |
1 0.000001 function! go#job#Start(cmd, options) | |
let l:options = copy(a:options) | |
if has('nvim') | |
let l:options = s:neooptions(l:options) | |
endif | |
" Verify that the working directory for the job actually exists. Return | |
" early if the directory does not exist. This helps avoid errors when | |
" working with plugins that use virtual files that don't actually exist on | |
" the file system. | |
let l:filedir = expand("%:p:h") | |
if has_key(l:options, 'cwd') && !isdirectory(l:options.cwd) | |
return | |
elseif !isdirectory(l:filedir) | |
return | |
endif | |
let l:manualcd = 0 | |
if !has_key(l:options, 'cwd') | |
" pre start | |
let l:manualcd = 1 | |
let l:dir = go#util#Chdir(filedir) | |
endif | |
if has_key(l:options, '_start') | |
call l:options._start() | |
" remove _start to play nicely with vim (when vim encounters an unexpected | |
" job option it reports an "E475: invalid argument" error). | |
unlet l:options._start | |
endif | |
" noblock was added in 8.1.350; remove it if it's not supported. | |
if has_key(l:options, 'noblock') && (has('nvim') || !has("patch-8.1.350")) | |
call remove(l:options, 'noblock') | |
endif | |
if go#util#HasDebug('shell-commands') | |
call go#util#EchoInfo('job command: ' . string(a:cmd)) | |
endif | |
if has('nvim') | |
let l:input = [] | |
if has_key(a:options, 'in_io') && a:options.in_io ==# 'file' && !empty(a:options.in_name) | |
let l:input = readfile(a:options.in_name, "b") | |
endif | |
let job = jobstart(a:cmd, l:options) | |
if len(l:input) > 0 | |
call chansend(job, l:input) | |
" close stdin to signal that no more bytes will be sent. | |
call chanclose(job, 'stdin') | |
endif | |
else | |
let l:cmd = a:cmd | |
if go#util#IsWin() | |
let l:cmd = join(map(copy(a:cmd), function('s:winjobarg')), " ") | |
endif | |
let job = job_start(l:cmd, l:options) | |
endif | |
if l:manualcd | |
" post start | |
call go#util#Chdir(l:dir) | |
endif | |
return job | |
endfunction | |
" s:neooptions returns a dictionary of job options suitable for use by Neovim | |
" based on a dictionary of job options suitable for Vim8. | |
1 0.000001 function! s:neooptions(options) | |
let l:options = {} | |
let l:options['stdout_buf'] = '' | |
let l:options['stderr_buf'] = '' | |
let l:err_mode = get(a:options, 'err_mode', get(a:options, 'mode', '')) | |
let l:out_mode = get(a:options, 'out_mode', get(a:options, 'mode', '')) | |
for key in keys(a:options) | |
if key == 'cwd' | |
let l:options['cwd'] = a:options['cwd'] | |
continue | |
endif | |
if key == 'callback' | |
let l:options['callback'] = a:options['callback'] | |
if !has_key(a:options, 'out_cb') | |
let l:options['on_stdout'] = function('s:callback2on_stdout', [l:out_mode], l:options) | |
endif | |
if !has_key(a:options, 'err_cb') | |
let l:options['on_stderr'] = function('s:callback2on_stderr', [l:err_mode], l:options) | |
endif | |
continue | |
endif | |
if key == 'out_cb' | |
let l:options['out_cb'] = a:options['out_cb'] | |
let l:options['on_stdout'] = function('s:on_stdout', [l:out_mode], l:options) | |
continue | |
endif | |
if key == 'err_cb' | |
let l:options['err_cb'] = a:options['err_cb'] | |
let l:options['on_stderr'] = function('s:on_stderr', [l:err_mode], l:options) | |
continue | |
endif | |
if key == 'exit_cb' | |
let l:options['exit_cb'] = a:options['exit_cb'] | |
let l:options['on_exit'] = function('s:on_exit', [], l:options) | |
continue | |
endif | |
if key == 'close_cb' | |
continue | |
endif | |
if key == 'stoponexit' | |
if a:options['stoponexit'] == '' | |
let l:options['detach'] = 1 | |
endif | |
continue | |
endif | |
endfor | |
return l:options | |
endfunction | |
1 0.000001 function! s:callback2on_stdout(mode, ch, data, event) dict | |
let self.stdout_buf = s:neocb(a:mode, a:ch, self.stdout_buf, a:data, self.callback) | |
endfunction | |
1 0.000001 function! s:callback2on_stderr(mode, ch, data, event) dict | |
let self.stderr_buf = s:neocb(a:mode, a:ch, self.stderr_buf, a:data, self.callback) | |
endfunction | |
1 0.000001 function! s:on_stdout(mode, ch, data, event) dict | |
let self.stdout_buf = s:neocb(a:mode, a:ch, self.stdout_buf, a:data, self.out_cb) | |
endfunction | |
1 0.000001 function! s:on_stderr(mode, ch, data, event) dict | |
let self.stderr_buf = s:neocb(a:mode, a:ch, self.stderr_buf, a:data, self.err_cb ) | |
endfunction | |
1 0.000001 function! s:on_exit(jobid, exitval, event) dict | |
call self.exit_cb(a:jobid, a:exitval) | |
endfunction | |
1 0.000001 function! go#job#Stop(job) abort | |
if has('nvim') | |
call jobstop(a:job) | |
return | |
endif | |
call job_stop(a:job) | |
call go#job#Wait(a:job) | |
return | |
endfunction | |
1 0.000001 function! go#job#Wait(job) abort | |
if has('nvim') | |
call jobwait([a:job]) | |
return | |
endif | |
while job_status(a:job) is# 'run' | |
sleep 50m | |
endwhile | |
endfunction | |
1 0.000001 function! s:winjobarg(idx, val) abort | |
if empty(a:val) | |
return '""' | |
endif | |
return a:val | |
endfunction | |
1 0.000001 function! s:neocb(mode, ch, buf, data, callback) | |
" dealing with the channel lines of Neovim is awful. The docs (:help | |
" channel-lines) say: | |
" stream event handlers may receive partial (incomplete) lines. For a | |
" given invocation of on_stdout etc, `a:data` is not guaranteed to end | |
" with a newline. | |
" - `abcdefg` may arrive as `['abc']`, `['defg']`. | |
" - `abc\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`, | |
" `['','efg']`, or even `['ab']`, `['c','efg']`. | |
" | |
" Thankfully, though, this is explained a bit better in an issue: | |
" https://github.com/neovim/neovim/issues/3555. Specifically in these two | |
" comments: | |
" * https://github.com/neovim/neovim/issues/3555#issuecomment-152290804 | |
" * https://github.com/neovim/neovim/issues/3555#issuecomment-152588749 | |
" | |
" The key is | |
" Every item in the list passed to job control callbacks represents a | |
" string after a newline(Except the first, of course). If the program | |
" outputs: "hello\nworld" the corresponding list is ["hello", "world"]. | |
" If the program outputs "hello\nworld\n", the corresponding list is | |
" ["hello", "world", ""]. In other words, you can always determine if | |
" the last line received is complete or not. | |
" and | |
" for every list you receive in a callback, all items except the first | |
" represent newlines. | |
let l:buf = '' | |
" A single empty string means EOF was reached. The first item will never be | |
" an empty string except for when it's the only item and is signaling that | |
" EOF was reached. | |
if len(a:data) == 1 && a:data[0] == '' | |
" when there's nothing buffered, return early so that an | |
" erroneous message will not be added. | |
if a:buf == '' | |
return '' | |
endif | |
let l:data = [a:buf] | |
else | |
let l:data = copy(a:data) | |
let l:data[0] = a:buf . l:data[0] | |
" The last element may be a partial line; save it for next time. | |
if a:mode != 'raw' | |
let l:buf = l:data[-1] | |
let l:data = l:data[:-2] | |
endif | |
endif | |
let l:i = 0 | |
let l:last = len(l:data) - 1 | |
while l:i <= l:last | |
let l:msg = l:data[l:i] | |
if a:mode == 'raw' && l:i < l:last | |
let l:msg = l:msg . "\n" | |
endif | |
call a:callback(a:ch, l:msg) | |
let l:i += 1 | |
endwhile | |
return l:buf | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000002 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp/message.vim | |
Sourced 1 time | |
Total time: 0.000426 | |
Self time: 0.000426 | |
count total (s) self (s) | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000008 let s:cpo_save = &cpo | |
1 0.000005 set cpo&vim | |
1 0.000002 function! go#lsp#message#Initialize(wd) abort | |
return { | |
\ 'notification': 0, | |
\ 'method': 'initialize', | |
\ 'params': { | |
\ 'processId': getpid(), | |
\ 'rootUri': go#path#ToURI(a:wd), | |
\ 'capabilities': { | |
\ 'workspace': { | |
\ 'workspaceFolders': v:true, | |
\ 'didChangeConfiguration': { | |
\ 'dynamicRegistration': v:true, | |
\ }, | |
\ 'workspaceEdit': { | |
\ 'documentChanges': v:true, | |
\ }, | |
\ 'configuration': v:true, | |
\ }, | |
\ 'textDocument': { | |
\ 'hover': { | |
\ 'contentFormat': ['plaintext'], | |
\ }, | |
\ 'completion': { | |
\ 'completionItem': { | |
\ 'snippetSupport': go#config#GoplsUsePlaceholders() ? v:true : v:false, | |
\ }, | |
\ }, | |
\ 'codeAction': { | |
\ 'codeActionLiteralSupport': { | |
\ 'codeActionKind': { | |
\ 'valueSet': ['source.organizeImports', 'refactor.rewrite'], | |
\ }, | |
\ }, | |
\ }, | |
\ } | |
\ }, | |
\ 'workspaceFolders': [s:workspaceFolder(0, a:wd)], | |
\ } | |
\ } | |
endfunction | |
1 0.000002 function! go#lsp#message#Initialized() abort | |
return { | |
\ 'notification': 1, | |
\ 'method': 'initialized', | |
\ 'params': {}, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#Shutdown() abort | |
return { | |
\ 'notification': 0, | |
\ 'method': 'shutdown', | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#Format(file) abort | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/formatting', | |
\ 'params': { | |
\ 'textDocument': { | |
\ 'uri': go#path#ToURI(a:file) | |
\ }, | |
\ 'options': { | |
\ 'insertSpaces': v:false, | |
\ }, | |
\ } | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#CodeActionImports(file) abort | |
return s:codeAction('source.organizeImports', a:file) | |
endfunction | |
1 0.000001 function! go#lsp#message#CodeActionFillStruct(file, line, col) abort | |
return go#lsp#message#CodeActionRefactorRewrite(a:file, a:line, a:col, a:line, a:col) | |
endfunction | |
1 0.000002 function! go#lsp#message#CodeActionRefactorRewrite(file, startline, startcol, endline, endcol) abort | |
let l:startpos = s:position(a:startline, a:startcol) | |
let l:endpos = s:position(a:endline, a:endcol) | |
let l:request = s:codeAction('refactor.rewrite', a:file) | |
let l:request.params = extend(l:request.params, | |
\ { | |
\ 'range': { | |
\ 'start': l:startpos, | |
\ 'end': l:endpos, | |
\ } | |
\ }) | |
return l:request | |
endfunction | |
1 0.000002 function! s:codeAction(name, file) abort | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/codeAction', | |
\ 'params': { | |
\ 'textDocument': { | |
\ 'uri': go#path#ToURI(a:file) | |
\ }, | |
\ 'range': { | |
\ 'start': s:position(0, 0), | |
\ 'end': s:position(line('$'), 0), | |
\ }, | |
\ 'context': { | |
\ 'only': [a:name], | |
\ }, | |
\ } | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#Exit() abort | |
return { | |
\ 'notification': 1, | |
\ 'method': 'exit', | |
\ } | |
endfunction | |
1 0.000002 function! go#lsp#message#WorkspaceFoldersResult(dirs) abort | |
return map(copy(a:dirs), function('s:workspaceFolder', [])) | |
endfunction | |
1 0.000002 function! go#lsp#message#Definition(file, line, col) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/definition', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000005 function! go#lsp#message#TypeDefinition(file, line, col) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/typeDefinition', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#Implementation(file, line, col) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/implementation', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#DidOpen(file, content, version) abort | |
return { | |
\ 'notification': 1, | |
\ 'method': 'textDocument/didOpen', | |
\ 'params': { | |
\ 'textDocument': { | |
\ 'uri': go#path#ToURI(a:file), | |
\ 'languageId': 'go', | |
\ 'text': a:content, | |
\ 'version': a:version, | |
\ } | |
\ } | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#DidChange(file, content, version) abort | |
return { | |
\ 'notification': 1, | |
\ 'method': 'textDocument/didChange', | |
\ 'params': { | |
\ 'textDocument': { | |
\ 'uri': go#path#ToURI(a:file), | |
\ 'version': a:version, | |
\ }, | |
\ 'contentChanges': [ | |
\ { | |
\ 'text': a:content, | |
\ } | |
\ ] | |
\ } | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#DidClose(file) abort | |
return { | |
\ 'notification': 1, | |
\ 'method': 'textDocument/didClose', | |
\ 'params': { | |
\ 'textDocument': { | |
\ 'uri': go#path#ToURI(a:file), | |
\ } | |
\ } | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#Completion(file, line, col) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/completion', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#References(file, line, col) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
let l:params.context = {'includeDeclaration': v:true} | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/references', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#PrepareCallHierarchy(file, line, col) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/prepareCallHierarchy', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#IncomingCalls(item) abort | |
return { | |
\ 'notification': 0, | |
\ 'method': 'callHierarchy/incomingCalls', | |
\ 'params': { | |
\ 'item': a:item, | |
\ } | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#Hover(file, line, col) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/hover', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#Rename(file, line, col, newName) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
let l:params.newName = a:newName | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/rename', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#ChangeWorkspaceFolders(add, remove) abort | |
let l:addDirs = map(copy(a:add), function('s:workspaceFolder', [])) | |
let l:removeDirs = map(copy(a:remove), function('s:workspaceFolder', [])) | |
return { | |
\ 'notification': 1, | |
\ 'method': 'workspace/didChangeWorkspaceFolders', | |
\ 'params': { | |
\ 'event': { | |
\ 'removed': l:removeDirs, | |
\ 'added': l:addDirs, | |
\ }, | |
\ } | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#ConfigurationResult(items) abort | |
let l:result = [] | |
" results must be in the same order as the items | |
for l:item in a:items | |
let l:workspace = go#path#FromURI(l:item.scopeUri) | |
let l:config = { | |
\ 'buildFlags': [], | |
\ 'hoverKind': 'Structured', | |
\ } | |
let l:buildtags = go#config#BuildTags() | |
if buildtags isnot '' | |
let l:config.buildFlags = extend(l:config.buildFlags, ['-tags', go#config#BuildTags()]) | |
endif | |
let l:deepCompletion = go#config#GoplsDeepCompletion() | |
let l:matcher = go#config#GoplsMatcher() | |
let l:completeUnimported = go#config#GoplsCompleteUnimported() | |
let l:staticcheck = go#config#GoplsStaticCheck() | |
let l:usePlaceholder = go#config#GoplsUsePlaceholders() | |
let l:tempModfile = go#config#GoplsTempModfile() | |
let l:analyses = go#config#GoplsAnalyses() | |
let l:local = go#config#GoplsLocal() | |
if type(l:local) is v:t_dict | |
let l:local = get(l:local, l:workspace, v:null) | |
endif | |
let l:gofumpt = go#config#GoplsGofumpt() | |
let l:settings = go#config#GoplsSettings() | |
if l:deepCompletion isnot v:null | |
if l:deepCompletion | |
let l:config.deepCompletion = v:true | |
else | |
let l:config.deepCompletion = v:false | |
endif | |
endif | |
if l:matcher isnot v:null | |
let l:config.matcher = l:matcher | |
endif | |
if l:completeUnimported isnot v:null | |
if l:completeUnimported | |
let l:config.completeUnimported = v:true | |
else | |
let l:config.completeUnimported = v:false | |
endif | |
endif | |
if l:staticcheck isnot v:null | |
if l:staticcheck | |
let l:config.staticcheck = v:true | |
else | |
let l:config.staticcheck = v:false | |
endif | |
endif | |
if l:usePlaceholder isnot v:null | |
if l:usePlaceholder | |
let l:config.usePlaceholders = v:true | |
else | |
let l:config.usePlaceholders = v:false | |
endif | |
endif | |
if l:tempModfile isnot v:null | |
if l:tempModfile | |
let l:config.tempModfile = v:true | |
else | |
let l:config.tempModfile = v:false | |
endif | |
endif | |
if l:analyses isnot v:null | |
let l:config.analyses = l:analyses | |
endif | |
if l:local isnot v:null | |
let l:config.local = l:local | |
endif | |
if l:gofumpt isnot v:null | |
if l:gofumpt | |
let l:config.gofumpt = v:true | |
else | |
let l:config.gofumpt = v:false | |
endif | |
endif | |
if l:settings isnot v:null | |
let l:config = extend(l:config, l:settings, 'keep') | |
endif | |
let l:result = add(l:result, deepcopy(l:config)) | |
endfor | |
return l:result | |
endfunction | |
1 0.000001 function! go#lsp#message#ExecuteCommand(cmd, args) abort | |
return { | |
\ 'notification': 0, | |
\ 'method': 'workspace/executeCommand', | |
\ 'params': { | |
\ 'command': a:cmd, | |
\ 'arguments': a:args, | |
\ } | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#ApplyWorkspaceEditResponse(ok) abort | |
return { | |
\ 'applied': a:ok, | |
\ } | |
endfunction | |
1 0.000001 function! go#lsp#message#PrepareRename(file, line, col) abort | |
let l:params = s:textDocumentPositionParams(a:file, a:line, a:col) | |
return { | |
\ 'notification': 0, | |
\ 'method': 'textDocument/prepareRename', | |
\ 'params': l:params, | |
\ } | |
endfunction | |
1 0.000001 function! s:workspaceFolder(key, val) abort | |
return {'uri': go#path#ToURI(a:val), 'name': a:val} | |
endfunction | |
1 0.000001 function! s:position(line, col) abort | |
return {'line': a:line, 'character': a:col} | |
endfunction | |
1 0.000001 function! s:textDocumentPositionParams(fname, line, col) abort | |
return { | |
\ 'textDocument': { | |
\ 'uri': go#path#ToURI(a:fname) | |
\ }, | |
\ 'position': s:position(a:line, a:col), | |
\ } | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000003 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/uri.vim | |
Sourced 1 time | |
Total time: 0.000334 | |
Self time: 0.000334 | |
count total (s) self (s) | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000003 let s:cpo_save = &cpo | |
1 0.000003 set cpo&vim | |
1 0.000001 function! go#uri#Encode(value) abort | |
return s:encode(a:value, '[^A-Za-z0-9_.~-]') | |
endfunction | |
1 0.000001 function! go#uri#EncodePath(value) abort | |
let l:separator = '/' | |
if go#util#IsWin() | |
let l:separator = '\\' | |
endif | |
return s:encode(a:value, '[^' . l:separator . 'A-Za-z0-9_.~-]') | |
endfunction | |
1 0.000001 function! s:encode(value, unreserved) | |
return substitute( | |
\ a:value, | |
\ a:unreserved, | |
\ '\=s:encodechar(submatch(0))', | |
\ 'g' | |
\) | |
endfunction | |
1 0.000001 function! go#uri#Decode(value) abort | |
return substitute( | |
\ a:value, | |
\ '%\(\x\x\)', | |
\ '\=s:decodehex(submatch(1))', | |
\ 'g' | |
\) | |
endfunction | |
1 0.000001 function! s:encodechar(value) | |
let l:idx = 0 | |
let l:encoded = '' | |
while l:idx < strlen(a:value) | |
let l:byte = strpart(a:value, l:idx, 1) | |
let l:encoded = printf('%s%%%02X', l:encoded, char2nr(l:byte)) | |
let l:idx += 1 | |
endwhile | |
return l:encoded | |
endfunction | |
1 0.000001 function! s:decodehex(value) | |
return eval(printf('"\x%s"', a:value)) | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000003 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/statusline.vim | |
Sourced 1 time | |
Total time: 0.000356 | |
Self time: 0.000356 | |
count total (s) self (s) | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000006 let s:cpo_save = &cpo | |
1 0.000011 set cpo&vim | |
" Statusline | |
"""""""""""""""""""""""""""""""" | |
" s:statuses is a global reference to all statuses. It stores the statuses per | |
" import paths (map[string]status), where each status is unique per its | |
" type. Current status dict is in form: | |
" { | |
" 'desc' : 'Job description', | |
" 'state' : 'Job state, such as success, failure, etc..', | |
" 'type' : 'Job type, such as build, test, etc..' | |
" 'created_at' : 'Time it was created as seconds since 1st Jan 1970' | |
" } | |
1 0.000001 let s:statuses = {} | |
" timer_id for cleaner | |
1 0.000001 let s:timer_id = 0 | |
" last_status stores the last generated text per status | |
1 0.000001 let s:last_status = "" | |
" Show returns the current status of the job for 20 seconds (configurable). It | |
" displays it in form of 'desc: [type|state]' if there is any state available, | |
" if not it returns an empty string. This function should be plugged directly | |
" into the statusline. | |
1 0.000002 function! go#statusline#Show() abort | |
" lazy initialization of the cleaner | |
if !s:timer_id | |
let interval = go#config#StatuslineDuration() | |
let s:timer_id = timer_start(interval, function('go#statusline#Clear'), {'repeat': -1}) | |
endif | |
" nothing to show | |
if empty(s:statuses) | |
return '' | |
endif | |
let status_dir = expand('%:p:h') | |
if !has_key(s:statuses, status_dir) | |
return '' | |
endif | |
let status = s:statuses[status_dir] | |
if !has_key(status, 'desc') || !has_key(status, 'state') || !has_key(status, 'type') | |
return '' | |
endif | |
let status_text = printf("[%s|%s]", status.type, status.state) | |
if empty(status_text) | |
return '' | |
endif | |
" only update highlight if status has changed. | |
if status_text != s:last_status | |
if status.state =~ "success" || status.state =~ "finished" || status.state =~ "pass" || status.state =~ 'initialized' | |
hi goStatusLineColor cterm=bold ctermbg=76 ctermfg=22 guibg=#5fd700 guifg=#005f00 | |
elseif status.state =~ "started" || status.state =~ "analysing" || status.state =~ "compiling" || status.state =~ 'initializing' | |
hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88 guibg=#ff8700 guifg=#870000 | |
elseif status.state =~ "failed" | |
hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52 guibg=#ff0000 guifg=#5f0000 | |
endif | |
endif | |
let s:last_status = status_text | |
return status_text | |
endfunction | |
" Update updates (adds) the statusline for the given status_dir with the | |
" given status dict. It overrides any previously set status. | |
1 0.000002 function! go#statusline#Update(status_dir, status) abort | |
let a:status.created_at = reltime() | |
let s:statuses[a:status_dir] = a:status | |
" force to update the statusline, otherwise the user needs to move the | |
" cursor | |
exe 'let &ro = &ro' | |
" before we stop the timer, check if we have any previous jobs to be cleaned | |
" up. Otherwise every job will reset the timer when this function is called | |
" and thus old jobs will never be cleaned | |
call s:clear() | |
" also reset the timer, so the user has time to see it in the statusline. | |
" Setting the timer_id to 0 will cause a new timer to be created the next | |
" time the go#statusline#Show() is called. | |
call timer_stop(s:timer_id) | |
let s:timer_id = 0 | |
endfunction | |
" Clear clears all currently stored statusline data. The timer_id argument is | |
" just a placeholder so we can pass it to a timer_start() function if needed. | |
1 0.000001 function! go#statusline#Clear(timer_id) abort | |
call s:clear() | |
endfunction | |
1 0.000001 function! s:clear() | |
for [status_dir, status] in items(s:statuses) | |
let elapsed_time = reltimestr(reltime(status.created_at)) | |
" strip whitespace | |
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') | |
if str2nr(elapsed_time) > 10 | |
call remove(s:statuses, status_dir) | |
endif | |
endfor | |
if len(s:statuses) == 0 | |
let s:statuses = {} | |
endif | |
" force to update the statusline, otherwise the user needs to move the | |
" cursor | |
exe 'let &ro = &ro' | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000003 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/auto.vim | |
Sourced 1 time | |
Total time: 0.000242 | |
Self time: 0.000242 | |
count total (s) self (s) | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000007 let s:cpo_save = &cpo | |
1 0.000006 set cpo&vim | |
1 0.000002 function! go#auto#template_autocreate() | |
if !go#config#TemplateAutocreate() || !&modifiable | |
return | |
endif | |
" create new template from scratch | |
call go#template#create() | |
endfunction | |
1 0.000001 function! go#auto#complete_done() | |
if &omnifunc isnot 'go#complete#Complete' | |
return | |
endif | |
call s:echo_go_info() | |
call s:ExpandSnippet() | |
endfunction | |
1 0.000001 function! s:ExpandSnippet() abort | |
if !exists('v:completed_item') || empty(v:completed_item) || !go#config#GoplsUsePlaceholders() | |
return | |
endif | |
let l:engine = go#config#SnippetEngine() | |
if l:engine is 'ultisnips' | |
if !get(g:, 'did_plugin_ultisnips', 0) | |
return | |
endif | |
" the snippet may have a '{\}' in it. For UltiSnips, that should be spelled | |
" \{}. fmt.Printf is such a snippet that can be used to demonstrate. | |
let l:snippet = substitute(v:completed_item.word, '{\\}', '\{}', 'g') | |
call UltiSnips#Anon(l:snippet, v:completed_item.word, '', 'i') | |
" elseif l:engine is 'neosnippet' | |
" " TODO(bc): make the anonymous expansion for neosnippet work | |
" | |
" if !get(g:, 'loaded_neosnippet') is 1 | |
" return | |
" endif | |
" | |
" " neosnippet#anonymous doesn't need a trigger, so replace the | |
" " completed_item.word with an empty string before calling neosnippet#anonymous | |
" let l:snippet = substitute(v:completed_item.word, '{\\}', '\{\}', 'g') | |
" call setline('.', substitute(getline('.'), substitute(v:completed_item.word, '\', '\\', 'g'), '', '')) | |
" call neosnippet#anonymous(l:snippet) | |
endif | |
endfunction | |
1 0.000001 function! s:echo_go_info() | |
if !go#config#EchoGoInfo() | |
return | |
endif | |
if !exists('v:completed_item') || empty(v:completed_item) | |
return | |
endif | |
let item = v:completed_item | |
if !has_key(item, "user_data") | |
return | |
endif | |
if empty(item.user_data) | |
return | |
endif | |
redraws! | echo "vim-go: " | echohl Function | echon item.user_data | echohl None | |
endfunction | |
1 0.000001 let s:timer_id = 0 | |
" go#auto#update_autocmd() will be called on BufEnter,CursorHold. This | |
" configures the augroup according to conditions below. | |
" | |
" | # | has_timer | should_enable | do | | |
" |---|-----------|---------------|------------------------------------| | |
" | 1 | false | false | return early | | |
" | 2 | true | true | return early | | |
" | 3 | true | false | clear the group and stop the timer | | |
" | 4 | false | true | configure the group | | |
1 0.000001 function! go#auto#update_autocmd() | |
let has_timer = get(b:, 'has_timer') | |
let should_enable = go#config#AutoTypeInfo() || go#config#AutoSameids() | |
if (!has_timer && !should_enable) || (has_timer && should_enable) | |
return | |
endif | |
if has_timer | |
augroup vim-go-buffer-auto | |
autocmd! * <buffer> | |
augroup END | |
let b:has_timer = 0 | |
call s:timer_stop() | |
return | |
endif | |
augroup vim-go-buffer-auto | |
autocmd! * <buffer> | |
autocmd CursorMoved <buffer> call s:timer_restart() | |
autocmd BufLeave <buffer> call s:timer_stop() | |
augroup END | |
let b:has_timer = 1 | |
call s:timer_start() | |
endfunction | |
1 0.000001 function! s:timer_restart() | |
if isdirectory(expand('%:p:h')) | |
call s:timer_stop() | |
call s:timer_start() | |
endif | |
endfunction | |
1 0.000000 function! s:timer_stop() | |
if s:timer_id | |
call timer_stop(s:timer_id) | |
let s:timer_id = 0 | |
endif | |
endfunction | |
1 0.000001 function! s:timer_start() | |
let s:timer_id = timer_start(go#config#Updatetime(), function('s:handler')) | |
endfunction | |
1 0.000001 function! s:handler(timer_id) | |
if go#config#AutoTypeInfo() | |
call go#tool#Info(0) | |
endif | |
if go#config#AutoSameids() | |
call go#guru#SameIds(0) | |
endif | |
let s:timer_id = 0 | |
endfunction | |
1 0.000001 function! go#auto#fmt_autosave() | |
if !(isdirectory(expand('%:p:h')) && expand('<afile>:p') == expand('%:p')) | |
return | |
endif | |
if !(go#config#FmtAutosave() || go#config#ImportsAutosave()) | |
return | |
endif | |
" Order matters when formatting and adjusting imports, because of gopls' | |
" support for gofumpt. Gofumpt formatting will group all imports that look | |
" like a stdlib package (e.g. there's no '.' in the package path) together. | |
" When the local setting is provided, the only way to get the local imports | |
" grouped separately when gofumpt is used to format is to format first and | |
" then organize imports. | |
if go#config#FmtAutosave() && !(go#config#ImportsAutosave() && go#config#ImportsMode() == 'goimports') | |
call go#fmt#Format(0) | |
" return early when the imports mode is goimports, because there's no need | |
" to format again when goimports was run | |
if go#config#FmtCommand() == 'goimports' | |
return | |
endif | |
endif | |
if !go#config#ImportsAutosave() | |
return | |
endif | |
call go#fmt#Format(1) | |
endfunction | |
1 0.000001 function! go#auto#metalinter_autosave() | |
if !go#config#MetalinterAutosave() || !isdirectory(expand('%:p:h')) | |
return | |
endif | |
" run gometalinter on save | |
call go#lint#Gometa(!g:go_jump_to_error, 1) | |
endfunction | |
1 0.000001 function! go#auto#modfmt_autosave() | |
if !(go#config#ModFmtAutosave() && isdirectory(expand('%:p:h')) && expand('<afile>:p') == expand('%:p')) | |
return | |
endif | |
" go.mod code formatting on save | |
call go#mod#Format() | |
endfunction | |
1 0.000000 function! go#auto#asmfmt_autosave() | |
if !(go#config#AsmfmtAutosave() && isdirectory(expand('%:p:h')) && expand('<afile>:p') == expand('%:p')) | |
return | |
endif | |
" Go asm formatting on save | |
call go#asmfmt#Format() | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000003 let &cpo = s:cpo_save | |
1 0.000001 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/bingo.vim | |
Sourced 2 times | |
Total time: 0.000490 | |
Self time: 0.000234 | |
count total (s) self (s) | |
" Author: Jerko Steiner <https://github.com/jeremija> | |
" Description: https://github.com/saibing/bingo | |
2 0.000026 0.000013 call ale#Set('go_bingo_executable', 'bingo') | |
2 0.000012 0.000005 call ale#Set('go_bingo_options', '--mode stdio') | |
2 0.000003 function! ale_linters#go#bingo#GetCommand(buffer) abort | |
return ale#go#EnvString(a:buffer) . '%e' . ale#Pad(ale#Var(a:buffer, 'go_bingo_options')) | |
endfunction | |
2 0.000002 function! ale_linters#go#bingo#FindProjectRoot(buffer) abort | |
let l:go_modules_off = ale#Var(a:buffer, 'go_go111module') is# 'off' | |
let l:project_root = l:go_modules_off ? | |
\ '' : ale#path#FindNearestFile(a:buffer, 'go.mod') | |
let l:mods = ':h' | |
if empty(l:project_root) | |
let l:project_root = ale#path#FindNearestDirectory(a:buffer, '.git') | |
let l:mods = ':h:h' | |
endif | |
return !empty(l:project_root) ? fnamemodify(l:project_root, l:mods) : '' | |
endfunction | |
2 0.000267 0.000030 call ale#linter#Define('go', { | |
\ 'name': 'bingo', | |
\ 'lsp': 'stdio', | |
\ 'executable': {b -> ale#Var(b, 'go_bingo_executable')}, | |
\ 'command': function('ale_linters#go#bingo#GetCommand'), | |
\ 'project_root': function('ale_linters#go#bingo#FindProjectRoot'), | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/cspell.vim | |
Sourced 2 times | |
Total time: 0.001478 | |
Self time: 0.000786 | |
count total (s) self (s) | |
2 0.000005 scriptencoding utf-8 | |
" Author: David Houston <houstdav000> | |
" Description: cspell support for Go files. | |
2 0.001376 0.000684 call ale#handlers#cspell#DefineLinter('go') | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/handlers/cspell.vim | |
Sourced 1 time | |
Total time: 0.000341 | |
Self time: 0.000341 | |
count total (s) self (s) | |
1 0.000002 scriptencoding utf-8 | |
" Author: David Houston <houstdav000> | |
" Description: Define a handler function for cspell's output | |
1 0.000002 function! ale#handlers#cspell#GetExecutable(buffer) abort | |
return ale#path#FindExecutable(a:buffer, | |
\ 'cspell', [ | |
\ 'node_modules/.bin/cspell', | |
\ 'node_modules/cspell/bin.js', | |
\ ] | |
\) | |
endfunction | |
1 0.000001 function! ale#handlers#cspell#GetCommand(buffer) abort | |
let l:executable = ale#handlers#cspell#GetExecutable(a:buffer) | |
let l:options = ale#Var(a:buffer, 'cspell_options') | |
return ale#node#Executable(a:buffer, l:executable) | |
\ . ' lint --no-color --no-progress --no-summary' | |
\ . ale#Pad(l:options) | |
\ . ' -- stdin' | |
endfunction | |
1 0.000001 function! ale#handlers#cspell#Handle(buffer, lines) abort | |
" Look for lines like the following: | |
" | |
" /home/user/repos/ale/README.md:723:48 - Unknown word (stylelint) | |
let l:pattern = '\v^.*:(\d+):(\d+) - (.*)$' | |
let l:output = [] | |
for l:match in ale#util#GetMatches(a:lines, l:pattern) | |
call add(l:output, { | |
\ 'lnum': l:match[1] + 0, | |
\ 'col': l:match[2] + 0, | |
\ 'text': l:match[3], | |
\ 'type': 'W', | |
\}) | |
endfor | |
return l:output | |
endfunction | |
1 0.000001 function! ale#handlers#cspell#DefineLinter(filetype) abort | |
call ale#Set('cspell_executable', 'cspell') | |
call ale#Set('cspell_options', '') | |
call ale#Set('cspell_use_global', get(g:, 'ale_use_global_executables', 0)) | |
call ale#linter#Define(a:filetype, { | |
\ 'name': 'cspell', | |
\ 'executable': function('ale#handlers#cspell#GetExecutable'), | |
\ 'command': function('ale#handlers#cspell#GetCommand'), | |
\ 'callback': 'ale#handlers#cspell#Handle', | |
\}) | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gobuild.vim | |
Sourced 2 times | |
Total time: 0.000434 | |
Self time: 0.000183 | |
count total (s) self (s) | |
" Author: Joshua Rubin <joshua@rubixconsulting.com>, Ben Reedy <https://github.com/breed808>, | |
" Jeff Willette <jrwillette88@gmail.com> | |
" Description: go build for Go files | |
" inspired by work from dzhou121 <dzhou121@gmail.com> | |
2 0.000020 0.000010 call ale#Set('go_go_executable', 'go') | |
2 0.000011 0.000004 call ale#Set('go_gobuild_options', '') | |
2 0.000003 function! ale_linters#go#gobuild#GetCommand(buffer) abort | |
let l:options = ale#Var(a:buffer, 'go_gobuild_options') | |
" Run go test in local directory with relative path | |
return ale#go#EnvString(a:buffer) | |
\ . ale#Var(a:buffer, 'go_go_executable') . ' test' | |
\ . (!empty(l:options) ? ' ' . l:options : '') | |
\ . ' -c -o /dev/null ./' | |
endfunction | |
2 0.000002 function! ale_linters#go#gobuild#GetMatches(lines) abort | |
" Matches patterns like the following: | |
" | |
" file.go:27: missing argument for Printf("%s"): format reads arg 2, have only 1 args | |
" file.go:53:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) | |
" file.go:5:2: expected declaration, found 'STRING' "log" | |
" go test returns relative paths so use tail of filename as part of pattern matcher | |
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? (.+)$' | |
return ale#util#GetMatches(a:lines, l:pattern) | |
endfunction | |
2 0.000002 function! ale_linters#go#gobuild#Handler(buffer, lines) abort | |
let l:dir = expand('#' . a:buffer . ':p:h') | |
let l:output = [] | |
for l:match in ale_linters#go#gobuild#GetMatches(a:lines) | |
call add(l:output, { | |
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), | |
\ 'lnum': l:match[2] + 0, | |
\ 'col': l:match[3] + 0, | |
\ 'text': l:match[4], | |
\ 'type': 'E', | |
\}) | |
endfor | |
return l:output | |
endfunction | |
2 0.000262 0.000028 call ale#linter#Define('go', { | |
\ 'name': 'gobuild', | |
\ 'aliases': ['go build'], | |
\ 'executable': {b -> ale#Var(b, 'go_go_executable')}, | |
\ 'cwd': '%s:h', | |
\ 'command': function('ale_linters#go#gobuild#GetCommand'), | |
\ 'output_stream': 'stderr', | |
\ 'callback': 'ale_linters#go#gobuild#Handler', | |
\ 'lint_file': 1, | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gofmt.vim | |
Sourced 2 times | |
Total time: 0.000332 | |
Self time: 0.000113 | |
count total (s) self (s) | |
" Author: neersighted <bjorn@neersighted.com> | |
" Description: gofmt for Go files | |
2 0.000006 function! ale_linters#go#gofmt#GetCommand(buffer) abort | |
return ale#go#EnvString(a:buffer) | |
\ . '%e -e %t' | |
endfunction | |
2 0.000240 0.000022 call ale#linter#Define('go', { | |
\ 'name': 'gofmt', | |
\ 'output_stream': 'stderr', | |
\ 'executable': 'gofmt', | |
\ 'command': function('ale_linters#go#gofmt#GetCommand'), | |
\ 'callback': 'ale#handlers#unix#HandleAsError', | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/golangci_lint.vim | |
Sourced 2 times | |
Total time: 0.000506 | |
Self time: 0.000167 | |
count total (s) self (s) | |
" Author: Sascha Grunert <mail@saschagrunert.de> | |
" Description: Adds support of golangci-lint | |
2 0.000046 0.000015 call ale#Set('go_golangci_lint_options', '--enable-all') | |
2 0.000012 0.000005 call ale#Set('go_golangci_lint_executable', 'golangci-lint') | |
2 0.000013 0.000004 call ale#Set('go_golangci_lint_package', 0) | |
2 0.000003 function! ale_linters#go#golangci_lint#GetCommand(buffer) abort | |
let l:filename = expand('#' . a:buffer . ':t') | |
let l:options = ale#Var(a:buffer, 'go_golangci_lint_options') | |
let l:lint_package = ale#Var(a:buffer, 'go_golangci_lint_package') | |
if l:lint_package | |
return ale#go#EnvString(a:buffer) | |
\ . '%e run ' | |
\ . l:options | |
endif | |
return ale#go#EnvString(a:buffer) | |
\ . '%e run ' | |
\ . ale#Escape(l:filename) | |
\ . ' ' . l:options | |
endfunction | |
2 0.000002 function! ale_linters#go#golangci_lint#GetMatches(lines) abort | |
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?:?\s\*?(.+)$' | |
return ale#util#GetMatches(a:lines, l:pattern) | |
endfunction | |
2 0.000002 function! ale_linters#go#golangci_lint#Handler(buffer, lines) abort | |
let l:dir = expand('#' . a:buffer . ':p:h') | |
let l:output = [] | |
for l:match in ale_linters#go#golangci_lint#GetMatches(a:lines) | |
" l:match[1] will already be an absolute path, output from | |
" golangci_lint | |
call add(l:output, { | |
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), | |
\ 'lnum': l:match[2] + 0, | |
\ 'col': l:match[3] + 0, | |
\ 'type': 'E', | |
\ 'text': l:match[4], | |
\}) | |
endfor | |
return l:output | |
endfunction | |
2 0.000319 0.000027 call ale#linter#Define('go', { | |
\ 'name': 'golangci-lint', | |
\ 'executable': {b -> ale#Var(b, 'go_golangci_lint_executable')}, | |
\ 'cwd': '%s:h', | |
\ 'command': function('ale_linters#go#golangci_lint#GetCommand'), | |
\ 'callback': 'ale_linters#go#golangci_lint#Handler', | |
\ 'lint_file': 1, | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/golint.vim | |
Sourced 2 times | |
Total time: 0.000500 | |
Self time: 0.000271 | |
count total (s) self (s) | |
" Author: neersighted <bjorn@neersighted.com> | |
" Description: golint for Go files | |
2 0.000182 0.000172 call ale#Set('go_golint_executable', 'golint') | |
2 0.000010 0.000004 call ale#Set('go_golint_options', '') | |
2 0.000003 function! ale_linters#go#golint#GetCommand(buffer) abort | |
let l:options = ale#Var(a:buffer, 'go_golint_options') | |
return ale#go#EnvString(a:buffer) . '%e' | |
\ . (!empty(l:options) ? ' ' . l:options : '') | |
\ . ' %t' | |
endfunction | |
2 0.000235 0.000021 call ale#linter#Define('go', { | |
\ 'name': 'golint', | |
\ 'output_stream': 'both', | |
\ 'executable': {b -> ale#Var(b, 'go_golint_executable')}, | |
\ 'command': function('ale_linters#go#golint#GetCommand'), | |
\ 'callback': 'ale#handlers#unix#HandleAsWarning', | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gometalinter.vim | |
Sourced 2 times | |
Total time: 0.000396 | |
Self time: 0.000133 | |
count total (s) self (s) | |
" Author: Ben Reedy <https://github.com/breed808>, Jeff Willette <jrwillette88@gmail.com> | |
" Description: Adds support for the gometalinter suite for Go files | |
2 0.000020 0.000010 call ale#Set('go_gometalinter_options', '') | |
2 0.000014 0.000007 call ale#Set('go_gometalinter_executable', 'gometalinter') | |
2 0.000010 0.000004 call ale#Set('go_gometalinter_lint_package', 0) | |
2 0.000003 function! ale_linters#go#gometalinter#GetCommand(buffer) abort | |
let l:filename = expand('#' . a:buffer . ':t') | |
let l:options = ale#Var(a:buffer, 'go_gometalinter_options') | |
let l:lint_package = ale#Var(a:buffer, 'go_gometalinter_lint_package') | |
" BufferCdString is used so that we can be sure the paths output from gometalinter can | |
" be calculated to absolute paths in the Handler | |
if l:lint_package | |
return ale#go#EnvString(a:buffer) | |
\ . '%e' | |
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .' | |
endif | |
return ale#go#EnvString(a:buffer) | |
\ . '%e' | |
\ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename)) | |
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .' | |
endfunction | |
2 0.000002 function! ale_linters#go#gometalinter#GetMatches(lines) abort | |
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?(warning|error):?\s\*?(.+)$' | |
return ale#util#GetMatches(a:lines, l:pattern) | |
endfunction | |
2 0.000002 function! ale_linters#go#gometalinter#Handler(buffer, lines) abort | |
let l:dir = expand('#' . a:buffer . ':p:h') | |
let l:output = [] | |
for l:match in ale_linters#go#gometalinter#GetMatches(a:lines) | |
" l:match[1] will already be an absolute path, output from gometalinter | |
call add(l:output, { | |
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), | |
\ 'lnum': l:match[2] + 0, | |
\ 'col': l:match[3] + 0, | |
\ 'type': tolower(l:match[4]) is# 'warning' ? 'W' : 'E', | |
\ 'text': l:match[5], | |
\}) | |
endfor | |
return l:output | |
endfunction | |
2 0.000263 0.000022 call ale#linter#Define('go', { | |
\ 'name': 'gometalinter', | |
\ 'executable': {b -> ale#Var(b, 'go_gometalinter_executable')}, | |
\ 'cwd': '%s:h', | |
\ 'command': function('ale_linters#go#gometalinter#GetCommand'), | |
\ 'callback': 'ale_linters#go#gometalinter#Handler', | |
\ 'lint_file': 1, | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gopls.vim | |
Sourced 2 times | |
Total time: 0.000408 | |
Self time: 0.000159 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Author: Jerko Steiner <https://github.com/jeremija> | |
" Description: https://github.com/saibing/gopls | |
2 0.000030 0.000021 call ale#Set('go_gopls_executable', 'gopls') | |
2 0.000011 0.000005 call ale#Set('go_gopls_options', '--mode stdio') | |
2 0.000010 0.000005 call ale#Set('go_gopls_init_options', {}) | |
2 0.000011 0.000005 call ale#Set('go_gopls_use_global', get(g:, 'ale_use_global_executables', 0)) | |
2 0.000002 function! ale_linters#go#gopls#GetCommand(buffer) abort | |
return ale#go#EnvString(a:buffer) | |
\ . '%e' | |
\ . ale#Pad(ale#Var(a:buffer, 'go_gopls_options')) | |
endfunction | |
2 0.000002 function! ale_linters#go#gopls#FindProjectRoot(buffer) abort | |
let l:go_modules_off = ale#Var(a:buffer, 'go_go111module') is# 'off' | |
let l:project_root = l:go_modules_off ? | |
\ '' : ale#path#FindNearestFile(a:buffer, 'go.mod') | |
let l:mods = ':h' | |
if empty(l:project_root) | |
let l:project_root = ale#path#FindNearestDirectory(a:buffer, '.git') | |
let l:mods = ':h:h' | |
endif | |
return !empty(l:project_root) ? fnamemodify(l:project_root, l:mods) : '' | |
endfunction | |
2 0.000253 0.000030 call ale#linter#Define('go', { | |
\ 'name': 'gopls', | |
\ 'lsp': 'stdio', | |
\ 'executable': {b -> ale#path#FindExecutable(b, 'go_gopls', [ | |
\ ale#go#GetGoPathExecutable('bin/gopls'), | |
\ ])}, | |
\ 'command': function('ale_linters#go#gopls#GetCommand'), | |
\ 'project_root': function('ale_linters#go#gopls#FindProjectRoot'), | |
\ 'initialization_options': {b -> ale#Var(b, 'go_gopls_init_options')}, | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gosimple.vim | |
Sourced 2 times | |
Total time: 0.000344 | |
Self time: 0.000119 | |
count total (s) self (s) | |
" Author: Ben Reedy <https://github.com/breed808> | |
" Description: gosimple for Go files | |
2 0.000276 0.000052 call ale#linter#Define('go', { | |
\ 'name': 'gosimple', | |
\ 'executable': 'gosimple', | |
\ 'cwd': '%s:h', | |
\ 'command': {b -> ale#go#EnvString(b) . 'gosimple .'}, | |
\ 'callback': 'ale#handlers#go#Handler', | |
\ 'output_stream': 'both', | |
\ 'lint_file': 1, | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gotype.vim | |
Sourced 2 times | |
Total time: 0.000341 | |
Self time: 0.000099 | |
count total (s) self (s) | |
" Author: Jelte Fennema <github-public@jeltef.nl> | |
" Description: gotype for Go files | |
2 0.000004 function! ale_linters#go#gotype#GetExecutable(buffer) abort | |
if expand('#' . a:buffer . ':p') =~# '_test\.go$' | |
return '' | |
endif | |
return 'gotype' | |
endfunction | |
2 0.000002 function! ale_linters#go#gotype#GetCommand(buffer) abort | |
return ale#go#EnvString(a:buffer) . 'gotype -e .' | |
endfunction | |
2 0.000266 0.000024 call ale#linter#Define('go', { | |
\ 'name': 'gotype', | |
\ 'output_stream': 'stderr', | |
\ 'executable': function('ale_linters#go#gotype#GetExecutable'), | |
\ 'cwd': '%s:h', | |
\ 'command': function('ale_linters#go#gotype#GetCommand'), | |
\ 'callback': 'ale#handlers#go#Handler', | |
\ 'lint_file': 1, | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/govet.vim | |
Sourced 2 times | |
Total time: 0.000329 | |
Self time: 0.000093 | |
count total (s) self (s) | |
" Author: neersighted <bjorn@neersighted.com> | |
" Description: go vet for Go files | |
" | |
" Author: John Eikenberry <jae@zhar.net> | |
" Description: updated to work with go1.10 | |
2 0.000019 0.000010 call ale#Set('go_go_executable', 'go') | |
2 0.000011 0.000004 call ale#Set('go_govet_options', '') | |
2 0.000003 function! ale_linters#go#govet#GetCommand(buffer) abort | |
let l:options = ale#Var(a:buffer, 'go_govet_options') | |
return ale#go#EnvString(a:buffer) | |
\ . ale#Var(a:buffer, 'go_go_executable') . ' vet ' | |
\ . (!empty(l:options) ? ' ' . l:options : '') | |
\ . ' .' | |
endfunction | |
2 0.000244 0.000025 call ale#linter#Define('go', { | |
\ 'name': 'govet', | |
\ 'aliases': ['go vet'], | |
\ 'output_stream': 'stderr', | |
\ 'executable': {b -> ale#Var(b, 'go_go_executable')}, | |
\ 'cwd': '%s:h', | |
\ 'command': function('ale_linters#go#govet#GetCommand'), | |
\ 'callback': 'ale#handlers#go#Handler', | |
\ 'lint_file': 1, | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/langserver.vim | |
Sourced 2 times | |
Total time: 0.000330 | |
Self time: 0.000098 | |
count total (s) self (s) | |
" Author: Horacio Sanson <https://github.com/hsanson> | |
" Description: Support for go-langserver https://github.com/sourcegraph/go-langserver | |
2 0.000017 0.000008 call ale#Set('go_langserver_executable', 'go-langserver') | |
2 0.000010 0.000004 call ale#Set('go_langserver_options', '') | |
2 0.000002 function! ale_linters#go#langserver#GetCommand(buffer) abort | |
let l:executable = [ale#Escape(ale#Var(a:buffer, 'go_langserver_executable'))] | |
let l:options = ale#Var(a:buffer, 'go_langserver_options') | |
let l:options = substitute(l:options, '-gocodecompletion', '', 'g') | |
let l:options = filter(split(l:options, ' '), 'empty(v:val) != 1') | |
if ale#Var(a:buffer, 'completion_enabled') | |
call add(l:options, '-gocodecompletion') | |
endif | |
let l:options = uniq(sort(l:options)) | |
let l:env = ale#go#EnvString(a:buffer) | |
return l:env . join(extend(l:executable, l:options), ' ') | |
endfunction | |
2 0.000238 0.000021 call ale#linter#Define('go', { | |
\ 'name': 'golangserver', | |
\ 'lsp': 'stdio', | |
\ 'executable': {b -> ale#Var(b, 'go_langserver_executable')}, | |
\ 'command': function('ale_linters#go#langserver#GetCommand'), | |
\ 'project_root': function('ale#go#FindProjectRoot'), | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/revive.vim | |
Sourced 2 times | |
Total time: 0.000356 | |
Self time: 0.000109 | |
count total (s) self (s) | |
" Author: Penghui Liao <liaoishere@gmail.com> | |
" Description: Adds support for revive | |
2 0.000020 0.000010 call ale#Set('go_revive_executable', 'revive') | |
2 0.000010 0.000004 call ale#Set('go_revive_options', '') | |
2 0.000003 function! ale_linters#go#revive#GetCommand(buffer) abort | |
let l:options = ale#Var(a:buffer, 'go_revive_options') | |
return ale#go#EnvString(a:buffer) . '%e' | |
\ . (!empty(l:options) ? ' ' . l:options : '') | |
\ . ' %t' | |
endfunction | |
2 0.000252 0.000021 call ale#linter#Define('go', { | |
\ 'name': 'revive', | |
\ 'output_stream': 'both', | |
\ 'executable': {b -> ale#Var(b, 'go_revive_executable')}, | |
\ 'command': function('ale_linters#go#revive#GetCommand'), | |
\ 'callback': 'ale#handlers#unix#HandleAsWarning', | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/staticcheck.vim | |
Sourced 2 times | |
Total time: 0.000379 | |
Self time: 0.000144 | |
count total (s) self (s) | |
" Author: Ben Reedy <https://github.com/breed808> | |
" Description: staticcheck for Go files | |
2 0.000025 0.000010 call ale#Set('go_staticcheck_executable', 'staticcheck') | |
2 0.000012 0.000006 call ale#Set('go_staticcheck_options', '') | |
2 0.000010 0.000004 call ale#Set('go_staticcheck_lint_package', 1) | |
2 0.000011 0.000006 call ale#Set('go_staticcheck_use_global', get(g:, 'ale_use_global_executables', 0)) | |
2 0.000002 function! ale_linters#go#staticcheck#GetCommand(buffer) abort | |
let l:options = ale#Var(a:buffer, 'go_staticcheck_options') | |
let l:lint_package = ale#Var(a:buffer, 'go_staticcheck_lint_package') | |
let l:env = ale#go#EnvString(a:buffer) | |
if l:lint_package | |
return l:env . '%e' | |
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .' | |
endif | |
return l:env . '%e' | |
\ . (!empty(l:options) ? ' ' . l:options : '') | |
\ . ' %s:t' | |
endfunction | |
2 0.000228 0.000025 call ale#linter#Define('go', { | |
\ 'name': 'staticcheck', | |
\ 'executable': {b -> ale#path#FindExecutable(b, 'go_staticcheck', [ | |
\ ale#go#GetGoPathExecutable('bin/staticcheck'), | |
\ ])}, | |
\ 'cwd': '%s:h', | |
\ 'command': function('ale_linters#go#staticcheck#GetCommand'), | |
\ 'callback': 'ale#handlers#go#Handler', | |
\ 'output_stream': 'both', | |
\ 'lint_file': 1, | |
\}) | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim | |
Sourced 1 time | |
Total time: 0.000612 | |
Self time: 0.000612 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Backend execution and job management | |
" Executes linters in the background, using NeoVim or Vim 8 jobs | |
" Remapping of linter problems. | |
1 0.000003 let g:ale_type_map = get(g:, 'ale_type_map', {}) | |
1 0.000003 let g:ale_filename_mappings = get(g:, 'ale_filename_mappings', {}) | |
1 0.000001 if !has_key(s:, 'executable_cache_map') | |
1 0.000001 let s:executable_cache_map = {} | |
1 0.000000 endif | |
1 0.000001 function! ale#engine#CleanupEveryBuffer() abort | |
for l:key in keys(g:ale_buffer_info) | |
" The key could be a filename or a buffer number, so try and | |
" convert it to a number. We need a number for the other | |
" functions. | |
let l:buffer = str2nr(l:key) | |
if l:buffer > 0 | |
" Stop all jobs and clear the results for everything, and delete | |
" all of the data we stored for the buffer. | |
call ale#engine#Cleanup(l:buffer) | |
endif | |
endfor | |
endfunction | |
1 0.000001 function! ale#engine#MarkLinterActive(info, linter) abort | |
let l:found = 0 | |
for l:other_linter in a:info.active_linter_list | |
if l:other_linter.name is# a:linter.name | |
let l:found = 1 | |
break | |
endif | |
endfor | |
if !l:found | |
call add(a:info.active_linter_list, a:linter) | |
endif | |
endfunction | |
1 0.000001 function! ale#engine#MarkLinterInactive(info, linter_name) abort | |
call filter(a:info.active_linter_list, 'v:val.name isnot# a:linter_name') | |
endfunction | |
1 0.000001 function! ale#engine#ResetExecutableCache() abort | |
let s:executable_cache_map = {} | |
endfunction | |
" Check if files are executable, and if they are, remember that they are | |
" for subsequent calls. We'll keep checking until programs can be executed. | |
1 0.000001 function! ale#engine#IsExecutable(buffer, executable) abort | |
if empty(a:executable) | |
" Don't log the executable check if the executable string is empty. | |
return 0 | |
endif | |
" Check for a cached executable() check. | |
let l:result = get(s:executable_cache_map, a:executable, v:null) | |
if l:result isnot v:null | |
return l:result | |
endif | |
" Check if the file is executable, and convert -1 to 1. | |
let l:result = executable(a:executable) isnot 0 | |
" Cache the executable check if we found it, or if the option to cache | |
" failing checks is on. | |
if l:result || get(g:, 'ale_cache_executable_check_failures', 0) | |
let s:executable_cache_map[a:executable] = l:result | |
endif | |
if g:ale_history_enabled | |
call ale#history#Add(a:buffer, l:result, 'executable', a:executable) | |
endif | |
return l:result | |
endfunction | |
1 0.000001 function! ale#engine#InitBufferInfo(buffer) abort | |
if !has_key(g:ale_buffer_info, a:buffer) | |
" active_linter_list will hold the list of active linter names | |
" loclist holds the loclist items after all jobs have completed. | |
let g:ale_buffer_info[a:buffer] = { | |
\ 'active_linter_list': [], | |
\ 'active_other_sources_list': [], | |
\ 'loclist': [], | |
\} | |
return 1 | |
endif | |
return 0 | |
endfunction | |
" This function is documented and part of the public API. | |
" | |
" Return 1 if ALE is busy checking a given buffer | |
1 0.000001 function! ale#engine#IsCheckingBuffer(buffer) abort | |
let l:info = get(g:ale_buffer_info, a:buffer, {}) | |
return !empty(get(l:info, 'active_linter_list', [])) | |
\ || !empty(get(l:info, 'active_other_sources_list', [])) | |
endfunction | |
1 0.000001 function! ale#engine#HandleLoclist(linter_name, buffer, loclist, from_other_source) abort | |
let l:info = get(g:ale_buffer_info, a:buffer, {}) | |
if empty(l:info) | |
return | |
endif | |
if !a:from_other_source | |
" Remove this linter from the list of active linters. | |
" This may have already been done when the job exits. | |
call filter(l:info.active_linter_list, 'v:val.name isnot# a:linter_name') | |
endif | |
" Make some adjustments to the loclists to fix common problems, and also | |
" to set default values for loclist items. | |
let l:linter_loclist = ale#engine#FixLocList( | |
\ a:buffer, | |
\ a:linter_name, | |
\ a:from_other_source, | |
\ a:loclist, | |
\) | |
" Remove previous items for this linter. | |
call filter(l:info.loclist, 'v:val.linter_name isnot# a:linter_name') | |
" We don't need to add items or sort the list when this list is empty. | |
if !empty(l:linter_loclist) | |
" Add the new items. | |
call extend(l:info.loclist, l:linter_loclist) | |
" Sort the loclist again. | |
" We need a sorted list so we can run a binary search against it | |
" for efficient lookup of the messages in the cursor handler. | |
call sort(l:info.loclist, 'ale#util#LocItemCompare') | |
endif | |
if ale#ShouldDoNothing(a:buffer) | |
return | |
endif | |
call ale#engine#SetResults(a:buffer, l:info.loclist) | |
endfunction | |
1 0.000001 function! s:HandleExit(job_info, buffer, output, data) abort | |
let l:buffer_info = get(g:ale_buffer_info, a:buffer) | |
if empty(l:buffer_info) | |
return | |
endif | |
let l:linter = a:job_info.linter | |
let l:executable = a:job_info.executable | |
" Remove this job from the list. | |
call ale#engine#MarkLinterInactive(l:buffer_info, l:linter.name) | |
" Stop here if we land in the handle for a job completing if we're in | |
" a sandbox. | |
if ale#util#InSandbox() | |
return | |
endif | |
if has('nvim') && !empty(a:output) && empty(a:output[-1]) | |
call remove(a:output, -1) | |
endif | |
try | |
let l:loclist = ale#util#GetFunction(l:linter.callback)(a:buffer, a:output) | |
" Handle the function being unknown, or being deleted. | |
catch /E700/ | |
let l:loclist = [] | |
endtry | |
call ale#engine#HandleLoclist(l:linter.name, a:buffer, l:loclist, 0) | |
endfunction | |
1 0.000001 function! ale#engine#SetResults(buffer, loclist) abort | |
let l:linting_is_done = !ale#engine#IsCheckingBuffer(a:buffer) | |
" Set signs first. This could potentially fix some line numbers. | |
" The List could be sorted again here by SetSigns. | |
if g:ale_set_signs | |
call ale#sign#SetSigns(a:buffer, a:loclist) | |
endif | |
if g:ale_set_quickfix || g:ale_set_loclist | |
call ale#list#SetLists(a:buffer, a:loclist) | |
endif | |
if exists('*ale#statusline#Update') | |
" Don't load/run if not already loaded. | |
call ale#statusline#Update(a:buffer, a:loclist) | |
endif | |
if g:ale_set_highlights | |
call ale#highlight#SetHighlights(a:buffer, a:loclist) | |
endif | |
if l:linting_is_done | |
if g:ale_echo_cursor | |
" Try and echo the warning now. | |
" This will only do something meaningful if we're in normal mode. | |
call ale#cursor#EchoCursorWarning() | |
endif | |
if g:ale_virtualtext_cursor | |
" Try and show the warning now. | |
" This will only do something meaningful if we're in normal mode. | |
call ale#virtualtext#ShowCursorWarning() | |
endif | |
" Reset the save event marker, used for opening windows, etc. | |
call setbufvar(a:buffer, 'ale_save_event_fired', 0) | |
" Set a marker showing how many times a buffer has been checked. | |
call setbufvar( | |
\ a:buffer, | |
\ 'ale_linted', | |
\ getbufvar(a:buffer, 'ale_linted', 0) + 1 | |
\) | |
" Automatically remove all managed temporary files and directories | |
" now that all jobs have completed. | |
call ale#command#RemoveManagedFiles(a:buffer) | |
" Call user autocommands. This allows users to hook into ALE's lint cycle. | |
silent doautocmd <nomodeline> User ALELintPost | |
endif | |
endfunction | |
1 0.000001 function! s:RemapItemTypes(type_map, loclist) abort | |
for l:item in a:loclist | |
let l:key = l:item.type | |
\ . (get(l:item, 'sub_type', '') is# 'style' ? 'S' : '') | |
let l:new_key = get(a:type_map, l:key, '') | |
if l:new_key is# 'E' | |
\|| l:new_key is# 'ES' | |
\|| l:new_key is# 'W' | |
\|| l:new_key is# 'WS' | |
\|| l:new_key is# 'I' | |
let l:item.type = l:new_key[0] | |
if l:new_key is# 'ES' || l:new_key is# 'WS' | |
let l:item.sub_type = 'style' | |
elseif has_key(l:item, 'sub_type') | |
call remove(l:item, 'sub_type') | |
endif | |
endif | |
endfor | |
endfunction | |
1 0.000001 function! ale#engine#FixLocList(buffer, linter_name, from_other_source, loclist) abort | |
let l:mappings = ale#GetFilenameMappings(a:buffer, a:linter_name) | |
if !empty(l:mappings) | |
" We need to apply reverse filename mapping here. | |
let l:mappings = ale#filename_mapping#Invert(l:mappings) | |
endif | |
let l:bufnr_map = {} | |
let l:new_loclist = [] | |
" Some errors have line numbers beyond the end of the file, | |
" so we need to adjust them so they set the error at the last line | |
" of the file instead. | |
let l:last_line_number = ale#util#GetLineCount(a:buffer) | |
for l:old_item in a:loclist | |
" Copy the loclist item with some default values and corrections. | |
" | |
" line and column numbers will be converted to numbers. | |
" The buffer will default to the buffer being checked. | |
" The vcol setting will default to 0, a byte index. | |
" The error type will default to 'E' for errors. | |
" The error number will default to -1. | |
" | |
" The line number and text are the only required keys. | |
" | |
" The linter_name will be set on the errors so it can be used in | |
" output, filtering, etc.. | |
let l:item = { | |
\ 'bufnr': a:buffer, | |
\ 'text': l:old_item.text, | |
\ 'lnum': str2nr(l:old_item.lnum), | |
\ 'col': str2nr(get(l:old_item, 'col', 0)), | |
\ 'vcol': 0, | |
\ 'type': get(l:old_item, 'type', 'E'), | |
\ 'nr': get(l:old_item, 'nr', -1), | |
\ 'linter_name': a:linter_name, | |
\} | |
if a:from_other_source | |
let l:item.from_other_source = 1 | |
endif | |
if has_key(l:old_item, 'code') | |
let l:item.code = l:old_item.code | |
endif | |
let l:old_name = get(l:old_item, 'filename', '') | |
" Map parsed from output to local filesystem files. | |
if !empty(l:old_name) && !empty(l:mappings) | |
let l:old_name = ale#filename_mapping#Map(l:old_name, l:mappings) | |
endif | |
if !empty(l:old_name) && !ale#path#IsTempName(l:old_name) | |
" Use the filename given. | |
" Temporary files are assumed to be for this buffer, | |
" and the filename is not included then, because it looks bad | |
" in the loclist window. | |
let l:filename = l:old_name | |
let l:item.filename = l:filename | |
if has_key(l:old_item, 'bufnr') | |
" If a buffer number is also given, include that too. | |
" If Vim detects that he buffer number is valid, it will | |
" be used instead of the filename. | |
let l:item.bufnr = l:old_item.bufnr | |
elseif has_key(l:bufnr_map, l:filename) | |
" Get the buffer number from the map, which can be faster. | |
let l:item.bufnr = l:bufnr_map[l:filename] | |
else | |
" Look up the buffer number. | |
let l:item.bufnr = bufnr(l:filename) | |
let l:bufnr_map[l:filename] = l:item.bufnr | |
endif | |
elseif has_key(l:old_item, 'bufnr') | |
let l:item.bufnr = l:old_item.bufnr | |
endif | |
if has_key(l:old_item, 'detail') | |
let l:item.detail = l:old_item.detail | |
endif | |
" Pass on a end_col key if set, used for highlights. | |
if has_key(l:old_item, 'end_col') | |
let l:item.end_col = str2nr(l:old_item.end_col) | |
endif | |
if has_key(l:old_item, 'end_lnum') | |
let l:item.end_lnum = str2nr(l:old_item.end_lnum) | |
endif | |
if has_key(l:old_item, 'sub_type') | |
let l:item.sub_type = l:old_item.sub_type | |
endif | |
if l:item.lnum < 1 | |
" When errors appear before line 1, put them at line 1. | |
let l:item.lnum = 1 | |
elseif l:item.bufnr == a:buffer && l:item.lnum > l:last_line_number | |
" When errors go beyond the end of the file, put them at the end. | |
" This is only done for the current buffer. | |
let l:item.lnum = l:last_line_number | |
elseif get(l:old_item, 'vcol', 0) | |
" Convert virtual column positions to byte positions. | |
" The positions will be off if the buffer has changed recently. | |
let l:line = getbufline(a:buffer, l:item.lnum)[0] | |
let l:item.col = ale#util#Col(l:line, l:item.col) | |
if has_key(l:item, 'end_col') | |
let l:end_line = get(l:item, 'end_lnum', l:line) != l:line | |
\ ? getbufline(a:buffer, l:item.end_lnum)[0] | |
\ : l:line | |
let l:item.end_col = ale#util#Col(l:end_line, l:item.end_col) | |
endif | |
endif | |
call add(l:new_loclist, l:item) | |
endfor | |
let l:type_map = get(ale#Var(a:buffer, 'type_map'), a:linter_name, {}) | |
if !empty(l:type_map) | |
call s:RemapItemTypes(l:type_map, l:new_loclist) | |
endif | |
return l:new_loclist | |
endfunction | |
" Given part of a command, replace any % with %%, so that no characters in | |
" the string will be replaced with filenames, etc. | |
1 0.000001 function! ale#engine#EscapeCommandPart(command_part) abort | |
" TODO: Emit deprecation warning here later. | |
return ale#command#EscapeCommandPart(a:command_part) | |
endfunction | |
" Run a job. | |
" | |
" Returns 1 when a job was started successfully. | |
1 0.000001 function! s:RunJob(command, options) abort | |
if ale#command#IsDeferred(a:command) | |
let a:command.result_callback = { | |
\ command -> s:RunJob(command, a:options) | |
\} | |
return 1 | |
endif | |
let l:command = a:command | |
if empty(l:command) | |
return 0 | |
endif | |
let l:cwd = a:options.cwd | |
let l:executable = a:options.executable | |
let l:buffer = a:options.buffer | |
let l:linter = a:options.linter | |
let l:output_stream = a:options.output_stream | |
let l:read_buffer = a:options.read_buffer && !a:options.lint_file | |
let l:info = g:ale_buffer_info[l:buffer] | |
let l:Callback = function('s:HandleExit', [{ | |
\ 'linter': l:linter, | |
\ 'executable': l:executable, | |
\}]) | |
let l:result = ale#command#Run(l:buffer, l:command, l:Callback, { | |
\ 'cwd': l:cwd, | |
\ 'output_stream': l:output_stream, | |
\ 'executable': l:executable, | |
\ 'read_buffer': l:read_buffer, | |
\ 'log_output': 1, | |
\ 'filename_mappings': ale#GetFilenameMappings(l:buffer, l:linter.name), | |
\}) | |
" Only proceed if the job is being run. | |
if empty(l:result) | |
return 0 | |
endif | |
call ale#engine#MarkLinterActive(l:info, l:linter) | |
silent doautocmd <nomodeline> User ALEJobStarted | |
return 1 | |
endfunction | |
1 0.000001 function! s:StopCurrentJobs(buffer, clear_lint_file_jobs, linter_slots) abort | |
let l:info = get(g:ale_buffer_info, a:buffer, {}) | |
call ale#command#StopJobs(a:buffer, 'linter') | |
" Update the active linter list, clearing out anything not running. | |
if a:clear_lint_file_jobs | |
call ale#command#StopJobs(a:buffer, 'file_linter') | |
let l:info.active_linter_list = [] | |
else | |
let l:lint_file_map = {} | |
" Use a previously computed map of `lint_file` values to find | |
" linters that are used for linting files. | |
for [l:lint_file, l:linter] in a:linter_slots | |
if l:lint_file is 1 | |
let l:lint_file_map[l:linter.name] = 1 | |
endif | |
endfor | |
" Keep jobs for linting files when we're only linting buffers. | |
call filter(l:info.active_linter_list, 'get(l:lint_file_map, v:val.name)') | |
endif | |
endfunction | |
1 0.000001 function! ale#engine#Stop(buffer) abort | |
call s:StopCurrentJobs(a:buffer, 1, []) | |
endfunction | |
1 0.000001 function! s:RemoveProblemsForDisabledLinters(buffer, linters) abort | |
" Figure out which linters are still enabled, and remove | |
" problems for linters which are no longer enabled. | |
" Problems from other sources will be kept. | |
let l:name_map = {} | |
for l:linter in a:linters | |
let l:name_map[l:linter.name] = 1 | |
endfor | |
call filter( | |
\ get(g:ale_buffer_info[a:buffer], 'loclist', []), | |
\ 'get(v:val, ''from_other_source'') || get(l:name_map, get(v:val, ''linter_name''))', | |
\) | |
endfunction | |
1 0.000114 function! s:AddProblemsFromOtherBuffers(buffer, linters) abort | |
let l:filename = expand('#' . a:buffer . ':p') | |
let l:loclist = [] | |
let l:name_map = {} | |
" Build a map of the active linters. | |
for l:linter in a:linters | |
let l:name_map[l:linter.name] = 1 | |
endfor | |
" Find the items from other buffers, for the linters that are enabled. | |
for l:info in values(g:ale_buffer_info) | |
for l:item in l:info.loclist | |
if has_key(l:item, 'filename') | |
\&& l:item.filename is# l:filename | |
\&& has_key(l:name_map, l:item.linter_name) | |
" Copy the items and set the buffer numbers to this one. | |
let l:new_item = copy(l:item) | |
let l:new_item.bufnr = a:buffer | |
call add(l:loclist, l:new_item) | |
endif | |
endfor | |
endfor | |
if !empty(l:loclist) | |
call sort(l:loclist, function('ale#util#LocItemCompareWithText')) | |
call uniq(l:loclist, function('ale#util#LocItemCompareWithText')) | |
" Set the loclist variable, used by some parts of ALE. | |
let g:ale_buffer_info[a:buffer].loclist = l:loclist | |
call ale#engine#SetResults(a:buffer, l:loclist) | |
endif | |
endfunction | |
1 0.000001 function! s:RunIfExecutable(buffer, linter, lint_file, executable) abort | |
if ale#command#IsDeferred(a:executable) | |
let a:executable.result_callback = { | |
\ executable -> s:RunIfExecutable( | |
\ a:buffer, | |
\ a:linter, | |
\ a:lint_file, | |
\ executable | |
\ ) | |
\} | |
return 1 | |
endif | |
if ale#engine#IsExecutable(a:buffer, a:executable) | |
" Use different job types for file or linter jobs. | |
let l:job_type = a:lint_file ? 'file_linter' : 'linter' | |
call setbufvar(a:buffer, 'ale_job_type', l:job_type) | |
" Get the cwd for the linter and set it before we call GetCommand. | |
" This will ensure that ale#command#Run uses it by default. | |
let l:cwd = ale#linter#GetCwd(a:buffer, a:linter) | |
if l:cwd isnot v:null | |
call ale#command#SetCwd(a:buffer, l:cwd) | |
endif | |
let l:command = ale#linter#GetCommand(a:buffer, a:linter) | |
if l:cwd isnot v:null | |
call ale#command#ResetCwd(a:buffer) | |
endif | |
let l:options = { | |
\ 'cwd': l:cwd, | |
\ 'executable': a:executable, | |
\ 'buffer': a:buffer, | |
\ 'linter': a:linter, | |
\ 'output_stream': get(a:linter, 'output_stream', 'stdout'), | |
\ 'read_buffer': a:linter.read_buffer, | |
\ 'lint_file': a:lint_file, | |
\} | |
return s:RunJob(l:command, l:options) | |
endif | |
return 0 | |
endfunction | |
" Run a linter for a buffer. | |
" | |
" Returns 1 if the linter was successfully run. | |
1 0.000001 function! s:RunLinter(buffer, linter, lint_file) abort | |
if !empty(a:linter.lsp) | |
return ale#lsp_linter#CheckWithLSP(a:buffer, a:linter) | |
else | |
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) | |
return s:RunIfExecutable(a:buffer, a:linter, a:lint_file, l:executable) | |
endif | |
return 0 | |
endfunction | |
1 0.000001 function! s:GetLintFileSlots(buffer, linters) abort | |
let l:linter_slots = [] | |
for l:linter in a:linters | |
let l:LintFile = l:linter.lint_file | |
if type(l:LintFile) is v:t_func | |
let l:LintFile = l:LintFile(a:buffer) | |
endif | |
call add(l:linter_slots, [l:LintFile, l:linter]) | |
endfor | |
return l:linter_slots | |
endfunction | |
1 0.000001 function! s:GetLintFileValues(slots, Callback) abort | |
let l:deferred_list = [] | |
let l:new_slots = [] | |
for [l:lint_file, l:linter] in a:slots | |
while ale#command#IsDeferred(l:lint_file) && has_key(l:lint_file, 'value') | |
" If we've already computed the return value, use it. | |
let l:lint_file = l:lint_file.value | |
endwhile | |
if ale#command#IsDeferred(l:lint_file) | |
" If we are going to return the result later, wait for it. | |
call add(l:deferred_list, l:lint_file) | |
else | |
" If we have the value now, coerce it to 0 or 1. | |
let l:lint_file = l:lint_file is 1 | |
endif | |
call add(l:new_slots, [l:lint_file, l:linter]) | |
endfor | |
if !empty(l:deferred_list) | |
for l:deferred in l:deferred_list | |
let l:deferred.result_callback = | |
\ {-> s:GetLintFileValues(l:new_slots, a:Callback)} | |
endfor | |
else | |
call a:Callback(l:new_slots) | |
endif | |
endfunction | |
1 0.000002 function! s:RunLinters( | |
\ buffer, | |
\ linters, | |
\ slots, | |
\ should_lint_file, | |
\ new_buffer, | |
\) abort | |
call s:StopCurrentJobs(a:buffer, a:should_lint_file, a:slots) | |
call s:RemoveProblemsForDisabledLinters(a:buffer, a:linters) | |
" We can only clear the results if we aren't checking the buffer. | |
let l:can_clear_results = !ale#engine#IsCheckingBuffer(a:buffer) | |
silent doautocmd <nomodeline> User ALELintPre | |
for [l:lint_file, l:linter] in a:slots | |
" Only run lint_file linters if we should. | |
if !l:lint_file || a:should_lint_file | |
if s:RunLinter(a:buffer, l:linter, l:lint_file) | |
" If a single linter ran, we shouldn't clear everything. | |
let l:can_clear_results = 0 | |
endif | |
else | |
" If we skipped running a lint_file linter still in the list, | |
" we shouldn't clear everything. | |
let l:can_clear_results = 0 | |
endif | |
endfor | |
" Clear the results if we can. This needs to be done when linters are | |
" disabled, or ALE itself is disabled. | |
if l:can_clear_results | |
call ale#engine#SetResults(a:buffer, []) | |
elseif a:new_buffer | |
call s:AddProblemsFromOtherBuffers( | |
\ a:buffer, | |
\ map(copy(a:slots), 'v:val[1]') | |
\) | |
endif | |
endfunction | |
1 0.000001 function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort | |
" Initialise the buffer information if needed. | |
let l:new_buffer = ale#engine#InitBufferInfo(a:buffer) | |
call s:GetLintFileValues( | |
\ s:GetLintFileSlots(a:buffer, a:linters), | |
\ { | |
\ slots -> s:RunLinters( | |
\ a:buffer, | |
\ a:linters, | |
\ slots, | |
\ a:should_lint_file, | |
\ l:new_buffer, | |
\ ) | |
\ } | |
\) | |
endfunction | |
" Clean up a buffer. | |
" | |
" This function will stop all current jobs for the buffer, | |
" clear the state of everything, and remove the Dictionary for managing | |
" the buffer. | |
1 0.000001 function! ale#engine#Cleanup(buffer) abort | |
" Don't bother with cleanup code when newer NeoVim versions are exiting. | |
if get(v:, 'exiting', v:null) isnot v:null | |
return | |
endif | |
if exists('*ale#lsp#CloseDocument') | |
call ale#lsp#CloseDocument(a:buffer) | |
endif | |
if !has_key(g:ale_buffer_info, a:buffer) | |
return | |
endif | |
call ale#engine#RunLinters(a:buffer, [], 1) | |
call remove(g:ale_buffer_info, a:buffer) | |
endfunction | |
" Given a buffer number, return the warnings and errors for a given buffer. | |
1 0.000001 function! ale#engine#GetLoclist(buffer) abort | |
if !has_key(g:ale_buffer_info, a:buffer) | |
return [] | |
endif | |
return g:ale_buffer_info[a:buffer].loclist | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/command.vim | |
Sourced 1 time | |
Total time: 0.000283 | |
Self time: 0.000283 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Functions for formatting command strings, running commands, and | |
" managing files during linting and fixing cycles. | |
" This dictionary holds lists of files and directories to remove later. | |
1 0.000002 if !exists('s:buffer_data') | |
1 0.000001 let s:buffer_data = {} | |
1 0.000000 endif | |
" The regular expression used for formatting filenames with modifiers. | |
1 0.000001 let s:path_format_regex = '\v\%s(%(:h|:t|:r|:e)*)' | |
" Used to get the data in tests. | |
1 0.000001 function! ale#command#GetData() abort | |
return deepcopy(s:buffer_data) | |
endfunction | |
1 0.000001 function! ale#command#ClearData() abort | |
let s:buffer_data = {} | |
endfunction | |
1 0.000001 function! ale#command#InitData(buffer) abort | |
if !has_key(s:buffer_data, a:buffer) | |
let s:buffer_data[a:buffer] = { | |
\ 'jobs': {}, | |
\ 'file_list': [], | |
\ 'directory_list': [], | |
\} | |
endif | |
endfunction | |
" Set the cwd for commands that are about to run. | |
" Used internally. | |
1 0.000001 function! ale#command#SetCwd(buffer, cwd) abort | |
call ale#command#InitData(a:buffer) | |
let s:buffer_data[a:buffer].cwd = a:cwd | |
endfunction | |
1 0.000000 function! ale#command#ResetCwd(buffer) abort | |
if has_key(s:buffer_data, a:buffer) | |
let s:buffer_data[a:buffer].cwd = v:null | |
endif | |
endfunction | |
1 0.000001 function! ale#command#ManageFile(buffer, file) abort | |
call ale#command#InitData(a:buffer) | |
call add(s:buffer_data[a:buffer].file_list, a:file) | |
endfunction | |
1 0.000001 function! ale#command#ManageDirectory(buffer, directory) abort | |
call ale#command#InitData(a:buffer) | |
call add(s:buffer_data[a:buffer].directory_list, a:directory) | |
endfunction | |
1 0.000001 function! ale#command#CreateFile(buffer) abort | |
" This variable can be set to 1 in tests to stub this out. | |
if get(g:, 'ale_create_dummy_temporary_file') | |
return 'TEMP' | |
endif | |
let l:temporary_file = ale#util#Tempname() | |
call ale#command#ManageFile(a:buffer, l:temporary_file) | |
return l:temporary_file | |
endfunction | |
" Create a new temporary directory and manage it in one go. | |
1 0.000001 function! ale#command#CreateDirectory(buffer) abort | |
" This variable can be set to 1 in tests to stub this out. | |
if get(g:, 'ale_create_dummy_temporary_file') | |
return 'TEMP_DIR' | |
endif | |
let l:temporary_directory = ale#util#Tempname() | |
" Create the temporary directory for the file, unreadable by 'other' | |
" users. | |
call mkdir(l:temporary_directory, '', 0750) | |
call ale#command#ManageDirectory(a:buffer, l:temporary_directory) | |
return l:temporary_directory | |
endfunction | |
1 0.000001 function! ale#command#RemoveManagedFiles(buffer) abort | |
let l:info = get(s:buffer_data, a:buffer, {}) | |
if !empty(l:info) && empty(l:info.jobs) | |
" We can't delete anything in a sandbox, so wait until we escape from | |
" it to delete temporary files and directories. | |
if ale#util#InSandbox() | |
return | |
endif | |
" Delete files with a call akin to a plan `rm` command. | |
for l:filename in l:info.file_list | |
call delete(l:filename) | |
endfor | |
" Delete directories like `rm -rf`. | |
" Directories are handled differently from files, so paths that are | |
" intended to be single files can be set up for automatic deletion | |
" without accidentally deleting entire directories. | |
for l:directory in l:info.directory_list | |
call delete(l:directory, 'rf') | |
endfor | |
call remove(s:buffer_data, a:buffer) | |
endif | |
endfunction | |
1 0.000001 function! ale#command#CreateTempFile(buffer, temporary_file, input) abort | |
if empty(a:temporary_file) | |
" There is no file, so we didn't create anything. | |
return 0 | |
endif | |
" Use an existing list of lines of input if we have it, or get the lines | |
" from the file. | |
let l:lines = a:input isnot v:null ? a:input : getbufline(a:buffer, 1, '$') | |
let l:temporary_directory = fnamemodify(a:temporary_file, ':h') | |
" Create the temporary directory for the file, unreadable by 'other' | |
" users. | |
call mkdir(l:temporary_directory, '', 0750) | |
" Automatically delete the directory later. | |
call ale#command#ManageDirectory(a:buffer, l:temporary_directory) | |
" Write the buffer out to a file. | |
call ale#util#Writefile(a:buffer, l:lines, a:temporary_file) | |
return 1 | |
endfunction | |
1 0.000001 function! s:TemporaryFilename(buffer) abort | |
let l:filename = fnamemodify(bufname(a:buffer), ':t') | |
if empty(l:filename) | |
" If the buffer's filename is empty, create a dummy filename. | |
let l:ft = getbufvar(a:buffer, '&filetype') | |
let l:filename = 'file' . ale#filetypes#GuessExtension(l:ft) | |
endif | |
" Create a temporary filename, <temp_dir>/<original_basename> | |
" The file itself will not be created by this function. | |
return ale#util#Tempname() . (has('win32') ? '\' : '/') . l:filename | |
endfunction | |
" Given part of a command, replace any % with %%, so that no characters in | |
" the string will be replaced with filenames, etc. | |
1 0.000001 function! ale#command#EscapeCommandPart(command_part) abort | |
return substitute(a:command_part, '%', '%%', 'g') | |
endfunction | |
" Format a filename, converting it with filename mappings, if non-empty, | |
" and escaping it for putting into a command string. | |
" | |
" The filename can be modified. | |
1 0.000001 function! s:FormatFilename(filename, mappings, modifiers) abort | |
let l:filename = a:filename | |
if !empty(a:mappings) | |
let l:filename = ale#filename_mapping#Map(l:filename, a:mappings) | |
endif | |
if !empty(a:modifiers) | |
let l:filename = fnamemodify(l:filename, a:modifiers) | |
endif | |
return ale#Escape(l:filename) | |
endfunction | |
" Produce a command prefix to check to a particular directory for a command. | |
" %s format markers with filename-modifiers can be used as the directory, and | |
" will be returned verbatim for formatting in paths relative to files. | |
1 0.000001 function! ale#command#CdString(directory) abort | |
let l:match = matchstrpos(a:directory, s:path_format_regex) | |
" Do not escape the directory here if it's a valid format string. | |
" This allows us to use sequences like %s:h, %s:h:h, etc. | |
let l:directory = l:match[1:] == [0, len(a:directory)] | |
\ ? a:directory | |
\ : ale#Escape(a:directory) | |
if has('win32') | |
return 'cd /d ' . l:directory . ' && ' | |
endif | |
return 'cd ' . l:directory . ' && ' | |
endfunction | |
" Given a command string, replace every... | |
" %s -> with the current filename | |
" %t -> with the name of an unused file in a temporary directory | |
" %% -> with a literal % | |
1 0.000003 function! ale#command#FormatCommand( | |
\ buffer, | |
\ executable, | |
\ command, | |
\ pipe_file_if_needed, | |
\ input, | |
\ cwd, | |
\ mappings, | |
\) abort | |
let l:temporary_file = '' | |
let l:command = a:command | |
if !empty(a:cwd) | |
let l:command = ale#command#CdString(a:cwd) . l:command | |
endif | |
" First replace all uses of %%, used for literal percent characters, | |
" with an ugly string. | |
let l:command = substitute(l:command, '%%', '<<PERCENTS>>', 'g') | |
" Replace %e with the escaped executable, if available. | |
if !empty(a:executable) && l:command =~# '%e' | |
let l:command = substitute(l:command, '%e', '\=ale#Escape(a:executable)', 'g') | |
endif | |
" Replace all %s occurrences in the string with the name of the current | |
" file. | |
if l:command =~# '%s' | |
let l:filename = fnamemodify(bufname(a:buffer), ':p') | |
let l:command = substitute( | |
\ l:command, | |
\ s:path_format_regex, | |
\ '\=s:FormatFilename(l:filename, a:mappings, submatch(1))', | |
\ 'g' | |
\) | |
endif | |
if a:input isnot v:false && l:command =~# '%t' | |
" Create a temporary filename, <temp_dir>/<original_basename> | |
" The file itself will not be created by this function. | |
let l:temporary_file = s:TemporaryFilename(a:buffer) | |
let l:command = substitute( | |
\ l:command, | |
\ '\v\%t(%(:h|:t|:r|:e)*)', | |
\ '\=s:FormatFilename(l:temporary_file, a:mappings, submatch(1))', | |
\ 'g' | |
\) | |
endif | |
" Finish formatting so %% becomes %. | |
let l:command = substitute(l:command, '<<PERCENTS>>', '%', 'g') | |
if a:pipe_file_if_needed && empty(l:temporary_file) | |
" If we are to send the Vim buffer to a command, we'll do it | |
" in the shell. We'll write out the file to a temporary file, | |
" and then read it back in, in the shell. | |
let l:temporary_file = s:TemporaryFilename(a:buffer) | |
let l:command = l:command . ' < ' . ale#Escape(l:temporary_file) | |
endif | |
let l:file_created = ale#command#CreateTempFile( | |
\ a:buffer, | |
\ l:temporary_file, | |
\ a:input, | |
\) | |
return [l:temporary_file, l:command, l:file_created] | |
endfunction | |
1 0.000001 function! ale#command#StopJobs(buffer, job_type) abort | |
let l:info = get(s:buffer_data, a:buffer, {}) | |
if !empty(l:info) | |
let l:new_map = {} | |
for [l:job_id, l:job_type] in items(l:info.jobs) | |
let l:job_id = str2nr(l:job_id) | |
if a:job_type is# 'all' || a:job_type is# l:job_type | |
call ale#job#Stop(l:job_id) | |
else | |
let l:new_map[l:job_id] = l:job_type | |
endif | |
endfor | |
let l:info.jobs = l:new_map | |
endif | |
endfunction | |
1 0.000001 function! s:GatherOutput(line_list, job_id, line) abort | |
call add(a:line_list, a:line) | |
endfunction | |
1 0.000001 function! s:ExitCallback(buffer, line_list, Callback, data) abort | |
if !has_key(s:buffer_data, a:buffer) | |
return | |
endif | |
let l:jobs = s:buffer_data[a:buffer].jobs | |
if !has_key(l:jobs, a:data.job_id) | |
return | |
endif | |
let l:job_type = remove(l:jobs, a:data.job_id) | |
if g:ale_history_enabled | |
call ale#history#SetExitCode(a:buffer, a:data.job_id, a:data.exit_code) | |
" Log the output of the command for ALEInfo if we should. | |
if g:ale_history_log_output && a:data.log_output is 1 | |
call ale#history#RememberOutput( | |
\ a:buffer, | |
\ a:data.job_id, | |
\ a:line_list[:] | |
\) | |
endif | |
endif | |
" If the callback starts any new jobs, use the same job type for them. | |
call setbufvar(a:buffer, 'ale_job_type', l:job_type) | |
let l:value = a:Callback(a:buffer, a:line_list, { | |
\ 'exit_code': a:data.exit_code, | |
\ 'temporary_file': a:data.temporary_file, | |
\}) | |
let l:result = a:data.result | |
let l:result.value = l:value | |
" Set the default cwd for this buffer in this call stack. | |
call ale#command#SetCwd(a:buffer, l:result.cwd) | |
try | |
if get(l:result, 'result_callback', v:null) isnot v:null | |
call call(l:result.result_callback, [l:value]) | |
endif | |
finally | |
call ale#command#ResetCwd(a:buffer) | |
endtry | |
endfunction | |
1 0.000001 function! ale#command#Run(buffer, command, Callback, ...) abort | |
let l:options = get(a:000, 0, {}) | |
if len(a:000) > 1 | |
throw 'Too many arguments!' | |
endif | |
let l:output_stream = get(l:options, 'output_stream', 'stdout') | |
let l:line_list = [] | |
let l:cwd = get(l:options, 'cwd', v:null) | |
if l:cwd is v:null | |
" Default the working directory to whatever it was for the last | |
" command run in the chain. | |
let l:cwd = get(get(s:buffer_data, a:buffer, {}), 'cwd', v:null) | |
endif | |
let [l:temporary_file, l:command, l:file_created] = ale#command#FormatCommand( | |
\ a:buffer, | |
\ get(l:options, 'executable', ''), | |
\ a:command, | |
\ get(l:options, 'read_buffer', 0), | |
\ get(l:options, 'input', v:null), | |
\ l:cwd, | |
\ get(l:options, 'filename_mappings', []), | |
\) | |
let l:command = ale#job#PrepareCommand(a:buffer, l:command) | |
let l:job_options = { | |
\ 'exit_cb': {job_id, exit_code -> s:ExitCallback( | |
\ a:buffer, | |
\ l:line_list, | |
\ a:Callback, | |
\ { | |
\ 'job_id': job_id, | |
\ 'exit_code': exit_code, | |
\ 'temporary_file': l:temporary_file, | |
\ 'log_output': get(l:options, 'log_output', 1), | |
\ 'result': l:result, | |
\ } | |
\ )}, | |
\ 'mode': 'nl', | |
\} | |
if l:output_stream is# 'stdout' | |
let l:job_options.out_cb = function('s:GatherOutput', [l:line_list]) | |
elseif l:output_stream is# 'stderr' | |
let l:job_options.err_cb = function('s:GatherOutput', [l:line_list]) | |
elseif l:output_stream is# 'both' | |
let l:job_options.out_cb = function('s:GatherOutput', [l:line_list]) | |
let l:job_options.err_cb = function('s:GatherOutput', [l:line_list]) | |
endif | |
let l:status = 'failed' | |
if get(g:, 'ale_run_synchronously') == 1 | |
if get(g:, 'ale_emulate_job_failure') == 1 | |
let l:job_id = 0 | |
else | |
" Generate a fake job ID for tests. | |
let s:fake_job_id = get(s:, 'fake_job_id', 0) + 1 | |
let l:job_id = s:fake_job_id | |
endif | |
elseif has('win32') | |
let l:job_id = ale#job#StartWithCmd(l:command, l:job_options) | |
else | |
let l:job_id = ale#job#Start(l:command, l:job_options) | |
endif | |
if l:job_id | |
let l:status = 'started' | |
let l:job_type = getbufvar(a:buffer, 'ale_job_type', 'all') | |
call ale#command#InitData(a:buffer) | |
let s:buffer_data[a:buffer].jobs[l:job_id] = l:job_type | |
endif | |
if g:ale_history_enabled | |
call ale#history#Add(a:buffer, l:status, l:job_id, l:command) | |
endif | |
if !l:job_id | |
return 0 | |
endif | |
" We'll return this Dictionary. A `result_callback` can be assigned to it | |
" later for capturing the result of a:Callback. | |
" | |
" The `_deferred_job_id` is used for both checking the type of object, and | |
" for checking the job ID and status. | |
" | |
" The cwd is kept and used as the default value for the next command in | |
" the chain. | |
" | |
" The original command here is used in tests. | |
let l:result = { | |
\ '_deferred_job_id': l:job_id, | |
\ 'executable': get(l:options, 'executable', ''), | |
\ 'cwd': l:cwd, | |
\ 'command': a:command, | |
\} | |
if get(g:, 'ale_run_synchronously') == 1 && l:job_id | |
if !exists('g:ale_run_synchronously_callbacks') | |
let g:ale_run_synchronously_callbacks = [] | |
endif | |
if get(g:, 'ale_run_synchronously_emulate_commands', 0) | |
call add( | |
\ g:ale_run_synchronously_callbacks, | |
\ {exit_code, output -> [ | |
\ extend(l:line_list, output), | |
\ l:job_options.exit_cb(l:job_id, exit_code), | |
\ ]} | |
\) | |
else | |
" Run a command synchronously if this test option is set. | |
call extend(l:line_list, systemlist( | |
\ type(l:command) is v:t_list | |
\ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2]) | |
\ : l:command | |
\)) | |
" Don't capture output when the callbacks aren't set. | |
if !has_key(l:job_options, 'out_cb') | |
\&& !has_key(l:job_options, 'err_cb') | |
let l:line_list = [] | |
endif | |
call add( | |
\ g:ale_run_synchronously_callbacks, | |
\ {-> l:job_options.exit_cb(l:job_id, v:shell_error)} | |
\) | |
endif | |
endif | |
return l:result | |
endfunction | |
1 0.000001 function! ale#command#IsDeferred(value) abort | |
return type(a:value) is v:t_dict && has_key(a:value, '_deferred_job_id') | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/history.vim | |
Sourced 1 time | |
Total time: 0.000169 | |
Self time: 0.000169 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Tools for managing command history | |
" A flag for controlling the maximum size of the command history to store. | |
1 0.000003 let g:ale_max_buffer_history_size = get(g:, 'ale_max_buffer_history_size', 20) | |
" Return a shallow copy of the command history for a given buffer number. | |
1 0.000001 function! ale#history#Get(buffer) abort | |
return copy(getbufvar(a:buffer, 'ale_history', [])) | |
endfunction | |
1 0.000001 function! ale#history#Add(buffer, status, job_id, command) abort | |
if g:ale_max_buffer_history_size <= 0 | |
" Don't save anything if the history isn't a positive number. | |
call setbufvar(a:buffer, 'ale_history', []) | |
return | |
endif | |
let l:history = getbufvar(a:buffer, 'ale_history', []) | |
" Remove the first item if we hit the max history size. | |
if len(l:history) >= g:ale_max_buffer_history_size | |
let l:history = l:history[1:] | |
endif | |
call add(l:history, { | |
\ 'status': a:status, | |
\ 'job_id': a:job_id, | |
\ 'command': a:command, | |
\}) | |
call setbufvar(a:buffer, 'ale_history', l:history) | |
endfunction | |
1 0.000001 function! s:FindHistoryItem(buffer, job_id) abort | |
" Search backwards to find a matching job ID. IDs might be recycled, | |
" so finding the last one should be good enough. | |
for l:obj in reverse(ale#history#Get(a:buffer)) | |
if l:obj.job_id == a:job_id | |
return l:obj | |
endif | |
endfor | |
return {} | |
endfunction | |
" Set an exit code for a command which finished. | |
1 0.000001 function! ale#history#SetExitCode(buffer, job_id, exit_code) abort | |
let l:obj = s:FindHistoryItem(a:buffer, a:job_id) | |
" If we find a match, then set the code and status. | |
let l:obj.exit_code = a:exit_code | |
let l:obj.status = 'finished' | |
endfunction | |
" Set the output for a command which finished. | |
1 0.000001 function! ale#history#RememberOutput(buffer, job_id, output) abort | |
let l:obj = s:FindHistoryItem(a:buffer, a:job_id) | |
let l:obj.output = a:output | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/go.vim | |
Sourced 1 time | |
Total time: 0.000281 | |
Self time: 0.000276 | |
count total (s) self (s) | |
" Author: Horacio Sanson https://github.com/hsanson | |
" Description: Functions for integrating with Go tools | |
" Find the nearest dir listed in GOPATH and assume it the root of the go | |
" project. | |
1 0.000001 function! ale#go#FindProjectRoot(buffer) abort | |
let l:sep = has('win32') ? ';' : ':' | |
let l:filename = ale#path#Simplify(expand('#' . a:buffer . ':p')) | |
for l:name in split($GOPATH, l:sep) | |
let l:path_dir = ale#path#Simplify(l:name) | |
" Use the directory from GOPATH if the current filename starts with it. | |
if l:filename[: len(l:path_dir) - 1] is? l:path_dir | |
return l:path_dir | |
endif | |
endfor | |
let l:default_go_path = ale#path#Simplify(expand('~/go')) | |
if isdirectory(l:default_go_path) | |
return l:default_go_path | |
endif | |
return '' | |
endfunction | |
1 0.000011 0.000007 call ale#Set('go_go111module', '') | |
" Return a string setting Go-specific environment variables | |
1 0.000001 function! ale#go#EnvString(buffer) abort | |
let l:env = '' | |
" GO111MODULE - turn go modules behavior on/off | |
let l:go111module = ale#Var(a:buffer, 'go_go111module') | |
if !empty(l:go111module) | |
let l:env = ale#Env('GO111MODULE', l:go111module) . l:env | |
endif | |
return l:env | |
endfunction | |
1 0.000001 function! ale#go#GetGoPathExecutable(suffix) abort | |
let l:prefix = $GOPATH | |
if !empty($GOPATH) | |
let l:prefix = $GOPATH | |
elseif has('win32') | |
let l:prefix = $USERPROFILE . '/go' | |
else | |
let l:prefix = $HOME . '/go' | |
endif | |
return ale#path#Simplify(l:prefix . '/' . a:suffix) | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/job.vim | |
Sourced 1 time | |
Total time: 0.000267 | |
Self time: 0.000267 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: APIs for working with Asynchronous jobs, with an API normalised | |
" between Vim 8 and NeoVim. | |
" | |
" Important functions are described below. They are: | |
" | |
" ale#job#Start(command, options) -> job_id | |
" ale#job#IsRunning(job_id) -> 1 if running, 0 otherwise. | |
" ale#job#Stop(job_id) | |
" A setting for wrapping commands. | |
1 0.000003 let g:ale_command_wrapper = get(g:, 'ale_command_wrapper', '') | |
1 0.000001 if !has_key(s:, 'job_map') | |
1 0.000001 let s:job_map = {} | |
1 0.000000 endif | |
" A map from timer IDs to jobs, for tracking jobs that need to be killed | |
" with SIGKILL if they don't terminate right away. | |
1 0.000001 if !has_key(s:, 'job_kill_timers') | |
1 0.000001 let s:job_kill_timers = {} | |
1 0.000000 endif | |
1 0.000001 function! s:KillHandler(timer) abort | |
let l:job = remove(s:job_kill_timers, a:timer) | |
call job_stop(l:job, 'kill') | |
endfunction | |
1 0.000001 function! s:NeoVimCallback(job, data, event) abort | |
let l:info = s:job_map[a:job] | |
if a:event is# 'stdout' | |
let l:info.out_cb_line = ale#util#JoinNeovimOutput( | |
\ a:job, | |
\ l:info.out_cb_line, | |
\ a:data, | |
\ l:info.mode, | |
\ ale#util#GetFunction(l:info.out_cb), | |
\) | |
elseif a:event is# 'stderr' | |
let l:info.err_cb_line = ale#util#JoinNeovimOutput( | |
\ a:job, | |
\ l:info.err_cb_line, | |
\ a:data, | |
\ l:info.mode, | |
\ ale#util#GetFunction(l:info.err_cb), | |
\) | |
else | |
if has_key(l:info, 'out_cb') && !empty(l:info.out_cb_line) | |
call ale#util#GetFunction(l:info.out_cb)(a:job, l:info.out_cb_line) | |
endif | |
if has_key(l:info, 'err_cb') && !empty(l:info.err_cb_line) | |
call ale#util#GetFunction(l:info.err_cb)(a:job, l:info.err_cb_line) | |
endif | |
try | |
call ale#util#GetFunction(l:info.exit_cb)(a:job, a:data) | |
finally | |
" Automatically forget about the job after it's done. | |
if has_key(s:job_map, a:job) | |
call remove(s:job_map, a:job) | |
endif | |
endtry | |
endif | |
endfunction | |
1 0.000001 function! s:VimOutputCallback(channel, data) abort | |
let l:job = ch_getjob(a:channel) | |
let l:job_id = ale#job#ParseVim8ProcessID(string(l:job)) | |
" Only call the callbacks for jobs which are valid. | |
if l:job_id > 0 && has_key(s:job_map, l:job_id) | |
call ale#util#GetFunction(s:job_map[l:job_id].out_cb)(l:job_id, a:data) | |
endif | |
endfunction | |
1 0.000001 function! s:VimErrorCallback(channel, data) abort | |
let l:job = ch_getjob(a:channel) | |
let l:job_id = ale#job#ParseVim8ProcessID(string(l:job)) | |
" Only call the callbacks for jobs which are valid. | |
if l:job_id > 0 && has_key(s:job_map, l:job_id) | |
call ale#util#GetFunction(s:job_map[l:job_id].err_cb)(l:job_id, a:data) | |
endif | |
endfunction | |
1 0.000001 function! s:VimCloseCallback(channel) abort | |
let l:job = ch_getjob(a:channel) | |
let l:job_id = ale#job#ParseVim8ProcessID(string(l:job)) | |
let l:info = get(s:job_map, l:job_id, {}) | |
if empty(l:info) | |
return | |
endif | |
" job_status() can trigger the exit handler. | |
" The channel can close before the job has exited. | |
if job_status(l:job) is# 'dead' | |
try | |
if !empty(l:info) && has_key(l:info, 'exit_cb') | |
" We have to remove the callback, so we don't call it twice. | |
call ale#util#GetFunction(remove(l:info, 'exit_cb'))(l:job_id, get(l:info, 'exit_code', 1)) | |
endif | |
finally | |
" Automatically forget about the job after it's done. | |
if has_key(s:job_map, l:job_id) | |
call remove(s:job_map, l:job_id) | |
endif | |
endtry | |
endif | |
endfunction | |
1 0.000001 function! s:VimExitCallback(job, exit_code) abort | |
let l:job_id = ale#job#ParseVim8ProcessID(string(a:job)) | |
let l:info = get(s:job_map, l:job_id, {}) | |
if empty(l:info) | |
return | |
endif | |
let l:info.exit_code = a:exit_code | |
" The program can exit before the data has finished being read. | |
if ch_status(job_getchannel(a:job)) is# 'closed' | |
try | |
if !empty(l:info) && has_key(l:info, 'exit_cb') | |
" We have to remove the callback, so we don't call it twice. | |
call ale#util#GetFunction(remove(l:info, 'exit_cb'))(l:job_id, a:exit_code) | |
endif | |
finally | |
" Automatically forget about the job after it's done. | |
if has_key(s:job_map, l:job_id) | |
call remove(s:job_map, l:job_id) | |
endif | |
endtry | |
endif | |
endfunction | |
1 0.000001 function! ale#job#ParseVim8ProcessID(job_string) abort | |
return matchstr(a:job_string, '\d\+') + 0 | |
endfunction | |
1 0.000001 function! ale#job#ValidateArguments(command, options) abort | |
if a:options.mode isnot# 'nl' && a:options.mode isnot# 'raw' | |
throw 'Invalid mode: ' . a:options.mode | |
endif | |
endfunction | |
1 0.000001 function! s:PrepareWrappedCommand(original_wrapper, command) abort | |
let l:match = matchlist(a:command, '\v^(.*(\&\&|;)) *(.*)$') | |
let l:prefix = '' | |
let l:command = a:command | |
if !empty(l:match) | |
let l:prefix = l:match[1] . ' ' | |
let l:command = l:match[3] | |
endif | |
let l:format = a:original_wrapper | |
if l:format =~# '%@' | |
let l:wrapped = substitute(l:format, '%@', ale#Escape(l:command), '') | |
else | |
if l:format !~# '%\*' | |
let l:format .= ' %*' | |
endif | |
let l:wrapped = substitute(l:format, '%\*', l:command, '') | |
endif | |
return l:prefix . l:wrapped | |
endfunction | |
1 0.000001 function! ale#job#PrepareCommand(buffer, command) abort | |
let l:wrapper = ale#Var(a:buffer, 'command_wrapper') | |
" The command will be executed in a subshell. This fixes a number of | |
" issues, including reading the PATH variables correctly, %PATHEXT% | |
" expansion on Windows, etc. | |
" | |
" NeoVim handles this issue automatically if the command is a String, | |
" but we'll do this explicitly, so we use the same exact command for both | |
" versions. | |
let l:command = !empty(l:wrapper) | |
\ ? s:PrepareWrappedCommand(l:wrapper, a:command) | |
\ : a:command | |
" If a custom shell is specified, use that. | |
if exists('g:ale_shell') | |
let l:shell_arguments = get(g:, 'ale_shell_arguments', &shellcmdflag) | |
return split(g:ale_shell) + split(l:shell_arguments) + [l:command] | |
endif | |
if has('win32') | |
return 'cmd /s/c "' . l:command . '"' | |
endif | |
if &shell =~? 'fish$\|pwsh$' | |
return ['/bin/sh', '-c', l:command] | |
endif | |
return split(&shell) + split(&shellcmdflag) + [l:command] | |
endfunction | |
" Start a job with options which are agnostic to Vim and NeoVim. | |
" | |
" The following options are accepted: | |
" | |
" out_cb - A callback for receiving stdin. Arguments: (job_id, data) | |
" err_cb - A callback for receiving stderr. Arguments: (job_id, data) | |
" exit_cb - A callback for program exit. Arguments: (job_id, status_code) | |
" mode - A mode for I/O. Can be 'nl' for split lines or 'raw'. | |
1 0.000001 function! ale#job#Start(command, options) abort | |
call ale#job#ValidateArguments(a:command, a:options) | |
let l:job_info = copy(a:options) | |
let l:job_options = {} | |
if has('nvim') | |
if has_key(a:options, 'out_cb') | |
let l:job_options.on_stdout = function('s:NeoVimCallback') | |
let l:job_info.out_cb_line = '' | |
endif | |
if has_key(a:options, 'err_cb') | |
let l:job_options.on_stderr = function('s:NeoVimCallback') | |
let l:job_info.err_cb_line = '' | |
endif | |
if has_key(a:options, 'exit_cb') | |
let l:job_options.on_exit = function('s:NeoVimCallback') | |
endif | |
let l:job_info.job = jobstart(a:command, l:job_options) | |
let l:job_id = l:job_info.job | |
else | |
let l:job_options = { | |
\ 'in_mode': l:job_info.mode, | |
\ 'out_mode': l:job_info.mode, | |
\ 'err_mode': l:job_info.mode, | |
\} | |
if has_key(a:options, 'out_cb') | |
let l:job_options.out_cb = function('s:VimOutputCallback') | |
endif | |
if has_key(a:options, 'err_cb') | |
let l:job_options.err_cb = function('s:VimErrorCallback') | |
endif | |
if has_key(a:options, 'exit_cb') | |
" Set a close callback to which simply calls job_status() | |
" when the channel is closed, which can trigger the exit callback | |
" earlier on. | |
let l:job_options.close_cb = function('s:VimCloseCallback') | |
let l:job_options.exit_cb = function('s:VimExitCallback') | |
endif | |
" Use non-blocking writes for Vim versions that support the option. | |
if has('patch-8.1.350') | |
let l:job_options.noblock = 1 | |
endif | |
" Vim 8 will read the stdin from the file's buffer. | |
let l:job_info.job = job_start(a:command, l:job_options) | |
let l:job_id = ale#job#ParseVim8ProcessID(string(l:job_info.job)) | |
endif | |
if l:job_id > 0 | |
" Store the job in the map for later only if we can get the ID. | |
let s:job_map[l:job_id] = l:job_info | |
endif | |
return l:job_id | |
endfunction | |
" Force running commands in a Windows CMD command line. | |
" This means the same command syntax works everywhere. | |
1 0.000001 function! ale#job#StartWithCmd(command, options) abort | |
let l:shell = &l:shell | |
let l:shellcmdflag = &l:shellcmdflag | |
let &l:shell = 'cmd' | |
let &l:shellcmdflag = '/c' | |
try | |
let l:job_id = ale#job#Start(a:command, a:options) | |
finally | |
let &l:shell = l:shell | |
let &l:shellcmdflag = l:shellcmdflag | |
endtry | |
return l:job_id | |
endfunction | |
" Send raw data to the job. | |
1 0.000001 function! ale#job#SendRaw(job_id, string) abort | |
if has('nvim') | |
call jobsend(a:job_id, a:string) | |
else | |
let l:job = s:job_map[a:job_id].job | |
if ch_status(l:job) is# 'open' | |
call ch_sendraw(job_getchannel(l:job), a:string) | |
endif | |
endif | |
endfunction | |
" Given a job ID, return 1 if the job is currently running. | |
" Invalid job IDs will be ignored. | |
1 0.000001 function! ale#job#IsRunning(job_id) abort | |
if has('nvim') | |
try | |
" In NeoVim, if the job isn't running, jobpid() will throw. | |
call jobpid(a:job_id) | |
return 1 | |
catch | |
endtry | |
elseif has_key(s:job_map, a:job_id) | |
let l:job = s:job_map[a:job_id].job | |
return job_status(l:job) is# 'run' | |
endif | |
return 0 | |
endfunction | |
1 0.000001 function! ale#job#HasOpenChannel(job_id) abort | |
if ale#job#IsRunning(a:job_id) | |
if has('nvim') | |
" TODO: Implement a check for NeoVim. | |
return 1 | |
endif | |
" Check if the Job's channel can be written to. | |
return ch_status(s:job_map[a:job_id].job) is# 'open' | |
endif | |
return 0 | |
endfunction | |
" Given a Job ID, stop that job. | |
" Invalid job IDs will be ignored. | |
1 0.000001 function! ale#job#Stop(job_id) abort | |
if !has_key(s:job_map, a:job_id) | |
return | |
endif | |
if has('nvim') | |
" FIXME: NeoVim kills jobs on a timer, but will not kill any processes | |
" which are child processes on Unix. Some work needs to be done to | |
" kill child processes to stop long-running processes like pylint. | |
silent! call jobstop(a:job_id) | |
else | |
let l:job = s:job_map[a:job_id].job | |
" We must close the channel for reading the buffer if it is open | |
" when stopping a job. Otherwise, we will get errors in the status line. | |
if ch_status(job_getchannel(l:job)) is# 'open' | |
call ch_close_in(job_getchannel(l:job)) | |
endif | |
" Ask nicely for the job to stop. | |
call job_stop(l:job) | |
if ale#job#IsRunning(l:job) | |
" Set a 100ms delay for killing the job with SIGKILL. | |
let s:job_kill_timers[timer_start(100, function('s:KillHandler'))] = l:job | |
endif | |
endif | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp_linter.vim | |
Sourced 1 time | |
Total time: 0.000629 | |
Self time: 0.000629 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Integration between linters and LSP/tsserver. | |
" This code isn't loaded if a user never users LSP features or linters. | |
" Associates LSP connection IDs with linter names. | |
1 0.000006 if !has_key(s:, 'lsp_linter_map') | |
1 0.000002 let s:lsp_linter_map = {} | |
1 0.000001 endif | |
" A Dictionary to track one-shot handlers for custom LSP requests | |
1 0.000005 let s:custom_handlers_map = get(s:, 'custom_handlers_map', {}) | |
" Check if diagnostics for a particular linter should be ignored. | |
1 0.000002 function! s:ShouldIgnore(buffer, linter_name) abort | |
" Ignore all diagnostics if LSP integration is disabled. | |
if ale#Var(a:buffer, 'disable_lsp') | |
return 1 | |
endif | |
let l:config = ale#Var(a:buffer, 'linters_ignore') | |
" Don't load code for ignoring diagnostics if there's nothing to ignore. | |
if empty(l:config) | |
return 0 | |
endif | |
let l:filetype = getbufvar(a:buffer, '&filetype') | |
let l:ignore_list = ale#engine#ignore#GetList(l:filetype, l:config) | |
return index(l:ignore_list, a:linter_name) >= 0 | |
endfunction | |
1 0.000001 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:escaped_name = escape( | |
\ fnameescape(l:filename), | |
\ has('win32') ? '^' : '^,}]' | |
\) | |
let l:buffer = bufnr('^' . l:escaped_name . '$') | |
let l:info = get(g:ale_buffer_info, l:buffer, {}) | |
if empty(l:info) | |
return | |
endif | |
if s:ShouldIgnore(l:buffer, l:linter_name) | |
return | |
endif | |
let l:loclist = ale#lsp#response#ReadDiagnostics(a:response) | |
call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist, 0) | |
endfunction | |
1 0.000001 function! s:HandleTSServerDiagnostics(response, error_type) abort | |
let l:linter_name = 'tsserver' | |
let l:escaped_name = escape( | |
\ fnameescape(a:response.body.file), | |
\ has('win32') ? '^' : '^,}]' | |
\) | |
let l:buffer = bufnr('^' . l:escaped_name . '$') | |
let l:info = get(g:ale_buffer_info, l:buffer, {}) | |
if empty(l:info) | |
return | |
endif | |
call ale#engine#MarkLinterInactive(l:info, l:linter_name) | |
if s:ShouldIgnore(l:buffer, l:linter_name) | |
return | |
endif | |
let l:thislist = ale#lsp#response#ReadTSServerDiagnostics(a:response) | |
let l:no_changes = 0 | |
" tsserver sends syntax and semantic errors in separate messages, so we | |
" have to collect the messages separately for each buffer and join them | |
" back together again. | |
if a:error_type is# 'syntax' | |
if len(l:thislist) is 0 && len(get(l:info, 'syntax_loclist', [])) is 0 | |
let l:no_changes = 1 | |
endif | |
let l:info.syntax_loclist = l:thislist | |
elseif a:error_type is# 'semantic' | |
if len(l:thislist) is 0 && len(get(l:info, 'semantic_loclist', [])) is 0 | |
let l:no_changes = 1 | |
endif | |
let l:info.semantic_loclist = l:thislist | |
else | |
if len(l:thislist) is 0 && len(get(l:info, 'suggestion_loclist', [])) is 0 | |
let l:no_changes = 1 | |
endif | |
let l:info.suggestion_loclist = l:thislist | |
endif | |
if l:no_changes | |
return | |
endif | |
let l:loclist = get(l:info, 'semantic_loclist', []) | |
\ + get(l:info, 'suggestion_loclist', []) | |
\ + get(l:info, 'syntax_loclist', []) | |
call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist, 0) | |
endfunction | |
1 0.000001 function! s:HandleLSPErrorMessage(linter_name, response) abort | |
if !g:ale_history_enabled || !g:ale_history_log_output | |
return | |
endif | |
if empty(a:linter_name) | |
return | |
endif | |
let l:message = ale#lsp#response#GetErrorMessage(a:response) | |
if empty(l:message) | |
return | |
endif | |
" This global variable is set here so we don't load the debugging.vim file | |
" until someone uses :ALEInfo. | |
let g:ale_lsp_error_messages = get(g:, 'ale_lsp_error_messages', {}) | |
if !has_key(g:ale_lsp_error_messages, a:linter_name) | |
let g:ale_lsp_error_messages[a:linter_name] = [] | |
endif | |
call add(g:ale_lsp_error_messages[a:linter_name], l:message) | |
endfunction | |
1 0.000001 function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort | |
let l:method = get(a:response, 'method', '') | |
if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error') | |
let l:linter_name = get(s:lsp_linter_map, a:conn_id, '') | |
call s:HandleLSPErrorMessage(l:linter_name, a:response) | |
elseif l:method is# 'textDocument/publishDiagnostics' | |
call s:HandleLSPDiagnostics(a:conn_id, a:response) | |
elseif l:method is# 'window/showMessage' | |
call ale#lsp_window#HandleShowMessage( | |
\ s:lsp_linter_map[a:conn_id], | |
\ g:ale_lsp_show_message_format, | |
\ a:response.params | |
\) | |
elseif get(a:response, 'type', '') is# 'event' | |
\&& get(a:response, 'event', '') is# 'semanticDiag' | |
call s:HandleTSServerDiagnostics(a:response, 'semantic') | |
elseif get(a:response, 'type', '') is# 'event' | |
\&& get(a:response, 'event', '') is# 'syntaxDiag' | |
call s:HandleTSServerDiagnostics(a:response, 'syntax') | |
elseif get(a:response, 'type', '') is# 'event' | |
\&& get(a:response, 'event', '') is# 'suggestionDiag' | |
\&& get(g:, 'ale_lsp_suggestions', '1') == 1 | |
call s:HandleTSServerDiagnostics(a:response, 'suggestion') | |
endif | |
endfunction | |
1 0.000001 function! ale#lsp_linter#GetOptions(buffer, linter) abort | |
if has_key(a:linter, 'initialization_options_callback') | |
return ale#util#GetFunction(a:linter.initialization_options_callback)(a:buffer) | |
endif | |
if has_key(a:linter, 'initialization_options') | |
let l:Options = a:linter.initialization_options | |
if type(l:Options) is v:t_func | |
let l:Options = l:Options(a:buffer) | |
endif | |
return l:Options | |
endif | |
return {} | |
endfunction | |
1 0.000001 function! ale#lsp_linter#GetConfig(buffer, linter) abort | |
if has_key(a:linter, 'lsp_config_callback') | |
return ale#util#GetFunction(a:linter.lsp_config_callback)(a:buffer) | |
endif | |
if has_key(a:linter, 'lsp_config') | |
let l:Config = a:linter.lsp_config | |
if type(l:Config) is v:t_func | |
let l:Config = l:Config(a:buffer) | |
endif | |
return l:Config | |
endif | |
return {} | |
endfunction | |
1 0.000001 function! ale#lsp_linter#FindProjectRoot(buffer, linter) abort | |
let l:buffer_ale_root = getbufvar( | |
\ a:buffer, | |
\ 'ale_root', | |
\ getbufvar(a:buffer, 'ale_lsp_root', {}) | |
\) | |
if type(l:buffer_ale_root) is v:t_string | |
return l:buffer_ale_root | |
endif | |
" Try to get a buffer-local setting for the root | |
if has_key(l:buffer_ale_root, a:linter.name) | |
let l:Root = l:buffer_ale_root[a:linter.name] | |
if type(l:Root) is v:t_func | |
return l:Root(a:buffer) | |
else | |
return l:Root | |
endif | |
endif | |
let l:global_root = g:ale_root | |
if empty(g:ale_root) && exists('g:ale_lsp_root') | |
let l:global_root = g:ale_lsp_root | |
endif | |
" Try to get a global setting for the root | |
if has_key(l:global_root, a:linter.name) | |
let l:Root = l:global_root[a:linter.name] | |
if type(l:Root) is v:t_func | |
return l:Root(a:buffer) | |
else | |
return l:Root | |
endif | |
endif | |
" Fall back to the linter-specific configuration | |
if has_key(a:linter, 'project_root') | |
let l:Root = a:linter.project_root | |
return type(l:Root) is v:t_func ? l:Root(a:buffer) : l:Root | |
endif | |
return ale#util#GetFunction(a:linter.project_root_callback)(a:buffer) | |
endfunction | |
" This function is accessible so tests can call it. | |
1 0.000001 function! ale#lsp_linter#OnInit(linter, details, Callback) abort | |
let l:buffer = a:details.buffer | |
let l:conn_id = a:details.connection_id | |
let l:command = a:details.command | |
let l:config = ale#lsp_linter#GetConfig(l:buffer, a:linter) | |
let l:language_id = ale#linter#GetLanguage(l:buffer, a:linter) | |
call ale#lsp#UpdateConfig(l:conn_id, l:buffer, l:config) | |
if ale#lsp#OpenDocument(l:conn_id, l:buffer, l:language_id) | |
if g:ale_history_enabled && !empty(l:command) | |
call ale#history#Add(l:buffer, 'started', l:conn_id, l:command) | |
endif | |
endif | |
" The change message needs to be sent for tsserver before doing anything. | |
if a:linter.lsp is# 'tsserver' | |
call ale#lsp#NotifyForChanges(l:conn_id, l:buffer) | |
endif | |
" Tell the relevant buffer that the LSP has started via an autocmd. | |
if l:buffer > 0 | |
if l:buffer == bufnr('') | |
silent doautocmd <nomodeline> User ALELSPStarted | |
else | |
execute 'augroup ALELSPStartedGroup' . l:buffer | |
autocmd! | |
execute printf( | |
\ 'autocmd BufEnter <buffer=%d>' | |
\ . ' doautocmd <nomodeline> User ALELSPStarted', | |
\ l:buffer | |
\) | |
" Replicate ++once behavior for backwards compatibility. | |
execute printf( | |
\ 'autocmd BufEnter <buffer=%d>' | |
\ . ' autocmd! ALELSPStartedGroup%d', | |
\ l:buffer, l:buffer | |
\) | |
augroup END | |
endif | |
endif | |
call a:Callback(a:linter, a:details) | |
endfunction | |
1 0.000001 function! s:StartLSP(options, address, executable, command) abort | |
let l:buffer = a:options.buffer | |
let l:linter = a:options.linter | |
let l:root = a:options.root | |
let l:Callback = a:options.callback | |
let l:init_options = ale#lsp_linter#GetOptions(l:buffer, l:linter) | |
if l:linter.lsp is# 'socket' | |
let l:conn_id = ale#lsp#Register(a:address, l:root, l:init_options) | |
let l:ready = ale#lsp#ConnectToAddress(l:conn_id, a:address) | |
let l:command = '' | |
else | |
let l:conn_id = ale#lsp#Register(a:executable, l:root, l:init_options) | |
" tsserver behaves differently, so tell the LSP API that it is tsserver. | |
if l:linter.lsp is# 'tsserver' | |
call ale#lsp#MarkConnectionAsTsserver(l:conn_id) | |
endif | |
let l:cwd = ale#linter#GetCwd(l:buffer, l:linter) | |
let l:command = ale#command#FormatCommand( | |
\ l:buffer, | |
\ a:executable, | |
\ a:command, | |
\ 0, | |
\ v:false, | |
\ l:cwd, | |
\ ale#GetFilenameMappings(l:buffer, l:linter.name), | |
\)[1] | |
let l:command = ale#job#PrepareCommand(l:buffer, l:command) | |
let l:ready = ale#lsp#StartProgram(l:conn_id, a:executable, l:command) | |
endif | |
if !l:ready | |
if g:ale_history_enabled && !empty(a:command) | |
call ale#history#Add(l:buffer, 'failed', l:conn_id, a:command) | |
endif | |
return 0 | |
endif | |
let l:details = { | |
\ 'buffer': l:buffer, | |
\ 'connection_id': l:conn_id, | |
\ 'command': l:command, | |
\ 'project_root': l:root, | |
\} | |
call ale#lsp#OnInit(l:conn_id, {-> | |
\ ale#lsp_linter#OnInit(l:linter, l:details, l:Callback) | |
\}) | |
return 1 | |
endfunction | |
1 0.000001 function! s:StartWithAddress(options, address) abort | |
if ale#command#IsDeferred(a:address) | |
let a:address.result_callback = { | |
\ address -> s:StartWithAddress(a:options, address) | |
\} | |
return 1 | |
endif | |
if empty(a:address) | |
return 0 | |
endif | |
return s:StartLSP(a:options, a:address, '', '') | |
endfunction | |
1 0.000001 function! s:StartWithCommand(options, executable, command) abort | |
if ale#command#IsDeferred(a:command) | |
let a:command.result_callback = { | |
\ command -> s:StartWithCommand(a:options, a:executable, command) | |
\} | |
return 1 | |
endif | |
if empty(a:command) | |
return 0 | |
endif | |
return s:StartLSP(a:options, '', a:executable, a:command) | |
endfunction | |
1 0.000001 function! s:StartIfExecutable(options, executable) abort | |
if ale#command#IsDeferred(a:executable) | |
let a:executable.result_callback = { | |
\ executable -> s:StartIfExecutable(a:options, executable) | |
\} | |
return 1 | |
endif | |
if !ale#engine#IsExecutable(a:options.buffer, a:executable) | |
return 0 | |
endif | |
let l:command = ale#linter#GetCommand(a:options.buffer, a:options.linter) | |
return s:StartWithCommand(a:options, a:executable, l:command) | |
endfunction | |
" Given a buffer, an LSP linter, start up an LSP linter and get ready to | |
" receive messages for the document. | |
1 0.000001 function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort | |
let l:command = '' | |
let l:address = '' | |
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, a:linter) | |
if empty(l:root) && a:linter.lsp isnot# 'tsserver' | |
" If there's no project root, then we can't check files with LSP, | |
" unless we are using tsserver, which doesn't use project roots. | |
return 0 | |
endif | |
let l:options = { | |
\ 'buffer': a:buffer, | |
\ 'linter': a:linter, | |
\ 'callback': a:Callback, | |
\ 'root': l:root, | |
\} | |
if a:linter.lsp is# 'socket' | |
let l:address = ale#linter#GetAddress(a:buffer, a:linter) | |
return s:StartWithAddress(l:options, l:address) | |
endif | |
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) | |
return s:StartIfExecutable(l:options, l:executable) | |
endfunction | |
1 0.000001 function! s:CheckWithLSP(linter, details) abort | |
let l:buffer = a:details.buffer | |
let l:info = get(g:ale_buffer_info, l:buffer) | |
if empty(l:info) | |
return | |
endif | |
let l:id = a:details.connection_id | |
" Register a callback now for handling errors now. | |
let l:Callback = function('ale#lsp_linter#HandleLSPResponse') | |
call ale#lsp#RegisterCallback(l:id, l:Callback) | |
" Remember the linter this connection is for. | |
let s:lsp_linter_map[l:id] = a:linter.name | |
if a:linter.lsp is# 'tsserver' | |
let l:message = ale#lsp#tsserver_message#Geterr(l:buffer) | |
let l:notified = ale#lsp#Send(l:id, l:message) != 0 | |
if l:notified | |
call ale#engine#MarkLinterActive(l:info, a:linter) | |
endif | |
else | |
let l:notified = ale#lsp#NotifyForChanges(l:id, l:buffer) | |
endif | |
" If this was a file save event, also notify the server of that. | |
if a:linter.lsp isnot# 'tsserver' | |
\&& getbufvar(l:buffer, 'ale_save_event_fired', 0) | |
\&& ale#lsp#HasCapability(l:buffer, 'did_save') | |
let l:include_text = ale#lsp#HasCapability(l:buffer, 'includeText') | |
let l:save_message = ale#lsp#message#DidSave(l:buffer, l:include_text) | |
let l:notified = ale#lsp#Send(l:id, l:save_message) != 0 | |
endif | |
endfunction | |
1 0.000001 function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort | |
return ale#lsp_linter#StartLSP(a:buffer, a:linter, function('s:CheckWithLSP')) | |
endfunction | |
" Clear LSP linter data for the linting engine. | |
1 0.000001 function! ale#lsp_linter#ClearLSPData() abort | |
let s:lsp_linter_map = {} | |
let s:custom_handlers_map = {} | |
endfunction | |
" Just for tests. | |
1 0.000001 function! ale#lsp_linter#SetLSPLinterMap(replacement_map) abort | |
let s:lsp_linter_map = a:replacement_map | |
endfunction | |
1 0.000001 function! s:HandleLSPResponseToCustomRequests(conn_id, response) abort | |
if has_key(a:response, 'id') | |
\&& has_key(s:custom_handlers_map, a:response.id) | |
let l:Handler = remove(s:custom_handlers_map, a:response.id) | |
call l:Handler(a:response) | |
endif | |
endfunction | |
1 0.000001 function! s:OnReadyForCustomRequests(args, linter, lsp_details) abort | |
let l:id = a:lsp_details.connection_id | |
let l:request_id = ale#lsp#Send(l:id, a:args.message) | |
if l:request_id > 0 && has_key(a:args, 'handler') | |
let l:Callback = function('s:HandleLSPResponseToCustomRequests') | |
call ale#lsp#RegisterCallback(l:id, l:Callback) | |
let s:custom_handlers_map[l:request_id] = a:args.handler | |
endif | |
endfunction | |
" Send a custom request to an LSP linter. | |
1 0.000001 function! ale#lsp_linter#SendRequest(buffer, linter_name, message, ...) abort | |
let l:filetype = ale#linter#ResolveFiletype(getbufvar(a:buffer, '&filetype')) | |
let l:linter_list = ale#linter#GetAll(l:filetype) | |
let l:linter_list = filter(l:linter_list, {_, v -> v.name is# a:linter_name}) | |
if len(l:linter_list) < 1 | |
throw 'Linter "' . a:linter_name . '" not found!' | |
endif | |
let l:linter = l:linter_list[0] | |
if empty(l:linter.lsp) | |
throw 'Linter "' . a:linter_name . '" does not support LSP!' | |
endif | |
let l:is_notification = a:message[0] | |
let l:callback_args = {'message': a:message} | |
if !l:is_notification && a:0 | |
let l:callback_args.handler = a:1 | |
endif | |
let l:Callback = function('s:OnReadyForCustomRequests', [l:callback_args]) | |
return ale#lsp_linter#StartLSP(a:buffer, l:linter, l:Callback) | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/path.vim | |
Sourced 1 time | |
Total time: 0.000277 | |
Self time: 0.000246 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Functions for working with paths in the filesystem. | |
" simplify a path, and fix annoying issues with paths on Windows. | |
" | |
" Forward slashes are changed to back slashes so path equality works better | |
" on Windows. Back slashes are changed to forward slashes on Unix. | |
" | |
" Unix paths can technically contain back slashes, but in practice no path | |
" should, and replacing back slashes with forward slashes makes linters work | |
" in environments like MSYS. | |
" | |
" Paths starting with more than one forward slash are changed to only one | |
" forward slash, to prevent the paths being treated as special MSYS paths. | |
1 0.000002 function! ale#path#Simplify(path) abort | |
if has('unix') | |
let l:unix_path = substitute(a:path, '\\', '/', 'g') | |
return substitute(simplify(l:unix_path), '^//\+', '/', 'g') " no-custom-checks | |
endif | |
let l:win_path = substitute(a:path, '/', '\\', 'g') | |
return substitute(simplify(l:win_path), '^\\\+', '\', 'g') " no-custom-checks | |
endfunction | |
" Simplify a path without a Windows drive letter. | |
" This function can be used for checking if paths are equal. | |
1 0.000001 function! ale#path#RemoveDriveLetter(path) abort | |
return has('win32') && a:path[1:2] is# ':\' | |
\ ? ale#path#Simplify(a:path[2:]) | |
\ : ale#path#Simplify(a:path) | |
endfunction | |
" Given a buffer and a filename, find the nearest file by searching upwards | |
" through the paths relative to the given buffer. | |
1 0.000001 function! ale#path#FindNearestFile(buffer, filename) abort | |
let l:buffer_filename = fnamemodify(bufname(a:buffer), ':p') | |
let l:buffer_filename = fnameescape(l:buffer_filename) | |
let l:relative_path = findfile(a:filename, l:buffer_filename . ';') | |
if !empty(l:relative_path) | |
return fnamemodify(l:relative_path, ':p') | |
endif | |
return '' | |
endfunction | |
" Given a buffer and a directory name, find the nearest directory by searching upwards | |
" through the paths relative to the given buffer. | |
1 0.000002 function! ale#path#FindNearestDirectory(buffer, directory_name) abort | |
let l:buffer_filename = fnamemodify(bufname(a:buffer), ':p') | |
let l:buffer_filename = fnameescape(l:buffer_filename) | |
let l:relative_path = finddir(a:directory_name, l:buffer_filename . ';') | |
if !empty(l:relative_path) | |
return fnamemodify(l:relative_path, ':p') | |
endif | |
return '' | |
endfunction | |
" Given a buffer, a string to search for, and a global fallback for when | |
" the search fails, look for a file in parent paths, and if that fails, | |
" use the global fallback path instead. | |
1 0.000001 function! ale#path#ResolveLocalPath(buffer, search_string, global_fallback) abort | |
" Search for a locally installed file first. | |
let l:path = ale#path#FindNearestFile(a:buffer, a:search_string) | |
" If the search fails, try the global executable instead. | |
if empty(l:path) | |
let l:path = a:global_fallback | |
endif | |
return l:path | |
endfunction | |
" Given a buffer number, a base variable name, and a list of paths to search | |
" for in ancestor directories, detect the executable path for a program. | |
1 0.000001 function! ale#path#FindNearestExecutable(buffer, path_list) abort | |
for l:path in a:path_list | |
if ale#path#IsAbsolute(l:path) | |
let l:executable = filereadable(l:path) ? l:path : '' | |
else | |
let l:executable = ale#path#FindNearestFile(a:buffer, l:path) | |
endif | |
if !empty(l:executable) | |
return l:executable | |
endif | |
endfor | |
return '' | |
endfunction | |
" Given a buffer number, a base variable name, and a list of paths to search | |
" for in ancestor directories, detect the executable path for a program. | |
" | |
" The use_global and executable options for the relevant program will be used. | |
1 0.000001 function! ale#path#FindExecutable(buffer, base_var_name, path_list) abort | |
if ale#Var(a:buffer, a:base_var_name . '_use_global') | |
return ale#Var(a:buffer, a:base_var_name . '_executable') | |
endif | |
let l:nearest = ale#path#FindNearestExecutable(a:buffer, a:path_list) | |
if !empty(l:nearest) | |
return l:nearest | |
endif | |
return ale#Var(a:buffer, a:base_var_name . '_executable') | |
endfunction | |
" Return 1 if a path is an absolute path. | |
1 0.000001 function! ale#path#IsAbsolute(filename) abort | |
if has('win32') && a:filename[:0] is# '\' | |
return 1 | |
endif | |
" Check for /foo and C:\foo, etc. | |
return a:filename[:0] is# '/' || a:filename[1:2] is# ':\' | |
endfunction | |
1 0.000042 0.000011 let s:temp_dir = ale#path#Simplify(fnamemodify(ale#util#Tempname(), ':h:h')) | |
" Given a filename, return 1 if the file represents some temporary file | |
" created by Vim. | |
1 0.000001 function! ale#path#IsTempName(filename) abort | |
return ale#path#Simplify(a:filename)[:len(s:temp_dir) - 1] is# s:temp_dir | |
endfunction | |
" Given a base directory, which must not have a trailing slash, and a | |
" filename, which may have an absolute path a path relative to the base | |
" directory, return the absolute path to the file. | |
1 0.000001 function! ale#path#GetAbsPath(base_directory, filename) abort | |
if ale#path#IsAbsolute(a:filename) | |
return ale#path#Simplify(a:filename) | |
endif | |
let l:sep = has('win32') ? '\' : '/' | |
return ale#path#Simplify(a:base_directory . l:sep . a:filename) | |
endfunction | |
" Given a path, return the directory name for that path, with no trailing | |
" slashes. If the argument is empty(), return an empty string. | |
1 0.000001 function! ale#path#Dirname(path) abort | |
if empty(a:path) | |
return '' | |
endif | |
" For /foo/bar/ we need :h:h to get /foo | |
if a:path[-1:] is# '/' || (has('win32') && a:path[-1:] is# '\') | |
return fnamemodify(a:path, ':h:h') | |
endif | |
return fnamemodify(a:path, ':h') | |
endfunction | |
" Given a buffer number and a relative or absolute path, return 1 if the | |
" two paths represent the same file on disk. | |
1 0.000001 function! ale#path#IsBufferPath(buffer, complex_filename) abort | |
" If the path is one of many different names for stdin, we have a match. | |
if a:complex_filename is# '-' | |
\|| a:complex_filename is# 'stdin' | |
\|| a:complex_filename[:0] is# '<' | |
return 1 | |
endif | |
let l:test_filename = ale#path#Simplify(a:complex_filename) | |
if l:test_filename[:1] is# './' | |
let l:test_filename = l:test_filename[2:] | |
endif | |
if l:test_filename[:1] is# '..' | |
" Remove ../../ etc. from the front of the path. | |
let l:test_filename = substitute(l:test_filename, '\v^(\.\.[/\\])+', '/', '') | |
endif | |
" Use the basename for temporary files, as they are likely our files. | |
if ale#path#IsTempName(l:test_filename) | |
let l:test_filename = fnamemodify(l:test_filename, ':t') | |
endif | |
let l:buffer_filename = expand('#' . a:buffer . ':p') | |
return l:buffer_filename is# l:test_filename | |
\ || l:buffer_filename[-len(l:test_filename):] is# l:test_filename | |
endfunction | |
" Given a path, return every component of the path, moving upwards. | |
1 0.000001 function! ale#path#Upwards(path) abort | |
let l:pattern = has('win32') ? '\v/+|\\+' : '\v/+' | |
let l:sep = has('win32') ? '\' : '/' | |
let l:parts = split(ale#path#Simplify(a:path), l:pattern) | |
let l:path_list = [] | |
while !empty(l:parts) | |
call add(l:path_list, join(l:parts, l:sep)) | |
let l:parts = l:parts[:-2] | |
endwhile | |
if has('win32') && a:path =~# '^[a-zA-z]:\' | |
" Add \ to C: for C:\, etc. | |
let l:path_list[-1] .= '\' | |
elseif a:path[0] is# '/' | |
" If the path starts with /, even on Windows, add / and / to all paths. | |
call map(l:path_list, '''/'' . v:val') | |
call add(l:path_list, '/') | |
endif | |
return l:path_list | |
endfunction | |
" Convert a filesystem path to a file:// URI | |
" relatives paths will not be prefixed with the protocol. | |
" For Windows paths, the `:` in C:\ etc. will not be percent-encoded. | |
1 0.000001 function! ale#path#ToURI(path) abort | |
let l:has_drive_letter = a:path[1:2] is# ':\' | |
return substitute( | |
\ ((l:has_drive_letter || a:path[:0] is# '/') ? 'file://' : '') | |
\ . (l:has_drive_letter ? '/' . a:path[:2] : '') | |
\ . ale#uri#Encode(l:has_drive_letter ? a:path[3:] : a:path), | |
\ '\\', | |
\ '/', | |
\ 'g', | |
\) | |
endfunction | |
1 0.000001 function! ale#path#FromURI(uri) abort | |
if a:uri[:6] is? 'file://' | |
let l:encoded_path = a:uri[7:] | |
elseif a:uri[:4] is? 'file:' | |
let l:encoded_path = a:uri[5:] | |
else | |
let l:encoded_path = a:uri | |
endif | |
let l:path = ale#uri#Decode(l:encoded_path) | |
" If the path is like /C:/foo/bar, it should be C:\foo\bar instead. | |
if has('win32') && l:path =~# '^/[a-zA-Z][:|]' | |
let l:path = substitute(l:path[1:], '/', '\\', 'g') | |
let l:path = l:path[0] . ':' . l:path[2:] | |
endif | |
return l:path | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp.vim | |
Sourced 1 time | |
Total time: 0.000458 | |
Self time: 0.000458 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Language Server Protocol client code | |
" A Dictionary for tracking connections. | |
1 0.000006 let s:connections = get(s:, 'connections', {}) | |
1 0.000004 let g:ale_lsp_next_message_id = 1 | |
" Given an id, which can be an executable or address, and a project path, | |
" create a new connection if needed. Return a unique ID for the connection. | |
1 0.000002 function! ale#lsp#Register(executable_or_address, project, init_options) abort | |
let l:conn_id = a:executable_or_address . ':' . a:project | |
if !has_key(s:connections, l:conn_id) | |
" is_tsserver: 1 if the connection is for tsserver. | |
" data: The message data received so far. | |
" root: The project root. | |
" open_documents: A Dictionary mapping buffers to b:changedtick, keeping | |
" track of when documents were opened, and when we last changed them. | |
" initialized: 0 if the connection is ready, 1 otherwise. | |
" init_request_id: The ID for the init request. | |
" init_options: Options to send to the server. | |
" config: Configuration settings to send to the server. | |
" callback_list: A list of callbacks for handling LSP responses. | |
" capabilities_queue: The list of callbacks to call with capabilities. | |
" capabilities: Features the server supports. | |
let s:connections[l:conn_id] = { | |
\ 'id': l:conn_id, | |
\ 'is_tsserver': 0, | |
\ 'data': '', | |
\ 'root': a:project, | |
\ 'open_documents': {}, | |
\ 'initialized': 0, | |
\ 'init_request_id': 0, | |
\ 'init_options': a:init_options, | |
\ 'config': {}, | |
\ 'callback_list': [], | |
\ 'init_queue': [], | |
\ 'capabilities': { | |
\ 'hover': 0, | |
\ 'rename': 0, | |
\ 'references': 0, | |
\ 'completion': 0, | |
\ 'completion_trigger_characters': [], | |
\ 'definition': 0, | |
\ 'typeDefinition': 0, | |
\ 'symbol_search': 0, | |
\ 'code_actions': 0, | |
\ 'did_save': 0, | |
\ 'includeText': 0, | |
\ }, | |
\} | |
endif | |
return l:conn_id | |
endfunction | |
" Remove an LSP connection with a given ID. This is only for tests. | |
1 0.000001 function! ale#lsp#RemoveConnectionWithID(id) abort | |
if has_key(s:connections, a:id) | |
call remove(s:connections, a:id) | |
endif | |
endfunction | |
1 0.000001 function! ale#lsp#ResetConnections() abort | |
let s:connections = {} | |
endfunction | |
" Used only in tests. | |
1 0.000001 function! ale#lsp#GetConnections() abort | |
" This command will throw from the sandbox. | |
let &l:equalprg=&l:equalprg | |
return s:connections | |
endfunction | |
" This is only needed for tests | |
1 0.000001 function! ale#lsp#MarkDocumentAsOpen(id, buffer) abort | |
let l:conn = get(s:connections, a:id, {}) | |
if !empty(l:conn) | |
let l:conn.open_documents[a:buffer] = -1 | |
endif | |
endfunction | |
1 0.000001 function! ale#lsp#GetNextMessageID() abort | |
" Use the current ID | |
let l:id = g:ale_lsp_next_message_id | |
" Increment the ID variable. | |
let g:ale_lsp_next_message_id += 1 | |
" When the ID overflows, reset it to 1. By the time we hit the initial ID | |
" again, the messages will be long gone. | |
if g:ale_lsp_next_message_id < 1 | |
let g:ale_lsp_next_message_id = 1 | |
endif | |
return l:id | |
endfunction | |
" TypeScript messages use a different format. | |
1 0.000001 function! s:CreateTSServerMessageData(message) abort | |
let l:is_notification = a:message[0] | |
let l:obj = { | |
\ 'seq': v:null, | |
\ 'type': 'request', | |
\ 'command': a:message[1][3:], | |
\} | |
if !l:is_notification | |
let l:obj.seq = ale#lsp#GetNextMessageID() | |
endif | |
if len(a:message) > 2 | |
let l:obj.arguments = a:message[2] | |
endif | |
let l:data = json_encode(l:obj) . "\n" | |
return [l:is_notification ? 0 : l:obj.seq, l:data] | |
endfunction | |
" Given a List of one or two items, [method_name] or [method_name, params], | |
" return a List containing [message_id, message_data] | |
1 0.000001 function! ale#lsp#CreateMessageData(message) abort | |
if a:message[1][:2] is# 'ts@' | |
return s:CreateTSServerMessageData(a:message) | |
endif | |
let l:is_notification = a:message[0] | |
let l:obj = { | |
\ 'method': a:message[1], | |
\ 'jsonrpc': '2.0', | |
\} | |
if !l:is_notification | |
let l:obj.id = ale#lsp#GetNextMessageID() | |
endif | |
if len(a:message) > 2 | |
let l:obj.params = a:message[2] | |
endif | |
let l:body = json_encode(l:obj) | |
let l:data = 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body | |
return [l:is_notification ? 0 : l:obj.id, l:data] | |
endfunction | |
1 0.000001 function! ale#lsp#ReadMessageData(data) abort | |
let l:response_list = [] | |
let l:remainder = a:data | |
while 1 | |
" Look for the end of the HTTP headers | |
let l:body_start_index = matchend(l:remainder, "\r\n\r\n") | |
if l:body_start_index < 0 | |
" No header end was found yet. | |
break | |
endif | |
" Parse the Content-Length header. | |
let l:header_data = l:remainder[:l:body_start_index - 4] | |
let l:length_match = matchlist( | |
\ l:header_data, | |
\ '\vContent-Length: *(\d+)' | |
\) | |
if empty(l:length_match) | |
throw "Invalid JSON-RPC header:\n" . l:header_data | |
endif | |
" Split the body and the remainder of the text. | |
let l:remainder_start_index = l:body_start_index + str2nr(l:length_match[1]) | |
if len(l:remainder) < l:remainder_start_index | |
" We don't have enough data yet. | |
break | |
endif | |
let l:body = l:remainder[l:body_start_index : l:remainder_start_index - 1] | |
let l:remainder = l:remainder[l:remainder_start_index :] | |
" Parse the JSON object and add it to the list. | |
call add(l:response_list, json_decode(l:body)) | |
endwhile | |
return [l:remainder, l:response_list] | |
endfunction | |
" Update capabilities from the server, so we know which features the server | |
" supports. | |
1 0.000001 function! s:UpdateCapabilities(conn, capabilities) abort | |
if type(a:capabilities) isnot v:t_dict | |
return | |
endif | |
if get(a:capabilities, 'hoverProvider') is v:true | |
let a:conn.capabilities.hover = 1 | |
endif | |
if type(get(a:capabilities, 'hoverProvider')) is v:t_dict | |
let a:conn.capabilities.hover = 1 | |
endif | |
if get(a:capabilities, 'referencesProvider') is v:true | |
let a:conn.capabilities.references = 1 | |
endif | |
if type(get(a:capabilities, 'referencesProvider')) is v:t_dict | |
let a:conn.capabilities.references = 1 | |
endif | |
if get(a:capabilities, 'renameProvider') is v:true | |
let a:conn.capabilities.rename = 1 | |
endif | |
if type(get(a:capabilities, 'renameProvider')) is v:t_dict | |
let a:conn.capabilities.rename = 1 | |
endif | |
if get(a:capabilities, 'codeActionProvider') is v:true | |
let a:conn.capabilities.code_actions = 1 | |
endif | |
if type(get(a:capabilities, 'codeActionProvider')) is v:t_dict | |
let a:conn.capabilities.code_actions = 1 | |
endif | |
if !empty(get(a:capabilities, 'completionProvider')) | |
let a:conn.capabilities.completion = 1 | |
endif | |
if type(get(a:capabilities, 'completionProvider')) is v:t_dict | |
let l:chars = get(a:capabilities.completionProvider, 'triggerCharacters') | |
if type(l:chars) is v:t_list | |
let a:conn.capabilities.completion_trigger_characters = l:chars | |
endif | |
endif | |
if get(a:capabilities, 'definitionProvider') is v:true | |
let a:conn.capabilities.definition = 1 | |
endif | |
if type(get(a:capabilities, 'definitionProvider')) is v:t_dict | |
let a:conn.capabilities.definition = 1 | |
endif | |
if get(a:capabilities, 'typeDefinitionProvider') is v:true | |
let a:conn.capabilities.typeDefinition = 1 | |
endif | |
if type(get(a:capabilities, 'typeDefinitionProvider')) is v:t_dict | |
let a:conn.capabilities.typeDefinition = 1 | |
endif | |
if get(a:capabilities, 'workspaceSymbolProvider') is v:true | |
let a:conn.capabilities.symbol_search = 1 | |
endif | |
if type(get(a:capabilities, 'workspaceSymbolProvider')) is v:t_dict | |
let a:conn.capabilities.symbol_search = 1 | |
endif | |
if type(get(a:capabilities, 'textDocumentSync')) is v:t_dict | |
let l:syncOptions = get(a:capabilities, 'textDocumentSync') | |
if get(l:syncOptions, 'save') is v:true | |
let a:conn.capabilities.did_save = 1 | |
endif | |
if type(get(l:syncOptions, 'save')) is v:t_dict | |
let a:conn.capabilities.did_save = 1 | |
let l:saveOptions = get(l:syncOptions, 'save') | |
if get(l:saveOptions, 'includeText') is v:true | |
let a:conn.capabilities.includeText = 1 | |
endif | |
endif | |
endif | |
endfunction | |
" Update a connection's configuration dictionary and notify LSP servers | |
" of any changes since the last update. Returns 1 if a configuration | |
" update was sent; otherwise 0 will be returned. | |
1 0.000001 function! ale#lsp#UpdateConfig(conn_id, buffer, config) abort | |
let l:conn = get(s:connections, a:conn_id, {}) | |
if empty(l:conn) || a:config ==# l:conn.config " no-custom-checks | |
return 0 | |
endif | |
let l:conn.config = a:config | |
let l:message = ale#lsp#message#DidChangeConfiguration(a:buffer, a:config) | |
call ale#lsp#Send(a:conn_id, l:message) | |
return 1 | |
endfunction | |
1 0.000001 function! ale#lsp#HandleInitResponse(conn, response) abort | |
if get(a:response, 'method', '') is# 'initialize' | |
let a:conn.initialized = 1 | |
elseif type(get(a:response, 'result')) is v:t_dict | |
\&& has_key(a:response.result, 'capabilities') | |
call s:UpdateCapabilities(a:conn, a:response.result.capabilities) | |
let a:conn.initialized = 1 | |
endif | |
if !a:conn.initialized | |
return | |
endif | |
" The initialized message must be sent before everything else. | |
call ale#lsp#Send(a:conn.id, ale#lsp#message#Initialized()) | |
" Call capabilities callbacks queued for the project. | |
for l:Callback in a:conn.init_queue | |
call l:Callback() | |
endfor | |
let a:conn.init_queue = [] | |
endfunction | |
1 0.000001 function! ale#lsp#HandleMessage(conn_id, message) abort | |
let l:conn = get(s:connections, a:conn_id, {}) | |
if empty(l:conn) | |
return | |
endif | |
if type(a:message) isnot v:t_string | |
" Ignore messages that aren't strings. | |
return | |
endif | |
let l:conn.data .= a:message | |
" Parse the objects now if we can, and keep the remaining text. | |
let [l:conn.data, l:response_list] = ale#lsp#ReadMessageData(l:conn.data) | |
" Look for initialize responses first. | |
if !l:conn.initialized | |
for l:response in l:response_list | |
call ale#lsp#HandleInitResponse(l:conn, l:response) | |
endfor | |
endif | |
" If the connection is marked as initialized, call the callbacks with the | |
" responses. | |
if l:conn.initialized | |
for l:response in l:response_list | |
" Call all of the registered handlers with the response. | |
for l:Callback in l:conn.callback_list | |
call ale#util#GetFunction(l:Callback)(a:conn_id, l:response) | |
endfor | |
endfor | |
endif | |
endfunction | |
" Given a connection ID, mark it as a tsserver connection, so it will be | |
" handled that way. | |
1 0.000001 function! ale#lsp#MarkConnectionAsTsserver(conn_id) abort | |
let l:conn = s:connections[a:conn_id] | |
let l:conn.is_tsserver = 1 | |
let l:conn.initialized = 1 | |
" Set capabilities which are supported by tsserver. | |
let l:conn.capabilities.hover = 1 | |
let l:conn.capabilities.references = 1 | |
let l:conn.capabilities.completion = 1 | |
let l:conn.capabilities.completion_trigger_characters = ['.'] | |
let l:conn.capabilities.definition = 1 | |
let l:conn.capabilities.typeDefinition = 1 | |
let l:conn.capabilities.symbol_search = 1 | |
let l:conn.capabilities.rename = 1 | |
let l:conn.capabilities.code_actions = 1 | |
endfunction | |
1 0.000001 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, | |
\ { | |
\ '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) | |
endfunction | |
" Start a program for LSP servers. | |
" | |
" 1 will be returned if the program is running, or 0 if the program could | |
" not be started. | |
1 0.000002 function! ale#lsp#StartProgram(conn_id, executable, command) abort | |
let l:conn = s:connections[a:conn_id] | |
let l:started = 0 | |
if !has_key(l:conn, 'job_id') || !ale#job#HasOpenChannel(l:conn.job_id) | |
let l:options = { | |
\ 'mode': 'raw', | |
\ 'out_cb': {_, message -> ale#lsp#HandleMessage(a:conn_id, message)}, | |
\} | |
if has('win32') | |
let l:job_id = ale#job#StartWithCmd(a:command, l:options) | |
else | |
let l:job_id = ale#job#Start(a:command, l:options) | |
endif | |
let l:started = 1 | |
else | |
let l:job_id = l:conn.job_id | |
endif | |
if l:job_id > 0 | |
let l:conn.job_id = l:job_id | |
endif | |
if l:started && !l:conn.is_tsserver | |
let l:conn.initialized = 0 | |
call s:SendInitMessage(l:conn) | |
endif | |
return l:job_id > 0 | |
endfunction | |
" Connect to an LSP server via TCP. | |
" | |
" 1 will be returned if the connection is running, or 0 if the connection could | |
" not be opened. | |
1 0.000001 function! ale#lsp#ConnectToAddress(conn_id, address) abort | |
let l:conn = s:connections[a:conn_id] | |
let l:started = 0 | |
if !has_key(l:conn, 'channel_id') || !ale#socket#IsOpen(l:conn.channel_id) | |
let l:channel_id = ale#socket#Open(a:address, { | |
\ 'callback': {_, mess -> ale#lsp#HandleMessage(a:conn_id, mess)}, | |
\}) | |
let l:started = 1 | |
else | |
let l:channel_id = l:conn.channel_id | |
endif | |
if l:channel_id >= 0 | |
let l:conn.channel_id = l:channel_id | |
endif | |
if l:started | |
call s:SendInitMessage(l:conn) | |
endif | |
return l:channel_id >= 0 | |
endfunction | |
" Given a connection ID and a callback, register that callback for handling | |
" messages if the connection exists. | |
1 0.000001 function! ale#lsp#RegisterCallback(conn_id, callback) abort | |
let l:conn = get(s:connections, a:conn_id, {}) | |
if !empty(l:conn) | |
" Add the callback to the List if it's not there already. | |
call uniq(sort(add(l:conn.callback_list, a:callback))) | |
endif | |
endfunction | |
" Stop a single LSP connection. | |
1 0.000001 function! ale#lsp#Stop(conn_id) abort | |
if has_key(s:connections, a:conn_id) | |
let l:conn = remove(s:connections, a:conn_id) | |
if has_key(l:conn, 'channel_id') | |
call ale#socket#Close(l:conn.channel_id) | |
elseif has_key(l:conn, 'job_id') | |
call ale#job#Stop(l:conn.job_id) | |
endif | |
endif | |
endfunction | |
1 0.000001 function! ale#lsp#CloseDocument(conn_id) abort | |
endfunction | |
" Stop all LSP connections, closing all jobs and channels, and removing any | |
" queued messages. | |
1 0.000001 function! ale#lsp#StopAll() abort | |
for l:conn_id in keys(s:connections) | |
call ale#lsp#Stop(l:conn_id) | |
endfor | |
endfunction | |
1 0.000001 function! s:SendMessageData(conn, data) abort | |
if has_key(a:conn, 'job_id') | |
call ale#job#SendRaw(a:conn.job_id, a:data) | |
elseif has_key(a:conn, 'channel_id') && ale#socket#IsOpen(a:conn.channel_id) | |
" Send the message to the server | |
call ale#socket#Send(a:conn.channel_id, a:data) | |
else | |
return 0 | |
endif | |
return 1 | |
endfunction | |
" Send a message to an LSP server. | |
" Notifications do not need to be handled. | |
" | |
" Returns -1 when a message is sent, but no response is expected | |
" 0 when the message is not sent and | |
" >= 1 with the message ID when a response is expected. | |
1 0.000001 function! ale#lsp#Send(conn_id, message) abort | |
let l:conn = get(s:connections, a:conn_id, {}) | |
if empty(l:conn) | |
return 0 | |
endif | |
if !l:conn.initialized | |
throw 'LSP server not initialized yet!' | |
endif | |
let [l:id, l:data] = ale#lsp#CreateMessageData(a:message) | |
call s:SendMessageData(l:conn, l:data) | |
return l:id == 0 ? -1 : l:id | |
endfunction | |
" Notify LSP servers or tsserver if a document is opened, if needed. | |
" If a document is opened, 1 will be returned, otherwise 0 will be returned. | |
1 0.000001 function! ale#lsp#OpenDocument(conn_id, buffer, language_id) abort | |
let l:conn = get(s:connections, a:conn_id, {}) | |
let l:opened = 0 | |
if !empty(l:conn) && !has_key(l:conn.open_documents, a:buffer) | |
if l:conn.is_tsserver | |
let l:message = ale#lsp#tsserver_message#Open(a:buffer) | |
else | |
let l:message = ale#lsp#message#DidOpen(a:buffer, a:language_id) | |
endif | |
call ale#lsp#Send(a:conn_id, l:message) | |
let l:conn.open_documents[a:buffer] = getbufvar(a:buffer, 'changedtick') | |
let l:opened = 1 | |
endif | |
return l:opened | |
endfunction | |
" Notify LSP servers or tsserver that a document is closed, if opened before. | |
" If a document is closed, 1 will be returned, otherwise 0 will be returned. | |
" | |
" Only the buffer number is required here. A message will be sent to every | |
" language server that was notified previously of the document being opened. | |
1 0.000001 function! ale#lsp#CloseDocument(buffer) abort | |
let l:closed = 0 | |
" The connection keys are sorted so the messages are easier to test, and | |
" so messages are sent in a consistent order. | |
for l:conn_id in sort(keys(s:connections)) | |
let l:conn = s:connections[l:conn_id] | |
if l:conn.initialized && has_key(l:conn.open_documents, a:buffer) | |
if l:conn.is_tsserver | |
let l:message = ale#lsp#tsserver_message#Close(a:buffer) | |
else | |
let l:message = ale#lsp#message#DidClose(a:buffer) | |
endif | |
call ale#lsp#Send(l:conn_id, l:message) | |
call remove(l:conn.open_documents, a:buffer) | |
let l:closed = 1 | |
endif | |
endfor | |
return l:closed | |
endfunction | |
" Notify LSP servers or tsserver that a document has changed, if needed. | |
" If a notification is sent, 1 will be returned, otherwise 0 will be returned. | |
1 0.000003 function! ale#lsp#NotifyForChanges(conn_id, buffer) abort | |
let l:conn = get(s:connections, a:conn_id, {}) | |
let l:notified = 0 | |
if !empty(l:conn) && has_key(l:conn.open_documents, a:buffer) | |
let l:new_tick = getbufvar(a:buffer, 'changedtick') | |
if l:conn.open_documents[a:buffer] < l:new_tick | |
if l:conn.is_tsserver | |
let l:message = ale#lsp#tsserver_message#Change(a:buffer) | |
else | |
let l:message = ale#lsp#message#DidChange(a:buffer) | |
endif | |
call ale#lsp#Send(a:conn_id, l:message) | |
let l:conn.open_documents[a:buffer] = l:new_tick | |
let l:notified = 1 | |
endif | |
endif | |
return l:notified | |
endfunction | |
" Wait for an LSP server to be initialized. | |
1 0.000001 function! ale#lsp#OnInit(conn_id, Callback) abort | |
let l:conn = get(s:connections, a:conn_id, {}) | |
if empty(l:conn) | |
return | |
endif | |
if l:conn.initialized | |
call a:Callback() | |
else | |
call add(l:conn.init_queue, a:Callback) | |
endif | |
endfunction | |
" Check if an LSP has a given capability. | |
1 0.000001 function! ale#lsp#HasCapability(conn_id, capability) abort | |
let l:conn = get(s:connections, a:conn_id, {}) | |
if empty(l:conn) | |
return 0 | |
endif | |
if type(get(l:conn.capabilities, a:capability, v:null)) isnot v:t_number | |
throw 'Invalid capability ' . a:capability | |
endif | |
return l:conn.capabilities[a:capability] | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp/message.vim | |
Sourced 1 time | |
Total time: 0.000308 | |
Self time: 0.000308 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Language Server Protocol message implementations | |
" | |
" Messages in this movie will be returned in the format | |
" [is_notification, method_name, params?] | |
" | |
" All functions which accept line and column arguments expect them to be 1-based | |
" (the same format as being returned by getpos() and friends), those then | |
" will be converted to 0-based as specified by LSP. | |
1 0.000005 let g:ale_lsp_next_version_id = 1 | |
" The LSP protocols demands that we send every change to a document, including | |
" undo, with incrementing version numbers, so we'll just use one incrementing | |
" ID for everything. | |
1 0.000001 function! ale#lsp#message#GetNextVersionID() abort | |
" Use the current ID | |
let l:id = g:ale_lsp_next_version_id | |
" Increment the ID variable. | |
let g:ale_lsp_next_version_id += 1 | |
" When the ID overflows, reset it to 1. By the time we hit the initial ID | |
" again, the messages will be long gone. | |
if g:ale_lsp_next_version_id < 1 | |
let g:ale_lsp_next_version_id = 1 | |
endif | |
return l:id | |
endfunction | |
1 0.000001 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': a:capabilities, | |
\ 'initializationOptions': a:options, | |
\ 'rootUri': ale#path#ToURI(a:root_path), | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#Initialized() abort | |
return [1, 'initialized', {}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#Shutdown() abort | |
return [0, 'shutdown'] | |
endfunction | |
1 0.000001 function! ale#lsp#message#Exit() abort | |
return [1, 'exit'] | |
endfunction | |
1 0.000001 function! ale#lsp#message#DidOpen(buffer, language_id) abort | |
let l:lines = getbufline(a:buffer, 1, '$') | |
return [1, 'textDocument/didOpen', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ 'languageId': a:language_id, | |
\ 'version': ale#lsp#message#GetNextVersionID(), | |
\ 'text': join(l:lines, "\n") . "\n", | |
\ }, | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#DidChange(buffer) abort | |
let l:lines = getbufline(a:buffer, 1, '$') | |
" For changes, we simply send the full text of the document to the server. | |
return [1, 'textDocument/didChange', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ 'version': ale#lsp#message#GetNextVersionID(), | |
\ }, | |
\ 'contentChanges': [{'text': join(l:lines, "\n") . "\n"}] | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#DidSave(buffer, includeText) abort | |
let l:response = [1, 'textDocument/didSave', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\}] | |
if a:includeText | |
let l:response[2].textDocument.version = ale#lsp#message#GetNextVersionID() | |
let l:response[2].text = ale#util#GetBufferContents(a:buffer) | |
endif | |
return l:response | |
endfunction | |
1 0.000001 function! ale#lsp#message#DidClose(buffer) abort | |
return [1, 'textDocument/didClose', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\}] | |
endfunction | |
1 0.000001 let s:COMPLETION_TRIGGER_INVOKED = 1 | |
1 0.000001 let s:COMPLETION_TRIGGER_CHARACTER = 2 | |
1 0.000001 function! ale#lsp#message#Completion(buffer, line, column, trigger_character) abort | |
let l:message = [0, 'textDocument/completion', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\ 'position': {'line': a:line - 1, 'character': a:column - 1}, | |
\}] | |
if !empty(a:trigger_character) | |
let l:message[2].context = { | |
\ 'triggerKind': s:COMPLETION_TRIGGER_CHARACTER, | |
\ 'triggerCharacter': a:trigger_character, | |
\} | |
endif | |
return l:message | |
endfunction | |
1 0.000001 function! ale#lsp#message#Definition(buffer, line, column) abort | |
return [0, 'textDocument/definition', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\ 'position': {'line': a:line - 1, 'character': a:column - 1}, | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#TypeDefinition(buffer, line, column) abort | |
return [0, 'textDocument/typeDefinition', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\ 'position': {'line': a:line - 1, 'character': a:column - 1}, | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#References(buffer, line, column) abort | |
return [0, 'textDocument/references', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\ 'position': {'line': a:line - 1, 'character': a:column - 1}, | |
\ 'context': {'includeDeclaration': v:false}, | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#Symbol(query) abort | |
return [0, 'workspace/symbol', { | |
\ 'query': a:query, | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#Hover(buffer, line, column) abort | |
return [0, 'textDocument/hover', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\ 'position': {'line': a:line - 1, 'character': a:column - 1}, | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#DidChangeConfiguration(buffer, config) abort | |
return [1, 'workspace/didChangeConfiguration', { | |
\ 'settings': a:config, | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#Rename(buffer, line, column, new_name) abort | |
return [0, 'textDocument/rename', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\ 'position': {'line': a:line - 1, 'character': a:column - 1}, | |
\ 'newName': a:new_name, | |
\}] | |
endfunction | |
1 0.000004 function! ale#lsp#message#CodeAction(buffer, line, column, end_line, end_column, diagnostics) abort | |
return [0, 'textDocument/codeAction', { | |
\ 'textDocument': { | |
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), | |
\ }, | |
\ 'range': { | |
\ 'start': {'line': a:line - 1, 'character': a:column - 1}, | |
\ 'end': {'line': a:end_line - 1, 'character': a:end_column}, | |
\ }, | |
\ 'context': { | |
\ 'diagnostics': a:diagnostics | |
\ }, | |
\}] | |
endfunction | |
1 0.000001 function! ale#lsp#message#ExecuteCommand(command, arguments) abort | |
return [0, 'workspace/executeCommand', { | |
\ 'command': a:command, | |
\ 'arguments': a:arguments, | |
\}] | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/uri.vim | |
Sourced 1 time | |
Total time: 0.000183 | |
Self time: 0.000183 | |
count total (s) self (s) | |
1 0.000004 function! s:EncodeChar(char) abort | |
let l:result = '' | |
for l:index in range(strlen(a:char)) | |
let l:result .= printf('%%%02x', char2nr(a:char[l:index])) | |
endfor | |
return l:result | |
endfunction | |
1 0.000001 function! ale#uri#Encode(value) abort | |
return substitute( | |
\ a:value, | |
\ '\([^a-zA-Z0-9\\/$\-_.!*''(),]\)', | |
\ '\=s:EncodeChar(submatch(1))', | |
\ 'g' | |
\) | |
endfunction | |
1 0.000001 function! ale#uri#Decode(value) abort | |
return substitute( | |
\ a:value, | |
\ '%\(\x\x\)', | |
\ '\=printf("%c", str2nr(submatch(1), 16))', | |
\ 'g' | |
\) | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/guru.vim | |
Sourced 1 time | |
Total time: 0.000267 | |
Self time: 0.000267 | |
count total (s) self (s) | |
" guru.vim -- Vim integration for the Go guru. | |
" don't spam the user when Vim is started in Vi compatibility mode | |
1 0.000007 let s:cpo_save = &cpo | |
1 0.000005 set cpo&vim | |
" guru_cmd returns a dict that contains the command to execute guru. args | |
" is dict with following options: | |
" mode : guru mode, such as 'implements' | |
" format : output format, either 'plain' or 'json' | |
" needs_scope : if 1, adds the current package to the scope | |
" selected : if 1, means it's a range of selection, otherwise it picks up the | |
" offset under the cursor | |
" example output: | |
" {'cmd' : ['guru', '-json', 'implements', 'demo/demo.go:#66']} | |
1 0.000002 function! s:guru_cmd(args) range abort | |
"if !go#package#InGOPATH() | |
"return {'err': 'guru only supports packages within GOPATH'} | |
"endif | |
let mode = a:args.mode | |
let format = a:args.format | |
let needs_scope = a:args.needs_scope | |
let selected = a:args.selected | |
let postype = get(a:args, 'postype', 'cursor') | |
let result = {} | |
"return with a warning if the binary doesn't exist | |
let bin_path = go#path#CheckBinPath("guru") | |
if empty(bin_path) | |
return {'err': "bin path not found"} | |
endif | |
" start constructing the command | |
let cmd = [bin_path, '-tags', go#config#BuildTags()] | |
if &modified | |
let result.stdin_content = go#util#archive() | |
call add(cmd, "-modified") | |
endif | |
" enable outputting in json format | |
if format == "json" | |
call add(cmd, "-json") | |
endif | |
let scopes = go#config#GuruScope() | |
if empty(scopes) | |
" some modes require scope to be defined (such as callers). For these we | |
" choose a sensible setting, which is using the current file's package | |
if needs_scope | |
let pkg = go#package#ImportPath() | |
if pkg == -1 | |
return {'err': "current directory is not inside of a valid GOPATH"} | |
endif | |
let scopes = [pkg] | |
endif | |
endif | |
" Add the scope. | |
if !empty(scopes) | |
" guru expect a comma-separated list of patterns. | |
let l:scope = join(scopes, ",") | |
let result.scope = l:scope | |
call extend(cmd, ["-scope", l:scope]) | |
endif | |
if postype == 'balloon' | |
let pos = printf("#%s", go#util#Offset(v:beval_lnum, v:beval_col)) | |
else | |
let pos = printf("#%s", go#util#OffsetCursor()) | |
if selected != -1 | |
" means we have a range, get it | |
let pos1 = go#util#Offset(line("'<"), col("'<")) | |
let pos2 = go#util#Offset(line("'>"), col("'>")) | |
let pos = printf("#%s,#%s", pos1, pos2) | |
endif | |
endif | |
let l:filename = fnamemodify(expand("%"), ':p:gs?\\?/?') . ':' . pos | |
call extend(cmd, [mode, l:filename]) | |
let result.cmd = cmd | |
return result | |
endfunction | |
" sync_guru runs guru in sync mode with the given arguments | |
1 0.000001 function! s:sync_guru(args) abort | |
let result = s:guru_cmd(a:args) | |
if has_key(result, 'err') | |
call go#util#EchoError(result.err) | |
return -1 | |
endif | |
if !has_key(a:args, 'disable_progress') | |
if a:args.needs_scope | |
call go#util#EchoProgress("analysing with scope ". result.scope . | |
\ " (see ':help go-guru-scope' if this doesn't work)...") | |
elseif a:args.mode !=# 'what' | |
" the query might take time, let us give some feedback | |
call go#util#EchoProgress("analysing ...") | |
endif | |
endif | |
" run, forrest run!!! | |
if has_key(l:result, 'stdin_content') | |
let [l:out, l:err] = go#util#Exec(l:result.cmd, l:result.stdin_content) | |
else | |
let [l:out, l:err] = go#util#Exec(l:result.cmd) | |
endif | |
if has_key(a:args, 'custom_parse') | |
call a:args.custom_parse(l:err, l:out, a:args.mode) | |
else | |
call s:parse_guru_output(l:err, l:out, a:args.mode) | |
endif | |
return l:out | |
endfunc | |
" async_guru runs guru in async mode with the given arguments | |
1 0.000001 function! s:async_guru(args) abort | |
let result = s:guru_cmd(a:args) | |
if has_key(result, 'err') | |
call go#util#EchoError(result.err) | |
return | |
endif | |
let state = { | |
\ 'mode': a:args.mode, | |
\ 'parse' : get(a:args, 'custom_parse', funcref("s:parse_guru_output")) | |
\ } | |
" explicitly bind complete to state so that within it, self will | |
" always refer to state. See :help Partial for more information. | |
let state.complete = function('s:complete', [], state) | |
let opts = { | |
\ 'statustype': get(a:args, 'statustype', a:args.mode), | |
\ 'for': '_', | |
\ 'errorformat': "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m", | |
\ 'complete': state.complete, | |
\ } | |
if has_key(a:args, 'disable_progress') | |
let opts.statustype = '' | |
endif | |
let opts = go#job#Options(l:opts) | |
if has_key(result, 'stdin_content') | |
let l:tmpname = tempname() | |
call writefile(split(result.stdin_content, "\n"), l:tmpname, "b") | |
let l:opts.in_io = "file" | |
let l:opts.in_name = l:tmpname | |
endif | |
call go#job#Start(result.cmd, opts) | |
if a:args.needs_scope && go#config#EchoCommandInfo() && !has_key(a:args, 'disable_progress') | |
call go#util#EchoProgress("analysing with scope " . result.scope . | |
\ " (see ':help go-guru-scope' if this doesn't work)...") | |
endif | |
endfunc | |
1 0.000001 function! s:complete(job, exit_status, messages) dict abort | |
let output = join(a:messages, "\n") | |
call self.parse(a:exit_status, output, self.mode) | |
endfunction | |
" run_guru runs the given guru argument | |
1 0.000001 function! s:run_guru(args) abort | |
if go#util#has_job() | |
let res = s:async_guru(a:args) | |
else | |
let res = s:sync_guru(a:args) | |
endif | |
return res | |
endfunction | |
" Show 'implements' relation for selected package | |
1 0.000001 function! go#guru#Implements(selected) abort | |
let args = { | |
\ 'mode': 'implements', | |
\ 'format': 'plain', | |
\ 'selected': a:selected, | |
\ 'needs_scope': 1, | |
\ } | |
call s:run_guru(args) | |
endfunction | |
" Shows the set of possible objects to which a pointer may point. | |
1 0.000001 function! go#guru#PointsTo(selected) abort | |
let l:args = { | |
\ 'mode': 'pointsto', | |
\ 'format': 'plain', | |
\ 'selected': a:selected, | |
\ 'needs_scope': 1, | |
\ } | |
call s:run_guru(l:args) | |
endfunction | |
" Report the possible constants, global variables, and concrete types that may | |
" appear in a value of type error | |
1 0.000001 function! go#guru#Whicherrs(selected) abort | |
let args = { | |
\ 'mode': 'whicherrs', | |
\ 'format': 'plain', | |
\ 'selected': a:selected, | |
\ 'needs_scope': 1, | |
\ } | |
" TODO(arslan): handle empty case for both sync/async | |
" if empty(out.out) | |
" call go#util#EchoSuccess("no error variables found. Try to change the scope with :GoGuruScope") | |
" return | |
" endif | |
call s:run_guru(args) | |
endfunction | |
" Describe selected syntax: definition, methods, etc | |
1 0.000001 function! go#guru#Describe(selected) abort | |
let args = { | |
\ 'mode': 'describe', | |
\ 'format': 'plain', | |
\ 'selected': a:selected, | |
\ 'needs_scope': 1, | |
\ } | |
call s:run_guru(args) | |
endfunction | |
1 0.000001 function! go#guru#DescribeInfo(showstatus) abort | |
" check if the version of Vim being tested supports json_decode() | |
if !exists("*json_decode") | |
call go#util#EchoError("GoDescribeInfo requires 'json_decode'. Update your Vim/Neovim version.") | |
return | |
endif | |
let args = { | |
\ 'mode': 'describe', | |
\ 'format': 'json', | |
\ 'selected': -1, | |
\ 'needs_scope': 0, | |
\ 'custom_parse': function('s:info'), | |
\ 'disable_progress': a:showstatus == 0, | |
\ } | |
call s:run_guru(args) | |
endfunction | |
1 0.000001 function! s:info(exit_val, output, mode) | |
if a:exit_val != 0 | |
return | |
endif | |
if a:output[0] !=# '{' | |
return | |
endif | |
if empty(a:output) || type(a:output) != type("") | |
return | |
endif | |
let result = json_decode(a:output) | |
if type(result) != type({}) | |
call go#util#EchoError(printf("malformed output from guru: %s", a:output)) | |
return | |
endif | |
if !has_key(result, 'detail') | |
" if there is no detail check if there is a description and print it | |
if has_key(result, "desc") | |
call go#util#EchoInfo(result["desc"]) | |
return | |
endif | |
call go#util#EchoError("detail key is missing. Please open a bug report on vim-go repo.") | |
return | |
endif | |
let detail = result['detail'] | |
let info = "" | |
" guru gives different information based on the detail mode. Let try to | |
" extract the most useful information | |
if detail == "value" | |
if !has_key(result, 'value') | |
call go#util#EchoError("value key is missing. Please open a bug report on vim-go repo.") | |
return | |
endif | |
let val = result["value"] | |
if !has_key(val, 'type') | |
call go#util#EchoError("type key is missing (value.type). Please open a bug report on vim-go repo.") | |
return | |
endif | |
let info = val["type"] | |
elseif detail == "type" | |
if !has_key(result, 'type') | |
call go#util#EchoError("type key is missing. Please open a bug report on vim-go repo.") | |
return | |
endif | |
let type = result["type"] | |
if !has_key(type, 'type') | |
call go#util#EchoError("type key is missing (type.type). Please open a bug report on vim-go repo.") | |
return | |
endif | |
let info = type["type"] | |
elseif detail == "package" | |
if !has_key(result, 'package') | |
call go#util#EchoError("package key is missing. Please open a bug report on vim-go repo.") | |
return | |
endif | |
let package = result["package"] | |
if !has_key(package, 'path') | |
call go#util#EchoError("path key is missing (package.path). Please open a bug report on vim-go repo.") | |
return | |
endif | |
let info = printf("package %s", package["path"]) | |
elseif detail == "unknown" | |
let info = result["desc"] | |
else | |
call go#util#EchoError(printf("unknown detail mode found '%s'. Please open a bug report on vim-go repo", detail)) | |
return | |
endif | |
call go#util#ShowInfo(info) | |
endfunction | |
" Show possible targets of selected function call | |
1 0.000001 function! go#guru#Callees(selected) abort | |
let args = { | |
\ 'mode': 'callees', | |
\ 'format': 'plain', | |
\ 'selected': a:selected, | |
\ 'needs_scope': 1, | |
\ } | |
call s:run_guru(args) | |
endfunction | |
" Show path from callgraph root to selected function | |
1 0.000001 function! go#guru#Callstack(selected) abort | |
let args = { | |
\ 'mode': 'callstack', | |
\ 'format': 'plain', | |
\ 'selected': a:selected, | |
\ 'needs_scope': 1, | |
\ } | |
call s:run_guru(args) | |
endfunction | |
" Show free variables of selection | |
1 0.000000 function! go#guru#Freevars(selected) abort | |
" Freevars requires a selection | |
if a:selected == -1 | |
call go#util#EchoError("GoFreevars requires a selection (range) of code") | |
return | |
endif | |
let args = { | |
\ 'mode': 'freevars', | |
\ 'format': 'plain', | |
\ 'selected': 1, | |
\ 'needs_scope': 0, | |
\ } | |
call s:run_guru(args) | |
endfunction | |
" Show send/receive corresponding to selected channel op | |
1 0.000001 function! go#guru#ChannelPeers(selected) abort | |
let args = { | |
\ 'mode': 'peers', | |
\ 'format': 'plain', | |
\ 'selected': a:selected, | |
\ 'needs_scope': 1, | |
\ } | |
call s:run_guru(args) | |
endfunction | |
" Show all refs to entity denoted by selected identifier | |
1 0.000001 function! go#guru#Referrers(selected) abort | |
let args = { | |
\ 'mode': 'referrers', | |
\ 'format': 'plain', | |
\ 'selected': a:selected, | |
\ 'needs_scope': 0, | |
\ } | |
call s:run_guru(args) | |
endfunction | |
" TODO(bc) factor into a new file, sameids.vim and get rid of the guru adapter | |
" in lsp.vim. | |
1 0.000001 function! go#guru#SameIds(showstatus) abort | |
" check if the version of Vim being tested supports matchaddpos() | |
if !exists("*matchaddpos") | |
call go#util#EchoError("GoSameIds requires 'matchaddpos'. Update your Vim/Neovim version.") | |
return | |
endif | |
" check if the version of Vim being tested supports json_decode() | |
if !exists("*json_decode") | |
call go#util#EchoError("GoSameIds requires 'json_decode'. Update your Vim/Neovim version.") | |
return | |
endif | |
let [l:line, l:col] = getpos('.')[1:2] | |
let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col) | |
call go#lsp#SameIDs(0, expand('%:p'), l:line, l:col, funcref('s:same_ids_highlight')) | |
endfunction | |
1 0.000001 function! s:same_ids_highlight(exit_val, output, mode) abort | |
call go#guru#ClearSameIds() " run after calling guru to reduce flicker. | |
if a:output[0] !=# '{' | |
if !go#config#AutoSameids() | |
call go#util#EchoError(a:output) | |
endif | |
return | |
endif | |
let result = json_decode(a:output) | |
if type(result) != type({}) && !go#config#AutoSameids() | |
call go#util#EchoError("malformed output from guru") | |
return | |
endif | |
if !has_key(result, 'sameids') | |
if !go#config#AutoSameids() | |
call go#util#EchoError("no same_ids founds for the given identifier") | |
endif | |
return | |
endif | |
let poslen = 0 | |
for enclosing in result['enclosing'] | |
if enclosing['desc'] == 'identifier' | |
let poslen = enclosing['end'] - enclosing['start'] | |
break | |
endif | |
endfor | |
" return when there's no identifier to highlight. | |
if poslen == 0 | |
return | |
endif | |
let same_ids = result['sameids'] | |
" highlight the lines | |
let l:matches = [] | |
for item in same_ids | |
let pos = split(item, ':') | |
let l:matches = add(l:matches, [str2nr(pos[-2]), str2nr(pos[-1]), str2nr(poslen)]) | |
endfor | |
call go#util#HighlightPositions('goSameId', l:matches) | |
if go#config#AutoSameids() | |
" re-apply SameIds at the current cursor position at the time the buffer | |
" is redisplayed: e.g. :edit, :GoRename, etc. | |
augroup vim-go-sameids | |
autocmd! * <buffer> | |
if has('textprop') | |
autocmd BufReadPost <buffer> nested call go#guru#SameIds(0) | |
else | |
autocmd BufWinEnter <buffer> nested call go#guru#SameIds(0) | |
endif | |
augroup end | |
endif | |
endfunction | |
" ClearSameIds returns 0 when it removes goSameId groups and non-zero if no | |
" goSameId groups are found. | |
1 0.000001 function! go#guru#ClearSameIds() abort | |
let l:cleared = go#util#ClearHighlights('goSameId') | |
if !l:cleared | |
return 1 | |
endif | |
" remove the autocmds we defined | |
augroup vim-go-sameids | |
autocmd! * <buffer> | |
augroup end | |
return 0 | |
endfunction | |
1 0.000001 function! go#guru#ToggleSameIds() abort | |
if go#guru#ClearSameIds() != 0 | |
call go#guru#SameIds(1) | |
endif | |
endfunction | |
1 0.000001 function! go#guru#AutoToggleSameIds() abort | |
if go#config#AutoSameids() | |
call go#util#EchoProgress("sameids auto highlighting disabled") | |
call go#guru#ClearSameIds() | |
call go#config#SetAutoSameids(0) | |
else | |
call go#util#EchoSuccess("sameids auto highlighting enabled") | |
call go#config#SetAutoSameids(1) | |
endif | |
call go#auto#update_autocmd() | |
endfunction | |
"""""""""""""""""""""""""""""""""""""""" | |
"" HELPER FUNCTIONS | |
"""""""""""""""""""""""""""""""""""""""" | |
" This uses Vim's errorformat to parse the output from Guru's 'plain output | |
" and put it into location list. I believe using errorformat is much more | |
" easier to use. If we need more power we can always switch back to parse it | |
" via regex. Match two possible styles of errorformats: | |
" | |
" 'file:line.col-line2.col2: message' | |
" 'file:line:col: message' | |
" | |
" We discard line2 and col2 for the first errorformat, because it's not | |
" useful and location only has the ability to show one line and column | |
" number | |
1 0.000001 function! s:parse_guru_output(exit_val, output, title) abort | |
if a:exit_val | |
call go#util#EchoError(a:output) | |
return | |
endif | |
let errformat = "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m" | |
let l:listtype = go#list#Type("_guru") | |
call go#list#ParseFormat(l:listtype, errformat, a:output, a:title, 0) | |
let errors = go#list#Get(l:listtype) | |
call go#list#Window(l:listtype, len(errors)) | |
endfunction | |
1 0.000001 function! go#guru#Scope(...) abort | |
if a:0 | |
let scope = a:000 | |
if a:0 == 1 && a:1 == '""' | |
let scope = [] | |
endif | |
call go#config#SetGuruScope(scope) | |
if empty(scope) | |
call go#util#EchoSuccess("guru scope is cleared") | |
else | |
call go#util#EchoSuccess("guru scope changed to: ". join(a:000, ",")) | |
endif | |
return | |
endif | |
let scope = go#config#GuruScope() | |
if empty(scope) | |
call go#util#EchoError("guru scope is not set") | |
else | |
call go#util#EchoSuccess("current guru scope: ". join(scope, ",")) | |
endif | |
endfunction | |
" restore Vi compatibility settings | |
1 0.000003 let &cpo = s:cpo_save | |
1 0.000002 unlet s:cpo_save | |
" vim: sw=2 ts=2 et | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/cursor.vim | |
Sourced 1 time | |
Total time: 0.000142 | |
Self time: 0.000142 | |
count total (s) self (s) | |
1 0.000020 scriptencoding utf-8 | |
" Author: w0rp <devw0rp@gmail.com> | |
" Author: João Paulo S. de Souza <joao.paulo.silvasouza@hotmail.com> | |
" Description: Echoes lint message for the current line, if any | |
" Controls the milliseconds delay before echoing a message. | |
1 0.000006 let g:ale_echo_delay = get(g:, 'ale_echo_delay', 10) | |
" A string format for the echoed message. | |
1 0.000003 let g:ale_echo_msg_format = get(g:, 'ale_echo_msg_format', '%code: %%s') | |
1 0.000001 let s:cursor_timer = -1 | |
1 0.000003 function! ale#cursor#TruncatedEcho(original_message) abort | |
let l:message = a:original_message | |
" Change tabs to spaces. | |
let l:message = substitute(l:message, "\t", ' ', 'g') | |
" Remove any newlines in the message. | |
let l:message = substitute(l:message, "\n", '', 'g') | |
" We need to remember the setting for shortmess and reset it again. | |
let l:shortmess_options = &l:shortmess | |
try | |
let l:cursor_position = getpos('.') | |
" The message is truncated and saved to the history. | |
silent! setlocal shortmess+=T | |
try | |
exec "norm! :echomsg l:message\n" | |
catch /^Vim\%((\a\+)\)\=:E523/ | |
" Fallback into manual truncate (#1987) | |
let l:winwidth = winwidth(0) | |
if l:winwidth < strdisplaywidth(l:message) | |
" Truncate message longer than window width with trailing '...' | |
let l:message = l:message[:l:winwidth - 4] . '...' | |
endif | |
exec 'echomsg l:message' | |
catch /E481/ | |
" Do nothing if running from a visual selection. | |
endtry | |
" Reset the cursor position if we moved off the end of the line. | |
" Using :norm and :echomsg can move the cursor off the end of the | |
" line. | |
if l:cursor_position != getpos('.') | |
call setpos('.', l:cursor_position) | |
endif | |
finally | |
let &l:shortmess = l:shortmess_options | |
endtry | |
endfunction | |
1 0.000001 function! s:StopCursorTimer() abort | |
if s:cursor_timer != -1 | |
call timer_stop(s:cursor_timer) | |
let s:cursor_timer = -1 | |
endif | |
endfunction | |
1 0.000001 function! ale#cursor#EchoCursorWarning(...) abort | |
let l:buffer = bufnr('') | |
if !g:ale_echo_cursor && !g:ale_cursor_detail | |
return | |
endif | |
" Only echo the warnings in normal mode, otherwise we will get problems. | |
if mode(1) isnot# 'n' | |
return | |
endif | |
if ale#ShouldDoNothing(l:buffer) | |
return | |
endif | |
let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer) | |
if g:ale_echo_cursor | |
if !empty(l:loc) | |
let l:format = ale#Var(l:buffer, 'echo_msg_format') | |
let l:msg = ale#GetLocItemMessage(l:loc, l:format) | |
call ale#cursor#TruncatedEcho(l:msg) | |
let l:info.echoed = 1 | |
elseif get(l:info, 'echoed') | |
" We'll only clear the echoed message when moving off errors once, | |
" so we don't continually clear the echo line. | |
execute 'echo' | |
let l:info.echoed = 0 | |
endif | |
endif | |
if g:ale_cursor_detail | |
if !empty(l:loc) | |
call s:ShowCursorDetailForItem(l:loc, {'stay_here': 1}) | |
else | |
call ale#preview#CloseIfTypeMatches('ale-preview') | |
endif | |
endif | |
endfunction | |
1 0.000001 function! ale#cursor#EchoCursorWarningWithDelay() abort | |
let l:buffer = bufnr('') | |
if !g:ale_echo_cursor && !g:ale_cursor_detail | |
return | |
endif | |
" Only echo the warnings in normal mode, otherwise we will get problems. | |
if mode(1) isnot# 'n' | |
return | |
endif | |
call s:StopCursorTimer() | |
let l:pos = getpos('.')[0:2] | |
if !exists('w:last_pos') | |
let w:last_pos = [0, 0, 0] | |
endif | |
" Check the current buffer, line, and column number against the last | |
" recorded position. If the position has actually changed, *then* | |
" we should echo something. Otherwise we can end up doing processing | |
" the echo message far too frequently. | |
if l:pos != w:last_pos | |
let l:delay = ale#Var(l:buffer, 'echo_delay') | |
let w:last_pos = l:pos | |
let s:cursor_timer = timer_start( | |
\ l:delay, | |
\ function('ale#cursor#EchoCursorWarning') | |
\) | |
endif | |
endfunction | |
1 0.000001 function! s:ShowCursorDetailForItem(loc, options) abort | |
let l:stay_here = get(a:options, 'stay_here', 0) | |
let s:last_detailed_line = line('.') | |
let l:message = get(a:loc, 'detail', a:loc.text) | |
let l:lines = split(l:message, "\n") | |
if g:ale_floating_preview || g:ale_detail_to_floating_preview | |
call ale#floating_preview#Show(l:lines) | |
else | |
call ale#preview#Show(l:lines, {'stay_here': l:stay_here}) | |
" Clear the echo message if we manually displayed details. | |
if !l:stay_here | |
execute 'echo' | |
endif | |
endif | |
endfunction | |
1 0.000001 function! ale#cursor#ShowCursorDetail() abort | |
let l:buffer = bufnr('') | |
" Only echo the warnings in normal mode, otherwise we will get problems. | |
if mode() isnot# 'n' | |
return | |
endif | |
if ale#ShouldDoNothing(l:buffer) | |
return | |
endif | |
call s:StopCursorTimer() | |
let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer) | |
if !empty(l:loc) | |
call s:ShowCursorDetailForItem(l:loc, {'stay_here': 0}) | |
endif | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp_window.vim | |
Sourced 1 time | |
Total time: 0.000206 | |
Self time: 0.000206 | |
count total (s) self (s) | |
" Author: suoto <andre820@gmail.com> | |
" Description: Handling of window/* LSP methods, although right now only | |
" handles window/showMessage | |
" Constants for message type codes | |
1 0.000005 let s:LSP_MESSAGE_TYPE_DISABLED = 0 | |
1 0.000001 let s:LSP_MESSAGE_TYPE_ERROR = 1 | |
1 0.000001 let s:LSP_MESSAGE_TYPE_WARNING = 2 | |
1 0.000001 let s:LSP_MESSAGE_TYPE_INFORMATION = 3 | |
1 0.000001 let s:LSP_MESSAGE_TYPE_LOG = 4 | |
" Translate strings from the user config to a number so we can check | |
" severities | |
1 0.000007 let s:CFG_TO_LSP_SEVERITY = { | |
\ 'disabled': s:LSP_MESSAGE_TYPE_DISABLED, | |
\ 'error': s:LSP_MESSAGE_TYPE_ERROR, | |
\ 'warning': s:LSP_MESSAGE_TYPE_WARNING, | |
\ 'information': s:LSP_MESSAGE_TYPE_INFORMATION, | |
\ 'info': s:LSP_MESSAGE_TYPE_INFORMATION, | |
\ 'log': s:LSP_MESSAGE_TYPE_LOG | |
\} | |
" Handle window/showMessage response. | |
" - details: dict containing linter name and format (g:ale_lsp_show_message_format) | |
" - params: dict with the params for the call in the form of {type: number, message: string} | |
1 0.000002 function! ale#lsp_window#HandleShowMessage(linter_name, format, params) abort | |
let l:message = a:params.message | |
let l:type = a:params.type | |
" Get the configured severity level threshold and check if the message | |
" should be displayed or not | |
let l:configured_severity = tolower(get(g:, 'ale_lsp_show_message_severity', 'error')) | |
" If the user has configured with a value we can't find on the conversion | |
" dict, fall back to warning | |
let l:cfg_severity_threshold = get(s:CFG_TO_LSP_SEVERITY, l:configured_severity, s:LSP_MESSAGE_TYPE_WARNING) | |
if l:type > l:cfg_severity_threshold | |
return | |
endif | |
" Severity will depend on the message type | |
if l:type is# s:LSP_MESSAGE_TYPE_ERROR | |
let l:severity = g:ale_echo_msg_error_str | |
elseif l:type is# s:LSP_MESSAGE_TYPE_INFORMATION | |
let l:severity = g:ale_echo_msg_info_str | |
elseif l:type is# s:LSP_MESSAGE_TYPE_LOG | |
let l:severity = g:ale_echo_msg_log_str | |
else | |
" Default to warning just in case | |
let l:severity = g:ale_echo_msg_warning_str | |
endif | |
let l:string = substitute(a:format, '\V%severity%', l:severity, 'g') | |
let l:string = substitute(l:string, '\V%linter%', a:linter_name, 'g') | |
let l:string = substitute(l:string, '\V%s\>', l:message, 'g') | |
call ale#util#ShowMessage(l:string) | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/handlers/unix.vim | |
Sourced 1 time | |
Total time: 0.000206 | |
Self time: 0.000206 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Error handling for errors in a Unix format. | |
1 0.000003 function! s:HandleUnixFormat(buffer, lines, type) abort | |
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):?(\d+)?:? ?(.+)$' | |
let l:output = [] | |
for l:match in ale#util#GetMatches(a:lines, l:pattern) | |
call add(l:output, { | |
\ 'lnum': l:match[1] + 0, | |
\ 'col': l:match[2] + 0, | |
\ 'text': l:match[3], | |
\ 'type': a:type, | |
\}) | |
endfor | |
return l:output | |
endfunction | |
1 0.000003 function! ale#handlers#unix#HandleAsError(buffer, lines) abort | |
return s:HandleUnixFormat(a:buffer, a:lines, 'E') | |
endfunction | |
1 0.000001 function! ale#handlers#unix#HandleAsWarning(buffer, lines) abort | |
return s:HandleUnixFormat(a:buffer, a:lines, 'W') | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim | |
Sourced 1 time | |
Total time: 0.008833 | |
Self time: 0.008698 | |
count total (s) self (s) | |
1 0.000006 scriptencoding utf8 | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Draws error and warning signs into signcolumn | |
" This flag can be set to some integer to control the maximum number of signs | |
" that ALE will set. | |
1 0.000009 let g:ale_max_signs = get(g:, 'ale_max_signs', -1) | |
" This flag can be set to 1 to enable changing the sign column colors when | |
" there are errors. | |
1 0.000002 let g:ale_change_sign_column_color = get(g:, 'ale_change_sign_column_color', 0) | |
" These variables dictate what signs are used to indicate errors and warnings. | |
1 0.000002 let g:ale_sign_error = get(g:, 'ale_sign_error', '>>') | |
1 0.000002 let g:ale_sign_style_error = get(g:, 'ale_sign_style_error', g:ale_sign_error) | |
1 0.000003 let g:ale_sign_warning = get(g:, 'ale_sign_warning', '--') | |
1 0.000002 let g:ale_sign_style_warning = get(g:, 'ale_sign_style_warning', g:ale_sign_warning) | |
1 0.000002 let g:ale_sign_info = get(g:, 'ale_sign_info', g:ale_sign_warning) | |
1 0.000001 let g:ale_sign_priority = get(g:, 'ale_sign_priority', 30) | |
" This variable sets an offset which can be set for sign IDs. | |
" This ID can be changed depending on what IDs are set for other plugins. | |
" The dummy sign will use the ID exactly equal to the offset. | |
1 0.000001 let g:ale_sign_offset = get(g:, 'ale_sign_offset', 1000000) | |
" This flag can be set to 1 to keep sign gutter always open | |
1 0.000001 let g:ale_sign_column_always = get(g:, 'ale_sign_column_always', 0) | |
1 0.000002 let g:ale_sign_highlight_linenrs = get(g:, 'ale_sign_highlight_linenrs', 0) | |
1 0.000003 let s:supports_sign_groups = has('nvim-0.4.2') || has('patch-8.1.614') | |
1 0.000008 if !hlexists('ALEErrorSign') | |
highlight link ALEErrorSign error | |
1 0.000001 endif | |
1 0.000009 if !hlexists('ALEStyleErrorSign') | |
1 0.000010 highlight link ALEStyleErrorSign ALEErrorSign | |
1 0.000000 endif | |
1 0.000002 if !hlexists('ALEWarningSign') | |
highlight link ALEWarningSign todo | |
1 0.000000 endif | |
1 0.000004 if !hlexists('ALEStyleWarningSign') | |
1 0.000005 highlight link ALEStyleWarningSign ALEWarningSign | |
1 0.000000 endif | |
1 0.000002 if !hlexists('ALEInfoSign') | |
highlight link ALEInfoSign ALEWarningSign | |
1 0.000000 endif | |
1 0.000004 if !hlexists('ALESignColumnWithErrors') | |
1 0.000007 highlight link ALESignColumnWithErrors error | |
1 0.000000 endif | |
1 0.000002 function! ale#sign#SetUpDefaultColumnWithoutErrorsHighlight() abort | |
let l:verbose = &verbose | |
set verbose=0 | |
let l:output = execute('highlight SignColumn', 'silent') | |
let &verbose = l:verbose | |
let l:highlight_syntax = join(split(l:output)[2:]) | |
let l:match = matchlist(l:highlight_syntax, '\vlinks to (.+)$') | |
if !empty(l:match) | |
execute 'highlight link ALESignColumnWithoutErrors ' . l:match[1] | |
elseif l:highlight_syntax isnot# 'cleared' | |
execute 'highlight ALESignColumnWithoutErrors ' . l:highlight_syntax | |
endif | |
endfunction | |
1 0.000004 if !hlexists('ALESignColumnWithoutErrors') | |
1 0.008115 0.008001 call ale#sign#SetUpDefaultColumnWithoutErrorsHighlight() | |
1 0.000001 endif | |
" Spaces and backslashes need to be escaped for signs. | |
1 0.000003 function! s:EscapeSignText(sign_text) abort | |
return substitute(substitute(a:sign_text, ' *$', '', ''), '\\\| ', '\\\0', 'g') | |
endfunction | |
" Signs show up on the left for error markers. | |
1 0.000024 0.000017 execute 'sign define ALEErrorSign text=' . s:EscapeSignText(g:ale_sign_error) | |
\ . ' texthl=ALEErrorSign linehl=ALEErrorLine' | |
1 0.000011 0.000007 execute 'sign define ALEStyleErrorSign text=' . s:EscapeSignText(g:ale_sign_style_error) | |
\ . ' texthl=ALEStyleErrorSign linehl=ALEErrorLine' | |
1 0.000013 0.000010 execute 'sign define ALEWarningSign text=' . s:EscapeSignText(g:ale_sign_warning) | |
\ . ' texthl=ALEWarningSign linehl=ALEWarningLine' | |
1 0.000009 0.000006 execute 'sign define ALEStyleWarningSign text=' . s:EscapeSignText(g:ale_sign_style_warning) | |
\ . ' texthl=ALEStyleWarningSign linehl=ALEWarningLine' | |
1 0.000096 0.000092 execute 'sign define ALEInfoSign text=' . s:EscapeSignText(g:ale_sign_info) | |
\ . ' texthl=ALEInfoSign linehl=ALEInfoLine' | |
1 0.000015 sign define ALEDummySign text=\ texthl=SignColumn | |
1 0.000005 if g:ale_sign_highlight_linenrs && has('nvim-0.3.2') | |
if !hlexists('ALEErrorSignLineNr') | |
highlight link ALEErrorSignLineNr CursorLineNr | |
endif | |
if !hlexists('ALEStyleErrorSignLineNr') | |
highlight link ALEStyleErrorSignLineNr CursorLineNr | |
endif | |
if !hlexists('ALEWarningSignLineNr') | |
highlight link ALEWarningSignLineNr CursorLineNr | |
endif | |
if !hlexists('ALEStyleWarningSignLineNr') | |
highlight link ALEStyleWarningSignLineNr CursorLineNr | |
endif | |
if !hlexists('ALEInfoSignLineNr') | |
highlight link ALEInfoSignLineNr CursorLineNr | |
endif | |
sign define ALEErrorSign numhl=ALEErrorSignLineNr | |
sign define ALEStyleErrorSign numhl=ALEStyleErrorSignLineNr | |
sign define ALEWarningSign numhl=ALEWarningSignLineNr | |
sign define ALEStyleWarningSign numhl=ALEStyleWarningSignLineNr | |
sign define ALEInfoSign numhl=ALEInfoSignLineNr | |
1 0.000000 endif | |
1 0.000003 function! ale#sign#GetSignName(sublist) abort | |
let l:priority = g:ale#util#style_warning_priority | |
" Determine the highest priority item for the line. | |
for l:item in a:sublist | |
let l:item_priority = ale#util#GetItemPriority(l:item) | |
if l:item_priority > l:priority | |
let l:priority = l:item_priority | |
endif | |
endfor | |
if l:priority is# g:ale#util#error_priority | |
return 'ALEErrorSign' | |
endif | |
if l:priority is# g:ale#util#warning_priority | |
return 'ALEWarningSign' | |
endif | |
if l:priority is# g:ale#util#style_error_priority | |
return 'ALEStyleErrorSign' | |
endif | |
if l:priority is# g:ale#util#style_warning_priority | |
return 'ALEStyleWarningSign' | |
endif | |
if l:priority is# g:ale#util#info_priority | |
return 'ALEInfoSign' | |
endif | |
" Use the error sign for invalid severities. | |
return 'ALEErrorSign' | |
endfunction | |
1 0.000001 function! s:PriorityCmd() abort | |
if s:supports_sign_groups | |
return ' priority=' . g:ale_sign_priority . ' ' | |
else | |
return '' | |
endif | |
endfunction | |
1 0.000001 function! s:GroupCmd() abort | |
if s:supports_sign_groups | |
return ' group=ale ' | |
else | |
return ' ' | |
endif | |
endfunction | |
" Read sign data for a buffer to a list of lines. | |
1 0.000001 function! ale#sign#ReadSigns(buffer) abort | |
let l:output = execute( | |
\ 'sign place ' . s:GroupCmd() . s:PriorityCmd() | |
\ . ' buffer=' . a:buffer | |
\ ) | |
return split(l:output, "\n") | |
endfunction | |
1 0.000001 function! ale#sign#ParsePattern() abort | |
if s:supports_sign_groups | |
" Matches output like : | |
" line=4 id=1 group=ale name=ALEErrorSign | |
" строка=1 id=1000001 группа=ale имя=ALEErrorSign | |
" 行=1 識別子=1000001 グループ=ale 名前=ALEWarningSign | |
" línea=12 id=1000001 grupo=ale nombre=ALEWarningSign | |
" riga=1 id=1000001 gruppo=ale nome=ALEWarningSign | |
" Zeile=235 id=1000001 Gruppe=ale Name=ALEErrorSign | |
let l:pattern = '\v^.*\=(\d+).*\=(\d+).*\=ale>.*\=(ALE[a-zA-Z]+Sign)' | |
else | |
" Matches output like : | |
" line=4 id=1 name=ALEErrorSign | |
" строка=1 id=1000001 имя=ALEErrorSign | |
" 行=1 識別子=1000001 名前=ALEWarningSign | |
" línea=12 id=1000001 nombre=ALEWarningSign | |
" riga=1 id=1000001 nome=ALEWarningSign | |
" Zeile=235 id=1000001 Name=ALEErrorSign | |
let l:pattern = '\v^.*\=(\d+).*\=(\d+).*\=(ALE[a-zA-Z]+Sign)' | |
endif | |
return l:pattern | |
endfunction | |
" Given a buffer number, return a List of placed signs [line, id, group] | |
1 0.000001 function! ale#sign#ParseSignsWithGetPlaced(buffer) abort | |
let l:signs = sign_getplaced(a:buffer, { 'group': s:supports_sign_groups ? 'ale' : '' })[0].signs | |
let l:result = [] | |
let l:is_dummy_sign_set = 0 | |
for l:sign in l:signs | |
if l:sign['name'] is# 'ALEDummySign' | |
let l:is_dummy_sign_set = 1 | |
else | |
call add(l:result, [ | |
\ str2nr(l:sign['lnum']), | |
\ str2nr(l:sign['id']), | |
\ l:sign['name'], | |
\]) | |
endif | |
endfor | |
return [l:is_dummy_sign_set, l:result] | |
endfunction | |
" Given a list of lines for sign output, return a List of [line, id, group] | |
1 0.000001 function! ale#sign#ParseSigns(line_list) abort | |
let l:pattern =ale#sign#ParsePattern() | |
let l:result = [] | |
let l:is_dummy_sign_set = 0 | |
for l:line in a:line_list | |
let l:match = matchlist(l:line, l:pattern) | |
if len(l:match) > 0 | |
if l:match[3] is# 'ALEDummySign' | |
let l:is_dummy_sign_set = 1 | |
else | |
call add(l:result, [ | |
\ str2nr(l:match[1]), | |
\ str2nr(l:match[2]), | |
\ l:match[3], | |
\]) | |
endif | |
endif | |
endfor | |
return [l:is_dummy_sign_set, l:result] | |
endfunction | |
1 0.000002 function! ale#sign#FindCurrentSigns(buffer) abort | |
if exists('*sign_getplaced') | |
return ale#sign#ParseSignsWithGetPlaced(a:buffer) | |
else | |
let l:line_list = ale#sign#ReadSigns(a:buffer) | |
return ale#sign#ParseSigns(l:line_list) | |
endif | |
endfunction | |
" Given a loclist, group the List into with one List per line. | |
1 0.000001 function! s:GroupLoclistItems(buffer, loclist) abort | |
let l:grouped_items = [] | |
let l:last_lnum = -1 | |
for l:obj in a:loclist | |
if l:obj.bufnr != a:buffer | |
continue | |
endif | |
" Create a new sub-List when we hit a new line. | |
if l:obj.lnum != l:last_lnum | |
call add(l:grouped_items, []) | |
endif | |
call add(l:grouped_items[-1], l:obj) | |
let l:last_lnum = l:obj.lnum | |
endfor | |
return l:grouped_items | |
endfunction | |
1 0.000001 function! s:UpdateLineNumbers(buffer, current_sign_list, loclist) abort | |
let l:line_map = {} | |
let l:line_numbers_changed = 0 | |
for [l:line, l:sign_id, l:name] in a:current_sign_list | |
let l:line_map[l:sign_id] = l:line | |
endfor | |
for l:item in a:loclist | |
if l:item.bufnr == a:buffer | |
let l:lnum = get(l:line_map, get(l:item, 'sign_id', 0), 0) | |
if l:lnum && l:item.lnum != l:lnum | |
let l:item.lnum = l:lnum | |
let l:line_numbers_changed = 1 | |
endif | |
endif | |
endfor | |
" When the line numbers change, sort the list again | |
if l:line_numbers_changed | |
call sort(a:loclist, 'ale#util#LocItemCompare') | |
endif | |
endfunction | |
1 0.000001 function! s:BuildSignMap(buffer, current_sign_list, grouped_items) abort | |
let l:max_signs = ale#Var(a:buffer, 'max_signs') | |
if l:max_signs is 0 | |
let l:selected_grouped_items = [] | |
elseif type(l:max_signs) is v:t_number && l:max_signs > 0 | |
let l:selected_grouped_items = a:grouped_items[:l:max_signs - 1] | |
else | |
let l:selected_grouped_items = a:grouped_items | |
endif | |
let l:sign_map = {} | |
let l:sign_offset = g:ale_sign_offset | |
for [l:line, l:sign_id, l:name] in a:current_sign_list | |
let l:sign_info = get(l:sign_map, l:line, { | |
\ 'current_id_list': [], | |
\ 'current_name_list': [], | |
\ 'new_id': 0, | |
\ 'new_name': '', | |
\ 'items': [], | |
\}) | |
" Increment the sign offset for new signs, by the maximum sign ID. | |
if l:sign_id > l:sign_offset | |
let l:sign_offset = l:sign_id | |
endif | |
" Remember the sign names and IDs in separate Lists, so they are easy | |
" to work with. | |
call add(l:sign_info.current_id_list, l:sign_id) | |
call add(l:sign_info.current_name_list, l:name) | |
let l:sign_map[l:line] = l:sign_info | |
endfor | |
for l:group in l:selected_grouped_items | |
let l:line = l:group[0].lnum | |
let l:sign_info = get(l:sign_map, l:line, { | |
\ 'current_id_list': [], | |
\ 'current_name_list': [], | |
\ 'new_id': 0, | |
\ 'new_name': '', | |
\ 'items': [], | |
\}) | |
let l:sign_info.new_name = ale#sign#GetSignName(l:group) | |
let l:sign_info.items = l:group | |
let l:index = index( | |
\ l:sign_info.current_name_list, | |
\ l:sign_info.new_name | |
\) | |
if l:index >= 0 | |
" We have a sign with this name already, so use the same ID. | |
let l:sign_info.new_id = l:sign_info.current_id_list[l:index] | |
else | |
" This sign name replaces the previous name, so use a new ID. | |
let l:sign_info.new_id = l:sign_offset + 1 | |
let l:sign_offset += 1 | |
endif | |
let l:sign_map[l:line] = l:sign_info | |
endfor | |
return l:sign_map | |
endfunction | |
1 0.000001 function! ale#sign#GetSignCommands(buffer, was_sign_set, sign_map) abort | |
let l:command_list = [] | |
let l:is_dummy_sign_set = a:was_sign_set | |
" Set the dummy sign if we need to. | |
" The dummy sign is needed to keep the sign column open while we add | |
" and remove signs. | |
if !l:is_dummy_sign_set && (!empty(a:sign_map) || g:ale_sign_column_always) | |
call add(l:command_list, 'sign place ' | |
\ . g:ale_sign_offset | |
\ . s:GroupCmd() | |
\ . s:PriorityCmd() | |
\ . ' line=1 name=ALEDummySign ' | |
\ . ' buffer=' . a:buffer | |
\) | |
let l:is_dummy_sign_set = 1 | |
endif | |
" Place new items first. | |
for [l:line_str, l:info] in items(a:sign_map) | |
if l:info.new_id | |
" Save the sign IDs we are setting back on our loclist objects. | |
" These IDs will be used to preserve items which are set many times. | |
for l:item in l:info.items | |
let l:item.sign_id = l:info.new_id | |
endfor | |
if index(l:info.current_id_list, l:info.new_id) < 0 | |
call add(l:command_list, 'sign place ' | |
\ . (l:info.new_id) | |
\ . s:GroupCmd() | |
\ . s:PriorityCmd() | |
\ . ' line=' . l:line_str | |
\ . ' name=' . (l:info.new_name) | |
\ . ' buffer=' . a:buffer | |
\) | |
endif | |
endif | |
endfor | |
" Remove signs without new IDs. | |
for l:info in values(a:sign_map) | |
for l:current_id in l:info.current_id_list | |
if l:current_id isnot l:info.new_id | |
call add(l:command_list, 'sign unplace ' | |
\ . l:current_id | |
\ . s:GroupCmd() | |
\ . ' buffer=' . a:buffer | |
\) | |
endif | |
endfor | |
endfor | |
" Remove the dummy sign to close the sign column if we need to. | |
if l:is_dummy_sign_set && !g:ale_sign_column_always | |
call add(l:command_list, 'sign unplace ' | |
\ . g:ale_sign_offset | |
\ . s:GroupCmd() | |
\ . ' buffer=' . a:buffer | |
\) | |
endif | |
return l:command_list | |
endfunction | |
" This function will set the signs which show up on the left. | |
1 0.000001 function! ale#sign#SetSigns(buffer, loclist) abort | |
if !bufexists(str2nr(a:buffer)) | |
" Stop immediately when attempting to set signs for a buffer which | |
" does not exist. | |
return | |
endif | |
" Find the current markers | |
let [l:is_dummy_sign_set, l:current_sign_list] = | |
\ ale#sign#FindCurrentSigns(a:buffer) | |
" Update the line numbers for items from before which may have moved. | |
call s:UpdateLineNumbers(a:buffer, l:current_sign_list, a:loclist) | |
" Group items after updating the line numbers. | |
let l:grouped_items = s:GroupLoclistItems(a:buffer, a:loclist) | |
" Build a map of current and new signs, with the lines as the keys. | |
let l:sign_map = s:BuildSignMap( | |
\ a:buffer, | |
\ l:current_sign_list, | |
\ l:grouped_items, | |
\) | |
let l:command_list = ale#sign#GetSignCommands( | |
\ a:buffer, | |
\ l:is_dummy_sign_set, | |
\ l:sign_map, | |
\) | |
" Change the sign column color if the option is on. | |
if g:ale_change_sign_column_color && !empty(a:loclist) | |
highlight clear SignColumn | |
highlight link SignColumn ALESignColumnWithErrors | |
endif | |
for l:command in l:command_list | |
silent! execute l:command | |
endfor | |
" Reset the sign column color when there are no more errors. | |
if g:ale_change_sign_column_color && empty(a:loclist) | |
highlight clear SignColumn | |
highlight link SignColumn ALESignColumnWithoutErrors | |
endif | |
endfunction | |
" Remove all signs. | |
1 0.000001 function! ale#sign#Clear() abort | |
if s:supports_sign_groups | |
sign unplace group=ale * | |
else | |
sign unplace * | |
endif | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/list.vim | |
Sourced 1 time | |
Total time: 0.000344 | |
Self time: 0.000344 | |
count total (s) self (s) | |
" Author: Bjorn Neergaard <bjorn@neersighted.com>, modified by Yann fery <yann@fery.me> | |
" Description: Manages the loclist and quickfix lists | |
" This flag dictates if ale open the configured loclist | |
1 0.000011 let g:ale_open_list = get(g:, 'ale_open_list', 0) | |
" This flag dictates if ale keeps open loclist even if there is no error in loclist | |
1 0.000002 let g:ale_keep_list_window_open = get(g:, 'ale_keep_list_window_open', 0) | |
" This flag dictates that quickfix windows should be opened vertically | |
1 0.000003 let g:ale_list_vertical = get(g:, 'ale_list_vertical', 0) | |
" The window size to set for the quickfix and loclist windows | |
1 0.000001 let g:ale_list_window_size = get(g:, 'ale_list_window_size', 10) | |
" A string format for the loclist messages. | |
1 0.000004 let g:ale_loclist_msg_format = get(g:, 'ale_loclist_msg_format', | |
\ get(g:, 'ale_echo_msg_format', '%code: %%s') | |
\) | |
1 0.000002 if !exists('s:timer_args') | |
1 0.000001 let s:timer_args = {} | |
1 0.000000 endif | |
" Return 1 if there is a buffer with buftype == 'quickfix' in bufffer list | |
1 0.000001 function! ale#list#IsQuickfixOpen() abort | |
let l:res = getqflist({ 'winid' : winnr() }) | |
if has_key(l:res, 'winid') && l:res.winid > 0 | |
return 1 | |
endif | |
let l:res = getloclist(0, { 'winid' : winnr() }) | |
if has_key(l:res, 'winid') && l:res.winid > 0 | |
return 1 | |
endif | |
return 0 | |
endfunction | |
" Check if we should open the list, based on the save event being fired, and | |
" that setting being on, or the setting just being set to `1`. | |
1 0.000001 function! s:ShouldOpen(buffer) abort | |
let l:val = ale#Var(a:buffer, 'open_list') | |
let l:saved = getbufvar(a:buffer, 'ale_save_event_fired', 0) | |
return l:val is 1 || (l:val is# 'on_save' && l:saved) | |
endfunction | |
1 0.000001 function! s:Deduplicate(list) abort | |
let l:list = a:list | |
call sort(l:list, function('ale#util#LocItemCompareWithText')) | |
call uniq(l:list, function('ale#util#LocItemCompareWithText')) | |
return l:list | |
endfunction | |
1 0.000001 function! ale#list#GetCombinedList() abort | |
let l:list = [] | |
for l:info in values(g:ale_buffer_info) | |
call extend(l:list, l:info.loclist) | |
endfor | |
return s:Deduplicate(l:list) | |
endfunction | |
1 0.000001 function! s:FixList(buffer, list) abort | |
let l:format = ale#Var(a:buffer, 'loclist_msg_format') | |
let l:new_list = [] | |
for l:item in a:list | |
let l:fixed_item = copy(l:item) | |
let l:fixed_item.text = ale#GetLocItemMessage(l:item, l:format) | |
if l:item.bufnr == -1 | |
" If the buffer number is invalid, remove it. | |
call remove(l:fixed_item, 'bufnr') | |
endif | |
call add(l:new_list, l:fixed_item) | |
endfor | |
return l:new_list | |
endfunction | |
1 0.000001 function! s:WinFindBuf(buffer) abort | |
return exists('*win_findbuf') ? win_findbuf(str2nr(a:buffer)) : [0] | |
endfunction | |
1 0.000001 function! s:SetListsImpl(timer_id, buffer, loclist) abort | |
let l:title = expand('#' . a:buffer . ':p') | |
if g:ale_set_quickfix | |
let l:quickfix_list = ale#list#GetCombinedList() | |
if has('nvim') | |
call setqflist(s:FixList(a:buffer, l:quickfix_list), ' ', l:title) | |
else | |
call setqflist(s:FixList(a:buffer, l:quickfix_list)) | |
call setqflist([], 'r', {'title': l:title}) | |
endif | |
elseif g:ale_set_loclist | |
" If windows support is off, win_findbuf() may not exist. | |
" We'll set result in the current window, which might not be correct, | |
" but it's better than nothing. | |
let l:ids = s:WinFindBuf(a:buffer) | |
let l:loclist = s:Deduplicate(a:loclist) | |
for l:id in l:ids | |
if has('nvim') | |
call setloclist(l:id, s:FixList(a:buffer, l:loclist), ' ', l:title) | |
else | |
call setloclist(l:id, s:FixList(a:buffer, l:loclist)) | |
call setloclist(l:id, [], 'r', {'title': l:title}) | |
endif | |
endfor | |
endif | |
" Save the current view before opening/closing any window | |
call setbufvar(a:buffer, 'ale_winview', winsaveview()) | |
" Open a window to show the problems if we need to. | |
" | |
" We'll check if the current buffer's List is not empty here, so the | |
" window will only be opened if the current buffer has problems. | |
if s:ShouldOpen(a:buffer) && !empty(a:loclist) | |
let l:winnr = winnr() | |
let l:mode = mode() | |
" open windows vertically instead of default horizontally | |
let l:open_type = '' | |
if ale#Var(a:buffer, 'list_vertical') == 1 | |
let l:open_type = 'vert rightbelow ' | |
endif | |
if g:ale_set_quickfix | |
if !ale#list#IsQuickfixOpen() | |
silent! execute l:open_type . 'copen ' . str2nr(ale#Var(a:buffer, 'list_window_size')) | |
endif | |
elseif g:ale_set_loclist | |
silent! execute l:open_type . 'lopen ' . str2nr(ale#Var(a:buffer, 'list_window_size')) | |
endif | |
" If focus changed, restore it (jump to the last window). | |
if l:winnr isnot# winnr() | |
wincmd p | |
endif | |
" Return to original mode when applicable | |
if mode() != l:mode | |
if l:mode is? 'v' || l:mode is# "\<c-v>" | |
" Reset our last visual selection | |
normal! gv | |
elseif l:mode is? 's' || l:mode is# "\<c-s>" | |
" Reset our last character selection | |
normal! "\<c-g>" | |
endif | |
endif | |
call s:RestoreViewIfNeeded(a:buffer) | |
endif | |
" If ALE isn't currently checking for more problems, close the window if | |
" needed now. This check happens inside of this timer function, so | |
" the window can be closed reliably. | |
if !ale#engine#IsCheckingBuffer(a:buffer) | |
call s:CloseWindowIfNeeded(a:buffer) | |
endif | |
endfunction | |
" Try to restore the window view after closing any of the lists to avoid making | |
" the it moving around, especially useful when on insert mode | |
1 0.000002 function! s:RestoreViewIfNeeded(buffer) abort | |
let l:saved_view = getbufvar(a:buffer, 'ale_winview', {}) | |
" Saved view is empty, can't do anything | |
if empty(l:saved_view) | |
return | |
endif | |
" Check wether the cursor has moved since linting was actually requested. If | |
" the user has indeed moved lines, do nothing | |
let l:current_view = winsaveview() | |
if l:current_view['lnum'] != l:saved_view['lnum'] | |
return | |
endif | |
" Anchor view by topline if the list is set to open horizontally | |
if ale#Var(a:buffer, 'list_vertical') == 0 | |
call winrestview({'topline': l:saved_view['topline']}) | |
endif | |
endfunction | |
1 0.000001 function! ale#list#SetLists(buffer, loclist) abort | |
if get(g:, 'ale_set_lists_synchronously') == 1 | |
\|| getbufvar(a:buffer, 'ale_save_event_fired', 0) | |
" Update lists immediately if running a test synchronously, or if the | |
" buffer was saved. | |
" | |
" The lists need to be updated immediately when saving a buffer so | |
" that we can reliably close window automatically, if so configured. | |
call s:SetListsImpl(-1, a:buffer, a:loclist) | |
else | |
call ale#util#StartPartialTimer( | |
\ 0, | |
\ function('s:SetListsImpl'), | |
\ [a:buffer, a:loclist], | |
\) | |
endif | |
endfunction | |
1 0.000001 function! s:CloseWindowIfNeeded(buffer) abort | |
if ale#Var(a:buffer, 'keep_list_window_open') || !s:ShouldOpen(a:buffer) | |
return | |
endif | |
let l:did_close_any_list = 0 | |
try | |
" Only close windows if the quickfix list or loclist is completely empty, | |
" including errors set through other means. | |
if g:ale_set_quickfix | |
if empty(getqflist()) | |
cclose | |
let l:did_close_any_list = 1 | |
endif | |
else | |
let l:win_ids = s:WinFindBuf(a:buffer) | |
for l:win_id in l:win_ids | |
if g:ale_set_loclist && empty(getloclist(l:win_id)) | |
lclose | |
let l:did_close_any_list = 1 | |
endif | |
endfor | |
endif | |
" Ignore 'Cannot close last window' errors. | |
catch /E444/ | |
endtry | |
if l:did_close_any_list | |
call s:RestoreViewIfNeeded(a:buffer) | |
endif | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/highlight.vim | |
Sourced 1 time | |
Total time: 0.000371 | |
Self time: 0.000371 | |
count total (s) self (s) | |
1 0.000020 scriptencoding utf8 | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: This module implements error/warning highlighting. | |
1 0.000010 if !hlexists('ALEError') | |
highlight link ALEError SpellBad | |
1 0.000000 endif | |
1 0.000005 if !hlexists('ALEStyleError') | |
1 0.000008 highlight link ALEStyleError ALEError | |
1 0.000000 endif | |
1 0.000003 if !hlexists('ALEWarning') | |
highlight link ALEWarning SpellCap | |
1 0.000000 endif | |
1 0.000004 if !hlexists('ALEStyleWarning') | |
1 0.000007 highlight link ALEStyleWarning ALEWarning | |
1 0.000000 endif | |
1 0.000002 if !hlexists('ALEInfo') | |
highlight link ALEInfo ALEWarning | |
1 0.000000 endif | |
" The maximum number of items for the second argument of matchaddpos() | |
1 0.000001 let s:MAX_POS_VALUES = 8 | |
1 0.000005 let s:MAX_COL_SIZE = 1073741824 " pow(2, 30) | |
1 0.000003 let s:has_nvim_highlight = exists('*nvim_buf_add_highlight') && exists('*nvim_buf_clear_namespace') | |
1 0.000001 if s:has_nvim_highlight | |
1 0.000009 let s:ns_id = nvim_create_namespace('ale_highlight') | |
1 0.000000 endif | |
" Wrappers are necessary to test this functionality by faking the calls in tests. | |
1 0.000002 function! ale#highlight#nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) abort | |
" Ignore all errors for adding highlights. | |
try | |
call nvim_buf_add_highlight(a:buffer, a:ns_id, a:hl_group, a:line, a:col_start, a:col_end) | |
catch | |
endtry | |
endfunction | |
1 0.000002 function! ale#highlight#nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end) abort | |
call nvim_buf_clear_namespace(a:buffer, a:ns_id, a:line_start, a:line_end) | |
endfunction | |
1 0.000001 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. | |
return [[[a:line, a:col, a:end_col - a:col + 1]]] | |
endif | |
" Get positions from the first line at the first column, up to a large | |
" integer for highlighting up to the end of the line, followed by | |
" the lines in-between, for highlighting entire lines, and | |
" a highlight for the last line, up to the end column. | |
let l:all_positions = | |
\ [[a:line, a:col, s:MAX_COL_SIZE]] | |
\ + range(a:line + 1, a:end_line - 1) | |
\ + [[a:end_line, 1, a:end_col]] | |
return map( | |
\ range(0, len(l:all_positions) - 1, s:MAX_POS_VALUES), | |
\ 'l:all_positions[v:val : v:val + s:MAX_POS_VALUES - 1]', | |
\) | |
endfunction | |
" Given a loclist for current items to highlight, remove all highlights | |
" except these which have matching loclist item entries. | |
1 0.000001 function! ale#highlight#RemoveHighlights() abort | |
if s:has_nvim_highlight | |
call ale#highlight#nvim_buf_clear_namespace(bufnr(''), s:ns_id, 0, -1) | |
else | |
for l:match in getmatches() | |
if l:match.group =~? '\v^ALE(Style)?(Error|Warning|Info)(Line)?$' | |
call matchdelete(l:match.id) | |
endif | |
endfor | |
endif | |
endfunction | |
" Same semantics of matchaddpos but will use nvim_buf_add_highlight if | |
" available. This involves iterating over the position list, switching from | |
" 1-based indexing to 0-based indexing, and translating the multiple ways | |
" that position can be specified for matchaddpos into line + col_start + | |
" col_end. | |
1 0.000001 function! s:matchaddpos(group, pos_list) abort | |
if s:has_nvim_highlight | |
for l:pos in a:pos_list | |
let l:line = type(l:pos) == v:t_number | |
\ ? l:pos - 1 | |
\ : l:pos[0] - 1 | |
if type(l:pos) == v:t_number || len(l:pos) == 1 | |
let l:col_start = 0 | |
let l:col_end = s:MAX_COL_SIZE | |
else | |
let l:col_start = l:pos[1] - 1 | |
let l:col_end = l:col_start + get(l:pos, 2, 1) | |
endif | |
call ale#highlight#nvim_buf_add_highlight( | |
\ bufnr(''), | |
\ s:ns_id, | |
\ a:group, | |
\ l:line, | |
\ l:col_start, | |
\ l:col_end, | |
\) | |
endfor | |
else | |
call matchaddpos(a:group, a:pos_list) | |
endif | |
endfunction | |
1 0.000001 function! s:highlight_line(bufnr, lnum, group) abort | |
call s:matchaddpos(a:group, [a:lnum]) | |
endfunction | |
1 0.000001 function! s:highlight_range(bufnr, range, group) abort | |
" 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 | |
\ ), | |
\ 's:matchaddpos(a:group, v:val)' | |
\) | |
endfunction | |
1 0.000001 function! ale#highlight#UpdateHighlights() abort | |
let l:item_list = get(b:, 'ale_enabled', 1) && g:ale_enabled | |
\ ? get(b:, 'ale_highlight_items', []) | |
\ : [] | |
call ale#highlight#RemoveHighlights() | |
for l:item in l:item_list | |
if l:item.type is# 'W' | |
if get(l:item, 'sub_type', '') is# 'style' | |
let l:group = 'ALEStyleWarning' | |
else | |
let l:group = 'ALEWarning' | |
endif | |
elseif l:item.type is# 'I' | |
let l:group = 'ALEInfo' | |
elseif get(l:item, 'sub_type', '') is# 'style' | |
let l:group = 'ALEStyleError' | |
else | |
let l:group = 'ALEError' | |
endif | |
let l:range = { | |
\ 'lnum': l:item.lnum, | |
\ 'col': l:item.col, | |
\ 'end_lnum': get(l:item, 'end_lnum', l:item.lnum), | |
\ 'end_col': get(l:item, 'end_col', l:item.col) | |
\} | |
call s:highlight_range(l:item.bufnr, l:range, l:group) | |
endfor | |
" If highlights are enabled and signs are not enabled, we should still | |
" offer line highlights by adding a separate set of highlights. | |
if !g:ale_set_signs | |
let l:available_groups = { | |
\ 'ALEWarningLine': hlexists('ALEWarningLine'), | |
\ 'ALEInfoLine': hlexists('ALEInfoLine'), | |
\ 'ALEErrorLine': hlexists('ALEErrorLine'), | |
\} | |
for l:item in l:item_list | |
if l:item.type is# 'W' | |
let l:group = 'ALEWarningLine' | |
elseif l:item.type is# 'I' | |
let l:group = 'ALEInfoLine' | |
else | |
let l:group = 'ALEErrorLine' | |
endif | |
if l:available_groups[l:group] | |
call s:highlight_line(l:item.bufnr, l:item.lnum, l:group) | |
endif | |
endfor | |
endif | |
endfunction | |
1 0.000001 function! ale#highlight#BufferHidden(buffer) abort | |
" Remove highlights right away when buffers are hidden. | |
" They will be restored later when buffers are entered. | |
call ale#highlight#RemoveHighlights() | |
endfunction | |
1 0.000004 augroup ALEHighlightBufferGroup | |
1 0.000058 autocmd! | |
1 0.000023 autocmd BufEnter * call ale#highlight#UpdateHighlights() | |
1 0.000003 autocmd BufHidden * call ale#highlight#BufferHidden(expand('<abuf>')) | |
1 0.000001 augroup END | |
1 0.000002 function! ale#highlight#SetHighlights(buffer, loclist) abort | |
let l:new_list = getbufvar(a:buffer, 'ale_enabled', 1) && g:ale_enabled | |
\ ? filter(copy(a:loclist), 'v:val.bufnr == a:buffer && v:val.col > 0') | |
\ : [] | |
" Set the list in the buffer variable. | |
call setbufvar(str2nr(a:buffer), 'ale_highlight_items', l:new_list) | |
let l:exclude_list = ale#Var(a:buffer, 'exclude_highlights') | |
if !empty(l:exclude_list) | |
call filter(l:new_list, 'empty(ale#util#GetMatches(v:val.text, l:exclude_list))') | |
endif | |
" Update highlights for the current buffer, which may or may not | |
" be the buffer we just set highlights for. | |
call ale#highlight#UpdateHighlights() | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/hover.vim | |
Sourced 1 time | |
Total time: 0.000346 | |
Self time: 0.000346 | |
count total (s) self (s) | |
" Author: w0rp <devw0rp@gmail.com> | |
" Description: Hover support for LSP linters. | |
1 0.000009 let s:hover_map = {} | |
" Used to get the hover map in tests. | |
1 0.000004 function! ale#hover#GetMap() abort | |
return deepcopy(s:hover_map) | |
endfunction | |
" Used to set the hover map in tests. | |
1 0.000002 function! ale#hover#SetMap(map) abort | |
let s:hover_map = a:map | |
endfunction | |
1 0.000001 function! ale#hover#ClearLSPData() abort | |
let s:hover_map = {} | |
endfunction | |
1 0.000001 function! ale#hover#HandleTSServerResponse(conn_id, response) abort | |
if get(a:response, 'command', '') is# 'quickinfo' | |
\&& has_key(s:hover_map, a:response.request_seq) | |
let l:options = remove(s:hover_map, a:response.request_seq) | |
if get(a:response, 'success', v:false) is v:true | |
\&& get(a:response, 'body', v:null) isnot v:null | |
let l:set_balloons = ale#Var(l:options.buffer, 'set_balloons') | |
" If we pass the show_documentation flag, we should show the full | |
" documentation, and always in the preview window. | |
if get(l:options, 'show_documentation', 0) | |
let l:documentation = get(a:response.body, 'documentation', '') | |
" displayString is not included here, because it can be very | |
" noisy and run on for many lines for complex types. A less | |
" verbose alternative may be nice in future. | |
if !empty(l:documentation) | |
call ale#preview#Show(split(l:documentation, "\n"), { | |
\ 'filetype': 'ale-preview.message', | |
\ 'stay_here': 1, | |
\}) | |
endif | |
elseif get(l:options, 'hover_from_balloonexpr', 0) | |
\&& exists('*balloon_show') | |
\&& (l:set_balloons is 1 || l:set_balloons is# 'hover') | |
call balloon_show(a:response.body.displayString) | |
elseif get(l:options, 'truncated_echo', 0) | |
if !empty(a:response.body.displayString) | |
call ale#cursor#TruncatedEcho(split(a:response.body.displayString, "\n")[0]) | |
endif | |
elseif g:ale_hover_to_floating_preview || g:ale_floating_preview | |
call ale#floating_preview#Show(split(a:response.body.displayString, "\n"), { | |
\ 'filetype': 'ale-preview.message', | |
\}) | |
elseif g:ale_hover_to_preview | |
call ale#preview#Show(split(a:response.body.displayString, "\n"), { | |
\ 'filetype': 'ale-preview.message', | |
\ 'stay_here': 1, | |
\}) | |
else | |
call ale#util#ShowMessage(a:response.body.displayString) | |
endif | |
endif | |
endif | |
endfunction | |
" Convert a language name to another one. | |
" The language name could be an empty string or v:null | |
1 0.000002 function! s:ConvertLanguageName(language) abort | |
return a:language | |
endfunction | |
1 0.000001 function! ale#hover#ParseLSPResult(contents) abort | |
let l:includes = {} | |
let l:highlights = [] | |
let l:lines = [] | |
let l:list = type(a:contents) is v:t_list ? a:contents : [a:contents] | |
let l:region_index = 0 | |
for l:item in l:list | |
if !empty(l:lines) | |
call add(l:lines, '') | |
endif | |
if type(l:item) is v:t_dict && has_key(l:item, 'kind') | |
if l:item.kind is# 'markdown' | |
" Handle markdown values as we handle strings below. | |
let l:item = get(l:item, 'value', '') | |
elseif l:item.kind is# 'plaintext' | |
" We shouldn't try to parse plaintext as markdown. | |
" Pass the lines on and skip parsing them. | |
call extend(l:lines, split(get(l:item, 'value', ''), "\n")) | |
continue | |
endif | |
endif | |
let l:marked_list = [] | |
" If the item is a string, then we should parse it as Markdown text. | |
if type(l:item) is v:t_string | |
let l:fence_language = v:null | |
let l:fence_lines = [] | |
for l:line in split(l:item, "\n") | |
if l:fence_language is v:null | |
" Look for the start of a code fence. (```python, etc.) | |
let l:match = matchlist(l:line, '^```\(.*\)$') | |
if !empty(l:match) | |
let l:fence_language = l:match[1] | |
if !empty(l:marked_list) | |
call add(l:fence_lines, '') | |
endif | |
else | |
if !empty(l:marked_list) | |
\&& l:marked_list[-1][0] isnot v:null | |
call add(l:marked_list, [v:null, ['']]) | |
endif | |
call add(l:marked_list, [v:null, [l:line]]) | |
endif | |
elseif l:line =~# '^```$' | |
" When we hit the end of a code fence, pass the fenced | |
" lines on to the next steps below. | |
call add(l:marked_list, [l:fence_language, l:fence_lines]) | |
let l:fence_language = v:null | |
let l:fence_lines = [] | |
else | |
" Gather lines inside of a code fence. | |
call add(l:fence_lines, l:line) | |
endif | |
endfor | |
" If the result from the LSP server is a {language: ..., value: ...} | |
" Dictionary, then that should be interpreted as if it was: | |
" | |
" ```${language} | |
" ${value} | |
" ``` | |
elseif type(l:item) is v:t_dict | |
\&& has_key(l:item, 'language') | |
\&& type(l:item.language) is v:t_string | |
\&& has_key(l:item, 'value') | |
\&& type(l:item.value) is v:t_string | |
call add( | |
\ l:marked_list, | |
\ [l:item.language, split(l:item.value, "\n")], | |
\) | |
endif | |
for [l:language, l:marked_lines] in l:marked_list | |
if l:language is v:null | |
" NOTE: We could handle other Markdown formatting here. | |
call map( | |
\ l:marked_lines, | |
\ 'substitute(v:val, ''\\_'', ''_'', ''g'')', | |
\) | |
else | |
let l:language = s:ConvertLanguageName(l:language) | |
if !empty(l:language) | |
let l:includes[l:language] = printf( | |
\ 'syntax/%s.vim', | |
\ l:language, | |
\) | |
let l:start = len(l:lines) + 1 | |
let l:end = l:start + len(l:marked_lines) | |
let l:region_index += 1 | |
call add(l:highlights, 'syntax region' | |
\ . ' ALE_hover_' . l:region_index | |
\ . ' start=/\%' . l:start . 'l/' | |
\ . ' end=/\%' . l:end . 'l/' | |
\ . ' contains=@ALE_hover_' . l:language | |
\) | |
endif | |
endif | |
call extend(l:lines, l:marked_lines) | |
endfor | |
endfor | |
let l:include_commands = [] | |
for [l:language, l:lang_path] in sort(items(l:includes)) | |
call add(l:include_commands, 'unlet! b:current_syntax') | |
call add( | |
\ l:include_commands, | |
\ printf('syntax include @ALE_hover_%s %s', l:language, l:lang_path), | |
\) | |
endfor | |
return [l:include_commands + l:highlights, l:lines] | |
endfunction | |
1 0.000001 function! ale#hover#HandleLSPResponse(conn_id, response) abort | |
if has_key(a:response, 'id') | |
\&& has_key(s:hover_map, a:response.id) | |
let l:options = remove(s:hover_map, a:response.id) | |
" If the call did __not__ come from balloonexpr... | |
if !get(l:options, 'hover_from_balloonexpr', 0) | |
let l:buffer = bufnr('') | |
let [l:line, l:column] = getpos('.')[1:2] | |
let l:end = len(getline(l:line)) | |
if l:buffer isnot l:options.buffer | |
\|| l:line isnot l:options.line | |
\|| min([l:column, l:end]) isnot min([l:options.column, l:end]) | |
" ... Cancel display the message if the cursor has moved. | |
return | |
endif | |
endif | |
" The result can be a Dictionary item, a List of the same, or null. | |
let l:result = get(a:response, 'result', v:null) | |
if l:result is v:null | |
return | |
endif | |
let [l:commands, l:lines] = ale#hover#ParseLSPResult(l:result.contents) | |
if !empty(l:lines) | |
let l:set_balloons = ale#Var(l:options.buffer, 'set_balloons') | |
if get(l:options, 'hover_from_balloonexpr', 0) | |
\&& exists('*balloon_show') | |
\&& (l:set_balloons is 1 || l:set_balloons is# 'hover') | |
call balloon_show(join(l:lines, "\n")) | |
elseif get(l:options, 'truncated_echo', 0) | |
call ale#cursor#TruncatedEcho(l:lines[0]) | |
elseif g:ale_hover_to_floating_preview || g:ale_floating_preview | |
call ale#floating_preview#Show(l:lines, { | |
\ 'filetype': 'ale-preview.message', | |
\ 'commands': l:commands, | |
\}) | |
elseif g:ale_hover_to_preview | |
call ale#preview#Show(l:lines, { | |
\ 'filetype': 'ale-preview.message', | |
\ 'stay_here': 1, | |
\ 'commands': l:commands, | |
\}) | |
else | |
call ale#util#ShowMessage(join(l:lines, "\n"), { | |
\ 'commands': l:commands, | |
\}) | |
endif | |
endif | |
endif | |
endfunction | |
1 0.000002 function! s:OnReady(line, column, opt, linter, lsp_details) abort | |
let l:id = a:lsp_details.connection_id | |
if !ale#lsp#HasCapability(l:id, 'hover') | |
return | |
endif | |
let l:buffer = a:lsp_details.buffer | |
let l:Callback = a:linter.lsp is# 'tsserver' | |
\ ? function('ale#hover#HandleTSServerResponse') | |
\ : function('ale#hover#HandleLSPResponse') | |
call ale#lsp#RegisterCallback(l:id, l:Callback) | |
if a:linter.lsp is# 'tsserver' | |
let l:column = a:column | |
let l:message = ale#lsp#tsserver_message#Quickinfo( | |
\ l:buffer, | |
\ a:line, | |
\ l:column | |
\) | |
else | |
" Send a message saying the buffer has changed first, or the | |
" hover position probably won't make sense. | |
call ale#lsp#NotifyForChanges(l:id, l:buffer) | |
let l:column = max([ | |
\ min([a:column, len(getbufline(l:buffer, a:line)[0])]), | |
\ 1, | |
\]) | |
let l:message = ale#lsp#message#Hover(l:buffer, a:line, l:column) | |
endif | |
let l:request_id = ale#lsp#Send(l:id, l:message) | |
let s:hover_map[l:request_id] = { | |
\ 'buffer': l:buffer, | |
\ 'line': a:line, | |
\ 'column': l:column, | |
\ 'hover_from_balloonexpr': get(a:opt, 'called_from_balloonexpr', 0), | |
\ 'show_documentation': get(a:opt, 'show_documentation', 0), | |
\ 'truncated_echo': get(a:opt, 'truncated_echo', 0), | |
\} | |
endfunction | |
" Obtain Hover information for the specified position | |
" Pass optional arguments in the dictionary opt. | |
" Currently, only one key/value is useful: | |
" - called_from_balloonexpr, this flag marks if we want the result from this | |
" ale#hover#Show to display in a balloon if possible | |
" | |
" Currently, the callbacks displays the info from hover : | |
" - in the balloon if opt.called_from_balloonexpr and balloon_show is detected | |
" - as status message otherwise | |
1 0.000002 function! ale#hover#Show(buffer, line, col, opt) abort | |
let l:show_documentation = get(a:opt, 'show_documentation', 0) | |
let l:Callback = function('s:OnReady', [a:line, a:col, a:opt]) | |
for l:linter in ale#linter#Get(getbufvar(a:buffer, '&filetype')) | |
" Only tsserver supports documentation requests at the moment. | |
if !empty(l:linter.lsp) | |
\&& (!l:show_documentation || l:linter.lsp is# 'tsserver') | |
call ale#lsp_linter#StartLSP(a:buffer, l:linter, l:Callback) | |
endif | |
endfor | |
endfunction | |
1 0.000002 let s:last_pos = [0, 0, 0] | |
" This function implements the :ALEHover command. | |
1 0.000001 function! ale#hover#ShowAtCursor() abort | |
let l:buffer = bufnr('') | |
let l:pos = getpos('.') | |
call ale#hover#Show(l:buffer, l:pos[1], l:pos[2], {}) | |
endfunction | |
1 0.000001 function! ale#hover#ShowTruncatedMessageAtCursor() abort | |
let l:buffer = bufnr('') | |
let l:pos = getpos('.')[0:2] | |
if l:pos != s:last_pos | |
let s:last_pos = l:pos | |
let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer) | |
if empty(l:loc) | |
call ale#hover#Show( | |
\ l:buffer, | |
\ l:pos[1], | |
\ l:pos[2], | |
\ {'truncated_echo': 1}, | |
\) | |
endif | |
endif | |
endfunction | |
" This function implements the :ALEDocumentation command. | |
1 0.000001 function! ale#hover#ShowDocumentationAtCursor() abort | |
let l:buffer = bufnr('') | |
let l:pos = getpos('.') | |
let l:options = {'show_documentation': 1} | |
call ale#hover#Show(l:buffer, l:pos[1], l:pos[2], l:options) | |
endfunction | |
SCRIPT /Users/kyle/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/handlers/go.vim | |
Sourced 1 time | |
Total time: 0.000237 | |
Self time: 0.000237 | |
count total (s) self (s) | |
" Author: neersighted <bjorn@neersighted.com> | |
" Description: go vet for Go files | |
" | |
" Author: John Eikenberry <jae@zhar.net> | |
" Description: updated to work with go1.10 | |
" | |
" Author: Ben Paxton <ben@gn32.uk> | |
" Description: moved to generic Golang file from govet | |
" | |
" Author: mostfunkyduck <mostfunkyduck@protonmail.com> | |
" Description: updated to work with go 1.14 | |
1 0.000005 function! ale#handlers#go#Handler(buffer, lines) abort | |
let l:pattern = '\v^%(vet: )?([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? ?(.+)$' | |
let l:output = [] | |
let l:dir = expand('#' . a:buffer . ':p:h') | |
for l:match in ale#util#GetMatches(a:lines, l:pattern) | |
call add(l:output, { | |
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), | |
\ 'lnum': l:match[2] + 0, | |
\ 'col': l:match[3] + 0, | |
\ 'text': l:match[4], | |
\ 'type': 'E', | |
\}) | |
endfor | |
return l:output | |
endfunction | |
FUNCTION go#lsp#DidOpen() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:701 | |
Called 2 times | |
Total time: 0.046444 | |
Self time: 0.000164 | |
count total (s) self (s) | |
2 0.000006 if get(b:, 'go_lsp_did_open', 0) | |
1 0.000000 return | |
1 0.000000 endif | |
1 0.000006 let l:fname = fnamemodify(a:fname, ':p') | |
1 0.000004 if !isdirectory(fnamemodify(l:fname, ':h')) | |
return | |
1 0.000000 endif | |
1 0.003106 0.000005 let l:lsp = s:lspfactory.get() | |
1 0.000002 if !has_key(l:lsp.notificationQueue, l:fname) | |
1 0.000003 let l:lsp.notificationQueue[l:fname] = [] | |
1 0.000000 endif | |
1 0.042994 0.000030 call s:ensureWorkspace(fnamemodify(l:fname, ':h')) | |
1 0.000011 let l:lsp.fileVersions[l:fname] = getbufvar(l:fname, 'changedtick') | |
1 0.000163 0.000079 let l:msg = go#lsp#message#DidOpen(l:fname, join(go#util#GetLines(), "\n") . "\n", l:lsp.fileVersions[l:fname]) | |
1 0.000112 0.000004 let l:state = s:newHandlerState('') | |
" 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. | |
1 0.000001 let b:go_lsp_did_open = 1 | |
1 0.000024 0.000003 return l:lsp.sendMessage(l:msg, l:state) | |
FUNCTION go#config#HighlightExtraTypes() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:424 | |
Called 1 time | |
Total time: 0.000001 | |
Self time: 0.000001 | |
count total (s) self (s) | |
1 0.000001 return get(g:, 'go_highlight_extra_types', 0) | |
FUNCTION go#util#ExecInWorkDir() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:246 | |
Called 3 times | |
Total time: 0.300170 | |
Self time: 0.000167 | |
count total (s) self (s) | |
3 0.000028 if !isdirectory(a:wd) | |
return ['', 1] | |
3 0.000001 endif | |
3 0.001136 0.000015 let l:dir = go#util#Chdir(a:wd) | |
3 0.000001 try | |
3 0.297247 0.000076 let [l:out, l:err] = call('go#util#Exec', [a:cmd] + a:000) | |
3 0.000001 finally | |
3 0.001732 0.000021 call go#util#Chdir(l:dir) | |
3 0.000002 endtry | |
3 0.000008 return [l:out, l:err] | |
FUNCTION <SNR>119_Lint() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale.vim:99 | |
Called 1 time | |
Total time: 0.049268 | |
Self time: 0.001142 | |
count total (s) self (s) | |
" Use the filetype from the buffer | |
1 0.000001 let l:filetype = getbufvar(a:buffer, '&filetype') | |
1 0.023494 0.000006 let l:linters = ale#linter#Get(l:filetype) | |
1 0.000027 0.000006 let l:linters = ale#linter#RemoveIgnored(a:buffer, l:filetype, l:linters) | |
" Tell other sources that they can start checking the buffer now. | |
1 0.000001 let g:ale_want_results_buffer = a:buffer | |
1 0.000161 0.000152 silent doautocmd <nomodeline> User ALEWantResults | |
1 0.000002 unlet! g:ale_want_results_buffer | |
" Don't set up buffer data and so on if there are no linters to run. | |
1 0.000003 if !has_key(g:ale_buffer_info, a:buffer) && empty(l:linters) | |
return | |
1 0.000000 endif | |
" Clear lint_file linters, or only run them if the file exists. | |
1 0.000248 let l:lint_file = empty(l:linters) || (a:should_lint_file && filereadable(expand('#' . a:buffer . ':p'))) | |
1 0.025325 0.000717 call ale#engine#RunLinters(a:buffer, l:linters, l:lint_file) | |
FUNCTION ale#events#LintOnEnter() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/events.vim:42 | |
Called 1 time | |
Total time: 0.049390 | |
Self time: 0.000022 | |
count total (s) self (s) | |
" Unmark a file as being changed outside of Vim after we try to check it. | |
1 0.000002 call setbufvar(a:buffer, 'ale_file_changed', 0) | |
1 0.000014 0.000007 if ale#Var(a:buffer, 'enabled') && g:ale_lint_on_enter | |
1 0.049372 0.000010 call ale#Queue(0, 'lint_file', a:buffer) | |
1 0.000000 endif | |
FUNCTION <SNR>118_IndentLinesEnable() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/indentLine/after/plugin/indentLine.vim:148 | |
Called 1 time | |
Total time: 0.000235 | |
Self time: 0.000212 | |
count total (s) self (s) | |
1 0.000001 if g:indentLine_newVersion | |
1 0.000001 if exists("b:indentLine_enabled") && b:indentLine_enabled == 0 | |
return | |
1 0.000000 endif | |
1 0.000001 if !exists("w:indentLine_indentLineId") | |
let w:indentLine_indentLineId = [] | |
1 0.000000 endif | |
1 0.000026 0.000003 call s:SetConcealOption() | |
1 0.000001 if g:indentLine_showFirstIndentLevel | |
call add(w:indentLine_indentLineId, matchadd('Conceal', '^ ', 0, -1, {'conceal': g:indentLine_first_char})) | |
1 0.000000 endif | |
1 0.000002 let space = &l:shiftwidth == 0 ? &l:tabstop : &l:shiftwidth | |
1 0.000001 let n = len(g:indentLine_char_list) | |
1 0.000001 let level = 0 | |
21 0.000009 for i in range(space+1, space * g:indentLine_indentLevel + 1, space) | |
20 0.000006 if n > 0 | |
20 0.000016 let char = g:indentLine_char_list[level % n] | |
20 0.000008 let level += 1 | |
else | |
let char = g:indentLine_char | |
20 0.000004 endif | |
20 0.000132 call add(w:indentLine_indentLineId, matchadd('Conceal', '^\s\+\zs\%'.i.'v ', 0, -1, {'conceal': char})) | |
21 0.000004 endfor | |
1 0.000000 return | |
endif | |
if exists("b:indentLine_enabled") && b:indentLine_enabled | |
return | |
else | |
let b:indentLine_enabled = 1 | |
endif | |
call s:SetConcealOption() | |
let g:mysyntaxfile = g:indentLine_mysyntaxfile | |
let space = &l:shiftwidth == 0 ? &l:tabstop : &l:shiftwidth | |
if g:indentLine_showFirstIndentLevel | |
execute 'syntax match IndentLine /^ / containedin=ALL conceal cchar=' . g:indentLine_first_char | |
endif | |
if g:indentLine_faster | |
execute 'syntax match IndentLineSpace /^\s\+/ containedin=ALL contains=IndentLine' | |
execute 'syntax match IndentLine / \{'.(space-1).'}\zs / contained conceal cchar=' . g:indentLine_char | |
execute 'syntax match IndentLine /\t\zs / contained conceal cchar=' . g:indentLine_char | |
else | |
let pattern = line('$') < g:indentLine_maxLines ? 'v' : 'c' | |
for i in range(space+1, space * g:indentLine_indentLevel + 1, space) | |
execute 'syntax match IndentLine /\%(^\s\+\)\@<=\%'.i.pattern.' / containedin=ALL conceal cchar=' . g:indentLine_char | |
endfor | |
endif | |
FUNCTION <SNR>176_StopCursorTimer() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/cursor.vim:56 | |
Called 2 times | |
Total time: 0.000028 | |
Self time: 0.000028 | |
count total (s) self (s) | |
2 0.000005 if s:cursor_timer != -1 | |
1 0.000008 call timer_stop(s:cursor_timer) | |
1 0.000003 let s:cursor_timer = -1 | |
2 0.000001 endif | |
FUNCTION ale#lsp#RegisterCallback() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp.vim:524 | |
Called 1 time | |
Total time: 0.000082 | |
Self time: 0.000082 | |
count total (s) self (s) | |
1 0.000012 let l:conn = get(s:connections, a:conn_id, {}) | |
1 0.000065 if !empty(l:conn) | |
" Add the callback to the List if it's not there already. | |
1 0.000003 call uniq(sort(add(l:conn.callback_list, a:callback))) | |
1 0.000000 endif | |
FUNCTION <SNR>180_SetListsImpl() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/list.vim:90 | |
Called 3 times | |
Total time: 0.021357 | |
Self time: 0.002002 | |
count total (s) self (s) | |
3 0.001477 let l:title = expand('#' . a:buffer . ':p') | |
3 0.000004 if g:ale_set_quickfix | |
let l:quickfix_list = ale#list#GetCombinedList() | |
if has('nvim') | |
call setqflist(s:FixList(a:buffer, l:quickfix_list), ' ', l:title) | |
else | |
call setqflist(s:FixList(a:buffer, l:quickfix_list)) | |
call setqflist([], 'r', {'title': l:title}) | |
endif | |
3 0.000003 elseif g:ale_set_loclist | |
" If windows support is off, win_findbuf() may not exist. | |
" We'll set result in the current window, which might not be correct, | |
" but it's better than nothing. | |
3 0.000073 0.000059 let l:ids = s:WinFindBuf(a:buffer) | |
3 0.014058 0.000016 let l:loclist = s:Deduplicate(a:loclist) | |
6 0.000007 for l:id in l:ids | |
3 0.000008 if has('nvim') | |
3 0.005267 0.000112 call setloclist(l:id, s:FixList(a:buffer, l:loclist), ' ', l:title) | |
else | |
call setloclist(l:id, s:FixList(a:buffer, l:loclist)) | |
call setloclist(l:id, [], 'r', {'title': l:title}) | |
3 0.000001 endif | |
6 0.000002 endfor | |
3 0.000001 endif | |
" Save the current view before opening/closing any window | |
3 0.000117 call setbufvar(a:buffer, 'ale_winview', winsaveview()) | |
" Open a window to show the problems if we need to. | |
" | |
" We'll check if the current buffer's List is not empty here, so the | |
" window will only be opened if the current buffer has problems. | |
3 0.000051 0.000014 if s:ShouldOpen(a:buffer) && !empty(a:loclist) | |
let l:winnr = winnr() | |
let l:mode = mode() | |
" open windows vertically instead of default horizontally | |
let l:open_type = '' | |
if ale#Var(a:buffer, 'list_vertical') == 1 | |
let l:open_type = 'vert rightbelow ' | |
endif | |
if g:ale_set_quickfix | |
if !ale#list#IsQuickfixOpen() | |
silent! execute l:open_type . 'copen ' . str2nr(ale#Var(a:buffer, 'list_window_size')) | |
endif | |
elseif g:ale_set_loclist | |
silent! execute l:open_type . 'lopen ' . str2nr(ale#Var(a:buffer, 'list_window_size')) | |
endif | |
" If focus changed, restore it (jump to the last window). | |
if l:winnr isnot# winnr() | |
wincmd p | |
endif | |
" Return to original mode when applicable | |
if mode() != l:mode | |
if l:mode is? 'v' || l:mode is# "\<c-v>" | |
" Reset our last visual selection | |
normal! gv | |
elseif l:mode is? 's' || l:mode is# "\<c-s>" | |
" Reset our last character selection | |
normal! "\<c-g>" | |
endif | |
endif | |
call s:RestoreViewIfNeeded(a:buffer) | |
3 0.000001 endif | |
" If ALE isn't currently checking for more problems, close the window if | |
" needed now. This check happens inside of this timer function, so | |
" the window can be closed reliably. | |
3 0.000030 0.000011 if !ale#engine#IsCheckingBuffer(a:buffer) | |
1 0.000094 0.000006 call s:CloseWindowIfNeeded(a:buffer) | |
3 0.000001 endif | |
FUNCTION <SNR>144_debug() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:1327 | |
Called 40 times | |
Total time: 0.000417 | |
Self time: 0.000417 | |
count total (s) self (s) | |
40 0.000082 let l:shouldStart = len(s:log) == 0 | |
40 0.000088 let s:log = add(s:log, [a:event, a:data]) | |
40 0.000025 if l:shouldStart | |
18 0.000135 call timer_start(10, function('s:debugasync', [])) | |
40 0.000016 endif | |
FUNCTION <SNR>165_GetLintFileSlots() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:591 | |
Called 1 time | |
Total time: 0.000045 | |
Self time: 0.000045 | |
count total (s) self (s) | |
1 0.000001 let l:linter_slots = [] | |
5 0.000004 for l:linter in a:linters | |
4 0.000004 let l:LintFile = l:linter.lint_file | |
4 0.000004 if type(l:LintFile) is v:t_func | |
let l:LintFile = l:LintFile(a:buffer) | |
4 0.000001 endif | |
4 0.000006 call add(l:linter_slots, [l:LintFile, l:linter]) | |
5 0.000016 endfor | |
1 0.000001 return l:linter_slots | |
FUNCTION go#config#AutoSameids() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:246 | |
Called 2 times | |
Total time: 0.000003 | |
Self time: 0.000003 | |
count total (s) self (s) | |
2 0.000002 return get(g:, 'go_auto_sameids', 0) | |
FUNCTION ale#linter#Get() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/linter.vim:367 | |
Called 1 time | |
Total time: 0.023488 | |
Self time: 0.000154 | |
count total (s) self (s) | |
1 0.000001 let l:possibly_duplicated_linters = [] | |
" Handle dot-separated filetypes. | |
2 0.000005 for l:original_filetype in split(a:original_filetypes, '\.') | |
1 0.000032 0.000007 let l:filetype = ale#linter#ResolveFiletype(l:original_filetype) | |
1 0.000019 0.000006 let l:linter_names = s:GetLinterNames(l:original_filetype) | |
1 0.023300 0.000005 let l:all_linters = ale#linter#GetAll(l:filetype) | |
1 0.000001 let l:filetype_linters = [] | |
1 0.000002 if type(l:linter_names) is v:t_string && l:linter_names is# 'all' | |
let l:filetype_linters = l:all_linters | |
1 0.000001 elseif type(l:linter_names) is v:t_list | |
" Select only the linters we or the user has specified. | |
15 0.000005 for l:linter in l:all_linters | |
14 0.000017 let l:name_list = [l:linter.name] + l:linter.aliases | |
25 0.000010 for l:name in l:name_list | |
15 0.000012 if index(l:linter_names, l:name) >= 0 | |
4 0.000003 call add(l:filetype_linters, l:linter) | |
4 0.000002 break | |
11 0.000002 endif | |
25 0.000005 endfor | |
15 0.000003 endfor | |
1 0.000001 endif | |
1 0.000001 call extend(l:possibly_duplicated_linters, l:filetype_linters) | |
2 0.000001 endfor | |
1 0.000001 let l:name_list = [] | |
1 0.000001 let l:combined_linters = [] | |
" Make sure we override linters so we don't get two with the same name, | |
" like 'eslint' for both 'javascript' and 'typescript' | |
" | |
" Note that the reverse calls here modify the List variables. | |
5 0.000003 for l:linter in reverse(l:possibly_duplicated_linters) | |
4 0.000003 if index(l:name_list, l:linter.name) < 0 | |
4 0.000004 call add(l:name_list, l:linter.name) | |
4 0.000003 call add(l:combined_linters, l:linter) | |
4 0.000001 endif | |
5 0.000001 endfor | |
1 0.000001 return reverse(l:combined_linters) | |
FUNCTION <SNR>179_UpdateLineNumbers() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:282 | |
Called 3 times | |
Total time: 0.000304 | |
Self time: 0.000304 | |
count total (s) self (s) | |
3 0.000004 let l:line_map = {} | |
3 0.000003 let l:line_numbers_changed = 0 | |
23 0.000015 for [l:line, l:sign_id, l:name] in a:current_sign_list | |
20 0.000017 let l:line_map[l:sign_id] = l:line | |
23 0.000005 endfor | |
59 0.000017 for l:item in a:loclist | |
56 0.000025 if l:item.bufnr == a:buffer | |
56 0.000082 let l:lnum = get(l:line_map, get(l:item, 'sign_id', 0), 0) | |
56 0.000030 if l:lnum && l:item.lnum != l:lnum | |
let l:item.lnum = l:lnum | |
let l:line_numbers_changed = 1 | |
56 0.000010 endif | |
56 0.000009 endif | |
59 0.000011 endfor | |
" When the line numbers change, sort the list again | |
3 0.000002 if l:line_numbers_changed | |
call sort(a:loclist, 'ale#util#LocItemCompare') | |
3 0.000001 endif | |
FUNCTION <SNR>179_EscapeSignText() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:73 | |
Called 5 times | |
Total time: 0.000020 | |
Self time: 0.000020 | |
count total (s) self (s) | |
5 0.000019 return substitute(substitute(a:sign_text, ' *$', '', ''), '\\\| ', '\\\0', 'g') | |
FUNCTION ale#lsp#CloseDocument() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp.vim:619 | |
Called 1 time | |
Total time: 0.000030 | |
Self time: 0.000030 | |
count total (s) self (s) | |
1 0.000002 let l:closed = 0 | |
" The connection keys are sorted so the messages are easier to test, and | |
" so messages are sent in a consistent order. | |
2 0.000005 for l:conn_id in sort(keys(s:connections)) | |
1 0.000002 let l:conn = s:connections[l:conn_id] | |
1 0.000002 if l:conn.initialized && has_key(l:conn.open_documents, a:buffer) | |
if l:conn.is_tsserver | |
let l:message = ale#lsp#tsserver_message#Close(a:buffer) | |
else | |
let l:message = ale#lsp#message#DidClose(a:buffer) | |
endif | |
call ale#lsp#Send(l:conn_id, l:message) | |
call remove(l:conn.open_documents, a:buffer) | |
let l:closed = 1 | |
1 0.000000 endif | |
2 0.000001 endfor | |
1 0.000001 return l:closed | |
FUNCTION ale#hover#ShowTruncatedMessageAtCursor() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/hover.vim:334 | |
Called 1 time | |
Total time: 0.000089 | |
Self time: 0.000025 | |
count total (s) self (s) | |
1 0.000004 let l:buffer = bufnr('') | |
1 0.000004 let l:pos = getpos('.')[0:2] | |
1 0.000002 if l:pos != s:last_pos | |
1 0.000001 let s:last_pos = l:pos | |
1 0.000073 0.000008 let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer) | |
1 0.000002 if empty(l:loc) | |
call ale#hover#Show( l:buffer, l:pos[1], l:pos[2], {'truncated_echo': 1},) | |
1 0.000000 endif | |
1 0.000000 endif | |
FUNCTION go#config#HighlightVariableAssignments() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:477 | |
Called 1 time | |
Total time: 0.000001 | |
Self time: 0.000001 | |
count total (s) self (s) | |
1 0.000001 return get(g:, 'go_highlight_variable_assignments', 0) | |
FUNCTION go#config#HighlightBuildConstraints() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:461 | |
Called 2 times | |
Total time: 0.000002 | |
Self time: 0.000002 | |
count total (s) self (s) | |
2 0.000002 return get(g:, 'go_highlight_build_constraints', 0) | |
FUNCTION <SNR>118_IndentLinesDisable() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/indentLine/after/plugin/indentLine.vim:209 | |
Called 1 time | |
Total time: 0.000020 | |
Self time: 0.000015 | |
count total (s) self (s) | |
1 0.000001 if g:indentLine_newVersion | |
1 0.000004 if exists("w:indentLine_indentLineId") && ! empty(w:indentLine_indentLineId) | |
for id in w:indentLine_indentLineId | |
try | |
call matchdelete(id) | |
catch /^Vim\%((\a\+)\)\=:E80[23]/ | |
endtry | |
endfor | |
let w:indentLine_indentLineId = [] | |
1 0.000000 endif | |
1 0.000009 0.000003 call s:ResetConcealOption() | |
1 0.000000 return | |
endif | |
let b:indentLine_enabled = 0 | |
try | |
syntax clear IndentLine | |
syntax clear IndentLineSpace | |
catch /^Vim\%((\a\+)\)\=:E28/ " catch error E28 | |
endtry | |
FUNCTION go#config#GoplsAnalyses() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:560 | |
Called 2 times | |
Total time: 0.000016 | |
Self time: 0.000016 | |
count total (s) self (s) | |
2 0.000012 return get(g:, 'go_gopls_analyses', v:null) | |
FUNCTION <SNR>179_BuildSignMap() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:307 | |
Called 3 times | |
Total time: 0.003615 | |
Self time: 0.002214 | |
count total (s) self (s) | |
3 0.000036 0.000013 let l:max_signs = ale#Var(a:buffer, 'max_signs') | |
3 0.000002 if l:max_signs is 0 | |
let l:selected_grouped_items = [] | |
3 0.000006 elseif type(l:max_signs) is v:t_number && l:max_signs > 0 | |
let l:selected_grouped_items = a:grouped_items[:l:max_signs - 1] | |
3 0.000001 else | |
3 0.000003 let l:selected_grouped_items = a:grouped_items | |
3 0.000001 endif | |
3 0.000002 let l:sign_map = {} | |
3 0.000003 let l:sign_offset = g:ale_sign_offset | |
23 0.000014 for [l:line, l:sign_id, l:name] in a:current_sign_list | |
20 0.000048 let l:sign_info = get(l:sign_map, l:line, { 'current_id_list': [], 'current_name_list': [], 'new_id': 0, 'new_name': '', 'items': [],}) | |
" Increment the sign offset for new signs, by the maximum sign ID. | |
20 0.000010 if l:sign_id > l:sign_offset | |
20 0.000010 let l:sign_offset = l:sign_id | |
20 0.000003 endif | |
" Remember the sign names and IDs in separate Lists, so they are easy | |
" to work with. | |
20 0.000016 call add(l:sign_info.current_id_list, l:sign_id) | |
20 0.000015 call add(l:sign_info.current_name_list, l:name) | |
20 0.000016 let l:sign_map[l:line] = l:sign_info | |
23 0.000005 endfor | |
43 0.000020 for l:group in l:selected_grouped_items | |
40 0.000033 let l:line = l:group[0].lnum | |
40 0.001315 let l:sign_info = get(l:sign_map, l:line, { 'current_id_list': [], 'current_name_list': [], 'new_id': 0, 'new_name': '', 'items': [],}) | |
40 0.001621 0.000242 let l:sign_info.new_name = ale#sign#GetSignName(l:group) | |
40 0.000031 let l:sign_info.items = l:group | |
40 0.000081 let l:index = index( l:sign_info.current_name_list, l:sign_info.new_name) | |
40 0.000021 if l:index >= 0 | |
" We have a sign with this name already, so use the same ID. | |
20 0.000024 let l:sign_info.new_id = l:sign_info.current_id_list[l:index] | |
20 0.000004 else | |
" This sign name replaces the previous name, so use a new ID. | |
20 0.000029 let l:sign_info.new_id = l:sign_offset + 1 | |
20 0.000014 let l:sign_offset += 1 | |
40 0.000009 endif | |
40 0.000047 let l:sign_map[l:line] = l:sign_info | |
43 0.000012 endfor | |
3 0.000001 return l:sign_map | |
FUNCTION <SNR>142_hi() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/syntax/go.vim:395 | |
Called 1 time | |
Total time: 0.000098 | |
Self time: 0.000097 | |
count total (s) self (s) | |
1 0.000006 hi def link goSameId Search | |
1 0.000006 hi def link goDiagnosticError SpellBad | |
1 0.000006 hi def link goDiagnosticWarning SpellRare | |
" TODO(bc): is it appropriate to define text properties in a syntax file? | |
" The highlight groups need to be defined before the text properties types | |
" are added, and when users have syntax enabled in their vimrc after | |
" filetype plugin on, the highlight groups won't be defined when | |
" ftplugin/go.vim is executed when the first go file is opened. | |
" See https://github.com/fatih/vim-go/issues/2658. | |
1 0.000002 if has('textprop') | |
if empty(prop_type_get('goSameId')) | |
call prop_type_add('goSameId', {'highlight': 'goSameId'}) | |
endif | |
if empty(prop_type_get('goDiagnosticError')) | |
call prop_type_add('goDiagnosticError', {'highlight': 'goDiagnosticError'}) | |
endif | |
if empty(prop_type_get('goDiagnosticWarning')) | |
call prop_type_add('goDiagnosticWarning', {'highlight': 'goDiagnosticWarning'}) | |
endif | |
1 0.000000 endif | |
1 0.000006 hi def link goDeclsFzfKeyword Keyword | |
1 0.000006 hi def link goDeclsFzfFunction Function | |
1 0.000006 hi def link goDeclsFzfSpecialComment SpecialComment | |
1 0.000006 hi def link goDeclsFzfComment Comment | |
" :GoCoverage commands | |
1 0.000015 hi def goCoverageCovered ctermfg=green guifg=#A6E22E | |
1 0.000005 hi def goCoverageUncover ctermfg=red guifg=#F92672 | |
" :GoDebug commands | |
1 0.000004 0.000003 if go#config#HighlightDebug() | |
1 0.000010 hi def GoDebugBreakpoint term=standout ctermbg=117 ctermfg=0 guibg=#BAD4F5 guifg=Black | |
1 0.000010 hi def GoDebugCurrent term=reverse ctermbg=12 ctermfg=7 guibg=DarkBlue guifg=White | |
1 0.000000 endif | |
FUNCTION go#util#has_job() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:64 | |
Called 2 times | |
Total time: 0.000010 | |
Self time: 0.000010 | |
count total (s) self (s) | |
2 0.000010 return has('job') || has('nvim') | |
FUNCTION <SNR>144_dedup() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:1876 | |
Called 1 time | |
Total time: 0.000017 | |
Self time: 0.000017 | |
count total (s) self (s) | |
1 0.000009 let l:dict = {} | |
2 0.000002 for l:item in a:list | |
1 0.000001 let l:dict[l:item] = 1 | |
2 0.000001 endfor | |
1 0.000002 return sort(keys(l:dict)) | |
FUNCTION 9() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:9 | |
Called 5 times | |
Total time: 0.003132 | |
Self time: 0.000051 | |
count total (s) self (s) | |
5 0.000023 if empty(get(self, 'current', {})) || empty(get(self.current, 'job', {})) | |
1 0.003096 0.000015 let self.current = s:newlsp() | |
5 0.000001 endif | |
5 0.000003 return self.current | |
FUNCTION <SNR>165_GetLintFileValues() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:607 | |
Called 1 time | |
Total time: 0.023860 | |
Self time: 0.000876 | |
count total (s) self (s) | |
1 0.000001 let l:deferred_list = [] | |
1 0.000001 let l:new_slots = [] | |
5 0.000004 for [l:lint_file, l:linter] in a:slots | |
4 0.001128 0.000798 while ale#command#IsDeferred(l:lint_file) && has_key(l:lint_file, 'value') | |
" If we've already computed the return value, use it. | |
let l:lint_file = l:lint_file.value | |
4 0.000002 endwhile | |
4 0.000030 0.000021 if ale#command#IsDeferred(l:lint_file) | |
" If we are going to return the result later, wait for it. | |
call add(l:deferred_list, l:lint_file) | |
4 0.000001 else | |
" If we have the value now, coerce it to 0 or 1. | |
4 0.000003 let l:lint_file = l:lint_file is 1 | |
4 0.000001 endif | |
4 0.000006 call add(l:new_slots, [l:lint_file, l:linter]) | |
5 0.000003 endfor | |
1 0.000001 if !empty(l:deferred_list) | |
for l:deferred in l:deferred_list | |
let l:deferred.result_callback = {-> s:GetLintFileValues(l:new_slots, a:Callback)} | |
endfor | |
1 0.000000 else | |
1 0.022655 0.000009 call a:Callback(l:new_slots) | |
1 0.000000 endif | |
FUNCTION ale#lsp#UpdateConfig() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp.vim:291 | |
Called 1 time | |
Total time: 0.000005 | |
Self time: 0.000005 | |
count total (s) self (s) | |
1 0.000002 let l:conn = get(s:connections, a:conn_id, {}) | |
1 0.000002 if empty(l:conn) || a:config ==# l:conn.config " no-custom-checks | |
1 0.000000 return 0 | |
endif | |
let l:conn.config = a:config | |
let l:message = ale#lsp#message#DidChangeConfiguration(a:buffer, a:config) | |
call ale#lsp#Send(a:conn_id, l:message) | |
return 1 | |
FUNCTION <SNR>145_neooptions() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/job.vim:361 | |
Called 1 time | |
Total time: 0.000137 | |
Self time: 0.000137 | |
count total (s) self (s) | |
1 0.000001 let l:options = {} | |
1 0.000001 let l:options['stdout_buf'] = '' | |
1 0.000001 let l:options['stderr_buf'] = '' | |
1 0.000002 let l:err_mode = get(a:options, 'err_mode', get(a:options, 'mode', '')) | |
1 0.000001 let l:out_mode = get(a:options, 'out_mode', get(a:options, 'mode', '')) | |
10 0.000005 for key in keys(a:options) | |
9 0.000004 if key == 'cwd' | |
1 0.000001 let l:options['cwd'] = a:options['cwd'] | |
1 0.000001 continue | |
8 0.000001 endif | |
8 0.000003 if key == 'callback' | |
let l:options['callback'] = a:options['callback'] | |
if !has_key(a:options, 'out_cb') | |
let l:options['on_stdout'] = function('s:callback2on_stdout', [l:out_mode], l:options) | |
endif | |
if !has_key(a:options, 'err_cb') | |
let l:options['on_stderr'] = function('s:callback2on_stderr', [l:err_mode], l:options) | |
endif | |
continue | |
8 0.000001 endif | |
8 0.000003 if key == 'out_cb' | |
1 0.000001 let l:options['out_cb'] = a:options['out_cb'] | |
1 0.000003 let l:options['on_stdout'] = function('s:on_stdout', [l:out_mode], l:options) | |
1 0.000000 continue | |
7 0.000001 endif | |
7 0.000003 if key == 'err_cb' | |
1 0.000001 let l:options['err_cb'] = a:options['err_cb'] | |
1 0.000002 let l:options['on_stderr'] = function('s:on_stderr', [l:err_mode], l:options) | |
1 0.000000 continue | |
6 0.000001 endif | |
6 0.000002 if key == 'exit_cb' | |
1 0.000001 let l:options['exit_cb'] = a:options['exit_cb'] | |
1 0.000003 let l:options['on_exit'] = function('s:on_exit', [], l:options) | |
1 0.000000 continue | |
5 0.000001 endif | |
5 0.000002 if key == 'close_cb' | |
1 0.000000 continue | |
4 0.000001 endif | |
4 0.000002 if key == 'stoponexit' | |
if a:options['stoponexit'] == '' | |
let l:options['detach'] = 1 | |
endif | |
continue | |
4 0.000001 endif | |
5 0.000002 endfor | |
1 0.000001 return l:options | |
FUNCTION ale#highlight#RemoveHighlights() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/highlight.vim:72 | |
Called 3 times | |
Total time: 0.000177 | |
Self time: 0.000155 | |
count total (s) self (s) | |
3 0.000003 if s:has_nvim_highlight | |
3 0.000159 0.000137 call ale#highlight#nvim_buf_clear_namespace(bufnr(''), s:ns_id, 0, -1) | |
else | |
for l:match in getmatches() | |
if l:match.group =~? '\v^ALE(Style)?(Error|Warning|Info)(Line)?$' | |
call matchdelete(l:match.id) | |
endif | |
endfor | |
3 0.000001 endif | |
FUNCTION ale#command#CdString() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/command.vim:173 | |
Called 1 time | |
Total time: 0.000018 | |
Self time: 0.000018 | |
count total (s) self (s) | |
1 0.000009 let l:match = matchstrpos(a:directory, s:path_format_regex) | |
" Do not escape the directory here if it's a valid format string. | |
" This allows us to use sequences like %s:h, %s:h:h, etc. | |
1 0.000004 let l:directory = l:match[1:] == [0, len(a:directory)] ? a:directory : ale#Escape(a:directory) | |
1 0.000002 if has('win32') | |
return 'cd /d ' . l:directory . ' && ' | |
1 0.000000 endif | |
1 0.000001 return 'cd ' . l:directory . ' && ' | |
FUNCTION <SNR>144_start() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:582 | |
Called 4 times | |
Total time: 0.000018 | |
Self time: 0.000018 | |
count total (s) self (s) | |
4 0.000009 let self.started_at = reltime() | |
4 0.000004 if self.statustype == '' | |
4 0.000002 return | |
endif | |
let status = { 'desc': 'current status', 'type': self.statustype, 'state': "started", } | |
call go#statusline#Update(self.jobdir, status) | |
FUNCTION ale#handlers#unix#HandleAsWarning() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/handlers/unix.vim:24 | |
Called 1 time | |
Total time: 0.001613 | |
Self time: 0.000016 | |
count total (s) self (s) | |
1 0.001606 0.000009 return s:HandleUnixFormat(a:buffer, a:lines, 'W') | |
FUNCTION ale#sign#FindCurrentSigns() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:250 | |
Called 3 times | |
Total time: 0.000430 | |
Self time: 0.000220 | |
count total (s) self (s) | |
3 0.000004 if exists('*sign_getplaced') | |
3 0.000424 0.000215 return ale#sign#ParseSignsWithGetPlaced(a:buffer) | |
else | |
let l:line_list = ale#sign#ReadSigns(a:buffer) | |
return ale#sign#ParseSigns(l:line_list) | |
endif | |
FUNCTION ale#command#ManageDirectory() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/command.vim:50 | |
Called 2 times | |
Total time: 0.000023 | |
Self time: 0.000014 | |
count total (s) self (s) | |
2 0.000016 0.000007 call ale#command#InitData(a:buffer) | |
2 0.000006 call add(s:buffer_data[a:buffer].directory_list, a:directory) | |
FUNCTION ale#lsp#message#Initialize() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp/message.vim:31 | |
Called 1 time | |
Total time: 0.001084 | |
Self time: 0.000015 | |
count total (s) self (s) | |
" NOTE: rootPath is deprecated in favour of rootUri | |
1 0.001081 0.000013 return [0, 'initialize', { 'processId': getpid(), 'rootPath': a:root_path, 'capabilities': a:capabilities, 'initializationOptions': a:options, 'rootUri': ale#path#ToURI(a:root_path),}] | |
FUNCTION ale#highlight#nvim_buf_add_highlight() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/highlight.vim:36 | |
Called 56 times | |
Total time: 0.000873 | |
Self time: 0.000873 | |
count total (s) self (s) | |
" Ignore all errors for adding highlights. | |
56 0.000028 try | |
56 0.000725 call nvim_buf_add_highlight(a:buffer, a:ns_id, a:hl_group, a:line, a:col_start, a:col_end) | |
catch | |
56 0.000025 endtry | |
FUNCTION go#config#HighlightTypes() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:457 | |
Called 1 time | |
Total time: 0.000001 | |
Self time: 0.000001 | |
count total (s) self (s) | |
1 0.000001 return get(g:, 'go_highlight_types', 0) | |
FUNCTION go#config#Debug() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:199 | |
Called 24 times | |
Total time: 0.000076 | |
Self time: 0.000076 | |
count total (s) self (s) | |
24 0.000061 return get(g:, 'go_debug', []) | |
FUNCTION go#lsp#DidChange() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:732 | |
Called 1 time | |
Total time: 0.003400 | |
Self time: 0.001953 | |
count total (s) self (s) | |
" DidChange is called even when fname isn't open in a buffer (e.g. via | |
" go#lsp#Info); don't report the file as open or as having changed when it's | |
" not actually a buffer. | |
1 0.001669 if bufnr(a:fname) == -1 | |
return | |
1 0.000001 endif | |
1 0.000032 let l:fname = fnamemodify(a:fname, ':p') | |
1 0.000011 if !isdirectory(fnamemodify(l:fname, ':h')) | |
return | |
1 0.000000 endif | |
1 0.000020 0.000012 call go#lsp#DidOpen(a:fname) | |
1 0.000014 0.000004 let l:lsp = s:lspfactory.get() | |
1 0.000009 let l:version = getbufvar(l:fname, 'changedtick') | |
1 0.000003 if has_key(l:lsp.fileVersions, l:fname) && l:lsp.fileVersions[l:fname] == l:version | |
return | |
1 0.000000 endif | |
1 0.000002 let l:lsp.fileVersions[l:fname] = l:version | |
1 0.000192 0.000092 let l:msg = go#lsp#message#DidChange(l:fname, join(go#util#GetLines(), "\n") . "\n", l:lsp.fileVersions[l:fname]) | |
1 0.000112 0.000056 let l:state = s:newHandlerState('') | |
1 0.001323 0.000051 return l:lsp.sendMessage(l:msg, l:state) | |
FUNCTION ale#sign#GetSignName() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:118 | |
Called 40 times | |
Total time: 0.001379 | |
Self time: 0.000992 | |
count total (s) self (s) | |
40 0.000044 let l:priority = g:ale#util#style_warning_priority | |
" Determine the highest priority item for the line. | |
96 0.000063 for l:item in a:sublist | |
56 0.000840 0.000453 let l:item_priority = ale#util#GetItemPriority(l:item) | |
56 0.000039 if l:item_priority > l:priority | |
40 0.000027 let l:priority = l:item_priority | |
56 0.000037 endif | |
96 0.000034 endfor | |
40 0.000031 if l:priority is# g:ale#util#error_priority | |
return 'ALEErrorSign' | |
40 0.000008 endif | |
40 0.000033 if l:priority is# g:ale#util#warning_priority | |
40 0.000019 return 'ALEWarningSign' | |
endif | |
if l:priority is# g:ale#util#style_error_priority | |
return 'ALEStyleErrorSign' | |
endif | |
if l:priority is# g:ale#util#style_warning_priority | |
return 'ALEStyleWarningSign' | |
endif | |
if l:priority is# g:ale#util#info_priority | |
return 'ALEInfoSign' | |
endif | |
" Use the error sign for invalid severities. | |
return 'ALEErrorSign' | |
FUNCTION go#config#AutoTypeInfo() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:345 | |
Called 2 times | |
Total time: 0.000004 | |
Self time: 0.000004 | |
count total (s) self (s) | |
2 0.000003 return get(g:, "go_auto_type_info", 0) | |
FUNCTION ale#GetFilenameMappings() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale.vim:269 | |
Called 7 times | |
Total time: 0.000180 | |
Self time: 0.000120 | |
count total (s) self (s) | |
7 0.000107 0.000047 let l:linter_mappings = ale#Var(a:buffer, 'filename_mappings') | |
7 0.000011 if type(l:linter_mappings) is v:t_list | |
return l:linter_mappings | |
7 0.000003 endif | |
7 0.000005 let l:name = a:name | |
7 0.000010 if !has_key(l:linter_mappings, l:name) | |
" Use * as a default setting for all tools. | |
7 0.000005 let l:name = '*' | |
7 0.000002 endif | |
7 0.000009 return get(l:linter_mappings, l:name, []) | |
FUNCTION <SNR>98_register() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/plugin/go.vim:243 | |
Called 1 time | |
Total time: 0.048086 | |
Self time: 0.000727 | |
count total (s) self (s) | |
1 0.000002 if !(&modifiable && expand('<amatch>') ==# 'go') | |
return | |
1 0.000000 endif | |
1 0.048083 0.000724 call go#lsp#DidOpen(expand('<afile>:p')) | |
FUNCTION ale_linters#go#gopls#GetCommand() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gopls.vim:10 | |
Called 1 time | |
Total time: 0.000025 | |
Self time: 0.000007 | |
count total (s) self (s) | |
1 0.000025 0.000007 return ale#go#EnvString(a:buffer) . '%e' . ale#Pad(ale#Var(a:buffer, 'go_gopls_options')) | |
FUNCTION go#config#SearchBinPathFirst() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:412 | |
Called 4 times | |
Total time: 0.000012 | |
Self time: 0.000012 | |
count total (s) self (s) | |
4 0.000010 return get(g:, 'go_search_bin_path_first', 1) | |
FUNCTION ale#lsp#HandleMessage() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp.vim:332 | |
Called 18 times | |
Total time: 0.008885 | |
Self time: 0.001689 | |
count total (s) self (s) | |
18 0.000082 let l:conn = get(s:connections, a:conn_id, {}) | |
18 0.000021 if empty(l:conn) | |
return | |
18 0.000006 endif | |
18 0.000025 if type(a:message) isnot v:t_string | |
" Ignore messages that aren't strings. | |
return | |
18 0.000004 endif | |
18 0.000036 let l:conn.data .= a:message | |
" Parse the objects now if we can, and keep the remaining text. | |
18 0.002081 0.000596 let [l:conn.data, l:response_list] = ale#lsp#ReadMessageData(l:conn.data) | |
" Look for initialize responses first. | |
18 0.000015 if !l:conn.initialized | |
2 0.000002 for l:response in l:response_list | |
1 0.001597 0.000014 call ale#lsp#HandleInitResponse(l:conn, l:response) | |
2 0.000001 endfor | |
18 0.000005 endif | |
" If the connection is marked as initialized, call the callbacks with the | |
" responses. | |
18 0.000010 if l:conn.initialized | |
45 0.000030 for l:response in l:response_list | |
" Call all of the registered handlers with the response. | |
54 0.000051 for l:Callback in l:conn.callback_list | |
27 0.004633 0.000507 call ale#util#GetFunction(l:Callback)(a:conn_id, l:response) | |
54 0.000020 endfor | |
45 0.000017 endfor | |
18 0.000005 endif | |
FUNCTION ale#highlight#UpdateHighlights() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/highlight.vim:136 | |
Called 3 times | |
Total time: 0.007154 | |
Self time: 0.001617 | |
count total (s) self (s) | |
3 0.000010 let l:item_list = get(b:, 'ale_enabled', 1) && g:ale_enabled ? get(b:, 'ale_highlight_items', []) : [] | |
3 0.000209 0.000032 call ale#highlight#RemoveHighlights() | |
59 0.000034 for l:item in l:item_list | |
56 0.000051 if l:item.type is# 'W' | |
56 0.000077 if get(l:item, 'sub_type', '') is# 'style' | |
let l:group = 'ALEStyleWarning' | |
56 0.000014 else | |
56 0.000037 let l:group = 'ALEWarning' | |
56 0.000013 endif | |
elseif l:item.type is# 'I' | |
let l:group = 'ALEInfo' | |
elseif get(l:item, 'sub_type', '') is# 'style' | |
let l:group = 'ALEStyleError' | |
else | |
let l:group = 'ALEError' | |
56 0.000016 endif | |
56 0.000308 let l:range = { 'lnum': l:item.lnum, 'col': l:item.col, 'end_lnum': get(l:item, 'end_lnum', l:item.lnum), 'end_col': get(l:item, 'end_col', l:item.col)} | |
56 0.005994 0.000634 call s:highlight_range(l:item.bufnr, l:range, l:group) | |
59 0.000020 endfor | |
" If highlights are enabled and signs are not enabled, we should still | |
" offer line highlights by adding a separate set of highlights. | |
3 0.000003 if !g:ale_set_signs | |
let l:available_groups = { 'ALEWarningLine': hlexists('ALEWarningLine'), 'ALEInfoLine': hlexists('ALEInfoLine'), 'ALEErrorLine': hlexists('ALEErrorLine'),} | |
for l:item in l:item_list | |
if l:item.type is# 'W' | |
let l:group = 'ALEWarningLine' | |
elseif l:item.type is# 'I' | |
let l:group = 'ALEInfoLine' | |
else | |
let l:group = 'ALEErrorLine' | |
endif | |
if l:available_groups[l:group] | |
call s:highlight_line(l:item.bufnr, l:item.lnum, l:group) | |
endif | |
endfor | |
3 0.000001 endif | |
FUNCTION ale#job#Start() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/job.vim:215 | |
Called 4 times | |
Total time: 0.007283 | |
Self time: 0.007268 | |
count total (s) self (s) | |
4 0.000054 0.000039 call ale#job#ValidateArguments(a:command, a:options) | |
4 0.000009 let l:job_info = copy(a:options) | |
4 0.000003 let l:job_options = {} | |
4 0.000007 if has('nvim') | |
4 0.000004 if has_key(a:options, 'out_cb') | |
2 0.000006 let l:job_options.on_stdout = function('s:NeoVimCallback') | |
2 0.000002 let l:job_info.out_cb_line = '' | |
4 0.000001 endif | |
4 0.000003 if has_key(a:options, 'err_cb') | |
3 0.000006 let l:job_options.on_stderr = function('s:NeoVimCallback') | |
3 0.000002 let l:job_info.err_cb_line = '' | |
4 0.000001 endif | |
4 0.000003 if has_key(a:options, 'exit_cb') | |
3 0.000004 let l:job_options.on_exit = function('s:NeoVimCallback') | |
4 0.000001 endif | |
4 0.007012 let l:job_info.job = jobstart(a:command, l:job_options) | |
4 0.000009 let l:job_id = l:job_info.job | |
else | |
let l:job_options = { 'in_mode': l:job_info.mode, 'out_mode': l:job_info.mode, 'err_mode': l:job_info.mode,} | |
if has_key(a:options, 'out_cb') | |
let l:job_options.out_cb = function('s:VimOutputCallback') | |
endif | |
if has_key(a:options, 'err_cb') | |
let l:job_options.err_cb = function('s:VimErrorCallback') | |
endif | |
if has_key(a:options, 'exit_cb') | |
" Set a close callback to which simply calls job_status() | |
" when the channel is closed, which can trigger the exit callback | |
" earlier on. | |
let l:job_options.close_cb = function('s:VimCloseCallback') | |
let l:job_options.exit_cb = function('s:VimExitCallback') | |
endif | |
" Use non-blocking writes for Vim versions that support the option. | |
if has('patch-8.1.350') | |
let l:job_options.noblock = 1 | |
endif | |
" Vim 8 will read the stdin from the file's buffer. | |
let l:job_info.job = job_start(a:command, l:job_options) | |
let l:job_id = ale#job#ParseVim8ProcessID(string(l:job_info.job)) | |
4 0.000001 endif | |
4 0.000003 if l:job_id > 0 | |
" Store the job in the map for later only if we can get the ID. | |
4 0.000014 let s:job_map[l:job_id] = l:job_info | |
4 0.000001 endif | |
4 0.000031 return l:job_id | |
FUNCTION <SNR>165_RunLinters() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:638 | |
Called 1 time | |
Total time: 0.022630 | |
Self time: 0.000285 | |
count total (s) self (s) | |
1 0.000041 0.000006 call s:StopCurrentJobs(a:buffer, a:should_lint_file, a:slots) | |
1 0.000018 0.000005 call s:RemoveProblemsForDisabledLinters(a:buffer, a:linters) | |
" We can only clear the results if we aren't checking the buffer. | |
1 0.000009 0.000004 let l:can_clear_results = !ale#engine#IsCheckingBuffer(a:buffer) | |
1 0.000097 0.000091 silent doautocmd <nomodeline> User ALELintPre | |
5 0.000008 for [l:lint_file, l:linter] in a:slots | |
" Only run lint_file linters if we should. | |
4 0.000004 if !l:lint_file || a:should_lint_file | |
4 0.022042 0.000049 if s:RunLinter(a:buffer, l:linter, l:lint_file) | |
" If a single linter ran, we shouldn't clear everything. | |
4 0.000012 let l:can_clear_results = 0 | |
4 0.000005 endif | |
else | |
" If we skipped running a lint_file linter still in the list, | |
" we shouldn't clear everything. | |
let l:can_clear_results = 0 | |
4 0.000001 endif | |
5 0.000029 endfor | |
" Clear the results if we can. This needs to be done when linters are | |
" disabled, or ALE itself is disabled. | |
1 0.000001 if l:can_clear_results | |
call ale#engine#SetResults(a:buffer, []) | |
1 0.000001 elseif a:new_buffer | |
1 0.000315 0.000022 call s:AddProblemsFromOtherBuffers( a:buffer, map(copy(a:slots), 'v:val[1]')) | |
1 0.000000 endif | |
FUNCTION go#uri#Decode() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/uri.vim:26 | |
Called 2 times | |
Total time: 0.000007 | |
Self time: 0.000007 | |
count total (s) self (s) | |
2 0.000006 return substitute( a:value, '%\(\x\x\)', '\=s:decodehex(submatch(1))', 'g') | |
FUNCTION ale#command#SetCwd() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/command.vim:34 | |
Called 4 times | |
Total time: 0.000037 | |
Self time: 0.000019 | |
count total (s) self (s) | |
4 0.000030 0.000011 call ale#command#InitData(a:buffer) | |
4 0.000007 let s:buffer_data[a:buffer].cwd = a:cwd | |
FUNCTION go#config#HighlightFormatStrings() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:469 | |
Called 1 time | |
Total time: 0.000001 | |
Self time: 0.000001 | |
count total (s) self (s) | |
1 0.000001 return get(g:, 'go_highlight_format_strings', 1) | |
FUNCTION ale#lsp_linter#StartLSP() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp_linter.vim:409 | |
Called 1 time | |
Total time: 0.007813 | |
Self time: 0.000038 | |
count total (s) self (s) | |
1 0.000001 let l:command = '' | |
1 0.000000 let l:address = '' | |
1 0.001793 0.000005 let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, a:linter) | |
1 0.000001 if empty(l:root) && a:linter.lsp isnot# 'tsserver' | |
" If there's no project root, then we can't check files with LSP, | |
" unless we are using tsserver, which doesn't use project roots. | |
return 0 | |
1 0.000000 endif | |
1 0.000003 let l:options = { 'buffer': a:buffer, 'linter': a:linter, 'callback': a:Callback, 'root': l:root,} | |
1 0.000001 if a:linter.lsp is# 'socket' | |
let l:address = ale#linter#GetAddress(a:buffer, a:linter) | |
return s:StartWithAddress(l:options, l:address) | |
1 0.000000 endif | |
1 0.000084 0.000005 let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) | |
1 0.005923 0.000015 return s:StartIfExecutable(l:options, l:executable) | |
FUNCTION ale#lsp#message#Initialized() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp/message.vim:42 | |
Called 1 time | |
Total time: 0.000001 | |
Self time: 0.000001 | |
count total (s) self (s) | |
1 0.000001 return [1, 'initialized', {}] | |
FUNCTION ale#linter#GetLanguage() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/linter.vim:452 | |
Called 1 time | |
Total time: 0.000004 | |
Self time: 0.000004 | |
count total (s) self (s) | |
1 0.000001 let l:Language = a:linter.language | |
1 0.000002 return type(l:Language) is v:t_func ? l:Language(a:buffer) : l:Language | |
FUNCTION go#util#IsUsingCygwinShell() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:56 | |
Called 4 times | |
Total time: 0.000023 | |
Self time: 0.000017 | |
count total (s) self (s) | |
4 0.000021 0.000015 return go#util#IsWin() && executable('cygpath') && &shell =~ '.*sh.*' | |
FUNCTION <SNR>170_StartLSP() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp_linter.vim:301 | |
Called 1 time | |
Total time: 0.005732 | |
Self time: 0.000877 | |
count total (s) self (s) | |
1 0.000001 let l:buffer = a:options.buffer | |
1 0.000001 let l:linter = a:options.linter | |
1 0.000001 let l:root = a:options.root | |
1 0.000001 let l:Callback = a:options.callback | |
1 0.000021 0.000004 let l:init_options = ale#lsp_linter#GetOptions(l:buffer, l:linter) | |
1 0.000001 if l:linter.lsp is# 'socket' | |
let l:conn_id = ale#lsp#Register(a:address, l:root, l:init_options) | |
let l:ready = ale#lsp#ConnectToAddress(l:conn_id, a:address) | |
let l:command = '' | |
1 0.000000 else | |
1 0.001337 0.000802 let l:conn_id = ale#lsp#Register(a:executable, l:root, l:init_options) | |
" tsserver behaves differently, so tell the LSP API that it is tsserver. | |
1 0.000001 if l:linter.lsp is# 'tsserver' | |
call ale#lsp#MarkConnectionAsTsserver(l:conn_id) | |
1 0.000000 endif | |
1 0.000008 0.000004 let l:cwd = ale#linter#GetCwd(l:buffer, l:linter) | |
1 0.000107 0.000029 let l:command = ale#command#FormatCommand( l:buffer, a:executable, a:command, 0, v:false, l:cwd, ale#GetFilenameMappings(l:buffer, l:linter.name),)[1] | |
1 0.000027 0.000004 let l:command = ale#job#PrepareCommand(l:buffer, l:command) | |
1 0.004200 0.000009 let l:ready = ale#lsp#StartProgram(l:conn_id, a:executable, l:command) | |
1 0.000000 endif | |
1 0.000000 if !l:ready | |
if g:ale_history_enabled && !empty(a:command) | |
call ale#history#Add(l:buffer, 'failed', l:conn_id, a:command) | |
endif | |
return 0 | |
1 0.000000 endif | |
1 0.000003 let l:details = { 'buffer': l:buffer, 'connection_id': l:conn_id, 'command': l:command, 'project_root': l:root,} | |
1 0.000012 0.000005 call ale#lsp#OnInit(l:conn_id, {-> ale#lsp_linter#OnInit(l:linter, l:details, l:Callback)}) | |
1 0.000000 return 1 | |
FUNCTION go#util#HasDebug() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:501 | |
Called 24 times | |
Total time: 0.000238 | |
Self time: 0.000161 | |
count total (s) self (s) | |
24 0.000226 0.000150 return index(go#config#Debug(), a:flag) >= 0 | |
FUNCTION <SNR>82_sortByLength() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/auto-pairs/plugin/auto-pairs.vim:467 | |
Called 24 times | |
Total time: 0.000049 | |
Self time: 0.000049 | |
count total (s) self (s) | |
24 0.000042 return len(a:i2[0])-len(a:i1[0]) | |
FUNCTION go#util#Shelljoin() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:294 | |
Called 4 times | |
Total time: 0.000103 | |
Self time: 0.000103 | |
count total (s) self (s) | |
4 0.000004 try | |
4 0.000007 let ssl_save = &shellslash | |
4 0.000004 set noshellslash | |
4 0.000002 if a:0 | |
return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ') | |
4 0.000001 endif | |
4 0.000059 return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ') | |
4 0.000003 finally | |
4 0.000005 let &shellslash = ssl_save | |
4 0.000003 endtry | |
FUNCTION ale#events#ReadOrEnterEvent() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/events.vim:51 | |
Called 2 times | |
Total time: 0.000046 | |
Self time: 0.000046 | |
count total (s) self (s) | |
" Apply pattern options if the variable is set. | |
2 0.000009 if get(g:, 'ale_pattern_options_enabled', 1)&& !empty(get(g:, 'ale_pattern_options')) | |
call ale#pattern_options#SetOptions(a:buffer) | |
2 0.000001 endif | |
" When entering a buffer, we are no longer quitting it. | |
2 0.000010 call setbufvar(a:buffer, 'ale_quitting', 0) | |
2 0.000006 let l:filetype = getbufvar(a:buffer, '&filetype') | |
2 0.000005 call setbufvar(a:buffer, 'ale_original_filetype', l:filetype) | |
" If the file changed outside of Vim, check it on BufEnter,BufRead | |
2 0.000002 if getbufvar(a:buffer, 'ale_file_changed') | |
call ale#events#LintOnEnter(a:buffer) | |
2 0.000000 endif | |
FUNCTION go#config#FoldEnable() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:501 | |
Called 14 times | |
Total time: 0.000064 | |
Self time: 0.000042 | |
count total (s) self (s) | |
14 0.000005 if a:0 > 0 | |
7 0.000008 return index(go#config#FoldEnable(), a:1) > -1 | |
7 0.000001 endif | |
7 0.000010 return get(g:, 'go_fold_enable', ['block', 'import', 'varconst', 'package_comment']) | |
FUNCTION ale#path#ToURI() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/path.vim:221 | |
Called 2 times | |
Total time: 0.001098 | |
Self time: 0.000833 | |
count total (s) self (s) | |
2 0.000005 let l:has_drive_letter = a:path[1:2] is# ':\' | |
2 0.001090 0.000824 return substitute( ((l:has_drive_letter || a:path[:0] is# '/') ? 'file://' : '') . (l:has_drive_letter ? '/' . a:path[:2] : '') . ale#uri#Encode(l:has_drive_letter ? a:path[3:] : a:path), '\\', '/', 'g',) | |
FUNCTION go#config#GoplsLocal() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:564 | |
Called 2 times | |
Total time: 0.000003 | |
Self time: 0.000003 | |
count total (s) self (s) | |
2 0.000003 return get(g:, 'go_gopls_local', v:null) | |
FUNCTION <SNR>180_Deduplicate() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/list.vim:47 | |
Called 3 times | |
Total time: 0.014042 | |
Self time: 0.003381 | |
count total (s) self (s) | |
3 0.000002 let l:list = a:list | |
3 0.009497 0.001798 call sort(l:list, function('ale#util#LocItemCompareWithText')) | |
3 0.004521 0.001559 call uniq(l:list, function('ale#util#LocItemCompareWithText')) | |
3 0.000002 return l:list | |
FUNCTION <SNR>125_ApplyPartialTimer() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/util.vim:446 | |
Called 3 times | |
Total time: 0.021437 | |
Self time: 0.000081 | |
count total (s) self (s) | |
3 0.000016 if has_key(s:partial_timers, a:timer_id) | |
3 0.000018 let [l:Callback, l:args] = remove(s:partial_timers, a:timer_id) | |
3 0.021398 0.000041 call call(l:Callback, [a:timer_id] + l:args) | |
3 0.000001 endif | |
FUNCTION loupe#private#very_magic_slash() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/loupe/autoload/loupe/private.vim:26 | |
Called 1 time | |
Total time: 0.000464 | |
Self time: 0.000244 | |
count total (s) self (s) | |
1 0.000035 if getcmdtype() != ':' | |
return a:slash | |
1 0.000005 endif | |
" For simplicity, only consider a slash typed at the end of the command-line. | |
1 0.000018 let l:pos=getcmdpos() | |
1 0.000008 let l:cmd=getcmdline() | |
1 0.000009 if len(l:cmd) + 1 != l:pos | |
return a:slash | |
1 0.000001 endif | |
" Skip over ranges | |
1 0.000006 while 1 | |
1 0.000265 0.000045 let l:stripped=s:strip_ranges(l:cmd) | |
1 0.000004 if l:stripped ==# l:cmd | |
1 0.000004 break | |
else | |
let l:cmd=l:stripped | |
endif | |
1 0.000003 endwhile | |
" We special case `:g!` (and `gl!`, `glo!`, `glob!`, `globa!`, `global!`). | |
" All of those commands are equivalent to `:v` (ie. `!` is not being used as a | |
" slash). Using `!` with `:v` (etc) is an error (`:h E477`). Using it with `:s` | |
" is ok (it _is_ treated as a delimiter there). Fun fact: `:g!!foo!d` is a | |
" legitmate command. | |
1 0.000019 if index(['g', 'gl', 'glo', 'glob', 'globa', 'global'], l:cmd != 1) && a:slash == '!' | |
return a:slash | |
1 0.000032 elseif index([ 'g', 'gl', 'glo', 'glob', 'globa', 'global', 'g!', 'gl!', 'glo!', 'glob!', 'globa!', 'global!', 's', 'su', 'sub', 'subs', 'subst', 'substi', 'substit', 'substitu', 'substitut', 'substitute', 'v', 'vg', 'vgl', 'vglo', 'vglob', 'vgloba', 'vglobal', ], l:cmd) != -1 | |
return loupe#private#prepare_highlight(a:slash . '\v') | |
1 0.000001 endif | |
1 0.000002 return a:slash | |
FUNCTION go#config#HighlightSpaceTabError() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:428 | |
Called 1 time | |
Total time: 0.000001 | |
Self time: 0.000001 | |
count total (s) self (s) | |
1 0.000001 return get(g:, 'go_highlight_space_tab_error', 0) | |
FUNCTION go#config#GoplsUsePlaceholders() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:552 | |
Called 3 times | |
Total time: 0.000007 | |
Self time: 0.000007 | |
count total (s) self (s) | |
3 0.000006 return get(g:, 'go_gopls_use_placeholders', v:null) | |
FUNCTION <SNR>118_Setup() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/indentLine/after/plugin/indentLine.vim:317 | |
Called 1 time | |
Total time: 0.000277 | |
Self time: 0.000018 | |
count total (s) self (s) | |
1 0.000002 if &filetype ==# "" | |
call s:InitColor() | |
1 0.000000 endif | |
1 0.000019 0.000004 if s:Filter() && g:indentLine_enabled || exists("b:indentLine_enabled") && b:indentLine_enabled | |
1 0.000240 0.000005 call s:IndentLinesEnable() | |
1 0.000000 endif | |
1 0.000013 0.000004 if s:Filter() && g:indentLine_leadingSpaceEnabled || exists("b:indentLine_leadingSpaceEnabled") && b:indentLine_leadingSpaceEnabled | |
call s:LeadingSpaceEnable() | |
1 0.000000 endif | |
FUNCTION 11() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:82 | |
Called 90 times | |
Total time: 0.005373 | |
Self time: 0.005006 | |
count total (s) self (s) | |
90 0.000086 let l:responses = [] | |
90 0.000079 let l:rest = a:data | |
122 0.000069 while 1 | |
" Look for the end of the HTTP headers | |
122 0.000448 let l:body_start_idx = matchend(l:rest, "\r\n\r\n") | |
122 0.000094 if l:body_start_idx < 0 | |
" incomplete header | |
56 0.000029 break | |
66 0.000018 endif | |
" Parse the Content-Length header. | |
66 0.000113 let l:header = l:rest[:l:body_start_idx - 4] | |
66 0.000747 let l:length_match = matchlist( l:header, '\vContent-Length: *(\d+)') | |
66 0.000081 if empty(l:length_match) | |
" TODO(bc): shutdown gopls? | |
throw "invalid JSON-RPC header:\n" . l:header | |
66 0.000019 endif | |
" get the start of the rest | |
66 0.000156 let l:next_start_idx = l:body_start_idx + str2nr(l:length_match[1]) | |
66 0.000142 if len(l:rest) < l:next_start_idx | |
" incomplete response body | |
34 0.000011 break | |
32 0.000009 endif | |
32 0.000601 0.000235 call s:debug('received', l:rest[:l:next_start_idx - 1]) | |
32 0.000064 let l:body = l:rest[l:body_start_idx : l:next_start_idx - 1] | |
32 0.000051 let l:rest = l:rest[l:next_start_idx :] | |
32 0.000012 try | |
" add the json body to the list. | |
32 0.000273 call add(l:responses, json_decode(l:body)) | |
catch | |
" TODO(bc): log the message and/or show an error message. | |
32 0.000016 finally | |
" intentionally left blank. | |
32 0.000015 endtry | |
122 0.000141 endwhile | |
90 0.000113 return [l:rest, l:responses] | |
FUNCTION go#config#GoplsOptions() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:595 | |
Called 1 time | |
Total time: 0.000002 | |
Self time: 0.000002 | |
count total (s) self (s) | |
1 0.000001 return get(g:, 'go_gopls_options', ['-remote=auto']) | |
FUNCTION 13() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:151 | |
Called 3 times | |
Total time: 0.001839 | |
Self time: 0.000097 | |
count total (s) self (s) | |
3 0.000003 if a:req.method == 'workspace/workspaceFolders' | |
let l:resp = go#lsp#message#WorkspaceFoldersResult(self.workspaceDirectories) | |
3 0.000007 elseif a:req.method == 'workspace/configuration' && has_key(a:req, 'params') && has_key(a:req.params, 'items') | |
2 0.001609 0.000014 let l:resp = go#lsp#message#ConfigurationResult(a:req.params.items) | |
1 0.000002 elseif a:req.method == 'client/registerCapability' && has_key(a:req, 'params') && has_key(a:req.params, 'registrations') | |
1 0.000001 let l:resp = v:null | |
elseif a:req.method == 'workspace/applyEdit' | |
try | |
let l:ok = v:true | |
for l:change in a:req.params.edit.documentChanges | |
call s:applyDocumentChanges(a:req.params.edit.documentChanges) | |
endfor | |
catch | |
call go#util#EchoError(printf('could not apply edit: %s', v:exception)) | |
let l:ok = v:false | |
endtry | |
let l:resp = go#lsp#message#ApplyWorkspaceEditResponse(l:ok) | |
else | |
return | |
3 0.000001 endif | |
3 0.000003 if get(self, 'exited', 0) | |
return | |
3 0.000000 endif | |
3 0.000020 0.000011 let l:msg = self.newResponse(a:req.id, l:resp) | |
3 0.000149 0.000011 call self.write(l:msg) | |
FUNCTION 14() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:181 | |
Called 1 time | |
Total time: 0.005171 | |
Self time: 0.000035 | |
count total (s) self (s) | |
1 0.000002 if has_key(a:resp, 'id') && has_key(self.handlers, a:resp.id) | |
1 0.000000 try | |
1 0.000001 let l:handler = self.handlers[a:resp.id] | |
1 0.000002 let l:winid = win_getid(winnr()) | |
" Always set the active window to the window that was active when | |
" the request was sent. Among other things, this makes sure that | |
" the correct window's location list will be populated when the | |
" list type is 'location' and the user has moved windows since | |
" sending the request. | |
1 0.000002 call win_gotoid(l:handler.winid) | |
1 0.000001 if has_key(a:resp, 'error') | |
call l:handler.requestComplete(0) | |
if has_key(l:handler, 'error') | |
call call(l:handler.error, [a:resp.error.message]) | |
else | |
call go#util#EchoError(a:resp.error.message) | |
endif | |
call win_gotoid(l:winid) | |
return | |
1 0.000000 endif | |
1 0.000005 0.000003 call l:handler.requestComplete(1) | |
1 0.000001 let l:winidBeforeHandler = l:handler.winid | |
1 0.005143 0.000008 call call(l:handler.handleResult, [a:resp.result]) | |
" change the window back to the window that was active when | |
" starting to handle the message _only_ if the handler didn't | |
" update the winid, so that handlers can set the winid if needed | |
" (e.g. :GoDef). | |
1 0.000001 if l:handler.winid == l:winidBeforeHandler | |
1 0.000001 call win_gotoid(l:winid) | |
1 0.000000 endif | |
1 0.000001 finally | |
1 0.000002 call remove(self.handlers, a:resp.id) | |
1 0.000000 endtry | |
1 0.000000 endif | |
FUNCTION 15() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:222 | |
Called 28 times | |
Total time: 0.000283 | |
Self time: 0.000204 | |
count total (s) self (s) | |
" TODO(bc): handle more notifications (e.g. window/showMessage). | |
28 0.000057 if a:req.method == 'textDocument/publishDiagnostics' | |
call self.handleDiagnostics(a:req.params) | |
28 0.000034 elseif a:req.method == 'window/showMessage' | |
3 0.000088 0.000008 call self.showMessage(a:req.params) | |
28 0.000010 endif | |
FUNCTION 17() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:236 | |
Called 3 times | |
Total time: 0.000080 | |
Self time: 0.000021 | |
count total (s) self (s) | |
3 0.000003 let l:msg = a:data.message | |
3 0.000002 if a:data.type == 1 | |
call go#util#EchoError(l:msg) | |
3 0.000002 elseif a:data.type == 2 | |
call go#util#EchoWarning(l:msg) | |
3 0.000001 elseif a:data.type == 3 | |
1 0.000062 0.000004 call go#util#EchoInfo(l:msg) | |
2 0.000001 elseif a:data.type == 4 | |
" do nothing for Log messages | |
3 0.000001 endif | |
FUNCTION 19() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:318 | |
Called 1 time | |
Total time: 0.005134 | |
Self time: 0.000048 | |
count total (s) self (s) | |
1 0.000008 0.000006 if go#config#EchoCommandInfo() | |
1 0.004783 0.000004 call go#util#EchoProgress("initialized gopls") | |
1 0.000002 endif | |
1 0.000003 let status = { 'desc': '', 'type': 'gopls', 'state': 'initialized', } | |
1 0.000073 0.000007 call go#statusline#Update(self.wd, status) | |
1 0.000001 let self.ready = 1 | |
1 0.000018 0.000007 let l:msg = self.newMessage(go#lsp#message#Initialized()) | |
1 0.000028 0.000002 call self.write(l:msg) | |
" send messages queued while waiting for ready. | |
3 0.000002 for l:item in self.queue | |
2 0.000209 0.000005 call self.sendMessage(l:item.data, l:item.handler) | |
3 0.000001 endfor | |
" reset the queue | |
1 0.000003 let self.queue = [] | |
FUNCTION <SNR>144_newHandlerState() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:527 | |
Called 4 times | |
Total time: 0.000398 | |
Self time: 0.000398 | |
count total (s) self (s) | |
4 0.000363 let l:state = { 'winid': win_getid(winnr()), 'statustype': a:statustype, 'jobdir': getcwd(), 'handleResult': funcref('s:noop'), } | |
" explicitly bind requestComplete to state so that within it, self will | |
" always refer to state. See :help Partial for more information. | |
4 0.000014 let l:state.requestComplete = funcref('s:requestComplete', [], l:state) | |
" explicitly bind start to state so that within it, self will | |
" always refer to state. See :help Partial for more information. | |
4 0.000008 let l:state.start = funcref('s:start', [], l:state) | |
4 0.000003 return l:state | |
FUNCTION ale#history#RememberOutput() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/history.vim:58 | |
Called 3 times | |
Total time: 0.000363 | |
Self time: 0.000026 | |
count total (s) self (s) | |
3 0.000356 0.000019 let l:obj = s:FindHistoryItem(a:buffer, a:job_id) | |
3 0.000005 let l:obj.output = a:output | |
FUNCTION <SNR>165_AddProblemsFromOtherBuffers() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:493 | |
Called 1 time | |
Total time: 0.000294 | |
Self time: 0.000294 | |
count total (s) self (s) | |
1 0.000258 let l:filename = expand('#' . a:buffer . ':p') | |
1 0.000001 let l:loclist = [] | |
1 0.000001 let l:name_map = {} | |
" Build a map of the active linters. | |
5 0.000003 for l:linter in a:linters | |
4 0.000004 let l:name_map[l:linter.name] = 1 | |
5 0.000001 endfor | |
" Find the items from other buffers, for the linters that are enabled. | |
2 0.000005 for l:info in values(g:ale_buffer_info) | |
1 0.000001 for l:item in l:info.loclist | |
if has_key(l:item, 'filename')&& l:item.filename is# l:filename&& has_key(l:name_map, l:item.linter_name) | |
" Copy the items and set the buffer numbers to this one. | |
let l:new_item = copy(l:item) | |
let l:new_item.bufnr = a:buffer | |
call add(l:loclist, l:new_item) | |
endif | |
1 0.000000 endfor | |
2 0.000000 endfor | |
1 0.000001 if !empty(l:loclist) | |
call sort(l:loclist, function('ale#util#LocItemCompareWithText')) | |
call uniq(l:loclist, function('ale#util#LocItemCompareWithText')) | |
" Set the loclist variable, used by some parts of ALE. | |
let g:ale_buffer_info[a:buffer].loclist = l:loclist | |
call ale#engine#SetResults(a:buffer, l:loclist) | |
1 0.000000 endif | |
FUNCTION ale#Var() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale.vim:180 | |
Called 46 times | |
Total time: 0.000347 | |
Self time: 0.000347 | |
count total (s) self (s) | |
46 0.000070 let l:full_name = 'ale_' . a:variable_name | |
46 0.000140 let l:vars = getbufvar(str2nr(a:buffer), '', {}) | |
46 0.000109 return get(l:vars, l:full_name, g:[l:full_name]) | |
FUNCTION <SNR>100_system() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:181 | |
Called 4 times | |
Total time: 0.294607 | |
Self time: 0.000421 | |
count total (s) self (s) | |
" Preserve original shell, shellredir and shellcmdflag values | |
4 0.000004 let l:shell = &shell | |
4 0.000004 let l:shellredir = &shellredir | |
4 0.000004 let l:shellcmdflag = &shellcmdflag | |
4 0.000129 0.000118 if !go#util#IsWin() && executable('/bin/sh') | |
4 0.000029 set shell=/bin/sh shellredir=>%s\ 2>&1 shellcmdflag=-c | |
4 0.000001 endif | |
4 0.000019 0.000013 if go#util#IsWin() | |
if executable($COMSPEC) | |
let &shell = $COMSPEC | |
set shellcmdflag=/C | |
endif | |
4 0.000001 endif | |
4 0.000001 try | |
4 0.294314 0.000146 return call('system', [a:cmd] + a:000) | |
4 0.000013 finally | |
" Restore original values | |
4 0.000033 let &shell = l:shell | |
4 0.000007 let &shellredir = l:shellredir | |
4 0.000006 let &shellcmdflag = l:shellcmdflag | |
4 0.000005 endtry | |
FUNCTION ale#ShouldDoNothing() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale.vim:32 | |
Called 6 times | |
Total time: 0.000507 | |
Self time: 0.000397 | |
count total (s) self (s) | |
" The checks are split into separate if statements to make it possible to | |
" profile each check individually with Vim's profiling tools. | |
" | |
" Do nothing if ALE is disabled. | |
6 0.000034 if !getbufvar(a:buffer, 'ale_enabled', get(g:, 'ale_enabled', 0)) | |
return 1 | |
6 0.000001 endif | |
" Don't perform any checks when newer NeoVim versions are exiting. | |
6 0.000013 if get(v:, 'exiting', v:null) isnot v:null | |
return 1 | |
6 0.000001 endif | |
6 0.000015 let l:filetype = getbufvar(a:buffer, '&filetype') | |
" Do nothing when there's no filetype. | |
6 0.000005 if l:filetype is# '' | |
return 1 | |
6 0.000001 endif | |
" Do nothing for diff buffers. | |
6 0.000009 if getbufvar(a:buffer, '&diff') | |
return 1 | |
6 0.000001 endif | |
" Do nothing for blacklisted files. | |
6 0.000025 if index(get(g:, 'ale_filetype_blacklist', []), l:filetype) >= 0 | |
return 1 | |
6 0.000001 endif | |
" Do nothing if running from command mode. | |
6 0.000012 if s:getcmdwintype_exists && !empty(getcmdwintype()) | |
return 1 | |
6 0.000001 endif | |
6 0.000017 let l:filename = fnamemodify(bufname(a:buffer), ':t') | |
" Do nothing for directories. | |
6 0.000004 if l:filename is# '.' | |
return 1 | |
6 0.000001 endif | |
" Don't start linting and so on when an operator is pending. | |
6 0.000059 0.000042 if ale#util#Mode(1) is# 'no' | |
return 1 | |
6 0.000001 endif | |
" Do nothing if running in the sandbox. | |
6 0.000079 0.000019 if ale#util#InSandbox() | |
return 1 | |
6 0.000001 endif | |
" Do nothing if the file is too large. | |
6 0.000052 0.000019 if ale#FileTooLarge(a:buffer) | |
return 1 | |
6 0.000001 endif | |
" Do nothing from CtrlP buffers with CtrlP-funky. | |
6 0.000048 if exists(':CtrlPFunky') is 2&& getbufvar(a:buffer, '&l:statusline') =~# 'CtrlPMode.*funky' | |
return 1 | |
6 0.000002 endif | |
6 0.000003 return 0 | |
FUNCTION go#util#gobin() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:95 | |
Called 1 time | |
Total time: 0.021516 | |
Self time: 0.000029 | |
count total (s) self (s) | |
1 0.021516 0.000029 return substitute(s:exec(['go', 'env', 'GOBIN'])[0], '\n', '', 'g') | |
FUNCTION <SNR>165_RemoveProblemsForDisabledLinters() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:477 | |
Called 1 time | |
Total time: 0.000013 | |
Self time: 0.000013 | |
count total (s) self (s) | |
" Figure out which linters are still enabled, and remove | |
" problems for linters which are no longer enabled. | |
" Problems from other sources will be kept. | |
1 0.000001 let l:name_map = {} | |
5 0.000002 for l:linter in a:linters | |
4 0.000004 let l:name_map[l:linter.name] = 1 | |
5 0.000001 endfor | |
1 0.000004 call filter( get(g:ale_buffer_info[a:buffer], 'loclist', []), 'get(v:val, ''from_other_source'') || get(l:name_map, get(v:val, ''linter_name''))',) | |
FUNCTION go#config#CodeCompletionEnabled() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:512 | |
Called 1 time | |
Total time: 0.000009 | |
Self time: 0.000009 | |
count total (s) self (s) | |
1 0.000007 return get(g:, "go_code_completion_enabled", 1) | |
FUNCTION <SNR>180_FixList() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/list.vim:66 | |
Called 3 times | |
Total time: 0.005155 | |
Self time: 0.001886 | |
count total (s) self (s) | |
3 0.000043 0.000013 let l:format = ale#Var(a:buffer, 'loclist_msg_format') | |
3 0.000003 let l:new_list = [] | |
87 0.000045 for l:item in a:list | |
84 0.000292 let l:fixed_item = copy(l:item) | |
84 0.004388 0.001150 let l:fixed_item.text = ale#GetLocItemMessage(l:item, l:format) | |
84 0.000055 if l:item.bufnr == -1 | |
" If the buffer number is invalid, remove it. | |
call remove(l:fixed_item, 'bufnr') | |
84 0.000023 endif | |
84 0.000103 call add(l:new_list, l:fixed_item) | |
87 0.000029 endfor | |
3 0.000001 return l:new_list | |
FUNCTION ale#path#FindExecutable() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/path.vim:102 | |
Called 1 time | |
Total time: 0.000047 | |
Self time: 0.000011 | |
count total (s) self (s) | |
1 0.000009 0.000003 if ale#Var(a:buffer, a:base_var_name . '_use_global') | |
return ale#Var(a:buffer, a:base_var_name . '_executable') | |
1 0.000000 endif | |
1 0.000036 0.000005 let l:nearest = ale#path#FindNearestExecutable(a:buffer, a:path_list) | |
1 0.000001 if !empty(l:nearest) | |
1 0.000000 return l:nearest | |
endif | |
return ale#Var(a:buffer, a:base_var_name . '_executable') | |
FUNCTION go#util#Chdir() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:721 | |
Called 8 times | |
Total time: 0.003630 | |
Self time: 0.003630 | |
count total (s) self (s) | |
8 0.000016 if !exists('*chdir') | |
8 0.001080 let l:olddir = getcwd() | |
8 0.000033 let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' | |
8 0.002475 execute printf('%s %s', cd, fnameescape(a:dir)) | |
8 0.000013 return l:olddir | |
endif | |
return chdir(a:dir) | |
FUNCTION go#util#PathListSep() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:14 | |
Called 8 times | |
Total time: 0.000047 | |
Self time: 0.000032 | |
count total (s) self (s) | |
8 0.000036 0.000020 if go#util#IsWin() | |
return ";" | |
8 0.000002 endif | |
8 0.000003 return ":" | |
FUNCTION 20() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:342 | |
Called 5 times | |
Total time: 0.030273 | |
Self time: 0.001999 | |
count total (s) self (s) | |
5 0.000005 if !self.last_request_id | |
1 0.011365 0.000029 let l:wd = go#util#ModuleRoot() | |
1 0.000001 if l:wd == -1 | |
call go#util#EchoError('could not determine appropriate working directory for gopls') | |
return -1 | |
1 0.000000 endif | |
1 0.000000 if l:wd == '' | |
let l:wd = getcwd() | |
1 0.000000 endif | |
1 0.000003 let self.wd = l:wd | |
1 0.000008 0.000006 if go#config#EchoCommandInfo() | |
1 0.015827 0.000004 call go#util#EchoProgress("initializing gopls") | |
1 0.000000 endif | |
1 0.000002 let l:status = { 'desc': '', 'type': 'gopls', 'state': 'initializing', } | |
1 0.001232 0.000732 call go#statusline#Update(l:wd, l:status) | |
1 0.000004 let self.workspaceDirectories = add(self.workspaceDirectories, l:wd) | |
1 0.000129 0.000007 let l:msg = self.newMessage(go#lsp#message#Initialize(l:wd)) | |
1 0.000132 0.000004 let l:state = s:newHandlerState('') | |
1 0.000003 let l:state.handleResult = funcref('self.handleInitializeResult', [], l:self) | |
1 0.000002 let self.handlers[l:msg.id] = l:state | |
1 0.000007 0.000004 call l:state.start() | |
1 0.000048 0.000002 call self.write(l:msg) | |
5 0.000001 endif | |
5 0.000002 if !self.ready | |
2 0.000006 call add(self.queue, {'data': a:data, 'handler': a:handler}) | |
2 0.000001 return | |
3 0.000001 endif | |
3 0.000028 0.000007 let l:msg = self.newMessage(a:data) | |
3 0.000002 if has_key(l:msg, 'id') | |
let self.handlers[l:msg.id] = a:handler | |
3 0.000000 endif | |
3 0.001093 0.001079 call a:handler.start() | |
3 0.000287 0.000008 call self.write(l:msg) | |
FUNCTION 21() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:394 | |
Called 5 times | |
Total time: 0.000040 | |
Self time: 0.000040 | |
count total (s) self (s) | |
5 0.000009 let l:msg = { 'method': a:data.method, 'jsonrpc': '2.0', } | |
5 0.000002 if !a:data.notification | |
1 0.000001 let self.last_request_id += 1 | |
1 0.000001 let l:msg.id = self.last_request_id | |
5 0.000001 endif | |
5 0.000008 if has_key(a:data, 'params') | |
5 0.000004 let l:msg.params = a:data.params | |
5 0.000001 endif | |
5 0.000002 return l:msg | |
FUNCTION 22() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:412 | |
Called 3 times | |
Total time: 0.000009 | |
Self time: 0.000009 | |
count total (s) self (s) | |
3 0.000007 let l:msg = { 'jsonrpc': '2.0', 'id': a:id, 'result': a:result, } | |
3 0.000001 return l:msg | |
FUNCTION 23() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:422 | |
Called 8 times | |
Total time: 0.000488 | |
Self time: 0.000437 | |
count total (s) self (s) | |
8 0.000017 if empty(get(self, 'job', {})) | |
return | |
8 0.000002 endif | |
8 0.000224 let l:body = json_encode(a:msg) | |
8 0.000024 let l:data = 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body | |
8 0.000095 0.000044 call s:debug('sent', l:data) | |
8 0.000010 if has('nvim') | |
8 0.000093 call chansend(self.job, l:data) | |
8 0.000009 return | |
endif | |
try | |
call ch_sendraw(self.job, l:data) | |
catch | |
call go#util#EchoError(printf('could not send message: %s', v:exception)) | |
endtry | |
FUNCTION go#util#ExecInDir() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:239 | |
Called 3 times | |
Total time: 0.304865 | |
Self time: 0.004695 | |
count total (s) self (s) | |
3 0.004642 let l:wd = expand('%:p:h') | |
3 0.300222 0.000052 return call('go#util#ExecInWorkDir', [a:cmd, l:wd] + a:000) | |
FUNCTION <SNR>126_IsCallback() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/linter.vim:75 | |
Called 22 times | |
Total time: 0.000046 | |
Self time: 0.000046 | |
count total (s) self (s) | |
22 0.000041 return type(a:value) is v:t_string || type(a:value) is v:t_func | |
FUNCTION ale#path#FindNearestFile() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/path.vim:37 | |
Called 1 time | |
Total time: 0.000680 | |
Self time: 0.000680 | |
count total (s) self (s) | |
1 0.000283 let l:buffer_filename = fnamemodify(bufname(a:buffer), ':p') | |
1 0.000006 let l:buffer_filename = fnameescape(l:buffer_filename) | |
1 0.000299 let l:relative_path = findfile(a:filename, l:buffer_filename . ';') | |
1 0.000002 if !empty(l:relative_path) | |
1 0.000089 return fnamemodify(l:relative_path, ':p') | |
endif | |
return '' | |
FUNCTION <SNR>57_LoadIndent() | |
Defined: /opt/homebrew/Cellar/neovim/0.5.1_1/share/nvim/runtime/indent.vim:13 | |
Called 1 time | |
Total time: 0.003015 | |
Self time: 0.002609 | |
count total (s) self (s) | |
1 0.000002 if exists("b:undo_indent") | |
exe b:undo_indent | |
unlet! b:undo_indent b:did_indent | |
1 0.000000 endif | |
1 0.000002 let s = expand("<amatch>") | |
1 0.000001 if s != "" | |
1 0.000001 if exists("b:did_indent") | |
unlet b:did_indent | |
1 0.000000 endif | |
" When there is a dot it is used to separate filetype names. Thus for | |
" "aaa.bbb" load "indent/aaa.vim" and then "indent/bbb.vim". | |
2 0.000003 for name in split(s, '\.') | |
1 0.002251 0.001846 exe 'runtime! indent/' . name . '.vim' | |
1 0.000747 exe 'runtime! indent/' . name . '.lua' | |
2 0.000001 endfor | |
1 0.000000 endif | |
FUNCTION <SNR>144_newlsp() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:23 | |
Called 1 time | |
Total time: 0.003081 | |
Self time: 0.000783 | |
count total (s) self (s) | |
" job is the job used to talk to the backing instance of gopls. | |
" ready is 0 until the initialize response has been received. 1 afterwards. | |
" queue is messages to send after initialization | |
" last_request_id is id of the most recently sent request. | |
" buf is unprocessed/incomplete responses | |
" handlers is a mapping of request ids to dictionaries of functions. | |
" request id -> {start, requestComplete, handleResult, error} | |
" * start is a function that takes no arguments | |
" * requestComplete is a function that takes 1 argument. The parameter will be 1 | |
" if the call was succesful. | |
" * handleResult takes a single argument, the result message received from gopls | |
" * error takes a single argument, the error message received from gopls. | |
" The error method is optional. | |
" workspaceDirectories is an array of named workspaces. | |
" wd is the working directory for gopls | |
" diagnostics is a dictionary whose keys are filenames and each value is a | |
" list of diagnostic messages for the file. | |
" diagnosticsQueue is a queue of diagnostics notifications that have been | |
" received, but not yet processed. | |
" fileVersions is a dictionary of filenames to versions. | |
" notificationQueue is a dictionary of filenames to functions. For a given | |
" filename, each notification will call the first function in the list of | |
" function values and remove it from the list. The functions should accept | |
" two arguments: an absolute path and a list of diagnotics messages for | |
" the file. | |
1 0.000008 let l:lsp = { 'job': '', 'ready': 0, 'queue': [], 'last_request_id': 0, 'buf': '', 'handlers': {}, 'workspaceDirectories': [], 'wd' : '', 'diagnosticsQueue': [], 'diagnostics': {}, 'fileVersions': {}, 'notificationQueue': {}, } | |
1 0.000005 0.000003 if !go#config#GoplsEnabled() | |
let l:lsp.sendMessage = funcref('s:noop') | |
return l:lsp | |
1 0.000000 endif | |
1 0.000005 0.000002 if !go#util#has_job() | |
let l:oldshortmess=&shortmess | |
if has('nvim') | |
set shortmess-=F | |
endif | |
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 l:lsp | |
1 0.000000 endif | |
1 0.000001 function! l:lsp.readMessage(data) dict abort | |
let l:responses = [] | |
let l:rest = a:data | |
while 1 | |
" Look for the end of the HTTP headers | |
let l:body_start_idx = matchend(l:rest, "\r\n\r\n") | |
if l:body_start_idx < 0 | |
" incomplete header | |
break | |
endif | |
" Parse the Content-Length header. | |
let l:header = l:rest[:l:body_start_idx - 4] | |
let l:length_match = matchlist( l:header, '\vContent-Length: *(\d+)') | |
if empty(l:length_match) | |
" TODO(bc): shutdown gopls? | |
throw "invalid JSON-RPC header:\n" . l:header | |
endif | |
" get the start of the rest | |
let l:next_start_idx = l:body_start_idx + str2nr(l:length_match[1]) | |
if len(l:rest) < l:next_start_idx | |
" incomplete response body | |
break | |
endif | |
call s:debug('received', l:rest[:l:next_start_idx - 1]) | |
let l:body = l:rest[l:body_start_idx : l:next_start_idx - 1] | |
let l:rest = l:rest[l:next_start_idx :] | |
try | |
" add the json body to the list. | |
call add(l:responses, json_decode(l:body)) | |
catch | |
" TODO(bc): log the message and/or show an error message. | |
finally | |
" intentionally left blank. | |
endtry | |
endwhile | |
return [l:rest, l:responses] | |
endfunction | |
1 0.000001 function! l:lsp.handleMessage(ch, data) dict abort | |
let self.buf .= a:data | |
let [self.buf, l:messages] = self.readMessage(self.buf) | |
for l:message in l:messages | |
if has_key(l:message, 'method') | |
if has_key(l:message, 'id') | |
call self.handleRequest(l:message) | |
else | |
call self.handleNotification(l:message) | |
endif | |
elseif has_key(l:message, 'result') || has_key(l:message, 'error') | |
call self.handleResponse(l:message) | |
endif | |
endfor | |
endfunction | |
1 0.000001 function! l:lsp.handleRequest(req) dict abort | |
if a:req.method == 'workspace/workspaceFolders' | |
let l:resp = go#lsp#message#WorkspaceFoldersResult(self.workspaceDirectories) | |
elseif a:req.method == 'workspace/configuration' && has_key(a:req, 'params') && has_key(a:req.params, 'items') | |
let l:resp = go#lsp#message#ConfigurationResult(a:req.params.items) | |
elseif a:req.method == 'client/registerCapability' && has_key(a:req, 'params') && has_key(a:req.params, 'registrations') | |
let l:resp = v:null | |
elseif a:req.method == 'workspace/applyEdit' | |
try | |
let l:ok = v:true | |
for l:change in a:req.params.edit.documentChanges | |
call s:applyDocumentChanges(a:req.params.edit.documentChanges) | |
endfor | |
catch | |
call go#util#EchoError(printf('could not apply edit: %s', v:exception)) | |
let l:ok = v:false | |
endtry | |
let l:resp = go#lsp#message#ApplyWorkspaceEditResponse(l:ok) | |
else | |
return | |
endif | |
if get(self, 'exited', 0) | |
return | |
endif | |
let l:msg = self.newResponse(a:req.id, l:resp) | |
call self.write(l:msg) | |
endfunction | |
1 0.000001 function! l:lsp.handleResponse(resp) dict abort | |
if has_key(a:resp, 'id') && has_key(self.handlers, a:resp.id) | |
try | |
let l:handler = self.handlers[a:resp.id] | |
let l:winid = win_getid(winnr()) | |
" Always set the active window to the window that was active when | |
" the request was sent. Among other things, this makes sure that | |
" the correct window's location list will be populated when the | |
" list type is 'location' and the user has moved windows since | |
" sending the request. | |
call win_gotoid(l:handler.winid) | |
if has_key(a:resp, 'error') | |
call l:handler.requestComplete(0) | |
if has_key(l:handler, 'error') | |
call call(l:handler.error, [a:resp.error.message]) | |
else | |
call go#util#EchoError(a:resp.error.message) | |
endif | |
call win_gotoid(l:winid) | |
return | |
endif | |
call l:handler.requestComplete(1) | |
let l:winidBeforeHandler = l:handler.winid | |
call call(l:handler.handleResult, [a:resp.result]) | |
" change the window back to the window that was active when | |
" starting to handle the message _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, a:resp.id) | |
endtry | |
endif | |
endfunction | |
1 0.000000 function! l:lsp.handleNotification(req) dict abort | |
" TODO(bc): handle more notifications (e.g. window/showMessage). | |
if a:req.method == 'textDocument/publishDiagnostics' | |
call self.handleDiagnostics(a:req.params) | |
elseif a:req.method == 'window/showMessage' | |
call self.showMessage(a:req.params) | |
endif | |
endfunction | |
1 0.000000 function! l:lsp.handleDiagnostics(data) dict abort | |
let self.diagnosticsQueue = add(self.diagnosticsQueue, a:data) | |
call self.updateDiagnostics() | |
endfunction | |
1 0.000000 function! l:lsp.showMessage(data) dict abort | |
let l:msg = a:data.message | |
if a:data.type == 1 | |
call go#util#EchoError(l:msg) | |
elseif a:data.type == 2 | |
call go#util#EchoWarning(l:msg) | |
elseif a:data.type == 3 | |
call go#util#EchoInfo(l:msg) | |
elseif a:data.type == 4 | |
" do nothing for Log messages | |
endif | |
endfunction | |
" TODO(bc): process the queue asynchronously | |
1 0.000000 function! l:lsp.updateDiagnostics() dict abort | |
let l:level = go#config#DiagnosticsLevel() | |
for l:data in self.diagnosticsQueue | |
call remove(self.diagnosticsQueue, 0) | |
try | |
let l:diagnostics = [] | |
let l:errorMatches = [] | |
let l:warningMatches = [] | |
let l:fname = go#path#FromURI(l:data.uri) | |
" get the buffer name relative to the current directory, because | |
" Vim says that a buffer name can't be an absolute path. | |
let l:bufname = fnamemodify(l:fname, ':.') | |
if len(l:data.diagnostics) > 0 && (l:level > 0 || bufnr(l:bufname) == bufnr('')) | |
" make sure the buffer is listed and loaded before calling getbufline() on it | |
if !bufexists(l:bufname) | |
call bufadd(l:bufname) | |
endif | |
if !bufloaded(l:bufname) | |
call bufload(l:bufname) | |
endif | |
for l:diag in l:data.diagnostics | |
if l:level < l:diag.severity | |
continue | |
endif | |
let [l:error, l:matchpos] = s:errorFromDiagnostic(l:diag, l:bufname, l:fname) | |
let l:diagnostics = add(l:diagnostics, l:error) | |
if empty(l:matchpos) | |
continue | |
endif | |
if l:diag.severity == 1 | |
let l:errorMatches = add(l:errorMatches, l:matchpos) | |
elseif l:diag.severity == 2 | |
let l:warningMatches = add(l:warningMatches, l:matchpos) | |
endif | |
endfor | |
endif | |
if bufnr(l:bufname) == bufnr('') | |
" only apply highlighting when the diagnostics are for the current | |
" version. | |
let l:lsp = s:lspfactory.get() | |
let l:version = get(l:lsp.fileVersions, l:fname, 0) | |
" it's tempting to only highlight matches when they are for the | |
" current version of the buffer, but that causes problems when the | |
" version number has been updated and the content has not. In such a | |
" case, the diagnostics may not be sent for later versions. | |
call s:highlightMatches(l:errorMatches, l:warningMatches) | |
endif | |
let self.diagnostics[l:fname] = l:diagnostics | |
if has_key(self.notificationQueue, l:fname) && len(self.notificationQueue[l:fname]) > 0 | |
call call(self.notificationQueue[l:fname][0], copy(l:diagnostics)) | |
call remove(self.notificationQueue[l:fname], 0) | |
endif | |
catch | |
"call go#util#EchoError(printf('%s: %s', v:throwpoint, v:exception)) | |
endtry | |
endfor | |
endfunction | |
1 0.000000 function! l:lsp.handleInitializeResult(result) dict abort | |
if go#config#EchoCommandInfo() | |
call go#util#EchoProgress("initialized gopls") | |
endif | |
let status = { 'desc': '', 'type': 'gopls', 'state': 'initialized', } | |
call go#statusline#Update(self.wd, status) | |
let self.ready = 1 | |
let l:msg = self.newMessage(go#lsp#message#Initialized()) | |
call self.write(l:msg) | |
" send messages queued while waiting for ready. | |
for l:item in self.queue | |
call self.sendMessage(l:item.data, l:item.handler) | |
endfor | |
" reset the queue | |
let self.queue = [] | |
endfunction | |
1 0.000000 function! l:lsp.sendMessage(data, handler) dict abort | |
if !self.last_request_id | |
let l:wd = go#util#ModuleRoot() | |
if l:wd == -1 | |
call go#util#EchoError('could not determine appropriate working directory for gopls') | |
return -1 | |
endif | |
if l:wd == '' | |
let l:wd = getcwd() | |
endif | |
let self.wd = l:wd | |
if go#config#EchoCommandInfo() | |
call go#util#EchoProgress("initializing gopls") | |
endif | |
let l:status = { 'desc': '', 'type': 'gopls', 'state': 'initializing', } | |
call go#statusline#Update(l:wd, l:status) | |
let self.workspaceDirectories = add(self.workspaceDirectories, l:wd) | |
let l:msg = self.newMessage(go#lsp#message#Initialize(l:wd)) | |
let l:state = s:newHandlerState('') | |
let l:state.handleResult = funcref('self.handleInitializeResult', [], l:self) | |
let self.handlers[l:msg.id] = l:state | |
call l:state.start() | |
call self.write(l:msg) | |
endif | |
if !self.ready | |
call add(self.queue, {'data': a:data, 'handler': a:handler}) | |
return | |
endif | |
let l:msg = self.newMessage(a:data) | |
if has_key(l:msg, 'id') | |
let self.handlers[l:msg.id] = a:handler | |
endif | |
call a:handler.start() | |
call self.write(l:msg) | |
endfunction | |
" newMessage returns a message constructed from data. data should be a dict | |
" with 2 or 3 keys: notification, method, and optionally params. | |
1 0.000000 function! l:lsp.newMessage(data) dict abort | |
let l:msg = { 'method': a:data.method, 'jsonrpc': '2.0', } | |
if !a:data.notification | |
let self.last_request_id += 1 | |
let l:msg.id = self.last_request_id | |
endif | |
if has_key(a:data, 'params') | |
let l:msg.params = a:data.params | |
endif | |
return l:msg | |
endfunction | |
1 0.000001 function l:lsp.newResponse(id, result) dict abort | |
let l:msg = { 'jsonrpc': '2.0', 'id': a:id, 'result': a:result, } | |
return l:msg | |
endfunction | |
1 0.000000 function! l:lsp.write(msg) dict abort | |
if empty(get(self, 'job', {})) | |
return | |
endif | |
let l:body = json_encode(a:msg) | |
let l:data = 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body | |
call s:debug('sent', l:data) | |
if has('nvim') | |
call chansend(self.job, l:data) | |
return | |
endif | |
try | |
call ch_sendraw(self.job, l:data) | |
catch | |
call go#util#EchoError(printf('could not send message: %s', v:exception)) | |
endtry | |
endfunction | |
1 0.000001 function! l:lsp.exit_cb(job, exit_status) dict | |
let self.exited = 1 | |
if !get(self, 'restarting', 0) | |
return | |
endif | |
let l:queue = self.queue | |
let l:workspaces = self.workspaceDirectories | |
call s:lspfactory.reset() | |
let l:lsp = s:lspfactory.get() | |
" restore workspaces | |
call call('go#lsp#AddWorkspaceDirectory', l:workspaces) | |
" * send DidOpen messages for all buffers that have b:did_lsp_open set | |
" TODO(bc): check modifiable and filetype, too? | |
bufdo if get(b:, 'go_lsp_did_open', 0) | if &modified | call go#lsp#DidOpen(expand('%:p')) | else | call go#lsp#DidChange(expand('%:p')) | endif | endif | |
let l:lsp.queue = extend(l:lsp.queue, l:queue) | |
return | |
endfunction | |
1 0.000000 function! l:lsp.close_cb(ch) dict abort | |
" TODO(bc): remove the buffer variables that indicate that gopls has been | |
" informed that the file is open | |
endfunction | |
1 0.000000 function! l:lsp.err_cb(ch, msg) dict abort | |
if a:msg =~ '^\d\{4}/\d\d/\d\d\ \d\d:\d\d:\d\d debug server listening on port \d\+$' && !get(self, 'debugport', 0) | |
let self.debugport = substitute(a:msg, '\d\{4}/\d\d/\d\d\ \d\d:\d\d:\d\d debug server listening on port \(\d\+\).*$', '\1', '') | |
endif | |
call s:debug('stderr', a:msg) | |
endfunction | |
" explicitly bind callbacks to l:lsp so that within it, self will always refer | |
" to l:lsp instead of l:opts. See :help Partial for more information. | |
1 0.000085 let l:opts = { 'in_mode': 'raw', 'out_mode': 'raw', 'err_mode': 'nl', 'noblock': 1, 'err_cb': funcref('l:lsp.err_cb', [], l:lsp), 'out_cb': funcref('l:lsp.handleMessage', [], l:lsp), 'close_cb': funcref('l:lsp.close_cb', [], l:lsp), 'exit_cb': funcref('l:lsp.exit_cb', [], l:lsp), 'cwd': getcwd(),} | |
1 0.000133 0.000007 let l:bin_path = go#path#CheckBinPath("gopls") | |
1 0.000001 if empty(l:bin_path) | |
let l:lsp.sendMessage = funcref('s:noop') | |
return l:lsp | |
1 0.000000 endif | |
1 0.000001 let l:cmd = [l:bin_path] | |
1 0.000005 0.000003 let l:cmdopts = go#config#GoplsOptions() | |
1 0.000007 0.000003 if go#util#HasDebug('lsp') | |
" debugging can be enabled either with g:go_debug or with | |
" g:go_gopls_options; use g:go_gopls_options if it's given in case users | |
" are running the gopls debug server on a known port. | |
let l:needsDebug = 1 | |
for l:item in l:cmdopts | |
let l:idx = stridx(l:item, '-debug') | |
if l:idx == 0 || l:idx == 1 | |
let l:needsDebug = 0 | |
endif | |
endfor | |
if l:needsDebug | |
let l:cmd = extend(l:cmd, ['-debug', 'localhost:0']) | |
endif | |
1 0.000000 endif | |
1 0.002726 0.000564 let l:lsp.job = go#job#Start(l:cmd+l:cmdopts, l:opts) | |
1 0.000003 return l:lsp | |
FUNCTION dashboard#change_to_dir() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/dashboard-nvim/autoload/dashboard.vim:216 | |
Called 1 time | |
Total time: 0.000006 | |
Self time: 0.000006 | |
count total (s) self (s) | |
1 0.000002 if get(g:, 'dashboard_change_to_dir', 0) | |
let dir = fnamemodify(a:path, ':h') | |
if isdirectory(dir) | |
echom "test" | |
execute 'lcd' dir | |
else | |
" Do nothing. E.g. a:path == `scp://foo/bar` | |
endif | |
1 0.000000 endif | |
FUNCTION ale#history#SetExitCode() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/history.vim:49 | |
Called 3 times | |
Total time: 0.000141 | |
Self time: 0.000034 | |
count total (s) self (s) | |
3 0.000130 0.000023 let l:obj = s:FindHistoryItem(a:buffer, a:job_id) | |
" If we find a match, then set the code and status. | |
3 0.000005 let l:obj.exit_code = a:exit_code | |
3 0.000003 let l:obj.status = 'finished' | |
FUNCTION <SNR>126_GetLinterNames() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/linter.vim:330 | |
Called 1 time | |
Total time: 0.000013 | |
Self time: 0.000013 | |
count total (s) self (s) | |
1 0.000001 let l:buffer_ale_linters = get(b:, 'ale_linters', {}) | |
" b:ale_linters can be set to 'all' | |
1 0.000001 if l:buffer_ale_linters is# 'all' | |
return 'all' | |
1 0.000000 endif | |
" b:ale_linters can be set to a List. | |
1 0.000001 if type(l:buffer_ale_linters) is v:t_list | |
return l:buffer_ale_linters | |
1 0.000000 endif | |
" Try to get a buffer-local setting for the filetype | |
1 0.000001 if has_key(l:buffer_ale_linters, a:original_filetype) | |
return l:buffer_ale_linters[a:original_filetype] | |
1 0.000000 endif | |
" Try to get a global setting for the filetype | |
1 0.000001 if has_key(g:ale_linters, a:original_filetype) | |
return g:ale_linters[a:original_filetype] | |
1 0.000000 endif | |
" If the user has configured ALE to only enable linters explicitly, then | |
" don't enable any linters by default. | |
1 0.000001 if g:ale_linters_explicit | |
return [] | |
1 0.000000 endif | |
" Try to get a default setting for the filetype | |
1 0.000001 if has_key(s:default_ale_linters, a:original_filetype) | |
1 0.000001 return s:default_ale_linters[a:original_filetype] | |
endif | |
return 'all' | |
FUNCTION ale#Pad() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale.vim:202 | |
Called 1 time | |
Total time: 0.000001 | |
Self time: 0.000001 | |
count total (s) self (s) | |
1 0.000001 return !empty(a:string) ? ' ' . a:string : '' | |
FUNCTION ale#util#Writefile() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/util.vim:431 | |
Called 2 times | |
Total time: 0.000934 | |
Self time: 0.000934 | |
count total (s) self (s) | |
2 0.000009 let l:corrected_lines = getbufvar(a:buffer, '&fileformat') is# 'dos' ? map(copy(a:lines), 'substitute(v:val, ''\r*$'', ''\r'', '''')') : a:lines | |
" Set binary flag if buffer doesn't have eol and nofixeol to avoid appending newline | |
2 0.000008 let l:flags = !getbufvar(a:buffer, '&eol') && exists('+fixeol') && !&fixeol ? 'bS' : 'S' | |
2 0.000914 call writefile(l:corrected_lines, a:filename, l:flags) " no-custom-checks | |
FUNCTION go#util#env() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:73 | |
Called 4 times | |
Total time: 0.021679 | |
Self time: 0.000162 | |
count total (s) self (s) | |
4 0.000007 let l:key = tolower(a:key) | |
4 0.000006 if has_key(s:env_cache, l:key) | |
3 0.000003 return s:env_cache[l:key] | |
1 0.000000 endif | |
1 0.000097 if executable('go') | |
1 0.021530 0.000015 let l:var = call('go#util#'.l:key, []) | |
1 0.000016 0.000014 if go#util#ShellError() != 0 | |
call go#util#EchoError(printf("'go env %s' failed", toupper(l:key))) | |
return '' | |
1 0.000001 endif | |
else | |
let l:var = eval("$".toupper(a:key)) | |
1 0.000001 endif | |
1 0.000004 let s:env_cache[l:key] = l:var | |
1 0.000001 return l:var | |
FUNCTION ale_linters#go#gofmt#GetCommand() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gofmt.vim:4 | |
Called 1 time | |
Total time: 0.000851 | |
Self time: 0.000505 | |
count total (s) self (s) | |
1 0.000851 0.000505 return ale#go#EnvString(a:buffer) . '%e -e %t' | |
FUNCTION <SNR>165_RunJob() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:401 | |
Called 3 times | |
Total time: 0.010244 | |
Self time: 0.000559 | |
count total (s) self (s) | |
3 0.000035 0.000029 if ale#command#IsDeferred(a:command) | |
let a:command.result_callback = { command -> s:RunJob(command, a:options)} | |
return 1 | |
3 0.000000 endif | |
3 0.000002 let l:command = a:command | |
3 0.000002 if empty(l:command) | |
return 0 | |
3 0.000000 endif | |
3 0.000002 let l:cwd = a:options.cwd | |
3 0.000002 let l:executable = a:options.executable | |
3 0.000002 let l:buffer = a:options.buffer | |
3 0.000002 let l:linter = a:options.linter | |
3 0.000003 let l:output_stream = a:options.output_stream | |
3 0.000004 let l:read_buffer = a:options.read_buffer && !a:options.lint_file | |
3 0.000007 let l:info = g:ale_buffer_info[l:buffer] | |
3 0.000014 let l:Callback = function('s:HandleExit', [{ 'linter': l:linter, 'executable': l:executable,}]) | |
3 0.009578 0.000050 let l:result = ale#command#Run(l:buffer, l:command, l:Callback, { 'cwd': l:cwd, 'output_stream': l:output_stream, 'executable': l:executable, 'read_buffer': l:read_buffer, 'log_output': 1, 'filename_mappings': ale#GetFilenameMappings(l:buffer, l:linter.name),}) | |
" Only proceed if the job is being run. | |
3 0.000003 if empty(l:result) | |
return 0 | |
3 0.000000 endif | |
3 0.000067 0.000024 call ale#engine#MarkLinterActive(l:info, l:linter) | |
3 0.000488 0.000380 silent doautocmd <nomodeline> User ALEJobStarted | |
3 0.000008 return 1 | |
FUNCTION ale#lsp_linter#GetOptions() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp_linter.vim:167 | |
Called 1 time | |
Total time: 0.000017 | |
Self time: 0.000010 | |
count total (s) self (s) | |
1 0.000001 if has_key(a:linter, 'initialization_options_callback') | |
return ale#util#GetFunction(a:linter.initialization_options_callback)(a:buffer) | |
1 0.000000 endif | |
1 0.000001 if has_key(a:linter, 'initialization_options') | |
1 0.000001 let l:Options = a:linter.initialization_options | |
1 0.000001 if type(l:Options) is v:t_func | |
1 0.000009 0.000003 let l:Options = l:Options(a:buffer) | |
1 0.000000 endif | |
1 0.000000 return l:Options | |
endif | |
return {} | |
FUNCTION go#lsp#message#ChangeWorkspaceFolders() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp/message.vim:260 | |
Called 1 time | |
Total time: 0.001126 | |
Self time: 0.000022 | |
count total (s) self (s) | |
1 0.001117 0.000012 let l:addDirs = map(copy(a:add), function('s:workspaceFolder', [])) | |
1 0.000004 let l:removeDirs = map(copy(a:remove), function('s:workspaceFolder', [])) | |
1 0.000003 return { 'notification': 1, 'method': 'workspace/didChangeWorkspaceFolders', 'params': { 'event': { 'removed': l:removeDirs, 'added': l:addDirs, }, } } | |
FUNCTION ale#lsp#Register() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp.vim:10 | |
Called 1 time | |
Total time: 0.000021 | |
Self time: 0.000021 | |
count total (s) self (s) | |
1 0.000003 let l:conn_id = a:executable_or_address . ':' . a:project | |
1 0.000002 if !has_key(s:connections, l:conn_id) | |
" is_tsserver: 1 if the connection is for tsserver. | |
" data: The message data received so far. | |
" root: The project root. | |
" open_documents: A Dictionary mapping buffers to b:changedtick, keeping | |
" track of when documents were opened, and when we last changed them. | |
" initialized: 0 if the connection is ready, 1 otherwise. | |
" init_request_id: The ID for the init request. | |
" init_options: Options to send to the server. | |
" config: Configuration settings to send to the server. | |
" callback_list: A list of callbacks for handling LSP responses. | |
" capabilities_queue: The list of callbacks to call with capabilities. | |
" capabilities: Features the server supports. | |
1 0.000012 let s:connections[l:conn_id] = { 'id': l:conn_id, 'is_tsserver': 0, 'data': '', 'root': a:project, 'open_documents': {}, 'initialized': 0, 'init_request_id': 0, 'init_options': a:init_options, 'config': {}, 'callback_list': [], 'init_queue': [], 'capabilities': { 'hover': 0, 'rename': 0, 'references': 0, 'completion': 0, 'completion_trigger_characters': [], 'definition': 0, 'typeDefinition': 0, 'symbol_search': 0, 'code_actions': 0, 'did_save': 0, 'includeText': 0, },} | |
1 0.000001 endif | |
1 0.000001 return l:conn_id | |
FUNCTION ale#lsp_linter#HandleLSPResponse() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp_linter.vim:139 | |
Called 27 times | |
Total time: 0.003120 | |
Self time: 0.002619 | |
count total (s) self (s) | |
27 0.000073 let l:method = get(a:response, 'method', '') | |
27 0.000093 if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error') | |
let l:linter_name = get(s:lsp_linter_map, a:conn_id, '') | |
call s:HandleLSPErrorMessage(l:linter_name, a:response) | |
27 0.000028 elseif l:method is# 'textDocument/publishDiagnostics' | |
call s:HandleLSPDiagnostics(a:conn_id, a:response) | |
27 0.000020 elseif l:method is# 'window/showMessage' | |
2 0.002253 0.001752 call ale#lsp_window#HandleShowMessage( s:lsp_linter_map[a:conn_id], g:ale_lsp_show_message_format, a:response.params) | |
25 0.000054 elseif get(a:response, 'type', '') is# 'event'&& get(a:response, 'event', '') is# 'semanticDiag' | |
call s:HandleTSServerDiagnostics(a:response, 'semantic') | |
25 0.000124 elseif get(a:response, 'type', '') is# 'event'&& get(a:response, 'event', '') is# 'syntaxDiag' | |
call s:HandleTSServerDiagnostics(a:response, 'syntax') | |
25 0.000073 elseif get(a:response, 'type', '') is# 'event'&& get(a:response, 'event', '') is# 'suggestionDiag'&& get(g:, 'ale_lsp_suggestions', '1') == 1 | |
call s:HandleTSServerDiagnostics(a:response, 'suggestion') | |
27 0.000009 endif | |
FUNCTION <SNR>100_echo() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:407 | |
Called 3 times | |
Total time: 0.000225 | |
Self time: 0.000225 | |
count total (s) self (s) | |
3 0.000007 let l:msg = [] | |
3 0.000006 if type(a:msg) != type([]) | |
3 0.000008 let l:msg = split(a:msg, "\n") | |
else | |
let l:msg = a:msg | |
3 0.000001 endif | |
" Tabs display as ^I or <09>, so manually expand them. | |
3 0.000014 let l:msg = map(l:msg, 'substitute(v:val, "\t", " ", "")') | |
3 0.000029 exe 'echohl ' . a:hi | |
6 0.000006 for line in l:msg | |
3 0.000088 echom "vim-go: " . line | |
6 0.000008 endfor | |
3 0.000038 echohl None | |
FUNCTION go#lsp#message#Initialize() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp/message.vim:5 | |
Called 1 time | |
Total time: 0.000111 | |
Self time: 0.000040 | |
count total (s) self (s) | |
1 0.000110 0.000040 return { 'notification': 0, 'method': 'initialize', 'params': { 'processId': getpid(), 'rootUri': go#path#ToURI(a:wd), 'capabilities': { 'workspace': { 'workspaceFolders': v:true, 'didChangeConfiguration': { 'dynamicRegistration': v:true, }, 'workspaceEdit': { 'documentChanges': v:true, }, 'configuration': v:true, }, 'textDocument': { 'hover': { 'contentFormat': ['plaintext'], }, 'completion': { 'completionItem': { 'snippetSupport': go#config#GoplsUsePlaceholders() ? v:true : v:false, }, }, 'codeAction': { 'codeActionLiteralSupport': { 'codeActionKind': { 'valueSet': ['source.organizeImports', 'refactor.rewrite'], }, }, }, } }, 'workspaceFolders': [s:workspaceFolder(0, a:wd)], } } | |
FUNCTION <SNR>180_CloseWindowIfNeeded() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/list.vim:215 | |
Called 1 time | |
Total time: 0.000088 | |
Self time: 0.000042 | |
count total (s) self (s) | |
1 0.000086 0.000040 if ale#Var(a:buffer, 'keep_list_window_open') || !s:ShouldOpen(a:buffer) | |
1 0.000001 return | |
endif | |
let l:did_close_any_list = 0 | |
try | |
" Only close windows if the quickfix list or loclist is completely empty, | |
" including errors set through other means. | |
if g:ale_set_quickfix | |
if empty(getqflist()) | |
cclose | |
let l:did_close_any_list = 1 | |
endif | |
else | |
let l:win_ids = s:WinFindBuf(a:buffer) | |
for l:win_id in l:win_ids | |
if g:ale_set_loclist && empty(getloclist(l:win_id)) | |
lclose | |
let l:did_close_any_list = 1 | |
endif | |
endfor | |
endif | |
" Ignore 'Cannot close last window' errors. | |
catch /E444/ | |
endtry | |
if l:did_close_any_list | |
call s:RestoreViewIfNeeded(a:buffer) | |
endif | |
FUNCTION <SNR>180_ShouldOpen() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/list.vim:40 | |
Called 4 times | |
Total time: 0.000061 | |
Self time: 0.000034 | |
count total (s) self (s) | |
4 0.000044 0.000016 let l:val = ale#Var(a:buffer, 'open_list') | |
4 0.000008 let l:saved = getbufvar(a:buffer, 'ale_save_event_fired', 0) | |
4 0.000006 return l:val is 1 || (l:val is# 'on_save' && l:saved) | |
FUNCTION ale#linter#Define() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/linter.vim:251 | |
Called 28 times | |
Total time: 0.003219 | |
Self time: 0.000515 | |
count total (s) self (s) | |
" This command will throw from the sandbox. | |
28 0.000062 let &l:equalprg=&l:equalprg | |
28 0.002846 0.000142 let l:new_linter = ale#linter#PreProcess(a:filetype, a:linter) | |
28 0.000028 if !has_key(s:linters, a:filetype) | |
1 0.000001 let s:linters[a:filetype] = [] | |
28 0.000004 endif | |
" Remove previously defined linters with the same name. | |
28 0.000188 call filter(s:linters[a:filetype], 'v:val.name isnot# a:linter.name') | |
28 0.000037 call add(s:linters[a:filetype], l:new_linter) | |
FUNCTION go#lsp#AddWorkspaceDirectory() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:1174 | |
Called 1 time | |
Total time: 0.031196 | |
Self time: 0.000639 | |
count total (s) self (s) | |
1 0.000001 if a:0 == 0 | |
return | |
1 0.000000 endif | |
1 0.000023 0.000006 call go#lsp#CleanWorkspaces() | |
1 0.000000 let l:workspaces = [] | |
2 0.000001 for l:dir in a:000 | |
1 0.000008 let l:dir = fnamemodify(l:dir, ':p') | |
1 0.000002 if len(l:dir) > 1 && l:dir[-1:] == '/' | |
1 0.000001 let l:dir = l:dir[:-2] | |
1 0.000000 endif | |
1 0.000003 if !isdirectory(l:dir) | |
continue | |
1 0.000000 endif | |
1 0.000004 let l:workspaces = add(l:workspaces, l:dir) | |
2 0.000001 endfor | |
1 0.000006 0.000002 let l:lsp = s:lspfactory.get() | |
1 0.000110 0.000005 let l:state = s:newHandlerState('') | |
1 0.000027 0.000011 let l:lsp.workspaceDirectories = s:dedup(extend(l:lsp.workspaceDirectories, l:workspaces)) | |
1 0.002210 0.000573 let l:msg = go#lsp#message#ChangeWorkspaceFolders(l:workspaces, []) | |
1 0.028788 0.000011 call l:lsp.sendMessage(l:msg, l:state) | |
1 0.000000 return 0 | |
FUNCTION <SNR>118_InitColor() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/indentLine/after/plugin/indentLine.vim:35 | |
Called 2 times | |
Total time: 0.000116 | |
Self time: 0.000116 | |
count total (s) self (s) | |
2 0.000003 if !g:indentLine_setColors | |
return | |
2 0.000000 endif | |
2 0.000002 let default_term_bg = "NONE" | |
2 0.000001 let default_gui_bg = "NONE" | |
2 0.000002 if &background ==# "light" | |
let default_term_fg = 249 | |
let default_gui_fg = "Grey70" | |
2 0.000001 else | |
2 0.000001 let default_term_fg = 239 | |
2 0.000001 let default_gui_fg = "Grey30" | |
2 0.000000 endif | |
2 0.000002 if g:indentLine_defaultGroup != "" | |
let default_id = synIDtrans(hlID(g:indentLine_defaultGroup)) | |
let default_term_fg = synIDattr(default_id, "fg", "cterm") == "" ? default_term_fg : synIDattr(default_id, "fg", "cterm") | |
let default_term_bg = synIDattr(default_id, "bg", "cterm") == "" ? default_term_bg : synIDattr(default_id, "bg", "cterm") | |
let default_gui_fg = synIDattr(default_id, "fg", "gui") == "" ? default_gui_fg : synIDattr(default_id, "fg", "gui") | |
let default_gui_bg = synIDattr(default_id, "bg", "gui") == "" ? default_gui_bg : synIDattr(default_id, "bg", "gui") | |
2 0.000000 endif | |
2 0.000003 if !exists("g:indentLine_color_term") | |
2 0.000002 let term_color = default_term_fg | |
else | |
let term_color = g:indentLine_color_term | |
2 0.000000 endif | |
2 0.000002 if !exists("g:indentLine_bgcolor_term") | |
2 0.000001 let term_bgcolor = default_term_bg | |
else | |
let term_bgcolor = g:indentLine_bgcolor_term | |
2 0.000000 endif | |
2 0.000002 if !exists("g:indentLine_color_gui") | |
2 0.000001 let gui_color = default_gui_fg | |
else | |
let gui_color = g:indentLine_color_gui | |
2 0.000000 endif | |
2 0.000002 if !exists("g:indentLine_bgcolor_gui") | |
2 0.000001 let gui_bgcolor = default_gui_bg | |
else | |
let gui_bgcolor = g:indentLine_bgcolor_gui | |
2 0.000000 endif | |
2 0.000026 execute "highlight Conceal cterm=NONE ctermfg=" . term_color . " ctermbg=" . term_bgcolor | |
2 0.000012 execute "highlight Conceal gui=NONE guifg=" . gui_color . " guibg=" . gui_bgcolor | |
2 0.000001 if &term ==# "linux" | |
if &background ==# "light" | |
let tty_color = exists("g:indentLine_color_tty_light") ? g:indentLine_color_tty_light : 4 | |
else | |
let tty_color = exists("g:indentLine_color_tty_dark") ? g:indentLine_color_tty_dark : 2 | |
endif | |
execute "highlight Conceal cterm=bold ctermfg=" . tty_color . " ctermbg=NONE" | |
2 0.000000 endif | |
FUNCTION 12() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp.vim:133 | |
Called 90 times | |
Total time: 0.014810 | |
Self time: 0.002144 | |
count total (s) self (s) | |
90 0.000140 let self.buf .= a:data | |
90 0.005899 0.000527 let [self.buf, l:messages] = self.readMessage(self.buf) | |
122 0.000126 for l:message in l:messages | |
32 0.000072 if has_key(l:message, 'method') | |
31 0.000031 if has_key(l:message, 'id') | |
3 0.001852 0.000013 call self.handleRequest(l:message) | |
28 0.000011 else | |
28 0.000441 0.000157 call self.handleNotification(l:message) | |
31 0.000010 endif | |
1 0.000001 elseif has_key(l:message, 'result') || has_key(l:message, 'error') | |
1 0.005174 0.000003 call self.handleResponse(l:message) | |
32 0.000009 endif | |
122 0.000107 endfor | |
FUNCTION <SNR>100_clear_group_from_matches() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:611 | |
Called 1 time | |
Total time: 0.000076 | |
Self time: 0.000076 | |
count total (s) self (s) | |
1 0.000001 let l:cleared = 0 | |
1 0.000025 let m = getmatches() | |
21 0.000009 for item in m | |
20 0.000012 if item['group'] == a:group | |
call matchdelete(item['id']) | |
let l:cleared = 1 | |
20 0.000004 endif | |
21 0.000004 endfor | |
1 0.000001 return l:cleared | |
FUNCTION ale_linters#go#gopls#FindProjectRoot() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gopls.vim:16 | |
Called 1 time | |
Total time: 0.001754 | |
Self time: 0.000725 | |
count total (s) self (s) | |
1 0.000012 0.000005 let l:go_modules_off = ale#Var(a:buffer, 'go_go111module') is# 'off' | |
1 0.001734 0.000713 let l:project_root = l:go_modules_off ? '' : ale#path#FindNearestFile(a:buffer, 'go.mod') | |
1 0.000001 let l:mods = ':h' | |
1 0.000001 if empty(l:project_root) | |
let l:project_root = ale#path#FindNearestDirectory(a:buffer, '.git') | |
let l:mods = ':h:h' | |
1 0.000000 endif | |
1 0.000002 return !empty(l:project_root) ? fnamemodify(l:project_root, l:mods) : '' | |
FUNCTION <SNR>127_strip_ranges() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/loupe/autoload/loupe/private.vim:67 | |
Called 1 time | |
Total time: 0.000221 | |
Self time: 0.000221 | |
count total (s) self (s) | |
1 0.000004 let l:cmdline=a:cmdline | |
" All the range tokens may be followed (several times) by '+' or '-' and an | |
" optional number. | |
1 0.000003 let l:modifier='\([+-]\d*\)*' | |
" Range tokens as specified in `:h cmdline-ranges`. | |
1 0.000047 let l:cmdline=substitute(l:cmdline, '^\d\+' . l:modifier, '', '') " line number | |
1 0.000016 let l:cmdline=substitute(l:cmdline, '^\.' . l:modifier, '', '') " current line | |
1 0.000011 let l:cmdline=substitute(l:cmdline, '^$' . l:modifier, '', '') " last line in file | |
1 0.000011 let l:cmdline=substitute(l:cmdline, '^%' . l:modifier, '', '') " entire file | |
1 0.000016 let l:cmdline=substitute(l:cmdline, "^'[a-z]\\c" . l:modifier, '', '') " mark t (or T) | |
1 0.000012 let l:cmdline=substitute(l:cmdline, "^'[<>]" . l:modifier, '', '') " visual selection marks | |
1 0.000013 let l:cmdline=substitute(l:cmdline, '^/[^/]\+/' . l:modifier, '', '') " /{pattern}/ | |
1 0.000011 let l:cmdline=substitute(l:cmdline, '^?[^?]\+?' . l:modifier, '', '') " ?{pattern}? | |
1 0.000012 let l:cmdline=substitute(l:cmdline, '^\\/' . l:modifier, '', '') " \/ (next match of previous pattern) | |
1 0.000010 let l:cmdline=substitute(l:cmdline, '^\\?' . l:modifier, '', '') " \? (last match of previous pattern) | |
1 0.000010 let l:cmdline=substitute(l:cmdline, '^\\&' . l:modifier, '', '') " \& (last match of previous substitution) | |
" Separators (see: `:h :,` and `:h :;`). | |
1 0.000009 let l:cmdline=substitute(l:cmdline, '^,', '', '') " , (separator) | |
1 0.000008 let l:cmdline=substitute(l:cmdline, '^;', '', '') " ; (separator) | |
1 0.000004 return l:cmdline | |
FUNCTION ale#sign#SetSigns() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:442 | |
Called 3 times | |
Total time: 0.005932 | |
Self time: 0.000352 | |
count total (s) self (s) | |
3 0.000009 if !bufexists(str2nr(a:buffer)) | |
" Stop immediately when attempting to set signs for a buffer which | |
" does not exist. | |
return | |
3 0.000001 endif | |
" Find the current markers | |
3 0.000472 0.000042 let [l:is_dummy_sign_set, l:current_sign_list] = ale#sign#FindCurrentSigns(a:buffer) | |
" Update the line numbers for items from before which may have moved. | |
3 0.000399 0.000095 call s:UpdateLineNumbers(a:buffer, l:current_sign_list, a:loclist) | |
" Group items after updating the line numbers. | |
3 0.000404 0.000089 let l:grouped_items = s:GroupLoclistItems(a:buffer, a:loclist) | |
" Build a map of current and new signs, with the lines as the keys. | |
3 0.003632 0.000017 let l:sign_map = s:BuildSignMap( a:buffer, l:current_sign_list, l:grouped_items,) | |
3 0.000934 0.000017 let l:command_list = ale#sign#GetSignCommands( a:buffer, l:is_dummy_sign_set, l:sign_map,) | |
" Change the sign column color if the option is on. | |
3 0.000003 if g:ale_change_sign_column_color && !empty(a:loclist) | |
highlight clear SignColumn | |
highlight link SignColumn ALESignColumnWithErrors | |
3 0.000001 endif | |
27 0.000010 for l:command in l:command_list | |
24 0.000031 silent! execute l:command | |
27 0.000005 endfor | |
" Reset the sign column color when there are no more errors. | |
3 0.000003 if g:ale_change_sign_column_color && empty(a:loclist) | |
highlight clear SignColumn | |
highlight link SignColumn ALESignColumnWithoutErrors | |
3 0.000001 endif | |
FUNCTION <SNR>165_RunIfExecutable() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:527 | |
Called 3 times | |
Total time: 0.012452 | |
Self time: 0.000174 | |
count total (s) self (s) | |
3 0.000020 0.000013 if ale#command#IsDeferred(a:executable) | |
let a:executable.result_callback = { executable -> s:RunIfExecutable( a:buffer, a:linter, a:lint_file, executable )} | |
return 1 | |
3 0.000002 endif | |
3 0.001036 0.000013 if ale#engine#IsExecutable(a:buffer, a:executable) | |
" Use different job types for file or linter jobs. | |
3 0.000003 let l:job_type = a:lint_file ? 'file_linter' : 'linter' | |
3 0.000015 call setbufvar(a:buffer, 'ale_job_type', l:job_type) | |
" Get the cwd for the linter and set it before we call GetCommand. | |
" This will ensure that ale#command#Run uses it by default. | |
3 0.000023 0.000010 let l:cwd = ale#linter#GetCwd(a:buffer, a:linter) | |
3 0.000002 if l:cwd isnot v:null | |
1 0.000012 0.000003 call ale#command#SetCwd(a:buffer, l:cwd) | |
3 0.000001 endif | |
3 0.000991 0.000011 let l:command = ale#linter#GetCommand(a:buffer, a:linter) | |
3 0.000002 if l:cwd isnot v:null | |
1 0.000005 0.000003 call ale#command#ResetCwd(a:buffer) | |
3 0.000001 endif | |
3 0.000016 let l:options = { 'cwd': l:cwd, 'executable': a:executable, 'buffer': a:buffer, 'linter': a:linter, 'output_stream': get(a:linter, 'output_stream', 'stdout'), 'read_buffer': a:linter.read_buffer, 'lint_file': a:lint_file,} | |
3 0.010296 0.000052 return s:RunJob(l:command, l:options) | |
endif | |
return 0 | |
FUNCTION ale#lsp#OnInit() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp.vim:669 | |
Called 1 time | |
Total time: 0.000007 | |
Self time: 0.000007 | |
count total (s) self (s) | |
1 0.000002 let l:conn = get(s:connections, a:conn_id, {}) | |
1 0.000001 if empty(l:conn) | |
return | |
1 0.000000 endif | |
1 0.000000 if l:conn.initialized | |
call a:Callback() | |
1 0.000000 else | |
1 0.000001 call add(l:conn.init_queue, a:Callback) | |
1 0.000000 endif | |
FUNCTION ale#engine#InitBufferInfo() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:82 | |
Called 1 time | |
Total time: 0.000006 | |
Self time: 0.000006 | |
count total (s) self (s) | |
1 0.000001 if !has_key(g:ale_buffer_info, a:buffer) | |
" active_linter_list will hold the list of active linter names | |
" loclist holds the loclist items after all jobs have completed. | |
1 0.000003 let g:ale_buffer_info[a:buffer] = { 'active_linter_list': [], 'active_other_sources_list': [], 'loclist': [],} | |
1 0.000001 return 1 | |
endif | |
return 0 | |
FUNCTION ale_linters#go#govet#GetCommand() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/govet.vim:10 | |
Called 1 time | |
Total time: 0.000030 | |
Self time: 0.000010 | |
count total (s) self (s) | |
1 0.000008 0.000003 let l:options = ale#Var(a:buffer, 'go_govet_options') | |
1 0.000022 0.000007 return ale#go#EnvString(a:buffer) . ale#Var(a:buffer, 'go_go_executable') . ' vet ' . (!empty(l:options) ? ' ' . l:options : '') . ' .' | |
FUNCTION <SNR>170_CheckWithLSP() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp_linter.vim:438 | |
Called 1 time | |
Total time: 0.000154 | |
Self time: 0.000057 | |
count total (s) self (s) | |
1 0.000002 let l:buffer = a:details.buffer | |
1 0.000003 let l:info = get(g:ale_buffer_info, l:buffer) | |
1 0.000001 if empty(l:info) | |
return | |
1 0.000000 endif | |
1 0.000001 let l:id = a:details.connection_id | |
" Register a callback now for handling errors now. | |
1 0.000002 let l:Callback = function('ale#lsp_linter#HandleLSPResponse') | |
1 0.000107 0.000025 call ale#lsp#RegisterCallback(l:id, l:Callback) | |
" Remember the linter this connection is for. | |
1 0.000002 let s:lsp_linter_map[l:id] = a:linter.name | |
1 0.000001 if a:linter.lsp is# 'tsserver' | |
let l:message = ale#lsp#tsserver_message#Geterr(l:buffer) | |
let l:notified = ale#lsp#Send(l:id, l:message) != 0 | |
if l:notified | |
call ale#engine#MarkLinterActive(l:info, a:linter) | |
endif | |
1 0.000000 else | |
1 0.000020 0.000005 let l:notified = ale#lsp#NotifyForChanges(l:id, l:buffer) | |
1 0.000000 endif | |
" If this was a file save event, also notify the server of that. | |
1 0.000003 if a:linter.lsp isnot# 'tsserver'&& getbufvar(l:buffer, 'ale_save_event_fired', 0)&& ale#lsp#HasCapability(l:buffer, 'did_save') | |
let l:include_text = ale#lsp#HasCapability(l:buffer, 'includeText') | |
let l:save_message = ale#lsp#message#DidSave(l:buffer, l:include_text) | |
let l:notified = ale#lsp#Send(l:id, l:save_message) != 0 | |
1 0.000000 endif | |
FUNCTION go#lsp#message#DidChange() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp/message.vim:173 | |
Called 1 time | |
Total time: 0.000062 | |
Self time: 0.000012 | |
count total (s) self (s) | |
1 0.000061 0.000011 return { 'notification': 1, 'method': 'textDocument/didChange', 'params': { 'textDocument': { 'uri': go#path#ToURI(a:file), 'version': a:version, }, 'contentChanges': [ { 'text': a:content, } ] } } | |
FUNCTION <SNR>165_RunLinter() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:579 | |
Called 4 times | |
Total time: 0.021993 | |
Self time: 0.000899 | |
count total (s) self (s) | |
4 0.000007 if !empty(a:linter.lsp) | |
1 0.009357 0.000779 return ale#lsp_linter#CheckWithLSP(a:buffer, a:linter) | |
3 0.000001 else | |
3 0.000124 0.000060 let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) | |
3 0.012497 0.000045 return s:RunIfExecutable(a:buffer, a:linter, a:lint_file, l:executable) | |
endif | |
return 0 | |
FUNCTION <SNR>178_HandleUnixFormat() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/handlers/unix.vim:4 | |
Called 2 times | |
Total time: 0.001622 | |
Self time: 0.000300 | |
count total (s) self (s) | |
2 0.000003 let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):?(\d+)?:? ?(.+)$' | |
2 0.000001 let l:output = [] | |
30 0.001356 0.000034 for l:match in ale#util#GetMatches(a:lines, l:pattern) | |
28 0.000242 call add(l:output, { 'lnum': l:match[1] + 0, 'col': l:match[2] + 0, 'text': l:match[3], 'type': a:type,}) | |
30 0.000007 endfor | |
2 0.000001 return l:output | |
FUNCTION go#config#HighlightFunctionCalls() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/config.vim:449 | |
Called 1 time | |
Total time: 0.000002 | |
Self time: 0.000002 | |
count total (s) self (s) | |
1 0.000001 return get(g:, 'go_highlight_function_calls', 0) | |
FUNCTION go#util#ClearHighlights() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:594 | |
Called 1 time | |
Total time: 0.000100 | |
Self time: 0.000024 | |
count total (s) self (s) | |
1 0.000002 if has('textprop') | |
" the property type may not exist when syntax highlighting is not enabled. | |
if empty(prop_type_get(a:group)) | |
return | |
endif | |
if !has('patch-8.1.1035') | |
return prop_remove({'type': a:group, 'all': 1}, 1, line('$')) | |
endif | |
return prop_remove({'type': a:group, 'all': 1}) | |
1 0.000000 endif | |
1 0.000002 if exists("*matchaddpos") | |
1 0.000089 0.000013 return s:clear_group_from_matches(a:group) | |
endif | |
FUNCTION go#util#Exec() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/util.vim:217 | |
Called 3 times | |
Total time: 0.297171 | |
Self time: 0.000786 | |
count total (s) self (s) | |
3 0.000004 if len(a:cmd) == 0 | |
call go#util#EchoError("go#util#Exec() called with empty a:cmd") | |
return ['', 1] | |
3 0.000001 endif | |
3 0.000004 let l:bin = a:cmd[0] | |
" Lookup the full path, respecting settings such as 'go_bin_path'. On errors, | |
" CheckBinPath will show a warning for us. | |
3 0.023522 0.000695 let l:bin = go#path#CheckBinPath(l:bin) | |
3 0.000005 if empty(l:bin) | |
return ['', 1] | |
3 0.000001 endif | |
" Finally execute the command using the full, resolved path. Do not pass the | |
" unmodified command as the correct program might not exist in $PATH. | |
3 0.273616 0.000057 return call('s:exec', [[l:bin] + a:cmd[1:]] + a:000) | |
FUNCTION ale#FileTooLarge() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale.vim:24 | |
Called 6 times | |
Total time: 0.000033 | |
Self time: 0.000033 | |
count total (s) self (s) | |
6 0.000017 let l:max = getbufvar(a:buffer, 'ale_maximum_file_size', get(g:, 'ale_maximum_file_size', 0)) | |
6 0.000013 return l:max > 0 ? (line2byte(line('$') + 1) > l:max) : 0 | |
FUNCTION ale#engine#MarkLinterInactive() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:43 | |
Called 3 times | |
Total time: 0.000024 | |
Self time: 0.000024 | |
count total (s) self (s) | |
3 0.000023 call filter(a:info.active_linter_list, 'v:val.name isnot# a:linter_name') | |
FUNCTION ale_linters#go#golint#GetCommand() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/golint.vim:7 | |
Called 1 time | |
Total time: 0.000079 | |
Self time: 0.000037 | |
count total (s) self (s) | |
1 0.000008 0.000003 let l:options = ale#Var(a:buffer, 'go_golint_options') | |
1 0.000068 0.000031 return ale#go#EnvString(a:buffer) . '%e' . (!empty(l:options) ? ' ' . l:options : '') . ' %t' | |
FUNCTION ale#engine#IsCheckingBuffer() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:101 | |
Called 7 times | |
Total time: 0.000040 | |
Self time: 0.000040 | |
count total (s) self (s) | |
7 0.000014 let l:info = get(g:ale_buffer_info, a:buffer, {}) | |
7 0.000022 return !empty(get(l:info, 'active_linter_list', [])) || !empty(get(l:info, 'active_other_sources_list', [])) | |
FUNCTION ale#job#ValidateArguments() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/job.vim:144 | |
Called 4 times | |
Total time: 0.000015 | |
Self time: 0.000015 | |
count total (s) self (s) | |
4 0.000008 if a:options.mode isnot# 'nl' && a:options.mode isnot# 'raw' | |
throw 'Invalid mode: ' . a:options.mode | |
4 0.000001 endif | |
FUNCTION ale#engine#MarkLinterActive() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:28 | |
Called 3 times | |
Total time: 0.000043 | |
Self time: 0.000043 | |
count total (s) self (s) | |
3 0.000002 let l:found = 0 | |
6 0.000018 for l:other_linter in a:info.active_linter_list | |
3 0.000004 if l:other_linter.name is# a:linter.name | |
let l:found = 1 | |
break | |
3 0.000001 endif | |
6 0.000002 endfor | |
3 0.000002 if !l:found | |
3 0.000003 call add(a:info.active_linter_list, a:linter) | |
3 0.000001 endif | |
FUNCTION ale#command#ResetCwd() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/command.vim:39 | |
Called 4 times | |
Total time: 0.000010 | |
Self time: 0.000010 | |
count total (s) self (s) | |
4 0.000004 if has_key(s:buffer_data, a:buffer) | |
4 0.000004 let s:buffer_data[a:buffer].cwd = v:null | |
4 0.000001 endif | |
FUNCTION ale#sign#ParseSignsWithGetPlaced() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:205 | |
Called 3 times | |
Total time: 0.000209 | |
Self time: 0.000209 | |
count total (s) self (s) | |
3 0.000041 let l:signs = sign_getplaced(a:buffer, { 'group': s:supports_sign_groups ? 'ale' : '' })[0].signs | |
3 0.000003 let l:result = [] | |
3 0.000003 let l:is_dummy_sign_set = 0 | |
23 0.000009 for l:sign in l:signs | |
20 0.000012 if l:sign['name'] is# 'ALEDummySign' | |
let l:is_dummy_sign_set = 1 | |
20 0.000003 else | |
20 0.000038 call add(l:result, [ str2nr(l:sign['lnum']), str2nr(l:sign['id']), l:sign['name'],]) | |
20 0.000003 endif | |
23 0.000006 endfor | |
3 0.000008 return [l:is_dummy_sign_set, l:result] | |
FUNCTION ale#command#FormatCommand() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/command.vim:192 | |
Called 4 times | |
Total time: 0.002308 | |
Self time: 0.000488 | |
count total (s) self (s) | |
4 0.000007 let l:temporary_file = '' | |
4 0.000003 let l:command = a:command | |
4 0.000003 if !empty(a:cwd) | |
1 0.000022 0.000004 let l:command = ale#command#CdString(a:cwd) . l:command | |
4 0.000001 endif | |
" First replace all uses of %%, used for literal percent characters, | |
" with an ugly string. | |
4 0.000014 let l:command = substitute(l:command, '%%', '<<PERCENTS>>', 'g') | |
" Replace %e with the escaped executable, if available. | |
4 0.000008 if !empty(a:executable) && l:command =~# '%e' | |
3 0.000049 0.000020 let l:command = substitute(l:command, '%e', '\=ale#Escape(a:executable)', 'g') | |
4 0.000001 endif | |
" Replace all %s occurrences in the string with the name of the current | |
" file. | |
4 0.000004 if l:command =~# '%s' | |
1 0.000242 let l:filename = fnamemodify(bufname(a:buffer), ':p') | |
1 0.000048 0.000024 let l:command = substitute( l:command, s:path_format_regex, '\=s:FormatFilename(l:filename, a:mappings, submatch(1))', 'g') | |
4 0.000001 endif | |
4 0.000006 if a:input isnot v:false && l:command =~# '%t' | |
" Create a temporary filename, <temp_dir>/<original_basename> | |
" The file itself will not be created by this function. | |
2 0.000059 0.000008 let l:temporary_file = s:TemporaryFilename(a:buffer) | |
2 0.000050 0.000023 let l:command = substitute( l:command, '\v\%t(%(:h|:t|:r|:e)*)', '\=s:FormatFilename(l:temporary_file, a:mappings, submatch(1))', 'g') | |
4 0.000001 endif | |
" Finish formatting so %% becomes %. | |
4 0.000011 let l:command = substitute(l:command, '<<PERCENTS>>', '%', 'g') | |
4 0.000004 if a:pipe_file_if_needed && empty(l:temporary_file) | |
" If we are to send the Vim buffer to a command, we'll do it | |
" in the shell. We'll write out the file to a temporary file, | |
" and then read it back in, in the shell. | |
let l:temporary_file = s:TemporaryFilename(a:buffer) | |
let l:command = l:command . ' < ' . ale#Escape(l:temporary_file) | |
4 0.000001 endif | |
4 0.001713 0.000043 let l:file_created = ale#command#CreateTempFile( a:buffer, l:temporary_file, a:input,) | |
4 0.000005 return [l:temporary_file, l:command, l:file_created] | |
FUNCTION <SNR>118_Disable() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/indentLine/after/plugin/indentLine.vim:309 | |
Called 1 time | |
Total time: 0.000023 | |
Self time: 0.000005 | |
count total (s) self (s) | |
1 0.000021 0.000003 if s:Filter() == 0 | |
call s:IndentLinesDisable() | |
call s:LeadingSpaceDisable() | |
1 0.000000 endif | |
FUNCTION ale#command#Run() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/command.vim:333 | |
Called 3 times | |
Total time: 0.009483 | |
Self time: 0.001029 | |
count total (s) self (s) | |
3 0.000004 let l:options = get(a:000, 0, {}) | |
3 0.000003 if len(a:000) > 1 | |
throw 'Too many arguments!' | |
3 0.000000 endif | |
3 0.000004 let l:output_stream = get(l:options, 'output_stream', 'stdout') | |
3 0.000002 let l:line_list = [] | |
3 0.000003 let l:cwd = get(l:options, 'cwd', v:null) | |
3 0.000002 if l:cwd is v:null | |
" Default the working directory to whatever it was for the last | |
" command run in the chain. | |
2 0.000004 let l:cwd = get(get(s:buffer_data, a:buffer, {}), 'cwd', v:null) | |
3 0.000001 endif | |
3 0.002280 0.000029 let [l:temporary_file, l:command, l:file_created] = ale#command#FormatCommand( a:buffer, get(l:options, 'executable', ''), a:command, get(l:options, 'read_buffer', 0), get(l:options, 'input', v:null), l:cwd, get(l:options, 'filename_mappings', []),) | |
3 0.000954 0.000566 let l:command = ale#job#PrepareCommand(a:buffer, l:command) | |
3 0.000026 let l:job_options = { 'exit_cb': {job_id, exit_code -> s:ExitCallback( a:buffer, l:line_list, a:Callback, { 'job_id': job_id, 'exit_code': exit_code, 'temporary_file': l:temporary_file, 'log_output': get(l:options, 'log_output', 1), 'result': l:result, } )}, 'mode': 'nl',} | |
3 0.000002 if l:output_stream is# 'stdout' | |
let l:job_options.out_cb = function('s:GatherOutput', [l:line_list]) | |
3 0.000002 elseif l:output_stream is# 'stderr' | |
2 0.000006 let l:job_options.err_cb = function('s:GatherOutput', [l:line_list]) | |
1 0.000000 elseif l:output_stream is# 'both' | |
1 0.000003 let l:job_options.out_cb = function('s:GatherOutput', [l:line_list]) | |
1 0.000002 let l:job_options.err_cb = function('s:GatherOutput', [l:line_list]) | |
3 0.000001 endif | |
3 0.000002 let l:status = 'failed' | |
3 0.000003 if get(g:, 'ale_run_synchronously') == 1 | |
if get(g:, 'ale_emulate_job_failure') == 1 | |
let l:job_id = 0 | |
else | |
" Generate a fake job ID for tests. | |
let s:fake_job_id = get(s:, 'fake_job_id', 0) + 1 | |
let l:job_id = s:fake_job_id | |
endif | |
3 0.000005 elseif has('win32') | |
let l:job_id = ale#job#StartWithCmd(l:command, l:job_options) | |
3 0.000001 else | |
3 0.005813 0.000082 let l:job_id = ale#job#Start(l:command, l:job_options) | |
3 0.000001 endif | |
3 0.000001 if l:job_id | |
3 0.000005 let l:status = 'started' | |
3 0.000008 let l:job_type = getbufvar(a:buffer, 'ale_job_type', 'all') | |
3 0.000079 0.000052 call ale#command#InitData(a:buffer) | |
3 0.000028 let s:buffer_data[a:buffer].jobs[l:job_id] = l:job_type | |
3 0.000001 endif | |
3 0.000002 if g:ale_history_enabled | |
3 0.000071 0.000012 call ale#history#Add(a:buffer, l:status, l:job_id, l:command) | |
3 0.000001 endif | |
3 0.000001 if !l:job_id | |
return 0 | |
3 0.000000 endif | |
" We'll return this Dictionary. A `result_callback` can be assigned to it | |
" later for capturing the result of a:Callback. | |
" | |
" The `_deferred_job_id` is used for both checking the type of object, and | |
" for checking the job ID and status. | |
" | |
" The cwd is kept and used as the default value for the next command in | |
" the chain. | |
" | |
" The original command here is used in tests. | |
3 0.000017 let l:result = { '_deferred_job_id': l:job_id, 'executable': get(l:options, 'executable', ''), 'cwd': l:cwd, 'command': a:command,} | |
3 0.000004 if get(g:, 'ale_run_synchronously') == 1 && l:job_id | |
if !exists('g:ale_run_synchronously_callbacks') | |
let g:ale_run_synchronously_callbacks = [] | |
endif | |
if get(g:, 'ale_run_synchronously_emulate_commands', 0) | |
call add( g:ale_run_synchronously_callbacks, {exit_code, output -> [ extend(l:line_list, output), l:job_options.exit_cb(l:job_id, exit_code), ]}) | |
else | |
" Run a command synchronously if this test option is set. | |
call extend(l:line_list, systemlist( type(l:command) is v:t_list ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2]) : l:command)) | |
" Don't capture output when the callbacks aren't set. | |
if !has_key(l:job_options, 'out_cb')&& !has_key(l:job_options, 'err_cb') | |
let l:line_list = [] | |
endif | |
call add( g:ale_run_synchronously_callbacks, {-> l:job_options.exit_cb(l:job_id, v:shell_error)}) | |
endif | |
3 0.000000 endif | |
3 0.000002 return l:result | |
FUNCTION go#auto#update_autocmd() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/auto.vim:86 | |
Called 2 times | |
Total time: 0.000052 | |
Self time: 0.000045 | |
count total (s) self (s) | |
2 0.000004 let has_timer = get(b:, 'has_timer') | |
2 0.000043 0.000036 let should_enable = go#config#AutoTypeInfo() || go#config#AutoSameids() | |
2 0.000003 if (!has_timer && !should_enable) || (has_timer && should_enable) | |
2 0.000001 return | |
endif | |
if has_timer | |
augroup vim-go-buffer-auto | |
autocmd! * <buffer> | |
augroup END | |
let b:has_timer = 0 | |
call s:timer_stop() | |
return | |
endif | |
augroup vim-go-buffer-auto | |
autocmd! * <buffer> | |
autocmd CursorMoved <buffer> call s:timer_restart() | |
autocmd BufLeave <buffer> call s:timer_stop() | |
augroup END | |
let b:has_timer = 1 | |
call s:timer_start() | |
FUNCTION ale#events#FileTypeEvent() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/events.vim:69 | |
Called 1 time | |
Total time: 0.000011 | |
Self time: 0.000011 | |
count total (s) self (s) | |
" The old filetype will be set to an empty string by the BuFEnter event, | |
" and not linting when the old filetype hasn't been set yet prevents | |
" buffers being checked when you enter them when linting on enter is off. | |
1 0.000003 let l:old_filetype = getbufvar(a:buffer, 'ale_original_filetype', v:null) | |
1 0.000002 if l:old_filetype isnot v:null&& !empty(a:new_filetype)&& a:new_filetype isnot# l:old_filetype | |
" Remember what the new filetype is. | |
call setbufvar(a:buffer, 'ale_original_filetype', a:new_filetype) | |
if g:ale_lint_on_filetype_changed | |
call ale#Queue(300, 'lint_file', a:buffer) | |
endif | |
1 0.000000 endif | |
FUNCTION <SNR>180_WinFindBuf() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/list.vim:86 | |
Called 3 times | |
Total time: 0.000014 | |
Self time: 0.000014 | |
count total (s) self (s) | |
3 0.000013 return exists('*win_findbuf') ? win_findbuf(str2nr(a:buffer)) : [0] | |
FUNCTION ale#command#IsDeferred() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/command.vim:471 | |
Called 16 times | |
Total time: 0.000040 | |
Self time: 0.000040 | |
count total (s) self (s) | |
16 0.000036 return type(a:value) is v:t_dict && has_key(a:value, '_deferred_job_id') | |
FUNCTION <lambda>343() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/ale_linters/go/gopls.vim:29 | |
Called 1 time | |
Total time: 0.000007 | |
Self time: 0.000002 | |
count total (s) self (s) | |
return ale#Var(b, 'go_gopls_init_options') | |
FUNCTION ale#path#IsAbsolute() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/path.vim:117 | |
Called 1 time | |
Total time: 0.000005 | |
Self time: 0.000005 | |
count total (s) self (s) | |
1 0.000002 if has('win32') && a:filename[:0] is# '\' | |
return 1 | |
1 0.000000 endif | |
" Check for /foo and C:\foo, etc. | |
1 0.000001 return a:filename[:0] is# '/' || a:filename[1:2] is# ':\' | |
FUNCTION ale#linter#GetExecutable() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/linter.vim:424 | |
Called 4 times | |
Total time: 0.000142 | |
Self time: 0.000040 | |
count total (s) self (s) | |
4 0.000012 let l:Executable = a:linter.executable | |
4 0.000123 0.000021 return type(l:Executable) is v:t_func ? l:Executable(a:buffer) : l:Executable | |
FUNCTION <SNR>181_matchaddpos() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/highlight.vim:89 | |
Called 56 times | |
Total time: 0.003452 | |
Self time: 0.002579 | |
count total (s) self (s) | |
56 0.000042 if s:has_nvim_highlight | |
112 0.000124 for l:pos in a:pos_list | |
56 0.000137 let l:line = type(l:pos) == v:t_number ? l:pos - 1 : l:pos[0] - 1 | |
56 0.000094 if type(l:pos) == v:t_number || len(l:pos) == 1 | |
let l:col_start = 0 | |
let l:col_end = s:MAX_COL_SIZE | |
56 0.000031 else | |
56 0.000090 let l:col_start = l:pos[1] - 1 | |
56 0.000096 let l:col_end = l:col_start + get(l:pos, 2, 1) | |
56 0.000015 endif | |
56 0.001893 0.001020 call ale#highlight#nvim_buf_add_highlight( bufnr(''), s:ns_id, a:group, l:line, l:col_start, l:col_end,) | |
112 0.000062 endfor | |
else | |
call matchaddpos(a:group, a:pos_list) | |
56 0.000014 endif | |
FUNCTION ale#lsp_window#HandleShowMessage() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp_window.vim:26 | |
Called 2 times | |
Total time: 0.000022 | |
Self time: 0.000022 | |
count total (s) self (s) | |
2 0.000003 let l:message = a:params.message | |
2 0.000002 let l:type = a:params.type | |
" Get the configured severity level threshold and check if the message | |
" should be displayed or not | |
2 0.000007 let l:configured_severity = tolower(get(g:, 'ale_lsp_show_message_severity', 'error')) | |
" If the user has configured with a value we can't find on the conversion | |
" dict, fall back to warning | |
2 0.000005 let l:cfg_severity_threshold = get(s:CFG_TO_LSP_SEVERITY, l:configured_severity, s:LSP_MESSAGE_TYPE_WARNING) | |
2 0.000002 if l:type > l:cfg_severity_threshold | |
2 0.000001 return | |
endif | |
" Severity will depend on the message type | |
if l:type is# s:LSP_MESSAGE_TYPE_ERROR | |
let l:severity = g:ale_echo_msg_error_str | |
elseif l:type is# s:LSP_MESSAGE_TYPE_INFORMATION | |
let l:severity = g:ale_echo_msg_info_str | |
elseif l:type is# s:LSP_MESSAGE_TYPE_LOG | |
let l:severity = g:ale_echo_msg_log_str | |
else | |
" Default to warning just in case | |
let l:severity = g:ale_echo_msg_warning_str | |
endif | |
let l:string = substitute(a:format, '\V%severity%', l:severity, 'g') | |
let l:string = substitute(l:string, '\V%linter%', a:linter_name, 'g') | |
let l:string = substitute(l:string, '\V%s\>', l:message, 'g') | |
call ale#util#ShowMessage(l:string) | |
FUNCTION <SNR>165_StopCurrentJobs() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:449 | |
Called 1 time | |
Total time: 0.000035 | |
Self time: 0.000018 | |
count total (s) self (s) | |
1 0.000002 let l:info = get(g:ale_buffer_info, a:buffer, {}) | |
1 0.000015 0.000005 call ale#command#StopJobs(a:buffer, 'linter') | |
" Update the active linter list, clearing out anything not running. | |
1 0.000001 if a:clear_lint_file_jobs | |
1 0.000010 0.000003 call ale#command#StopJobs(a:buffer, 'file_linter') | |
1 0.000001 let l:info.active_linter_list = [] | |
else | |
let l:lint_file_map = {} | |
" Use a previously computed map of `lint_file` values to find | |
" linters that are used for linting files. | |
for [l:lint_file, l:linter] in a:linter_slots | |
if l:lint_file is 1 | |
let l:lint_file_map[l:linter.name] = 1 | |
endif | |
endfor | |
" Keep jobs for linting files when we're only linting buffers. | |
call filter(l:info.active_linter_list, 'get(l:lint_file_map, v:val.name)') | |
1 0.000000 endif | |
FUNCTION <SNR>146_workspaceFolder() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/lsp/message.vim:402 | |
Called 2 times | |
Total time: 0.001138 | |
Self time: 0.000010 | |
count total (s) self (s) | |
2 0.001138 0.000009 return {'uri': go#path#ToURI(a:val), 'name': a:val} | |
FUNCTION <SNR>60_SynSet() | |
Defined: /opt/homebrew/Cellar/neovim/0.5.1_1/share/nvim/runtime/syntax/synload.vim:33 | |
Called 1 time | |
Total time: 0.005070 | |
Self time: 0.003307 | |
count total (s) self (s) | |
" clear syntax for :set syntax=OFF and any syntax name that doesn't exist | |
1 0.000003 syn clear | |
1 0.000001 if exists("b:current_syntax") | |
unlet b:current_syntax | |
1 0.000000 endif | |
1 0.000001 let s = expand("<amatch>") | |
1 0.000001 if s == "ON" | |
" :set syntax=ON | |
if &filetype == "" | |
echohl ErrorMsg | |
echo "filetype unknown" | |
echohl None | |
endif | |
let s = &filetype | |
1 0.000001 elseif s == "OFF" | |
let s = "" | |
1 0.000000 endif | |
1 0.000000 if s != "" | |
" Load the syntax file(s). When there are several, separated by dots, | |
" load each in sequence. Skip empty entries. | |
2 0.000003 for name in split(s, '\.') | |
1 0.000001 if !empty(name) | |
1 0.003962 0.002199 exe "runtime! syntax/" . name . ".vim syntax/" . name . "/*.vim" | |
1 0.001086 exe "runtime! syntax/" . name . ".lua syntax/" . name . "/*.lua" | |
1 0.000001 endif | |
2 0.000001 endfor | |
1 0.000000 endif | |
FUNCTION ale#util#LocItemCompareWithText() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/util.vim:208 | |
Called 252 times | |
Total time: 0.010661 | |
Self time: 0.005394 | |
count total (s) self (s) | |
252 0.010075 0.004808 let l:cmp_value = ale#util#LocItemCompare(a:left, a:right) | |
252 0.000140 if l:cmp_value | |
201 0.000086 return l:cmp_value | |
51 0.000011 endif | |
51 0.000060 if a:left.text < a:right.text | |
51 0.000021 return -1 | |
endif | |
if a:left.text > a:right.text | |
return 1 | |
endif | |
return 0 | |
FUNCTION AutoPairsInit() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/auto-pairs/plugin/auto-pairs.vim:471 | |
Called 1 time | |
Total time: 0.000730 | |
Self time: 0.000533 | |
count total (s) self (s) | |
1 0.000005 let b:autopairs_loaded = 1 | |
1 0.000001 if !exists('b:autopairs_enabled') | |
1 0.000001 let b:autopairs_enabled = 1 | |
1 0.000000 end | |
1 0.000001 if !exists('b:AutoPairs') | |
1 0.000085 0.000034 let b:AutoPairs = AutoPairsDefaultPairs() | |
1 0.000000 end | |
1 0.000001 if !exists('b:AutoPairsMoveCharacter') | |
1 0.000001 let b:AutoPairsMoveCharacter = g:AutoPairsMoveCharacter | |
1 0.000000 end | |
1 0.000009 let b:autopairs_return_pos = 0 | |
1 0.000001 let b:autopairs_saved_pair = [0, 0] | |
1 0.000001 let b:AutoPairsList = [] | |
" buffer level map pairs keys | |
" n - do not map the first charactor of closed pair to close key | |
" m - close key jumps through multi line | |
" s - close key jumps only in the same line | |
10 0.000009 for [open, close] in items(b:AutoPairs) | |
9 0.000006 let o = open[-1:-1] | |
9 0.000005 let c = close[0] | |
9 0.000009 let opt = {'mapclose': 1, 'multiline':1} | |
9 0.000006 let opt['key'] = c | |
9 0.000004 if o == c | |
6 0.000004 let opt['multiline'] = 0 | |
9 0.000002 end | |
9 0.000040 let m = matchlist(close, '\v(.*)//(.*)$') | |
9 0.000006 if len(m) > 0 | |
if m[2] =~ 'n' | |
let opt['mapclose'] = 0 | |
end | |
if m[2] =~ 'm' | |
let opt['multiline'] = 1 | |
end | |
if m[2] =~ 's' | |
let opt['multiline'] = 0 | |
end | |
let ks = matchlist(m[2], '\vk(.)') | |
if len(ks) > 0 | |
let opt['key'] = ks[1] | |
let c = opt['key'] | |
end | |
let close = m[1] | |
9 0.000002 end | |
9 0.000098 0.000020 call AutoPairsMap(o) | |
9 0.000008 if o != c && c != '' && opt['mapclose'] | |
3 0.000026 0.000006 call AutoPairsMap(c) | |
9 0.000002 end | |
9 0.000011 let b:AutoPairsList += [[open, close, opt]] | |
10 0.000003 endfor | |
" sort pairs by length, longer pair should have higher priority | |
1 0.000177 0.000129 let b:AutoPairsList = sort(b:AutoPairsList, "s:sortByLength") | |
10 0.000004 for item in b:AutoPairsList | |
9 0.000006 let [open, close, opt] = item | |
9 0.000006 if open == "'" && open == close | |
1 0.000001 let item[0] = '\v(^|\W)\zs''' | |
9 0.000001 end | |
10 0.000002 endfor | |
9 0.000010 for key in split(b:AutoPairsMoveCharacter, '\s*') | |
8 0.000013 let escaped_key = substitute(key, "'", "''", 'g') | |
8 0.000035 execute 'inoremap <silent> <buffer> <M-'.key."> <C-R>=AutoPairsMoveCharacter('".escaped_key."')<CR>" | |
9 0.000002 endfor | |
" Still use <buffer> level mapping for <BS> <SPACE> | |
1 0.000001 if g:AutoPairsMapBS | |
" Use <C-R> instead of <expr> for issue #14 sometimes press BS output strange words | |
1 0.000005 execute 'inoremap <buffer> <silent> <BS> <C-R>=AutoPairsDelete()<CR>' | |
1 0.000000 end | |
1 0.000000 if g:AutoPairsMapCh | |
1 0.000003 execute 'inoremap <buffer> <silent> <C-h> <C-R>=AutoPairsDelete()<CR>' | |
1 0.000000 endif | |
1 0.000001 if g:AutoPairsMapSpace | |
" Try to respect abbreviations on a <SPACE> | |
1 0.000001 let do_abbrev = "" | |
1 0.000001 if v:version == 703 && has("patch489") || v:version > 703 | |
1 0.000001 let do_abbrev = "<C-]>" | |
1 0.000000 endif | |
1 0.000004 execute 'inoremap <buffer> <silent> <SPACE> '.do_abbrev.'<C-R>=AutoPairsSpace()<CR>' | |
1 0.000000 end | |
1 0.000001 if g:AutoPairsShortcutFastWrap != '' | |
1 0.000004 execute 'inoremap <buffer> <silent> '.g:AutoPairsShortcutFastWrap.' <C-R>=AutoPairsFastWrap()<CR>' | |
1 0.000000 end | |
1 0.000001 if g:AutoPairsShortcutBackInsert != '' | |
1 0.000004 execute 'inoremap <buffer> <silent> '.g:AutoPairsShortcutBackInsert.' <C-R>=AutoPairsBackInsert()<CR>' | |
1 0.000000 end | |
1 0.000001 if g:AutoPairsShortcutToggle != '' | |
" use <expr> to ensure showing the status when toggle | |
1 0.000004 execute 'inoremap <buffer> <silent> <expr> '.g:AutoPairsShortcutToggle.' AutoPairsToggle()' | |
1 0.000005 execute 'noremap <buffer> <silent> '.g:AutoPairsShortcutToggle.' :call AutoPairsToggle()<CR>' | |
1 0.000000 end | |
1 0.000001 if g:AutoPairsShortcutJump != '' | |
1 0.000004 execute 'inoremap <buffer> <silent> ' . g:AutoPairsShortcutJump. ' <ESC>:call AutoPairsJump()<CR>a' | |
1 0.000004 execute 'noremap <buffer> <silent> ' . g:AutoPairsShortcutJump. ' :call AutoPairsJump()<CR>' | |
1 0.000000 end | |
1 0.000001 if &keymap != '' | |
let l:imsearch = &imsearch | |
let l:iminsert = &iminsert | |
let l:imdisable = &imdisable | |
execute 'setlocal keymap=' . &keymap | |
execute 'setlocal imsearch=' . l:imsearch | |
execute 'setlocal iminsert=' . l:iminsert | |
if l:imdisable | |
execute 'setlocal imdisable' | |
else | |
execute 'setlocal noimdisable' | |
end | |
1 0.000000 end | |
FUNCTION ale#sign#SetUpDefaultColumnWithoutErrorsHighlight() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:52 | |
Called 1 time | |
Total time: 0.000135 | |
Self time: 0.000120 | |
count total (s) self (s) | |
1 0.000010 let l:verbose = &verbose | |
1 0.000027 0.000013 set verbose=0 | |
1 0.000021 let l:output = execute('highlight SignColumn', 'silent') | |
1 0.000004 0.000002 let &verbose = l:verbose | |
1 0.000017 let l:highlight_syntax = join(split(l:output)[2:]) | |
1 0.000004 let l:match = matchlist(l:highlight_syntax, '\vlinks to (.+)$') | |
1 0.000001 if !empty(l:match) | |
execute 'highlight link ALESignColumnWithoutErrors ' . l:match[1] | |
1 0.000002 elseif l:highlight_syntax isnot# 'cleared' | |
1 0.000021 execute 'highlight ALESignColumnWithoutErrors ' . l:highlight_syntax | |
1 0.000000 endif | |
FUNCTION <SNR>179_PriorityCmd() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/sign.vim:154 | |
Called 22 times | |
Total time: 0.000037 | |
Self time: 0.000037 | |
count total (s) self (s) | |
22 0.000010 if s:supports_sign_groups | |
22 0.000021 return ' priority=' . g:ale_sign_priority . ' ' | |
else | |
return '' | |
endif | |
FUNCTION <SNR>118_ResetConcealOption() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/indentLine/after/plugin/indentLine.vim:110 | |
Called 1 time | |
Total time: 0.000006 | |
Self time: 0.000006 | |
count total (s) self (s) | |
1 0.000001 if exists("b:indentLine_ConcealOptionSet") && b:indentLine_ConcealOptionSet | |
if exists("b:indentLine_original_concealcursor") | |
let &l:concealcursor = b:indentLine_original_concealcursor | |
endif | |
if exists("b:indentLine_original_conceallevel") | |
let &l:conceallevel = b:indentLine_original_conceallevel | |
endif | |
let b:indentLine_ConcealOptionSet = 0 | |
1 0.000000 endif | |
FUNCTION <SNR>126_GetAliasedFiletype() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/linter.vim:294 | |
Called 1 time | |
Total time: 0.000018 | |
Self time: 0.000018 | |
count total (s) self (s) | |
1 0.000002 let l:buffer_aliases = get(b:, 'ale_linter_aliases', {}) | |
" b:ale_linter_aliases can be set to a List or String. | |
1 0.000002 if type(l:buffer_aliases) is v:t_list|| type(l:buffer_aliases) is v:t_string | |
return l:buffer_aliases | |
1 0.000000 endif | |
" Check for aliased filetypes first in a buffer variable, | |
" then the global variable, | |
" then in the default mapping, | |
" otherwise use the original filetype. | |
4 0.000003 for l:dict in [ l:buffer_aliases, g:ale_linter_aliases, s:default_ale_linter_aliases,] | |
3 0.000003 if has_key(l:dict, a:original_filetype) | |
return l:dict[a:original_filetype] | |
3 0.000001 endif | |
4 0.000001 endfor | |
1 0.000001 return a:original_filetype | |
FUNCTION ale#Queue() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale.vim:123 | |
Called 1 time | |
Total time: 0.049362 | |
Self time: 0.000042 | |
count total (s) self (s) | |
1 0.000001 if a:0 > 2 | |
throw 'too many arguments!' | |
1 0.000000 endif | |
1 0.000002 let l:buffer = get(a:000, 1, v:null) | |
1 0.000001 if l:buffer is v:null | |
let l:buffer = bufnr('') | |
1 0.000000 endif | |
1 0.000001 if type(l:buffer) isnot v:t_number | |
throw 'buffer_number must be a Number' | |
1 0.000000 endif | |
1 0.000055 0.000003 if ale#ShouldDoNothing(l:buffer) | |
return | |
1 0.000000 endif | |
" Default linting_flag to '' | |
1 0.000001 let l:should_lint_file = get(a:000, 0) is# 'lint_file' | |
1 0.000001 if s:lint_timer != -1 | |
1 0.000001 call timer_stop(s:lint_timer) | |
1 0.000001 let s:lint_timer = -1 | |
1 0.000000 endif | |
1 0.000000 if a:delay > 0 | |
let s:lint_timer = timer_start( a:delay, function('s:Lint', [l:buffer, l:should_lint_file])) | |
1 0.000000 else | |
1 0.049287 0.000019 call s:Lint(l:buffer, l:should_lint_file, 0) | |
1 0.000000 endif | |
FUNCTION <SNR>148_clear() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/vim-go/autoload/go/statusline.vim:100 | |
Called 2 times | |
Total time: 0.000076 | |
Self time: 0.000074 | |
count total (s) self (s) | |
4 0.000006 for [status_dir, status] in items(s:statuses) | |
2 0.000008 let elapsed_time = reltimestr(reltime(status.created_at)) | |
" strip whitespace | |
2 0.000018 let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '') | |
2 0.000003 if str2nr(elapsed_time) > 10 | |
call remove(s:statuses, status_dir) | |
2 0.000001 endif | |
4 0.000002 endfor | |
2 0.000002 if len(s:statuses) == 0 | |
let s:statuses = {} | |
2 0.000001 endif | |
" force to update the statusline, otherwise the user needs to move the | |
" cursor | |
2 0.000010 0.000008 exe 'let &ro = &ro' | |
FUNCTION <SNR>128_project_name() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/dashboard-nvim/autoload/sessions/session.vim:48 | |
Called 1 time | |
Total time: 0.001644 | |
Self time: 0.001644 | |
count total (s) self (s) | |
1 0.000907 let l:cwd = resolve(getcwd()) | |
1 0.000046 let l:cwd = substitute(l:cwd, '^'.$HOME.'/', '', '') | |
1 0.000675 let l:cwd = fnamemodify(l:cwd, ':p:gs?/?_?') | |
1 0.000010 let l:cwd = substitute(l:cwd, '^\.', '', '') | |
1 0.000004 return l:cwd | |
FUNCTION ale#lsp#message#DidOpen() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/lsp/message.vim:54 | |
Called 1 time | |
Total time: 0.000423 | |
Self time: 0.000387 | |
count total (s) self (s) | |
1 0.000039 let l:lines = getbufline(a:buffer, 1, '$') | |
1 0.000384 0.000348 return [1, 'textDocument/didOpen', { 'textDocument': { 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), 'languageId': a:language_id, 'version': ale#lsp#message#GetNextVersionID(), 'text': join(l:lines, "\n") . "\n", },}] | |
FUNCTION <SNR>165_HandleExit() | |
Defined: ~/.local/share/nvim/site/pack/packer/start/ale/autoload/ale/engine.vim:151 | |
Called 3 times | |
Total time: 0.041664 | |
Self time: 0.003776 | |
count total (s) self (s) | |
3 0.000009 let l:buffer_info = get(g:ale_buffer_info, a:buffer) | |
3 0.000004 if empty(l:buffer_info) | |
return | |
3 0.000001 e |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment