Add generated file

This PR adds generated files under pkg/client and vendor folder.
This commit is contained in:
xing-yang
2018-07-12 10:55:15 -07:00
parent 36b1de0341
commit e213d1890d
17729 changed files with 5090889 additions and 0 deletions

373
vendor/golang.org/x/tools/refactor/eg/eg.go generated vendored Normal file
View File

@@ -0,0 +1,373 @@
// Copyright 2014 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 eg implements the example-based refactoring tool whose
// command-line is defined in golang.org/x/tools/cmd/eg.
package eg // import "golang.org/x/tools/refactor/eg"
import (
"bytes"
"fmt"
"go/ast"
"go/format"
"go/printer"
"go/token"
"go/types"
"os"
)
const Help = `
This tool implements example-based refactoring of expressions.
The transformation is specified as a Go file defining two functions,
'before' and 'after', of identical types. Each function body consists
of a single statement: either a return statement with a single
(possibly multi-valued) expression, or an expression statement. The
'before' expression specifies a pattern and the 'after' expression its
replacement.
package P
import ( "errors"; "fmt" )
func before(s string) error { return fmt.Errorf("%s", s) }
func after(s string) error { return errors.New(s) }
The expression statement form is useful when the expression has no
result, for example:
func before(msg string) { log.Fatalf("%s", msg) }
func after(msg string) { log.Fatal(msg) }
The parameters of both functions are wildcards that may match any
expression assignable to that type. If the pattern contains multiple
occurrences of the same parameter, each must match the same expression
in the input for the pattern to match. If the replacement contains
multiple occurrences of the same parameter, the expression will be
duplicated, possibly changing the side-effects.
The tool analyses all Go code in the packages specified by the
arguments, replacing all occurrences of the pattern with the
substitution.
So, the transform above would change this input:
err := fmt.Errorf("%s", "error: " + msg)
to this output:
err := errors.New("error: " + msg)
Identifiers, including qualified identifiers (p.X) are considered to
match only if they denote the same object. This allows correct
matching even in the presence of dot imports, named imports and
locally shadowed package names in the input program.
Matching of type syntax is semantic, not syntactic: type syntax in the
pattern matches type syntax in the input if the types are identical.
Thus, func(x int) matches func(y int).
This tool was inspired by other example-based refactoring tools,
'gofmt -r' for Go and Refaster for Java.
LIMITATIONS
===========
EXPRESSIVENESS
Only refactorings that replace one expression with another, regardless
of the expression's context, may be expressed. Refactoring arbitrary
statements (or sequences of statements) is a less well-defined problem
and is less amenable to this approach.
A pattern that contains a function literal (and hence statements)
never matches.
There is no way to generalize over related types, e.g. to express that
a wildcard may have any integer type, for example.
It is not possible to replace an expression by one of a different
type, even in contexts where this is legal, such as x in fmt.Print(x).
The struct literals T{x} and T{K: x} cannot both be matched by a single
template.
SAFETY
Verifying that a transformation does not introduce type errors is very
complex in the general case. An innocuous-looking replacement of one
constant by another (e.g. 1 to 2) may cause type errors relating to
array types and indices, for example. The tool performs only very
superficial checks of type preservation.
IMPORTS
Although the matching algorithm is fully aware of scoping rules, the
replacement algorithm is not, so the replacement code may contain
incorrect identifier syntax for imported objects if there are dot
imports, named imports or locally shadowed package names in the input
program.
Imports are added as needed, but they are not removed as needed.
Run 'goimports' on the modified file for now.
Dot imports are forbidden in the template.
TIPS
====
Sometimes a little creativity is required to implement the desired
migration. This section lists a few tips and tricks.
To remove the final parameter from a function, temporarily change the
function signature so that the final parameter is variadic, as this
allows legal calls both with and without the argument. Then use eg to
remove the final argument from all callers, and remove the variadic
parameter by hand. The reverse process can be used to add a final
parameter.
To add or remove parameters other than the final one, you must do it in
stages: (1) declare a variant function f' with a different name and the
desired parameters; (2) use eg to transform calls to f into calls to f',
changing the arguments as needed; (3) change the declaration of f to
match f'; (4) use eg to rename f' to f in all calls; (5) delete f'.
`
// TODO(adonovan): expand upon the above documentation as an HTML page.
// A Transformer represents a single example-based transformation.
type Transformer struct {
fset *token.FileSet
verbose bool
info *types.Info // combined type info for template/input/output ASTs
seenInfos map[*types.Info]bool
wildcards map[*types.Var]bool // set of parameters in func before()
env map[string]ast.Expr // maps parameter name to wildcard binding
importedObjs map[types.Object]*ast.SelectorExpr // objects imported by after().
before, after ast.Expr
afterStmts []ast.Stmt
allowWildcards bool
// Working state of Transform():
nsubsts int // number of substitutions made
currentPkg *types.Package // package of current call
}
// NewTransformer returns a transformer based on the specified template,
// a single-file package containing "before" and "after" functions as
// described in the package documentation.
// tmplInfo is the type information for tmplFile.
//
func NewTransformer(fset *token.FileSet, tmplPkg *types.Package, tmplFile *ast.File, tmplInfo *types.Info, verbose bool) (*Transformer, error) {
// Check the template.
beforeSig := funcSig(tmplPkg, "before")
if beforeSig == nil {
return nil, fmt.Errorf("no 'before' func found in template")
}
afterSig := funcSig(tmplPkg, "after")
if afterSig == nil {
return nil, fmt.Errorf("no 'after' func found in template")
}
// TODO(adonovan): should we also check the names of the params match?
if !types.Identical(afterSig, beforeSig) {
return nil, fmt.Errorf("before %s and after %s functions have different signatures",
beforeSig, afterSig)
}
for _, imp := range tmplFile.Imports {
if imp.Name != nil && imp.Name.Name == "." {
// Dot imports are currently forbidden. We
// make the simplifying assumption that all
// imports are regular, without local renames.
return nil, fmt.Errorf("dot-import (of %s) in template", imp.Path.Value)
}
}
var beforeDecl, afterDecl *ast.FuncDecl
for _, decl := range tmplFile.Decls {
if decl, ok := decl.(*ast.FuncDecl); ok {
switch decl.Name.Name {
case "before":
beforeDecl = decl
case "after":
afterDecl = decl
}
}
}
before, err := soleExpr(beforeDecl)
if err != nil {
return nil, fmt.Errorf("before: %s", err)
}
afterStmts, after, err := stmtAndExpr(afterDecl)
if err != nil {
return nil, fmt.Errorf("after: %s", err)
}
wildcards := make(map[*types.Var]bool)
for i := 0; i < beforeSig.Params().Len(); i++ {
wildcards[beforeSig.Params().At(i)] = true
}
// checkExprTypes returns an error if Tb (type of before()) is not
// safe to replace with Ta (type of after()).
//
// Only superficial checks are performed, and they may result in both
// false positives and negatives.
//
// Ideally, we would only require that the replacement be assignable
// to the context of a specific pattern occurrence, but the type
// checker doesn't record that information and it's complex to deduce.
// A Go type cannot capture all the constraints of a given expression
// context, which may include the size, constness, signedness,
// namedness or constructor of its type, and even the specific value
// of the replacement. (Consider the rule that array literal keys
// must be unique.) So we cannot hope to prove the safety of a
// transformation in general.
Tb := tmplInfo.TypeOf(before)
Ta := tmplInfo.TypeOf(after)
if types.AssignableTo(Tb, Ta) {
// safe: replacement is assignable to pattern.
} else if tuple, ok := Tb.(*types.Tuple); ok && tuple.Len() == 0 {
// safe: pattern has void type (must appear in an ExprStmt).
} else {
return nil, fmt.Errorf("%s is not a safe replacement for %s", Ta, Tb)
}
tr := &Transformer{
fset: fset,
verbose: verbose,
wildcards: wildcards,
allowWildcards: true,
seenInfos: make(map[*types.Info]bool),
importedObjs: make(map[types.Object]*ast.SelectorExpr),
before: before,
after: after,
afterStmts: afterStmts,
}
// Combine type info from the template and input packages, and
// type info for the synthesized ASTs too. This saves us
// having to book-keep where each ast.Node originated as we
// construct the resulting hybrid AST.
tr.info = &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
Defs: make(map[*ast.Ident]types.Object),
Uses: make(map[*ast.Ident]types.Object),
Selections: make(map[*ast.SelectorExpr]*types.Selection),
}
mergeTypeInfo(tr.info, tmplInfo)
// Compute set of imported objects required by after().
// TODO(adonovan): reject dot-imports in pattern
ast.Inspect(after, func(n ast.Node) bool {
if n, ok := n.(*ast.SelectorExpr); ok {
if _, ok := tr.info.Selections[n]; !ok {
// qualified ident
obj := tr.info.Uses[n.Sel]
tr.importedObjs[obj] = n
return false // prune
}
}
return true // recur
})
return tr, nil
}
// WriteAST is a convenience function that writes AST f to the specified file.
func WriteAST(fset *token.FileSet, filename string, f *ast.File) (err error) {
fh, err := os.Create(filename)
if err != nil {
return err
}
defer func() {
if err2 := fh.Close(); err != nil {
err = err2 // prefer earlier error
}
}()
return format.Node(fh, fset, f)
}
// -- utilities --------------------------------------------------------
// funcSig returns the signature of the specified package-level function.
func funcSig(pkg *types.Package, name string) *types.Signature {
if f, ok := pkg.Scope().Lookup(name).(*types.Func); ok {
return f.Type().(*types.Signature)
}
return nil
}
// soleExpr returns the sole expression in the before/after template function.
func soleExpr(fn *ast.FuncDecl) (ast.Expr, error) {
if fn.Body == nil {
return nil, fmt.Errorf("no body")
}
if len(fn.Body.List) != 1 {
return nil, fmt.Errorf("must contain a single statement")
}
switch stmt := fn.Body.List[0].(type) {
case *ast.ReturnStmt:
if len(stmt.Results) != 1 {
return nil, fmt.Errorf("return statement must have a single operand")
}
return stmt.Results[0], nil
case *ast.ExprStmt:
return stmt.X, nil
}
return nil, fmt.Errorf("must contain a single return or expression statement")
}
// stmtAndExpr returns the expression in the last return statement as well as the preceeding lines.
func stmtAndExpr(fn *ast.FuncDecl) ([]ast.Stmt, ast.Expr, error) {
if fn.Body == nil {
return nil, nil, fmt.Errorf("no body")
}
n := len(fn.Body.List)
if n == 0 {
return nil, nil, fmt.Errorf("must contain at least one statement")
}
stmts, last := fn.Body.List[:n-1], fn.Body.List[n-1]
switch last := last.(type) {
case *ast.ReturnStmt:
if len(last.Results) != 1 {
return nil, nil, fmt.Errorf("return statement must have a single operand")
}
return stmts, last.Results[0], nil
case *ast.ExprStmt:
return stmts, last.X, nil
}
return nil, nil, fmt.Errorf("must end with a single return or expression statement")
}
// mergeTypeInfo adds type info from src to dst.
func mergeTypeInfo(dst, src *types.Info) {
for k, v := range src.Types {
dst.Types[k] = v
}
for k, v := range src.Defs {
dst.Defs[k] = v
}
for k, v := range src.Uses {
dst.Uses[k] = v
}
for k, v := range src.Selections {
dst.Selections[k] = v
}
}
// (debugging only)
func astString(fset *token.FileSet, n ast.Node) string {
var buf bytes.Buffer
printer.Fprint(&buf, fset, n)
return buf.String()
}

