mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
internal/lsp: only cache type information for active packages
Currently, we cache source.CheckPackageHandles for each file and package that we are aware of, as well as dependencies. This is not necessary, since the active packages pin their imports in memory. Change-Id: Ia0101f4d4a2d36d5baeb890af3d7c8baec297847 Reviewed-on: https://go-review.googlesource.com/c/tools/+/196982 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
6816ec868d
commit
0f9bb8f614
44
internal/lsp/cache/check.go
vendored
44
internal/lsp/cache/check.go
vendored
@ -220,11 +220,6 @@ func (imp *importer) Import(pkgPath string) (*types.Package, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
imp.parentPkg.imports[packagePath(pkgPath)] = pkg
|
imp.parentPkg.imports[packagePath(pkgPath)] = pkg
|
||||||
|
|
||||||
// Add every file in this package to our cache.
|
|
||||||
if err := imp.cachePackage(ctx, cph); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return pkg.GetTypes(), nil
|
return pkg.GetTypes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,45 +330,6 @@ func (imp *importer) child(ctx context.Context, pkg *pkg, cph *checkPackageHandl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (imp *importer) cachePackage(ctx context.Context, cph *checkPackageHandle) error {
|
|
||||||
for _, ph := range cph.files {
|
|
||||||
uri := ph.File().Identity().URI
|
|
||||||
f, err := imp.view.GetFile(ctx, uri)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Errorf("no such file %s: %v", uri, err)
|
|
||||||
}
|
|
||||||
gof, ok := f.(*goFile)
|
|
||||||
if !ok {
|
|
||||||
return errors.Errorf("%s is not a Go file", uri)
|
|
||||||
}
|
|
||||||
if err := imp.cachePerFile(ctx, gof, ph, cph); err != nil {
|
|
||||||
return errors.Errorf("failed to cache file %s: %v", gof.URI(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (imp *importer) cachePerFile(ctx context.Context, gof *goFile, ph source.ParseGoHandle, cph *checkPackageHandle) error {
|
|
||||||
gof.mu.Lock()
|
|
||||||
defer gof.mu.Unlock()
|
|
||||||
|
|
||||||
// Set the package even if we failed to parse the file.
|
|
||||||
if gof.cphs == nil {
|
|
||||||
gof.cphs = make(map[packageKey]*checkPackageHandle)
|
|
||||||
}
|
|
||||||
gof.cphs[packageKey{
|
|
||||||
id: cph.m.id,
|
|
||||||
mode: ph.Mode(),
|
|
||||||
}] = cph
|
|
||||||
|
|
||||||
file, _, _, err := ph.Parse(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
gof.imports = file.Imports
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cache) appendPkgError(pkg *pkg, err error) {
|
func (c *cache) appendPkgError(pkg *pkg, err error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
|
1
internal/lsp/cache/external.go
vendored
1
internal/lsp/cache/external.go
vendored
@ -53,6 +53,7 @@ func (h *nativeFileHandle) Identity() source.FileIdentity {
|
|||||||
func (h *nativeFileHandle) Read(ctx context.Context) ([]byte, string, error) {
|
func (h *nativeFileHandle) Read(ctx context.Context) ([]byte, string, error) {
|
||||||
ctx, done := trace.StartSpan(ctx, "cache.nativeFileHandle.Read", telemetry.File.Of(h.identity.URI.Filename()))
|
ctx, done := trace.StartSpan(ctx, "cache.nativeFileHandle.Read", telemetry.File.Of(h.identity.URI.Filename()))
|
||||||
defer done()
|
defer done()
|
||||||
|
|
||||||
ioLimit <- struct{}{}
|
ioLimit <- struct{}{}
|
||||||
defer func() { <-ioLimit }()
|
defer func() { <-ioLimit }()
|
||||||
// TODO: this should fail if the version is not the same as the handle
|
// TODO: this should fail if the version is not the same as the handle
|
||||||
|
39
internal/lsp/cache/load.go
vendored
39
internal/lsp/cache/load.go
vendored
@ -7,6 +7,7 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
"golang.org/x/tools/internal/lsp/source"
|
"golang.org/x/tools/internal/lsp/source"
|
||||||
@ -38,15 +39,45 @@ func (view *view) loadParseTypecheck(ctx context.Context, f *goFile, fh source.F
|
|||||||
log.Error(ctx, "loadParseTypeCheck: failed to get CheckPackageHandle", err, telemetry.Package.Of(m.id))
|
log.Error(ctx, "loadParseTypeCheck: failed to get CheckPackageHandle", err, telemetry.Package.Of(m.id))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Cache this package on the file object, since all dependencies are cached in the Import function.
|
// Cache the package type information for the top-level package.
|
||||||
if err := imp.cachePackage(ctx, cph); err != nil {
|
for _, ph := range cph.files {
|
||||||
log.Error(ctx, "loadParseTypeCheck: failed to cache package", err, telemetry.Package.Of(m.id))
|
file, _, _, err := ph.Parse(ctx)
|
||||||
continue
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f, err := imp.view.GetFile(ctx, ph.File().Identity().URI)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Errorf("no such file %s: %v", ph.File().Identity().URI, err)
|
||||||
|
}
|
||||||
|
gof, ok := f.(*goFile)
|
||||||
|
if !ok {
|
||||||
|
return errors.Errorf("%s is not a Go file", ph.File().Identity().URI)
|
||||||
|
}
|
||||||
|
if err := cachePerFile(ctx, gof, ph.Mode(), file.Imports, cph); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cachePerFile(ctx context.Context, f *goFile, mode source.ParseMode, imports []*ast.ImportSpec, cph *checkPackageHandle) error {
|
||||||
|
f.mu.Lock()
|
||||||
|
defer f.mu.Unlock()
|
||||||
|
|
||||||
|
f.imports = imports
|
||||||
|
|
||||||
|
if f.cphs == nil {
|
||||||
|
f.cphs = make(map[packageKey]*checkPackageHandle)
|
||||||
|
}
|
||||||
|
f.cphs[packageKey{
|
||||||
|
id: cph.m.id,
|
||||||
|
mode: mode,
|
||||||
|
}] = cph
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (view *view) load(ctx context.Context, f *goFile, fh source.FileHandle) ([]*metadata, error) {
|
func (view *view) load(ctx context.Context, f *goFile, fh source.FileHandle) ([]*metadata, error) {
|
||||||
ctx, done := trace.StartSpan(ctx, "cache.view.load", telemetry.URI.Of(f.URI()))
|
ctx, done := trace.StartSpan(ctx, "cache.view.load", telemetry.URI.Of(f.URI()))
|
||||||
defer done()
|
defer done()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user