diff --git a/internal/imports/fix.go b/internal/imports/fix.go index 7fd513062f..916ddf3ac6 100644 --- a/internal/imports/fix.go +++ b/internal/imports/fix.go @@ -846,6 +846,8 @@ type Resolver interface { // loadExports returns the set of exported symbols in the package at dir. // loadExports may be called concurrently. loadExports(ctx context.Context, pkg *pkg) (string, []string, error) + + ClearForNewScan() } // gopackagesResolver implements resolver for GOPATH and module workspaces using go/packages. @@ -853,6 +855,8 @@ type goPackagesResolver struct { env *ProcessEnv } +func (r *goPackagesResolver) ClearForNewScan() {} + func (r *goPackagesResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) { if len(importPaths) == 0 { return nil, nil @@ -1032,6 +1036,10 @@ func (r *gopathResolver) init() { } } +func (r *gopathResolver) ClearForNewScan() { + r.cache = nil +} + func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) { r.init() names := map[string]string{} diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go index 2a5c45e791..118a21d95f 100644 --- a/internal/lsp/cache/view.go +++ b/internal/lsp/cache/view.go @@ -14,6 +14,7 @@ import ( "os/exec" "strings" "sync" + "time" "golang.org/x/tools/go/packages" "golang.org/x/tools/internal/imports" @@ -22,6 +23,7 @@ import ( "golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/span" "golang.org/x/tools/internal/telemetry/log" + "golang.org/x/tools/internal/telemetry/tag" "golang.org/x/tools/internal/xcontext" errors "golang.org/x/xerrors" ) @@ -59,7 +61,8 @@ type view struct { // TODO(suzmue): the state cached in the process env is specific to each view, // however, there is state that can be shared between views that is not currently // cached, like the module cache. - processEnv *imports.ProcessEnv + processEnv *imports.ProcessEnv + cacheRefreshTime time.Time // modFileVersions stores the last seen versions of the module files that are used // by processEnvs resolver. @@ -142,12 +145,8 @@ func (v *view) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) } // Before running the user provided function, clear caches in the resolver. - if r, ok := v.processEnv.GetResolver().(*imports.ModuleResolver); ok { - if v.modFilesChanged() { - r.ClearForNewMod() - } else { - r.ClearForNewScan() - } + if v.modFilesChanged() { + v.processEnv.GetResolver().(*imports.ModuleResolver).ClearForNewMod() } // Run the user function. @@ -155,11 +154,27 @@ func (v *view) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) if err := fn(opts); err != nil { return err } + if v.cacheRefreshTime.IsZero() { + v.cacheRefreshTime = time.Now() + } // If applicable, store the file versions of the 'go.mod' files that are // looked at by the resolver. v.storeModFileVersions() + if time.Since(v.cacheRefreshTime) > 30*time.Second { + go func() { + v.mu.Lock() + defer v.mu.Unlock() + + log.Print(context.Background(), "background imports cache refresh starting") + v.processEnv.GetResolver().ClearForNewScan() + _, err := imports.GetAllCandidates("", opts) + v.cacheRefreshTime = time.Now() + log.Print(context.Background(), "background refresh finished with err: ", tag.Of("err", err)) + }() + } + return nil }