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