@@ -14,17 +14,16 @@ import (
1414 "go/token"
1515 "go/types"
1616 "path/filepath"
17- "sort"
1817 "strings"
1918 "unicode"
2019 "unicode/utf8"
2120
22- fmtparser "golang.org/x/text/internal/format"
2321 "golang.org/x/tools/go/callgraph"
2422 "golang.org/x/tools/go/callgraph/cha"
25- "golang.org/x/tools/go/loader "
23+ "golang.org/x/tools/go/packages "
2624 "golang.org/x/tools/go/ssa"
27- "golang.org/x/tools/go/ssa/ssautil"
25+
26+ fmtparser "golang.org/x/text/internal/format"
2827)
2928
3029const debug = false
@@ -50,8 +49,7 @@ func Extract(c *Config) (*State, error) {
5049 x .extractMessages ()
5150
5251 return & State {
53- Config : * c ,
54- program : x .iprog ,
52+ Config : * c ,
5553 Extracted : Messages {
5654 Language : c .SourceLanguage ,
5755 Messages : x .messages ,
@@ -60,8 +58,8 @@ func Extract(c *Config) (*State, error) {
6058}
6159
6260type extracter struct {
63- conf loader .Config
64- iprog * loader. Program
61+ conf packages .Config
62+ pkgs [] * packages. Package
6563 prog * ssa.Program
6664 callGraph * callgraph.Graph
6765
@@ -73,17 +71,20 @@ type extracter struct {
7371
7472func newExtracter (c * Config ) (x * extracter , err error ) {
7573 x = & extracter {
76- conf : loader.Config {},
74+ conf : packages.Config {
75+ Fset : token .NewFileSet (),
76+ },
7777 globals : map [token.Pos ]* constData {},
7878 funcs : map [token.Pos ]* callData {},
7979 }
8080
81- x . iprog , err = loadPackages (& x .conf , c .Packages )
81+ prog , pkgs , err : = loadPackages (& x .conf , c .Packages )
8282 if err != nil {
8383 return nil , wrap (err , "" )
8484 }
85+ x .prog = prog
86+ x .pkgs = pkgs
8587
86- x .prog = ssautil .CreateProgram (x .iprog , ssa .GlobalDebug | ssa .BareInits )
8788 x .prog .Build ()
8889
8990 x .callGraph = cha .CallGraph (x .prog )
@@ -101,26 +102,46 @@ func (x *extracter) globalData(pos token.Pos) *constData {
101102}
102103
103104func (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" )
107130 }
108- pkg := x .prog .Package (pkgInfo .Pkg )
109- typ := types .NewPointer (pkg .Type ("Printer" ).Type ())
110131
111132 x .processGlobalVars ()
112133
113- x .handleFunc (x .prog .LookupMethod (typ , pkg .Pkg , "Printf" ), & callData {
134+ x .handleFunc (x .prog .LookupMethod (typ , pkg .Types , "Printf" ), & callData {
114135 formatPos : 1 ,
115136 argPos : 2 ,
116137 isMethod : true ,
117138 })
118- x .handleFunc (x .prog .LookupMethod (typ , pkg .Pkg , "Sprintf" ), & callData {
139+ x .handleFunc (x .prog .LookupMethod (typ , pkg .Types , "Sprintf" ), & callData {
119140 formatPos : 1 ,
120141 argPos : 2 ,
121142 isMethod : true ,
122143 })
123- x .handleFunc (x .prog .LookupMethod (typ , pkg .Pkg , "Fprintf" ), & callData {
144+ x .handleFunc (x .prog .LookupMethod (typ , pkg .Types , "Fprintf" ), & callData {
124145 formatPos : 2 ,
125146 argPos : 3 ,
126147 isMethod : true ,
@@ -489,14 +510,14 @@ func (x *extracter) visitArgs(fd *callData, v ssa.Value) {
489510// print returns Go syntax for the specified node.
490511func (x * extracter ) print (n ast.Node ) string {
491512 var buf bytes.Buffer
492- format .Node (& buf , x .conf .Fset , n )
513+ _ = format .Node (& buf , x .conf .Fset , n )
493514 return buf .String ()
494515}
495516
496517type packageExtracter struct {
497518 f * ast.File
498519 x * extracter
499- info * loader. PackageInfo
520+ pkg * packages. Package
500521 cmap ast.CommentMap
501522}
502523
@@ -509,20 +530,13 @@ func (px packageExtracter) getComment(n ast.Node) string {
509530}
510531
511532func (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 () })
518533 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 {
522536 // Associate comments with nodes.
523537 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 ),
526540 }
527541 files = append (files , px )
528542 }
@@ -616,13 +630,13 @@ func (px packageExtracter) handleCall(call *ast.CallExpr) bool {
616630func (px packageExtracter ) getArguments (data * callData ) []argument {
617631 arguments := []argument {}
618632 x := px .x
619- info := px .info
633+ pkg := px .pkg
620634 if data .callArgsStart () >= 0 {
621635 args := data .expr .Args [data .callArgsStart ():]
622636 for i , arg := range args {
623637 expr := x .print (arg )
624638 val := ""
625- if v := info .Types [arg ].Value ; v != nil {
639+ if v := pkg . TypesInfo .Types [arg ].Value ; v != nil {
626640 val = v .ExactString ()
627641 switch arg .(type ) {
628642 case * ast.BinaryExpr , * ast.UnaryExpr :
@@ -631,12 +645,12 @@ func (px packageExtracter) getArguments(data *callData) []argument {
631645 }
632646 arguments = append (arguments , argument {
633647 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 (),
636650 Expr : expr ,
637651 Value : val ,
638652 Comment : px .getComment (arg ),
639- Position : posString (& x .conf , info . Pkg , arg .Pos ()),
653+ Position : posString (& x .conf , pkg . Types , arg .Pos ()),
640654 // TODO report whether it implements
641655 // interfaces plural.Interface,
642656 // gender.Interface.
@@ -682,7 +696,7 @@ func (px packageExtracter) addMessage(
682696 case fmtparser .StatusBadArgNum , fmtparser .StatusMissingArg :
683697 arg = & argument {
684698 ArgNum : p .ArgNum ,
685- Position : posString (& x .conf , px .info . Pkg , pos ),
699+ Position : posString (& x .conf , px .pkg . Types , pos ),
686700 }
687701 name , arg .UnderlyingType = verbToPlaceholder (p .Text (), p .ArgNum )
688702 }
@@ -711,11 +725,11 @@ func (px packageExtracter) addMessage(
711725 // TODO(fix): this doesn't get the before comment.
712726 Comment : comment ,
713727 Placeholders : ph .slice ,
714- Position : posString (& x .conf , px .info . Pkg , pos ),
728+ Position : posString (& x .conf , px .pkg . Types , pos ),
715729 })
716730}
717731
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 {
719733 p := conf .Fset .Position (pos )
720734 file := fmt .Sprintf ("%s:%d:%d" , filepath .Base (p .Filename ), p .Line , p .Column )
721735 return filepath .Join (pkg .Path (), file )
@@ -818,4 +832,4 @@ func isMsg(s string) bool {
818832 }
819833 }
820834 return false
821- }
835+ }
0 commit comments