166
vendor/golang.org/x/tools/refactor/eg/eg_test.go generated vendored Normal file
View File

@@ -0,0 +1,166 @@
// Copyright 2014 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.
// No testdata on Android.
// +build !android
package eg_test
import (
"bytes"
"flag"
exact "go/constant"
"go/parser"
"go/token"
"go/types"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/refactor/eg"
)
// TODO(adonovan): more tests:
// - of command-line tool
// - of all parts of syntax
// - of applying a template to a package it imports:
// the replacement syntax should use unqualified names for its objects.
var (
updateFlag = flag.Bool("update", false, "update the golden files")
verboseFlag = flag.Bool("verbose", false, "show matcher information")
)
func Test(t *testing.T) {
switch runtime.GOOS {
case "windows":
t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
}
conf := loader.Config{
Fset: token.NewFileSet(),
ParserMode: parser.ParseComments,
}
// Each entry is a single-file package.
// (Multi-file packages aren't interesting for this test.)
// Order matters: each non-template package is processed using
// the preceding template package.
for _, filename := range []string{
"testdata/A.template",
"testdata/A1.go",
"testdata/A2.go",
"testdata/B.template",
"testdata/B1.go",
"testdata/C.template",
"testdata/C1.go",
"testdata/D.template",
"testdata/D1.go",
"testdata/E.template",
"testdata/E1.go",
"testdata/F.template",
"testdata/F1.go",
"testdata/G.template",
"testdata/G1.go",
"testdata/H.template",
"testdata/H1.go",
"testdata/I.template",
"testdata/I1.go",
"testdata/J.template",
"testdata/J1.go",
"testdata/bad_type.template",
"testdata/no_before.template",
"testdata/no_after_return.template",
"testdata/type_mismatch.template",
"testdata/expr_type_mismatch.template",
} {
pkgname := strings.TrimSuffix(filepath.Base(filename), ".go")
conf.CreateFromFilenames(pkgname, filename)
}
iprog, err := conf.Load()
if err != nil {
t.Fatal(err)
}
var xform *eg.Transformer
for _, info := range iprog.Created {
file := info.Files[0]
filename := iprog.Fset.File(file.Pos()).Name() // foo.go
if strings.HasSuffix(filename, "template") {
// a new template
shouldFail, _ := info.Pkg.Scope().Lookup("shouldFail").(*types.Const)
xform, err = eg.NewTransformer(iprog.Fset, info.Pkg, file, &info.Info, *verboseFlag)
if err != nil {
if shouldFail == nil {
t.Errorf("NewTransformer(%s): %s", filename, err)
} else if want := exact.StringVal(shouldFail.Val()); !strings.Contains(err.Error(), want) {
t.Errorf("NewTransformer(%s): got error %q, want error %q", filename, err, want)
}
} else if shouldFail != nil {
t.Errorf("NewTransformer(%s) succeeded unexpectedly; want error %q",
filename, shouldFail.Val())
}
continue
}
if xform == nil {
t.Errorf("%s: no previous template", filename)
continue
}
// apply previous template to this package
n := xform.Transform(&info.Info, info.Pkg, file)
if n == 0 {
t.Errorf("%s: no matches", filename)
continue
}
got := filename + "t" // foo.got
golden := filename + "lden" // foo.golden
// Write actual output to foo.got.
if err := eg.WriteAST(iprog.Fset, got, file); err != nil {
t.Error(err)
}
defer os.Remove(got)
// Compare foo.got with foo.golden.
var cmd *exec.Cmd
switch runtime.GOOS {
case "plan9":
cmd = exec.Command("/bin/diff", "-c", golden, got)
default:
cmd = exec.Command("/usr/bin/diff", "-u", golden, got)
}
buf := new(bytes.Buffer)
cmd.Stdout = buf
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
t.Errorf("eg tests for %s failed: %s.\n%s\n", filename, err, buf)
if *updateFlag {
t.Logf("Updating %s...", golden)
if err := exec.Command("/bin/cp", got, golden).Run(); err != nil {
t.Errorf("Update failed: %s", err)
}
}
}
}
}

