Skip to content

Commit d3a1606

Browse files
madelinekalilgopherbot
authored andcommitted
gopls/internal/golang: definition support return statements
Enables you to use the definition operation on a return token and brings you to the return parameters. Updates golang/go#70462 Change-Id: I080ff37aad5ac1498e320429fad6dd4b043f02c8 Reviewed-on: https://go-review.googlesource.com/c/tools/+/636855 Auto-Submit: Madeline Kalil <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent bf42cd7 commit d3a1606

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

gopls/doc/features/navigation.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ A definition query also works in these unexpected places:
2424
it returns the location of the embedded file.
2525
- On the declaration of a non-Go function (a `func` with no body),
2626
it returns the location of the assembly implementation, if any,
27+
- On a **return statement**, it returns the location of the function's result variables.
2728

2829
<!-- On a built-in symbol such as `append` or `unsafe.Pointer`, `definition` reports
2930
the location of the declaration in the builtin or unsafe pseudo-packages,

gopls/doc/release/v0.18.0.md

+7
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,10 @@ func (C[T]) Pop() (T, bool) { ... }
2828
var _ Stack[int] = C[int]{}
2929
```
3030

31+
## Improvements to "Definition"
32+
33+
The Definition query now supports additional locations:
34+
35+
- When invoked on a return statement, it reports the location
36+
of the function's result variables.
37+

gopls/internal/golang/definition.go

+29-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ import (
1515
"regexp"
1616
"strings"
1717

18+
"golang.org/x/tools/go/ast/astutil"
1819
"golang.org/x/tools/gopls/internal/cache"
1920
"golang.org/x/tools/gopls/internal/cache/metadata"
2021
"golang.org/x/tools/gopls/internal/cache/parsego"
2122
"golang.org/x/tools/gopls/internal/file"
2223
"golang.org/x/tools/gopls/internal/protocol"
23-
"golang.org/x/tools/gopls/internal/util/astutil"
24+
goplsastutil "golang.org/x/tools/gopls/internal/util/astutil"
2425
"golang.org/x/tools/gopls/internal/util/bug"
2526
"golang.org/x/tools/internal/event"
2627
)
@@ -84,6 +85,32 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
8485
return locations, err // may be success or failure
8586
}
8687

88+
// Handle the case where the cursor is on a return statement by jumping to the result variables.
89+
path, _ := astutil.PathEnclosingInterval(pgf.File, pos, pos)
90+
if is[*ast.ReturnStmt](path[0]) {
91+
var funcType *ast.FuncType
92+
for _, n := range path {
93+
switch n := n.(type) {
94+
case *ast.FuncLit:
95+
funcType = n.Type
96+
case *ast.FuncDecl:
97+
funcType = n.Type
98+
}
99+
if funcType != nil {
100+
break
101+
}
102+
}
103+
// Inv: funcType != nil, as a return stmt cannot appear outside a function.
104+
if funcType.Results == nil {
105+
return nil, nil // no result variables
106+
}
107+
loc, err := pgf.NodeLocation(funcType.Results)
108+
if err != nil {
109+
return nil, err
110+
}
111+
return []protocol.Location{loc}, nil
112+
}
113+
87114
// The general case: the cursor is on an identifier.
88115
_, obj, _ := referencedObject(pkg, pgf, pos)
89116
if obj == nil {
@@ -102,7 +129,7 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
102129
for _, decl := range pgf.File.Decls {
103130
if decl, ok := decl.(*ast.FuncDecl); ok &&
104131
decl.Body == nil &&
105-
astutil.NodeContains(decl.Name, pos) {
132+
goplsastutil.NodeContains(decl.Name, pos) {
106133
return nonGoDefinition(ctx, snapshot, pkg, decl.Name.Name)
107134
}
108135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
This test checks definition operations in function return statements.
2+
Go to definition on 'return' should go to the result parameter list.
3+
4+
-- go.mod --
5+
module mod.com
6+
7+
go 1.18
8+
9+
-- a/a.go --
10+
package a
11+
12+
func Hi() string { //@loc(HiReturn, "string")
13+
return "Hello" //@def("return", HiReturn)
14+
}
15+
16+
func Bye() (int, int, int) { //@loc(ByeReturn, "(int, int, int)")
17+
return 1, 2, 3 //@def("return", ByeReturn)
18+
}
19+
20+
func TestLit() {
21+
f := func(a, b int) bool { return a*b < 100 } //@loc(FuncLitReturn, "bool"),def("return", FuncLitReturn)
22+
f(1, 2)
23+
}

0 commit comments

Comments
 (0)