Skip to content

Commit d376e74

Browse files
committed
gopls: Add test cases for references in assembly and Go files
Improve code comments for better readability.Remove type checking logic from assembly file reference lookup.Update xrefs index retrieval for consistency Updates golang/go#71754
1 parent 556b741 commit d376e74

File tree

8 files changed

+65
-62
lines changed

8 files changed

+65
-62
lines changed

gopls/internal/cache/metadata/metadata.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ type Package struct {
5151
IgnoredFiles []protocol.DocumentURI
5252
OtherFiles []protocol.DocumentURI
5353

54-
// These fields ares as defined by asm.File
55-
AsmFiles []protocol.DocumentURI
54+
AsmFiles []protocol.DocumentURI // *.s subset of OtherFiles
5655

5756
ForTest PackagePath // q in a "p [q.test]" package, else ""
5857
TypesSizes types.Sizes

gopls/internal/cache/package.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func (pkg *syntaxPackage) AsmFile(uri protocol.DocumentURI) (*asm.File, error) {
215215
for _, af := range pkg.asmFiles {
216216
if af.URI == uri {
217217
return af, nil
218-
}
218+
}
219219
}
220220

221221
return nil, fmt.Errorf("no parsed file for %s in %v", uri, pkg.id)

gopls/internal/cache/xrefs/xrefs.go

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package xrefs
1111
import (
1212
"go/ast"
1313
"go/types"
14+
"slices"
1415
"sort"
1516

1617
"golang.org/x/tools/go/types/objectpath"
@@ -72,7 +73,7 @@ func Index(files []*parsego.File, pkg *types.Package, info *types.Info, asmFiles
7273
// (e.g. local const/var/type).
7374
continue
7475
}
75-
gobObj = &gobObject{Path: path, isAsm: false}
76+
gobObj = &gobObject{Path: path}
7677
objects[obj] = gobObj
7778
}
7879

@@ -114,29 +115,21 @@ func Index(files []*parsego.File, pkg *types.Package, info *types.Info, asmFiles
114115
}
115116
}
116117

