gitee.com/wgliang/goreporter@v0.0.0-20180902115603-df1b20f7c5d0/linters/simpler/ssa/util.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build go1.5 6 7 package ssa 8 9 // This file defines a number of miscellaneous utility functions. 10 11 import ( 12 "fmt" 13 "go/ast" 14 "go/token" 15 "go/types" 16 "io" 17 "os" 18 19 "golang.org/x/tools/go/ast/astutil" 20 ) 21 22 //// AST utilities 23 24 func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) } 25 26 // isBlankIdent returns true iff e is an Ident with name "_". 27 // They have no associated types.Object, and thus no type. 28 // 29 func isBlankIdent(e ast.Expr) bool { 30 id, ok := e.(*ast.Ident) 31 return ok && id.Name == "_" 32 } 33 34 //// Type utilities. Some of these belong in go/types. 35 36 // isPointer returns true for types whose underlying type is a pointer. 37 func isPointer(typ types.Type) bool { 38 _, ok := typ.Underlying().(*types.Pointer) 39 return ok 40 } 41 42 func isInterface(T types.Type) bool { return types.IsInterface(T) } 43 44 // deref returns a pointer's element type; otherwise it returns typ. 45 func deref(typ types.Type) types.Type { 46 if p, ok := typ.Underlying().(*types.Pointer); ok { 47 return p.Elem() 48 } 49 return typ 50 } 51 52 // recvType returns the receiver type of method obj. 53 func recvType(obj *types.Func) types.Type { 54 return obj.Type().(*types.Signature).Recv().Type() 55 } 56 57 // DefaultType returns the default "typed" type for an "untyped" type; 58 // it returns the incoming type for all other types. The default type 59 // for untyped nil is untyped nil. 60 // 61 // Exported to ssa/interp. 62 // 63 // TODO(gri): this is a copy of go/types.defaultType; export that function. 64 // 65 func DefaultType(typ types.Type) types.Type { 66 if t, ok := typ.(*types.Basic); ok { 67 k := t.Kind() 68 switch k { 69 case types.UntypedBool: 70 k = types.Bool 71 case types.UntypedInt: 72 k = types.Int 73 case types.UntypedRune: 74 k = types.Rune 75 case types.UntypedFloat: 76 k = types.Float64 77 case types.UntypedComplex: 78 k = types.Complex128 79 case types.UntypedString: 80 k = types.String 81 } 82 typ = types.Typ[k] 83 } 84 return typ 85 } 86 87 // logStack prints the formatted "start" message to stderr and 88 // returns a closure that prints the corresponding "end" message. 89 // Call using 'defer logStack(...)()' to show builder stack on panic. 90 // Don't forget trailing parens! 91 // 92 func logStack(format string, args ...interface{}) func() { 93 msg := fmt.Sprintf(format, args...) 94 io.WriteString(os.Stderr, msg) 95 io.WriteString(os.Stderr, "\n") 96 return func() { 97 io.WriteString(os.Stderr, msg) 98 io.WriteString(os.Stderr, " end\n") 99 } 100 } 101 102 // newVar creates a 'var' for use in a types.Tuple. 103 func newVar(name string, typ types.Type) *types.Var { 104 return types.NewParam(token.NoPos, nil, name, typ) 105 } 106 107 // anonVar creates an anonymous 'var' for use in a types.Tuple. 108 func anonVar(typ types.Type) *types.Var { 109 return newVar("", typ) 110 } 111 112 var lenResults = types.NewTuple(anonVar(tInt)) 113 114 // makeLen returns the len builtin specialized to type func(T)int. 115 func makeLen(T types.Type) *Builtin { 116 lenParams := types.NewTuple(anonVar(T)) 117 return &Builtin{ 118 name: "len", 119 sig: types.NewSignature(nil, lenParams, lenResults, false), 120 } 121 }