mirror of
https://github.com/golang/go
synced 2024-11-18 11:14:39 -07:00
internal/lsp: add document link handling for import paths to godoc
Change-Id: Ib2eef50047dfcc64110c264e77d648f959613b88 Reviewed-on: https://go-review.googlesource.com/c/tools/+/173698 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
9cb3dcf692
commit
3b6f9c0030
@ -57,6 +57,10 @@ func (r *runner) Signature(t *testing.T, data tests.Signatures) {
|
||||
//TODO: add command line signature tests when it works
|
||||
}
|
||||
|
||||
func (r *runner) Link(t *testing.T, data tests.Links) {
|
||||
//TODO: add command line link tests when it works
|
||||
}
|
||||
|
||||
func captureStdOut(t testing.TB, f func()) string {
|
||||
r, out, err := os.Pipe()
|
||||
if err != nil {
|
||||
|
@ -84,6 +84,7 @@ func (s *Server) initialize(ctx context.Context, params *protocol.InitializePara
|
||||
DocumentSymbolProvider: true,
|
||||
HoverProvider: true,
|
||||
DocumentHighlightProvider: true,
|
||||
DocumentLinkProvider: &protocol.DocumentLinkOptions{},
|
||||
SignatureHelpProvider: &protocol.SignatureHelpOptions{
|
||||
TriggerCharacters: []string{"(", ","},
|
||||
},
|
||||
|
45
internal/lsp/link.go
Normal file
45
internal/lsp/link.go
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
|
||||
func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLinkParams) ([]protocol.DocumentLink, error) {
|
||||
uri := span.NewURI(params.TextDocument.URI)
|
||||
view := s.findView(ctx, uri)
|
||||
f, m, err := newColumnMap(ctx, view, uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// find the import block
|
||||
ast := f.GetAST(ctx)
|
||||
var result []protocol.DocumentLink
|
||||
for _, imp := range ast.Imports {
|
||||
spn, err := span.NewRange(f.GetFileSet(ctx), imp.Pos(), imp.End()).Span()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rng, err := m.Range(spn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
target, err := strconv.Unquote(imp.Path.Value)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
target = "https://godoc.org/" + target
|
||||
result = append(result, protocol.DocumentLink{
|
||||
Range: rng,
|
||||
Target: target,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
@ -536,6 +536,41 @@ func diffSignatures(spn span.Span, want source.SignatureInformation, got *protoc
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *runner) Link(t *testing.T, data tests.Links) {
|
||||
for uri, wantLinks := range data {
|
||||
m := r.mapper(uri)
|
||||
gotLinks, err := r.server.DocumentLink(context.Background(), &protocol.DocumentLinkParams{
|
||||
TextDocument: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.NewURI(uri),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
links := make(map[span.Span]string, len(wantLinks))
|
||||
for _, link := range wantLinks {
|
||||
links[link.Src] = link.Target
|
||||
}
|
||||
for _, link := range gotLinks {
|
||||
spn, err := m.RangeSpan(link.Range)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if target, ok := links[spn]; ok {
|
||||
delete(links, spn)
|
||||
if target != link.Target {
|
||||
t.Errorf("for %v want %v, got %v\n", spn, link.Target, target)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("unexpected link %v:%v\n", spn, link.Target)
|
||||
}
|
||||
}
|
||||
for spn, target := range links {
|
||||
t.Errorf("missing link %v:%v\n", spn, target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *runner) mapper(uri span.URI) *protocol.ColumnMapper {
|
||||
fname, err := uri.Filename()
|
||||
if err != nil {
|
||||
|
@ -210,8 +210,8 @@ func (s *Server) ResolveCodeLens(context.Context, *protocol.CodeLens) (*protocol
|
||||
return nil, notImplemented("ResolveCodeLens")
|
||||
}
|
||||
|
||||
func (s *Server) DocumentLink(context.Context, *protocol.DocumentLinkParams) ([]protocol.DocumentLink, error) {
|
||||
return nil, nil // ignore
|
||||
func (s *Server) DocumentLink(ctx context.Context, params *protocol.DocumentLinkParams) ([]protocol.DocumentLink, error) {
|
||||
return s.documentLink(ctx, params)
|
||||
}
|
||||
|
||||
func (s *Server) ResolveDocumentLink(context.Context, *protocol.DocumentLink) (*protocol.DocumentLink, error) {
|
||||
|
12
internal/lsp/testdata/links/links.go
vendored
Normal file
12
internal/lsp/testdata/links/links.go
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
package links
|
||||
|
||||
import (
|
||||
"fmt" //@link(re`".*"`,"https://godoc.org/fmt")
|
||||
|
||||
"golang.org/x/tools/internal/lsp/foo" //@link(re`".*"`,"https://godoc.org/golang.org/x/tools/internal/lsp/foo")
|
||||
)
|
||||
|
||||
var (
|
||||
_ fmt.Formatter
|
||||
_ foo.StructFoo
|
||||
)
|
@ -36,6 +36,7 @@ const (
|
||||
ExpectedSymbolsCount = 1
|
||||
ExpectedSignaturesCount = 19
|
||||
ExpectedCompletionSnippetCount = 9
|
||||
ExpectedLinksCount = 2
|
||||
)
|
||||
|
||||
const (
|
||||
@ -57,6 +58,7 @@ type Highlights map[string][]span.Span
|
||||
type Symbols map[span.URI][]source.Symbol
|
||||
type SymbolsChildren map[string][]source.Symbol
|
||||
type Signatures map[span.Span]source.SignatureInformation
|
||||
type Links map[span.URI][]Link
|
||||
|
||||
type Data struct {
|
||||
Config packages.Config
|
||||
@ -71,6 +73,7 @@ type Data struct {
|
||||
Symbols Symbols
|
||||
symbolsChildren SymbolsChildren
|
||||
Signatures Signatures
|
||||
Links Links
|
||||
|
||||
t testing.TB
|
||||
fragments map[string]string
|
||||
@ -85,6 +88,7 @@ type Tests interface {
|
||||
Highlight(*testing.T, Highlights)
|
||||
Symbol(*testing.T, Symbols)
|
||||
Signature(*testing.T, Signatures)
|
||||
Link(*testing.T, Links)
|
||||
}
|
||||
|
||||
type Definition struct {
|
||||
@ -101,6 +105,11 @@ type CompletionSnippet struct {
|
||||
PlaceholderSnippet string
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
Src span.Span
|
||||
Target string
|
||||
}
|
||||
|
||||
func Load(t testing.TB, exporter packagestest.Exporter, dir string) *Data {
|
||||
t.Helper()
|
||||
|
||||
@ -114,6 +123,7 @@ func Load(t testing.TB, exporter packagestest.Exporter, dir string) *Data {
|
||||
Symbols: make(Symbols),
|
||||
symbolsChildren: make(SymbolsChildren),
|
||||
Signatures: make(Signatures),
|
||||
Links: make(Links),
|
||||
|
||||
t: t,
|
||||
dir: dir,
|
||||
@ -180,6 +190,7 @@ func Load(t testing.TB, exporter packagestest.Exporter, dir string) *Data {
|
||||
"symbol": data.collectSymbols,
|
||||
"signature": data.collectSignatures,
|
||||
"snippet": data.collectCompletionSnippets,
|
||||
"link": data.collectLinks,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -264,6 +275,18 @@ func Run(t *testing.T, tests Tests, data *Data) {
|
||||
}
|
||||
tests.Signature(t, data.Signatures)
|
||||
})
|
||||
|
||||
t.Run("Links", func(t *testing.T) {
|
||||
t.Helper()
|
||||
linksCount := 0
|
||||
for _, want := range data.Links {
|
||||
linksCount += len(want)
|
||||
}
|
||||
if linksCount != ExpectedLinksCount {
|
||||
t.Errorf("got %v links expected %v", linksCount, ExpectedLinksCount)
|
||||
}
|
||||
tests.Link(t, data.Links)
|
||||
})
|
||||
}
|
||||
|
||||
func (data *Data) Golden(tag string, target string, update func(golden string) error) []byte {
|
||||
@ -379,3 +402,11 @@ func (data *Data) collectCompletionSnippets(spn span.Span, item token.Pos, plain
|
||||
PlaceholderSnippet: placeholder,
|
||||
}
|
||||
}
|
||||
|
||||
func (data *Data) collectLinks(spn span.Span, link string) {
|
||||
uri := spn.URI()
|
||||
data.Links[uri] = append(data.Links[uri], Link{
|
||||
Src: spn,
|
||||
Target: link,
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user