type Snapshot … var _ … func (s *Snapshot) awaitPromise(ctx context.Context, p *memoize.Promise) (interface{ … } // Acquire prevents the snapshot from being destroyed until the returned // function is called. // // (s.Acquire().release() could instead be expressed as a pair of // method calls s.IncRef(); s.DecRef(). The latter has the advantage // that the DecRefs are fungible and don't require holding anything in // addition to the refcounted object s, but paradoxically that is also // an advantage of the current approach, which forces the caller to // consider the release function at every stage, making a reference // leak more obvious.) func (s *Snapshot) Acquire() func() { … } // decref should only be referenced by Acquire, and by View when it frees its // reference to View.snapshot. func (s *Snapshot) decref() { … } // SequenceID is the sequence id of this snapshot within its containing // view. // // Relative to their view sequence ids are monotonically increasing, but this // does not hold globally: when new views are created their initial snapshot // has sequence ID 0. func (s *Snapshot) SequenceID() uint64 { … } // SnapshotLabels returns a new slice of labels that should be used for events // related to a snapshot. func (s *Snapshot) Labels() []label.Label { … } // Folder returns the folder at the base of this snapshot. func (s *Snapshot) Folder() protocol.DocumentURI { … } // View returns the View associated with this snapshot. func (s *Snapshot) View() *View { … } // FileKind returns the kind of a file. // // We can't reliably deduce the kind from the file name alone, // as some editors can be told to interpret a buffer as // language different from the file name heuristic, e.g. that // an .html file actually contains Go "html/template" syntax, // or even that a .go file contains Python. func (s *Snapshot) FileKind(fh file.Handle) file.Kind { … } // fileKind returns the default file kind for a file, before considering // template file extensions. See [Snapshot.FileKind]. func fileKind(fh file.Handle) file.Kind { … } // Options returns the options associated with this snapshot. func (s *Snapshot) Options() *settings.Options { … } // BackgroundContext returns a context used for all background processing // on behalf of this snapshot. func (s *Snapshot) BackgroundContext() context.Context { … } // Templates returns the .tmpl files. func (s *Snapshot) Templates() map[protocol.DocumentURI]file.Handle { … } // config returns the configuration used for the snapshot's interaction with // the go/packages API. It uses the given working directory. // // TODO(rstambler): go/packages requires that we do not provide overlays for // multiple modules in one config, so buildOverlay needs to filter overlays by // module. func (s *Snapshot) config(ctx context.Context, inv *gocommand.Invocation) *packages.Config { … } // RunGoModUpdateCommands runs a series of `go` commands that updates the go.mod // and go.sum file for wd, and returns their updated contents. // // TODO(rfindley): the signature of RunGoModUpdateCommands is very confusing, // and is the only thing forcing the ModFlag and ModFile indirection. // Simplify it. func (s *Snapshot) RunGoModUpdateCommands(ctx context.Context, modURI protocol.DocumentURI, run func(invoke func(...string) (*bytes.Buffer, error)) error) ([]byte, []byte, error) { … } // TempModDir creates a temporary directory with the contents of the provided // modURI, as well as its corresponding go.sum file, if it exists. On success, // it is the caller's responsibility to call the cleanup function to remove the // directory when it is no longer needed. func TempModDir(ctx context.Context, fs file.Source, modURI protocol.DocumentURI) (dir string, _ func(), rerr error) { … } // GoCommandInvocation populates inv with configuration for running go commands // on the snapshot. // // On success, the caller must call the cleanup function exactly once // when the invocation is no longer needed. // // TODO(rfindley): although this function has been simplified significantly, // additional refactoring is still required: the responsibility for Env and // BuildFlags should be more clearly expressed in the API. // // If allowNetwork is set, do not set GOPROXY=off. func (s *Snapshot) GoCommandInvocation(allowNetwork bool, inv *gocommand.Invocation) (_ *gocommand.Invocation, cleanup func(), _ error) { … } // buildOverlays returns a new mapping from logical file name to // effective content, for each unsaved editor buffer, in the same form // as [packages.Cfg]'s Overlay field. func (s *Snapshot) buildOverlays() map[string][]byte { … } // Overlays returns the set of overlays at this snapshot. // // Note that this may differ from the set of overlays on the server, if the // snapshot observed a historical state. func (s *Snapshot) Overlays() []*overlay { … } const xrefsKind … const methodSetsKind … const testsKind … const exportDataKind … const diagnosticsKind … const typerefsKind … // PackageDiagnostics returns diagnostics for files contained in specified // packages. // // If these diagnostics cannot be loaded from cache, the requested packages // may be type-checked. func (s *Snapshot) PackageDiagnostics(ctx context.Context, ids ...PackageID) (map[protocol.DocumentURI][]*Diagnostic, error) { … } // References returns cross-reference indexes for the specified packages. // // If these indexes cannot be loaded from cache, the requested packages may // be type-checked. func (s *Snapshot) References(ctx context.Context, ids ...PackageID) ([]xrefIndex, error) { … } type xrefIndex … func (index xrefIndex) Lookup(targets map[PackagePath]map[objectpath.Path]struct{ … } // MethodSets returns method-set indexes for the specified packages. // // If these indexes cannot be loaded from cache, the requested packages may // be type-checked. func (s *Snapshot) MethodSets(ctx context.Context, ids ...PackageID) ([]*methodsets.Index, error) { … } // Tests returns test-set indexes for the specified packages. There is a // one-to-one correspondence between ID and Index. // // If these indexes cannot be loaded from cache, the requested packages may be // type-checked. func (s *Snapshot) Tests(ctx context.Context, ids ...PackageID) ([]*testfuncs.Index, error) { … } // MetadataForFile returns a new slice containing metadata for each // package containing the Go file identified by uri, ordered by the // number of CompiledGoFiles (i.e. "narrowest" to "widest" package), // and secondarily by IsIntermediateTestVariant (false < true). // The result may include tests and intermediate test variants of // importable packages. // It returns an error if the context was cancelled. func (s *Snapshot) MetadataForFile(ctx context.Context, uri protocol.DocumentURI) ([]*metadata.Package, error) { … } func boolLess(x, y bool) bool { … } // ReverseDependencies returns a new mapping whose entries are // the ID and Metadata of each package in the workspace that // directly or transitively depend on the package denoted by id, // excluding id itself. func (s *Snapshot) ReverseDependencies(ctx context.Context, id PackageID, transitive bool) (map[PackageID]*metadata.Package, error) { … } // See Session.FileWatchingGlobPatterns for a description of gopls' file // watching heuristic. func (s *Snapshot) fileWatchingGlobPatterns() map[protocol.RelativePattern]unit { … } func (s *Snapshot) addKnownSubdirs(patterns map[protocol.RelativePattern]unit, wsDirs []string) { … } // watchSubdirs reports whether gopls should request separate file watchers for // each relevant subdirectory. This is necessary only for clients (namely VS // Code) that do not send notifications for individual files in a directory // when the entire directory is deleted. func (s *Snapshot) watchSubdirs() bool { … } // filesInDir returns all files observed by the snapshot that are contained in // a directory with the provided URI. func (s *Snapshot) filesInDir(uri protocol.DocumentURI) []protocol.DocumentURI { … } // WorkspaceMetadata returns a new, unordered slice containing // metadata for all ordinary and test packages (but not // intermediate test variants) in the workspace. // // The workspace is the set of modules typically defined by a // go.work file. It is not transitively closed: for example, // the standard library is not usually part of the workspace // even though every module in the workspace depends on it. // // Operations that must inspect all the dependencies of the // workspace packages should instead use AllMetadata. func (s *Snapshot) WorkspaceMetadata(ctx context.Context) ([]*metadata.Package, error) { … } // isWorkspacePackage reports whether the given package ID refers to a // workspace package for the snapshot. func (s *Snapshot) isWorkspacePackage(id PackageID) bool { … } // Symbols extracts and returns symbol information for every file contained in // a loaded package. It awaits snapshot loading. // // If workspaceOnly is set, this only includes symbols from files in a // workspace package. Otherwise, it returns symbols from all loaded packages. // // TODO(rfindley): move to symbols.go. func (s *Snapshot) Symbols(ctx context.Context, workspaceOnly bool) (map[protocol.DocumentURI][]Symbol, error) { … } // AllMetadata returns a new unordered array of metadata for // all packages known to this snapshot, which includes the // packages of all workspace modules plus their transitive // import dependencies. // // It may also contain ad-hoc packages for standalone files. // It includes all test variants. // // TODO(rfindley): Replace this with s.MetadataGraph(). func (s *Snapshot) AllMetadata(ctx context.Context) ([]*metadata.Package, error) { … } // GoModForFile returns the URI of the go.mod file for the given URI. // // TODO(rfindley): clarify that this is only active modules. Or update to just // use findRootPattern. func (s *Snapshot) GoModForFile(uri protocol.DocumentURI) protocol.DocumentURI { … } func moduleForURI(modFiles map[protocol.DocumentURI]struct{ … } // nearestModFile finds the nearest go.mod file contained in the directory // containing uri, or a parent of that directory. // // The given uri must be a file, not a directory. func nearestModFile(ctx context.Context, uri protocol.DocumentURI, fs file.Source) (protocol.DocumentURI, error) { … } // Metadata returns the metadata for the specified package, // or nil if it was not found. func (s *Snapshot) Metadata(id PackageID) *metadata.Package { … } // clearShouldLoad clears package IDs that no longer need to be reloaded after // scopes has been loaded. func (s *Snapshot) clearShouldLoad(scopes ...loadScope) { … } // FindFile returns the FileHandle for the given URI, if it is already // in the given snapshot. // TODO(adonovan): delete this operation; use ReadFile instead. func (s *Snapshot) FindFile(uri protocol.DocumentURI) file.Handle { … } // ReadFile returns a File for the given URI. If the file is unknown it is added // to the managed set. // // ReadFile succeeds even if the file does not exist. A non-nil error return // indicates some type of internal error, for example if ctx is cancelled. func (s *Snapshot) ReadFile(ctx context.Context, uri protocol.DocumentURI) (file.Handle, error) { … } type lockedSnapshot … func (s lockedSnapshot) ReadFile(ctx context.Context, uri protocol.DocumentURI) (file.Handle, error) { … } // preloadFiles delegates to the view FileSource to read the requested uris in // parallel, without holding the snapshot lock. func (s *Snapshot) preloadFiles(ctx context.Context, uris []protocol.DocumentURI) { … } // IsOpen returns whether the editor currently has a file open. func (s *Snapshot) IsOpen(uri protocol.DocumentURI) bool { … } // MetadataGraph returns the current metadata graph for the Snapshot. func (s *Snapshot) MetadataGraph() *metadata.Graph { … } // InitializationError returns the last error from initialization. func (s *Snapshot) InitializationError() *InitializationError { … } // awaitLoaded awaits initialization and package reloading, and returns // ctx.Err(). func (s *Snapshot) awaitLoaded(ctx context.Context) error { … } // AwaitInitialized waits until the snapshot's view is initialized. func (s *Snapshot) AwaitInitialized(ctx context.Context) { … } // reloadWorkspace reloads the metadata for all invalidated workspace packages. func (s *Snapshot) reloadWorkspace(ctx context.Context) { … } func (s *Snapshot) orphanedFileDiagnostics(ctx context.Context, overlays []*overlay) ([]*Diagnostic, error) { … } // orphanedFileDiagnosticRange returns the position to use for orphaned file diagnostics. // We only warn about an orphaned file if it is well-formed enough to actually // be part of a package. Otherwise, we need more information. func orphanedFileDiagnosticRange(ctx context.Context, cache *parseCache, fh file.Handle) (*parsego.File, protocol.Range, bool) { … } // TODO(golang/go#53756): this function needs to consider more than just the // absolute URI, for example: // - the position of /vendor/ with respect to the relevant module root // - whether or not go.work is in use (as vendoring isn't supported in workspace mode) // // Most likely, each call site of inVendor needs to be reconsidered to // understand and correctly implement the desired behavior. func inVendor(uri protocol.DocumentURI) bool { … } // clone copies state from the receiver into a new Snapshot, applying the given // state changes. // // The caller of clone must call Snapshot.decref on the returned // snapshot when they are finished using it. // // The resulting bool reports whether the change invalidates any derived // diagnostics for the snapshot, for example because it invalidates Packages or // parsed go.mod files. This is used to mark a view as needing diagnosis in the // server. // // TODO(rfindley): long term, it may be better to move responsibility for // diagnostics into the Snapshot (e.g. a Snapshot.Diagnostics method), at which // point the Snapshot could be responsible for tracking and forwarding a // 'viewsToDiagnose' field. As is, this field is instead externalized in the // server.viewsToDiagnose map. Moving it to the snapshot would entirely // eliminate any 'relevance' heuristics from Session.DidModifyFiles, but would // also require more strictness about diagnostic dependencies. For example, // template.Diagnostics currently re-parses every time: there is no Snapshot // data responsible for providing these diagnostics. func (s *Snapshot) clone(ctx, bgCtx context.Context, changed StateChange, done func()) (*Snapshot, bool) { … } // cloneWithout clones m then deletes from it the keys of changes. // // The optional didDelete variable is set to true if there were deletions. func cloneWithout[K constraints.Ordered, V1, V2 any](m *persistent.Map[K, V1], changes map[K]V2, didDelete *bool) *persistent.Map[K, V1] { … } // cloneWith clones m then inserts the changes into it. func cloneWith[K constraints.Ordered, V any](m *persistent.Map[K, V], changes map[K]V) *persistent.Map[K, V] { … } // deleteMostRelevantModFile deletes the mod file most likely to be the mod // file for the changed URI, if it exists. // // Specifically, this is the longest mod file path in a directory containing // changed. This might not be accurate if there is another mod file closer to // changed that happens not to be present in the map, but that's OK: the goal // of this function is to guarantee that IF the nearest mod file is present in // the map, it is invalidated. func deleteMostRelevantModFile(m *persistent.Map[protocol.DocumentURI, *memoize.Promise], changed protocol.DocumentURI) { … } // invalidatedPackageIDs returns all packages invalidated by a change to uri. // If we haven't seen this URI before, we guess based on files in the same // directory. This is of course incorrect in build systems where packages are // not organized by directory. // // If packageFileChanged is set, the file is either a new file, or has a new // package name. In this case, all known packages in the directory will be // invalidated. func invalidatedPackageIDs(uri protocol.DocumentURI, known map[protocol.DocumentURI][]PackageID, packageFileChanged bool) map[PackageID]struct{ … } // fileWasSaved reports whether the FileHandle passed in has been saved. It // accomplishes this by checking to see if the original and current FileHandles // are both overlays, and if the current FileHandle is saved while the original // FileHandle was not saved. func fileWasSaved(originalFH, currentFH file.Handle) bool { … } // metadataChanges detects features of the change from oldFH->newFH that may // affect package metadata. // // It uses lockedSnapshot to access cached parse information. lockedSnapshot // must be locked. // // The result parameters have the following meaning: // - invalidate means that package metadata for packages containing the file // should be invalidated. // - pkgFileChanged means that the file->package associates for the file have // changed (possibly because the file is new, or because its package name has // changed). // - importDeleted means that an import has been deleted, or we can't // determine if an import was deleted due to errors. func metadataChanges(ctx context.Context, lockedSnapshot *Snapshot, oldFH, newFH file.Handle) (invalidate, pkgFileChanged, importDeleted bool) { … } func magicCommentsChanged(original *ast.File, current *ast.File) bool { … } // validImportPaths extracts the set of valid import paths from imports. func validImportPaths(imports []*ast.ImportSpec) map[string]struct{ … } func validImportPath(path string) bool { … } var buildConstraintOrEmbedRe … // extractMagicComments finds magic comments that affect metadata in f. func extractMagicComments(f *ast.File) []string { … } // BuiltinFile returns the pseudo-source file builtins.go, // parsed with legacy ast.Object resolution. func (s *Snapshot) BuiltinFile(ctx context.Context) (*parsego.File, error) { … } // IsBuiltin reports whether uri is part of the builtin package. func (s *Snapshot) IsBuiltin(uri protocol.DocumentURI) bool { … } func (s *Snapshot) setBuiltin(path string) { … } // WantGCDetails reports whether to compute GC optimization details for the // specified package. func (s *Snapshot) WantGCDetails(id metadata.PackageID) bool { … } type CodeLensSourceFunc …