249
vendor/golang.org/x/tools/refactor/eg/match.go generated vendored Normal file
View File

@@ -0,0 +1,249 @@
// Copyright 2014 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 eg
import (
"fmt"
"go/ast"
exact "go/constant"
"go/token"
"go/types"
"log"
"os"
"reflect"
"golang.org/x/tools/go/ast/astutil"
)
// matchExpr reports whether pattern x matches y.
//
// If tr.allowWildcards, Idents in x that refer to parameters are
// treated as wildcards, and match any y that is assignable to the
// parameter type; matchExpr records this correspondence in tr.env.
// Otherwise, matchExpr simply reports whether the two trees are
// equivalent.
//
// A wildcard appearing more than once in the pattern must
// consistently match the same tree.
//
func (tr *Transformer) matchExpr(x, y ast.Expr) bool {
if x == nil && y == nil {
return true
}
if x == nil || y == nil {
return false
}
x = unparen(x)
y = unparen(y)
// Is x a wildcard? (a reference to a 'before' parameter)
if xobj, ok := tr.wildcardObj(x); ok {
return tr.matchWildcard(xobj, y)
}
// Object identifiers (including pkg-qualified ones)
// are handled semantically, not syntactically.
xobj := isRef(x, tr.info)
yobj := isRef(y, tr.info)
if xobj != nil {
return xobj == yobj
}
if yobj != nil {
return false
}
// TODO(adonovan): audit: we cannot assume these ast.Exprs
// contain non-nil pointers. e.g. ImportSpec.Name may be a
// nil *ast.Ident.
if reflect.TypeOf(x) != reflect.TypeOf(y) {
return false
}
switch x := x.(type) {
case *ast.Ident:
log.Fatalf("unexpected Ident: %s", astString(tr.fset, x))
case *ast.BasicLit:
y := y.(*ast.BasicLit)
xval := exact.MakeFromLiteral(x.Value, x.Kind, 0)
yval := exact.MakeFromLiteral(y.Value, y.Kind, 0)
return exact.Compare(xval, token.EQL, yval)
case *ast.FuncLit:
// func literals (and thus statement syntax) never match.
return false
case *ast.CompositeLit:
y := y.(*ast.CompositeLit)
return (x.Type == nil) == (y.Type == nil) &&
(x.Type == nil || tr.matchType(x.Type, y.Type)) &&
tr.matchExprs(x.Elts, y.Elts)
case *ast.SelectorExpr:
y := y.(*ast.SelectorExpr)
return tr.matchSelectorExpr(x, y) &&
tr.info.Selections[x].Obj() == tr.info.Selections[y].Obj()
case *ast.IndexExpr:
y := y.(*ast.IndexExpr)
return tr.matchExpr(x.X, y.X) &&
tr.matchExpr(x.Index, y.Index)
case *ast.SliceExpr:
y := y.(*ast.SliceExpr)
return tr.matchExpr(x.X, y.X) &&
tr.matchExpr(x.Low, y.Low) &&
tr.matchExpr(x.High, y.High) &&
tr.matchExpr(x.Max, y.Max) &&
x.Slice3 == y.Slice3
case *ast.TypeAssertExpr:
y := y.(*ast.TypeAssertExpr)
return tr.matchExpr(x.X, y.X) &&
tr.matchType(x.Type, y.Type)
case *ast.CallExpr:
y := y.(*ast.CallExpr)
match := tr.matchExpr // function call
if tr.info.Types[x.Fun].IsType() {
match = tr.matchType // type conversion
}
return x.Ellipsis.IsValid() == y.Ellipsis.IsValid() &&
match(x.Fun, y.Fun) &&
tr.matchExprs(x.Args, y.Args)
case *ast.StarExpr:
y := y.(*ast.StarExpr)
return tr.matchExpr(x.X, y.X)
case *ast.UnaryExpr:
y := y.(*ast.UnaryExpr)
return x.Op == y.Op &&
tr.matchExpr(x.X, y.X)
case *ast.BinaryExpr:
y := y.(*ast.BinaryExpr)
return x.Op == y.Op &&
tr.matchExpr(x.X, y.X) &&
tr.matchExpr(x.Y, y.Y)
case *ast.KeyValueExpr:
y := y.(*ast.KeyValueExpr)
return tr.matchExpr(x.Key, y.Key) &&
tr.matchExpr(x.Value, y.Value)
}
panic(fmt.Sprintf("unhandled AST node type: %T", x))
}
func (tr *Transformer) matchExprs(xx, yy []ast.Expr) bool {
if len(xx) != len(yy) {
return false
}
for i := range xx {
if !tr.matchExpr(xx[i], yy[i]) {
return false
}
}
return true
}
// matchType reports whether the two type ASTs denote identical types.
func (tr *Transformer) matchType(x, y ast.Expr) bool {
tx := tr.info.Types[x].Type
ty := tr.info.Types[y].Type
return types.Identical(tx, ty)
}
func (tr *Transformer) wildcardObj(x ast.Expr) (*types.Var, bool) {
if x, ok := x.(*ast.Ident); ok && x != nil && tr.allowWildcards {
if xobj, ok := tr.info.Uses[x].(*types.Var); ok && tr.wildcards[xobj] {
return xobj, true
}
}
return nil, false
}
func (tr *Transformer) matchSelectorExpr(x, y *ast.SelectorExpr) bool {
if xobj, ok := tr.wildcardObj(x.X); ok {
field := x.Sel.Name
yt := tr.info.TypeOf(y.X)
o, _, _ := types.LookupFieldOrMethod(yt, true, tr.currentPkg, field)
if o != nil {
tr.env[xobj.Name()] = y.X // record binding
return true
}
}
return tr.matchExpr(x.X, y.X)
}
func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool {
name := xobj.Name()
if tr.verbose {
fmt.Fprintf(os.Stderr, "%s: wildcard %s -> %s?: ",
tr.fset.Position(y.Pos()), name, astString(tr.fset, y))
}
// Check that y is assignable to the declared type of the param.
yt := tr.info.TypeOf(y)
if yt == nil {
// y has no type.
// Perhaps it is an *ast.Ellipsis in [...]T{}, or
// an *ast.KeyValueExpr in T{k: v}.
// Clearly these pseudo-expressions cannot match a
// wildcard, but it would nice if we had a way to ignore
// the difference between T{v} and T{k:v} for structs.
return false
}
if !types.AssignableTo(yt, xobj.Type()) {
if tr.verbose {
fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type())
}
return false
}
// A wildcard matches any expression.
// If it appears multiple times in the pattern, it must match
// the same expression each time.
if old, ok := tr.env[name]; ok {
// found existing binding
tr.allowWildcards = false
r := tr.matchExpr(old, y)
if tr.verbose {
fmt.Fprintf(os.Stderr, "%t secondary match, primary was %s\n",
r, astString(tr.fset, old))
}
tr.allowWildcards = true
return r
}
if tr.verbose {
fmt.Fprintf(os.Stderr, "primary match\n")
}
tr.env[name] = y // record binding
return true
}
// -- utilities --------------------------------------------------------
func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
// isRef returns the object referred to by this (possibly qualified)
// identifier, or nil if the node is not a referring identifier.
func isRef(n ast.Node, info *types.Info) types.Object {
switch n := n.(type) {
case *ast.Ident:
return info.Uses[n]
case *ast.SelectorExpr:
if _, ok := info.Selections[n]; !ok {
// qualified ident
return info.Uses[n.Sel]
}
}
return nil
}

