Skip to content

Commit 57610ed

Browse files
committed
internal/lsp: rework snapshots and cache FileHandles per-snapshot
This change does not complete the work to handle snapshots correctly, but it does implement the behavior of re-building the snapshot on each file invalidation. It also moves to the approach of caching the FileHandles on the snapshot, rather than in the goFile object, which is now not necessary. Finally, this change shifts the logic of metadata invalidation into the content invalidation step, so there is less logic to decide if we should re-load a package or not. Change-Id: I18387c385fb070da4db1302bf97035ce6328b5c3 Reviewed-on: https://go-review.googlesource.com/c/tools/+/197799 Run-TryBot: Rebecca Stambler <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Cottrell <[email protected]>
1 parent 8b695b2 commit 57610ed

38 files changed

+641
-679
lines changed

internal/lsp/cache/check.go

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import (
2323
)
2424

2525
type importer struct {
26-
view *view
27-
ctx context.Context
28-
config *packages.Config
26+
snapshot *snapshot
27+
ctx context.Context
28+
config *packages.Config
2929

3030
// seen maintains the set of previously imported packages.
3131
// If we have seen a package that is already in this map, we have a circular import.
@@ -62,7 +62,7 @@ type checkPackageHandle struct {
6262
config *packages.Config
6363
}
6464

65-
func (cph *checkPackageHandle) mode() source.ParseMode {
65+
func (cph *checkPackageHandle) Mode() source.ParseMode {
6666
if len(cph.files) == 0 {
6767
return -1
6868
}
@@ -83,19 +83,15 @@ type checkPackageData struct {
8383
err error
8484
}
8585

86-
func (pkg *pkg) GetImport(ctx context.Context, pkgPath string) (source.Package, error) {
87-
if imp := pkg.imports[packagePath(pkgPath)]; imp != nil {
88-
return imp, nil
89-
}
90-
// Don't return a nil pointer because that still satisfies the interface.
91-
return nil, errors.Errorf("no imported package for %s", pkgPath)
92-
}
93-
9486
// checkPackageHandle returns a source.CheckPackageHandle for a given package and config.
95-
func (imp *importer) checkPackageHandle(ctx context.Context, m *metadata) (*checkPackageHandle, error) {
87+
func (imp *importer) checkPackageHandle(ctx context.Context, id packageID, s *snapshot) (*checkPackageHandle, error) {
88+
m := s.getMetadata(id)
89+
if m == nil {
90+
return nil, errors.Errorf("no metadata for %s", id)
91+
}
9692
phs, err := imp.parseGoHandles(ctx, m)
9793
if err != nil {
98-
log.Error(ctx, "no ParseGoHandles", err, telemetry.Package.Of(m.id))
94+
log.Error(ctx, "no ParseGoHandles", err, telemetry.Package.Of(id))
9995
return nil, err
10096
}
10197
cph := &checkPackageHandle{
@@ -104,12 +100,19 @@ func (imp *importer) checkPackageHandle(ctx context.Context, m *metadata) (*chec
104100
config: imp.config,
105101
imports: make(map[packagePath]*checkPackageHandle),
106102
}
107-
h := imp.view.session.cache.store.Bind(cph.key(), func(ctx context.Context) interface{} {
103+
h := imp.snapshot.view.session.cache.store.Bind(cph.key(), func(ctx context.Context) interface{} {
108104
data := &checkPackageData{}
109105
data.pkg, data.err = imp.typeCheck(ctx, cph, m)
110106
return data
111107
})
108+
112109
cph.handle = h
110+
111+
// Cache the CheckPackageHandle in the snapshot.
112+
for _, ph := range cph.files {
113+
uri := ph.File().Identity().URI
114+
s.addPackage(uri, cph)
115+
}
113116
return cph, nil
114117
}
115118

@@ -190,16 +193,16 @@ func (cph *checkPackageHandle) key() checkPackageKey {
190193
func (imp *importer) parseGoHandles(ctx context.Context, m *metadata) ([]source.ParseGoHandle, error) {
191194
phs := make([]source.ParseGoHandle, 0, len(m.files))
192195
for _, uri := range m.files {
193-
f, err := imp.view.GetFile(ctx, uri)
196+
f, err := imp.snapshot.view.GetFile(ctx, uri)
194197
if err != nil {
195198
return nil, err
196199
}
197-
fh := f.Handle(ctx)
200+
fh := imp.snapshot.Handle(ctx, f)
198201
mode := source.ParseExported
199202
if imp.topLevelPackageID == m.id {
200203
mode = source.ParseFull
201204
}
202-
phs = append(phs, imp.view.session.cache.ParseGoHandle(fh, mode))
205+
phs = append(phs, imp.snapshot.view.session.cache.ParseGoHandle(fh, mode))
203206
}
204207
return phs, nil
205208
}
@@ -236,7 +239,7 @@ func (imp *importer) typeCheck(ctx context.Context, cph *checkPackageHandle, m *
236239
defer done()
237240

238241
pkg := &pkg{
239-
view: imp.view,
242+
view: imp.snapshot.view,
240243
id: m.id,
241244
pkgPath: m.pkgPath,
242245
files: cph.Files(),
@@ -259,13 +262,17 @@ func (imp *importer) typeCheck(ctx context.Context, cph *checkPackageHandle, m *
259262
}
260263
// Set imports of package to correspond to cached packages.
261264
cimp := imp.child(ctx, pkg, cph)
262-
for _, child := range m.children {
263-
childHandle, err := cimp.checkPackageHandle(ctx, child)
265+
for _, depID := range m.deps {
266+
dep := imp.snapshot.getMetadata(depID)
267+
if dep == nil {
268+
continue
269+
}
270+
depHandle, err := cimp.checkPackageHandle(ctx, depID, imp.snapshot)
264271
if err != nil {
265-
log.Error(ctx, "no check package handle", err, telemetry.Package.Of(child.id))
272+
log.Error(ctx, "no check package handle", err, telemetry.Package.Of(depID))
266273
continue
267274
}
268-
cph.imports[child.pkgPath] = childHandle
275+
cph.imports[dep.pkgPath] = depHandle
269276
}
270277
var (
271278
files = make([]*ast.File, len(pkg.files))
@@ -284,7 +291,7 @@ func (imp *importer) typeCheck(ctx context.Context, cph *checkPackageHandle, m *
284291

285292
for _, err := range parseErrors {
286293
if err != nil {
287-
imp.view.session.cache.appendPkgError(pkg, err)
294+
imp.snapshot.view.session.cache.appendPkgError(pkg, err)
288295
}
289296
}
290297

@@ -308,11 +315,11 @@ func (imp *importer) typeCheck(ctx context.Context, cph *checkPackageHandle, m *
308315

309316
cfg := &types.Config{
310317
Error: func(err error) {
311-
imp.view.session.cache.appendPkgError(pkg, err)
318+
imp.snapshot.view.session.cache.appendPkgError(pkg, err)
312319
},
313320
Importer: cimp,
314321
}
315-
check := types.NewChecker(cfg, imp.view.session.cache.FileSet(), pkg.types, pkg.typesInfo)
322+
check := types.NewChecker(cfg, imp.snapshot.view.session.cache.FileSet(), pkg.types, pkg.typesInfo)
316323

317324
// Type checking errors are handled via the config, so ignore them here.
318325
_ = check.Files(files)
@@ -328,7 +335,7 @@ func (imp *importer) child(ctx context.Context, pkg *pkg, cph *checkPackageHandl
328335
}
329336
seen[pkg.id] = struct{}{}
330337
return &importer{
331-
view: imp.view,
338+
snapshot: imp.snapshot,
332339
ctx: ctx,
333340
config: imp.config,
334341
seen: seen,

internal/lsp/cache/file.go

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
package cache
66

77
import (
8-
"context"
98
"go/token"
109
"path/filepath"
1110
"strings"
12-
"sync"
1311

1412
"golang.org/x/tools/internal/lsp/source"
1513
"golang.org/x/tools/internal/span"
@@ -31,9 +29,6 @@ type fileBase struct {
3129
kind source.FileKind
3230

3331
view *view
34-
35-
handleMu sync.Mutex
36-
handle source.FileHandle
3732
}
3833

3934
func basename(filename string) string {
@@ -44,6 +39,10 @@ func (f *fileBase) URI() span.URI {
4439
return f.uris[0]
4540
}
4641

42+
func (f *fileBase) Kind() source.FileKind {
43+
return f.kind
44+
}
45+
4746
func (f *fileBase) filename() string {
4847
return f.fname
4948
}
@@ -53,17 +52,6 @@ func (f *fileBase) View() source.View {
5352
return f.view
5453
}
5554

56-
// Content returns a handle for the contents of the file.
57-
func (f *fileBase) Handle(ctx context.Context) source.FileHandle {
58-
f.handleMu.Lock()
59-
defer f.handleMu.Unlock()
60-
61-
if f.handle == nil {
62-
f.handle = f.view.session.GetFile(f.URI(), f.kind)
63-
}
64-
return f.handle
65-
}
66-
6755
func (f *fileBase) FileSet() *token.FileSet {
6856
return f.view.Session().Cache().FileSet()
6957
}

0 commit comments

Comments
 (0)