Skip to content

Commit

Permalink
x/text: update for go modules support. Updates #24661
Browse files Browse the repository at this point in the history
  • Loading branch information
ssoroka committed Aug 9, 2019
1 parent 342b2e1 commit 059a5b1
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 101 deletions.
29 changes: 0 additions & 29 deletions cmd/gotext/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ package main

import (
"fmt"
"go/build"
"go/parser"

"golang.org/x/tools/go/loader"
)

const (
extractFile = "extracted.gotext.json"
outFile = "out.gotext.json"
gotextSuffix = ".gotext.json"
)

// NOTE: The command line tool already prefixes with "gotext:".
Expand All @@ -28,22 +18,3 @@ var (
}
errorf = fmt.Errorf
)

// TODO: still used. Remove when possible.
func loadPackages(conf *loader.Config, args []string) (*loader.Program, error) {
if len(args) == 0 {
args = []string{"."}
}

conf.Build = &build.Default
conf.ParserMode = parser.ParseComments

// Use the initial packages from the command line.
args, err := conf.FromArgs(args, false)
if err != nil {
return nil, wrap(err, "loading packages failed")
}

// Load, parse and type-check the whole program.
return conf.Load()
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module golang.org/x/text

require golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
require golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de h1:VNumCimp/Bwk6fRqgPHkjiUPZ/vzlpi23/kQTuQ4gBA=
golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
84 changes: 52 additions & 32 deletions message/pipeline/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ import (
fmtparser "golang.org/x/text/internal/format"
"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/callgraph/cha"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
)

const debug = false
Expand All @@ -49,8 +48,7 @@ func Extract(c *Config) (*State, error) {
x.extractMessages()

return &State{
Config: *c,
program: x.iprog,
Config: *c,
Extracted: Messages{
Language: c.SourceLanguage,
Messages: x.messages,
Expand All @@ -59,8 +57,8 @@ func Extract(c *Config) (*State, error) {
}

type extracter struct {
conf loader.Config
iprog *loader.Program
conf packages.Config
pkgs []*packages.Package
prog *ssa.Program
callGraph *callgraph.Graph

Expand All @@ -72,17 +70,20 @@ type extracter struct {

func newExtracter(c *Config) (x *extracter, err error) {
x = &extracter{
conf: loader.Config{},
conf: packages.Config{
Fset: token.NewFileSet(),
},
globals: map[token.Pos]*constData{},
funcs: map[token.Pos]*callData{},
}

x.iprog, err = loadPackages(&x.conf, c.Packages)
prog, pkgs, err := loadPackages(&x.conf, c.Packages)
if err != nil {
return nil, wrap(err, "")
}
x.prog = prog
x.pkgs = pkgs

x.prog = ssautil.CreateProgram(x.iprog, ssa.GlobalDebug|ssa.BareInits)
x.prog.Build()

x.callGraph = cha.CallGraph(x.prog)
Expand All @@ -100,26 +101,46 @@ func (x *extracter) globalData(pos token.Pos) *constData {
}

func (x *extracter) seedEndpoints() error {
pkgInfo := x.iprog.Package("golang.org/x/text/message")
if pkgInfo == nil {
return errors.New("pipeline: golang.org/x/text/message is not imported")
var pkg *packages.Package
imports := ""
for _, p := range x.pkgs {
for k := range p.Imports {
imports = imports + k + "\n"
}
if p2, ok := p.Imports["golang.org/x/text/message"]; ok {
pkg = p2
break
}
}
if pkg == nil {
return errors.New("pipeline: golang.org/x/text/message is not imported.\n" + imports)
}

var typ *types.Pointer
for _, typeAndVal := range pkg.TypesInfo.Types {
if typeAndVal.Type.String() == "golang.org/x/text/message.Printer" {
typ = types.NewPointer(typeAndVal.Type)
break
}
}

if typ == nil {
return errors.New("pipeline: golang.org/x/text/message.Printer was not found")
}
pkg := x.prog.Package(pkgInfo.Pkg)
typ := types.NewPointer(pkg.Type("Printer").Type())

x.processGlobalVars()

x.handleFunc(x.prog.LookupMethod(typ, pkg.Pkg, "Printf"), &callData{
x.handleFunc(x.prog.LookupMethod(typ, pkg.Types, "Printf"), &callData{
formatPos: 1,
argPos: 2,
isMethod: true,
})
x.handleFunc(x.prog.LookupMethod(typ, pkg.Pkg, "Sprintf"), &callData{
x.handleFunc(x.prog.LookupMethod(typ, pkg.Types, "Sprintf"), &callData{
formatPos: 1,
argPos: 2,
isMethod: true,
})
x.handleFunc(x.prog.LookupMethod(typ, pkg.Pkg, "Fprintf"), &callData{
x.handleFunc(x.prog.LookupMethod(typ, pkg.Types, "Fprintf"), &callData{
formatPos: 2,
argPos: 3,
isMethod: true,
Expand Down Expand Up @@ -488,14 +509,14 @@ func (x *extracter) visitArgs(fd *callData, v ssa.Value) {
// print returns Go syntax for the specified node.
func (x *extracter) print(n ast.Node) string {
var buf bytes.Buffer
format.Node(&buf, x.conf.Fset, n)
_ = format.Node(&buf, x.conf.Fset, n)
return buf.String()
}

type packageExtracter struct {
f *ast.File
x *extracter
info *loader.PackageInfo
pkg *packages.Package
cmap ast.CommentMap
}

Expand All @@ -508,14 +529,13 @@ func (px packageExtracter) getComment(n ast.Node) string {
}

func (x *extracter) extractMessages() {
prog := x.iprog
files := []packageExtracter{}
for _, info := range x.iprog.AllPackages {
for _, f := range info.Files {
for _, pkg := range x.pkgs {
for _, f := range pkg.Syntax {
// Associate comments with nodes.
px := packageExtracter{
f, x, info,
ast.NewCommentMap(prog.Fset, f, f.Comments),
f, x, pkg,
ast.NewCommentMap(pkg.Fset, f, f.Comments),
}
files = append(files, px)
}
Expand Down Expand Up @@ -609,13 +629,13 @@ func (px packageExtracter) handleCall(call *ast.CallExpr) bool {
func (px packageExtracter) getArguments(data *callData) []argument {
arguments := []argument{}
x := px.x
info := px.info
pkg := px.pkg
if data.callArgsStart() >= 0 {
args := data.expr.Args[data.callArgsStart():]
for i, arg := range args {
expr := x.print(arg)
val := ""
if v := info.Types[arg].Value; v != nil {
if v := pkg.TypesInfo.Types[arg].Value; v != nil {
val = v.ExactString()
switch arg.(type) {
case *ast.BinaryExpr, *ast.UnaryExpr:
Expand All @@ -624,12 +644,12 @@ func (px packageExtracter) getArguments(data *callData) []argument {
}
arguments = append(arguments, argument{
ArgNum: i + 1,
Type: info.Types[arg].Type.String(),
UnderlyingType: info.Types[arg].Type.Underlying().String(),
Type: pkg.TypesInfo.Types[arg].Type.String(),
UnderlyingType: pkg.TypesInfo.Types[arg].Type.Underlying().String(),
Expr: expr,
Value: val,
Comment: px.getComment(arg),
Position: posString(&x.conf, info.Pkg, arg.Pos()),
Position: posString(&x.conf, pkg.Types, arg.Pos()),
// TODO report whether it implements
// interfaces plural.Interface,
// gender.Interface.
Expand Down Expand Up @@ -675,7 +695,7 @@ func (px packageExtracter) addMessage(
case fmtparser.StatusBadArgNum, fmtparser.StatusMissingArg:
arg = &argument{
ArgNum: p.ArgNum,
Position: posString(&x.conf, px.info.Pkg, pos),
Position: posString(&x.conf, px.pkg.Types, pos),
}
name, arg.UnderlyingType = verbToPlaceholder(p.Text(), p.ArgNum)
}
Expand Down Expand Up @@ -704,11 +724,11 @@ func (px packageExtracter) addMessage(
// TODO(fix): this doesn't get the before comment.
Comment: comment,
Placeholders: ph.slice,
Position: posString(&x.conf, px.info.Pkg, pos),
Position: posString(&x.conf, px.pkg.Types, pos),
})
}

func posString(conf *loader.Config, pkg *types.Package, pos token.Pos) string {
func posString(conf *packages.Config, pkg *types.Package, pos token.Pos) string {
p := conf.Fset.Position(pos)
file := fmt.Sprintf("%s:%d:%d", filepath.Base(p.Filename), p.Line, p.Column)
return filepath.Join(pkg.Path(), file)
Expand Down
10 changes: 4 additions & 6 deletions message/pipeline/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"golang.org/x/text/internal/catmsg"
"golang.org/x/text/internal/gen"
"golang.org/x/text/language"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/go/packages"
)

var transRe = regexp.MustCompile(`messages\.(.*)\.json`)
Expand All @@ -34,26 +34,24 @@ func (s *State) Generate() error {
path = "."
}
isDir := path[0] == '.'
prog, err := loadPackages(&loader.Config{}, []string{path})
_, pkgs, err := loadPackages(&packages.Config{}, []string{path})
if err != nil {
return wrap(err, "could not load package")
}
pkgs := prog.InitialPackages()
if len(pkgs) != 1 {
return errorf("more than one package selected: %v", pkgs)
}
pkg := pkgs[0].Pkg.Name()

cw, err := s.generate()
if err != nil {
return err
}
if !isDir {
gopath := build.Default.GOPATH
path = filepath.Join(gopath, filepath.FromSlash(pkgs[0].Pkg.Path()))
path = filepath.Join(gopath, filepath.FromSlash(pkgs[0].PkgPath))
}
path = filepath.Join(path, s.Config.GenFile)
cw.WriteGoFile(path, pkg) // TODO: WriteGoFile should return error.
cw.WriteGoFile(path, pkgs[0].Name) // TODO: WriteGoFile should return error.
return err
}

Expand Down
24 changes: 11 additions & 13 deletions message/pipeline/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"go/build"
"go/parser"
"io/ioutil"
"log"
"os"
Expand All @@ -25,7 +23,9 @@ import (
"golang.org/x/text/internal"
"golang.org/x/text/language"
"golang.org/x/text/runes"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
)

const (
Expand Down Expand Up @@ -125,7 +125,6 @@ type State struct {
Config Config

Package string
program *loader.Program

Extracted Messages `json:"messages"`

Expand Down Expand Up @@ -403,20 +402,19 @@ func warnf(format string, args ...interface{}) {
log.Printf(format, args...)
}

func loadPackages(conf *loader.Config, args []string) (*loader.Program, error) {
func loadPackages(conf *packages.Config, args []string) (*ssa.Program, []*packages.Package, error) {
if len(args) == 0 {
args = []string{"."}
}

conf.Build = &build.Default
conf.ParserMode = parser.ParseComments

// Use the initial packages from the command line.
args, err := conf.FromArgs(args, false)
conf.Mode = packages.LoadAllSyntax
pkgs, err := packages.Load(conf, args...)
if err != nil {
return nil, wrap(err, "loading packages failed")
packages.PrintErrors(pkgs)
return nil, nil, err
}

// Load, parse and type-check the whole program.
return conf.Load()
prog, _ := ssautil.Packages(pkgs, 0)

return prog, pkgs, nil
}
Loading

0 comments on commit 059a5b1

Please sign in to comment.