401
vendor/golang.org/x/tools/refactor/eg/rewrite.go generated vendored Normal file
View File

@@ -0,0 +1,401 @@
// Copyright 2014 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 eg
// This file defines the AST rewriting pass.
// Most of it was plundered directly from
// $GOROOT/src/cmd/gofmt/rewrite.go (after convergent evolution).
import (
"fmt"
"go/ast"
"go/token"
"go/types"
"os"
"reflect"
"sort"
"strconv"
"strings"
"golang.org/x/tools/go/ast/astutil"
)
// transformItem takes a reflect.Value representing a variable of type ast.Node
// transforms its child elements recursively with apply, and then transforms the
// actual element if it contains an expression.
func (tr *Transformer) transformItem(rv reflect.Value) (reflect.Value, bool, map[string]ast.Expr) {
// don't bother if val is invalid to start with
if !rv.IsValid() {
return reflect.Value{}, false, nil
}
rv, changed, newEnv := tr.apply(tr.transformItem, rv)
e := rvToExpr(rv)
if e == nil {
return rv, changed, newEnv
}
savedEnv := tr.env
tr.env = make(map[string]ast.Expr) // inefficient! Use a slice of k/v pairs
if tr.matchExpr(tr.before, e) {
if tr.verbose {
fmt.Fprintf(os.Stderr, "%s matches %s",
astString(tr.fset, tr.before), astString(tr.fset, e))
if len(tr.env) > 0 {
fmt.Fprintf(os.Stderr, " with:")
for name, ast := range tr.env {
fmt.Fprintf(os.Stderr, " %s->%s",
name, astString(tr.fset, ast))
}
}
fmt.Fprintf(os.Stderr, "\n")
}
tr.nsubsts++
// Clone the replacement tree, performing parameter substitution.
// We update all positions to n.Pos() to aid comment placement.
rv = tr.subst(tr.env, reflect.ValueOf(tr.after),
reflect.ValueOf(e.Pos()))
changed = true
newEnv = tr.env
}
tr.env = savedEnv
return rv, changed, newEnv
}
// Transform applies the transformation to the specified parsed file,
// whose type information is supplied in info, and returns the number
// of replacements that were made.
//
// It mutates the AST in place (the identity of the root node is
// unchanged), and may add nodes for which no type information is
// available in info.
//
// Derived from rewriteFile in $GOROOT/src/cmd/gofmt/rewrite.go.
//
func (tr *Transformer) Transform(info *types.Info, pkg *types.Package, file *ast.File) int {
if !tr.seenInfos[info] {
tr.seenInfos[info] = true
mergeTypeInfo(tr.info, info)
}
tr.currentPkg = pkg
tr.nsubsts = 0
if tr.verbose {
fmt.Fprintf(os.Stderr, "before: %s\n", astString(tr.fset, tr.before))
fmt.Fprintf(os.Stderr, "after: %s\n", astString(tr.fset, tr.after))
fmt.Fprintf(os.Stderr, "afterStmts: %s\n", tr.afterStmts)
}
o, changed, _ := tr.apply(tr.transformItem, reflect.ValueOf(file))
if changed {
panic("BUG")
}
file2 := o.Interface().(*ast.File)
// By construction, the root node is unchanged.
if file != file2 {
panic("BUG")
}
// Add any necessary imports.
// TODO(adonovan): remove no-longer needed imports too.
if tr.nsubsts > 0 {
pkgs := make(map[string]*types.Package)
for obj := range tr.importedObjs {
pkgs[obj.Pkg().Path()] = obj.Pkg()
}
for _, imp := range file.Imports {
path, _ := strconv.Unquote(imp.Path.Value)
delete(pkgs, path)
}
delete(pkgs, pkg.Path()) // don't import self
// NB: AddImport may completely replace the AST!
// It thus renders info and tr.info no longer relevant to file.
var paths []string
for path := range pkgs {
paths = append(paths, path)
}
sort.Strings(paths)
for _, path := range paths {
astutil.AddImport(tr.fset, file, path)
}
}
tr.currentPkg = nil
return tr.nsubsts
}
// setValue is a wrapper for x.SetValue(y); it protects
// the caller from panics if x cannot be changed to y.
func setValue(x, y reflect.Value) {
// don't bother if y is invalid to start with
if !y.IsValid() {
return
}
defer func() {
if x := recover(); x != nil {
if s, ok := x.(string); ok &&
(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
// x cannot be set to y - ignore this rewrite
return
}
panic(x)
}
}()
x.Set(y)
}
// Values/types for special cases.
var (
objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
scopePtrNil = reflect.ValueOf((*ast.Scope)(nil))
identType = reflect.TypeOf((*ast.Ident)(nil))
selectorExprType = reflect.TypeOf((*ast.SelectorExpr)(nil))
objectPtrType = reflect.TypeOf((*ast.Object)(nil))
statementType = reflect.TypeOf((*ast.Stmt)(nil)).Elem()
positionType = reflect.TypeOf(token.NoPos)
scopePtrType = reflect.TypeOf((*ast.Scope)(nil))
)
// apply replaces each AST field x in val with f(x), returning val.
// To avoid extra conversions, f operates on the reflect.Value form.
// f takes a reflect.Value representing the variable to modify of type ast.Node.
// It returns a reflect.Value containing the transformed value of type ast.Node,
// whether any change was made, and a map of identifiers to ast.Expr (so we can
// do contextually correct substitutions in the parent statements).
func (tr *Transformer) apply(f func(reflect.Value) (reflect.Value, bool, map[string]ast.Expr), val reflect.Value) (reflect.Value, bool, map[string]ast.Expr) {
if !val.IsValid() {
return reflect.Value{}, false, nil
}
// *ast.Objects introduce cycles and are likely incorrect after
// rewrite; don't follow them but replace with nil instead
if val.Type() == objectPtrType {
return objectPtrNil, false, nil
}
// similarly for scopes: they are likely incorrect after a rewrite;
// replace them with nil
if val.Type() == scopePtrType {
return scopePtrNil, false, nil
}
switch v := reflect.Indirect(val); v.Kind() {
case reflect.Slice:
// no possible rewriting of statements.
if v.Type().Elem() != statementType {
changed := false
var envp map[string]ast.Expr
for i := 0; i < v.Len(); i++ {
e := v.Index(i)
o, localchanged, env := f(e)
if localchanged {
changed = true
// we clobber envp here,
// which means if we have two sucessive
// replacements inside the same statement
// we will only generate the setup for one of them.
envp = env
}
setValue(e, o)
}
return val, changed, envp
}
// statements are rewritten.
var out []ast.Stmt
for i := 0; i < v.Len(); i++ {
e := v.Index(i)
o, changed, env := f(e)
if changed {
for _, s := range tr.afterStmts {
t := tr.subst(env, reflect.ValueOf(s), reflect.Value{}).Interface()
out = append(out, t.(ast.Stmt))
}
}
setValue(e, o)
out = append(out, e.Interface().(ast.Stmt))
}
return reflect.ValueOf(out), false, nil
case reflect.Struct:
changed := false
var envp map[string]ast.Expr
for i := 0; i < v.NumField(); i++ {
e := v.Field(i)
o, localchanged, env := f(e)
if localchanged {
changed = true
envp = env
}
setValue(e, o)
}
return val, changed, envp
case reflect.Interface:
e := v.Elem()
o, changed, env := f(e)
setValue(v, o)
return val, changed, env
}
return val, false, nil
}
// subst returns a copy of (replacement) pattern with values from env
// substituted in place of wildcards and pos used as the position of
// tokens from the pattern. if env == nil, subst returns a copy of
// pattern and doesn't change the line number information.
func (tr *Transformer) subst(env map[string]ast.Expr, pattern, pos reflect.Value) reflect.Value {
if !pattern.IsValid() {
return reflect.Value{}
}
// *ast.Objects introduce cycles and are likely incorrect after
// rewrite; don't follow them but replace with nil instead
if pattern.Type() == objectPtrType {
return objectPtrNil
}
// similarly for scopes: they are likely incorrect after a rewrite;
// replace them with nil
if pattern.Type() == scopePtrType {
return scopePtrNil
}
// Wildcard gets replaced with map value.
if env != nil && pattern.Type() == identType {
id := pattern.Interface().(*ast.Ident)
if old, ok := env[id.Name]; ok {
return tr.subst(nil, reflect.ValueOf(old), reflect.Value{})
}
}
// Emit qualified identifiers in the pattern by appropriate
// (possibly qualified) identifier in the input.
//
// The template cannot contain dot imports, so all identifiers
// for imported objects are explicitly qualified.
//
// We assume (unsoundly) that there are no dot or named
// imports in the input code, nor are any imported package
// names shadowed, so the usual normal qualified identifier
// syntax may be used.
// TODO(adonovan): fix: avoid this assumption.
//
// A refactoring may be applied to a package referenced by the
// template. Objects belonging to the current package are
// denoted by unqualified identifiers.
//
if tr.importedObjs != nil && pattern.Type() == selectorExprType {
obj := isRef(pattern.Interface().(*ast.SelectorExpr), tr.info)
if obj != nil {
if sel, ok := tr.importedObjs[obj]; ok {
var id ast.Expr
if obj.Pkg() == tr.currentPkg {
id = sel.Sel // unqualified
} else {
id = sel // pkg-qualified
}
// Return a clone of id.
saved := tr.importedObjs
tr.importedObjs = nil // break cycle
r := tr.subst(nil, reflect.ValueOf(id), pos)
tr.importedObjs = saved
return r
}
}
}
if pos.IsValid() && pattern.Type() == positionType {
// use new position only if old position was valid in the first place
if old := pattern.Interface().(token.Pos); !old.IsValid() {
return pattern
}
return pos
}
// Otherwise copy.
switch p := pattern; p.Kind() {
case reflect.Slice:
v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
for i := 0; i < p.Len(); i++ {
v.Index(i).Set(tr.subst(env, p.Index(i), pos))
}
return v
case reflect.Struct:
v := reflect.New(p.Type()).Elem()
for i := 0; i < p.NumField(); i++ {
v.Field(i).Set(tr.subst(env, p.Field(i), pos))
}
return v
case reflect.Ptr:
v := reflect.New(p.Type()).Elem()
if elem := p.Elem(); elem.IsValid() {
v.Set(tr.subst(env, elem, pos).Addr())
}
// Duplicate type information for duplicated ast.Expr.
// All ast.Node implementations are *structs,
// so this case catches them all.
if e := rvToExpr(v); e != nil {
updateTypeInfo(tr.info, e, p.Interface().(ast.Expr))
}
return v
case reflect.Interface:
v := reflect.New(p.Type()).Elem()
if elem := p.Elem(); elem.IsValid() {
v.Set(tr.subst(env, elem, pos))
}
return v
}
return pattern
}
// -- utilities -------------------------------------------------------
func rvToExpr(rv reflect.Value) ast.Expr {
if rv.CanInterface() {
if e, ok := rv.Interface().(ast.Expr); ok {
return e
}
}
return nil
}
// updateTypeInfo duplicates type information for the existing AST old
// so that it also applies to duplicated AST new.
func updateTypeInfo(info *types.Info, new, old ast.Expr) {
switch new := new.(type) {
case *ast.Ident:
orig := old.(*ast.Ident)
if obj, ok := info.Defs[orig]; ok {
info.Defs[new] = obj
}
if obj, ok := info.Uses[orig]; ok {
info.Uses[new] = obj
}
case *ast.SelectorExpr:
orig := old.(*ast.SelectorExpr)
if sel, ok := info.Selections[orig]; ok {
info.Selections[new] = sel
}
}
if tv, ok := info.Types[old]; ok {
info.Types[new] = tv
}
}

