@@ -40,6 +40,8 @@ import (
40
40
"golang.org/x/tools/gopls/internal/lsp/source/xrefs"
41
41
"golang.org/x/tools/gopls/internal/persistent"
42
42
"golang.org/x/tools/gopls/internal/span"
43
+ "golang.org/x/tools/gopls/internal/vulncheck"
44
+ "golang.org/x/tools/internal/constraints"
43
45
"golang.org/x/tools/internal/event"
44
46
"golang.org/x/tools/internal/event/tag"
45
47
"golang.org/x/tools/internal/gocommand"
@@ -177,6 +179,13 @@ type snapshot struct {
177
179
// detect ignored files.
178
180
ignoreFilterOnce sync.Once
179
181
ignoreFilter * ignoreFilter
182
+
183
+ // moduleUpgrades tracks known upgrades for module paths in each modfile.
184
+ // Each modfile has a map of module name to upgrade version.
185
+ moduleUpgrades * persistent.Map [span.URI , map [string ]string ]
186
+
187
+ // vulns maps each go.mod file's URI to its known vulnerabilities.
188
+ vulns * persistent.Map [span.URI , * vulncheck.Result ]
180
189
}
181
190
182
191
var globalSnapshotID uint64
@@ -251,6 +260,8 @@ func (s *snapshot) destroy(destroyedBy string) {
251
260
s .modVulnHandles .Destroy ()
252
261
s .modWhyHandles .Destroy ()
253
262
s .unloadableFiles .Destroy ()
263
+ s .moduleUpgrades .Destroy ()
264
+ s .vulns .Destroy ()
254
265
}
255
266
256
267
func (s * snapshot ) SequenceID () uint64 {
@@ -1814,7 +1825,8 @@ func inVendor(uri span.URI) bool {
1814
1825
return found && strings .Contains (after , "/" )
1815
1826
}
1816
1827
1817
- func (s * snapshot ) clone (ctx , bgCtx context.Context , changes map [span.URI ]source.FileHandle ) (* snapshot , func ()) {
1828
+ func (s * snapshot ) clone (ctx , bgCtx context.Context , changed source.StateChange ) (* snapshot , func ()) {
1829
+ changedFiles := changed .Files
1818
1830
ctx , done := event .Start (ctx , "cache.snapshot.clone" )
1819
1831
defer done ()
1820
1832
@@ -1834,20 +1846,22 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]source
1834
1846
initializedErr : s .initializedErr ,
1835
1847
packages : s .packages .Clone (),
1836
1848
activePackages : s .activePackages .Clone (),
1837
- files : s .files .Clone (changes ),
1838
- symbolizeHandles : cloneWithout (s .symbolizeHandles , changes ),
1849
+ files : s .files .Clone (changedFiles ),
1850
+ symbolizeHandles : cloneWithout (s .symbolizeHandles , changedFiles ),
1839
1851
workspacePackages : s .workspacePackages ,
1840
1852
shouldLoad : s .shouldLoad .Clone (), // not cloneWithout: shouldLoad is cleared on loads
1841
1853
unloadableFiles : s .unloadableFiles .Clone (), // not cloneWithout: typing in a file doesn't necessarily make it loadable
1842
- parseModHandles : cloneWithout (s .parseModHandles , changes ),
1843
- parseWorkHandles : cloneWithout (s .parseWorkHandles , changes ),
1844
- modTidyHandles : cloneWithout (s .modTidyHandles , changes ),
1845
- modWhyHandles : cloneWithout (s .modWhyHandles , changes ),
1846
- modVulnHandles : cloneWithout (s .modVulnHandles , changes ),
1854
+ parseModHandles : cloneWithout (s .parseModHandles , changedFiles ),
1855
+ parseWorkHandles : cloneWithout (s .parseWorkHandles , changedFiles ),
1856
+ modTidyHandles : cloneWithout (s .modTidyHandles , changedFiles ),
1857
+ modWhyHandles : cloneWithout (s .modWhyHandles , changedFiles ),
1858
+ modVulnHandles : cloneWithout (s .modVulnHandles , changedFiles ),
1847
1859
workspaceModFiles : s .workspaceModFiles ,
1848
1860
workspaceModFilesErr : s .workspaceModFilesErr ,
1849
1861
importGraph : s .importGraph ,
1850
1862
pkgIndex : s .pkgIndex ,
1863
+ moduleUpgrades : cloneWith (s .moduleUpgrades , changed .ModuleUpgrades ),
1864
+ vulns : cloneWith (s .vulns , changed .Vulns ),
1851
1865
}
1852
1866
1853
1867
// Create a lease on the new snapshot.
@@ -1864,7 +1878,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]source
1864
1878
// vendor tree after 'go mod vendor' or 'rm -fr vendor/'.
1865
1879
//
1866
1880
// TODO(rfindley): revisit the location of this check.
1867
- for uri := range changes {
1881
+ for uri := range changedFiles {
1868
1882
if inVendor (uri ) && s .initializedErr != nil ||
1869
1883
strings .HasSuffix (string (uri ), "/vendor/modules.txt" ) {
1870
1884
reinit = true
@@ -1877,7 +1891,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]source
1877
1891
// where a file is added on disk; we don't want to read the newly added file
1878
1892
// into the old snapshot, as that will break our change detection below.
1879
1893
oldFiles := make (map [span.URI ]source.FileHandle )
1880
- for uri := range changes {
1894
+ for uri := range changedFiles {
1881
1895
if fh , ok := s .files .Get (uri ); ok {
1882
1896
oldFiles [uri ] = fh
1883
1897
}
@@ -1898,7 +1912,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]source
1898
1912
}
1899
1913
1900
1914
if workURI , _ := s .view .GOWORK (); workURI != "" {
1901
- if newFH , ok := changes [workURI ]; ok {
1915
+ if newFH , ok := changedFiles [workURI ]; ok {
1902
1916
result .workspaceModFiles , result .workspaceModFilesErr = computeWorkspaceModFiles (ctx , s .view .gomod , workURI , s .view .effectiveGO111MODULE (), result )
1903
1917
if changedOnDisk (oldFiles [workURI ], newFH ) {
1904
1918
reinit = true
@@ -1907,14 +1921,14 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]source
1907
1921
}
1908
1922
1909
1923
// Reinitialize if any workspace mod file has changed on disk.
1910
- for uri , newFH := range changes {
1924
+ for uri , newFH := range changedFiles {
1911
1925
if _ , ok := result .workspaceModFiles [uri ]; ok && changedOnDisk (oldFiles [uri ], newFH ) {
1912
1926
reinit = true
1913
1927
}
1914
1928
}
1915
1929
1916
1930
// Finally, process sumfile changes that may affect loading.
1917
- for uri , newFH := range changes {
1931
+ for uri , newFH := range changedFiles {
1918
1932
if ! changedOnDisk (oldFiles [uri ], newFH ) {
1919
1933
continue // like with go.mod files, we only reinit when things change on disk
1920
1934
}
@@ -1955,7 +1969,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]source
1955
1969
anyFileOpenedOrClosed := false // opened files affect workspace packages
1956
1970
anyFileAdded := false // adding a file can resolve missing dependencies
1957
1971
1958
- for uri , newFH := range changes {
1972
+ for uri , newFH := range changedFiles {
1959
1973
// The original FileHandle for this URI is cached on the snapshot.
1960
1974
oldFH , _ := oldFiles [uri ] // may be nil
1961
1975
_ , oldOpen := oldFH .(* Overlay )
@@ -2160,14 +2174,24 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]source
2160
2174
return result , release
2161
2175
}
2162
2176
2163
- func cloneWithout [V any ](m * persistent.Map [span.URI , V ], changes map [span.URI ]source.FileHandle ) * persistent.Map [span.URI , V ] {
2177
+ // cloneWithout clones m then deletes from it the keys of changes.
2178
+ func cloneWithout [K constraints.Ordered , V1 , V2 any ](m * persistent.Map [K , V1 ], changes map [K ]V2 ) * persistent.Map [K , V1 ] {
2164
2179
m2 := m .Clone ()
2165
2180
for k := range changes {
2166
2181
m2 .Delete (k )
2167
2182
}
2168
2183
return m2
2169
2184
}
2170
2185
2186
+ // cloneWith clones m then inserts the changes into it.
2187
+ func cloneWith [K constraints.Ordered , V any ](m * persistent.Map [K , V ], changes map [K ]V ) * persistent.Map [K , V ] {
2188
+ m2 := m .Clone ()
2189
+ for k , v := range changes {
2190
+ m2 .Set (k , v , nil )
2191
+ }
2192
+ return m2
2193
+ }
2194
+
2171
2195
// deleteMostRelevantModFile deletes the mod file most likely to be the mod
2172
2196
// file for the changed URI, if it exists.
2173
2197
//
0 commit comments