118+
// For each asm file, record references to identifiers.
117119
for fileIndex, af := range asmFiles {
118120
for _, id := range af.Idents {
119121
_, name, ok := morestrings.CutLast(id.Name, ".")
120122
if !ok {
121123
continue
122124
}
123-
if id.Kind != asm.Text {
124-
continue
125-
}
126125
obj := pkg.Scope().Lookup(name)
127126
if obj == nil {
128127
continue
129128
}
130129
objects := getObjects(pkg)
131130
gobObj, ok := objects[obj]
132131
if !ok {
133-
path, err := objectpathFor(obj)
134-
if err != nil {
135-
// Capitalized but not exported
136-
// (e.g. local const/var/type).
137-
continue
138-
}
139-
gobObj = &gobObject{Path: path, isAsm: true}
132+
gobObj = &gobObject{Path: objectpath.Path(obj.Name())}
140133
objects[obj] = gobObj
141134
}
142135
if rng, err := af.NodeRange(id); err == nil {
@@ -183,10 +176,7 @@ func Lookup(mp *metadata.Package, data []byte, targets map[metadata.PackagePath]
183176
for _, gobObj := range gp.Objects {
184177
if _, ok := objectSet[gobObj.Path]; ok {
185178
for _, ref := range gobObj.Refs {
186-
uri := mp.CompiledGoFiles[ref.FileIndex]
187-
if gobObj.isAsm {
188-
uri = mp.AsmFiles[ref.FileIndex]
189-
}
179+
uri := slices.Concat(mp.CompiledGoFiles, mp.AsmFiles)[ref.FileIndex]
190180
locs = append(locs, protocol.Location{
191181
URI: uri,
192182
Range: ref.Range,
@@ -223,9 +213,8 @@ type gobPackage struct {
223213

224214
// A gobObject records all references to a particular symbol.
225215
type gobObject struct {
226-
Path objectpath.Path // symbol name within package; "" => import of package itself
227-
Refs []gobRef // locations of references within P, in lexical order
228-
isAsm bool // true if this is an assembly object
216+
Path objectpath.Path // symbol name within package; "" => import of package itself
217+
Refs []gobRef // locations of references within P, in lexical order
229218
}
230219

231220
type gobRef struct {

gopls/internal/goasm/references.go

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,36 @@ import (
2020
"golang.org/x/tools/internal/event"
2121
)
2222

23-
func References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position) ([]protocol.Location, error) {
23+
// References returns a list of locations (file and position) where the symbol under the cursor in an assembly file is referenced,
24+
// including both Go source files and assembly files within the same package.
25+
func References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, position protocol.Position, includeDeclaration bool) ([]protocol.Location, error) {
2426
ctx, done := event.Start(ctx, "goasm.References")
2527
defer done()
2628

27-
pkg, asmFile, err := GetPackageID(ctx, snapshot, fh.URI())
29+
mps, err := snapshot.MetadataForFile(ctx, fh.URI())
2830
if err != nil {
2931
return nil, err
3032
}
31-
32-
// Read the file.
33-
content, err := fh.Content()
33+
metadata.RemoveIntermediateTestVariants(&mps)
34+
if len(mps) == 0 {
35+
return nil, fmt.Errorf("no package metadata for file %s", fh.URI())
36+
}
37+
mp := mps[0]
38+
pkgs, err := snapshot.TypeCheck(ctx, mp.ID)
3439
if err != nil {
3540
return nil, err
3641
}
37-
mapper := protocol.NewMapper(fh.URI(), content)
38-
offset, err := mapper.PositionOffset(position)
42+
pkg := pkgs[0]
43+
asmFile, err := pkg.AsmFile(fh.URI())
44+
if err != nil {
45+
return nil, err // "can't happen"
46+
}
47+
48+
offset, err := asmFile.Mapper.PositionOffset(position)
3949
if err != nil {
4050
return nil, err
4151
}
4252

43-
// // Parse the assembly.
44-
// file := asm.Parse(fh.URI(), content)
45-
4653
// Figure out the selected symbol.
4754
// For now, just find the identifier around the cursor.
4855
var found *asm.Ident
@@ -62,7 +69,10 @@ func References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
6269
if !ok {
6370
return nil, fmt.Errorf("not found")
6471
}
65-
// return localReferences(pkg, targets, true, report)
72+
73+
// 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).
74+
// 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.
75+
// Refer to the global search logic in golang.References, and add corresponding test cases for verification.
6676
for _, pgf := range pkg.CompiledGoFiles() {
6777
for curId := range pgf.Cursor.Preorder((*ast.Ident)(nil)) {
6878
id := curId.Node().(*ast.Ident)
@@ -76,6 +86,11 @@ func References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
7686
}
7787
}
7888

89+
// If includeDeclaration is false, return only reference locations (exclude declarations).
90+
if !includeDeclaration {
91+
return locations, nil
92+
}
93+
7994
for _, asmFile := range pkg.AsmFiles() {
8095
for _, id := range asmFile.Idents {
8196
if id.Name != sym {
@@ -93,25 +108,3 @@ func References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
93108

94109
return locations, nil
95110
}
96-
97-
func GetPackageID(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) (*cache.Package, *asm.File, error) {
98-
mps, err := snapshot.MetadataForFile(ctx, uri)
99-
if err != nil {
100-
return nil, nil, err
101-
}
102-
metadata.RemoveIntermediateTestVariants(&mps)
103-
if len(mps) == 0 {
104-
return nil, nil, fmt.Errorf("no package metadata for file %s", uri)
105-
}
106-
mp := mps[0]
107-
pkgs, err := snapshot.TypeCheck(ctx, mp.ID)
108-
if err != nil {
109-
return nil, nil, err
110-
}
111-
pkg := pkgs[0]
112-
asmFile, err := pkg.AsmFile(uri)
113-
if err != nil {
114-
return nil, nil, err // "can't happen"
115-
}
116-
return pkg, asmFile, nil
117-
}

gopls/internal/golang/references.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import (
3232
"golang.org/x/tools/gopls/internal/cache/parsego"
3333
"golang.org/x/tools/gopls/internal/file"
3434
"golang.org/x/tools/gopls/internal/protocol"
35-
"golang.org/x/tools/gopls/internal/util/asm"
3635
"golang.org/x/tools/gopls/internal/util/morestrings"
3736
"golang.org/x/tools/gopls/internal/util/safetoken"
3837
"golang.org/x/tools/internal/event"
@@ -613,15 +612,13 @@ func localReferences(pkg *cache.Package, targets map[types.Object]bool, correspo
613612
}
614613
}
615614

615+
// Iterate over all assembly files and find all references to the target object.
616616
for _, pgf := range pkg.AsmFiles() {
617617
for _, id := range pgf.Idents {
618618
_, name, ok := morestrings.CutLast(id.Name, ".")
619619
if !ok {
620620
continue
621621
}
622-
if id.Kind != asm.Text {
623-
continue
624-
}
625622
obj := pkg.Types().Scope().Lookup(name)
626623
if obj == nil {
627624
continue
@@ -631,7 +628,7 @@ func localReferences(pkg *cache.Package, targets map[types.Object]bool, correspo
631628
URI: pgf.URI,
632629
Range: rng,
633630
}
634-
report(asmLocation, true)
631+
report(asmLocation, false)
635632
}
636633
}
637634
}

gopls/internal/server/references.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func (s *server) References(ctx context.Context, params *protocol.ReferenceParam
3737
case file.Go:
3838
return golang.References(ctx, snapshot, fh, params.Position, params.Context.IncludeDeclaration)
3939
case file.Asm:
40-
return goasm.References(ctx, snapshot, fh, params.Position)
40+
return goasm.References(ctx, snapshot, fh, params.Position, params.Context.IncludeDeclaration)
4141
}
4242
return nil, nil // empty result
4343
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
-- go.mod --
3+
module example.com
4+
go 1.24
5+
6+
-- foo/foo.go --
7+
package foo
8+
9+
func Add(a, b int) int //@ loc(use, "Add"), refs("Add", use, def)
10+
func sub(a, b int) int //@ loc(useSub, "sub"), refs("sub", useSub, defSub, refSub)
11+
var _ = sub //@loc(refSub, "sub"), refs("sub", useSub, defSub, refSub)
12+
13+
-- foo/foo.s --
14+
// portable assembly
15+
#include "textflag.h"
16+
17+
TEXT ·Add(SB), NOSPLIT, $0-24 //@ loc(def, "Add"), refs("Add", def, use)
18+
MOVQ a+0(FP), AX
19+
ADDQ b+8(FP), AX
20+
RET
21+
22+
TEXT ·sub(SB), NOSPLIT, $0-24 //@ loc(defSub, "sub"), refs("sub", defSub, useSub, refSub)
23+
MOVQ a+0(FP), AX
24+
SUBQ b+8(FP), AX
25+
RET

gopls/internal/util/asm/parse.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ type File struct {
4848
URI protocol.DocumentURI
4949
Idents []Ident
5050

51-
Mapper *protocol.Mapper // may map fixed Src, not file content
51+
Mapper *protocol.Mapper
5252

5353
// TODO(adonovan): use token.File? This may be important in a
5454
// future in which analyzers can report diagnostics in .s files.
5555
}
5656

5757
func (f *File) NodeRange(ident Ident) (protocol.Range, error) {
58-
return f.Mapper.OffsetRange(ident.Offset, ident.End())
58+
return f.Mapper.OffsetRange(ident.Offset+2, ident.End()+1)
5959
}
6060

6161
// Ident represents an identifier in an assembly file.

0 commit comments

Comments
 (0)