x/tools/gopls: TypeDefinition: return multiple locations for types.Signature or Tuple
gopls version
head
go env
N/A
What did you do?
Execute type definition
What did you see happen?
When the request location is pointing a function,
func() (foo, bar, error) gopls return "no type definition"
func() (foo, error) gopls return location to foo
func() (error) gopls return "no type definition"
#38589 mentions, gopls will ignore the error return value. The typeToObject function also only return one typeName even if multiples could be available.
What did you expect to see?
func() (foo, bar, error) gopls return locations to "foo", "bar", "error"
func() (foo, error) gopls return location to "foo", "error"
func() (error) gopls return "error"
the user can choose which type he/she want to jump to. The LSP type def support return []location.
Editor and settings
While introducing the range into TextDocumentPositionParam, I noticed that the type def method also extends TextDocumentPositionParam. So it is very intuitive idea to return type definition of an expression.
time.Now().Add(time.Second).String()
User can select a sub expression in the expression above and query "TypeDef". Some expression have multiple return values so the return type of a given expression is "types.Tuple". I wonder if it is possible to return the slice of location when the expression evaluates to a tuple.
Is there any reason for return only one location. (I understand if the language server only return one location, the language client will simply take user directly to the location without asking user "where you want to go among all these X types?")
@adonovan
Logs
No response
As an experiment, I have done a small prototype like below:
User can select a range and right click, Go To Type Definition:
Then, the vscode-go (or other language client) can send LSP TypeDef to gopls, "what is the type def of this expression!"
In this case, gopls will return three locations, error, time.Duration, time.Time.
Edge case: if an expression return two identical locations in the slice. E.g. a function returns "time.Time, time.Time, error", I think the language server should still return 3 locations, language client can decide whether it want to consolidate the first two. Some client may build UX based on the order of the returned locations. (Imagine a next button can take user to the next type def, so the order matters). For VSCode-Go, the language client will consolidate duplicated locations. but this is simply a vscode decision to make such changes.
A CL will be sent out to you soon.
Thank you!
Change https://go.dev/cl/728600 mentions this issue: gopls/internal/server: support type def with selected range
Change https://go.dev/cl/727560 mentions this issue: extension/src/language: extend range support to type def
Change https://go.dev/cl/728880 mentions this issue: gopls/internal/test/marker: add optional error to typedef marker
The implementation is done. :D