View File

@@ -0,0 +1,13 @@
// +build ignore
package template
// Basic test of type-aware expression refactoring.
import (
"errors"
"fmt"
)
func before(s string) error { return fmt.Errorf("%s", s) }
func after(s string) error { return errors.New(s) }

51
vendor/golang.org/x/tools/refactor/eg/testdata/A1.go generated vendored Normal file
View File

@@ -0,0 +1,51 @@
// +build ignore
package A1
import (
. "fmt"
myfmt "fmt"
"os"
"strings"
)
func example(n int) {
x := "foo" + strings.Repeat("\t", n)
// Match, despite named import.
myfmt.Errorf("%s", x)
// Match, despite dot import.
Errorf("%s", x)
// Match: multiple matches in same function are possible.
myfmt.Errorf("%s", x)
// No match: wildcarded operand has the wrong type.
myfmt.Errorf("%s", 3)
// No match: function operand doesn't match.
myfmt.Printf("%s", x)
// No match again, dot import.
Printf("%s", x)
// Match.
myfmt.Fprint(os.Stderr, myfmt.Errorf("%s", x+"foo"))
// No match: though this literally matches the template,
// fmt doesn't resolve to a package here.
var fmt struct{ Errorf func(string, string) }
fmt.Errorf("%s", x)
// Recursive matching:
// Match: both matches are well-typed, so both succeed.
myfmt.Errorf("%s", myfmt.Errorf("%s", x+"foo").Error())
// Outer match succeeds, inner doesn't: 3 has wrong type.
myfmt.Errorf("%s", myfmt.Errorf("%s", 3).Error())
// Inner match succeeds, outer doesn't: the inner replacement
// has the wrong type (error not string).
myfmt.Errorf("%s", myfmt.Errorf("%s", x+"foo"))
}

