From 54d3d47daf9190275bbdaf8703b84969a4593451 Mon Sep 17 00:00:00 2001 From: Corey Hulen Date: Fri, 24 Mar 2017 23:31:34 -0700 Subject: PLT-6076 Adding viper libs for config file changes (#5871) * Adding viper libs for config file changes * Removing the old fsnotify lib * updating some missing libs --- vendor/golang.org/x/text/cmd/gotext/extract.go | 195 +++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 vendor/golang.org/x/text/cmd/gotext/extract.go (limited to 'vendor/golang.org/x/text/cmd/gotext/extract.go') diff --git a/vendor/golang.org/x/text/cmd/gotext/extract.go b/vendor/golang.org/x/text/cmd/gotext/extract.go new file mode 100644 index 000000000..79a9b596d --- /dev/null +++ b/vendor/golang.org/x/text/cmd/gotext/extract.go @@ -0,0 +1,195 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "go/ast" + "go/build" + "go/constant" + "go/format" + "go/parser" + "go/types" + "io/ioutil" + "os" + "path" + "path/filepath" + "strings" + + "golang.org/x/tools/go/loader" +) + +// TODO: +// - merge information into existing files +// - handle different file formats (PO, XLIFF) +// - handle features (gender, plural) +// - message rewriting + +var cmdExtract = &Command{ + Run: runExtract, + UsageLine: "extract *", + Short: "extract strings to be translated from code", +} + +func runExtract(cmd *Command, args []string) error { + if len(args) == 0 { + args = []string{"."} + } + + conf := loader.Config{ + Build: &build.Default, + ParserMode: parser.ParseComments, + } + + // Use the initial packages from the command line. + args, err := conf.FromArgs(args, false) + if err != nil { + return err + } + + // Load, parse and type-check the whole program. + iprog, err := conf.Load() + if err != nil { + return err + } + + // print returns Go syntax for the specified node. + print := func(n ast.Node) string { + var buf bytes.Buffer + format.Node(&buf, conf.Fset, n) + return buf.String() + } + + var translations []Translation + + for _, info := range iprog.InitialPackages() { + for _, f := range info.Files { + // Associate comments with nodes. + cmap := ast.NewCommentMap(iprog.Fset, f, f.Comments) + getComment := func(n ast.Node) string { + cs := cmap.Filter(n).Comments() + if len(cs) > 0 { + return strings.TrimSpace(cs[0].Text()) + } + return "" + } + + // Find function calls. + ast.Inspect(f, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok { + return true + } + + // Skip calls of functions other than + // (*message.Printer).{Sp,Fp,P}rintf. + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return true + } + meth := info.Selections[sel] + if meth == nil || meth.Kind() != types.MethodVal { + return true + } + // TODO: remove cheap hack and check if the type either + // implements some interface or is specifically of type + // "golang.org/x/text/message".Printer. + m, ok := extractFuncs[path.Base(meth.Recv().String())] + if !ok { + return true + } + + // argn is the index of the format string. + argn, ok := m[meth.Obj().Name()] + if !ok || argn >= len(call.Args) { + return true + } + + // Skip calls with non-constant format string. + fmtstr := info.Types[call.Args[argn]].Value + if fmtstr == nil || fmtstr.Kind() != constant.String { + return true + } + + posn := conf.Fset.Position(call.Lparen) + filepos := fmt.Sprintf("%s:%d:%d", filepath.Base(posn.Filename), posn.Line, posn.Column) + + // TODO: identify the type of the format argument. If it is not + // a string, multiple keys may be defined. + var key []string + + // TODO: replace substitutions (%v) with a translator friendly + // notation. For instance: + // "%d files remaining" -> "{numFiles} files remaining", or + // "%d files remaining" -> "{arg1} files remaining" + // Alternatively, this could be done at a later stage. + msg := constant.StringVal(fmtstr) + + // Construct a Translation unit. + c := Translation{ + Key: key, + Position: filepath.Join(info.Pkg.Path(), filepos), + Original: Text{Msg: msg}, + ExtractedComment: getComment(call.Args[0]), + // TODO(fix): this doesn't get the before comment. + // Comment: getComment(call), + } + + for i, arg := range call.Args[argn+1:] { + var val string + if v := info.Types[arg].Value; v != nil { + val = v.ExactString() + } + posn := conf.Fset.Position(arg.Pos()) + filepos := fmt.Sprintf("%s:%d:%d", filepath.Base(posn.Filename), posn.Line, posn.Column) + c.Args = append(c.Args, Argument{ + ID: i + 1, + Type: info.Types[arg].Type.String(), + UnderlyingType: info.Types[arg].Type.Underlying().String(), + Expr: print(arg), + Value: val, + Comment: getComment(arg), + Position: filepath.Join(info.Pkg.Path(), filepos), + // TODO report whether it implements + // interfaces plural.Interface, + // gender.Interface. + }) + } + + translations = append(translations, c) + return true + }) + } + } + + data, err := json.MarshalIndent(translations, "", " ") + if err != nil { + return err + } + for _, tag := range getLangs() { + // TODO: merge with existing files, don't overwrite. + os.MkdirAll(*dir, 0744) + file := filepath.Join(*dir, fmt.Sprintf("gotext_%v.out.json", tag)) + if err := ioutil.WriteFile(file, data, 0744); err != nil { + return fmt.Errorf("could not create file: %v", err) + } + } + return nil +} + +// extractFuncs indicates the types and methods for which to extract strings, +// and which argument to extract. +// TODO: use the types in conf.Import("golang.org/x/text/message") to extract +// the correct instances. +var extractFuncs = map[string]map[string]int{ + // TODO: Printer -> *golang.org/x/text/message.Printer + "message.Printer": { + "Printf": 0, + "Sprintf": 0, + "Fprintf": 1, + }, +} -- cgit v1.2.3-1-g7c22