This test was ported from 'godef' in the old marker tests.
It tests various hover and definition requests.

-- go.mod --
module godef.test

go 1.18

-- a/a_x_test.go --
package a_test

import (
	"testing"
)

func TestA2(t *testing.T) { //@hover("TestA2", "TestA2", TestA2)
	Nonexistant() //@diag("Nonexistant", re"(undeclared name|undefined): Nonexistant")
}

-- @TestA2 --
```go
func TestA2(t *testing.T)
```
-- @ember --
```go
field Member string
```

---

@loc(Member, "Member")


---

[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Thing.Member)
-- a/d.go --
package a //@hover("a", _, a)

import "fmt"

type Thing struct { //@loc(Thing, "Thing")
	Member string //@loc(Member, "Member")
}

var Other Thing //@loc(Other, "Other")

func Things(val []string) []Thing { //@loc(Things, "Things")
	return nil
}

func (t Thing) Method(i int) string { //@loc(Method, "Method")
	return t.Member
}

func (t Thing) Method3() {
}

func (t *Thing) Method2(i int, j int) (error, string) {
	return nil, t.Member
}

func (t *Thing) private() {
}

func useThings() {
	t := Thing{ //@hover("ing", "Thing", ing)
		Member: "string", //@hover("ember", "Member", ember), def("ember", Member)
	}
	fmt.Print(t.Member) //@hover("ember", "Member", ember), def("ember", Member)
	fmt.Print(Other)    //@hover("ther", "Other", ther), def("ther", Other)
	Things(nil)         //@hover("ings", "Things", ings), def("ings", Things)
	t.Method(0)         //@hover("eth", "Method", eth), def("eth", Method)
}

type NextThing struct { //@loc(NextThing, "NextThing")
	Thing
	Value int
}

func (n NextThing) another() string {
	return n.Member
}

// Shadows Thing.Method3
func (n *NextThing) Method3() int {
	return n.Value
}

var nextThing NextThing //@hover("NextThing", "NextThing", NextThing), def("NextThing", NextThing)

-- @ings --
```go
func Things(val []string) []Thing
```

---

[`a.Things` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Things)
-- @ther --
```go
var Other Thing
```

---

@loc(Other, "Other")


---

[`a.Other` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Other)
-- @a --
-- @ing --
```go
type Thing struct {
	Member string //@loc(Member, "Member")
}
```

---

```go
func (t Thing) Method(i int) string
func (t *Thing) Method2(i int, j int) (error, string)
func (t Thing) Method3()
func (t *Thing) private()
```

---

[`a.Thing` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Thing)
-- @NextThing --
```go
type NextThing struct {
	Thing
	Value int
}
```

---

```go
// Embedded fields:
Member string // through Thing 
```

```go
func (t Thing) Method(i int) string
func (t *Thing) Method2(i int, j int) (error, string)
func (n *NextThing) Method3() int
func (n NextThing) another() string
func (t *Thing) private()
```

---

