@@ -68,16 +68,8 @@ type snapshot struct {
6868 // builtin pins the AST and package for builtin.go in memory.
6969 builtin span.URI
7070
71- // ids maps file URIs to package IDs.
72- // It may be invalidated on calls to go/packages.
73- ids map [span.URI ][]PackageID
74-
75- // metadata maps file IDs to their associated metadata.
76- // It may invalidated on calls to go/packages.
77- metadata map [PackageID ]* KnownMetadata
78-
79- // importedBy maps package IDs to the list of packages that import them.
80- importedBy map [PackageID ][]PackageID
71+ // meta holds loaded metadata.
72+ meta * metadataGraph
8173
8274 // files maps file URIs to their corresponding FileHandles.
8375 // It may invalidated when a file's content changes.
@@ -716,25 +708,25 @@ func (s *snapshot) getImportedBy(id PackageID) []PackageID {
716708
717709func (s * snapshot ) getImportedByLocked (id PackageID ) []PackageID {
718710 // If we haven't rebuilt the import graph since creating the snapshot.
719- if len (s .importedBy ) == 0 {
711+ if len (s .meta . importedBy ) == 0 {
720712 s .rebuildImportGraph ()
721713 }
722- return s .importedBy [id ]
714+ return s .meta . importedBy [id ]
723715}
724716
725717func (s * snapshot ) clearAndRebuildImportGraph () {
726718 s .mu .Lock ()
727719 defer s .mu .Unlock ()
728720
729721 // Completely invalidate the original map.
730- s .importedBy = make (map [PackageID ][]PackageID )
722+ s .meta . importedBy = make (map [PackageID ][]PackageID )
731723 s .rebuildImportGraph ()
732724}
733725
734726func (s * snapshot ) rebuildImportGraph () {
735- for id , m := range s .metadata {
727+ for id , m := range s .meta . metadata {
736728 for _ , importID := range m .Deps {
737- s .importedBy [importID ] = append (s .importedBy [importID ], id )
729+ s .meta . importedBy [importID ] = append (s . meta .importedBy [importID ], id )
738730 }
739731 }
740732}
@@ -789,7 +781,7 @@ func (s *snapshot) isActiveLocked(id PackageID, seen map[PackageID]bool) (active
789781 defer func () {
790782 seen [id ] = active
791783 }()
792- m , ok := s .metadata [id ]
784+ m , ok := s .meta . metadata [id ]
793785 if ! ok {
794786 return false
795787 }
@@ -1045,7 +1037,7 @@ func (s *snapshot) KnownPackages(ctx context.Context) ([]source.Package, error)
10451037 // workspace packages first.
10461038 ids := s .workspacePackageIDs ()
10471039 s .mu .Lock ()
1048- for id := range s .metadata {
1040+ for id := range s .meta . metadata {
10491041 if _ , ok := s .workspacePackages [id ]; ok {
10501042 continue
10511043 }
@@ -1177,14 +1169,14 @@ func (s *snapshot) getIDsForURI(uri span.URI) []PackageID {
11771169 s .mu .Lock ()
11781170 defer s .mu .Unlock ()
11791171
1180- return s .ids [uri ]
1172+ return s .meta . ids [uri ]
11811173}
11821174
11831175func (s * snapshot ) getMetadata (id PackageID ) * KnownMetadata {
11841176 s .mu .Lock ()
11851177 defer s .mu .Unlock ()
11861178
1187- return s .metadata [id ]
1179+ return s .meta . metadata [id ]
11881180}
11891181
11901182func (s * snapshot ) shouldLoad (scope interface {}) bool {
@@ -1194,7 +1186,7 @@ func (s *snapshot) shouldLoad(scope interface{}) bool {
11941186 switch scope := scope .(type ) {
11951187 case PackagePath :
11961188 var meta * KnownMetadata
1197- for _ , m := range s .metadata {
1189+ for _ , m := range s .meta . metadata {
11981190 if m .PkgPath != scope {
11991191 continue
12001192 }
@@ -1206,12 +1198,12 @@ func (s *snapshot) shouldLoad(scope interface{}) bool {
12061198 return false
12071199 case fileURI :
12081200 uri := span .URI (scope )
1209- ids := s .ids [uri ]
1201+ ids := s .meta . ids [uri ]
12101202 if len (ids ) == 0 {
12111203 return true
12121204 }
12131205 for _ , id := range ids {
1214- m , ok := s .metadata [id ]
1206+ m , ok := s .meta . metadata [id ]
12151207 if ! ok || m .ShouldLoad {
12161208 return true
12171209 }
@@ -1229,7 +1221,7 @@ func (s *snapshot) clearShouldLoad(scope interface{}) {
12291221 switch scope := scope .(type ) {
12301222 case PackagePath :
12311223 var meta * KnownMetadata
1232- for _ , m := range s .metadata {
1224+ for _ , m := range s .meta . metadata {
12331225 if m .PkgPath == scope {
12341226 meta = m
12351227 }
@@ -1240,12 +1232,12 @@ func (s *snapshot) clearShouldLoad(scope interface{}) {
12401232 meta .ShouldLoad = false
12411233 case fileURI :
12421234 uri := span .URI (scope )
1243- ids := s .ids [uri ]
1235+ ids := s .meta . ids [uri ]
12441236 if len (ids ) == 0 {
12451237 return
12461238 }
12471239 for _ , id := range ids {
1248- if m , ok := s .metadata [id ]; ok {
1240+ if m , ok := s .meta . metadata [id ]; ok {
12491241 m .ShouldLoad = false
12501242 }
12511243 }
@@ -1255,12 +1247,12 @@ func (s *snapshot) clearShouldLoad(scope interface{}) {
12551247// noValidMetadataForURILocked reports whether there is any valid metadata for
12561248// the given URI.
12571249func (s * snapshot ) noValidMetadataForURILocked (uri span.URI ) bool {
1258- ids , ok := s .ids [uri ]
1250+ ids , ok := s .meta . ids [uri ]
12591251 if ! ok {
12601252 return true
12611253 }
12621254 for _ , id := range ids {
1263- if m , ok := s .metadata [id ]; ok && m .Valid {
1255+ if m , ok := s .meta . metadata [id ]; ok && m .Valid {
12641256 return false
12651257 }
12661258 }
@@ -1276,7 +1268,7 @@ func (s *snapshot) noValidMetadataForID(id PackageID) bool {
12761268}
12771269
12781270func (s * snapshot ) noValidMetadataForIDLocked (id PackageID ) bool {
1279- m := s .metadata [id ]
1271+ m := s .meta . metadata [id ]
12801272 return m == nil || ! m .Valid
12811273}
12821274
@@ -1289,7 +1281,7 @@ func (s *snapshot) updateIDForURIsLocked(id PackageID, uris map[span.URI]struct{
12891281 for uri := range uris {
12901282 // Collect the new set of IDs, preserving any valid existing IDs.
12911283 newIDs := []PackageID {id }
1292- for _ , existingID := range s .ids [uri ] {
1284+ for _ , existingID := range s .meta . ids [uri ] {
12931285 // Don't set duplicates of the same ID.
12941286 if existingID == id {
12951287 continue
@@ -1302,15 +1294,15 @@ func (s *snapshot) updateIDForURIsLocked(id PackageID, uris map[span.URI]struct{
13021294 }
13031295 // If the metadata for an existing ID is invalid, and we are
13041296 // setting metadata for a new, valid ID--don't preserve the old ID.
1305- if m , ok := s .metadata [existingID ]; ! ok || ! m .Valid {
1297+ if m , ok := s .meta . metadata [existingID ]; ! ok || ! m .Valid {
13061298 continue
13071299 }
13081300 newIDs = append (newIDs , existingID )
13091301 }
13101302 sort .Slice (newIDs , func (i , j int ) bool {
13111303 return newIDs [i ] < newIDs [j ]
13121304 })
1313- s .ids [uri ] = newIDs
1305+ s .meta . ids [uri ] = newIDs
13141306 }
13151307}
13161308
@@ -1396,10 +1388,10 @@ func (s *snapshot) awaitLoaded(ctx context.Context) error {
13961388
13971389 // If we still have absolutely no metadata, check if the view failed to
13981390 // initialize and return any errors.
1399- if s .useInvalidMetadata () && len (s .metadata ) > 0 {
1391+ if s .useInvalidMetadata () && len (s .meta . metadata ) > 0 {
14001392 return nil
14011393 }
1402- for _ , m := range s .metadata {
1394+ for _ , m := range s .meta . metadata {
14031395 if m .Valid {
14041396 return nil
14051397 }
@@ -1523,10 +1515,10 @@ func (s *snapshot) AwaitInitialized(ctx context.Context) {
15231515func (s * snapshot ) reloadWorkspace (ctx context.Context ) error {
15241516 // See which of the workspace packages are missing metadata.
15251517 s .mu .Lock ()
1526- missingMetadata := len (s .workspacePackages ) == 0 || len (s .metadata ) == 0
1518+ missingMetadata := len (s .workspacePackages ) == 0 || len (s .meta . metadata ) == 0
15271519 pkgPathSet := map [PackagePath ]struct {}{}
15281520 for id , pkgPath := range s .workspacePackages {
1529- if m , ok := s .metadata [id ]; ok && m .Valid {
1521+ if m , ok := s .meta . metadata [id ]; ok && m .Valid {
15301522 continue
15311523 }
15321524 missingMetadata = true
@@ -1670,10 +1662,10 @@ func checkSnapshotLocked(ctx context.Context, s *snapshot) {
16701662 // Check that every go file for a workspace package is identified as
16711663 // belonging to that workspace package.
16721664 for wsID := range s .workspacePackages {
1673- if m , ok := s .metadata [wsID ]; ok {
1665+ if m , ok := s .meta . metadata [wsID ]; ok {
16741666 for _ , uri := range m .GoFiles {
16751667 found := false
1676- for _ , id := range s .ids [uri ] {
1668+ for _ , id := range s .meta . ids [uri ] {
16771669 if id == wsID {
16781670 found = true
16791671 break
@@ -1723,9 +1715,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
17231715 builtin : s .builtin ,
17241716 initializeOnce : s .initializeOnce ,
17251717 initializedErr : s .initializedErr ,
1726- ids : make (map [span.URI ][]PackageID , len (s .ids )),
1727- importedBy : make (map [PackageID ][]PackageID , len (s .importedBy )),
1728- metadata : make (map [PackageID ]* KnownMetadata , len (s .metadata )),
1718+ meta : NewMetadataGraph (),
17291719 packages : make (map [packageKey ]* packageHandle , len (s .packages )),
17301720 actions : make (map [actionKey ]* actionHandle , len (s .actions )),
17311721 files : make (map [span.URI ]source.VersionedFileHandle , len (s .files )),
@@ -1813,7 +1803,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
18131803
18141804 // Invalidate all package metadata if the workspace module has changed.
18151805 if workspaceReload {
1816- for k := range s .metadata {
1806+ for k := range s .meta . metadata {
18171807 directIDs [k ] = true
18181808 }
18191809 }
@@ -1843,7 +1833,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
18431833 anyImportDeleted = anyImportDeleted || importDeleted
18441834
18451835 // Mark all of the package IDs containing the given file.
1846- filePackageIDs := invalidatedPackageIDs (uri , s .ids , pkgFileChanged )
1836+ filePackageIDs := invalidatedPackageIDs (uri , s .meta . ids , pkgFileChanged )
18471837 if pkgFileChanged {
18481838 for id := range filePackageIDs {
18491839 changedPkgFiles [id ] = struct {}{}
@@ -1892,7 +1882,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
18921882 // from an unparseable state to a parseable state, as we don't have a
18931883 // starting point to compare with.
18941884 if anyImportDeleted {
1895- for id , metadata := range s .metadata {
1885+ for id , metadata := range s .meta . metadata {
18961886 if len (metadata .Errors ) > 0 {
18971887 directIDs [id ] = true
18981888 }
@@ -1952,7 +1942,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
19521942 continue
19531943 }
19541944 // The file has been deleted.
1955- if ids , ok := s .ids [c .fileHandle .URI ()]; ok {
1945+ if ids , ok := s .meta . ids [c .fileHandle .URI ()]; ok {
19561946 for _ , id := range ids {
19571947 skipID [id ] = true
19581948 }
@@ -1968,7 +1958,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
19681958 return
19691959 }
19701960 reachableID [id ] = true
1971- m , ok := s .metadata [id ]
1961+ m , ok := s .meta . metadata [id ]
19721962 if ! ok {
19731963 return
19741964 }
@@ -1984,7 +1974,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
19841974 // metadata will be reloaded in future calls to load.
19851975 deleteInvalidMetadata := forceReloadMetadata || workspaceModeChanged
19861976 idsInSnapshot := map [PackageID ]bool {} // track all known IDs
1987- for uri , ids := range s .ids {
1977+ for uri , ids := range s .meta . ids {
19881978 var resultIDs []PackageID
19891979 for _ , id := range ids {
19901980 if skipID [id ] || deleteInvalidMetadata && idsToInvalidate [id ] {
@@ -1998,20 +1988,20 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
19981988 idsInSnapshot [id ] = true
19991989 resultIDs = append (resultIDs , id )
20001990 }
2001- result .ids [uri ] = resultIDs
1991+ result .meta . ids [uri ] = resultIDs
20021992 }
20031993
20041994 // Copy the package metadata. We only need to invalidate packages directly
20051995 // containing the affected file, and only if it changed in a relevant way.
2006- for k , v := range s .metadata {
1996+ for k , v := range s .meta . metadata {
20071997 if ! idsInSnapshot [k ] {
20081998 // Delete metadata for IDs that are no longer reachable from files
20091999 // in the snapshot.
20102000 continue
20112001 }
20122002 invalidateMetadata := idsToInvalidate [k ]
20132003 // Mark invalidated metadata rather than deleting it outright.
2014- result .metadata [k ] = & KnownMetadata {
2004+ result .meta . metadata [k ] = & KnownMetadata {
20152005 Metadata : v .Metadata ,
20162006 Valid : v .Valid && ! invalidateMetadata ,
20172007 ShouldLoad : v .ShouldLoad || invalidateMetadata ,
@@ -2032,9 +2022,9 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
20322022
20332023 // If all the files we know about in a package have been deleted,
20342024 // the package is gone and we should no longer try to load it.
2035- if m := s .metadata [id ]; m != nil {
2025+ if m := s .meta . metadata [id ]; m != nil {
20362026 hasFiles := false
2037- for _ , uri := range s .metadata [id ].GoFiles {
2027+ for _ , uri := range s .meta . metadata [id ].GoFiles {
20382028 // For internal tests, we need _test files, not just the normal
20392029 // ones. External tests only have _test files, but we can check
20402030 // them anyway.
0 commit comments