Skip to content

Commit 87ad891

Browse files
committed
gopls/internal/lsp/source/typerefs: move test into _test.go
This change moves logic needed only by the test into the test package. (I got quite confused trying to understand the algorithm before I realized this code is never used in the product.) Also: - move Decode trace logic into test. - expose PackageSet.AddDeclaringPackage to test. - rename Symbol.PackageID(PackageIndex) to PackageIndex.DeclaringPackage(Symbol) to match. - use receiver name 'index' consistently. Fixes golang/go#60598 Change-Id: Icb88bde030a18bcab71d4cb74e0004fe27c815f4 Reviewed-on: https://go-review.googlesource.com/c/tools/+/502536 Run-TryBot: Alan Donovan <[email protected]> TryBot-Result: Gopher Robot <[email protected]> gopls-CI: kokoro <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 27fd94e commit 87ad891

File tree

6 files changed

+82
-72
lines changed

6 files changed

+82
-72
lines changed

gopls/internal/lsp/cache/check.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -884,15 +884,15 @@ func (b *packageHandleBuilder) getTransitiveRefsLocked(id PackageID) map[string]
884884
for name := range ph.refs {
885885
if token.IsExported(name) {
886886
pkgs := b.s.pkgIndex.NewSet()
887-
for _, node := range ph.refs[name] {
887+
for _, sym := range ph.refs[name] {
888888
// TODO: opt: avoid int -> PackageID -> int conversions here.
889-
id := node.PackageID(b.s.pkgIndex)
889+
id := b.s.pkgIndex.DeclaringPackage(sym)
890890
pkgs.Add(id)
891891
otherRefs := b.getTransitiveRefsLocked(id)
892892
if otherRefs == nil {
893893
return nil // a predecessor failed: exit early
894894
}
895-
if otherSet, ok := otherRefs[node.Name]; ok {
895+
if otherSet, ok := otherRefs[sym.Name]; ok {
896896
pkgs.Union(otherSet)
897897
}
898898
}

gopls/internal/lsp/source/typerefs/packageset.go

+22-13
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,25 @@ func NewPackageIndex() *PackageIndex {
3434

3535
// idx returns the packageIdx referencing id, creating one if id is not yet
3636
// tracked by the receiver.
37-
func (r *PackageIndex) idx(id source.PackageID) int {
38-
r.mu.Lock()
39-
defer r.mu.Unlock()
40-
if i, ok := r.m[id]; ok {
37+
func (index *PackageIndex) idx(id source.PackageID) int {
38+
index.mu.Lock()
39+
defer index.mu.Unlock()
40+
if i, ok := index.m[id]; ok {
4141
return i
4242
}
43-
i := len(r.ids)
44-
r.m[id] = i
45-
r.ids = append(r.ids, id)
43+
i := len(index.ids)
44+
index.m[id] = i
45+
index.ids = append(index.ids, id)
4646
return i
4747
}
4848

4949
// id returns the PackageID for idx.
5050
//
5151
// idx must have been created by this PackageIndex instance.
52-
func (r *PackageIndex) id(idx int) source.PackageID {
53-
r.mu.Lock()
54-
defer r.mu.Unlock()
55-
return r.ids[idx]
52+
func (index *PackageIndex) id(idx int) source.PackageID {
53+
index.mu.Lock()
54+
defer index.mu.Unlock()
55+
return index.ids[idx]
5656
}
5757

5858
// A PackageSet is a set of source.PackageIDs, optimized for inuse memory
@@ -70,18 +70,27 @@ const blockSize = bits.UintSize
7070
//
7171
// PackageSets may only be combined with other PackageSets from the same
7272
// instance.
73-
func (s *PackageIndex) NewSet() *PackageSet {
73+
func (index *PackageIndex) NewSet() *PackageSet {
7474
return &PackageSet{
75-
parent: s,
75+
parent: index,
7676
sparse: make(map[int]blockType),
7777
}
7878
}
7979

80+
// DeclaringPackage returns the ID of the symbol's declaring package.
81+
// The package index must be the one used during decoding.
82+
func (index *PackageIndex) DeclaringPackage(sym Symbol) source.PackageID {
83+
return index.id(sym.pkgIdx)
84+
}
85+
8086
// Add records a new element in the package set.
8187
func (s *PackageSet) Add(id source.PackageID) {
8288
s.add(s.parent.idx(id))
8389
}
8490

91+
// AddDeclaringPackage adds sym's declaring package to the set.
92+
func (s *PackageSet) AddDeclaringPackage(sym Symbol) { s.add(sym.pkgIdx) }
93+
8594
func (s *PackageSet) add(idx int) {
8695
i := int(idx)
8796
s.sparse[i/blockSize] |= 1 << (i % blockSize)

gopls/internal/lsp/source/typerefs/pkgrefs.go renamed to gopls/internal/lsp/source/typerefs/pkggraph_test.go

+50-18
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,23 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
package typerefs
5+
package typerefs_test
6+
7+
// This file is logically part of the test in pkgrefs_test.go: that
8+
// file defines the test assertion logic; this file provides a
9+
// reference implementation of a client of the typerefs package.
610

711
import (
12+
"bytes"
813
"context"
14+
"fmt"
15+
"os"
916
"runtime"
1017
"sync"
1118

1219
"golang.org/x/sync/errgroup"
1320
"golang.org/x/tools/gopls/internal/lsp/source"
21+
"golang.org/x/tools/gopls/internal/lsp/source/typerefs"
1422
"golang.org/x/tools/gopls/internal/span"
1523
)
1624

@@ -19,9 +27,6 @@ const (
1927
//
2028
// Warning: produces a lot of output! Best to run with small package queries.
2129
trace = false
22-
23-
// debug enables additional assertions.
24-
debug = false
2530
)
2631

2732
// A Package holds reference information for a single package.
@@ -32,18 +37,18 @@ type Package struct {
3237
// transitiveRefs records, for each exported declaration in the package, the
3338
// transitive set of packages within the containing graph that are
3439
// transitively reachable through references, starting with the given decl.
35-
transitiveRefs map[string]*PackageSet
40+
transitiveRefs map[string]*typerefs.PackageSet
3641

3742
// ReachesViaDeps records the set of packages in the containing graph whose
3843
// syntax may affect the current package's types. See the package
3944
// documentation for more details of what this means.
40-
ReachesByDeps *PackageSet
45+
ReachesByDeps *typerefs.PackageSet
4146
}
4247

4348
// A PackageGraph represents a fully analyzed graph of packages and their
4449
// dependencies.
4550
type PackageGraph struct {
46-
pkgIndex *PackageIndex
51+
pkgIndex *typerefs.PackageIndex
4752
meta source.MetadataSource
4853
parse func(context.Context, span.URI) (*source.ParsedGoFile, error)
4954

@@ -63,7 +68,7 @@ type PackageGraph struct {
6368
// algorithm.
6469
func BuildPackageGraph(ctx context.Context, meta source.MetadataSource, ids []source.PackageID, parse func(context.Context, span.URI) (*source.ParsedGoFile, error)) (*PackageGraph, error) {
6570
g := &PackageGraph{
66-
pkgIndex: NewPackageIndex(),
71+
pkgIndex: typerefs.NewPackageIndex(),
6772
meta: meta,
6873
parse: parse,
6974
packages: make(map[source.PackageID]*futurePackage),
@@ -120,7 +125,7 @@ func (g *PackageGraph) Package(ctx context.Context, id source.PackageID) (*Packa
120125
func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*Package, error) {
121126
p := &Package{
122127
metadata: g.meta.Metadata(id),
123-
transitiveRefs: make(map[string]*PackageSet),
128+
transitiveRefs: make(map[string]*typerefs.PackageSet),
124129
}
125130
var files []*source.ParsedGoFile
126131
for _, filename := range p.metadata.CompiledGoFiles {
@@ -138,9 +143,10 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
138143
}
139144

140145
// Compute the symbol-level dependencies through this package.
141-
// TODO(adonovan): opt: persist this in the filecache, keyed
146+
data := typerefs.Encode(files, id, imports)
147+
148+
// data can be persisted in a filecache, keyed
142149
// by hash(id, CompiledGoFiles, imports).
143-
data := Encode(files, id, imports)
144150

145151
// This point separates the local preprocessing
146152
// -- of a single package (above) from the global --
@@ -150,9 +156,33 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
150156
// package and declarations in this package or another
151157
// package. See the package documentation for a detailed
152158
// description of what these edges do (and do not) represent.
153-
classes := Decode(g.pkgIndex, id, data)
154-
155-
idx := g.pkgIndex.idx(id)
159+
classes := typerefs.Decode(g.pkgIndex, id, data)
160+
161+
// Debug
162+
if trace && len(classes) > 0 {
163+
var buf bytes.Buffer
164+
fmt.Fprintf(&buf, "%s\n", id)
165+
for _, class := range classes {
166+
for i, name := range class.Decls {
167+
if i == 0 {
168+
fmt.Fprintf(&buf, "\t")
169+
}
170+
fmt.Fprintf(&buf, " .%s", name)
171+
}
172+
// Group symbols by package.
173+
var prevID PackageID
174+
for _, sym := range class.Refs {
175+
id := g.pkgIndex.DeclaringPackage(sym)
176+
if id != prevID {
177+
prevID = id
178+
fmt.Fprintf(&buf, "\n\t\t-> %s:", id)
179+
}
180+
fmt.Fprintf(&buf, " .%s", sym.Name)
181+
}
182+
fmt.Fprintln(&buf)
183+
}
184+
os.Stderr.Write(buf.Bytes())
185+
}
156186

157187
// Now compute the transitive closure of packages reachable
158188
// from any exported symbol of this package.
@@ -164,8 +194,10 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
164194
// when the package id changes.
165195
depP := p
166196
for _, sym := range class.Refs {
167-
assert(sym.pkgIdx != idx, "intra-package edge")
168-
symPkgID := g.pkgIndex.id(sym.pkgIdx)
197+
symPkgID := g.pkgIndex.DeclaringPackage(sym)
198+
if symPkgID == id {
199+
panic("intra-package edge")
200+
}
169201
if depP.metadata.ID != symPkgID {
170202
// package changed
171203
var err error
@@ -174,7 +206,7 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
174206
return nil, err
175207
}
176208
}
177-
set.add(sym.pkgIdx)
209+
set.AddDeclaringPackage(sym)
178210
set.Union(depP.transitiveRefs[sym.Name])
179211
}
180212
for _, name := range class.Decls {
@@ -195,7 +227,7 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
195227

196228
// reachesByDeps computes the set of packages that are reachable through
197229
// dependencies of the package m.
198-
func (g *PackageGraph) reachesByDeps(ctx context.Context, m *source.Metadata) (*PackageSet, error) {
230+
func (g *PackageGraph) reachesByDeps(ctx context.Context, m *source.Metadata) (*typerefs.PackageSet, error) {
199231
transitive := g.pkgIndex.NewSet()
200232
for _, depID := range m.DepsByPkgPath {
201233
dep, err := g.Package(ctx, depID)

gopls/internal/lsp/source/typerefs/pkgrefs_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"golang.org/x/tools/gopls/internal/astutil"
2424
"golang.org/x/tools/gopls/internal/lsp/cache"
2525
"golang.org/x/tools/gopls/internal/lsp/source"
26-
"golang.org/x/tools/gopls/internal/lsp/source/typerefs"
2726
"golang.org/x/tools/gopls/internal/span"
2827
"golang.org/x/tools/internal/packagesinternal"
2928
"golang.org/x/tools/internal/testenv"
@@ -87,7 +86,7 @@ func TestBuildPackageGraph(t *testing.T) {
8786
})
8887

8988
t0 = time.Now()
90-
g, err := typerefs.BuildPackageGraph(ctx, meta, ids, newParser().parse)
89+
g, err := BuildPackageGraph(ctx, meta, ids, newParser().parse)
9190
if err != nil {
9291
t.Fatal(err)
9392
}
@@ -263,7 +262,7 @@ func BenchmarkBuildPackageGraph(b *testing.B) {
263262
b.ResetTimer()
264263

265264
for i := 0; i < b.N; i++ {
266-
_, err := typerefs.BuildPackageGraph(ctx, meta, ids, newParser().parse)
265+
_, err := BuildPackageGraph(ctx, meta, ids, newParser().parse)
267266
if err != nil {
268267
b.Fatal(err)
269268
}

gopls/internal/lsp/source/typerefs/refs.go

+4-34
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"go/ast"
1212
"go/token"
1313
"log"
14-
"os"
1514
"sort"
1615
"strings"
1716

@@ -65,12 +64,6 @@ type Symbol struct {
6564
Name string
6665
}
6766

68-
// PackageID returns the symbol's package identifier.
69-
// The package index must be the one used during decoding.
70-
func (sym Symbol) PackageID(index *PackageIndex) source.PackageID {
71-
return index.id(sym.pkgIdx)
72-
}
73-
7467
// -- internals --
7568

7669
// A symbolSet is a set of symbols used internally during index construction.
@@ -726,14 +719,16 @@ func (decl *declNode) find() *declNode {
726719
return rep
727720
}
728721

722+
const debugSCC = false // enable assertions in strong-component algorithm
723+
729724
func checkCanonical(x *declNode) {
730-
if debug {
725+
if debugSCC {
731726
assert(x == x.find(), "not canonical")
732727
}
733728
}
734729

735730
func assert(cond bool, msg string) {
736-
if debug && !cond {
731+
if debugSCC && !cond {
737732
panic(msg)
738733
}
739734
}
@@ -828,31 +823,6 @@ func decode(pkgIndex *PackageIndex, id source.PackageID, data []byte) []Class {
828823
return classes[i].Decls[0] < classes[j].Decls[0]
829824
})
830825

831-
// Debug
832-
if trace && len(classes) > 0 {
833-
var buf bytes.Buffer
834-
fmt.Fprintf(&buf, "%s\n", id)
835-
for _, class := range classes {
836-
for i, name := range class.Decls {
837-
if i == 0 {
838-
fmt.Fprintf(&buf, "\t")
839-
}
840-
fmt.Fprintf(&buf, " .%s", name)
841-
}
842-
// Group symbols by package.
843-
prevID := -1
844-
for _, sym := range class.Refs {
845-
if sym.pkgIdx != prevID {
846-
prevID = sym.pkgIdx
847-
fmt.Fprintf(&buf, "\n\t\t-> %s:", sym.PackageID(pkgIndex))
848-
}
849-
fmt.Fprintf(&buf, " .%s", sym.Name)
850-
}
851-
fmt.Fprintln(&buf)
852-
}
853-
os.Stderr.Write(buf.Bytes())
854-
}
855-
856826
return classes
857827
}
858828

gopls/internal/lsp/source/typerefs/refs_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ type Z map[ext.A]ext.B
543543
for _, name := range class.Decls {
544544
var syms []string
545545
for _, sym := range class.Refs {
546-
syms = append(syms, fmt.Sprintf("%s.%s", sym.PackageID(index), sym.Name))
546+
syms = append(syms, fmt.Sprintf("%s.%s", index.DeclaringPackage(sym), sym.Name))
547547
}
548548
sort.Strings(syms)
549549
got[name] = syms

0 commit comments

Comments
 (0)