From 4da6c80845455e9e105ef35ae32ccfd275329fd9 Mon Sep 17 00:00:00 2001 From: Billie Cleek Date: Sat, 11 Apr 2020 14:48:43 -0700 Subject: [PATCH 1/5] lsp: use structured hover content --- autoload/go/lsp.vim | 26 +++++++++++++++----------- autoload/go/lsp/message.vim | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/autoload/go/lsp.vim b/autoload/go/lsp.vim index 4826c18f33..89a07b98e7 100644 --- a/autoload/go/lsp.vim +++ b/autoload/go/lsp.vim @@ -898,15 +898,13 @@ function! go#lsp#Hover(fname, line, col, handler) abort endfunction function! s:hoverHandler(next, msg) abort dict - try - let l:content = split(a:msg.contents.value, '; ') - if len(l:content) > 1 - let l:curly = stridx(l:content[0], '{') - let l:content = extend([l:content[0][0:l:curly]], map(extend([l:content[0][l:curly+1:]], l:content[1:]), '"\t" . v:val')) - let l:content[len(l:content)-1] = '}' - endif + if a:msg is v:null || !has_key(a:msg, 'contents') + return + endif - let l:args = [l:content] + try + let l:value = json_decode(a:msg.contents.value) + let l:args = [l:value.signature] call call(a:next, l:args) catch " TODO(bc): log the message and/or show an error message. @@ -973,13 +971,19 @@ function! s:infoDefinitionHandler(next, showstatus, msg) abort dict let l:state = s:newHandlerState('') endif - let l:state.handleResult = funcref('s:hoverHandler', [a:next], l:state) + let l:state.handleResult = a:next let l:state.error = funcref('s:noop') return l:lsp.sendMessage(l:msg, l:state) endfunction -function! s:info(show, content) abort dict - let l:content = s:infoFromHoverContent(a:content) +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) diff --git a/autoload/go/lsp/message.vim b/autoload/go/lsp/message.vim index 8f128366c1..730901a278 100644 --- a/autoload/go/lsp/message.vim +++ b/autoload/go/lsp/message.vim @@ -254,7 +254,7 @@ function! go#lsp#message#ConfigurationResult(items) abort for l:item in a:items let l:config = { \ 'buildFlags': [], - \ 'hoverKind': 'NoDocumentation', + \ 'hoverKind': 'Structured', \ } let l:buildtags = go#config#BuildTags() if buildtags isnot '' From 6dfba509a40d6e548149d02e0985dd0f287e1d77 Mon Sep 17 00:00:00 2001 From: Billie Cleek Date: Sat, 11 Apr 2020 15:49:33 -0700 Subject: [PATCH 2/5] doc: use gopls for getting documentation under the cursor Fixes #2808 --- autoload/go/doc.vim | 9 +++------ autoload/go/lsp.vim | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/autoload/go/doc.vim b/autoload/go/doc.vim index 43f936bd52..ca4b44da4e 100644 --- a/autoload/go/doc.vim +++ b/autoload/go/doc.vim @@ -60,11 +60,8 @@ function! go#doc#Open(newmode, mode, ...) abort " With argument: run "godoc [arg]". if len(a:000) let [l:out, l:err] = go#util#Exec(['go', 'doc'] + a:000) - else " Without argument: run gogetdoc on cursor position. - let [l:out, l:err] = s:gogetdoc(0) - if out == -1 - return - endif + else " Without argument: use gopls to get documentation + let [l:out, l:err] = go#lsp#Doc() endif if l:err @@ -72,7 +69,7 @@ function! go#doc#Open(newmode, mode, ...) abort return endif - call s:GodocView(a:newmode, a:mode, out) + call s:GodocView(a:newmode, a:mode, l:out) endfunction function! s:GodocView(newposition, position, content) abort diff --git a/autoload/go/lsp.vim b/autoload/go/lsp.vim index 89a07b98e7..1e1d252318 100644 --- a/autoload/go/lsp.vim +++ b/autoload/go/lsp.vim @@ -911,6 +911,40 @@ function! s:hoverHandler(next, msg) abort dict endtry endfunction +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 + +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 + 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 + function! go#lsp#Info(showstatus) let l:fname = expand('%:p') let [l:line, l:col] = go#lsp#lsp#Position() From 64458ac2207cbd96c554fdfbbc51fa071b7c64f3 Mon Sep 17 00:00:00 2001 From: Billie Cleek Date: Fri, 17 Apr 2020 10:42:21 -0700 Subject: [PATCH 3/5] doc: respect arguments to :GoDocBrowser Make go#doc#OpenBrowser support :GoDocBrowser's optional argument to open the browser to the requested identifier. --- autoload/go/doc.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/go/doc.vim b/autoload/go/doc.vim index ca4b44da4e..2557af6154 100644 --- a/autoload/go/doc.vim +++ b/autoload/go/doc.vim @@ -13,7 +13,7 @@ function! go#doc#OpenBrowser(...) abort " Only supported if we have json_decode as it's not worth to parse the plain " non-json output of gogetdoc let bin_path = go#path#CheckBinPath('gogetdoc') - if !empty(bin_path) && exists('*json_decode') + if len(a:000) == 0 && !empty(bin_path) && exists('*json_decode') let [l:json_out, l:err] = s:gogetdoc(1) if l:err call go#util#EchoError(json_out) From 53bb2d653b4d78b72f11403d0e245c2845889177 Mon Sep 17 00:00:00 2001 From: Billie Cleek Date: Fri, 17 Apr 2020 11:07:14 -0700 Subject: [PATCH 4/5] doc: use gopls to get link for :GoDocBrowser Fixes #2295 --- autoload/go/doc.vim | 33 ++++++++------------------------- autoload/go/lsp.vim | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/autoload/go/doc.vim b/autoload/go/doc.vim index 2557af6154..4f5ff6794c 100644 --- a/autoload/go/doc.vim +++ b/autoload/go/doc.vim @@ -9,37 +9,20 @@ set cpo&vim let s:buf_nr = -1 function! go#doc#OpenBrowser(...) abort - " check if we have gogetdoc as it gives us more and accurate information. - " Only supported if we have json_decode as it's not worth to parse the plain - " non-json output of gogetdoc - let bin_path = go#path#CheckBinPath('gogetdoc') - if len(a:000) == 0 && !empty(bin_path) && exists('*json_decode') - let [l:json_out, l:err] = s:gogetdoc(1) + if len(a:000) == 0 + let [l:out, l:err] = go#lsp#DocLink() if l:err - call go#util#EchoError(json_out) + call go#util#EchoError(l:out) return endif - let out = json_decode(json_out) - if type(out) != type({}) - call go#util#EchoError("gogetdoc output is malformed") + if len(l:out) == 0 + call go#util#EchoWarning("could not path for doc URL") endif - let import = out["import"] - let name = out["name"] - let decl = out["decl"] + let l:godoc_url = printf('%s/%s', go#config#DocUrl(), l:out) - let godoc_url = go#config#DocUrl() - let godoc_url .= "/" . import - if decl !~ '^package' - let anchor = name - if decl =~ '^func (' - let anchor = substitute(decl, '^func ([^ ]\+ \*\?\([^)]\+\)) ' . name . '(.*', '\1', '') . "." . name - endif - let godoc_url .= "#" . anchor - endif - - call go#util#OpenBrowser(godoc_url) + call go#util#OpenBrowser(l:godoc_url) return endif @@ -52,7 +35,7 @@ function! go#doc#OpenBrowser(...) abort let exported_name = pkgs[1] " example url: https://godoc.org/github.com/fatih/set#Set - let godoc_url = go#config#DocUrl() . "/" . pkg . "#" . exported_name + let godoc_url = printf('%s/%s#%s', go#config#DocUrl(), pkg, exported_name) call go#util#OpenBrowser(godoc_url) endfunction diff --git a/autoload/go/lsp.vim b/autoload/go/lsp.vim index 1e1d252318..49c81a97d2 100644 --- a/autoload/go/lsp.vim +++ b/autoload/go/lsp.vim @@ -945,6 +945,35 @@ function! s:docFromHoverResult(msg) abort dict return [l:content, 0] endfunction +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 + +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 + endif + + let l:doc = json_decode(a:msg.contents.value) + return [l:doc.link, ''] +endfunction + function! go#lsp#Info(showstatus) let l:fname = expand('%:p') let [l:line, l:col] = go#lsp#lsp#Position() From b639fb48a175248462ee7a164e1abb4b7e2e88eb Mon Sep 17 00:00:00 2001 From: Billie Cleek Date: Fri, 17 Apr 2020 11:08:16 -0700 Subject: [PATCH 5/5] remove gogetdoc Remove gogetdoc because it is no longer used. --- autoload/go/doc.vim | 17 ----------------- plugin/go.vim | 1 - 2 files changed, 18 deletions(-) diff --git a/autoload/go/doc.vim b/autoload/go/doc.vim index 4f5ff6794c..15f3b503fe 100644 --- a/autoload/go/doc.vim +++ b/autoload/go/doc.vim @@ -161,23 +161,6 @@ function! s:GodocView(newposition, position, content) abort nnoremap [ [ endfunction -function! s:gogetdoc(json) abort - let l:cmd = [ - \ 'gogetdoc', - \ '-tags', go#config#BuildTags(), - \ '-pos', expand("%:p:gs!\\!/!") . ':#' . go#util#OffsetCursor()] - if a:json - let l:cmd += ['-json'] - endif - - if &modified - let l:cmd += ['-modified'] - return go#util#ExecInDir(l:cmd, go#util#archive()) - endif - - return go#util#ExecInDir(l:cmd) -endfunction - " returns the package and exported name. exported name might be empty. " ie: fmt and Println " ie: github.com/fatih/set and New diff --git a/plugin/go.vim b/plugin/go.vim index 8a01730d59..00d3d408dc 100644 --- a/plugin/go.vim +++ b/plugin/go.vim @@ -45,7 +45,6 @@ let s:packages = { \ 'errcheck': ['github.com/kisielk/errcheck@master'], \ 'fillstruct': ['github.com/davidrjenni/reftools/cmd/fillstruct@master'], \ 'godef': ['github.com/rogpeppe/godef@master'], - \ 'gogetdoc': ['github.com/zmb3/gogetdoc@master'], \ 'goimports': ['golang.org/x/tools/cmd/goimports@master'], \ 'golint': ['golang.org/x/lint/golint@master'], \ 'gopls': ['golang.org/x/tools/gopls@latest', {}, {'after': function('go#lsp#Restart', [])}],