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  }