5
5
package ssa_test
6
6
7
7
import (
8
- "fmt"
9
8
"go/ast"
10
9
"go/parser"
11
10
"go/token"
11
+ "io/fs"
12
12
"testing"
13
13
14
+ "golang.org/x/tools/go/packages"
14
15
"golang.org/x/tools/go/ssa"
15
16
"golang.org/x/tools/go/ssa/ssautil"
16
-
17
- "golang.org/x/tools/go/packages"
18
17
"golang.org/x/tools/internal/testfiles"
19
18
"golang.org/x/tools/txtar"
20
19
)
21
20
22
- // loadPackageFromSingleFile is a utility function to create a package based on the content of a go file,
23
- // and returns the pkgInfo about the input go file. The package name is retrieved from content after parsing.
24
- // It's useful to create a ssa package and its packages.Package and ast.File representation.
25
- func loadPackageFromSingleFile (t * testing.T , content string , mode ssa.BuilderMode ) * pkgInfo {
26
- ar := archiveFromSingleFileContent (content )
27
- pkgs := fromTxtar (t , ar )
28
- prog , _ := ssautil .Packages (pkgs , mode )
29
-
30
- pkgName := packageName (t , content )
31
- pkgInfo := getPkgInfo (prog , pkgs , pkgName )
32
- if pkgInfo == nil {
33
- t .Fatalf ("fail to get package %s from loaded packages" , pkgName )
34
- }
35
- return pkgInfo
36
- }
37
-
38
- // archiveFromSingleFileContent helps to create a go archive format string
39
- // with go module example.com, the given content is put inside main.go.
40
- // The package name depends on the package clause in the content.
41
- //
42
- // It's useful to define a package in a string variable instead of putting it inside a file.
43
- func archiveFromSingleFileContent (content string ) string {
44
- return fmt .Sprintf (`
45
- -- go.mod --
46
- module example.com
47
- go 1.18
48
- -- main.go --
49
- %s` , content )
50
- }
51
-
52
- // fromTxtar creates a temporary folder from the content in txtar format
53
- // and then loads the packages.
54
- func fromTxtar (t * testing.T , content string ) []* packages.Package {
55
- ar := txtar .Parse ([]byte (content ))
56
-
57
- fs , err := txtar .FS (ar )
21
+ // packageFromBytes creates a package under the go module example.com from file content data,
22
+ // and returns its ssa package.
23
+ func packageFromBytes (t * testing.T , data string , mode ssa.BuilderMode ) * ssa.Package {
24
+ src , err := txtar .FS (& txtar.Archive {
25
+ Files : []txtar.File {
26
+ {Name : "go.mod" , Data : []byte ("module example.com\n go 1.18" )},
27
+ {Name : "main.go" , Data : []byte (data )},
28
+ }})
58
29
if err != nil {
59
30
t .Fatal (err )
60
31
}
61
32
62
- dir := testfiles .CopyToTmp (t , fs )
63
- if err != nil {
64
- t .Fatal (err )
33
+ pkgs := fromFS (t , src , "." )
34
+ prog , _ := ssautil .Packages (pkgs , mode )
35
+
36
+ pkgName := packageName (t , data )
37
+ for _ , spkg := range prog .AllPackages () {
38
+ if spkg .Pkg .Name () == pkgName {
39
+ return spkg
40
+ }
65
41
}
42
+ t .Fatalf ("fail to get package %s from loaded packages" , pkgName )
43
+ return nil
44
+ }
66
45
46
+ // fromFS copies the files and directories in src to a new temporary testing directory,
47
+ // loads and returns the Go packages named by the given patterns.
48
+ func fromFS (t * testing.T , src fs.FS , patterns ... string ) []* packages.Package {
49
+ dir := testfiles .CopyToTmp (t , src )
67
50
var baseConfig = & packages.Config {
68
51
Mode : packages .NeedSyntax |
69
52
packages .NeedTypesInfo |
@@ -75,7 +58,7 @@ func fromTxtar(t *testing.T, content string) []*packages.Package {
75
58
packages .NeedTypes ,
76
59
Dir : dir ,
77
60
}
78
- pkgs , err := packages .Load (baseConfig , "./..." )
61
+ pkgs , err := packages .Load (baseConfig , patterns ... )
79
62
if err != nil {
80
63
t .Fatal (err )
81
64
}
@@ -88,18 +71,16 @@ func fromTxtar(t *testing.T, content string) []*packages.Package {
88
71
// pkgInfo holds information about a ssa package for testing purpose.
89
72
// We assume ssa package only has one file in tests.
90
73
type pkgInfo struct {
91
- spkg * ssa.Package // ssa representation of a package
92
74
ppkg * packages.Package // packages representation of a package
93
75
file * ast.File // AST representation of the first package file
94
76
}
95
77
96
- // getPkgInfo retrieves the package info from the program with the given name.
97
- // It's useful to test a package from a string instead of storing it inside a file.
98
- func getPkgInfo (prog * ssa.Program , pkgs []* packages.Package , pkgname string ) * pkgInfo {
78
+ // getPkgInfo gets the ast.File and packages.Package of a ssa package.
79
+ func getPkgInfo (pkgs []* packages.Package , pkgname string ) * pkgInfo {
99
80
for _ , pkg := range pkgs {
81
+ // checking package name is enough for testing purpose
100
82
if pkg .Name == pkgname {
101
83
return & pkgInfo {
102
- spkg : prog .Package (pkg .Types ),
103
84
ppkg : pkg ,
104
85
file : pkg .Syntax [0 ], // we assume the test package is only consisted by one file
105
86
}
0 commit comments