Skip to content

Commit 18f76ec

Browse files
committed
gopls/internal/lsp: split ActivePackages
ActivePackages used to compute a set of packages, then type check them all, even though many clients need only metadata. This change replaces it by ActiveMetadata, which returns only metadata for the set of packages, and exposes the LoadPackages operation allowing callers to load only the subset they actually need. Details: - Snapshot.TypeCheck method is exposed. - Snapshot.DiagnosePackage now takes a PackageID, and calls for typechecking itself. Similarly Server.diagnosePkg. - source.Analyze now takes a PackageID, noot Package (which it previously used only for its ID). - GCOptimizationDetails accepts a Metadata, not a Package. - workspaceMetadata replaces workspacePackageID, activePackageIDs. - Combined the two loops in Server.diagnoseChangedFiles, and parallelized the diagnose calls in moddiagnostics, to ensure that type checking happens in parallel. Change-Id: Id0383a678ce45447f3313d1426e3f9b96050eaa1 Reviewed-on: https://go-review.googlesource.com/c/tools/+/456275 Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> gopls-CI: kokoro <noreply+kokoro@google.com> Run-TryBot: Alan Donovan <adonovan@google.com>
1 parent 84299a0 commit 18f76ec

File tree

10 files changed

+184
-153
lines changed

10 files changed

+184
-153
lines changed

gopls/internal/lsp/cache/analysis.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,12 @@ func factType(fact analysis.Fact) reflect.Type {
462462
return t
463463
}
464464

