diff --git a/internal/code/packages.go b/internal/code/packages.go index 17fd5bb6fe4..e7f8655aa01 100644 --- a/internal/code/packages.go +++ b/internal/code/packages.go @@ -21,10 +21,12 @@ var ( var mode = packages.NeedName | packages.NeedFiles | + packages.NeedImports | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | - packages.NeedModule + packages.NeedModule | + packages.NeedDeps type ( // Packages is a wrapper around x/tools/go/packages that maintains a (hopefully prewarmed) cache of packages @@ -133,6 +135,11 @@ func (p *Packages) LoadAll(importPaths ...string) []*packages.Package { func (p *Packages) addToCache(pkg *packages.Package) { imp := NormalizeVendor(pkg.PkgPath) p.packages[imp] = pkg + for _, imp := range pkg.Imports { + if _, found := p.packages[NormalizeVendor(imp.PkgPath)]; !found { + p.addToCache(imp) + } + } } // Load works the same as LoadAll, except a single package at a time. @@ -213,9 +220,18 @@ func (p *Packages) NameForPackage(importPath string) string { return pkg.Name } -// Evict removes a given package import path from the cache. Further calls to Load will fetch it from disk. +// Evict removes a given package import path from the cache, along with any packages that depend on it. Further calls +// to Load will fetch it from disk. func (p *Packages) Evict(importPath string) { delete(p.packages, importPath) + + for _, pkg := range p.packages { + for _, imported := range pkg.Imports { + if imported.PkgPath == importPath { + p.Evict(pkg.PkgPath) + } + } + } } func (p *Packages) ModTidy() error { diff --git a/internal/code/packages_test.go b/internal/code/packages_test.go index d390741c568..6a3c7f45f99 100644 --- a/internal/code/packages_test.go +++ b/internal/code/packages_test.go @@ -30,6 +30,14 @@ func TestPackages(t *testing.T) { require.Equal(t, 2, p.numLoadCalls) }) + t.Run("evicting a package also evicts its dependencies", func(t *testing.T) { + p := initialState(t) + p.Evict("github.com/99designs/gqlgen/internal/code/testdata/a") + require.Equal(t, "a", p.Load("github.com/99designs/gqlgen/internal/code/testdata/a").Name) + require.Equal(t, 2, p.numLoadCalls) + require.Equal(t, "b", p.Load("github.com/99designs/gqlgen/internal/code/testdata/b").Name) + require.Equal(t, 3, p.numLoadCalls) + }) t.Run("able to load private package with build tags", func(t *testing.T) { p := initialState(t, WithBuildTags("private")) p.Evict("github.com/99designs/gqlgen/internal/code/testdata/a")