View File

@@ -0,0 +1,52 @@
// +build ignore
package A1
import (
"errors"
. "fmt"
myfmt "fmt"
"os"
"strings"
)
func example(n int) {
x := "foo" + strings.Repeat("\t", n)
// Match, despite named import.
errors.New(x)
// Match, despite dot import.
errors.New(x)
// Match: multiple matches in same function are possible.
errors.New(x)
// No match: wildcarded operand has the wrong type.
myfmt.Errorf("%s", 3)
// No match: function operand doesn't match.
myfmt.Printf("%s", x)
// No match again, dot import.
Printf("%s", x)
// Match.
myfmt.Fprint(os.Stderr, errors.New(x+"foo"))
// No match: though this literally matches the template,
// fmt doesn't resolve to a package here.
var fmt struct{ Errorf func(string, string) }
fmt.Errorf("%s", x)
// Recursive matching:
// Match: both matches are well-typed, so both succeed.
errors.New(errors.New(x + "foo").Error())
// Outer match succeeds, inner doesn't: 3 has wrong type.
errors.New(myfmt.Errorf("%s", 3).Error())
// Inner match succeeds, outer doesn't: the inner replacement
// has the wrong type (error not string).
myfmt.Errorf("%s", errors.New(x+"foo"))
}

12
vendor/golang.org/x/tools/refactor/eg/testdata/A2.go generated vendored Normal file
View File

