Bumping k8s version to 1.13.0-beta.1

This commit is contained in:
Cheng Xing
2018-11-19 14:10:50 -08:00
parent 01bd7f356e
commit e2f1bdc372
633 changed files with 11189 additions and 126194 deletions

View File

@@ -7,6 +7,7 @@ package lsp
import (
"bytes"
"context"
"fmt"
"go/token"
"os/exec"
"path/filepath"
@@ -27,6 +28,10 @@ func TestLSP(t *testing.T) {
func testLSP(t *testing.T, exporter packagestest.Exporter) {
const dir = "testdata"
const expectedCompletionsCount = 4
const expectedDiagnosticsCount = 9
const expectedFormatCount = 3
const expectedDefinitionsCount = 16
files := packagestest.MustCopyFileTree(dir)
for fragment, operation := range files {
@@ -47,9 +52,11 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
dirs := make(map[string]bool)
// collect results for certain tests
expectedDiagnostics := make(map[string][]protocol.Diagnostic)
expectedCompletions := make(map[token.Position]*protocol.CompletionItem)
expectedFormat := make(map[string]string)
expectedDiagnostics := make(diagnostics)
completionItems := make(completionItems)
expectedCompletions := make(completions)
expectedFormat := make(formats)
expectedDefinitions := make(definitions)
s := &server{
view: source.NewView(),
@@ -80,70 +87,86 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
}
// Collect any data that needs to be used by subsequent tests.
if err := exported.Expect(map[string]interface{}{
"diag": func(pos token.Position, msg string) {
collectDiagnostics(t, expectedDiagnostics, pos, msg)
},
"item": func(pos token.Position, label, detail, kind string) {
collectCompletionItems(expectedCompletions, pos, label, detail, kind)
},
"format": func(pos token.Position) {
collectFormat(expectedFormat, pos)
},
"diag": expectedDiagnostics.collect,
"item": completionItems.collect,
"complete": expectedCompletions.collect,
"format": expectedFormat.collect,
"godef": expectedDefinitions.collect,
}); err != nil {
t.Fatal(err)
}
// test completion
testCompletion(t, exported, s, expectedCompletions)
t.Run("Completion", func(t *testing.T) {
t.Helper()
if len(expectedCompletions) != expectedCompletionsCount {
t.Errorf("got %v completions expected %v", len(expectedCompletions), expectedCompletionsCount)
}
expectedCompletions.test(t, exported, s, completionItems)
})
// test diagnostics
var dirList []string
for dir := range dirs {
dirList = append(dirList, dir)
}
exported.Config.Mode = packages.LoadFiles
pkgs, err := packages.Load(exported.Config, dirList...)
if err != nil {
t.Fatal(err)
}
testDiagnostics(t, s.view, pkgs, expectedDiagnostics)
t.Run("Diagnostics", func(t *testing.T) {
t.Helper()
diagnosticsCount := expectedDiagnostics.test(t, exported, s.view, dirs)
if diagnosticsCount != expectedDiagnosticsCount {
t.Errorf("got %v diagnostics expected %v", diagnosticsCount, expectedDiagnosticsCount)
}
})
// test format
testFormat(t, s, expectedFormat)
t.Run("Format", func(t *testing.T) {
t.Helper()
if len(expectedFormat) != expectedFormatCount {
t.Errorf("got %v formats expected %v", len(expectedFormat), expectedFormatCount)
}
expectedFormat.test(t, s)
})
t.Run("Definitions", func(t *testing.T) {
t.Helper()
if len(expectedDefinitions) != expectedDefinitionsCount {
t.Errorf("got %v definitions expected %v", len(expectedDefinitions), expectedDefinitionsCount)
}
expectedDefinitions.test(t, s)
})
}
func testCompletion(t *testing.T, exported *packagestest.Exported, s *server, wants map[token.Position]*protocol.CompletionItem) {
if err := exported.Expect(map[string]interface{}{
"complete": func(src token.Position, expected []token.Position) {
var want []protocol.CompletionItem
for _, pos := range expected {
want = append(want, *wants[pos])
}
list, err := s.Completion(context.Background(), &protocol.CompletionParams{
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
TextDocument: protocol.TextDocumentIdentifier{
URI: protocol.DocumentURI(source.ToURI(src.Filename)),
},
Position: protocol.Position{
Line: float64(src.Line - 1),
Character: float64(src.Column - 1),
},
type diagnostics map[string][]protocol.Diagnostic
type completionItems map[token.Pos]*protocol.CompletionItem
type completions map[token.Position][]token.Pos
type formats map[string]string
type definitions map[protocol.Location]protocol.Location
func (c completions) test(t *testing.T, exported *packagestest.Exported, s *server, items completionItems) {
for src, itemList := range c {
var want []protocol.CompletionItem
for _, pos := range itemList {
want = append(want, *items[pos])
}
list, err := s.Completion(context.Background(), &protocol.CompletionParams{
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
TextDocument: protocol.TextDocumentIdentifier{
URI: protocol.DocumentURI(source.ToURI(src.Filename)),
},
})
if err != nil {
t.Fatal(err)
}
got := list.Items
if equal := reflect.DeepEqual(want, got); !equal {
t.Errorf("completion failed for %s:%v:%v: (expected: %v), (got: %v)", filepath.Base(src.Filename), src.Line, src.Column, want, got)
}
},
}); err != nil {
t.Fatal(err)
Position: protocol.Position{
Line: float64(src.Line - 1),
Character: float64(src.Column - 1),
},
},
})
if err != nil {
t.Fatal(err)
}
got := list.Items
if equal := reflect.DeepEqual(want, got); !equal {
t.Errorf("completion failed for %s:%v:%v: (expected: %v), (got: %v)", filepath.Base(src.Filename), src.Line, src.Column, want, got)
}
}
}
func collectCompletionItems(expectedCompletions map[token.Position]*protocol.CompletionItem, pos token.Position, label, detail, kind string) {
func (c completions) collect(src token.Position, expected []token.Pos) {
c[src] = expected
}
func (i completionItems) collect(pos token.Pos, label, detail, kind string) {
var k protocol.CompletionItemKind
switch kind {
case "struct":
@@ -163,14 +186,26 @@ func collectCompletionItems(expectedCompletions map[token.Position]*protocol.Com
case "method":
k = protocol.MethodCompletion
}
expectedCompletions[pos] = &protocol.CompletionItem{
i[pos] = &protocol.CompletionItem{
Label: label,
Detail: detail,
Kind: float64(k),
}
}
func testDiagnostics(t *testing.T, v *source.View, pkgs []*packages.Package, wants map[string][]protocol.Diagnostic) {
func (d diagnostics) test(t *testing.T, exported *packagestest.Exported, v *source.View, dirs map[string]bool) int {
// first trigger a load to get the diagnostics
var dirList []string
for dir := range dirs {
dirList = append(dirList, dir)
}
exported.Config.Mode = packages.LoadFiles
pkgs, err := packages.Load(exported.Config, dirList...)
if err != nil {
t.Fatal(err)
}
// and now see if they match the expected ones
count := 0
for _, pkg := range pkgs {
for _, filename := range pkg.GoFiles {
f := v.GetFile(source.ToURI(filename))
@@ -182,15 +217,26 @@ func testDiagnostics(t *testing.T, v *source.View, pkgs []*packages.Package, wan
sort.Slice(got, func(i int, j int) bool {
return got[i].Range.Start.Line < got[j].Range.Start.Line
})
want := wants[filename]
want := d[filename]
if equal := reflect.DeepEqual(want, got); !equal {
t.Errorf("diagnostics failed for %s: (expected: %v), (got: %v)", filepath.Base(filename), want, got)
msg := &bytes.Buffer{}
fmt.Fprintf(msg, "diagnostics failed for %s: expected:\n", filepath.Base(filename))
for _, d := range want {
fmt.Fprintf(msg, " %v\n", d)
}
fmt.Fprintf(msg, "got:\n")
for _, d := range got {
fmt.Fprintf(msg, " %v\n", d)
}
t.Error(msg.String())
}
count += len(want)
}
}
return count
}
func collectDiagnostics(t *testing.T, expectedDiagnostics map[string][]protocol.Diagnostic, pos token.Position, msg string) {
func (d diagnostics) collect(pos token.Position, msg string) {
line := float64(pos.Line - 1)
col := float64(pos.Column - 1)
want := protocol.Diagnostic{
@@ -208,15 +254,11 @@ func collectDiagnostics(t *testing.T, expectedDiagnostics map[string][]protocol.
Source: "LSP",
Message: msg,
}
if _, ok := expectedDiagnostics[pos.Filename]; ok {
expectedDiagnostics[pos.Filename] = append(expectedDiagnostics[pos.Filename], want)
} else {
t.Errorf("unexpected filename: %v", pos.Filename)
}
d[pos.Filename] = append(d[pos.Filename], want)
}
func testFormat(t *testing.T, s *server, expectedFormat map[string]string) {
for filename, gofmted := range expectedFormat {
func (f formats) test(t *testing.T, s *server) {
for filename, gofmted := range f {
edits, err := s.Formatting(context.Background(), &protocol.DocumentFormattingParams{
TextDocument: protocol.TextDocumentIdentifier{
URI: protocol.DocumentURI(source.ToURI(filename)),
@@ -235,10 +277,38 @@ func testFormat(t *testing.T, s *server, expectedFormat map[string]string) {
}
}
func collectFormat(expectedFormat map[string]string, pos token.Position) {
func (f formats) collect(pos token.Position) {
cmd := exec.Command("gofmt", pos.Filename)
stdout := bytes.NewBuffer(nil)
cmd.Stdout = stdout
cmd.Run() // ignore error, sometimes we have intentionally ungofmt-able files
expectedFormat[pos.Filename] = stdout.String()
f[pos.Filename] = stdout.String()
}
func (d definitions) test(t *testing.T, s *server) {
for src, target := range d {
locs, err := s.Definition(context.Background(), &protocol.TextDocumentPositionParams{
TextDocument: protocol.TextDocumentIdentifier{
URI: src.URI,
},
Position: src.Range.Start,
})
if err != nil {
t.Fatal(err)
}
if len(locs) != 1 {
t.Errorf("got %d locations for definition, expected 1", len(locs))
}
if locs[0] != target {
t.Errorf("for %v got %v want %v", src, locs[0], target)
}
}
}
func (d definitions) collect(fset *token.FileSet, src, target packagestest.Range) {
sRange := source.Range{Start: src.Start, End: src.End}
sLoc := toProtocolLocation(fset, sRange)
tRange := source.Range{Start: target.Start, End: target.End}
tLoc := toProtocolLocation(fset, tRange)
d[sLoc] = tLoc
}

View File

@@ -24,11 +24,11 @@ func fromProtocolLocation(v *source.View, loc protocol.Location) (source.Range,
}
// toProtocolLocation converts from a source range back to a protocol location.
func toProtocolLocation(v *source.View, r source.Range) protocol.Location {
tokFile := v.Config.Fset.File(r.Start)
file := v.GetFile(source.ToURI(tokFile.Name()))
func toProtocolLocation(fset *token.FileSet, r source.Range) protocol.Location {
tokFile := fset.File(r.Start)
uri := source.ToURI(tokFile.Name())
return protocol.Location{
URI: protocol.DocumentURI(file.URI),
URI: protocol.DocumentURI(uri),
Range: toProtocolRange(tokFile, r),
}
}

View File

@@ -17,9 +17,9 @@ import (
)
func (p Position) Format(f fmt.State, c rune) {
fmt.Fprintf(f, "%d", int(p.Line))
fmt.Fprintf(f, "%d", int(p.Line)+1)
if p.Character >= 0 {
fmt.Fprintf(f, ":%d", int(p.Character))
fmt.Fprintf(f, ":%d", int(p.Character)+1)
}
}
@@ -28,7 +28,7 @@ func (r Range) Format(f fmt.State, c rune) {
case r.Start == r.End || r.End.Line < 0:
fmt.Fprintf(f, "%v", r.Start)
case r.End.Line == r.Start.Line:
fmt.Fprintf(f, "%v¦%d", r.Start, int(r.End.Character))
fmt.Fprintf(f, "%v¦%d", r.Start, int(r.End.Character)+1)
default:
fmt.Fprintf(f, "%v¦%v", r.Start, r.End)
}
@@ -37,3 +37,20 @@ func (r Range) Format(f fmt.State, c rune) {
func (l Location) Format(f fmt.State, c rune) {
fmt.Fprintf(f, "%s:%v", l.URI, l.Range)
}
func (s DiagnosticSeverity) Format(f fmt.State, c rune) {
switch s {
case SeverityError:
fmt.Fprint(f, "Error")
case SeverityWarning:
fmt.Fprint(f, "Warning")
case SeverityInformation:
fmt.Fprint(f, "Information")
case SeverityHint:
fmt.Fprint(f, "Hint")
}
}
func (d Diagnostic) Format(f fmt.State, c rune) {
fmt.Fprintf(f, "%v:%v from %v at %v: %v", d.Severity, d.Code, d.Source, d.Range, d.Message)
}

View File

@@ -204,7 +204,7 @@ func (s *server) Definition(ctx context.Context, params *protocol.TextDocumentPo
if err != nil {
return nil, err
}
return []protocol.Location{toProtocolLocation(s.view, r)}, nil
return []protocol.Location{toProtocolLocation(s.view.Config.Fset, r)}, nil
}
func (s *server) TypeDefinition(context.Context, *protocol.TextDocumentPositionParams) ([]protocol.Location, error) {

View File

@@ -5,11 +5,13 @@
package source
import (
"bytes"
"context"
"fmt"
"go/ast"
"go/token"
"go/types"
"io/ioutil"
"golang.org/x/tools/go/ast/astutil"
)
@@ -43,10 +45,7 @@ func Definition(ctx context.Context, f *File, pos token.Pos) (Range, error) {
}
}
}
return Range{
Start: obj.Pos(),
End: obj.Pos() + token.Pos(len([]byte(obj.Name()))), // TODO: use real range of obj
}, nil
return objToRange(f.view.Config.Fset, obj), nil
}
// ident returns the ident plus any extra information needed
@@ -93,3 +92,30 @@ func checkIdentifier(f *ast.File, pos token.Pos) (ident, error) {
}
return result, nil
}
func objToRange(fSet *token.FileSet, obj types.Object) Range {
p := obj.Pos()
f := fSet.File(p)
pos := f.Position(p)
if pos.Column == 1 {
// Column is 1, so we probably do not have full position information
// Currently exportdata does not store the column.
// For now we attempt to read the original source and find the identifier
// within the line. If we find it we patch the column to match its offset.
// TODO: we have probably already added the full data for the file to the
// fileset, we ought to track it rather than adding it over and over again
// TODO: if we parse from source, we will never need this hack
if src, err := ioutil.ReadFile(pos.Filename); err == nil {
newF := fSet.AddFile(pos.Filename, -1, len(src))
newF.SetLinesForContent(src)
lineStart := lineStart(newF, pos.Line)
offset := newF.Offset(lineStart)
col := bytes.Index(src[offset:], []byte(obj.Name()))
p = newF.Pos(offset + col)
}
}
return Range{
Start: p,
End: p + token.Pos(len([]byte(obj.Name()))), // TODO: use real range of obj
}
}

View File

@@ -1,5 +1,3 @@
// +build go1.11
package bad
func stuff() {
@@ -14,8 +12,7 @@ type bob struct {
}
func _() {
var q int
_ = &bob{
f: q, //@diag("f", "unknown field f in struct literal")
f: 0, //@diag("f", "unknown field f in struct literal")
}
}

View File

@@ -1,5 +1,3 @@
// +build go1.11
package bad
func random2(y int) int {

View File

@@ -0,0 +1,11 @@
// A comment just to push the positions out
package a
type A string //@A
func Stuff() { //@Stuff
x := 5
Random2(x) //@godef("dom2", Random2)
Random() //@godef("()", Random)
}

View File

@@ -0,0 +1,23 @@
package a
func Random() int { //@Random
y := 6 + 7
return y
}
func Random2(y int) int { //@Random2,mark(RandomParamY, "y")
return y //@godef("y", RandomParamY)
}
type Pos struct {
x, y int //@mark(PosX, "x"),mark(PosY, "y")
}
func (p *Pos) Sum() int { //@mark(PosSum, "Sum")
return p.x + p.y //@godef("x", PosX)
}
func _() {
var p Pos
_ = p.Sum() //@godef("()", PosSum)
}

View File

@@ -0,0 +1,23 @@
package b
import "golang.org/x/tools/internal/lsp/godef/a"
type S1 struct { //@S1
F1 int //@mark(S1F1, "F1")
S2 //@godef("S2", S2), mark(S1S2, "S2")
a.A //@godef("A", A)
}
type S2 struct { //@S2
F1 string //@mark(S2F1, "F1")
F2 int //@mark(S2F2, "F2")
}
func Bar() {
a.Stuff() //@godef("Stuff", Stuff)
var x S1 //@godef("S1", S1)
_ = x.S2 //@godef("S2", S1S2)
_ = x.F1 //@godef("F1", S1F1)
_ = x.F2 //@godef("F2", S2F2)
_ = x.S2.F1 //@godef("F1", S2F1)
}

View File

@@ -0,0 +1,8 @@
package b
// This is the in-editor version of the file.
// The on-disk version is in c.go.saved.
var _ = S1{ //@godef("S1", S1)
F1: 99, //@godef("F1", S1F1)
}

View File

@@ -0,0 +1,7 @@
package b
// This is the on-disk version of c.go, which represents
// the in-editor version of the file.
}

View File

@@ -0,0 +1,11 @@
package broken
import "fmt"
func unclosedIf() {
if false {
var myUnclosedIf string //@myUnclosedIf
fmt.Printf("s = %v\n", myUnclosedIf) //@godef("my", myUnclosedIf)
}
//@diag(EOF, "expected ';', found 'EOF'")
//@diag(EOF, "expected '}', found 'EOF'")

View File

@@ -0,0 +1,11 @@
// +build !go1.11
// This file does not actually test anything
// on 1.10 the errors are different
package noparse_format
func what() {
// we need a diagnostic below so we have the same count as the main file
var b int //@diag("b", "b declared but not used")
if true {}
}