1
0
mirror of https://github.com/golang/go synced 2024-11-18 20:14:43 -07:00
go/internal/lsp/cmd/cmd_test.go
Ian Cottrell 3b6f9c0030 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>
2019-05-03 18:56:57 +00:00

146 lines
3.5 KiB
Go

// Copyright 2019 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 cmd_test
import (
"bytes"
"io/ioutil"
"os"
"strings"
"testing"
"unicode"
"unicode/utf8"
"golang.org/x/tools/go/packages/packagestest"
"golang.org/x/tools/internal/lsp/cmd"
"golang.org/x/tools/internal/lsp/tests"
)
var isRace = false
type runner struct {
data *tests.Data
app *cmd.Application
}
func TestCommandLine(t *testing.T) {
packagestest.TestAll(t, testCommandLine)
}
func testCommandLine(t *testing.T, exporter packagestest.Exporter) {
data := tests.Load(t, exporter, "../testdata")
defer data.Exported.Cleanup()
r := &runner{
data: data,
app: &cmd.Application{
Config: *data.Exported.Config,
},
}
tests.Run(t, r, data)
}
func (r *runner) Completion(t *testing.T, data tests.Completions, snippets tests.CompletionSnippets, items tests.CompletionItems) {
//TODO: add command line completions tests when it works
}
func (r *runner) Highlight(t *testing.T, data tests.Highlights) {
//TODO: add command line highlight tests when it works
}
func (r *runner) Symbol(t *testing.T, data tests.Symbols) {
//TODO: add command line symbol tests when it works
}
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 {
t.Fatal(err)
}
old := os.Stdout
defer func() {
os.Stdout = old
out.Close()
r.Close()
}()
os.Stdout = out
f()
out.Close()
data, err := ioutil.ReadAll(r)
if err != nil {
t.Fatal(err)
}
return string(data)
}
// normalizePaths replaces all paths present in s with just the fragment portion
// this is used to make golden files not depend on the temporary paths of the files
func (r *runner) normalizePaths(s string) string {
type entry struct {
path string
index int
}
match := make([]entry, len(r.data.Exported.Modules))
// collect the initial state of all the matchers
for i, m := range r.data.Exported.Modules {
// any random file will do, we collect the first one only
for f := range m.Files {
path := strings.TrimSuffix(r.data.Exported.File(m.Name, f), f)
index := strings.Index(s, path)
match[i] = entry{path, index}
break
}
}
// result should be the same or shorter than the input
buf := bytes.NewBuffer(make([]byte, 0, len(s)))
last := 0
for {
// find the nearest path match to the start of the buffer
next := -1
nearest := len(s)
for i, c := range match {
if c.index >= 0 && nearest > c.index {
nearest = c.index
next = i
}
}
// if there are no matches, we copy the rest of the string and are done
if next < 0 {
buf.WriteString(s[last:])
return buf.String()
}
// we have a match
n := &match[next]
// copy up to the start of the match
buf.WriteString(s[last:n.index])
// skip over the non fragment prefix
last = n.index + len(n.path)
// now try to convert the fragment part
for last < len(s) {
r, size := utf8.DecodeRuneInString(s[last:])
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '/' {
buf.WriteRune(r)
} else if r == '\\' {
buf.WriteRune('/')
} else {
break
}
last += size
}
// see what the next match for this path is
n.index = strings.Index(s[last:], n.path)
if n.index >= 0 {
n.index += last
}
}
}