diff options
Diffstat (limited to 'internal/lsp/cache/imports.go')
-rw-r--r-- | internal/lsp/cache/imports.go | 201 |
1 files changed, 0 insertions, 201 deletions
diff --git a/internal/lsp/cache/imports.go b/internal/lsp/cache/imports.go deleted file mode 100644 index 01a2468ef..000000000 --- a/internal/lsp/cache/imports.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cache - -import ( - "context" - "fmt" - "reflect" - "strings" - "sync" - "time" - - "golang.org/x/tools/internal/event" - "golang.org/x/tools/internal/event/keys" - "golang.org/x/tools/internal/gocommand" - "golang.org/x/tools/internal/imports" - "golang.org/x/tools/internal/lsp/source" -) - -type importsState struct { - ctx context.Context - - mu sync.Mutex - processEnv *imports.ProcessEnv - cleanupProcessEnv func() - cacheRefreshDuration time.Duration - cacheRefreshTimer *time.Timer - cachedModFileHash string - cachedBuildFlags []string -} - -func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *snapshot, fn func(*imports.Options) error) error { - s.mu.Lock() - defer s.mu.Unlock() - - // Find the hash of the active mod file, if any. Using the unsaved content - // is slightly wasteful, since we'll drop caches a little too often, but - // the mod file shouldn't be changing while people are autocompleting. - var modFileHash string - // If we are using 'legacyWorkspace' mode, we can just read the modfile from - // the snapshot. Otherwise, we need to get the synthetic workspace mod file. - // - // TODO(rfindley): we should be able to just always use the synthetic - // workspace module, or alternatively use the go.work file. - if snapshot.workspace.moduleSource == legacyWorkspace { - for m := range snapshot.workspace.getActiveModFiles() { // range to access the only element - modFH, err := snapshot.GetFile(ctx, m) - if err != nil { - return err - } - modFileHash = modFH.FileIdentity().Hash - } - } else { - modFile, err := snapshot.workspace.modFile(ctx, snapshot) - if err != nil { - return err - } - modBytes, err := modFile.Format() - if err != nil { - return err - } - modFileHash = hashContents(modBytes) - } - - // view.goEnv is immutable -- changes make a new view. Options can change. - // We can't compare build flags directly because we may add -modfile. - snapshot.view.optionsMu.Lock() - localPrefix := snapshot.view.options.Local - currentBuildFlags := snapshot.view.options.BuildFlags - changed := !reflect.DeepEqual(currentBuildFlags, s.cachedBuildFlags) || - snapshot.view.options.VerboseOutput != (s.processEnv.Logf != nil) || - modFileHash != s.cachedModFileHash - snapshot.view.optionsMu.Unlock() - - // If anything relevant to imports has changed, clear caches and - // update the processEnv. Clearing caches blocks on any background - // scans. - if changed { - // As a special case, skip cleanup the first time -- we haven't fully - // initialized the environment yet and calling GetResolver will do - // unnecessary work and potentially mess up the go.mod file. - if s.cleanupProcessEnv != nil { - if resolver, err := s.processEnv.GetResolver(); err == nil { - if modResolver, ok := resolver.(*imports.ModuleResolver); ok { - modResolver.ClearForNewMod() - } - } - s.cleanupProcessEnv() - } - s.cachedModFileHash = modFileHash - s.cachedBuildFlags = currentBuildFlags - var err error - s.cleanupProcessEnv, err = s.populateProcessEnv(ctx, snapshot) - if err != nil { - return err - } - } - - // Run the user function. - opts := &imports.Options{ - // Defaults. - AllErrors: true, - Comments: true, - Fragment: true, - FormatOnly: false, - TabIndent: true, - TabWidth: 8, - Env: s.processEnv, - LocalPrefix: localPrefix, - } - - if err := fn(opts); err != nil { - return err - } - - if s.cacheRefreshTimer == nil { - // Don't refresh more than twice per minute. - delay := 30 * time.Second - // Don't spend more than a couple percent of the time refreshing. - if adaptive := 50 * s.cacheRefreshDuration; adaptive > delay { - delay = adaptive - } - s.cacheRefreshTimer = time.AfterFunc(delay, s.refreshProcessEnv) - } - - return nil -} - -// populateProcessEnv sets the dynamically configurable fields for the view's -// process environment. Assumes that the caller is holding the s.view.importsMu. -func (s *importsState) populateProcessEnv(ctx context.Context, snapshot *snapshot) (cleanup func(), err error) { - pe := s.processEnv - - if snapshot.view.Options().VerboseOutput { - pe.Logf = func(format string, args ...interface{}) { - event.Log(ctx, fmt.Sprintf(format, args...)) - } - } else { - pe.Logf = nil - } - - // Take an extra reference to the snapshot so that its workspace directory - // (if any) isn't destroyed while we're using it. - release := snapshot.generation.Acquire() - _, inv, cleanupInvocation, err := snapshot.goCommandInvocation(ctx, source.LoadWorkspace, &gocommand.Invocation{ - WorkingDir: snapshot.view.rootURI.Filename(), - }) - if err != nil { - return nil, err - } - pe.WorkingDir = inv.WorkingDir - pe.BuildFlags = inv.BuildFlags - pe.WorkingDir = inv.WorkingDir - pe.ModFile = inv.ModFile - pe.ModFlag = inv.ModFlag - pe.Env = map[string]string{} - for _, kv := range inv.Env { - split := strings.SplitN(kv, "=", 2) - if len(split) != 2 { - continue - } - pe.Env[split[0]] = split[1] - } - - return func() { - cleanupInvocation() - release() - }, nil -} - -func (s *importsState) refreshProcessEnv() { - start := time.Now() - - s.mu.Lock() - env := s.processEnv - if resolver, err := s.processEnv.GetResolver(); err == nil { - resolver.ClearForNewScan() - } - s.mu.Unlock() - - event.Log(s.ctx, "background imports cache refresh starting") - if err := imports.PrimeCache(context.Background(), env); err == nil { - event.Log(s.ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start))) - } else { - event.Log(s.ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)), keys.Err.Of(err)) - } - s.mu.Lock() - s.cacheRefreshDuration = time.Since(start) - s.cacheRefreshTimer = nil - s.mu.Unlock() -} - -func (s *importsState) destroy() { - s.mu.Lock() - if s.cleanupProcessEnv != nil { - s.cleanupProcessEnv() - } - s.mu.Unlock() -} |