@@ -0,0 +1,12 @@
// +build ignore
package A2
// This refactoring causes addition of "errors" import.
// TODO(adonovan): fix: it should also remove "fmt".
import myfmt "fmt"
func example(n int) {
myfmt.Errorf("%s", "")
}

View File

@@ -0,0 +1,15 @@
// +build ignore
package A2
// This refactoring causes addition of "errors" import.
// TODO(adonovan): fix: it should also remove "fmt".
import (
"errors"
myfmt "fmt"
)
func example(n int) {
errors.New("")
}

View File

@@ -0,0 +1,9 @@
package template
// Basic test of expression refactoring.
// (Types are not important in this case; it could be done with gofmt -r.)
import "time"
func before(t time.Time) time.Duration { return time.Now().Sub(t) }
func after(t time.Time) time.Duration { return time.Since(t) }

17
vendor/golang.org/x/tools/refactor/eg/testdata/B1.go generated vendored Normal file
View File

@@ -0,0 +1,17 @@
// +build ignore
package B1
import "time"
var startup = time.Now()
func example() time.Duration {
before := time.Now()
time.Sleep(1)
return time.Now().Sub(before)
}
func msSinceStartup() int64 {
return int64(time.Now().Sub(startup) / time.Millisecond)
}

View File

@@ -0,0 +1,17 @@
// +build ignore
package B1
import "time"
var startup = time.Now()
func example() time.Duration {
before := time.Now()
time.Sleep(1)
return time.Since(before)
}
func msSinceStartup() int64 {
return int64(time.Since(startup) / time.Millisecond)
}

View File

@@ -0,0 +1,10 @@
package template
// Test of repeated use of wildcard in pattern.
// NB: multiple patterns would be required to handle variants such as
// s[:len(s)], s[x:len(s)], etc, since a wildcard can't match nothing at all.
// TODO(adonovan): support multiple templates in a single pass.
func before(s string) string { return s[:len(s)] }
func after(s string) string { return s }

22
vendor/golang.org/x/tools/refactor/eg/testdata/C1.go generated vendored Normal file
View File

@@ -0,0 +1,22 @@
// +build ignore
package C1
import "strings"
func example() {
x := "foo"
println(x[:len(x)])
// Match, but the transformation is not sound w.r.t. possible side effects.
println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 3))])
// No match, since second use of wildcard doesn't match first.
println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 2))])
// Recursive match demonstrating bottom-up rewrite:
// only after the inner replacement occurs does the outer syntax match.
println((x[:len(x)])[:len(x[:len(x)])])
// -> (x[:len(x)])
// -> x
}

View File

@@ -0,0 +1,22 @@
// +build ignore
package C1
import "strings"
func example() {
x := "foo"
println(x)
// Match, but the transformation is not sound w.r.t. possible side effects.
println(strings.Repeat("*", 3))
// No match, since second use of wildcard doesn't match first.
println(strings.Repeat("*", 3)[:len(strings.Repeat("*", 2))])
// Recursive match demonstrating bottom-up rewrite:
// only after the inner replacement occurs does the outer syntax match.
println(x)
// -> (x[:len(x)])
// -> x
}

View File

@@ -0,0 +1,8 @@
package template
import "fmt"
// Test of semantic (not syntactic) matching of basic literals.
func before() (int, error) { return fmt.Println(123, "a") }
func after() (int, error) { return fmt.Println(456, "!") }

12
vendor/golang.org/x/tools/refactor/eg/testdata/D1.go generated vendored Normal file
View File

@@ -0,0 +1,12 @@
// +build ignore
package D1
import "fmt"
func example() {
fmt.Println(123, "a") // match
fmt.Println(0x7b, `a`) // match
fmt.Println(0173, "\x61") // match
fmt.Println(100+20+3, "a"+"") // no match: constant expressions, but not basic literals
}

View File

@@ -0,0 +1,12 @@
// +build ignore
package D1
import "fmt"
func example() {
fmt.Println(456, "!") // match
fmt.Println(456, "!") // match
fmt.Println(456, "!") // match
fmt.Println(100+20+3, "a"+"") // no match: constant expressions, but not basic literals
}

View File

@@ -0,0 +1,12 @@
package template
import (
"fmt"
"log"
"os"
)
// Replace call to void function by call to non-void function.
func before(x interface{}) { log.Fatal(x) }
func after(x interface{}) { fmt.Fprintf(os.Stderr, "warning: %v", x) }

9
vendor/golang.org/x/tools/refactor/eg/testdata/E1.go generated vendored Normal file
View File

@@ -0,0 +1,9 @@
// +build ignore
package E1
import "log"
func example() {
log.Fatal("oops") // match
}

View File

@@ -0,0 +1,13 @@
// +build ignore
package E1
import (
"fmt"
"log"
"os"
)
func example() {
fmt.Fprintf(os.Stderr, "warning: %v", "oops") // match
}

View File

@@ -0,0 +1,8 @@
package templates
// Test
import "sync"
func before(s sync.RWMutex) { s.Lock() }
func after(s sync.RWMutex) { s.RLock() }

