internal/lsp: enable enhanced hover by default

This change removes the explicit configuration for improved
documentation on hover. We use a comment's synopsis rather than the full
comment.

However, we also add a "noDocsOnHover" setting that is used by the cmd
tests. Ultimately, no one should use this setting and we should remove
it. We leave it temporarily because the cmd tests still need work.

Change-Id: I5488eca96a729ed7edad8f59b95af163903740d6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/174378
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go
index 45ce925..8be04fd 100644
--- a/internal/lsp/cmd/cmd.go
+++ b/internal/lsp/cmd/cmd.go
@@ -273,7 +273,10 @@
 			}
 			env[l[0]] = l[1]
 		}
-		results[i] = map[string]interface{}{"env": env}
+		results[i] = map[string]interface{}{
+			"env":           env,
+			"noDocsOnHover": true,
+		}
 	}
 	return results, nil
 }
diff --git a/internal/lsp/cmd/definition_test.go b/internal/lsp/cmd/definition_test.go
index e7ba04a..0f298c4 100644
--- a/internal/lsp/cmd/definition_test.go
+++ b/internal/lsp/cmd/definition_test.go
@@ -8,7 +8,6 @@
 	"context"
 	"fmt"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"regexp"
 	"runtime"
@@ -31,14 +30,11 @@
 const (
 	plainGodef = godefMode(1 << iota)
 	jsonGoDef
-	guruGoDef
 )
 
 var godefModes = []godefMode{
 	plainGodef,
 	jsonGoDef,
-	guruGoDef,
-	jsonGoDef | guruGoDef,
 }
 
 func TestDefinitionHelpExample(t *testing.T) {
@@ -52,7 +48,7 @@
 	}
 	thisFile := filepath.Join(dir, "definition.go")
 	baseArgs := []string{"query", "definition"}
-	expect := regexp.MustCompile(`^[\w/\\:_-]+flag[/\\]flag.go:\d+:\d+-\d+: defined here as type flag.FlagSet struct{.*}$`)
+	expect := regexp.MustCompile(`(?s)^[\w/\\:_-]+flag[/\\]flag.go:\d+:\d+-\d+: defined here as FlagSet struct {.*}$`)
 	for _, query := range []string{
 		fmt.Sprintf("%v:%v:%v", thisFile, cmd.ExampleLine, cmd.ExampleColumn),
 		fmt.Sprintf("%v:#%v", thisFile, cmd.ExampleOffset)} {
@@ -66,20 +62,6 @@
 	}
 }
 