465-
func (s *snapshot) DiagnosePackage(ctx context.Context, spkg source.Package) (map[span.URI][]*source.Diagnostic, error) {
466-
pkg := spkg.(*pkg)
465+
func (s *snapshot) DiagnosePackage(ctx context.Context, id PackageID) (map[span.URI][]*source.Diagnostic, error) {
466+
pkgs, err := s.TypeCheck(ctx, source.TypecheckFull, id)
467+
if err != nil {
468+
return nil, err
469+
}
470+
pkg := pkgs[0].(*pkg)
467471
var errorAnalyzerDiag []*source.Diagnostic
468472
if pkg.HasTypeErrors() {
469473
// Apply type error analyzers.

gopls/internal/lsp/cache/mod_tidy.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,7 @@ func modTidyDiagnostics(ctx context.Context, snapshot *snapshot, pm *source.Pars
192192
// Add diagnostics for missing modules anywhere they are imported in the
193193
// workspace.
194194
// TODO(adonovan): opt: opportunities for parallelism abound.
195-
for _, id := range snapshot.workspacePackageIDs() {
196-
m := snapshot.Metadata(id)
197-
if m == nil {
198-
return nil, fmt.Errorf("no metadata for %s", id)
199-
}
200-
195+
for _, m := range snapshot.workspaceMetadata() {
201196
// Read both lists of files of this package, in parallel.
202197
goFiles, compiledGoFiles, err := readGoFiles(ctx, snapshot, m)
203198
if err != nil {

gopls/internal/lsp/cache/snapshot.go

Lines changed: 29 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ func (s *snapshot) ValidBuildConfiguration() bool {
299299
}
300300
// The user may have a multiple directories in their GOPATH.
301301
// Check if the workspace is within any of them.
302+
// TODO(rfindley): this should probably be subject to "if GO111MODULES = off {...}".
302303
for _, gp := range filepath.SplitList(s.view.gopath) {
303304
if source.InDir(filepath.Join(gp, "src"), s.view.rootURI.Filename()) {
304305
return true
@@ -653,7 +654,7 @@ func (s *snapshot) PackagesForFile(ctx context.Context, uri span.URI, mode sourc
653654
ids = append(ids, m.ID)
654655
}
655656

656-
return s.loadPackages(ctx, mode, ids...)
657+
return s.TypeCheck(ctx, mode, ids...)
657658
}
658659

659660
func (s *snapshot) PackageForFile(ctx context.Context, uri span.URI, mode source.TypecheckMode, pkgPolicy source.PackageFilter) (source.Package, error) {
@@ -671,7 +672,7 @@ func (s *snapshot) PackageForFile(ctx context.Context, uri span.URI, mode source
671672
case source.WidestPackage:
672673
metas = metas[len(metas)-1:]
673674
}
674-
pkgs, err := s.loadPackages(ctx, mode, metas[0].ID)
675+
pkgs, err := s.TypeCheck(ctx, mode, metas[0].ID)
675676
if err != nil {
676677
return nil, err
677678
}
@@ -713,8 +714,8 @@ func (s *snapshot) containingPackages(ctx context.Context, uri span.URI) ([]*sou
713714
return metas, err
714715
}
715716

716-
// loadPackages type-checks the specified packages in the given mode.
717-
func (s *snapshot) loadPackages(ctx context.Context, mode source.TypecheckMode, ids ...PackageID) ([]source.Package, error) {
717+
// TypeCheck type-checks the specified packages in the given mode.
718+
func (s *snapshot) TypeCheck(ctx context.Context, mode source.TypecheckMode, ids ...PackageID) ([]source.Package, error) {
718719
// Build all the handles...
719720
var phs []*packageHandle
720721
for _, id := range ids {
@@ -854,30 +855,14 @@ func (s *snapshot) getImportedBy(id PackageID) []PackageID {
854855
return s.meta.importedBy[id]
855856
}
856857

857-
func (s *snapshot) workspacePackageIDs() (ids []PackageID) {
858+
func (s *snapshot) workspaceMetadata() (meta []*source.Metadata) {
858859
s.mu.Lock()
859860
defer s.mu.Unlock()
860861

861862
for id := range s.workspacePackages {
862-
ids = append(ids, id)
863+
meta = append(meta, s.meta.metadata[id])
863864
}
864-
return ids
865-
}
866-
867-
func (s *snapshot) activePackageIDs() (ids []PackageID) {
868-
if s.view.Options().MemoryMode == source.ModeNormal {
869-
return s.workspacePackageIDs()
870-
}
871-
872-
s.mu.Lock()
873-
defer s.mu.Unlock()
874-
875-
for id := range s.workspacePackages {
876-
if s.isActiveLocked(id) {
877-
ids = append(ids, id)
878-
}
879-
}
880-
return ids
865+
return meta
881866
}
882867

883868
func (s *snapshot) isActiveLocked(id PackageID) (active bool) {
@@ -1089,35 +1074,25 @@ func (s *snapshot) knownFilesInDir(ctx context.Context, dir span.URI) []span.URI
10891074
return files
10901075
}
10911076

1092-
func (s *snapshot) ActivePackages(ctx context.Context) ([]source.Package, error) {
1093-
phs, err := s.activePackageHandles(ctx)
1094-
if err != nil {
1077+
func (s *snapshot) ActiveMetadata(ctx context.Context) ([]*source.Metadata, error) {
1078+
if err := s.awaitLoaded(ctx); err != nil {
10951079
return nil, err
10961080
}
1097-
var pkgs []source.Package
1098-
for _, ph := range phs {
1099-
pkg, err := ph.await(ctx, s)
1100-
if err != nil {
1101-
return nil, err
1102-
}
1103-
pkgs = append(pkgs, pkg)
1104-
}
1105-
return pkgs, nil
1106-
}
11071081

1108-
func (s *snapshot) activePackageHandles(ctx context.Context) ([]*packageHandle, error) {
1109-
if err := s.awaitLoaded(ctx); err != nil {
1110-
return nil, err
1082+
if s.view.Options().MemoryMode == source.ModeNormal {
1083+
return s.workspaceMetadata(), nil
11111084
}
1112-
var phs []*packageHandle
1113-
for _, pkgID := range s.activePackageIDs() {
1114-
ph, err := s.buildPackageHandle(ctx, pkgID, s.workspaceParseMode(pkgID))
1115-
if err != nil {
1116-
return nil, err
1085+
1086+
// ModeDegradeClosed
1087+
s.mu.Lock()
1088+
defer s.mu.Unlock()
1089+
var active []*source.Metadata
1090+
for id := range s.workspacePackages {
1091+
if s.isActiveLocked(id) {
1092+
active = append(active, s.Metadata(id))
11171093
}
1118-
phs = append(phs, ph)
11191094
}
1120-
return phs, nil
1095+
return active, nil
11211096
}
11221097

11231098
// Symbols extracts and returns the symbols for each file in all the snapshot's views.
@@ -1394,8 +1369,8 @@ func (s *snapshot) GetCriticalError(ctx context.Context) *source.CriticalError {
13941369
// Even if packages didn't fail to load, we still may want to show
13951370
// additional warnings.
13961371
if loadErr == nil {
1397-
wsPkgs, _ := s.ActivePackages(ctx)
1398-
if msg := shouldShowAdHocPackagesWarning(s, wsPkgs); msg != "" {
1372+
active, _ := s.ActiveMetadata(ctx)
1373+
if msg := shouldShowAdHocPackagesWarning(s, active); msg != "" {
13991374
return &source.CriticalError{
14001375
MainError: errors.New(msg),
14011376
}
@@ -1410,7 +1385,7 @@ func (s *snapshot) GetCriticalError(ctx context.Context) *source.CriticalError {
14101385
// on-demand or via orphaned file reloading.
14111386
//
14121387
// TODO(rfindley): re-evaluate this heuristic.
1413-
if containsCommandLineArguments(wsPkgs) {
1388+
if containsCommandLineArguments(active) {
14141389
err, diags := s.workspaceLayoutError(ctx)
14151390
if err != nil {
14161391
if ctx.Err() != nil {
@@ -1445,15 +1420,9 @@ const adHocPackagesWarning = `You are outside of a module and outside of $GOPATH
14451420
If you are using modules, please open your editor to a directory in your module.
14461421
If you believe this warning is incorrect, please file an issue: https://github.com/golang/go/issues/new.`
14471422

1448-
func shouldShowAdHocPackagesWarning(snapshot source.Snapshot, pkgs []source.Package) string {
1423+
func shouldShowAdHocPackagesWarning(snapshot source.Snapshot, active []*source.Metadata) string {
14491424
if !snapshot.ValidBuildConfiguration() {
1450-
for _, pkg := range pkgs {
1451-
// TODO(adonovan): strength-reduce the parameter to []Metadata.
1452-
m := snapshot.Metadata(pkg.ID())
1453-
if m == nil {
1454-
continue
1455-
}
1456-
1425+
for _, m := range active {
14571426
// A blank entry in DepsByImpPath
14581427
// indicates a missing dependency.
14591428
for _, importID := range m.DepsByImpPath {
@@ -1466,9 +1435,9 @@ func shouldShowAdHocPackagesWarning(snapshot source.Snapshot, pkgs []source.Pack
14661435
return ""
14671436
}
14681437

1469-
func containsCommandLineArguments(pkgs []source.Package) bool {
1470-
for _, pkg := range pkgs {
1471-
if source.IsCommandLineArguments(pkg.ID()) {
1438+
func containsCommandLineArguments(metas []*source.Metadata) bool {
1439+
for _, m := range metas {
1440+
if source.IsCommandLineArguments(m.ID) {
14721441
return true
14731442
}
14741443
}

gopls/internal/lsp/code_action.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,16 +155,19 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
155155
if ctx.Err() != nil {
156156
return nil, ctx.Err()
157157
}
158-
pkg, err := snapshot.PackageForFile(ctx, fh.URI(), source.TypecheckFull, source.WidestPackage)
158+
metas, err := snapshot.MetadataForFile(ctx, fh.URI())
159159
if err != nil {
160160
return nil, err
161161
}
162-
163-
pkgDiagnostics, err := snapshot.DiagnosePackage(ctx, pkg)
162+
if len(metas) == 0 {
163+
return nil, fmt.Errorf("no package containing file %q", fh.URI())
164+
}
165+
id := metas[len(metas)-1].ID // last => widest package
166+
pkgDiagnostics, err := snapshot.DiagnosePackage(ctx, id)
164167
if err != nil {
165168
return nil, err
166169
}
167-
analysisDiags, err := source.Analyze(ctx, snapshot, pkg, true)
170+
analysisDiags, err := source.Analyze(ctx, snapshot, id, true)
168171
if err != nil {
169172
return nil, err
170173
}

0 commit comments

Comments
 (0)