diff --git a/internal/lsp/cache/session.go b/internal/lsp/cache/session.go index fcf7f26cac..863e844132 100644 --- a/internal/lsp/cache/session.go +++ b/internal/lsp/cache/session.go @@ -115,7 +115,13 @@ func (s *session) createView(ctx context.Context, name string, folder span.URI, // Preemptively build the builtin package, // so we immediately add builtin.go to the list of ignored files. - v.buildBuiltinPackage(ctx) + // TODO(rstambler): This could be part of the initialization process. + if err := v.buildBuiltinPackage(ctx); err != nil { + return nil, nil, err + } + + // Initialize the view without blocking. + go v.initialize(xcontext.Detach(ctx), v.snapshot) debug.AddView(debugView{v}) return v, v.snapshot, nil diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go index a184582407..a276805a74 100644 --- a/internal/lsp/cache/view.go +++ b/internal/lsp/cache/view.go @@ -470,11 +470,18 @@ func (v *view) getSnapshot() *snapshot { func (v *view) WorkspacePackageIDs(ctx context.Context) ([]string, error) { s := v.getSnapshot() + if err := s.awaitInitialized(ctx); err != nil { + return nil, err + } + return s.workspacePackageIDs(), nil +} + +func (v *view) initialize(ctx context.Context, s *snapshot) { v.initializeOnce.Do(func() { defer close(v.initialized) // Do not cancel the call to go/packages.Load for the entire workspace. - meta, err := s.load(xcontext.Detach(ctx), directoryURI(v.folder)) + meta, err := s.load(ctx, directoryURI(v.folder)) if err != nil { v.initializationError = err } @@ -484,10 +491,6 @@ func (v *view) WorkspacePackageIDs(ctx context.Context) ([]string, error) { s.setWorkspacePackage(m.id, m.pkgPath) } }) - if v.initializationError != nil { - return nil, v.initializationError - } - return s.workspacePackageIDs(), nil } func (s *snapshot) awaitInitialized(ctx context.Context) error { diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index c66c3d6ec3..601e80a8b9 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -53,13 +53,7 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) { options := tests.DefaultOptions() session.SetOptions(options) options.Env = data.Config.Env - view, _, err := session.NewView(ctx, viewName, span.FileURI(data.Config.Dir), options) - if err != nil { - t.Fatal(err) - } - // Load the workspace packages, since this would normally happen when a view is initialized. - // Otherwise, tests that need to look at all workspace packages will fail. - if _, err := view.WorkspacePackageIDs(ctx); err != nil { + if _, _, err := session.NewView(ctx, viewName, span.FileURI(data.Config.Dir), options); err != nil { t.Fatal(err) } for filename, content := range data.Config.Overlay { diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index 9136dbcf11..51885d3e98 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -60,11 +60,6 @@ func testSource(t *testing.T, exporter packagestest.Exporter) { data: data, ctx: ctx, } - // Load the workspace packages, since this would normally happen when a view is initialized. - // Otherwise, tests that need to look at all workspace packages will fail. - if _, err := view.WorkspacePackageIDs(ctx); err != nil { - t.Fatal(err) - } for filename, content := range data.Config.Overlay { kind := source.DetectLanguage("", filename) if kind != source.Go {