[`a.NextThing` on pkg.go.dev](https://pkg.go.dev/godef.test/a#NextThing)
-- @eth --
```go
func (t Thing) Method(i int) string
```

---

[`(a.Thing).Method` on pkg.go.dev](https://pkg.go.dev/godef.test/a#Thing.Method)
-- a/f.go --
// Package a is a package for testing go to definition.
package a

import "fmt"

func TypeStuff() {
	var x string

	switch y := any(x).(type) { //@loc(y, "y"), hover("y", "y", y) , def("y", y)
	case int: //@loc(intY, "int")
		fmt.Printf("%v", y) //@hover("y", "y", inty), def("y", y)
	case string: //@loc(stringY, "string")
		fmt.Printf("%v", y) //@hover("y", "y", stringy), def("y", y)
	}

}
-- @inty --
```go
var y int
```
-- @stringy --
```go
var y string
```
-- @y --
```go
var y any
```
-- a/h.go --
package a

func _() {
	type s struct {
		nested struct {
			// nested number
			number int64 //@loc(nestedNumber, "number")
		}
		nested2 []struct {
			// nested string
			str string //@loc(nestedString, "str")
		}
		x struct {
			x struct {
				x struct {
					x struct {
						x struct {
							// nested map
							m map[string]float64 //@loc(nestedMap, "m")
						}
					}
				}
			}
		}
	}

	var t s
	_ = t.nested.number  //@hover("number", "number", nestedNumber), def("number", nestedNumber)
	_ = t.nested2[0].str //@hover("str", "str", nestedString), def("str", nestedString)
	_ = t.x.x.x.x.x.m    //@hover("m", "m", nestedMap), def("m", nestedMap)
}

func _() {
	var s struct {
		// a field
		a int //@loc(structA, "a")
		// b nested struct
		b struct { //@loc(structB, "b")
			// c field of nested struct
			c int //@loc(structC, "c")
		}
	}
	_ = s.a   //@def("a", structA)
	_ = s.b   //@def("b", structB)
	_ = s.b.c //@def("c", structC)

	var arr []struct {
		// d field
		d int //@loc(arrD, "d")
		// e nested struct
		e struct { //@loc(arrE, "e")
			// f field of nested struct
			f int //@loc(arrF, "f")
		}
	}
	_ = arr[0].d   //@def("d", arrD)
	_ = arr[0].e   //@def("e", arrE)
	_ = arr[0].e.f //@def("f", arrF)

	var complex []struct {
		c <-chan map[string][]struct {
			// h field
			h int //@loc(complexH, "h")
			// i nested struct
			i struct { //@loc(complexI, "i")
				// j field of nested struct
				j int //@loc(complexJ, "j")
			}
		}
	}
	_ = (<-complex[0].c)["0"][0].h   //@def("h", complexH)
	_ = (<-complex[0].c)["0"][0].i   //@def("i", complexI)
	_ = (<-complex[0].c)["0"][0].i.j //@def("j", complexJ)

	var mapWithStructKey map[struct { //@diag("struct", re"invalid map key")
		// X key field
		x []string //@loc(mapStructKeyX, "x")
	}]int
	for k := range mapWithStructKey {
		_ = k.x //@def("x", mapStructKeyX)
	}

	var mapWithStructKeyAndValue map[struct {
		// Y key field
		y string //@loc(mapStructKeyY, "y")
	}]struct {
		// X value field
		x string //@loc(mapStructValueX, "x")
	}
	for k, v := range mapWithStructKeyAndValue {
		// TODO: we don't show docs for y field because both map key and value
		// are structs. And in this case, we parse only map value
		_ = k.y //@hover("y", "y", hoverStructKeyY), def("y", mapStructKeyY)
		_ = v.x //@hover("x", "x", hoverStructKeyX), def("x", mapStructValueX)
	}

	var i []map[string]interface {
		// open method comment
		open() error //@loc(openMethod, "open")
	}
	i[0]["1"].open() //@hover("pen","open", openMethod), def("open", openMethod)
}

func _() {
	test := struct {
		// test description
		desc string //@loc(testDescription, "desc")
	}{}
	_ = test.desc //@def("desc", testDescription)

	for _, tt := range []struct {
		// test input
		in map[string][]struct { //@loc(testInput, "in")
			// test key
			key string //@loc(testInputKey, "key")
			// test value
			value any //@loc(testInputValue, "value")
		}
		result struct {
			v <-chan struct {
				// expected test value
				value int //@loc(testResultValue, "value")
			}
		}
	}{} {
		_ = tt.in               //@def("in", testInput)
		_ = tt.in["0"][0].key   //@def("key", testInputKey)
		_ = tt.in["0"][0].value //@def("value", testInputValue)

		_ = (<-tt.result.v).value //@def("value", testResultValue)
	}
}

func _() {
	getPoints := func() []struct {
		// X coord
		x int //@loc(returnX, "x")
		// Y coord
		y int //@loc(returnY, "y")
	} {
		return nil
	}

	r := getPoints()
	_ = r[0].x //@def("x", returnX)
	_ = r[0].y //@def("y", returnY)
}
-- @hoverStructKeyX --
```go
field x string
```

---

X value field
-- @hoverStructKeyY --
```go
field y string
```

---

Y key field
-- @nestedNumber --
```go
field number int64
```

---

nested number
-- @nestedString --
```go
field str string
```

---

nested string
-- @openMethod --
```go
func (interface) open() error
```

---

open method comment
-- @nestedMap --
```go
field m map[string]float64
```

---

nested map
-- b/e.go --
package b

import (
	"fmt"

	"godef.test/a"
)

func useThings() {
	t := a.Thing{}      //@loc(bStructType, "ing")
	fmt.Print(t.Member) //@loc(bMember, "ember")
	fmt.Print(a.Other)  //@loc(bVar, "ther")
	a.Things(nil)          //@loc(bFunc, "ings")
}

/*@
def(bStructType, Thing)
def(bMember, Member)
def(bVar, Other)
def(bFunc, Things)
*/

func _() {
	var x any
	switch x := x.(type) { //@hover("x", "x", xInterface)
	case string: //@loc(eString, "string")
		fmt.Println(x) //@hover("x", "x", xString)
	case int: //@loc(eInt, "int")
		fmt.Println(x) //@hover("x", "x", xInt)
	}
}
-- @xInt --
```go
var x int
```
-- @xInterface --
```go
var x any
```
-- @xString --
```go
var x string
```
-- broken/unclosedIf.go --
package broken

import "fmt"

func unclosedIf() {
	if false {
		var myUnclosedIf string              //@loc(myUnclosedIf, "myUnclosedIf")
		fmt.Printf("s = %v\n", myUnclosedIf) //@def("my", myUnclosedIf)
}

func _() {} //@diag("_", re"expected")
