Skip to content

Commit d1c2fd2

Browse files
committed
gopls/internal/golang: cleanups while investigating golang/go#74434
- golang.mapPosition: doc tweak - cache: add (*Package).FileEnclosing method. Call it from findLinkname, renamer.update, goasm.mapPosition. - resolveDocLink: doc tweak; use labeled break; fix bad-style loop; name local vars. - goasm.Definition: return range (not start) of symbol name. Change-Id: I23a12627acfd3580c38f5dd41027aacad9030fdb Reviewed-on: https://go-review.googlesource.com/c/tools/+/684976 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 7f29a7e commit d1c2fd2

File tree

8 files changed

+69
-79
lines changed

8 files changed

+69
-79
lines changed

gopls/internal/cache/package.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"golang.org/x/tools/gopls/internal/cache/testfuncs"
2020
"golang.org/x/tools/gopls/internal/cache/xrefs"
2121
"golang.org/x/tools/gopls/internal/protocol"
22+
"golang.org/x/tools/gopls/internal/util/safetoken"
2223
)
2324

2425
// Convenient aliases for very heavily used types.
@@ -132,15 +133,26 @@ func (p *Package) File(uri protocol.DocumentURI) (*parsego.File, error) {
132133
return p.pkg.File(uri)
133134
}
134135

