@@ -100,10 +100,10 @@ type snapshot struct {
100
100
// It may be invalidated when a file's content changes.
101
101
//
102
102
// Invariants to preserve:
103
- // - packages.Get(id).m.Metadata == meta.metadata[id].Metadata for all ids
103
+ // - packages.Get(id).meta == meta.metadata[id] for all ids
104
104
// - if a package is in packages, then all of its dependencies should also
105
105
// be in packages, unless there is a missing import
106
- packages * persistent.Map // from packageKey to *memoize.Promise[* packageHandle]
106
+ packages * persistent.Map // from packageKey to *packageHandle
107
107
108
108
// isActivePackageCache maps package ID to the cached value if it is active or not.
109
109
// It may be invalidated when metadata changes or a new file is opened or closed.
@@ -655,6 +655,8 @@ func (s *snapshot) PackagesForFile(ctx context.Context, uri span.URI, mode sourc
655
655
func (s * snapshot ) PackageForFile (ctx context.Context , uri span.URI , mode source.TypecheckMode , pkgPolicy source.PackageFilter ) (source.Package , error ) {
656
656
ctx = event .Label (ctx , tag .URI .Of (uri ))
657
657
658
+ // TODO(adonovan): opt: apply pkgPolicy to the list of
659
+ // Metadatas before initiating loading of any package.
658
660
phs , err := s .packageHandlesForFile (ctx , uri , mode , false )
659
661
if err != nil {
660
662
return nil , err
@@ -699,24 +701,24 @@ func (s *snapshot) packageHandlesForFile(ctx context.Context, uri span.URI, mode
699
701
if kind := s .view .FileKind (fh ); kind != source .Go {
700
702
return nil , fmt .Errorf ("no packages for non-Go file %s (%v)" , uri , kind )
701
703
}
702
- knownIDs , err := s .getOrLoadIDsForURI (ctx , uri )
704
+ metas , err := s .MetadataForFile (ctx , uri )
703
705
if err != nil {
704
706
return nil , err
705
707
}
706
708
707
709
var phs []* packageHandle
708
- for _ , id := range knownIDs {
710
+ for _ , m := range metas {
709
711
// Filter out any intermediate test variants. We typically aren't
710
712
// interested in these packages for file= style queries.
711
- if m := s . getMetadata ( id ); m != nil && m .IsIntermediateTestVariant () && ! withIntermediateTestVariants {
713
+ if m .IsIntermediateTestVariant () && ! withIntermediateTestVariants {
712
714
continue
713
715
}
714
716
parseMode := source .ParseFull
715
717
if mode == source .TypecheckWorkspace {
716
- parseMode = s .workspaceParseMode (id )
718
+ parseMode = s .workspaceParseMode (m . ID )
717
719
}
718
720
719
- ph , err := s .buildPackageHandle (ctx , id , parseMode )
721
+ ph , err := s .buildPackageHandle (ctx , m . ID , parseMode )
720
722
if err != nil {
721
723
return nil , err
722
724
}
@@ -725,12 +727,10 @@ func (s *snapshot) packageHandlesForFile(ctx context.Context, uri span.URI, mode
725
727
return phs , nil
726
728
}
727
729
728
- // getOrLoadIDsForURI returns package IDs associated with the file uri. If no
729
- // such packages exist or if they are known to be stale, it reloads the file.
730
- //
731
- // If experimentalUseInvalidMetadata is set, this function may return package
732
- // IDs with invalid metadata.
733
- func (s * snapshot ) getOrLoadIDsForURI (ctx context.Context , uri span.URI ) ([]PackageID , error ) {
730
+ // MetadataForFile returns the Metadata for each package associated
731
+ // with the file uri. If no such package exists or if they are known
732
+ // to be stale, it reloads metadata for the file.
733
+ func (s * snapshot ) MetadataForFile (ctx context.Context , uri span.URI ) ([]* source.Metadata , error ) {
734
734
s .mu .Lock ()
735
735
736
736
// Start with the set of package associations derived from the last load.
@@ -772,23 +772,31 @@ func (s *snapshot) getOrLoadIDsForURI(ctx context.Context, uri span.URI) ([]Pack
772
772
s .clearShouldLoad (scope )
773
773
774
774
// Don't return an error here, as we may still return stale IDs.
775
- // Furthermore, the result of getOrLoadIDsForURI should be consistent upon
775
+ // Furthermore, the result of MetadataForFile should be consistent upon
776
776
// subsequent calls, even if the file is marked as unloadable.
777
777
if err != nil && ! errors .Is (err , errNoPackages ) {
778
- event .Error (ctx , "getOrLoadIDsForURI " , err )
778
+ event .Error (ctx , "MetadataForFile " , err )
779
779
}
780
780
}
781
781
782
+ // Retrieve the metadata.
782
783
s .mu .Lock ()
784
+ defer s .mu .Unlock ()
783
785
ids = s .meta .ids [uri ]
784
- // metadata is only ever added by loading, so if we get here and still have
785
- // no ids, uri is unloadable.
786
+ metas := make ([]* source.Metadata , len (ids ))
787
+ for i , id := range ids {
788
+ metas [i ] = s .meta .metadata [id ]
789
+ if metas [i ] == nil {
790
+ panic ("nil metadata" )
791
+ }
792
+ }
793
+ // Metadata is only ever added by loading,
794
+ // so if we get here and still have
795
+ // no IDs, uri is unloadable.
786
796
if ! unloadable && len (ids ) == 0 {
787
797
s .unloadableFiles [uri ] = struct {}{}
788
798
}
789
- s .mu .Unlock ()
790
-
791
- return ids , nil
799
+ return metas , nil
792
800
}
793
801
794
802
func (s * snapshot ) GetReverseDependencies (ctx context.Context , id PackageID ) ([]source.Package , error ) {
@@ -1135,37 +1143,17 @@ func (s *snapshot) Symbols(ctx context.Context) map[span.URI][]source.Symbol {
1135
1143
return result
1136
1144
}
1137
1145
1138
- func (s * snapshot ) MetadataForFile (ctx context.Context , uri span.URI ) ([]* source.Metadata , error ) {
1139
- knownIDs , err := s .getOrLoadIDsForURI (ctx , uri )
1140
- if err != nil {
1141
- return nil , err
1142
- }
1143
- var mds []* source.Metadata
1144
- for _ , id := range knownIDs {
1145
- md := s .getMetadata (id )
1146
- // TODO(rfindley): knownIDs and metadata should be in sync, but existing
1147
- // code is defensive of nil metadata.
1148
- if md != nil {
1149
- mds = append (mds , md )
1150
- }
1151
- }
1152
- return mds , nil
1153
- }
1154
-
1155
1146
func (s * snapshot ) KnownPackages (ctx context.Context ) ([]source.Package , error ) {
1156
1147
if err := s .awaitLoaded (ctx ); err != nil {
1157
1148
return nil , err
1158
1149
}
1159
1150
1160
- ids := make ([]source.PackageID , 0 , len (s .meta .metadata ))
1161
1151
s .mu .Lock ()
1162
- for id := range s .meta .metadata {
1163
- ids = append (ids , id )
1164
- }
1152
+ g := s .meta
1165
1153
s .mu .Unlock ()
1166
1154
1167
- pkgs := make ([]source.Package , 0 , len (ids ))
1168
- for _ , id := range ids {
1155
+ pkgs := make ([]source.Package , 0 , len (g . metadata ))
1156
+ for id := range g . metadata {
1169
1157
pkg , err := s .checkedPackage (ctx , id , s .workspaceParseMode (id ))
1170
1158
if err != nil {
1171
1159
return nil , err
@@ -1181,10 +1169,11 @@ func (s *snapshot) AllValidMetadata(ctx context.Context) ([]*source.Metadata, er
1181
1169
}
1182
1170
1183
1171
s .mu .Lock ()
1184
- defer s .mu .Unlock ()
1172
+ g := s .meta
1173
+ s .mu .Unlock ()
1185
1174
1186
- var meta []* source.Metadata
1187
- for _ , m := range s . meta .metadata {
1175
+ meta := make ( []* source.Metadata , 0 , len ( g . metadata ))
1176
+ for _ , m := range g .metadata {
1188
1177
meta = append (meta , m )
1189
1178
}
1190
1179
return meta , nil
@@ -1281,11 +1270,7 @@ func (s *snapshot) clearShouldLoad(scopes ...loadScope) {
1281
1270
// noValidMetadataForURILocked reports whether there is any valid metadata for
1282
1271
// the given URI.
1283
1272
func (s * snapshot ) noValidMetadataForURILocked (uri span.URI ) bool {
1284
- ids , ok := s .meta .ids [uri ]
1285
- if ! ok {
1286
- return true
1287
- }
1288
- for _ , id := range ids {
1273
+ for _ , id := range s .meta .ids [uri ] {
1289
1274
if _ , ok := s .meta .metadata [id ]; ok {
1290
1275
return false
1291
1276
}
@@ -1483,12 +1468,8 @@ func (s *snapshot) awaitLoadedAllErrors(ctx context.Context) *source.CriticalErr
1483
1468
// TODO(rfindley): Should we be more careful about returning the
1484
1469
// initialization error? Is it possible for the initialization error to be
1485
1470
// corrected without a successful reinitialization?
1486
- s .mu .Lock ()
1487
- initializedErr := s .initializedErr
1488
- s .mu .Unlock ()
1489
-
1490
- if initializedErr != nil {
1491
- return initializedErr
1471
+ if err := s .getInitializationError (); err != nil {
1472
+ return err
1492
1473
}
1493
1474
1494
1475
// TODO(rfindley): revisit this handling. Calling reloadWorkspace with a
@@ -1928,7 +1909,25 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
1928
1909
addRevDeps (id , invalidateMetadata )
1929
1910
}
1930
1911
1931
- result .invalidatePackagesLocked (idsToInvalidate )
1912
+ // Delete invalidated package type information.
1913
+ for id := range idsToInvalidate {
1914
+ for _ , mode := range source .AllParseModes {
1915
+ key := packageKey {mode , id }
1916
+ result .packages .Delete (key )
1917
+ }
1918
+ }
1919
+
1920
+ // Delete invalidated analysis actions.
1921
+ var actionsToDelete []actionKey
1922
+ result .actions .Range (func (k , _ interface {}) {
1923
+ key := k .(actionKey )
1924
+ if _ , ok := idsToInvalidate [key .pkgid ]; ok {
1925
+ actionsToDelete = append (actionsToDelete , key )
1926
+ }
1927
+ })
1928
+ for _ , key := range actionsToDelete {
1929
+ result .actions .Delete (key )
1930
+ }
1932
1931
1933
1932
// If a file has been deleted, we must delete metadata for all packages
1934
1933
// containing that file.
@@ -2080,35 +2079,6 @@ func invalidatedPackageIDs(uri span.URI, known map[span.URI][]PackageID, package
2080
2079
return invalidated
2081
2080
}
2082
2081
2083
- // invalidatePackagesLocked deletes data associated with the given package IDs.
2084
- //
2085
- // Note: all keys in the ids map are invalidated, regardless of the
2086
- // corresponding value.
2087
- //
2088
- // s.mu must be held while calling this function.
2089
- func (s * snapshot ) invalidatePackagesLocked (ids map [PackageID ]bool ) {
2090
- // Delete invalidated package type information.
2091
- for id := range ids {
2092
- for _ , mode := range source .AllParseModes {
2093
- key := packageKey {mode , id }
2094
- s .packages .Delete (key )
2095
- }
2096
- }
2097
-
2098
- // Copy actions.
2099
- // TODO(adonovan): opt: avoid iteration over s.actions.
2100
- var actionsToDelete []actionKey
2101
- s .actions .Range (func (k , _ interface {}) {
2102
- key := k .(actionKey )
2103
- if _ , ok := ids [key .pkgid ]; ok {
2104
- actionsToDelete = append (actionsToDelete , key )
2105
- }
2106
- })
2107
- for _ , key := range actionsToDelete {
2108
- s .actions .Delete (key )
2109
- }
2110
- }
2111
-
2112
2082
// fileWasSaved reports whether the FileHandle passed in has been saved. It
2113
2083
// accomplishes this by checking to see if the original and current FileHandles
2114
2084
// are both overlays, and if the current FileHandle is saved while the original
0 commit comments