@@ -21,9 +21,8 @@ import (
21
21
fmtparser "golang.org/x/text/internal/format"
22
22
"golang.org/x/tools/go/callgraph"
23
23
"golang.org/x/tools/go/callgraph/cha"
24
- "golang.org/x/tools/go/loader "
24
+ "golang.org/x/tools/go/packages "
25
25
"golang.org/x/tools/go/ssa"
26
- "golang.org/x/tools/go/ssa/ssautil"
27
26
)
28
27
29
28
const debug = false
@@ -49,8 +48,7 @@ func Extract(c *Config) (*State, error) {
49
48
x .extractMessages ()
50
49
51
50
return & State {
52
- Config : * c ,
53
- program : x .iprog ,
51
+ Config : * c ,
54
52
Extracted : Messages {
55
53
Language : c .SourceLanguage ,
56
54
Messages : x .messages ,
@@ -59,8 +57,8 @@ func Extract(c *Config) (*State, error) {
59
57
}
60
58
61
59
type extracter struct {
62
- conf loader .Config
63
- iprog * loader. Program
60
+ conf packages .Config
61
+ pkgs [] * packages. Package
64
62
prog * ssa.Program
65
63
callGraph * callgraph.Graph
66
64
@@ -72,17 +70,20 @@ type extracter struct {
72
70
73
71
func newExtracter (c * Config ) (x * extracter , err error ) {
74
72
x = & extracter {
75
- conf : loader.Config {},
73
+ conf : packages.Config {
74
+ Fset : token .NewFileSet (),
75
+ },
76
76
globals : map [token.Pos ]* constData {},
77
77
funcs : map [token.Pos ]* callData {},
78
78
}
79
79
80
- x . iprog , err = loadPackages (& x .conf , c .Packages )
80
+ prog , pkgs , err : = loadPackages (& x .conf , c .Packages )
81
81
if err != nil {
82
82
return nil , wrap (err , "" )
83
83
}
84
+ x .prog = prog
85
+ x .pkgs = pkgs
84
86
85
- x .prog = ssautil .CreateProgram (x .iprog , ssa .GlobalDebug | ssa .BareInits )
86
87
x .prog .Build ()
87
88
88
89
x .callGraph = cha .CallGraph (x .prog )
@@ -100,26 +101,46 @@ func (x *extracter) globalData(pos token.Pos) *constData {
100
101
}
101
102
102
103
func (x * extracter ) seedEndpoints () error {
103
- pkgInfo := x .iprog .Package ("golang.org/x/text/message" )
104
- if pkgInfo == nil {
105
- return errors .New ("pipeline: golang.org/x/text/message is not imported" )
104
+ var pkg * packages.Package
105
+ imports := ""
106
+ for _ , p := range x .pkgs {
107
+ for k := range p .Imports {
108
+ imports = imports + k + "\n "
109
+ }
110
+ if p2 , ok := p .Imports ["golang.org/x/text/message" ]; ok {
111
+ pkg = p2
112
+ break
113
+ }
114
+ }
115
+ if pkg == nil {
116
+ return errors .New ("pipeline: golang.org/x/text/message is not imported.\n " + imports )
117
+ }
118
+
119
+ var typ * types.Pointer
120
+ for _ , typeAndVal := range pkg .TypesInfo .Types {
121
+ if typeAndVal .Type .String () == "golang.org/x/text/message.Printer" {
122
+ typ = types .NewPointer (typeAndVal .Type )
123
+ break
124
+ }
125
+ }
126
+
127
+ if typ == nil {
128
+ return errors .New ("pipeline: golang.org/x/text/message.Printer was not found" )
106
129
}
107
- pkg := x .prog .Package (pkgInfo .Pkg )
108
- typ := types .NewPointer (pkg .Type ("Printer" ).Type ())
109
130
110
131
x .processGlobalVars ()
111
132
112
- x .handleFunc (x .prog .LookupMethod (typ , pkg .Pkg , "Printf" ), & callData {
133
+ x .handleFunc (x .prog .LookupMethod (typ , pkg .Types , "Printf" ), & callData {
113
134
formatPos : 1 ,
114
135
argPos : 2 ,
115
136
isMethod : true ,
116
137
})
117
- x .handleFunc (x .prog .LookupMethod (typ , pkg .Pkg , "Sprintf" ), & callData {
138
+ x .handleFunc (x .prog .LookupMethod (typ , pkg .Types , "Sprintf" ), & callData {
118
139
formatPos : 1 ,
119
140
argPos : 2 ,
120
141
isMethod : true ,
121
142
})
122
- x .handleFunc (x .prog .LookupMethod (typ , pkg .Pkg , "Fprintf" ), & callData {
143
+ x .handleFunc (x .prog .LookupMethod (typ , pkg .Types , "Fprintf" ), & callData {
123
144
formatPos : 2 ,
124
145
argPos : 3 ,
125
146
isMethod : true ,
@@ -488,14 +509,14 @@ func (x *extracter) visitArgs(fd *callData, v ssa.Value) {
488
509
// print returns Go syntax for the specified node.
489
510
func (x * extracter ) print (n ast.Node ) string {
490
511
var buf bytes.Buffer
491
- format .Node (& buf , x .conf .Fset , n )
512
+ _ = format .Node (& buf , x .conf .Fset , n )
492
513
return buf .String ()
493
514
}
494
515
495
516
type packageExtracter struct {
496
517
f * ast.File
497
518
x * extracter
498
- info * loader. PackageInfo
519
+ pkg * packages. Package
499
520
cmap ast.CommentMap
500
521
}
501
522
@@ -508,14 +529,13 @@ func (px packageExtracter) getComment(n ast.Node) string {
508
529
}
509
530
510
531
func (x * extracter ) extractMessages () {
511
- prog := x .iprog
512
532
files := []packageExtracter {}
513
- for _ , info := range x .iprog . AllPackages {
514
- for _ , f := range info . Files {
533
+ for _ , pkg := range x .pkgs {
534
+ for _ , f := range pkg . Syntax {
515
535
// Associate comments with nodes.
516
536
px := packageExtracter {
517
- f , x , info ,
518
- ast .NewCommentMap (prog .Fset , f , f .Comments ),
537
+ f , x , pkg ,
538
+ ast .NewCommentMap (pkg .Fset , f , f .Comments ),
519
539
}
520
540
files = append (files , px )
521
541
}
@@ -609,13 +629,13 @@ func (px packageExtracter) handleCall(call *ast.CallExpr) bool {
609
629
func (px packageExtracter ) getArguments (data * callData ) []argument {
610
630
arguments := []argument {}
611
631
x := px .x
612
- info := px .info
632
+ pkg := px .pkg
613
633
if data .callArgsStart () >= 0 {
614
634
args := data .expr .Args [data .callArgsStart ():]
615
635
for i , arg := range args {
616
636
expr := x .print (arg )
617
637
val := ""
618
- if v := info .Types [arg ].Value ; v != nil {
638
+ if v := pkg . TypesInfo .Types [arg ].Value ; v != nil {
619
639
val = v .ExactString ()
620
640
switch arg .(type ) {
621
641
case * ast.BinaryExpr , * ast.UnaryExpr :
@@ -624,12 +644,12 @@ func (px packageExtracter) getArguments(data *callData) []argument {
624
644
}
625
645
arguments = append (arguments , argument {
626
646
ArgNum : i + 1 ,
627
- Type : info .Types [arg ].Type .String (),
628
- UnderlyingType : info .Types [arg ].Type .Underlying ().String (),
647
+ Type : pkg . TypesInfo .Types [arg ].Type .String (),
648
+ UnderlyingType : pkg . TypesInfo .Types [arg ].Type .Underlying ().String (),
629
649
Expr : expr ,
630
650
Value : val ,
631
651
Comment : px .getComment (arg ),
632
- Position : posString (& x .conf , info . Pkg , arg .Pos ()),
652
+ Position : posString (& x .conf , pkg . Types , arg .Pos ()),
633
653
// TODO report whether it implements
634
654
// interfaces plural.Interface,
635
655
// gender.Interface.
@@ -675,7 +695,7 @@ func (px packageExtracter) addMessage(
675
695
case fmtparser .StatusBadArgNum , fmtparser .StatusMissingArg :
676
696
arg = & argument {
677
697
ArgNum : p .ArgNum ,
678
- Position : posString (& x .conf , px .info . Pkg , pos ),
698
+ Position : posString (& x .conf , px .pkg . Types , pos ),
679
699
}
680
700
name , arg .UnderlyingType = verbToPlaceholder (p .Text (), p .ArgNum )
681
701
}
@@ -704,11 +724,11 @@ func (px packageExtracter) addMessage(
704
724
// TODO(fix): this doesn't get the before comment.
705
725
Comment : comment ,
706
726
Placeholders : ph .slice ,
707
- Position : posString (& x .conf , px .info . Pkg , pos ),
727
+ Position : posString (& x .conf , px .pkg . Types , pos ),
708
728
})
709
729
}
710
730
711
- func posString (conf * loader .Config , pkg * types.Package , pos token.Pos ) string {
731
+ func posString (conf * packages .Config , pkg * types.Package , pos token.Pos ) string {
712
732
p := conf .Fset .Position (pos )
713
733
file := fmt .Sprintf ("%s:%d:%d" , filepath .Base (p .Filename ), p .Line , p .Column )
714
734
return filepath .Join (pkg .Path (), file )
0 commit comments