-var brokenDefinitionTests = map[string]bool{
-	// The following tests all have extra information in the description
-	"A-definition-json-guru":            true,
-	"err-definition-json-guru":          true,
-	"myUnclosedIf-definition-json-guru": true,
-	"Other-definition-json-guru":        true,
-	"RandomParamY-definition-json-guru": true,
-	"S1-definition-json-guru":           true,
-	"S2-definition-json-guru":           true,
-	"Stuff-definition-json-guru":        true,
-	"Thing-definition-json-guru":        true,
-	"Things-definition-json-guru":       true,
-}
-
 func (r *runner) Definition(t *testing.T, data tests.Definitions) {
 	for _, d := range data {
 		if d.IsType {
@@ -94,21 +76,6 @@
 				tag += "-json"
 				args = append(args, "-json")
 			}
-			if mode&guruGoDef != 0 {
-				if r.exporter.Name() != "GOPATH" {
-					//only run guru compatability tests in GOPATH mode
-					continue
-				}
-				if d.Name == "PackageFoo" {
-					//guru does not support definition on packages
-					continue
-				}
-				tag += "-guru"
-				args = append(args, "-emulate=guru")
-			}
-			if _, found := brokenDefinitionTests[tag]; found {
-				continue
-			}
 			args = append(args, "definition")
 			uri := d.Src.URI()
 			filename, err := uri.Filename()
@@ -123,35 +90,8 @@
 			if mode&jsonGoDef != 0 && runtime.GOOS == "windows" {
 				got = strings.Replace(got, "file:///", "file://", -1)
 			}
-			if mode&guruGoDef == 0 {
-				expect := string(r.data.Golden(tag, filename, func() ([]byte, error) {
-					return []byte(got), nil
-				}))
-				if got != expect {
-					t.Errorf("definition %v failed with %#v expected:\n%s\ngot:\n%s", tag, args, expect, got)
-				}
-				continue
-			}
-			guruArgs := []string{}
-			if mode&jsonGoDef != 0 {
-				guruArgs = append(guruArgs, "-json")
-			}
-			guruArgs = append(guruArgs, "definition", fmt.Sprint(d.Src))
 			expect := strings.TrimSpace(string(r.data.Golden(tag, filename, func() ([]byte, error) {
-				cmd := exec.Command("guru", guruArgs...)
-				cmd.Env = r.data.Exported.Config.Env
-				out, _ := cmd.Output()
-				if err != nil {
-					if _, ok := err.(*exec.ExitError); !ok {
-						return nil, fmt.Errorf("Could not run guru %v: %v\n%s", guruArgs, err, out)
-					}
-				}
-				result := normalizePaths(r.data, string(out))
-				// guru sometimes puts the full package path in type names, but we don't
-				if mode&jsonGoDef == 0 && d.Name != "AImport" {
-					result = strings.Replace(result, "golang.org/x/tools/internal/lsp/godef/", "", -1)
-				}
-				return []byte(result), nil
+				return []byte(got), nil
 			})))
 			if expect != "" && !strings.HasPrefix(got, expect) {
 				t.Errorf("definition %v failed with %#v expected:\n%q\ngot:\n%q", tag, args, expect, got)
diff --git a/internal/lsp/general.go b/internal/lsp/general.go
index 38f9b9c..b23d7d5 100644
--- a/internal/lsp/general.go
+++ b/internal/lsp/general.go
@@ -169,9 +169,9 @@
 	if usePlaceholders, ok := c["usePlaceholders"].(bool); ok {
 		s.usePlaceholders = usePlaceholders
 	}
-	// Check if enhancedHover is enabled.
-	if enhancedHover, ok := c["enhancedHover"].(bool); ok {
-		s.enhancedHover = enhancedHover
+	// Check if user has disabled documentation on hover.
+	if noDocsOnHover, ok := c["noDocsOnHover"].(bool); ok {
+		s.noDocsOnHover = noDocsOnHover
 	}
 	return nil
 }
diff --git a/internal/lsp/hover.go b/internal/lsp/hover.go
index a3d66aa..f053b9d 100644
--- a/internal/lsp/hover.go
+++ b/internal/lsp/hover.go
@@ -32,7 +32,7 @@
 	if err != nil {
 		return nil, err
 	}
-	hover, err := ident.Hover(ctx, nil, s.enhancedHover, s.preferredContentFormat == protocol.Markdown)
+	hover, err := ident.Hover(ctx, nil, s.preferredContentFormat == protocol.Markdown, !s.noDocsOnHover)
 	if err != nil {
 		return nil, err
 	}
diff --git a/internal/lsp/server.go b/internal/lsp/server.go
index 3ccd7f5..7424ba3 100644
--- a/internal/lsp/server.go
+++ b/internal/lsp/server.go
@@ -73,7 +73,7 @@
 	// Configurations.
 	// TODO(rstambler): Separate these into their own struct?
 	usePlaceholders               bool
-	enhancedHover                 bool
+	noDocsOnHover                 bool
 	insertTextFormat              protocol.InsertTextFormat
 	configurationSupported        bool
 	dynamicConfigurationSupported bool
diff --git a/internal/lsp/source/hover.go b/internal/lsp/source/hover.go
index ede27af..931489a 100644
--- a/internal/lsp/source/hover.go
+++ b/internal/lsp/source/hover.go
@@ -8,6 +8,7 @@
 	"context"
 	"fmt"
 	"go/ast"
+	"go/doc"
 	"go/format"
 	"go/token"
 	"go/types"
@@ -17,7 +18,7 @@
 // formatter returns the a hover value formatted with its documentation.
 type formatter func(interface{}, *ast.CommentGroup) (string, error)
 
-func (i *IdentifierInfo) Hover(ctx context.Context, qf types.Qualifier, enhancedHover, markdownSupported bool) (string, error) {
+func (i *IdentifierInfo) Hover(ctx context.Context, qf types.Qualifier, markdownSupported, wantComments bool) (string, error) {
 	file := i.File.GetAST(ctx)
 	if qf == nil {
 		pkg := i.File.GetPackage(ctx)
@@ -25,21 +26,21 @@
 	}
 	var b strings.Builder
 	f := func(x interface{}, c *ast.CommentGroup) (string, error) {
+		if !wantComments {
+			c = nil
+		}
 		return writeHover(x, i.File.GetFileSet(ctx), &b, c, markdownSupported, qf)
 	}
 	obj := i.Declaration.Object
-	// TODO(rstambler): Remove this configuration when hover behavior is stable.
-	if enhancedHover {
-		switch node := i.Declaration.Node.(type) {
-		case *ast.GenDecl:
-			switch obj := obj.(type) {
-			case *types.TypeName, *types.Var, *types.Const, *types.Func:
-				return formatGenDecl(node, obj, obj.Type(), f)
-			}
-		case *ast.FuncDecl:
-			if _, ok := obj.(*types.Func); ok {
-				return f(obj, node.Doc)
-			}
+	switch node := i.Declaration.Node.(type) {
+	case *ast.GenDecl:
+		switch obj := obj.(type) {
+		case *types.TypeName, *types.Var, *types.Const, *types.Func:
+			return formatGenDecl(node, obj, obj.Type(), f)
+		}
+	case *ast.FuncDecl:
+		if _, ok := obj.(*types.Func); ok {
+			return f(obj, node.Doc)
 		}
 	}
 	return f(obj, nil)
@@ -70,8 +71,8 @@
 	// Handle types.
 	switch spec := spec.(type) {
 	case *ast.TypeSpec:
-		// If multiple types are declared in the same block.
 		if len(node.Specs) > 1 {
+			// If multiple types are declared in the same block.
 			return f(spec.Type, spec.Doc)
 		} else {
 			return f(spec, node.Doc)
@@ -97,7 +98,7 @@
 	// If we have a struct or interface declaration,
 	// we need to match the object to the corresponding field or method.
 	if fieldList != nil {
-		for i := 0; i < fieldList.NumFields(); i++ {
+		for i := 0; i < len(fieldList.List); i++ {
 			field := fieldList.List[i]
 			if field.Pos() <= obj.Pos() && obj.Pos() <= field.End() {
 				if field.Doc.Text() != "" {
@@ -115,7 +116,8 @@
 // writeHover writes the hover for a given node and its documentation.
 func writeHover(x interface{}, fset *token.FileSet, b *strings.Builder, c *ast.CommentGroup, markdownSupported bool, qf types.Qualifier) (string, error) {
 	if c != nil {
-		b.WriteString(c.Text())
+		// TODO(rstambler): Improve conversion from Go docs to markdown.
+		b.WriteString(doc.Synopsis(c.Text()))
 		b.WriteRune('\n')
 	}
 	if markdownSupported {
diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go
index b08b110..a0e8308 100644
--- a/internal/lsp/source/source_test.go
+++ b/internal/lsp/source/source_test.go
@@ -301,7 +301,7 @@
 		if err != nil {
 			t.Fatalf("failed for %v: %v", d.Src, err)
 		}
-		hover, err := ident.Hover(ctx, nil, false, false)
+		hover, err := ident.Hover(ctx, nil, false, true)
 		if err != nil {
 			t.Fatalf("failed for %v: %v", d.Src, err)
 		}
diff --git a/internal/lsp/testdata/godef/a/a.go.golden b/internal/lsp/testdata/godef/a/a.go.golden
index c3cc488..a8a8108 100644
--- a/internal/lsp/testdata/godef/a/a.go.golden
+++ b/internal/lsp/testdata/godef/a/a.go.golden
@@ -1,6 +1,5 @@
 -- Random-definition --
 godef/a/random.go:3:6-12: defined here as func Random() int
--- Random-definition-guru --
 
 -- Random-definition-json --
 {
@@ -20,14 +19,10 @@
 	"description": "func Random() int"
 }
 
--- Random-definition-json-guru --
-
 -- Random-hover --
 func Random() int
 -- Random2-definition --
 godef/a/random.go:8:6-13: defined here as func Random2(y int) int
--- Random2-definition-guru --
-godef/a/random.go:8:6: defined here as func Random2(y int) int
 
 -- Random2-definition-json --
 {
@@ -47,18 +42,10 @@
 	"description": "func Random2(y int) int"
 }
 
--- Random2-definition-json-guru --
-{
-	"objpos": "godef/a/random.go:8:6",
-	"desc": "func Random2(y int) int"
-}
-
 -- Random2-hover --
 func Random2(y int) int
 -- err-definition --
 godef/a/a.go:14:6-9: defined here as var err error
--- err-definition-guru --
-godef/a/a.go:14:6: defined here as var err
 
 -- err-definition-json --
 {
diff --git a/internal/lsp/testdata/godef/a/d.go.golden b/internal/lsp/testdata/godef/a/d.go.golden
index 6e3a2bd..6c7cf09 100644
--- a/internal/lsp/testdata/godef/a/d.go.golden
+++ b/internal/lsp/testdata/godef/a/d.go.golden
@@ -1,7 +1,5 @@
 -- Member-definition --
 godef/a/d.go:6:2-8: defined here as field Member string
--- Member-definition-guru --
-godef/a/d.go:6:2: defined here as field Member string
 
 -- Member-definition-json --
 {
@@ -21,18 +19,11 @@
 	"description": "field Member string"
 }
 
--- Member-definition-json-guru --
-{
-	"objpos": "godef/a/d.go:6:2",
-	"desc": "field Member string"
-}
-
 -- Member-hover --
+@Member
 field Member string
 -- Method-definition --
 godef/a/d.go:15:16-22: defined here as func (Thing).Method(i int) string
--- Method-definition-guru --
-godef/a/d.go:15:16: defined here as func (Thing).Method(i int) string
 
 -- Method-definition-json --
 {
@@ -52,18 +43,10 @@
 	"description": "func (Thing).Method(i int) string"
 }
 
--- Method-definition-json-guru --
-{
-	"objpos": "godef/a/d.go:15:16",
-	"desc": "func (Thing).Method(i int) string"
-}
-
 -- Method-hover --
 func (Thing).Method(i int) string
 -- Other-definition --
 godef/a/d.go:9:5-10: defined here as var Other Thing
--- Other-definition-guru --
-godef/a/d.go:9:5: defined here as var Other
 
 -- Other-definition-json --
 {
@@ -86,9 +69,9 @@
 -- Other-hover --
 var Other Thing
 -- Thing-definition --
-godef/a/d.go:5:6-11: defined here as type Thing struct{Member string}
--- Thing-definition-guru --
-godef/a/d.go:5:6: defined here as type Thing
+godef/a/d.go:5:6-11: defined here as Thing struct {
+	Member string //@Member
+}
 
 -- Thing-definition-json --
 {
@@ -105,15 +88,15 @@
 			"offset": 35
 		}
 	},
-	"description": "type Thing struct{Member string}"
+	"description": "Thing struct {\n\tMember string //@Member\n}"
 }
 
 -- Thing-hover --
-type Thing struct{Member string}
+Thing struct {
+	Member string //@Member
+}
 -- Things-definition --
 godef/a/d.go:11:6-12: defined here as func Things(val []string) []Thing
--- Things-definition-guru --
-godef/a/d.go:11:6: defined here as func Things
 
 -- Things-definition-json --
 {
diff --git a/internal/lsp/testdata/godef/a/random.go.golden b/internal/lsp/testdata/godef/a/random.go.golden
index 077b710..0775d55 100644
--- a/internal/lsp/testdata/godef/a/random.go.golden
+++ b/internal/lsp/testdata/godef/a/random.go.golden
@@ -1,6 +1,5 @@
 -- PosSum-definition --
 godef/a/random.go:16:15-18: defined here as func (*Pos).Sum() int
--- PosSum-definition-guru --
 
 -- PosSum-definition-json --
 {
@@ -20,14 +19,10 @@
 	"description": "func (*Pos).Sum() int"
 }
 
--- PosSum-definition-json-guru --
-
 -- PosSum-hover --
 func (*Pos).Sum() int
 -- PosX-definition --
 godef/a/random.go:13:2-3: defined here as field x int
--- PosX-definition-guru --
-godef/a/random.go:13:2: defined here as field x int
 
 -- PosX-definition-json --
 {
@@ -47,18 +42,11 @@
 	"description": "field x int"
 }
 
--- PosX-definition-json-guru --
-{
-	"objpos": "godef/a/random.go:13:2",
-	"desc": "field x int"
-}
-
 -- PosX-hover --
+@mark(PosX, "x"),mark(PosY, "y")
 field x int
 -- RandomParamY-definition --
 godef/a/random.go:8:14-15: defined here as var y int
--- RandomParamY-definition-guru --
-godef/a/random.go:8:14: defined here as var y
 
 -- RandomParamY-definition-json --
 {
diff --git a/internal/lsp/testdata/godef/b/b.go.golden b/internal/lsp/testdata/godef/b/b.go.golden
index 556337e..febfce6 100644
--- a/internal/lsp/testdata/godef/b/b.go.golden
+++ b/internal/lsp/testdata/godef/b/b.go.golden
@@ -1,7 +1,5 @@
 -- A-definition --
-godef/a/a.go:7:6-7: defined here as type a.A string
--- A-definition-guru --
-godef/a/a.go:7:6: defined here as type a.A
+godef/a/a.go:7:6-7: defined here as A string //@A
 
 -- A-definition-json --
 {
@@ -18,15 +16,14 @@
 			"offset": 76
 		}
 	},
-	"description": "type a.A string"
+	"description": "A string //@A"
 }
 
 -- A-hover --
-type a.A string
+A string //@A
+
 -- AImport-definition --
 godef/b/b.go:5:2-3: defined here as package a ("golang.org/x/tools/internal/lsp/godef/a")
--- AImport-definition-guru --
-godef/b/b.go:5:2: defined here as package a ("golang.org/x/tools/internal/lsp/godef/a")
 
 -- AImport-definition-json --
 {
@@ -46,12 +43,6 @@
 	"description": "package a (\"golang.org/x/tools/internal/lsp/godef/a\")"
 }
 
--- AImport-definition-json-guru --
-{
-	"objpos": "godef/b/b.go:5:2",
-	"desc": "package a (\"golang.org/x/tools/internal/lsp/godef/a\")"
-}
-
 -- AImport-hover --
 package a ("golang.org/x/tools/internal/lsp/godef/a")
 -- PackageFoo-definition --
@@ -77,9 +68,11 @@
 -- PackageFoo-hover --
 
 -- S1-definition --
-godef/b/b.go:8:6-8: defined here as type S1 struct{F1 int; S2; a.A}
--- S1-definition-guru --
-godef/b/b.go:8:6: defined here as type S1
+godef/b/b.go:8:6-8: defined here as S1 struct {
+	F1  int //@mark(S1F1, "F1")
+	S2      //@godef("S2", S2), mark(S1S2, "S2")
+	a.A     //@godef("A", A)
+}
 
 -- S1-definition-json --
 {
@@ -96,15 +89,17 @@
 			"offset": 198
 		}
 	},
-	"description": "type S1 struct{F1 int; S2; a.A}"
+	"description": "S1 struct {\n\tF1  int //@mark(S1F1, \"F1\")\n\tS2      //@godef(\"S2\", S2), mark(S1S2, \"S2\")\n\ta.A     //@godef(\"A\", A)\n}"
 }
 
 -- S1-hover --
-type S1 struct{F1 int; S2; a.A}
+S1 struct {
+	F1  int //@mark(S1F1, "F1")
+	S2      //@godef("S2", S2), mark(S1S2, "S2")
+	a.A     //@godef("A", A)
+}
 -- S1F1-definition --
 godef/b/b.go:9:2-4: defined here as field F1 int
--- S1F1-definition-guru --
-godef/b/b.go:9:2: defined here as field F1 int
 
 -- S1F1-definition-json --
 {
@@ -124,18 +119,11 @@
 	"description": "field F1 int"
 }
 
--- S1F1-definition-json-guru --
-{
-	"objpos": "godef/b/b.go:9:2",
-	"desc": "field F1 int"
-}
-
 -- S1F1-hover --
+@mark(S1F1, "F1")
 field F1 int
 -- S1S2-definition --
 godef/b/b.go:10:2-4: defined here as field S2 S2
--- S1S2-definition-guru --
-godef/b/b.go:10:2: defined here as field S2 S2
 
 -- S1S2-definition-json --
 {
@@ -155,18 +143,15 @@
 	"description": "field S2 S2"
 }
 
--- S1S2-definition-json-guru --
-{
-	"objpos": "godef/b/b.go:10:2",
-	"desc": "field S2 S2"
-}
-
 -- S1S2-hover --
+@godef("S2", S2), mark(S1S2, "S2")
 field S2 S2
 -- S2-definition --
-godef/b/b.go:14:6-8: defined here as type S2 struct{F1 string; F2 int; *a.A}
--- S2-definition-guru --
-godef/b/b.go:14:6: defined here as type S2
+godef/b/b.go:14:6-8: defined here as S2 struct {
+	F1   string //@mark(S2F1, "F1")
+	F2   int    //@mark(S2F2, "F2")
+	*a.A        //@godef("A", A),godef("a",AImport)
+}
 
 -- S2-definition-json --
 {
@@ -183,15 +168,17 @@
 			"offset": 325
 		}
 	},
-	"description": "type S2 struct{F1 string; F2 int; *a.A}"
+	"description": "S2 struct {\n\tF1   string //@mark(S2F1, \"F1\")\n\tF2   int    //@mark(S2F2, \"F2\")\n\t*a.A        //@godef(\"A\", A),godef(\"a\",AImport)\n}"
 }
 
 -- S2-hover --
-type S2 struct{F1 string; F2 int; *a.A}
+S2 struct {
+	F1   string //@mark(S2F1, "F1")
+	F2   int    //@mark(S2F2, "F2")
+	*a.A        //@godef("A", A),godef("a",AImport)
+}
 -- S2F1-definition --
 godef/b/b.go:15:2-4: defined here as field F1 string
--- S2F1-definition-guru --
-godef/b/b.go:15:2: defined here as field F1 string
 
 -- S2F1-definition-json --
 {
@@ -211,18 +198,11 @@
 	"description": "field F1 string"
 }
 
--- S2F1-definition-json-guru --
-{
-	"objpos": "godef/b/b.go:15:2",
-	"desc": "field F1 string"
-}
-
 -- S2F1-hover --
+@mark(S2F1, "F1")
 field F1 string
 -- S2F2-definition --
 godef/b/b.go:16:2-4: defined here as field F2 int
--- S2F2-definition-guru --
-godef/b/b.go:16:2: defined here as field F2 int
 
 -- S2F2-definition-json --
 {
@@ -242,18 +222,11 @@
 	"description": "field F2 int"
 }
 
--- S2F2-definition-json-guru --
-{
-	"objpos": "godef/b/b.go:16:2",
-	"desc": "field F2 int"
-}
-
 -- S2F2-hover --
+@mark(S2F2, "F2")
 field F2 int
 -- Stuff-definition --
 godef/a/a.go:9:6-11: defined here as func a.Stuff()
--- Stuff-definition-guru --
-godef/a/a.go:9:6: defined here as func a.Stuff
 
 -- Stuff-definition-json --
 {
diff --git a/internal/lsp/testdata/godef/b/c.go.golden b/internal/lsp/testdata/godef/b/c.go.golden
index 69a14eb..62fb184 100644
--- a/internal/lsp/testdata/godef/b/c.go.golden
+++ b/internal/lsp/testdata/godef/b/c.go.golden
@@ -1,7 +1,9 @@
 -- S1-definition --
-godef/b/b.go:8:6-8: defined here as type S1 struct{F1 int; S2; a.A}
--- S1-definition-guru --
-godef/b/b.go:8:6: defined here as type S1 struct{F1 int; S2; a.A}
+godef/b/b.go:8:6-8: defined here as S1 struct {
+	F1  int //@mark(S1F1, "F1")
+	S2      //@godef("S2", S2), mark(S1S2, "S2")
+	a.A     //@godef("A", A)
+}
 
 -- S1-definition-json --
 {
@@ -18,15 +20,17 @@
 			"offset": 198
 		}
 	},
-	"description": "type S1 struct{F1 int; S2; a.A}"
+	"description": "S1 struct {\n\tF1  int //@mark(S1F1, \"F1\")\n\tS2      //@godef(\"S2\", S2), mark(S1S2, \"S2\")\n\ta.A     //@godef(\"A\", A)\n}"
 }
 
 -- S1-hover --
-type S1 struct{F1 int; S2; a.A}
+S1 struct {
+	F1  int //@mark(S1F1, "F1")
+	S2      //@godef("S2", S2), mark(S1S2, "S2")
+	a.A     //@godef("A", A)
+}
 -- S1F1-definition --
 godef/b/b.go:9:2-4: defined here as field F1 int
--- S1F1-definition-guru --
-godef/b/b.go:9:2: defined here as field F1 int
 
 -- S1F1-definition-json --
 {
@@ -46,11 +50,6 @@
 	"description": "field F1 int"
 }
 
--- S1F1-definition-json-guru --
-{
-	"objpos": "godef/b/b.go:9:2",
-	"desc": "field F1 int"
-}
-
 -- S1F1-hover --
+@mark(S1F1, "F1")
 field F1 int
diff --git a/internal/lsp/testdata/godef/b/e.go.golden b/internal/lsp/testdata/godef/b/e.go.golden
index 5db0e4c..8ff469e 100644
--- a/internal/lsp/testdata/godef/b/e.go.golden
+++ b/internal/lsp/testdata/godef/b/e.go.golden
@@ -1,7 +1,5 @@
 -- Member-definition --
 godef/a/d.go:6:2-8: defined here as field Member string
--- Member-definition-guru --
-godef/a/d.go:6:2: defined here as field Member string
 
 -- Member-definition-json --
 {
@@ -21,18 +19,11 @@
 	"description": "field Member string"
 }
 
--- Member-definition-json-guru --
-{
-	"objpos": "godef/a/d.go:6:2",
-	"desc": "field Member string"
-}
-
 -- Member-hover --
+@Member
 field Member string
 -- Other-definition --
 godef/a/d.go:9:5-10: defined here as var a.Other a.Thing
--- Other-definition-guru --
-godef/a/d.go:9:5: defined here as var a.Other
 
 -- Other-definition-json --
 {
@@ -55,9 +46,9 @@
 -- Other-hover --
 var a.Other a.Thing
 -- Thing-definition --
-godef/a/d.go:5:6-11: defined here as type a.Thing struct{Member string}
--- Thing-definition-guru --
-godef/a/d.go:5:6: defined here as type a.Thing
+godef/a/d.go:5:6-11: defined here as Thing struct {
+	Member string //@Member
+}
 
 -- Thing-definition-json --
 {
@@ -74,15 +65,15 @@
 			"offset": 35
 		}
 	},
-	"description": "type a.Thing struct{Member string}"
+	"description": "Thing struct {\n\tMember string //@Member\n}"
 }
 
 -- Thing-hover --
-type a.Thing struct{Member string}
+Thing struct {
+	Member string //@Member
+}
 -- Things-definition --
 godef/a/d.go:11:6-12: defined here as func a.Things(val []string) []a.Thing
--- Things-definition-guru --
-godef/a/d.go:11:6: defined here as func a.Things
 
 -- Things-definition-json --
 {
diff --git a/internal/lsp/testdata/godef/broken/unclosedIf.go.golden b/internal/lsp/testdata/godef/broken/unclosedIf.go.golden
index e49297a..2ed081a 100644
--- a/internal/lsp/testdata/godef/broken/unclosedIf.go.golden
+++ b/internal/lsp/testdata/godef/broken/unclosedIf.go.golden
@@ -1,7 +1,5 @@
 -- myUnclosedIf-definition --
 godef/broken/unclosedIf.go:7:7-19: defined here as var myUnclosedIf string
--- myUnclosedIf-definition-guru --
-godef/broken/unclosedIf.go:7:7: defined here as var myUnclosedIf
 
 -- myUnclosedIf-definition-json --
 {
diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go
index d374d70..1528677 100644
--- a/internal/lsp/tests/tests.go
+++ b/internal/lsp/tests/tests.go
@@ -267,7 +267,7 @@
 		tests.Format(t, data.Formats)
 	})
 
-	t.Run("Definitions", func(t *testing.T) {
+	t.Run("Definition", func(t *testing.T) {
 		t.Helper()
 		if len(data.Definitions) != ExpectedDefinitionsCount {
 			t.Errorf("got %v definitions expected %v", len(data.Definitions), ExpectedDefinitionsCount)
@@ -275,7 +275,7 @@
 		tests.Definition(t, data.Definitions)
 	})
 
-	t.Run("Highlights", func(t *testing.T) {
+	t.Run("Highlight", func(t *testing.T) {
 		t.Helper()
 		if len(data.Highlights) != ExpectedHighlightsCount {
 			t.Errorf("got %v highlights expected %v", len(data.Highlights), ExpectedHighlightsCount)
@@ -299,7 +299,7 @@
 		tests.SignatureHelp(t, data.Signatures)
 	})
 
-	t.Run("Links", func(t *testing.T) {
+	t.Run("Link", func(t *testing.T) {
 		t.Helper()
 		linksCount := 0
 		for _, want := range data.Links {