Skip to content

Commit 32ccbec

Browse files
committed
gopls: Refactor goasm.References function.
Leveraged Defs and Uses mappings from types.Info to efficiently find references in Go files. Updates golang/go#71754
1 parent 7c3d6ff commit 32ccbec

File tree

4 files changed

+67
-36
lines changed

4 files changed

+67
-36
lines changed

gopls/internal/goasm/references.go

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"context"
1111
"fmt"
1212
"go/ast"
13+
"go/types"
1314

1415
"golang.org/x/tools/gopls/internal/cache"
1516
"golang.org/x/tools/gopls/internal/cache/metadata"
@@ -73,16 +74,34 @@ func References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
7374
// TODO(grootguo): Currently, only references to the symbol within the package are found (i.e., only Idents in this package's Go files are searched).
7475
// It is still necessary to implement cross-package reference lookup: that is, to find all references to this symbol in other packages that import the current package.
7576
// Refer to the global search logic in golang.References, and add corresponding test cases for verification.
77+
obj := pkg.Types().Scope().Lookup(name)
78+
matches := func(curObj types.Object) bool {
79+
if curObj == nil {
80+
return false
81+
}
82+
if curObj.Name() != obj.Name() {
83+
return false
84+
}
85+
return true
86+
}
7687
for _, pgf := range pkg.CompiledGoFiles() {
7788
for curId := range pgf.Cursor.Preorder((*ast.Ident)(nil)) {
7889
id := curId.Node().(*ast.Ident)
79-
if id.Name == name {
80-
loc, err := pgf.NodeLocation(id)
81-
if err != nil {
82-
return nil, err
90+
curObj, ok := pkg.TypesInfo().Defs[id]
91+
if !ok {
92+
curObj, ok = pkg.TypesInfo().Uses[id]
93+
if !ok {
94+
continue
8395
}
84-
locations = append(locations, loc)
8596
}
97+
if !matches(curObj) {
98+
continue
99+
}
100+
loc, err := pgf.NodeLocation(id)
101+
if err != nil {
102+
return nil, err
103+
}
104+
locations = append(locations, loc)
86105
}
87106
}
88107

@@ -96,12 +115,8 @@ func References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
96115
if id.Name != sym {
97116
continue
98117
}
99-
if rng, err := asmFile.NodeRange(id); err == nil {
100-
asmLocation := protocol.Location{
101-
URI: asmFile.URI,
102-
Range: rng,
103-
}
104-
locations = append(locations, asmLocation)
118+
if loc, err := asmFile.NodeLocation(id); err == nil {
119+
locations = append(locations, loc)
105120
}
106121
}
107122
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
This test validates the References request functionality in Go assembly files.
2+
3+
It ensures that references to both exported (`Add`) and unexported (`sub`) functions are correctly identified across Go and assembly files. The test covers:
4+
- Locating the definition of functions in both Go and assembly files.
5+
- Identifying all references to the functions (`Add` and `sub`) within the Go and assembly files.
6+
7+
The test includes:
8+
- `Add`: An exported function with references in both Go and assembly files.
9+
- `sub`: An unexported function with references in both Go and assembly files, including a usage in Go code (`var _ = sub`).
10+
11+
The assembly file demonstrates portable assembly syntax and verifies cross-file reference handling.
12+
13+
-- go.mod --
14+
module example.com
15+
go 1.24
16+
17+
-- foo/foo.go --
18+
package foo
19+
20+
func Add(a, b int) int //@ loc(use, "Add"), refs("Add", use, def)
21+
func sub(a, b int) int //@ loc(useSub, "sub"), refs("sub", useSub, defSub, refSub)
22+
var _ = sub //@loc(refSub, "sub"), refs("sub", useSub, defSub, refSub)
23+
24+
-- foo/foo.s --
25+
// portable assembly
26+
#include "textflag.h"
27+
28+
TEXT ·Add(SB), NOSPLIT, $0-24 //@ loc(def, "Add"), refs("Add", def, use)
29+
MOVQ a+0(FP), AX
30+
ADDQ b+8(FP), AX
31+
RET
32+
33+
TEXT ·sub(SB), NOSPLIT, $0-24 //@ loc(defSub, "sub"), refs("sub", defSub, useSub, refSub)
34+
MOVQ a+0(FP), AX
35+
SUBQ b+8(FP), AX
36+
RET

gopls/internal/test/marker/testdata/references/asm_ref.txt

Lines changed: 0 additions & 25 deletions
This file was deleted.

gopls/internal/util/asm/parse.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ func (f *File) NodeRange(ident Ident) (protocol.Range, error) {
5858
return f.Mapper.OffsetRange(ident.Offset+2, ident.End()+1)
5959
}
6060

61+
// NodeLocation returns a protocol Location for the ast.Node interval in this file.
62+
func (f *File) NodeLocation(ident Ident) (protocol.Location, error) {
63+
return f.Mapper.OffsetLocation(ident.Offset+2, ident.End()+1)
64+
}
65+
6166
// Ident represents an identifier in an assembly file.
6267
type Ident struct {
6368
Name string // symbol name (after correcting [·∕]); Name[0]='.' => current package

0 commit comments

Comments
 (0)