mirror of
				https://github.com/amix/vimrc
				synced 2025-10-31 06:33:35 +08:00 
			
		
		
		
	Updated plugins and added vim-markdown
This commit is contained in:
		| @ -1,5 +1,5 @@ | ||||
| function! go#cmd#autowrite() abort | ||||
|   if &autowrite == 1 | ||||
|   if &autowrite == 1 || &autowriteall == 1 | ||||
|     silent! wall | ||||
|   endif | ||||
| endfunction | ||||
| @ -269,7 +269,7 @@ function s:cmd_job(args) abort | ||||
|   " autowrite is not enabled for jobs | ||||
|   call go#cmd#autowrite() | ||||
|  | ||||
|   function! s:error_info_cb(job, exit_status, data) closure abort | ||||
|   function! s:complete(job, exit_status, data) closure abort | ||||
|     let status = { | ||||
|           \ 'desc': 'last status', | ||||
|           \ 'type': a:args.cmd[1], | ||||
| @ -288,12 +288,13 @@ function s:cmd_job(args) abort | ||||
|     call go#statusline#Update(status_dir, status) | ||||
|   endfunction | ||||
|  | ||||
|   let a:args.error_info_cb = funcref('s:error_info_cb') | ||||
|   let a:args.complete = funcref('s:complete') | ||||
|   let callbacks = go#job#Spawn(a:args) | ||||
|  | ||||
|   let start_options = { | ||||
|         \ 'callback': callbacks.callback, | ||||
|         \ 'exit_cb': callbacks.exit_cb, | ||||
|         \ 'close_cb': callbacks.close_cb, | ||||
|         \ } | ||||
|  | ||||
|   " pre start | ||||
|  | ||||
| @ -51,7 +51,7 @@ function! go#coverage#Buffer(bang, ...) abort | ||||
|   if go#util#has_job() | ||||
|     call s:coverage_job({ | ||||
|           \ 'cmd': ['go', 'test', '-coverprofile', l:tmpname] + a:000, | ||||
|           \ 'custom_cb': function('s:coverage_callback', [l:tmpname]), | ||||
|           \ 'complete': function('s:coverage_callback', [l:tmpname]), | ||||
|           \ 'bang': a:bang, | ||||
|           \ 'for': 'GoTest', | ||||
|           \ }) | ||||
| @ -107,7 +107,7 @@ function! go#coverage#Browser(bang, ...) abort | ||||
|   if go#util#has_job() | ||||
|     call s:coverage_job({ | ||||
|           \ 'cmd': ['go', 'test', '-coverprofile', l:tmpname], | ||||
|           \ 'custom_cb': function('s:coverage_browser_callback', [l:tmpname]), | ||||
|           \ 'complete': function('s:coverage_browser_callback', [l:tmpname]), | ||||
|           \ 'bang': a:bang, | ||||
|           \ 'for': 'GoTest', | ||||
|           \ }) | ||||
| @ -278,7 +278,8 @@ function s:coverage_job(args) | ||||
|   call go#cmd#autowrite() | ||||
|  | ||||
|   let status_dir =  expand('%:p:h') | ||||
|   function! s:error_info_cb(job, exit_status, data) closure | ||||
|   let Complete = a:args.complete | ||||
|   function! s:complete(job, exit_status, data) closure | ||||
|     let status = { | ||||
|           \ 'desc': 'last status', | ||||
|           \ 'type': "coverage", | ||||
| @ -290,14 +291,16 @@ function s:coverage_job(args) | ||||
|     endif | ||||
|  | ||||
|     call go#statusline#Update(status_dir, status) | ||||
|     return Complete(a:job, a:exit_status, a:data) | ||||
|   endfunction | ||||
|  | ||||
|   let a:args.error_info_cb = funcref('s:error_info_cb') | ||||
|   let a:args.complete = funcref('s:complete') | ||||
|   let callbacks = go#job#Spawn(a:args) | ||||
|  | ||||
|   let start_options = { | ||||
|         \ 'callback': callbacks.callback, | ||||
|         \ 'exit_cb': callbacks.exit_cb, | ||||
|         \ 'close_cb': callbacks.close_cb, | ||||
|         \ } | ||||
|  | ||||
|   " pre start | ||||
|  | ||||
| @ -53,7 +53,7 @@ function! go#def#Jump(mode) abort | ||||
|     if go#util#has_job() | ||||
|       let l:spawn_args = { | ||||
|             \ 'cmd': cmd, | ||||
|             \ 'custom_cb': function('s:jump_to_declaration_cb', [a:mode, bin_name]), | ||||
|             \ 'complete': function('s:jump_to_declaration_cb', [a:mode, bin_name]), | ||||
|             \ } | ||||
|  | ||||
|       if &modified | ||||
| @ -292,16 +292,12 @@ function! go#def#Stack(...) abort | ||||
| endfunction | ||||
|  | ||||
| function s:def_job(args) abort | ||||
|   function! s:error_info_cb(job, exit_status, data) closure | ||||
|     " do not print anything during async definition search&jump | ||||
|   endfunction | ||||
|  | ||||
|   let a:args.error_info_cb = funcref('s:error_info_cb') | ||||
|   let callbacks = go#job#Spawn(a:args) | ||||
|  | ||||
|   let start_options = { | ||||
|         \ 'callback': callbacks.callback, | ||||
|         \ 'exit_cb': callbacks.exit_cb, | ||||
|         \ 'close_cb': callbacks.close_cb, | ||||
|         \ } | ||||
|  | ||||
|   if &modified | ||||
|  | ||||
| @ -29,18 +29,7 @@ function! go#doc#OpenBrowser(...) abort | ||||
|     let name = out["name"] | ||||
|     let decl = out["decl"] | ||||
|  | ||||
|     let godoc_url = get(g:, 'go_doc_url', 'https://godoc.org') | ||||
|     if godoc_url isnot 'https://godoc.org' | ||||
|       " strip last '/' character if available | ||||
|       let last_char = strlen(godoc_url) - 1 | ||||
|       if godoc_url[last_char] == '/' | ||||
|         let godoc_url = strpart(godoc_url, 0, last_char) | ||||
|       endif | ||||
|  | ||||
|       " custom godoc installations expects it | ||||
|       let godoc_url .= "/pkg" | ||||
|     endif | ||||
|  | ||||
|     let godoc_url = s:custom_godoc_url() | ||||
|     let godoc_url .= "/" . import | ||||
|     if decl !~ "^package" | ||||
|       let godoc_url .= "#" . name | ||||
| @ -61,7 +50,7 @@ function! go#doc#OpenBrowser(...) abort | ||||
|   let exported_name = pkgs[1] | ||||
|  | ||||
|   " example url: https://godoc.org/github.com/fatih/set#Set | ||||
|   let godoc_url = "https://godoc.org/" . pkg . "#" . exported_name | ||||
|   let godoc_url = s:custom_godoc_url() . "/" . pkg . "#" . exported_name | ||||
|   call go#tool#OpenBrowser(godoc_url) | ||||
| endfunction | ||||
|  | ||||
| @ -217,13 +206,18 @@ function! s:godocWord(args) abort | ||||
|   return [pkg, exported_name] | ||||
| endfunction | ||||
|  | ||||
| function! s:godocNotFound(content) abort | ||||
|   if len(a:content) == 0 | ||||
|     return 1 | ||||
| function! s:custom_godoc_url() abort | ||||
|   let godoc_url = get(g:, 'go_doc_url', 'https://godoc.org') | ||||
|   if godoc_url isnot 'https://godoc.org' | ||||
|     " strip last '/' character if available | ||||
|     let last_char = strlen(godoc_url) - 1 | ||||
|     if godoc_url[last_char] == '/' | ||||
|       let godoc_url = strpart(godoc_url, 0, last_char) | ||||
|     endif | ||||
|     " custom godoc installations expect /pkg before package names | ||||
|     let godoc_url .= "/pkg" | ||||
|   endif | ||||
|  | ||||
|   return a:content =~# '^.*: no such file or directory\n$' | ||||
|   return godoc_url | ||||
| endfunction | ||||
|  | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -1,7 +1,8 @@ | ||||
| function! go#fillstruct#FillStruct() abort | ||||
|   let l:cmd = ['fillstruct', | ||||
|       \ '-file', bufname(''), | ||||
|       \ '-offset', go#util#OffsetCursor()] | ||||
|       \ '-offset', go#util#OffsetCursor(), | ||||
|       \ '-line', line('.')] | ||||
|  | ||||
|   " Read from stdin if modified. | ||||
|   if &modified | ||||
| @ -23,27 +24,36 @@ function! go#fillstruct#FillStruct() abort | ||||
|     return | ||||
|   endtry | ||||
|  | ||||
|   let l:code = split(l:json['code'], "\n") | ||||
|   " Output is array: | ||||
|   "[ | ||||
|   "   {"start": 92, "end": 106, "code": "mail.Address{\n\tName:    \"\",\n\tAddress: \"\",\n}"}, | ||||
|   "   {...second struct...} | ||||
|   " ] | ||||
|  | ||||
|   let l:pos = getpos('.') | ||||
|  | ||||
|   try | ||||
|     " Add any code before/after the struct. | ||||
|     exe l:json['start'] . 'go' | ||||
|     let l:code[0] = getline('.')[:col('.')-1] . l:code[0] | ||||
|     exe l:json['end'] . 'go' | ||||
|     let l:code[len(l:code)-1] .= getline('.')[col('.'):] | ||||
|     for l:struct in l:json | ||||
|       let l:code = split(l:struct['code'], "\n") | ||||
|  | ||||
|     " Indent every line except the first one; makes it look nice. | ||||
|     let l:indent = repeat("\t", indent('.') / &ts) | ||||
|     for i in range(1, len(l:code)-1) | ||||
|       let l:code[l:i] = l:indent . l:code[i] | ||||
|       " Add any code before/after the struct. | ||||
|       exe l:struct['start'] . 'go' | ||||
|       let l:code[0] = getline('.')[:col('.')-1] . l:code[0] | ||||
|       exe l:struct['end'] . 'go' | ||||
|       let l:code[len(l:code)-1] .= getline('.')[col('.'):] | ||||
|  | ||||
|       " Indent every line except the first one; makes it look nice. | ||||
|       let l:indent = repeat("\t", indent('.') / &tabstop) | ||||
|       for l:i in range(1, len(l:code)-1) | ||||
|         let l:code[l:i] = l:indent . l:code[l:i] | ||||
|       endfor | ||||
|  | ||||
|       " Out with the old ... | ||||
|       exe 'normal! ' . l:struct['start'] . 'gov' . l:struct['end'] . 'gox' | ||||
|       " ... in with the new. | ||||
|       call setline('.', l:code[0]) | ||||
|       call append('.', l:code[1:]) | ||||
|     endfor | ||||
|  | ||||
|     " Out with the old ... | ||||
|     exe 'normal! ' . l:json['start'] . 'gov' . l:json['end'] . 'gox' | ||||
|     " ... in with the new. | ||||
|     call setline('.', l:code[0]) | ||||
|     call append('.', l:code[1:]) | ||||
|   finally | ||||
|     call setpos('.', l:pos) | ||||
|   endtry | ||||
|  | ||||
| @ -3,7 +3,7 @@ func! Test_fillstruct() abort | ||||
|     let l:tmp = gotest#write_file('a/a.go', [ | ||||
|           \ 'package a', | ||||
|           \ 'import "net/mail"', | ||||
|           \ 'var addr = mail.Address{}']) | ||||
|           \ "var addr = mail.\x1fAddress{}"]) | ||||
|  | ||||
|     call go#fillstruct#FillStruct() | ||||
|     call gotest#assert_buffer(1, [ | ||||
| @ -16,4 +16,75 @@ func! Test_fillstruct() abort | ||||
|   endtry | ||||
| endfunc | ||||
|  | ||||
| func! Test_fillstruct_line() abort | ||||
|   try | ||||
|     let l:tmp = gotest#write_file('a/a.go', [ | ||||
|           \ 'package a', | ||||
|           \ 'import "net/mail"', | ||||
|           \ "\x1f" . 'var addr = mail.Address{}']) | ||||
|  | ||||
|     call go#fillstruct#FillStruct() | ||||
|     call gotest#assert_buffer(1, [ | ||||
|           \ 'var addr = mail.Address{', | ||||
|           \ '\tName:    "",', | ||||
|           \ '\tAddress: "",', | ||||
|           \ '}']) | ||||
|   finally | ||||
|     call delete(l:tmp, 'rf') | ||||
|   endtry | ||||
| endfunc | ||||
|  | ||||
| func! Test_fillstruct_two_line() abort | ||||
|   try | ||||
|     let l:tmp = gotest#write_file('a/a.go', [ | ||||
|           \ 'package a', | ||||
|           \ 'import (', | ||||
|           \ '"fmt"', | ||||
|           \ '"net/mail"', | ||||
|           \ ')', | ||||
|           \ "\x1f" . 'func x() { fmt.Println(mail.Address{}, mail.Address{}) }']) | ||||
|  | ||||
|     call go#fillstruct#FillStruct() | ||||
|     call gotest#assert_buffer(1, [ | ||||
|           \ 'import (', | ||||
|           \ '"fmt"', | ||||
|           \ '"net/mail"', | ||||
|           \ ')', | ||||
|           \ 'func x() { fmt.Println(mail.Address{', | ||||
|           \ '\tName:    "",', | ||||
|           \ '\tAddress: "",', | ||||
|           \ '}, mail.Address{', | ||||
|           \ '\tName:    "",', | ||||
|           \ '\tAddress: "",', | ||||
|           \ '}) }']) | ||||
|   finally | ||||
|     "call delete(l:tmp, 'rf') | ||||
|   endtry | ||||
| endfunc | ||||
|  | ||||
| func! Test_fillstruct_two_cursor() abort | ||||
|   try | ||||
|     let l:tmp = gotest#write_file('a/a.go', [ | ||||
|           \ 'package a', | ||||
|           \ 'import (', | ||||
|           \ '"fmt"', | ||||
|           \ '"net/mail"', | ||||
|           \ ')', | ||||
|           \ "func x() { fmt.Println(mail.Address{}, mail.Ad\x1fdress{}) }"]) | ||||
|  | ||||
|     call go#fillstruct#FillStruct() | ||||
|     call gotest#assert_buffer(1, [ | ||||
|           \ 'import (', | ||||
|           \ '"fmt"', | ||||
|           \ '"net/mail"', | ||||
|           \ ')', | ||||
|           \ 'func x() { fmt.Println(mail.Address{}, mail.Address{', | ||||
|           \ '\tName:    "",', | ||||
|           \ '\tAddress: "",', | ||||
|           \ '}) }']) | ||||
|   finally | ||||
|     call delete(l:tmp, 'rf') | ||||
|   endtry | ||||
| endfunc | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -153,8 +153,7 @@ function! go#fmt#update_file(source, target) | ||||
| endfunction | ||||
|  | ||||
| " run runs the gofmt/goimport command for the given source file and returns | ||||
| " the the output of the executed command. Target is the real file to be | ||||
| " formated. | ||||
| " the output of the executed command. Target is the real file to be formatted. | ||||
| function! go#fmt#run(bin_name, source, target) | ||||
|   let cmd = s:fmt_cmd(a:bin_name, a:source, a:target) | ||||
|   if empty(cmd) | ||||
|  | ||||
| @ -162,8 +162,12 @@ function! s:async_guru(args) abort | ||||
|  | ||||
|   let status = {} | ||||
|   let exitval = 0 | ||||
|   let closed = 0 | ||||
|   let exited = 0 | ||||
|  | ||||
|   function! s:exit_cb(job, exitval) closure | ||||
|     let exited = 1 | ||||
|  | ||||
|     let status = { | ||||
|           \ 'desc': 'last status', | ||||
|           \ 'type': statusline_type, | ||||
| @ -176,9 +180,21 @@ function! s:async_guru(args) abort | ||||
|     endif | ||||
|  | ||||
|     call go#statusline#Update(status_dir, status) | ||||
|  | ||||
|     if closed | ||||
|       call s:complete() | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   function! s:close_cb(ch) closure | ||||
|     let closed = 1 | ||||
|  | ||||
|     if exited | ||||
|       call s:complete() | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   function! s:complete() closure | ||||
|     let out = join(messages, "\n") | ||||
|  | ||||
|     if has_key(a:args, 'custom_parse') | ||||
| @ -597,11 +613,9 @@ function! s:parse_guru_output(exit_val, output, title) abort | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   let old_errorformat = &errorformat | ||||
|   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) | ||||
|   let &errorformat = old_errorformat | ||||
|  | ||||
|   let errors = go#list#Get(l:listtype) | ||||
|   call go#list#Window(l:listtype, len(errors)) | ||||
|  | ||||
| @ -1,44 +1,78 @@ | ||||
| " Spawn returns callbacks to be used with job_start.  It's abstracted to be | ||||
| " used with various go command, such as build, test, install, etc.. This avoid | ||||
| " us to write the same callback over and over for some commands. It's fully | ||||
| " customizable so each command can change it to it's own logic. | ||||
| " Spawn 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 it's own | ||||
| " logic. | ||||
| " | ||||
| " args is a dictionary with the these keys: | ||||
| "   'cmd': | ||||
| "     The value to pass to job_start(). | ||||
| "   'bang': | ||||
| "     Set to 0 to jump to the first error in the error list. | ||||
| "     Defaults to 0. | ||||
| "   'for': | ||||
| "     The g:go_list_type_command key to use to get the error list type to use. | ||||
| "     Defaults to '_job' | ||||
| "   '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 value will | ||||
| "     process the messages and manage the error list after the job exits and | ||||
| "     the channel is closed. | ||||
| "   'callback': | ||||
| "     A function to call when there is a message to read from the job's | ||||
| "     channel. The function will be passed two arguments: the channel and a | ||||
| "     message. See job-callback. | ||||
|  | ||||
| " 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. | ||||
| function go#job#Spawn(args) | ||||
|   let cbs = { | ||||
|         \ 'winnr': winnr(), | ||||
|         \ 'dir': getcwd(), | ||||
|         \ 'jobdir': fnameescape(expand("%:p:h")), | ||||
|         \ 'messages': [], | ||||
|         \ 'args': a:args.cmd, | ||||
|         \ 'bang': 0, | ||||
|         \ 'for': "_job", | ||||
|         \ } | ||||
|   let cbs = {} | ||||
|  | ||||
|   let winnr = winnr() | ||||
|   let dir = getcwd() | ||||
|   let jobdir = fnameescape(expand("%:p:h")) | ||||
|   let messages = [] | ||||
|   let args = a:args.cmd | ||||
|   let bang = 0 | ||||
|   let for = "_job" | ||||
|  | ||||
|   if has_key(a:args, 'bang') | ||||
|     let cbs.bang = a:args.bang | ||||
|     let l:bang = a:args.bang | ||||
|   endif | ||||
|  | ||||
|   if has_key(a:args, 'for') | ||||
|     let cbs.for = a:args.for | ||||
|     let l:for = a:args.for | ||||
|   endif | ||||
|  | ||||
|   " add final callback to be called if async job is finished | ||||
|   " The signature should be in form: func(job, exit_status, messages) | ||||
|   if has_key(a:args, 'custom_cb') | ||||
|     let cbs.custom_cb = a:args.custom_cb | ||||
|   endif | ||||
|   let l:exited = 0 | ||||
|   let l:exit_status = 0 | ||||
|   let l:closed = 0 | ||||
|  | ||||
|   if has_key(a:args, 'error_info_cb') | ||||
|     let cbs.error_info_cb = a:args.error_info_cb | ||||
|   endif | ||||
|  | ||||
|   function cbs.callback(chan, msg) dict | ||||
|     call add(self.messages, a:msg) | ||||
|   function! s:NopComplete(job, exit_status, data) | ||||
|   endfunction | ||||
|  | ||||
|   function cbs.exit_cb(job, exitval) dict | ||||
|     if has_key(self, 'error_info_cb') | ||||
|       call self.error_info_cb(a:job, a:exitval, self.messages) | ||||
|     endif | ||||
|   let Complete = funcref('s:NopComplete') | ||||
|  | ||||
|   if has_key(a:args, 'complete') | ||||
|     let Complete = a:args.complete | ||||
|   endif | ||||
|  | ||||
|   function cbs.callback(chan, msg) dict closure | ||||
|     call add(messages, a:msg) | ||||
|   endfunction | ||||
|  | ||||
|   function cbs.exit_cb(job, exitval) dict closure | ||||
|     let exit_status = a:exitval | ||||
|     let exited = 1 | ||||
|  | ||||
|     if get(g:, 'go_echo_command_info', 1) | ||||
|       if a:exitval == 0 | ||||
| @ -48,55 +82,62 @@ function go#job#Spawn(args) | ||||
|       endif | ||||
|     endif | ||||
|  | ||||
|     if has_key(self, 'custom_cb') | ||||
|       call self.custom_cb(a:job, a:exitval, self.messages) | ||||
|     if closed | ||||
|       call Complete(a:job, exit_status, messages) | ||||
|       call s:show_errors(a:job, exit_status, messages) | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|     let l:listtype = go#list#Type(self.for) | ||||
|     if a:exitval == 0 | ||||
|   function cbs.close_cb(ch) dict closure | ||||
|     let closed = 1 | ||||
|  | ||||
|     if exited | ||||
|       let job = ch_getjob(a:ch) | ||||
|       call Complete(job, exit_status, messages) | ||||
|       call s:show_errors(job, exit_status, messages) | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   function! s:show_errors(job, exit_status, data) closure | ||||
|     let l:listtype = go#list#Type(for) | ||||
|     if a:exit_status == 0 | ||||
|       call go#list#Clean(l:listtype) | ||||
|       call go#list#Window(l:listtype) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     call self.show_errors(l:listtype) | ||||
|   endfunction | ||||
|  | ||||
|   function cbs.show_errors(listtype) dict | ||||
|     let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|     try | ||||
|       execute cd self.jobdir | ||||
|       let errors = go#tool#ParseErrors(self.messages) | ||||
|       let errors = go#tool#FilterValids(errors) | ||||
|     finally | ||||
|       execute cd . fnameescape(self.dir) | ||||
|     endtry | ||||
|  | ||||
|     if !len(errors) | ||||
|       " failed to parse errors, output the original content | ||||
|       call go#util#EchoError(self.messages + [self.dir]) | ||||
|     let l:listtype = go#list#Type(for) | ||||
|     if len(a:data) == 0 | ||||
|       call go#list#Clean(l:listtype) | ||||
|       call go#list#Window(l:listtype) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     if self.winnr == winnr() | ||||
|       call go#list#Populate(a:listtype, errors, join(self.args)) | ||||
|       call go#list#Window(a:listtype, len(errors)) | ||||
|       if !empty(errors) && !self.bang | ||||
|         call go#list#JumpToFirst(a:listtype) | ||||
|     let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|     try | ||||
|       execute cd jobdir | ||||
|       let errors = go#tool#ParseErrors(a:data) | ||||
|       let errors = go#tool#FilterValids(errors) | ||||
|     finally | ||||
|       execute cd . fnameescape(dir) | ||||
|     endtry | ||||
|  | ||||
|     if empty(errors) | ||||
|       " failed to parse errors, output the original content | ||||
|       call go#util#EchoError(messages + [dir]) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     if winnr == winnr() | ||||
|       call go#list#Populate(l:listtype, errors, join(args)) | ||||
|       call go#list#Window(l:listtype, len(errors)) | ||||
|       if !bang | ||||
|         call go#list#JumpToFirst(l:listtype) | ||||
|       endif | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   " override callback handler if user provided it | ||||
|   if has_key(a:args, 'callback') | ||||
|     let cbs.callback = a:args.callback | ||||
|   endif | ||||
|  | ||||
|   " override exit callback handler if user provided it | ||||
|   if has_key(a:args, 'exit_cb') | ||||
|     let cbs.exit_cb = a:args.exit_cb | ||||
|   endif | ||||
|  | ||||
|   return cbs | ||||
| endfunction | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -10,8 +10,8 @@ if !exists("g:go_metalinter_enabled") | ||||
|   let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck'] | ||||
| endif | ||||
|  | ||||
| if !exists("g:go_metalinter_excludes") | ||||
|   let g:go_metalinter_excludes = [] | ||||
| if !exists("g:go_metalinter_disabled") | ||||
|   let g:go_metalinter_disabled = [] | ||||
| endif | ||||
|  | ||||
| if !exists("g:go_golint_bin") | ||||
| @ -24,9 +24,9 @@ endif | ||||
|  | ||||
| function! go#lint#Gometa(autosave, ...) abort | ||||
|   if a:0 == 0 | ||||
|     let goargs = shellescape(expand('%:p:h')) | ||||
|     let goargs = [expand('%:p:h')] | ||||
|   else | ||||
|     let goargs = go#util#Shelljoin(a:000) | ||||
|     let goargs = a:000 | ||||
|   endif | ||||
|  | ||||
|   let bin_path = go#path#CheckBinPath("gometalinter") | ||||
| @ -44,8 +44,8 @@ function! go#lint#Gometa(autosave, ...) abort | ||||
|       let cmd += ["--enable=".linter] | ||||
|     endfor | ||||
|  | ||||
|     for exclude in g:go_metalinter_excludes | ||||
|       let cmd += ["--exclude=".exclude] | ||||
|     for linter in g:go_metalinter_disabled | ||||
|       let cmd += ["--disable=".linter] | ||||
|     endfor | ||||
|  | ||||
|     " gometalinter has a --tests flag to tell its linters whether to run | ||||
| @ -54,14 +54,20 @@ function! go#lint#Gometa(autosave, ...) abort | ||||
|     " test files. One example of a linter that will not run against tests if | ||||
|     " we do not specify this flag is errcheck. | ||||
|     let cmd += ["--tests"] | ||||
|  | ||||
|     " path | ||||
|     let cmd += [expand('%:p:h')] | ||||
|   else | ||||
|     " the user wants something else, let us use it. | ||||
|     let cmd += split(g:go_metalinter_command, " ") | ||||
|   endif | ||||
|  | ||||
|   if a:autosave | ||||
|     " redraw so that any messages that were displayed while writing the file | ||||
|     " will be cleared | ||||
|     redraw | ||||
|  | ||||
|     " Include only messages for the active buffer for autosave. | ||||
|     let cmd += [printf('--include=^%s:.*$', fnamemodify(expand('%:p'), ":."))] | ||||
|   endif | ||||
|  | ||||
|   " gometalinter has a default deadline of 5 seconds. | ||||
|   " | ||||
|   " For async mode (s:lint_job), we want to override the default deadline only | ||||
| @ -78,27 +84,26 @@ function! go#lint#Gometa(autosave, ...) abort | ||||
|       let cmd += ["--deadline=" . deadline] | ||||
|     endif | ||||
|  | ||||
|     call s:lint_job({'cmd': cmd}) | ||||
|     let cmd += goargs | ||||
|  | ||||
|     call s:lint_job({'cmd': cmd}, a:autosave) | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   " We're calling gometalinter synchronously. | ||||
|  | ||||
|   let cmd += ["--deadline=" . get(g:, 'go_metalinter_deadline', "5s")] | ||||
|  | ||||
|   let cmd += goargs | ||||
|  | ||||
|   let [l:out, l:err] = go#util#Exec(cmd) | ||||
|  | ||||
|   if a:autosave | ||||
|     " include only messages for the active buffer | ||||
|     let cmd += ["--include='^" . expand('%:p') . ".*$'"] | ||||
|     let l:listtype = go#list#Type("GoMetaLinterAutoSave") | ||||
|   else | ||||
|     let l:listtype = go#list#Type("GoMetaLinter") | ||||
|   endif | ||||
|  | ||||
|  | ||||
|   let meta_command = join(cmd, " ") | ||||
|  | ||||
|   let out = go#util#System(meta_command) | ||||
|  | ||||
|   let l:listtype = go#list#Type("GoMetaLinter") | ||||
|   if go#util#ShellError() == 0 | ||||
|     redraw | echo | ||||
|   if l:err == 0 | ||||
|     call go#list#Clean(l:listtype) | ||||
|     call go#list#Window(l:listtype) | ||||
|     echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None | ||||
| @ -240,7 +245,7 @@ function! go#lint#ToggleMetaLinterAutoSave() abort | ||||
|   call go#util#EchoProgress("auto metalinter enabled") | ||||
| endfunction | ||||
|  | ||||
| function s:lint_job(args) | ||||
| function! s:lint_job(args, autosave) | ||||
|   let status_dir = expand('%:p:h') | ||||
|   let started_at = reltime() | ||||
|  | ||||
| @ -253,29 +258,28 @@ function s:lint_job(args) | ||||
|   " autowrite is not enabled for jobs | ||||
|   call go#cmd#autowrite() | ||||
|  | ||||
|   let l:listtype = go#list#Type("GoMetaLinter") | ||||
|   if a:autosave | ||||
|     let l:listtype = go#list#Type("GoMetaLinterAutoSave") | ||||
|   else | ||||
|     let l:listtype = go#list#Type("GoMetaLinter") | ||||
|   endif | ||||
|  | ||||
|   let l:errformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m' | ||||
|  | ||||
|   let l:messages = [] | ||||
|   let l:exited = 0 | ||||
|   let l:closed = 0 | ||||
|   let l:exit_status = 0 | ||||
|   let l:winnr = winnr() | ||||
|  | ||||
|   function! s:callback(chan, msg) closure | ||||
|     let old_errorformat = &errorformat | ||||
|     let &errorformat = l:errformat | ||||
|     if l:listtype == "locationlist" | ||||
|       lad a:msg | ||||
|     elseif l:listtype == "quickfix" | ||||
|       caddexpr a:msg | ||||
|     endif | ||||
|     let &errorformat = old_errorformat | ||||
|  | ||||
|     " TODO(jinleileiking): give a configure to jump or not | ||||
|     let l:winnr = winnr() | ||||
|  | ||||
|     let errors = go#list#Get(l:listtype) | ||||
|     call go#list#Window(l:listtype, len(errors)) | ||||
|  | ||||
|     exe l:winnr . "wincmd w" | ||||
|     call add(messages, a:msg) | ||||
|   endfunction | ||||
|  | ||||
|   function! s:exit_cb(job, exitval) closure | ||||
|     let exited = 1 | ||||
|     let exit_status = a:exitval | ||||
|  | ||||
|     let status = { | ||||
|           \ 'desc': 'last status', | ||||
|           \ 'type': "gometaliner", | ||||
| @ -293,16 +297,33 @@ function s:lint_job(args) | ||||
|  | ||||
|     call go#statusline#Update(status_dir, status) | ||||
|  | ||||
|     let errors = go#list#Get(l:listtype) | ||||
|     if empty(errors) | ||||
|       call go#list#Window(l:listtype, len(errors)) | ||||
|     elseif has("patch-7.4.2200") | ||||
|       if l:listtype == 'quickfix' | ||||
|         call setqflist([], 'a', {'title': 'GoMetaLinter'}) | ||||
|       else | ||||
|         call setloclist(0, [], 'a', {'title': 'GoMetaLinter'}) | ||||
|       endif | ||||
|     if closed | ||||
|       call s:show_errors() | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   function! s:close_cb(ch) closure | ||||
|     let closed = 1 | ||||
|  | ||||
|     if exited | ||||
|       call s:show_errors() | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|  | ||||
|   function! s:show_errors() closure | ||||
|     " make sure the current window is the window from which gometalinter was | ||||
|     " run when the listtype is locationlist so that the location list for the | ||||
|     " correct window will be populated. | ||||
|     if l:listtype == 'locationlist' | ||||
|       exe l:winnr . "wincmd w" | ||||
|     endif | ||||
|  | ||||
|     let l:errorformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m' | ||||
|     call go#list#ParseFormat(l:listtype, l:errorformat, messages, 'GoMetaLinter') | ||||
|  | ||||
|     let errors = go#list#Get(l:listtype) | ||||
|     call go#list#Window(l:listtype, len(errors)) | ||||
|  | ||||
|     if get(g:, 'go_echo_command_info', 1) | ||||
|       call go#util#EchoSuccess("linting finished") | ||||
| @ -312,12 +333,11 @@ function s:lint_job(args) | ||||
|   let start_options = { | ||||
|         \ 'callback': funcref("s:callback"), | ||||
|         \ 'exit_cb': funcref("s:exit_cb"), | ||||
|         \ 'close_cb': funcref("s:close_cb"), | ||||
|         \ } | ||||
|  | ||||
|   call job_start(a:args.cmd, start_options) | ||||
|  | ||||
|   call go#list#Clean(l:listtype) | ||||
|  | ||||
|   if get(g:, 'go_echo_command_info', 1) | ||||
|     call go#util#EchoProgress("linting started ...") | ||||
|   endif | ||||
|  | ||||
							
								
								
									
										105
									
								
								sources_non_forked/vim-go/autoload/go/lint_test.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								sources_non_forked/vim-go/autoload/go/lint_test.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | ||||
| func! Test_Gometa() abort | ||||
|   let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint' | ||||
|   silent exe 'e ' . $GOPATH . '/src/lint/lint.go' | ||||
|  | ||||
|   let expected = [ | ||||
|         \ {'lnum': 5, 'bufnr': 3, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'} | ||||
|       \ ] | ||||
|  | ||||
|   " clear the quickfix lists | ||||
|   call setqflist([], 'r') | ||||
|  | ||||
|   " call go#lint#ToggleMetaLinterAutoSave from lint.vim so that the file will | ||||
|   " be autoloaded and the default for g:go_metalinter_enabled will be set so | ||||
|   " we can capture it to restore it after the test is run. | ||||
|   call go#lint#ToggleMetaLinterAutoSave() | ||||
|   " And restore it back to its previous value | ||||
|   call go#lint#ToggleMetaLinterAutoSave() | ||||
|  | ||||
|   let orig_go_metalinter_enabled = g:go_metalinter_enabled | ||||
|   let g:go_metalinter_enabled = ['golint'] | ||||
|  | ||||
|   call go#lint#Gometa(0, $GOPATH . '/src/foo') | ||||
|  | ||||
|   let actual = getqflist() | ||||
|   let start = reltime() | ||||
|   while len(actual) == 0 && reltimefloat(reltime(start)) < 10 | ||||
|     sleep 100m | ||||
|     let actual = getqflist() | ||||
|   endwhile | ||||
|  | ||||
|   call gotest#assert_quickfix(actual, expected) | ||||
|   let g:go_metalinter_enabled = orig_go_metalinter_enabled | ||||
| endfunc | ||||
|  | ||||
| func! Test_GometaWithDisabled() abort | ||||
|   let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint' | ||||
|   silent exe 'e ' . $GOPATH . '/src/lint/lint.go' | ||||
|  | ||||
|   let expected = [ | ||||
|         \ {'lnum': 5, 'bufnr': 3, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'} | ||||
|       \ ] | ||||
|  | ||||
|   " clear the quickfix lists | ||||
|   call setqflist([], 'r') | ||||
|  | ||||
|   " call go#lint#ToggleMetaLinterAutoSave from lint.vim so that the file will | ||||
|   " be autoloaded and the default for g:go_metalinter_disabled will be set so | ||||
|   " we can capture it to restore it after the test is run. | ||||
|   call go#lint#ToggleMetaLinterAutoSave() | ||||
|   " And restore it back to its previous value | ||||
|   call go#lint#ToggleMetaLinterAutoSave() | ||||
|  | ||||
|   let orig_go_metalinter_disabled = g:go_metalinter_disabled | ||||
|   let g:go_metalinter_disabled = ['vet'] | ||||
|  | ||||
|   call go#lint#Gometa(0, $GOPATH . '/src/foo') | ||||
|  | ||||
|   let actual = getqflist() | ||||
|   let start = reltime() | ||||
|   while len(actual) == 0 && reltimefloat(reltime(start)) < 10 | ||||
|     sleep 100m | ||||
|     let actual = getqflist() | ||||
|   endwhile | ||||
|  | ||||
|   call gotest#assert_quickfix(actual, expected) | ||||
|   let g:go_metalinter_disabled = orig_go_metalinter_disabled | ||||
| endfunc | ||||
|  | ||||
| func! Test_GometaAutoSave() abort | ||||
|   let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint' | ||||
|   silent exe 'e ' . $GOPATH . '/src/lint/lint.go' | ||||
|  | ||||
|   let expected = [ | ||||
|         \ {'lnum': 5, 'bufnr': 2, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported (golint)'} | ||||
|       \ ] | ||||
|  | ||||
|   let winnr = winnr() | ||||
|  | ||||
|   " clear the location lists | ||||
|   call setloclist(l:winnr, [], 'r') | ||||
|  | ||||
|   " call go#lint#ToggleMetaLinterAutoSave from lint.vim so that the file will | ||||
|   " be autoloaded and the default for g:go_metalinter_autosave_enabled will be | ||||
|   " set so we can capture it to restore it after the test is run. | ||||
|   call go#lint#ToggleMetaLinterAutoSave() | ||||
|   " And restore it back to its previous value | ||||
|   call go#lint#ToggleMetaLinterAutoSave() | ||||
|  | ||||
|   let orig_go_metalinter_autosave_enabled = g:go_metalinter_autosave_enabled | ||||
|   let g:go_metalinter_autosave_enabled = ['golint'] | ||||
|  | ||||
|   call go#lint#Gometa(1) | ||||
|  | ||||
|   let actual = getloclist(l:winnr) | ||||
|   let start = reltime() | ||||
|   while len(actual) == 0 && reltimefloat(reltime(start)) < 10 | ||||
|     sleep 100m | ||||
|     let actual = getloclist(l:winnr) | ||||
|   endwhile | ||||
|  | ||||
|   call gotest#assert_quickfix(actual, expected) | ||||
|   let g:go_metalinter_autosave_enabled = orig_go_metalinter_autosave_enabled | ||||
| endfunc | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
| @ -78,16 +78,18 @@ function! go#list#ParseFormat(listtype, errformat, items, title) abort | ||||
|  | ||||
|   " parse and populate the location list | ||||
|   let &errorformat = a:errformat | ||||
|   if a:listtype == "locationlist" | ||||
|     lgetexpr a:items | ||||
|     if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif | ||||
|   else | ||||
|     cgetexpr a:items | ||||
|     if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif | ||||
|   endif | ||||
|  | ||||
|   "restore back | ||||
|   let &errorformat = old_errorformat | ||||
|   try | ||||
|     if a:listtype == "locationlist" | ||||
|       lgetexpr a:items | ||||
|       if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif | ||||
|     else | ||||
|       cgetexpr a:items | ||||
|       if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif | ||||
|     endif | ||||
|   finally | ||||
|     "restore back | ||||
|     let &errorformat = old_errorformat | ||||
|   endtry | ||||
| endfunction | ||||
|  | ||||
| " Parse parses the given items based on the global errorformat and | ||||
| @ -135,21 +137,22 @@ endfunction | ||||
| " single file or buffer. Keys that begin with an underscore are not supported | ||||
| " in g:go_list_type_commands. | ||||
| let s:default_list_type_commands = { | ||||
|       \ "GoBuild":      "quickfix", | ||||
|       \ "GoErrCheck":   "quickfix", | ||||
|       \ "GoFmt":        "locationlist", | ||||
|       \ "GoGenerate":   "quickfix", | ||||
|       \ "GoInstall":    "quickfix", | ||||
|       \ "GoLint":       "quickfix", | ||||
|       \ "GoMetaLinter": "quickfix", | ||||
|       \ "GoModifyTags": "locationlist", | ||||
|       \ "GoRename":     "quickfix", | ||||
|       \ "GoRun":        "quickfix", | ||||
|       \ "GoTest":       "quickfix", | ||||
|       \ "GoVet":        "quickfix", | ||||
|       \ "_guru":        "locationlist", | ||||
|       \ "_term":        "locationlist", | ||||
|       \ "_job":         "locationlist", | ||||
|       \ "GoBuild":              "quickfix", | ||||
|       \ "GoErrCheck":           "quickfix", | ||||
|       \ "GoFmt":                "locationlist", | ||||
|       \ "GoGenerate":           "quickfix", | ||||
|       \ "GoInstall":            "quickfix", | ||||
|       \ "GoLint":               "quickfix", | ||||
|       \ "GoMetaLinter":         "quickfix", | ||||
|       \ "GoMetaLinterAutoSave": "locationlist", | ||||
|       \ "GoModifyTags":         "locationlist", | ||||
|       \ "GoRename":             "quickfix", | ||||
|       \ "GoRun":                "quickfix", | ||||
|       \ "GoTest":               "quickfix", | ||||
|       \ "GoVet":                "quickfix", | ||||
|       \ "_guru":                "locationlist", | ||||
|       \ "_term":                "locationlist", | ||||
|       \ "_job":                 "locationlist", | ||||
|   \ } | ||||
|  | ||||
| function! go#list#Type(for) abort | ||||
|  | ||||
| @ -45,9 +45,9 @@ function! go#path#Default() abort | ||||
|   return $GOPATH | ||||
| endfunction | ||||
|  | ||||
| " HasPath checks whether the given path exists in GOPATH environment variable | ||||
| " s:HasPath checks whether the given path exists in GOPATH environment variable | ||||
| " or not | ||||
| function! go#path#HasPath(path) abort | ||||
| function! s:HasPath(path) abort | ||||
|   let go_paths = split(go#path#Default(), go#util#PathListSep()) | ||||
|   let last_char = strlen(a:path) - 1 | ||||
|  | ||||
| @ -94,11 +94,11 @@ function! go#path#Detect() abort | ||||
|     " gb vendor plugin | ||||
|     " (https://github.com/constabulary/gb/tree/master/cmd/gb-vendor) | ||||
|     let gb_vendor_root = src_path . "vendor" . go#util#PathSep() | ||||
|     if isdirectory(gb_vendor_root) && !go#path#HasPath(gb_vendor_root) | ||||
|     if isdirectory(gb_vendor_root) && !s:HasPath(gb_vendor_root) | ||||
|       let gopath = gb_vendor_root . go#util#PathListSep() . gopath | ||||
|     endif | ||||
|  | ||||
|     if !go#path#HasPath(src_path) | ||||
|     if !s:HasPath(src_path) | ||||
|       let gopath =  src_path . go#util#PathListSep() . gopath | ||||
|     endif | ||||
|   endif | ||||
| @ -108,7 +108,7 @@ function! go#path#Detect() abort | ||||
|   if !empty(godeps_root) | ||||
|     let godeps_path = join([fnamemodify(godeps_root, ':p:h:h'), "Godeps", "_workspace" ], go#util#PathSep()) | ||||
|  | ||||
|     if !go#path#HasPath(godeps_path) | ||||
|     if !s:HasPath(godeps_path) | ||||
|       let gopath =  godeps_path . go#util#PathListSep() . gopath | ||||
|     endif | ||||
|   endif | ||||
| @ -164,7 +164,7 @@ function! go#path#CheckBinPath(binpath) abort | ||||
|     let $PATH = old_path | ||||
|  | ||||
|     if go#util#IsUsingCygwinShell() == 1 | ||||
|       return go#path#CygwinPath(binpath) | ||||
|       return s:CygwinPath(binpath) | ||||
|     endif | ||||
|  | ||||
|     return binpath | ||||
| @ -183,13 +183,13 @@ function! go#path#CheckBinPath(binpath) abort | ||||
|   let $PATH = old_path | ||||
|  | ||||
|   if go#util#IsUsingCygwinShell() == 1 | ||||
|     return go#path#CygwinPath(a:binpath) | ||||
|     return s:CygwinPath(a:binpath) | ||||
|   endif | ||||
|  | ||||
|   return go_bin_path . go#util#PathSep() . basename | ||||
| endfunction | ||||
|  | ||||
| function! go#path#CygwinPath(path) | ||||
| function! s:CygwinPath(path) | ||||
|    return substitute(a:path, '\\', '/', "g") | ||||
| endfunction | ||||
|  | ||||
|  | ||||
| @ -72,7 +72,11 @@ function! go#rename#Rename(bang, ...) abort | ||||
| endfunction | ||||
|  | ||||
| function s:rename_job(args) | ||||
|   let exited = 0 | ||||
|   let closed = 0 | ||||
|   let exitval = 0 | ||||
|   let messages = [] | ||||
|  | ||||
|   function! s:callback(chan, msg) closure | ||||
|     call add(messages, a:msg) | ||||
|   endfunction | ||||
| @ -80,6 +84,9 @@ function s:rename_job(args) | ||||
|   let status_dir =  expand('%:p:h') | ||||
|  | ||||
|   function! s:exit_cb(job, exitval) closure | ||||
|     let exited = 1 | ||||
|     let exitval = a:exitval | ||||
|  | ||||
|     let status = { | ||||
|           \ 'desc': 'last status', | ||||
|           \ 'type': "gorename", | ||||
| @ -92,12 +99,23 @@ function s:rename_job(args) | ||||
|  | ||||
|     call go#statusline#Update(status_dir, status) | ||||
|  | ||||
|     call s:parse_errors(a:exitval, a:args.bang, messages) | ||||
|     if closed | ||||
|       call s:parse_errors(a:exitval, a:args.bang, messages) | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   function! s:close_cb(ch) closure | ||||
|     let closed = 1 | ||||
|  | ||||
|     if exited | ||||
|       call s:parse_errors(exitval, a:args.bang, messages) | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   let start_options = { | ||||
|         \ 'callback': funcref("s:callback"), | ||||
|         \ 'exit_cb': funcref("s:exit_cb"), | ||||
|         \ 'close_cb': funcref("s:close_cb"), | ||||
|         \ } | ||||
|  | ||||
|   call go#statusline#Update(status_dir, { | ||||
|  | ||||
| @ -6,9 +6,12 @@ function! go#template#create() abort | ||||
|  | ||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|   let dir = getcwd() | ||||
|   execute cd . fnameescape(expand("%:p:h")) | ||||
|   let l:package_name = -1 | ||||
|  | ||||
|   let l:package_name = go#tool#PackageName() | ||||
|   if isdirectory(expand('%:p:h')) | ||||
|     execute cd . fnameescape(expand('%:p:h')) | ||||
|     let l:package_name = go#tool#PackageName() | ||||
|   endif | ||||
|  | ||||
|   " if we can't figure out any package name(no Go files or non Go package | ||||
|   " files) from the directory create the template or use the cwd | ||||
|  | ||||
| @ -44,10 +44,6 @@ function! go#term#newmode(bang, cmd, mode) abort | ||||
|  | ||||
|   let id = termopen(a:cmd, job) | ||||
|  | ||||
|   if l:winnr !=# winnr() | ||||
|     exe l:winnr . "wincmd w" | ||||
|   endif | ||||
|  | ||||
|   execute cd . fnameescape(dir) | ||||
|  | ||||
|   let job.id = id | ||||
| @ -58,12 +54,13 @@ function! go#term#newmode(bang, cmd, mode) abort | ||||
|   let height = get(g:, 'go_term_height', winheight(0)) | ||||
|   let width = get(g:, 'go_term_width', winwidth(0)) | ||||
|  | ||||
|   " we are careful how to resize. for example it's vertical we don't change | ||||
|   " we are careful how to resize. for example it's vsplit we don't change | ||||
|   " the height. The below command resizes the buffer | ||||
|   if a:mode == "split" | ||||
|     exe 'resize ' . height | ||||
|   elseif a:mode == "vertical" | ||||
|  | ||||
|   if mode =~ "vertical" || mode =~ "vsplit" || mode =~ "vnew" | ||||
|     exe 'vertical resize ' . width | ||||
|   elseif mode =~ "split" || mode =~ "new" | ||||
|     exe 'resize ' . height | ||||
|   endif | ||||
|  | ||||
|   " we also need to resize the pty, so there you go... | ||||
| @ -71,6 +68,11 @@ function! go#term#newmode(bang, cmd, mode) abort | ||||
|  | ||||
|   let s:jobs[id] = job | ||||
|   stopinsert | ||||
|  | ||||
|   if l:winnr !=# winnr() | ||||
|     exe l:winnr . "wincmd w" | ||||
|   endif | ||||
|  | ||||
|   return id | ||||
| endfunction | ||||
|  | ||||
|  | ||||
| @ -0,0 +1,7 @@ | ||||
| package foo | ||||
|  | ||||
| import "fmt" | ||||
|  | ||||
| func MissingFooDoc() { | ||||
| 	fmt.Println("missing doc") | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package lint | ||||
|  | ||||
| import "fmt" | ||||
|  | ||||
| func MissingDoc() { | ||||
| 	fmt.Println("missing doc") | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package lint | ||||
|  | ||||
| import "fmt" | ||||
|  | ||||
| func AlsoMissingDoc() { | ||||
| 	fmt.Println("missing doc") | ||||
| } | ||||
							
								
								
									
										1
									
								
								sources_non_forked/vim-go/autoload/go/test-fixtures/test/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								sources_non_forked/vim-go/autoload/go/test-fixtures/test/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| /pkg | ||||
| @ -0,0 +1,7 @@ | ||||
| package main | ||||
|  | ||||
| import "fmt" | ||||
|  | ||||
| func main() { | ||||
| 	fmt.Println("vim-go" | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package mock | ||||
|  | ||||
| import "testing" | ||||
|  | ||||
| func Fail(t *testing.T) { | ||||
| 	t.Fatal("another package badness") | ||||
| } | ||||
| @ -0,0 +1,59 @@ | ||||
| package play | ||||
|  | ||||
| import ( | ||||
| 	"sync" | ||||
| 	"testing" | ||||
|  | ||||
| 	"play/mock" | ||||
| ) | ||||
|  | ||||
| func TestTopSubHelper(t *testing.T) { | ||||
| 	t.Run("sub", func(t *testing.T) { | ||||
| 		t.Log("log message") | ||||
| 		t.Error("sub badness") | ||||
| 	}) | ||||
| 	t.Error("badness") | ||||
| 	helper(t) | ||||
| } | ||||
|  | ||||
| func TestMultiline(t *testing.T) { | ||||
| 	t.Error("this is an error\nand a second line, too") | ||||
| 	t.Error("\nthis is another error") | ||||
| } | ||||
|  | ||||
| func TestSub(t *testing.T) { | ||||
| 	t.Run("indented", func(t *testing.T) { | ||||
| 		t.Error("this is a sub-test error\nand a second line, too") | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestOK(t *testing.T) { | ||||
| 	t.Run("log", func(t *testing.T) { | ||||
| 		t.Log("goodness") | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // TestMocked tests behavior similar to what users may experience when using | ||||
| // github.com/golang/mock/gomock. | ||||
| func TestMocked(t *testing.T) { | ||||
| 	mock.Fail(t) | ||||
| } | ||||
|  | ||||
| func TestPanic(t *testing.T) { | ||||
| 	panic("worst ever") | ||||
| } | ||||
|  | ||||
| func TestConcurrentPanic(t *testing.T) { | ||||
| 	var wg sync.WaitGroup | ||||
| 	wg.Add(1) | ||||
| 	go func() { | ||||
| 		panic("concurrent fail") | ||||
| 		wg.Done() | ||||
| 	}() | ||||
| 	wg.Wait() | ||||
| } | ||||
|  | ||||
| func helper(t *testing.T) { | ||||
| 	t.Helper() | ||||
| 	t.Fatal("helper badness") | ||||
| } | ||||
| @ -0,0 +1,11 @@ | ||||
| package main | ||||
|  | ||||
| import "testing" | ||||
|  | ||||
| func TestHelloWorld(t *testing.T) { | ||||
| 	t.Error("so long") | ||||
|  | ||||
| 	t.Run("sub", func(t *testing.T) { | ||||
| 		t.Error("thanks for all the fish") | ||||
| 	}) | ||||
| } | ||||
| @ -0,0 +1,47 @@ | ||||
| // Run a few parallel tests, all in parallel, using multiple techniques for | ||||
| // causing the test to take a while so that the stacktraces resulting from a | ||||
| // test timeout will contain several goroutines to avoid giving a false sense | ||||
| // of confidence or creating error formats that don't account for the more | ||||
| // complex scenarios that can occur with timeouts. | ||||
|  | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| func TestSleep(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 	time.Sleep(15 * time.Second) | ||||
| 	t.Log("expected panic if run with timeout < 15s") | ||||
| } | ||||
|  | ||||
| func TestRunning(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 	c := time.After(15 * time.Second) | ||||
| Loop: | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-c: | ||||
| 			break Loop | ||||
| 		default: | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	t.Log("expected panic if run with timeout < 15s") | ||||
| } | ||||
|  | ||||
| func TestRunningAlso(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 	c := time.After(15 * time.Second) | ||||
| Loop: | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-c: | ||||
| 			break Loop | ||||
| 		default: | ||||
| 		} | ||||
| 	} | ||||
| 	t.Log("expected panic if run with timeout < 15s") | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| " Test runs `go test` in the current directory. If compile is true, it'll | ||||
| " compile the tests instead of running them (useful to catch errors in the | ||||
| " test files). Any other argument is appendend to the final `go test` command | ||||
| " test files). Any other argument is appended to the final `go test` command. | ||||
| function! go#test#Test(bang, compile, ...) abort | ||||
|   let args = ["test"] | ||||
|  | ||||
| @ -72,6 +72,8 @@ function! go#test#Test(bang, compile, ...) abort | ||||
|  | ||||
|   let command = "go " . join(args, ' ') | ||||
|   let out = go#tool#ExecuteInDir(command) | ||||
|   " TODO(bc): When the output is JSON, the JSON should be run through a | ||||
|   " filter to produce lines that are more easily described by errorformat. | ||||
|  | ||||
|   let l:listtype = go#list#Type("GoTest") | ||||
|  | ||||
| @ -80,10 +82,8 @@ function! go#test#Test(bang, compile, ...) abort | ||||
|   execute cd fnameescape(expand("%:p:h")) | ||||
|  | ||||
|   if go#util#ShellError() != 0 | ||||
|     let errors = s:parse_errors(split(out, '\n')) | ||||
|     let errors = go#tool#FilterValids(errors) | ||||
|  | ||||
|     call go#list#Populate(l:listtype, errors, command) | ||||
|     call go#list#ParseFormat(l:listtype, s:errorformat(), split(out, '\n'), command) | ||||
|     let errors = go#list#Get(l:listtype) | ||||
|     call go#list#Window(l:listtype, len(errors)) | ||||
|     if !empty(errors) && !a:bang | ||||
|       call go#list#JumpToFirst(l:listtype) | ||||
| @ -129,12 +129,16 @@ function! go#test#Func(bang, ...) abort | ||||
|  | ||||
|   if a:0 | ||||
|     call extend(args, a:000) | ||||
|   else | ||||
|     " only add this if no custom flags are passed | ||||
|     let timeout  = get(g:, 'go_test_timeout', '10s') | ||||
|     call add(args, printf("-timeout=%s", timeout)) | ||||
|   endif | ||||
|  | ||||
|   call call('go#test#Test', args) | ||||
| endfunction | ||||
|  | ||||
| function s:test_job(args) abort | ||||
| function! s:test_job(args) abort | ||||
|   let status_dir = expand('%:p:h') | ||||
|   let started_at = reltime() | ||||
|  | ||||
| @ -153,12 +157,19 @@ function s:test_job(args) abort | ||||
|   " autowrite is not enabled for jobs | ||||
|   call go#cmd#autowrite() | ||||
|  | ||||
|   let l:exited = 0 | ||||
|   let l:closed = 0 | ||||
|   let l:exitval = 0 | ||||
|   let messages = [] | ||||
|  | ||||
|   function! s:callback(chan, msg) closure | ||||
|     call add(messages, a:msg) | ||||
|   endfunction | ||||
|  | ||||
|   function! s:exit_cb(job, exitval) closure | ||||
|     let exited = 1 | ||||
|     let exitval = a:exitval | ||||
|  | ||||
|     let status = { | ||||
|           \ 'desc': 'last status', | ||||
|           \ 'type': "test", | ||||
| @ -192,19 +203,23 @@ function s:test_job(args) abort | ||||
|  | ||||
|     call go#statusline#Update(status_dir, status) | ||||
|  | ||||
|     let l:listtype = go#list#Type("GoTest") | ||||
|     if a:exitval == 0 | ||||
|       call go#list#Clean(l:listtype) | ||||
|       call go#list#Window(l:listtype) | ||||
|       return | ||||
|     if closed | ||||
|       call s:show_errors(a:args, l:exitval, messages) | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|     call s:show_errors(a:args, a:exitval, messages) | ||||
|   function! s:close_cb(ch) closure | ||||
|     let closed = 1 | ||||
|  | ||||
|     if exited | ||||
|       call s:show_errors(a:args, l:exitval, messages) | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   let start_options = { | ||||
|         \ 'callback': funcref("s:callback"), | ||||
|         \ 'exit_cb': funcref("s:exit_cb"), | ||||
|         \ 'close_cb': funcref("s:close_cb"), | ||||
|         \ } | ||||
|  | ||||
|   " pre start | ||||
| @ -223,13 +238,23 @@ endfunction | ||||
| " a quickfix compatible list of errors. It's intended to be used only for go | ||||
| " test output. | ||||
| function! s:show_errors(args, exit_val, messages) abort | ||||
|     let l:listtype = go#list#Type("GoTest") | ||||
|     if a:exit_val == 0 | ||||
|       call go#list#Clean(l:listtype) | ||||
|       call go#list#Window(l:listtype) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|   " TODO(bc): When messages is JSON, the JSON should be run through a | ||||
|   " filter to produce lines that are more easily described by errorformat. | ||||
|  | ||||
|   let l:listtype = go#list#Type("GoTest") | ||||
|  | ||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|   try | ||||
|     execute cd a:args.jobdir | ||||
|     let errors = s:parse_errors(a:messages) | ||||
|     let errors = go#tool#FilterValids(errors) | ||||
|     call go#list#ParseFormat(l:listtype, s:errorformat(), a:messages, join(a:args.cmd)) | ||||
|     let errors = go#list#Get(l:listtype) | ||||
|   finally | ||||
|     execute cd . fnameescape(a:args.dir) | ||||
|   endtry | ||||
| @ -242,7 +267,6 @@ function! s:show_errors(args, exit_val, messages) abort | ||||
|   endif | ||||
|  | ||||
|   if a:args.winnr == winnr() | ||||
|     call go#list#Populate(l:listtype, errors, join(a:args.cmd)) | ||||
|     call go#list#Window(l:listtype, len(errors)) | ||||
|     if !empty(errors) && !a:args.bang | ||||
|       call go#list#JumpToFirst(l:listtype) | ||||
| @ -250,100 +274,152 @@ function! s:show_errors(args, exit_val, messages) abort | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:parse_errors(lines) abort | ||||
|   let errors = [] | ||||
|   let paniced = 0 " signals whether all remaining lines should be included in errors. | ||||
|   let test = '' | ||||
|  | ||||
|   " NOTE(arslan): once we get JSON output everything will be easier :) | ||||
|   " https://github.com/golang/go/issues/2981 | ||||
|   for line in a:lines | ||||
|     let fatalerrors = matchlist(line, '^\(\(fatal error\|panic\):.*\)$') | ||||
|     if !empty(fatalerrors) | ||||
|       let paniced = 1 | ||||
|       call add(errors, {"text": line}) | ||||
|       continue | ||||
|     endif | ||||
| let s:efm= "" | ||||
| let s:go_test_show_name=0 | ||||
|  | ||||
|     if !paniced | ||||
|       " Matches failure lines. These lines always have zero or more leading spaces followed by '-- FAIL: ', following by the test name followed by a space the duration of the test in parentheses | ||||
|       " e.g.: | ||||
|       "   '--- FAIL: TestSomething (0.00s)' | ||||
|       let failure = matchlist(line, '^ *--- FAIL: \(.*\) (.*)$') | ||||
|       if get(g:, 'go_test_prepend_name', 0) | ||||
|         if !empty(failure) | ||||
|           let test = failure[1] . ': ' | ||||
|           continue | ||||
|         endif | ||||
|       endif | ||||
|     endif | ||||
| function! s:errorformat() abort | ||||
|   " NOTE(arslan): once we get JSON output everything will be easier :). | ||||
|   " TODO(bc): When the output is JSON, the JSON should be run through a | ||||
|   " filter to produce lines that are more easily described by errorformat. | ||||
|   "   https://github.com/golang/go/issues/2981. | ||||
|   let goroot = go#util#goroot() | ||||
|  | ||||
|     let tokens = [] | ||||
|     if paniced | ||||
|       " Matches lines in stacktraces produced by panic. The lines always have | ||||
|       " one or more leading tabs, followed by the path to the file. The file | ||||
|       " path is followed by a colon and then the line number within the file | ||||
|       " where the panic occurred. After that there's a space and hexadecimal | ||||
|       " number. | ||||
|       " | ||||
|       " e.g.: | ||||
|       "   '\t/usr/local/go/src/time.go:1313 +0x5d' | ||||
|       let tokens = matchlist(line, '^\t\+\(.\{-}\.go\):\(\d\+\) \(+0x.*\)') | ||||
|     else | ||||
|       " Matches lines produced by `go test`. When the test binary cannot be | ||||
|       " compiled, the errors will be a filename, followed by a colon, followed | ||||
|       " by the line number, followed by another colon, a space, and then the | ||||
|       " compiler error. | ||||
|       " e.g.: | ||||
|       "   'quux.go:123: undefined: foo' | ||||
|       " | ||||
|       " When the test binary can be successfully compiled, but tests fail, all | ||||
|       " lines produced by `go test` that we're interested in start with zero | ||||
|       " or more spaces (increasing depth of subtests is represented by a | ||||
|       " similar increase in the number of spaces at the start of output lines. | ||||
|       " Top level tests start with zero leading spaces). Lines that indicate | ||||
|       " test status (e.g. RUN, FAIL, PASS) start after the spaces. Lines that | ||||
|       " indicate test failure location or test log message location (e.g. | ||||
|       " "testing.T".Log) begin with the appropriate number of spaces for the | ||||
|       " current test level, followed by a tab, a filename , a colon, the line | ||||
|       " number, another colon, a space, and the failure or log message. | ||||
|       " | ||||
|       " e.g.: | ||||
|       "   '\ttime_test.go:30: Likely problem: the time zone files have not been installed.' | ||||
|       let tokens = matchlist(line, '^\%( *\t\+\)\?\(.\{-}\.go\):\(\d\+\):\s*\(.*\)') | ||||
|     endif | ||||
|   let show_name=get(g:, 'go_test_show_name', 0) | ||||
|   if s:efm != "" && s:go_test_show_name == show_name | ||||
|     return s:efm | ||||
|   endif | ||||
|   let s:go_test_show_name = show_name | ||||
|  | ||||
|     if !empty(tokens) " Check whether the line may refer to a file. | ||||
|       " strip endlines of form ^M | ||||
|       let out = substitute(tokens[3], '\r$', '', '') | ||||
|       let file = fnamemodify(tokens[1], ':p') | ||||
|   " each level of test indents the test output 4 spaces. Capturing groups | ||||
|   " (e.g. \(\)) cannot be used in an errorformat, but non-capturing groups can | ||||
|   " (e.g. \%(\)). | ||||
|   let indent = '%\\%(    %\\)%#' | ||||
|  | ||||
|       " Preserve the line when the filename is not readable. This is an | ||||
|       " unusual case, but possible; any test that produces lines that match | ||||
|       " the pattern used in the matchlist assigned to tokens is a potential | ||||
|       " source of this condition. For instance, github.com/golang/mock/gomock | ||||
|       " will sometimes produce lines that satisfy this condition. | ||||
|       if !filereadable(file) | ||||
|         call add(errors, {"text": test . line}) | ||||
|         continue | ||||
|       endif | ||||
|   " match compiler errors | ||||
|   let format = "%f:%l:%c: %m" | ||||
|  | ||||
|       call add(errors, { | ||||
|             \ "filename" : file, | ||||
|             \ "lnum"     : tokens[2], | ||||
|             \ "text"     : test . out, | ||||
|             \ }) | ||||
|     elseif paniced | ||||
|       call add(errors, {"text": line}) | ||||
|     elseif !empty(errors) | ||||
|       " Preserve indented lines. This comes up especially with multi-line test output. | ||||
|       if match(line, '^ *\t\+') >= 0 | ||||
|         call add(errors, {"text": line}) | ||||
|       endif | ||||
|     endif | ||||
|   endfor | ||||
|   " ignore `go test -v` output for starting tests | ||||
|   let format .= ",%-G=== RUN   %.%#" | ||||
|   " ignore `go test -v` output for passing tests | ||||
|   let format .= ",%-G" . indent . "--- PASS: %.%#" | ||||
|  | ||||
|   return errors | ||||
|   " Match failure lines. | ||||
|   " | ||||
|   " Test failures start with '--- FAIL: ', followed by the test name followed | ||||
|   " by a space the duration of the test in parentheses | ||||
|   " | ||||
|   " e.g.: | ||||
|   "   '--- FAIL: TestSomething (0.00s)' | ||||
|   if show_name | ||||
|     let format .= ",%G" . indent . "--- FAIL: %m (%.%#)" | ||||
|   else | ||||
|     let format .= ",%-G" . indent . "--- FAIL: %.%#" | ||||
|   endif | ||||
|  | ||||
|   " Matches test output lines. | ||||
|   " | ||||
|   " All test output lines start with the test indentation and a tab, followed | ||||
|   " by the filename, a colon, the line number, another colon, a space, and the | ||||
|   " message. e.g.: | ||||
|   "   '\ttime_test.go:30: Likely problem: the time zone files have not been installed.' | ||||
|   let format .= ",%A" . indent . "%\\t%\\+%f:%l: %m" | ||||
|   " also match lines that don't have a message (i.e. the message begins with a | ||||
|   " newline or is the empty string): | ||||
|   " e.g.: | ||||
|   "     t.Errorf("\ngot %v; want %v", actual, expected) | ||||
|   "     t.Error("") | ||||
|   let format .= ",%A" . indent . "%\\t%\\+%f:%l: " | ||||
|  | ||||
|   " Match the 2nd and later lines of multi-line output. These lines are | ||||
|   " indented the number of spaces for the level of nesting of the test, | ||||
|   " followed by two tabs, followed by the message. | ||||
|   " | ||||
|   " Treat these lines as if they are stand-alone lines of output by using %G. | ||||
|   " It would also be valid to treat these lines as if they were the | ||||
|   " continuation of a multi-line error by using %C instead of %G, but that | ||||
|   " would also require that all test errors using a %A or %E modifier to | ||||
|   " indicate that they're multiple lines of output, but in that case the lines | ||||
|   " get concatenated in the quickfix list, which is not what users typically | ||||
|   " want when writing a newline into their test output. | ||||
|   let format .= ",%G" . indent . "%\\t%\\{2}%m" | ||||
|  | ||||
|   " set the format for panics. | ||||
|  | ||||
|   " handle panics from test timeouts | ||||
|   let format .= ",%+Gpanic: test timed out after %.%\\+" | ||||
|  | ||||
|   " handle non-timeout panics | ||||
|   " In addition to 'panic', check for 'fatal error' to support older versions | ||||
|   " of Go that used 'fatal error'. | ||||
|   " | ||||
|   " Panics come in two flavors. When the goroutine running the tests panics, | ||||
|   " `go test` recovers and tries to exit more cleanly. In that case, the panic | ||||
|   " message is suffixed with ' [recovered]'. If the panic occurs in a | ||||
|   " different goroutine, it will not be suffixed with ' [recovered]'. | ||||
|   let format .= ",%+Afatal error: %.%# [recovered]" | ||||
|   let format .= ",%+Apanic: %.%# [recovered]" | ||||
|   let format .= ",%+Afatal error: %.%#" | ||||
|   let format .= ",%+Apanic: %.%#" | ||||
|  | ||||
|   " Match address lines in stacktraces produced by panic. | ||||
|   " | ||||
|   " Address lines in the stack trace have leading tabs, followed by the path | ||||
|   " to the file. The file path is followed by a colon and then the line number | ||||
|   " within the file where the panic occurred. After that there's a space and | ||||
|   " hexadecimal number. | ||||
|   " | ||||
|   " e.g.: | ||||
|   "   '\t/usr/local/go/src/time.go:1313 +0x5d' | ||||
|  | ||||
|   " panicaddress, and readyaddress are identical except for | ||||
|   " panicaddress sets the filename and line number. | ||||
|   let panicaddress = "%\\t%f:%l +0x%[0-9A-Fa-f]%\\+" | ||||
|   let readyaddress = "%\\t%\\f%\\+:%\\d%\\+ +0x%[0-9A-Fa-f]%\\+" | ||||
|   " stdlib address is identical to readyaddress, except it matches files | ||||
|   " inside GOROOT. | ||||
|   let stdlibaddress = "%\\t" . goroot . "%\\f%\\+:%\\d%\\+ +0x%[0-9A-Fa-f]%\\+" | ||||
|  | ||||
|   " Match and ignore the running goroutine line. | ||||
|   let format .= ",%-Cgoroutine %\\d%\\+ [running]:" | ||||
|   " Match address lines that refer to stdlib, but consider them informational | ||||
|   " only. This is to catch the lines after the first address line in the | ||||
|   " running goroutine of a panic stack trace. Ideally, this wouldn't be | ||||
|   " necessary, but when a panic happens in the goroutine running a test, it's | ||||
|   " recovered and another panic is created, so the stack trace actually has | ||||
|   " the line that caused the original panic a couple of addresses down the | ||||
|   " stack. | ||||
|   let format .= ",%-C" . stdlibaddress | ||||
|   " Match address lines in the first matching goroutine. This means the panic | ||||
|   " message will only be shown as the error message in the first address of | ||||
|   " the running goroutine's stack. | ||||
|   let format .= ",%Z" . panicaddress | ||||
|  | ||||
|   " Match and ignore panic address without being part of a multi-line message. | ||||
|   " This is to catch those lines that come after the top most non-standard | ||||
|   " library line in stack traces. | ||||
|   let format .= ",%-G" . readyaddress | ||||
|  | ||||
|   " Match and ignore exit status lines (produced when go test panics) whether | ||||
|   " part of a multi-line message or not, because these lines sometimes come | ||||
|   " before and sometimes after panic stacktraces. | ||||
|   let format .= ",%-Cexit status %[0-9]%\\+" | ||||
|   "let format .= ",exit status %[0-9]%\\+" | ||||
|  | ||||
|   " Match and ignore exit failure lines whether part of a multi-line message | ||||
|   " or not, because these lines sometimes come before and sometimes after | ||||
|   " panic stacktraces. | ||||
|   let format .= ",%-CFAIL%\\t%.%#" | ||||
|   "let format .= ",FAIL%\\t%.%#" | ||||
|  | ||||
|   " Match and ignore everything else in multi-line messages. | ||||
|   let format .= ",%-C%.%#" | ||||
|   " Match and ignore everything else not in a multi-line message: | ||||
|   let format .= ",%-G%.%#" | ||||
|  | ||||
|   let s:efm = format | ||||
|  | ||||
|   return s:efm | ||||
| endfunction | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
							
								
								
									
										121
									
								
								sources_non_forked/vim-go/autoload/go/test_test.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								sources_non_forked/vim-go/autoload/go/test_test.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | ||||
| func! Test_GoTest() abort | ||||
|   let expected = [ | ||||
|         \ {'lnum': 12, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'log message'}, | ||||
|         \ {'lnum': 13, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'sub badness'}, | ||||
|         \ {'lnum': 15, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'badness'}, | ||||
|         \ {'lnum': 16, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'helper badness'}, | ||||
|         \ {'lnum': 20, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is an error'}, | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'}, | ||||
|         \ {'lnum': 21, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ''}, | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is another error'}, | ||||
|         \ {'lnum': 26, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is a sub-test error'}, | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'}, | ||||
|         \ {'lnum': 6, 'bufnr': 3, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'another package badness'}, | ||||
|         \ {'lnum': 43, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: worst ever [recovered]'} | ||||
|       \ ] | ||||
|   call s:test('play/play_test.go', expected) | ||||
| endfunc | ||||
|  | ||||
| func! Test_GoTestConcurrentPanic() | ||||
|   let expected = [ | ||||
|         \ {'lnum': 50, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: concurrent fail'} | ||||
|       \ ] | ||||
|   call s:test('play/play_test.go', expected, "-run", "TestConcurrentPanic") | ||||
| endfunc | ||||
|  | ||||
| func! Test_GoTestVerbose() abort | ||||
|   let expected = [ | ||||
|         \ {'lnum': 12, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'log message'}, | ||||
|         \ {'lnum': 13, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'sub badness'}, | ||||
|         \ {'lnum': 15, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'badness'}, | ||||
|         \ {'lnum': 16, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'helper badness'}, | ||||
|         \ {'lnum': 20, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is an error'}, | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'}, | ||||
|         \ {'lnum': 21, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ''}, | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is another error'}, | ||||
|         \ {'lnum': 26, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'this is a sub-test error'}, | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'and a second line, too'}, | ||||
|         \ {'lnum': 32, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'goodness'}, | ||||
|         \ {'lnum': 6, 'bufnr': 3, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'another package badness'}, | ||||
|         \ {'lnum': 43, 'bufnr': 2, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: worst ever [recovered]'} | ||||
|       \ ] | ||||
|   call s:test('play/play_test.go', expected, "-v") | ||||
| endfunc | ||||
|  | ||||
| func! Test_GoTestCompilerError() abort | ||||
|   let expected = [ | ||||
|         \ {'lnum': 6, 'bufnr': 6, 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'syntax error: unexpected newline, expecting comma or )'} | ||||
|       \ ] | ||||
|   call s:test('compilerror/compilerror_test.go', expected) | ||||
| endfunc | ||||
|  | ||||
| func! Test_GoTestTimeout() abort | ||||
|   let expected = [ | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'panic: test timed out after 500ms'} | ||||
|       \ ] | ||||
|  | ||||
|   let g:go_test_timeout="500ms" | ||||
|   call s:test('timeout/timeout_test.go', expected) | ||||
|   unlet g:go_test_timeout | ||||
| endfunc | ||||
|  | ||||
| func! Test_GoTestShowName() abort | ||||
|   let expected = [ | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestHelloWorld'}, | ||||
|         \ {'lnum': 6, 'bufnr': 9, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'so long'}, | ||||
|         \ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'TestHelloWorld/sub'}, | ||||
|         \ {'lnum': 9, 'bufnr': 9, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'thanks for all the fish'}, | ||||
|       \ ] | ||||
|  | ||||
|   let g:go_test_show_name=1 | ||||
|   call s:test('showname/showname_test.go', expected) | ||||
|   let g:go_test_show_name=0 | ||||
| endfunc | ||||
|  | ||||
| func! s:test(file, expected, ...) abort | ||||
|   if has('nvim') | ||||
|     " nvim mostly shows test errors correctly, but the the expected errors are | ||||
|     " slightly different; buffer numbers are not the same and stderr doesn't | ||||
|     " seem to be redirected to the job, so the lines from the panic aren't in | ||||
|     " the output to be parsed, and hence are not in the quickfix lists. Once | ||||
|     " those two issues are resolved, this early return should be removed so | ||||
|     " the tests will run for Neovim, too. | ||||
|     return | ||||
|   endif | ||||
|   let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/test' | ||||
|   silent exe 'e ' . $GOPATH . '/src/' . a:file | ||||
|  | ||||
|   " clear the quickfix lists | ||||
|   call setqflist([], 'r') | ||||
|  | ||||
|   let args = [1,0] | ||||
|   if a:0 | ||||
|     let args += a:000 | ||||
|   endif | ||||
|  | ||||
|   " run the tests | ||||
|   call call(function('go#test#Test'), args) | ||||
|  | ||||
|   let actual = getqflist() | ||||
|   let start = reltime() | ||||
|   while len(actual) == 0 && reltimefloat(reltime(start)) < 10 | ||||
|     sleep 100m | ||||
|     let actual = getqflist() | ||||
|   endwhile | ||||
|  | ||||
|   for item in actual | ||||
|     let item.text = s:normalize_durations(item.text) | ||||
|   endfor | ||||
|  | ||||
|   for item in a:expected | ||||
|     let item.text = s:normalize_durations(item.text) | ||||
|   endfor | ||||
|  | ||||
|   call gotest#assert_quickfix(actual, a:expected) | ||||
| endfunc | ||||
|  | ||||
| func! s:normalize_durations(str) abort | ||||
|   return substitute(a:str, '[0-9]\+\(\.[0-9]\+\)\?s', '0.000s', 'g') | ||||
| endfunc | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
		Reference in New Issue
	
	Block a user
	 Amir Salihefendic
					Amir Salihefendic