135-
func (pkg *syntaxPackage) File(uri protocol.DocumentURI) (*parsego.File, error) {
136-
for _, cgf := range pkg.compiledGoFiles {
137-
if cgf.URI == uri {
138-
return cgf, nil
136+
// FileEnclosing returns the file of pkg that encloses the specified position,
137+
// which must be mapped by p.FileSet().
138+
func (p *Package) FileEnclosing(pos token.Pos) (*parsego.File, error) {
139+
for _, files := range [...][]*parsego.File{p.pkg.compiledGoFiles, p.pkg.goFiles} {
140+
for _, pgf := range files {
141+
if pgf.File.FileStart <= pos && pos <= pgf.File.FileEnd {
142+
return pgf, nil
143+
}
139144
}
140145
}
141-
for _, gf := range pkg.goFiles {
142-
if gf.URI == uri {
143-
return gf, nil
146+
return nil, fmt.Errorf("no parsed file for position %d (%s) in %v",
147+
pos, safetoken.StartPosition(p.FileSet(), pos), p.pkg.id)
148+
}
149+
150+
func (pkg *syntaxPackage) File(uri protocol.DocumentURI) (*parsego.File, error) {
151+
for _, files := range [...][]*parsego.File{pkg.compiledGoFiles, pkg.goFiles} {
152+
for _, pgf := range files {
153+
if pgf.URI == uri {
154+
return pgf, nil
155+
}
144156
}
145157
}
146158
return nil, fmt.Errorf("no parsed file for %s in %v", uri, pkg.id)

gopls/internal/goasm/definition.go

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
8585
return nil, fmt.Errorf("package %q is not a dependency", pkgpath)
8686
}
8787

88+
// Find declared symbol in syntax package.
8889
pkgs, err := snapshot.TypeCheck(ctx, declaring.ID)
8990
if err != nil {
9091
return nil, err
@@ -94,10 +95,18 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
9495
if def == nil {
9596
return nil, fmt.Errorf("no symbol %q in package %q", name, pkgpath)
9697
}
97-
loc, err := mapPosition(ctx, pkg.FileSet(), snapshot, def.Pos(), def.Pos())
98-
if err == nil {
99-
return []protocol.Location{loc}, nil
98+
99+
// Map position.
100+
pos := def.Pos()
101+
pgf, err := pkg.FileEnclosing(pos)
102+
if err != nil {
103+
return nil, err
100104
}
105+
loc, err := pgf.PosLocation(pos, pos+token.Pos(len(name)))
106+
if err != nil {
107+
return nil, err
108+
}
109+
return []protocol.Location{loc}, nil
101110

102111
} else {
103112
// local symbols (funcs, vars, labels)
@@ -116,21 +125,3 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
116125

117126
return nil, nil
118127
}
119-
120-
// TODO(rfindley): avoid the duplicate column mapping here, by associating a
121-
// column mapper with each file handle.
122-
// TODO(adonovan): plundered from ../golang; factor.
123-
func mapPosition(ctx context.Context, fset *token.FileSet, s file.Source, start, end token.Pos) (protocol.Location, error) {
124-
file := fset.File(start)
125-
uri := protocol.URIFromPath(file.Name())
126-
fh, err := s.ReadFile(ctx, uri)
127-
if err != nil {
128-
return protocol.Location{}, err
129-
}
130-
content, err := fh.Content()
131-
if err != nil {
132-
return protocol.Location{}, err
133-
}
134-
m := protocol.NewMapper(fh.URI(), content)
135-
return m.PosLocation(file, start, end)
136-
}

gopls/internal/golang/comment.go

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,17 @@ func docLinkDefinition(ctx context.Context, snapshot *cache.Snapshot, pkg *cache
7171
}
7272

7373
// resolveDocLink parses a doc link in a comment such as [fmt.Println]
74-
// and returns the symbol at pos, along with the link's start position.
74+
// and returns the symbol at pos, along with the link's range.
7575
func resolveDocLink(pkg *cache.Package, pgf *parsego.File, pos token.Pos) (types.Object, protocol.Range, error) {
7676
var comment *ast.Comment
77+
outer:
7778
for _, cg := range pgf.File.Comments {
7879
for _, c := range cg.List {
7980
if c.Pos() <= pos && pos <= c.End() {
8081
comment = c
81-
break
82+
break outer
8283
}
8384
}
84-
if comment != nil {
85-
break
86-
}
8785
}
8886
if comment == nil {
8987
return nil, protocol.Range{}, errNoCommentReference
@@ -110,32 +108,32 @@ func resolveDocLink(pkg *cache.Package, pgf *parsego.File, pos token.Pos) (types
110108
lineOffset := int(pos - start)
111109

112110
for _, idx := range docLinkRegex.FindAllStringSubmatchIndex(text, -1) {
113-
// The [idx[2], idx[3]) identifies the first submatch,
111+
mstart, mend := idx[2], idx[3]
112+
// [mstart, mend) identifies the first submatch,
114113
// which is the reference name in the doc link (sans '*').
115114
// e.g. The "[fmt.Println]" reference name is "fmt.Println".
116-
if !(idx[2] <= lineOffset && lineOffset < idx[3]) {
117-
continue
118-
}
119-
p := lineOffset - idx[2]
120-
name := text[idx[2]:idx[3]]
121-
i := strings.LastIndexByte(name, '.')
122-
for i != -1 {
123-
if p > i {
124-
break
115+
if mstart <= lineOffset && lineOffset < mend {
116+
p := lineOffset - mstart
117+
name := text[mstart:mend]
118+
i := strings.LastIndexByte(name, '.')
119+
for i != -1 {
120+
if p > i {
121+
break
122+
}
123+
name = name[:i]
124+
i = strings.LastIndexByte(name, '.')
125125
}
126-
name = name[:i]
127-
i = strings.LastIndexByte(name, '.')
128-
}
129-
obj := lookupDocLinkSymbol(pkg, pgf, name)
130-
if obj == nil {
131-
return nil, protocol.Range{}, errNoCommentReference
132-
}
133-
namePos := start + token.Pos(idx[2]+i+1)
134-
rng, err := pgf.PosRange(namePos, namePos+token.Pos(len(obj.Name())))
135-
if err != nil {
136-
return nil, protocol.Range{}, err
126+
obj := lookupDocLinkSymbol(pkg, pgf, name)
127+
if obj == nil {
128+
return nil, protocol.Range{}, errNoCommentReference
129+
}
130+
namePos := start + token.Pos(mstart+i+1)
131+
rng, err := pgf.PosRange(namePos, namePos+token.Pos(len(obj.Name())))
132+
if err != nil {
133+
return nil, protocol.Range{}, err
134+
}
135+
return obj, rng, nil // success
137136
}
138-
return obj, rng, nil
139137
}
140138

141139
return nil, protocol.Range{}, errNoCommentReference

gopls/internal/golang/definition.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ func importDefinition(ctx context.Context, s *cache.Snapshot, pkg *cache.Package
438438
return locs, nil
439439
}
440440

441+
// mapPosition returns the location of (start, end) in the file
442+
// that encloses that range according to fset.
443+
// It may need to read the file content, hence (ctx, s).
444+
//
441445
// TODO(rfindley): avoid the duplicate column mapping here, by associating a
442446
// column mapper with each file handle.
443447
func mapPosition(ctx context.Context, fset *token.FileSet, s file.Source, start, end token.Pos) (protocol.Location, error) {

gopls/internal/golang/linkname.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"golang.org/x/tools/gopls/internal/cache/metadata"
1616
"golang.org/x/tools/gopls/internal/cache/parsego"
1717
"golang.org/x/tools/gopls/internal/protocol"
18-
"golang.org/x/tools/gopls/internal/util/safetoken"
1918
)
2019

2120
// ErrNoLinkname is returned by LinknameDefinition when no linkname
@@ -135,11 +134,7 @@ func findLinkname(ctx context.Context, snapshot *cache.Snapshot, pkgPath Package
135134
return nil, nil, token.NoPos, fmt.Errorf("package %q does not define %s", pkgPath, name)
136135
}
137136

138-
objURI := safetoken.StartPosition(pkg.FileSet(), obj.Pos())
139-
pgf, err := pkg.File(protocol.URIFromPath(objURI.Filename))
140-
if err != nil {
141-
return nil, nil, token.NoPos, err
142-
}
143-
144-
return pkg, pgf, obj.Pos(), nil
137+
pos := obj.Pos()
138+
pgf, err := pkg.FileEnclosing(pos)
139+
return pkg, pgf, pos, err
145140
}

gopls/internal/golang/rename.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,9 +1294,9 @@ func (r *renamer) update() (map[protocol.DocumentURI][]diff.Edit, error) {
12941294

12951295
// Update each identifier, and its doc comment if it is a declaration.
12961296
for _, item := range items {
1297-
pgf, ok := enclosingFile(r.pkg, item.node.Pos())
1298-
if !ok {
1299-
bug.Reportf("edit does not belong to syntax of package %q", r.pkg)
1297+
pgf, err := r.pkg.FileEnclosing(item.node.Pos())
1298+
if err != nil {
1299+
bug.Reportf("edit does not belong to syntax of package %q: %v", r.pkg, err)
13001300
continue
13011301
}
13021302

@@ -1661,16 +1661,6 @@ func parsePackageNameDecl(ctx context.Context, snapshot *cache.Snapshot, fh file
16611661
return pgf, goplsastutil.NodeContains(pgf.File.Name, pos), nil
16621662
}
16631663

1664-
// enclosingFile returns the CompiledGoFile of pkg that contains the specified position.
1665-
func enclosingFile(pkg *cache.Package, pos token.Pos) (*parsego.File, bool) {
1666-
for _, pgf := range pkg.CompiledGoFiles() {
1667-
if pgf.File.FileStart <= pos && pos <= pgf.File.FileEnd {
1668-
return pgf, true
1669-
}
1670-
}
1671-
return nil, false
1672-
}
1673-
16741664
// posEdit returns an edit to replace the (start, end) range of tf with 'new'.
16751665
func posEdit(tf *token.File, start, end token.Pos, new string) (diff.Edit, error) {
16761666
startOffset, endOffset, err := safetoken.Offsets(tf, start, end)

gopls/internal/golang/rename_check.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ func (r *renamer) checkStructField(from *types.Var) {
439439
// go/types offers no easy way to get from a field (or interface
440440
// method) to its declaring struct (or interface), so we must
441441
// ascend the AST.
442-
if pgf, ok := enclosingFile(r.pkg, from.Pos()); ok {
442+
if pgf, err := r.pkg.FileEnclosing(from.Pos()); err == nil {
443443
path, _ := astutil.PathEnclosingInterval(pgf.File, from.Pos(), from.Pos())
444444
// path matches this pattern:
445445
// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]

gopls/internal/test/marker/testdata/definition/asm.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ package a
1616
import _ "fmt"
1717
import _ "example.com/b"
1818

19-
func ff() //@ loc(ffgo, re"()ff"), def("ff", ffasm)
19+
func ff() //@ loc(ffgo, "ff"), def("ff", ffasm)
2020

2121
var _ = ff // pacify unusedfunc analyzer
2222

@@ -33,4 +33,4 @@ label: //@ loc(label,"label")
3333
-- b/b.go --
3434
package b
3535

36-
func B() {} //@ loc(bB, re"()B")
36+
func B() {} //@ loc(bB, "B")

0 commit comments

Comments
 (0)