// NewSession creates a new gopls session with the given cache. func NewSession(ctx context.Context, c *Cache) *Session { … } type Session … // ID returns the unique identifier for this session on this server. func (s *Session) ID() string { … } func (s *Session) String() string { … } // GoCommandRunner returns the gocommand Runner for this session. func (s *Session) GoCommandRunner() *gocommand.Runner { … } // Shutdown the session and all views it has created. func (s *Session) Shutdown(ctx context.Context) { … } // Cache returns the cache that created this session, for debugging only. func (s *Session) Cache() *Cache { … } var ErrViewExists … // NewView creates a new View, returning it and its first snapshot. If a // non-empty tempWorkspace directory is provided, the View will record a copy // of its gopls workspace module in that directory, so that client tooling // can execute in the same main module. On success it also returns a release // function that must be called when the Snapshot is no longer needed. func (s *Session) NewView(ctx context.Context, folder *Folder) (*View, *Snapshot, func(), error) { … } // createView creates a new view, with an initial snapshot that retains the // supplied context, detached from events and cancelation. // // The caller is responsible for calling the release function once. func (s *Session) createView(ctx context.Context, def *viewDefinition) (*View, *Snapshot, func()) { … } var viewTypeKey … var rootDirKey … var goVersionKey … var buildFlagsKey … var envKey … var envOverlayKey … // RemoveView removes from the session the view rooted at the specified directory. // It reports whether a view of that directory was removed. func (s *Session) RemoveView(ctx context.Context, dir protocol.DocumentURI) bool { … } // View returns the view with a matching id, if present. func (s *Session) View(id string) (*View, error) { … } // SnapshotOf returns a Snapshot corresponding to the given URI. // // In the case where the file can be can be associated with a View by // bestViewForURI (based on directory information alone, without package // metadata), SnapshotOf returns the current Snapshot for that View. Otherwise, // it awaits loading package metadata and returns a Snapshot for the first View // containing a real (=not command-line-arguments) package for the file. // // If that also fails to find a View, SnapshotOf returns a Snapshot for the // first view in s.views that is not shut down (i.e. s.views[0] unless we lose // a race), for determinism in tests and so that we tend to aggregate the // resulting command-line-arguments packages into a single view. // // SnapshotOf returns an error if a failure occurs along the way (most likely due // to context cancellation), or if there are no Views in the Session. // // On success, the caller must call the returned function to release the snapshot. func (s *Session) SnapshotOf(ctx context.Context, uri protocol.DocumentURI) (*Snapshot, func(), error) { … } var errNoViews … // viewOfLocked evaluates the best view for uri, memoizing its result in // s.viewMap. // // Precondition: caller holds s.viewMu lock. // // May return (nil, nil) if no best view can be determined. func (s *Session) viewOfLocked(ctx context.Context, uri protocol.DocumentURI) (*View, error) { … } func (s *Session) Views() []*View { … } // selectViewDefs constructs the best set of views covering the provided workspace // folders and open files. // // This implements the zero-config algorithm of golang/go#57979. func selectViewDefs(ctx context.Context, fs file.Source, folders []*Folder, openFiles []protocol.DocumentURI) ([]*viewDefinition, error) { … } type viewDefiner … // RelevantViews returns the views that may contain the given URI, or nil if // none exist. A view is "relevant" if, ignoring build constraints, it may have // a workspace package containing uri. Therefore, the definition of relevance // depends on the view type. func RelevantViews[V viewDefiner](ctx context.Context, fs file.Source, uri protocol.DocumentURI, views []V) ([]V, error) { … } // matchingView returns the View or viewDefinition out of relevantViews that // matches the given file's build constraints, or nil if no match is found. // // Making this function generic is convenient so that we can avoid mapping view // definitions back to views inside Session.DidModifyFiles, where performance // matters. It is, however, not the cleanest application of generics. // // Note: keep this function in sync with defineView. func matchingView[V viewDefiner](fh file.Handle, relevantViews []V) V { … } // ResetView resets the best view for the given URI. func (s *Session) ResetView(ctx context.Context, uri protocol.DocumentURI) (*View, error) { … } // DidModifyFiles reports a file modification to the session. It returns // the new snapshots after the modifications have been applied, paired with // the affected file URIs for those snapshots. // On success, it returns a release function that // must be called when the snapshots are no longer needed. // // TODO(rfindley): what happens if this function fails? It must leave us in a // broken state, which we should surface to the user, probably as a request to // restart gopls. func (s *Session) DidModifyFiles(ctx context.Context, modifications []file.Modification) (map[*View][]protocol.DocumentURI, error) { … } // ExpandModificationsToDirectories returns the set of changes with the // directory changes removed and expanded to include all of the files in // the directory. func (s *Session) ExpandModificationsToDirectories(ctx context.Context, changes []file.Modification) []file.Modification { … } // updateOverlays updates the set of overlays and returns a map of any existing // overlay values that were replaced. // // Precondition: caller holds s.viewMu lock. // TODO(rfindley): move this to fs_overlay.go. func (fs *overlayFS) updateOverlays(ctx context.Context, changes []file.Modification) (map[protocol.DocumentURI]*overlay, error) { … } func mustReadFile(ctx context.Context, fs file.Source, uri protocol.DocumentURI) file.Handle { … } type brokenFile … func (b brokenFile) URI() protocol.DocumentURI { … } func (b brokenFile) Identity() file.Identity { … } func (b brokenFile) SameContentsOnDisk() bool { … } func (b brokenFile) Version() int32 { … } func (b brokenFile) Content() ([]byte, error) { … } // FileWatchingGlobPatterns returns a set of glob patterns that the client is // required to watch for changes, and notify the server of them, in order to // keep the server's state up to date. // // This set includes // 1. all go.mod and go.work files in the workspace; and // 2. for each Snapshot, its modules (or directory for ad-hoc views). In // module mode, this is the set of active modules (and for VS Code, all // workspace directories within them, due to golang/go#42348). // // The watch for workspace go.work and go.mod files in (1) is sufficient to // capture changes to the repo structure that may affect the set of views. // Whenever this set changes, we reload the workspace and invalidate memoized // files. // // The watch for workspace directories in (2) should keep each View up to date, // as it should capture any newly added/modified/deleted Go files. // // Patterns are returned as a set of protocol.RelativePatterns, since they can // always be later translated to glob patterns (i.e. strings) if the client // lacks relative pattern support. By convention, any pattern returned with // empty baseURI should be served as a glob pattern. // // In general, we prefer to serve relative patterns, as they work better on // most clients that support both, and do not have issues with Windows driver // letter casing: // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#relativePattern // // TODO(golang/go#57979): we need to reset the memoizedFS when a view changes. // Consider the case where we incidentally read a file, then it moved outside // of an active module, and subsequently changed: we would still observe the // original file state. func (s *Session) FileWatchingGlobPatterns(ctx context.Context) map[protocol.RelativePattern]unit { … } // OrphanedFileDiagnostics reports diagnostics describing why open files have // no packages or have only command-line-arguments packages. // // If the resulting diagnostic is nil, the file is either not orphaned or we // can't produce a good diagnostic. // // The caller must not mutate the result. func (s *Session) OrphanedFileDiagnostics(ctx context.Context) (map[protocol.DocumentURI][]*Diagnostic, error) { … }