@@ -539,6 +539,9 @@ type analysisNode struct {
539539 typesOnce sync.Once // guards lazy population of types and typesErr fields
540540 types * types.Package // type information lazily imported from summary
541541 typesErr error // an error producing type information
542+
543+ depHashOnce sync.Once
544+ _depHash file.Hash // memoized hash of data affecting dependents
542545}
543546
544547func (an * analysisNode ) String () string { return string (an .mp .ID ) }
@@ -597,6 +600,40 @@ func (an *analysisNode) _import() (*types.Package, error) {
597600 return an .types , an .typesErr
598601}
599602
603+ // depHash computes the hash of node information that may affect other nodes
604+ // depending on this node: the package path, export hash, and action results.
605+ //
606+ // The result is memoized to avoid redundant work when analysing multiple
607+ // dependents.
608+ func (an * analysisNode ) depHash () file.Hash {
609+ an .depHashOnce .Do (func () {
610+ hasher := sha256 .New ()
611+ fmt .Fprintf (hasher , "dep: %s\n " , an .mp .PkgPath )
612+ fmt .Fprintf (hasher , "export: %s\n " , an .summary .DeepExportHash )
613+
614+ // action results: errors and facts
615+ actions := an .summary .Actions
616+ names := make ([]string , 0 , len (actions ))
617+ for name := range actions {
618+ names = append (names , name )
619+ }
620+ sort .Strings (names )
621+ for _ , name := range names {
622+ summary := actions [name ]
623+ fmt .Fprintf (hasher , "action %s\n " , name )
624+ if summary .Err != "" {
625+ fmt .Fprintf (hasher , "error %s\n " , summary .Err )
626+ } else {
627+ fmt .Fprintf (hasher , "facts %s\n " , summary .FactsHash )
628+ // We can safely omit summary.diagnostics
629+ // from the key since they have no downstream effect.
630+ }
631+ }
632+ hasher .Sum (an ._depHash [:0 ])
633+ })
634+ return an ._depHash
635+ }
636+
600637// analyzeSummary is a gob-serializable summary of successfully
601638// applying a list of analyzers to a package.
602639type analyzeSummary struct {
@@ -770,27 +807,8 @@ func (an *analysisNode) cacheKey() [sha256.Size]byte {
770807
771808 // vdeps, in PackageID order
772809 for _ , vdep := range moremaps .Sorted (an .succs ) {
773- fmt .Fprintf (hasher , "dep: %s\n " , vdep .mp .PkgPath )
774- fmt .Fprintf (hasher , "export: %s\n " , vdep .summary .DeepExportHash )
775-
776- // action results: errors and facts
777- actions := vdep .summary .Actions
778- names := make ([]string , 0 , len (actions ))
779- for name := range actions {
780- names = append (names , name )
781- }
782- sort .Strings (names )
783- for _ , name := range names {
784- summary := actions [name ]
785- fmt .Fprintf (hasher , "action %s\n " , name )
786- if summary .Err != "" {
787- fmt .Fprintf (hasher , "error %s\n " , summary .Err )
788- } else {
789- fmt .Fprintf (hasher , "facts %s\n " , summary .FactsHash )
790- // We can safely omit summary.diagnostics
791- // from the key since they have no downstream effect.
792- }
793- }
810+ hash := vdep .depHash ()
811+ hasher .Write (hash [:])
794812 }
795813
796814 var hash [sha256 .Size ]byte
0 commit comments