@@ -613,6 +613,115 @@ func TestDeclNaming_VarsAndTypes(t *testing.T) {
613
613
)
614
614
}
615
615
616
+ func Test_CrossPackageAnalysis (t * testing.T ) {
617
+ src1 := `
618
+ package main
619
+ import "github.com/gopherjs/gopherjs/compiler/stable"
620
+
621
+ func main() {
622
+ m := map[string]int{
623
+ "one": 1,
624
+ "two": 2,
625
+ "three": 3,
626
+ }
627
+ stable.Print(m)
628
+ }`
629
+ src2 := `
630
+ package collections
631
+ import "github.com/gopherjs/gopherjs/compiler/cmp"
632
+
633
+ func Keys[K cmp.Ordered, V any, M ~map[K]V](m M) []K {
634
+ keys := make([]K, 0, len(m))
635
+ for k := range m {
636
+ keys = append(keys, k)
637
+ }
638
+ return keys
639
+ }`
640
+ src3 := `
641
+ package collections
642
+ import "github.com/gopherjs/gopherjs/compiler/cmp"
643
+
644
+ func Values[K cmp.Ordered, V any, M ~map[K]V](m M) []V {
645
+ values := make([]V, 0, len(m))
646
+ for _, v := range m {
647
+ values = append(values, v)
648
+ }
649
+ return values
650
+ }`
651
+ src4 := `
652
+ package sorts
653
+ import "github.com/gopherjs/gopherjs/compiler/cmp"
654
+
655
+ func Pair[K cmp.Ordered, V any, SK ~[]K, SV ~[]V](k SK, v SV) {
656
+ Bubble(len(k),
657
+ func(i, j int) bool { return k[i] < k[j] },
658
+ func(i, j int) { k[i], v[i], k[j], v[j] = k[j], v[j], k[i], v[i] })
659
+ }
660
+
661
+ func Bubble(length int, less func(i, j int) bool, swap func(i, j int)) {
662
+ for i := 0; i < length; i++ {
663
+ for j := i + 1; j < length; j++ {
664
+ if less(j, i) {
665
+ swap(i, j)
666
+ }
667
+ }
668
+ }
669
+ }`
670
+ src5 := `
671
+ package stable
672
+ import (
673
+ "github.com/gopherjs/gopherjs/compiler/collections"
674
+ "github.com/gopherjs/gopherjs/compiler/sorts"
675
+ "github.com/gopherjs/gopherjs/compiler/cmp"
676
+ )
677
+
678
+ func Print[K cmp.Ordered, V any, M ~map[K]V](m M) {
679
+ keys := collections.Keys(m)
680
+ values := collections.Values(m)
681
+ sorts.Pair(keys, values)
682
+ for i, k := range keys {
683
+ println(i, k, values[i])
684
+ }
685
+ }`
686
+ src6 := `
687
+ package cmp
688
+ type Ordered interface { ~int | ~uint | ~float64 | ~string }`
689
+
690
+ root := srctesting .ParseSources (t ,
691
+ []srctesting.Source {
692
+ {Name : `main.go` , Contents : []byte (src1 )},
693
+ },
694
+ []srctesting.Source {
695
+ {Name : `collections/keys.go` , Contents : []byte (src2 )},
696
+ {Name : `collections/values.go` , Contents : []byte (src3 )},
697
+ {Name : `sorts/sorts.go` , Contents : []byte (src4 )},
698
+ {Name : `stable/print.go` , Contents : []byte (src5 )},
699
+ {Name : `cmp/ordered.go` , Contents : []byte (src6 )},
700
+ })
701
+
702
+ archives := compileProject (t , root , false )
703
+ checkForDeclFullNames (t , archives ,
704
+ // collections
705
+ `funcVar:github.com/gopherjs/gopherjs/compiler/collections.Values` ,
706
+ `func:github.com/gopherjs/gopherjs/compiler/collections.Values<string, int, map[string]int>` ,
707
+ `funcVar:github.com/gopherjs/gopherjs/compiler/collections.Keys` ,
708
+ `func:github.com/gopherjs/gopherjs/compiler/collections.Keys<string, int, map[string]int>` ,
709
+
710
+ // sorts
711
+ `funcVar:github.com/gopherjs/gopherjs/compiler/sorts.Pair` ,
712
+ `func:github.com/gopherjs/gopherjs/compiler/sorts.Pair<string, int, []string, []int>` ,
713
+ `funcVar:github.com/gopherjs/gopherjs/compiler/sorts.Bubble` ,
714
+ `func:github.com/gopherjs/gopherjs/compiler/sorts.Bubble` ,
715
+
716
+ // stable
717
+ `funcVar:github.com/gopherjs/gopherjs/compiler/stable.Print` ,
718
+ `func:github.com/gopherjs/gopherjs/compiler/stable.Print<string, int, map[string]int>` ,
719
+
720
+ // main
721
+ `init:main` ,
722
+ )
723
+ }
724
+
616
725
func TestArchiveSelectionAfterSerialization (t * testing.T ) {
617
726
src := `
618
727
package main
@@ -679,43 +788,43 @@ func compileProject(t *testing.T, root *packages.Package, minify bool) map[strin
679
788
pkgMap [pkg .PkgPath ] = pkg
680
789
})
681
790
682
- archiveCache := map [string ]* Archive {}
683
- var importContext * ImportContext
684
- importContext = & ImportContext {
685
- Packages : map [string ]* types.Package {},
686
- ImportArchive : func (path string ) (* Archive , error ) {
687
- // find in local cache
688
- if a , ok := archiveCache [path ]; ok {
689
- return a , nil
690
- }
691
-
692
- pkg , ok := pkgMap [path ]
693
- if ! ok {
694
- t .Fatal (`package not found:` , path )
695
- }
696
- importContext .Packages [path ] = pkg .Types
697
-
698
- srcs := sources.Sources {
699
- ImportPath : path ,
700
- Files : pkg .Syntax ,
701
- FileSet : pkg .Fset ,
702
- }
791
+ allSrcs := map [string ]* sources.Sources {}
792
+ for _ , pkg := range pkgMap {
793
+ srcs := & sources.Sources {
794
+ ImportPath : pkg .PkgPath ,
795
+ Dir : `` ,
796
+ Files : pkg .Syntax ,
797
+ FileSet : pkg .Fset ,
798
+ }
799
+ allSrcs [pkg .PkgPath ] = srcs
800
+ }
703
801
704
- // compile package
705
- a , err := Compile (srcs , importContext , minify )
706
- if err != nil {
707
- return nil , err
708
- }
709
- archiveCache [path ] = a
710
- return a , nil
711
- },
802
+ importer := func (path , srcDir string ) (* sources.Sources , error ) {
803
+ srcs , ok := allSrcs [path ]
804
+ if ! ok {
805
+ t .Fatal (`package not found:` , path )
806
+ return nil , nil
807
+ }
808
+ return srcs , nil
712
809
}
713
810
714
- _ , err := importContext .ImportArchive (root .PkgPath )
715
- if err != nil {
716
- t .Fatal (`failed to compile:` , err )
811
+ tContext := types .NewContext ()
812
+ sortedSources := make ([]* sources.Sources , 0 , len (allSrcs ))
813
+ for _ , srcs := range allSrcs {
814
+ sortedSources = append (sortedSources , srcs )
717
815
}
718
- return archiveCache
816
+ sources .SortedSourcesSlice (sortedSources )
817
+ PrepareAllSources (sortedSources , importer , tContext )
818
+
819
+ archives := map [string ]* Archive {}
820
+ for _ , srcs := range allSrcs {
821
+ a , err := Compile (srcs , tContext , minify )
822
+ if err != nil {
823
+ t .Fatal (`failed to compile:` , err )
824
+ }
825
+ archives [srcs .ImportPath ] = a
826
+ }
827
+ return archives
719
828
}
720
829
721
830
// newTime creates an arbitrary time.Time offset by the given number of seconds.
@@ -730,6 +839,13 @@ func newTime(seconds float64) time.Time {
730
839
func reloadCompiledProject (t * testing.T , archives map [string ]* Archive , rootPkgPath string ) map [string ]* Archive {
731
840
t .Helper ()
732
841
842
+ // TODO(grantnelson-wf): The tests using this function are out-of-date
843
+ // since they are testing the old archive caching that has been disabled.
844
+ // At some point, these tests should be updated to test any new caching
845
+ // mechanism that is implemented or removed. As is this function is faking
846
+ // the old recursive archive loading that is no longer used since it
847
+ // doesn't allow cross package analysis for generings.
848
+
733
849
buildTime := newTime (5.0 )
734
850
serialized := map [string ][]byte {}
735
851
for path , a := range archives {
@@ -742,6 +858,10 @@ func reloadCompiledProject(t *testing.T, archives map[string]*Archive, rootPkgPa
742
858
743
859
srcModTime := newTime (0.0 )
744
860
reloadCache := map [string ]* Archive {}
861
+ type ImportContext struct {
862
+ Packages map [string ]* types.Package
863
+ ImportArchive func (path string ) (* Archive , error )
864
+ }
745
865
var importContext * ImportContext
746
866
importContext = & ImportContext {
747
867
Packages : map [string ]* types.Package {},
0 commit comments