2
2
// Use of this source code is governed by a BSD-style
3
3
// license that can be found in the LICENSE file.
4
4
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.
6
10
7
11
import (
12
+ "bytes"
8
13
"context"
14
+ "fmt"
15
+ "os"
9
16
"runtime"
10
17
"sync"
11
18
12
19
"golang.org/x/sync/errgroup"
13
20
"golang.org/x/tools/gopls/internal/lsp/source"
21
+ "golang.org/x/tools/gopls/internal/lsp/source/typerefs"
14
22
"golang.org/x/tools/gopls/internal/span"
15
23
)
16
24
@@ -19,9 +27,6 @@ const (
19
27
//
20
28
// Warning: produces a lot of output! Best to run with small package queries.
21
29
trace = false
22
-
23
- // debug enables additional assertions.
24
- debug = false
25
30
)
26
31
27
32
// A Package holds reference information for a single package.
@@ -32,18 +37,18 @@ type Package struct {
32
37
// transitiveRefs records, for each exported declaration in the package, the
33
38
// transitive set of packages within the containing graph that are
34
39
// transitively reachable through references, starting with the given decl.
35
- transitiveRefs map [string ]* PackageSet
40
+ transitiveRefs map [string ]* typerefs. PackageSet
36
41
37
42
// ReachesViaDeps records the set of packages in the containing graph whose
38
43
// syntax may affect the current package's types. See the package
39
44
// documentation for more details of what this means.
40
- ReachesByDeps * PackageSet
45
+ ReachesByDeps * typerefs. PackageSet
41
46
}
42
47
43
48
// A PackageGraph represents a fully analyzed graph of packages and their
44
49
// dependencies.
45
50
type PackageGraph struct {
46
- pkgIndex * PackageIndex
51
+ pkgIndex * typerefs. PackageIndex
47
52
meta source.MetadataSource
48
53
parse func (context.Context , span.URI ) (* source.ParsedGoFile , error )
49
54
@@ -63,7 +68,7 @@ type PackageGraph struct {
63
68
// algorithm.
64
69
func BuildPackageGraph (ctx context.Context , meta source.MetadataSource , ids []source.PackageID , parse func (context.Context , span.URI ) (* source.ParsedGoFile , error )) (* PackageGraph , error ) {
65
70
g := & PackageGraph {
66
- pkgIndex : NewPackageIndex (),
71
+ pkgIndex : typerefs . NewPackageIndex (),
67
72
meta : meta ,
68
73
parse : parse ,
69
74
packages : make (map [source.PackageID ]* futurePackage ),
@@ -120,7 +125,7 @@ func (g *PackageGraph) Package(ctx context.Context, id source.PackageID) (*Packa
120
125
func (g * PackageGraph ) buildPackage (ctx context.Context , id source.PackageID ) (* Package , error ) {
121
126
p := & Package {
122
127
metadata : g .meta .Metadata (id ),
123
- transitiveRefs : make (map [string ]* PackageSet ),
128
+ transitiveRefs : make (map [string ]* typerefs. PackageSet ),
124
129
}
125
130
var files []* source.ParsedGoFile
126
131
for _ , filename := range p .metadata .CompiledGoFiles {
@@ -138,9 +143,10 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
138
143
}
139
144
140
145
// 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
142
149
// by hash(id, CompiledGoFiles, imports).
143
- data := Encode (files , id , imports )
144
150
145
151
// This point separates the local preprocessing
146
152
// -- of a single package (above) from the global --
@@ -150,9 +156,33 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
150
156
// package and declarations in this package or another
151
157
// package. See the package documentation for a detailed
152
158
// 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
+ }
156
186
157
187
// Now compute the transitive closure of packages reachable
158
188
// from any exported symbol of this package.
@@ -164,8 +194,10 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
164
194
// when the package id changes.
165
195
depP := p
166
196
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
+ }
169
201
if depP .metadata .ID != symPkgID {
170
202
// package changed
171
203
var err error
@@ -174,7 +206,7 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
174
206
return nil , err
175
207
}
176
208
}
177
- set .add (sym . pkgIdx )
209
+ set .AddDeclaringPackage (sym )
178
210
set .Union (depP .transitiveRefs [sym .Name ])
179
211
}
180
212
for _ , name := range class .Decls {
@@ -195,7 +227,7 @@ func (g *PackageGraph) buildPackage(ctx context.Context, id source.PackageID) (*
195
227
196
228
// reachesByDeps computes the set of packages that are reachable through
197
229
// 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 ) {
199
231
transitive := g .pkgIndex .NewSet ()
200
232
for _ , depID := range m .DepsByPkgPath {
201
233
dep , err := g .Package (ctx , depID )
0 commit comments