48
vendor/golang.org/x/tools/refactor/eg/testdata/F1.go generated vendored Normal file
View File

@@ -0,0 +1,48 @@
// +build ignore
package F1
import "sync"
func example(n int) {
var x struct {
mutex sync.RWMutex
}
var y struct {
sync.RWMutex
}
type l struct {
sync.RWMutex
}
var z struct {
l
}
var a struct {
*l
}
var b struct{ Lock func() }
// Match
x.mutex.Lock()
// Match
y.Lock()
// Match indirect
z.Lock()
// Should be no match however currently matches due to:
// https://golang.org/issue/8584
// Will start failing when this is fixed then just change golden to
// No match pointer indirect
// a.Lock()
a.Lock()
// No match
b.Lock()
}

View File

@@ -0,0 +1,48 @@
// +build ignore
package F1
import "sync"
func example(n int) {
var x struct {
mutex sync.RWMutex
}
var y struct {
sync.RWMutex
}
type l struct {
sync.RWMutex
}
var z struct {
l
}
var a struct {
*l
}
var b struct{ Lock func() }
// Match
x.mutex.RLock()
// Match
y.RLock()
// Match indirect
z.RLock()
// Should be no match however currently matches due to:
// https://golang.org/issue/8584
// Will start failing when this is fixed then just change golden to
// No match pointer indirect
// a.Lock()
a.RLock()
// No match
b.Lock()
}

View File

@@ -0,0 +1,10 @@
package templates
import (
"go/ast" // defines many unencapsulated structs
"go/token"
)
func before(from, to token.Pos) ast.BadExpr { return ast.BadExpr{From: from, To: to} }
func after(from, to token.Pos) ast.BadExpr { return ast.BadExpr{from, to} }

12
vendor/golang.org/x/tools/refactor/eg/testdata/G1.go generated vendored Normal file
View File

@@ -0,0 +1,12 @@
// +build ignore
package G1
import "go/ast"
func example() {
_ = ast.BadExpr{From: 123, To: 456} // match
_ = ast.BadExpr{123, 456} // no match
_ = ast.BadExpr{From: 123} // no match
_ = ast.BadExpr{To: 456} // no match
}

View File

@@ -0,0 +1,12 @@
// +build ignore
package G1
import "go/ast"
func example() {
_ = ast.BadExpr{123, 456} // match
_ = ast.BadExpr{123, 456} // no match
_ = ast.BadExpr{From: 123} // no match
_ = ast.BadExpr{To: 456} // no match
}

View File

@@ -0,0 +1,9 @@
package templates
import (
"go/ast" // defines many unencapsulated structs
"go/token"
)
func before(from, to token.Pos) ast.BadExpr { return ast.BadExpr{from, to} }
func after(from, to token.Pos) ast.BadExpr { return ast.BadExpr{From: from, To: to} }

12
vendor/golang.org/x/tools/refactor/eg/testdata/H1.go generated vendored Normal file
View File

@@ -0,0 +1,12 @@
// +build ignore
package H1
import "go/ast"
func example() {
_ = ast.BadExpr{From: 123, To: 456} // no match
_ = ast.BadExpr{123, 456} // match
_ = ast.BadExpr{From: 123} // no match
_ = ast.BadExpr{To: 456} // no match
}

View File

@@ -0,0 +1,12 @@
// +build ignore
package H1
import "go/ast"
func example() {
_ = ast.BadExpr{From: 123, To: 456} // no match
_ = ast.BadExpr{From: 123, To: 456} // match
_ = ast.BadExpr{From: 123} // no match
_ = ast.BadExpr{To: 456} // no match
}

View File

@@ -0,0 +1,14 @@
// +build ignore
package templates
import (
"errors"
"fmt"
)
func before(s string) error { return fmt.Errorf("%s", s) }
func after(s string) error {
n := fmt.Sprintf("error - %s", s)
return errors.New(n)
}

9
vendor/golang.org/x/tools/refactor/eg/testdata/I1.go generated vendored Normal file
View File

@@ -0,0 +1,9 @@
// +build ignore
package I1
import "fmt"
func example() {
_ = fmt.Errorf("%s", "foo")
}

View File

@@ -0,0 +1,14 @@
// +build ignore
package I1
import (
"errors"
"fmt"
)
func example() {
n := fmt.Sprintf("error - %s", "foo")
_ = errors.New(n)
}

View File

@@ -0,0 +1,11 @@
// +build ignore
package templates
import ()
func before(x int) int { return x + x + x }
func after(x int) int {
temp := x + x
return temp + x
}

10
vendor/golang.org/x/tools/refactor/eg/testdata/J1.go generated vendored Normal file
View File

@@ -0,0 +1,10 @@
// +build ignore
package I1
import "fmt"
func example() {
temp := 5
fmt.Print(temp + temp + temp)
}

View File

@@ -0,0 +1,11 @@
// +build ignore
package I1
import "fmt"
func example() {
temp := 5
temp := temp + temp
fmt.Print(temp + temp)
}

View File

@@ -0,0 +1,8 @@
package template
// Test in which replacement has a different type.
const shouldFail = "int is not a safe replacement for string"
func before() interface{} { return "three" }
func after() interface{} { return 3 }

View File

@@ -0,0 +1,15 @@
package template
import (
"crypto/x509"
"fmt"
)
// This test demonstrates a false negative: according to the language
// rules this replacement should be ok, but types.Assignable doesn't work
// in the expected way (elementwise assignability) for tuples.
// Perhaps that's even a type-checker bug?
const shouldFail = "(n int, err error) is not a safe replacement for (key interface{}, err error)"
func before() (interface{}, error) { return x509.ParsePKCS8PrivateKey(nil) }
func after() (interface{}, error) { return fmt.Print() }

View File

@@ -0,0 +1,4 @@
package template
func before() int { return 0 }
func after() int { println(); return 0 }

View File

@@ -0,0 +1,5 @@
package template
const shouldFail = "no 'before' func found in template"
func Before() {}

View File

@@ -0,0 +1,6 @@
package template
const shouldFail = "different signatures"
func before() int { return 0 }
func after() string { return "" }