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