github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/go/ast/inspector/typeof.go (about)

     1  // Copyright 2018 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 inspector
     6  
     7  // This file defines func typeOf(ast.Node) uint64.
     8  //
     9  // The initial map-based implementation was too slow;
    10  // see https://go-review.googlesource.com/c/tools/+/135655/1/go/ast/inspector/inspector.go#196
    11  
    12  import (
    13  	"go/ast"
    14  
    15  	"github.com/powerman/golang-tools/internal/typeparams"
    16  )
    17  
    18  const (
    19  	nArrayType = iota
    20  	nAssignStmt
    21  	nBadDecl
    22  	nBadExpr
    23  	nBadStmt
    24  	nBasicLit
    25  	nBinaryExpr
    26  	nBlockStmt
    27  	nBranchStmt
    28  	nCallExpr
    29  	nCaseClause
    30  	nChanType
    31  	nCommClause
    32  	nComment
    33  	nCommentGroup
    34  	nCompositeLit
    35  	nDeclStmt
    36  	nDeferStmt
    37  	nEllipsis
    38  	nEmptyStmt
    39  	nExprStmt
    40  	nField
    41  	nFieldList
    42  	nFile
    43  	nForStmt
    44  	nFuncDecl
    45  	nFuncLit
    46  	nFuncType
    47  	nGenDecl
    48  	nGoStmt
    49  	nIdent
    50  	nIfStmt
    51  	nImportSpec
    52  	nIncDecStmt
    53  	nIndexExpr
    54  	nIndexListExpr
    55  	nInterfaceType
    56  	nKeyValueExpr
    57  	nLabeledStmt
    58  	nMapType
    59  	nPackage
    60  	nParenExpr
    61  	nRangeStmt
    62  	nReturnStmt
    63  	nSelectStmt
    64  	nSelectorExpr
    65  	nSendStmt
    66  	nSliceExpr
    67  	nStarExpr
    68  	nStructType
    69  	nSwitchStmt
    70  	nTypeAssertExpr
    71  	nTypeSpec
    72  	nTypeSwitchStmt
    73  	nUnaryExpr
    74  	nValueSpec
    75  )
    76  
    77  // typeOf returns a distinct single-bit value that represents the type of n.
    78  //
    79  // Various implementations were benchmarked with BenchmarkNewInspector:
    80  //								GOGC=off
    81  // - type switch				4.9-5.5ms	2.1ms
    82  // - binary search over a sorted list of types  5.5-5.9ms	2.5ms
    83  // - linear scan, frequency-ordered list 	5.9-6.1ms	2.7ms
    84  // - linear scan, unordered list		6.4ms		2.7ms
    85  // - hash table					6.5ms		3.1ms
    86  // A perfect hash seemed like overkill.
    87  //
    88  // The compiler's switch statement is the clear winner
    89  // as it produces a binary tree in code,
    90  // with constant conditions and good branch prediction.
    91  // (Sadly it is the most verbose in source code.)
    92  // Binary search suffered from poor branch prediction.
    93  //
    94  func typeOf(n ast.Node) uint64 {
    95  	// Fast path: nearly half of all nodes are identifiers.
    96  	if _, ok := n.(*ast.Ident); ok {
    97  		return 1 << nIdent
    98  	}
    99  
   100  	// These cases include all nodes encountered by ast.Inspect.
   101  	switch n.(type) {
   102  	case *ast.ArrayType:
   103  		return 1 << nArrayType
   104  	case *ast.AssignStmt:
   105  		return 1 << nAssignStmt
   106  	case *ast.BadDecl:
   107  		return 1 << nBadDecl
   108  	case *ast.BadExpr:
   109  		return 1 << nBadExpr
   110  	case *ast.BadStmt:
   111  		return 1 << nBadStmt
   112  	case *ast.BasicLit:
   113  		return 1 << nBasicLit
   114  	case *ast.BinaryExpr:
   115  		return 1 << nBinaryExpr
   116  	case *ast.BlockStmt:
   117  		return 1 << nBlockStmt
   118  	case *ast.BranchStmt:
   119  		return 1 << nBranchStmt
   120  	case *ast.CallExpr:
   121  		return 1 << nCallExpr
   122  	case *ast.CaseClause:
   123  		return 1 << nCaseClause
   124  	case *ast.ChanType:
   125  		return 1 << nChanType
   126  	case *ast.CommClause:
   127  		return 1 << nCommClause
   128  	case *ast.Comment:
   129  		return 1 << nComment
   130  	case *ast.CommentGroup:
   131  		return 1 << nCommentGroup
   132  	case *ast.CompositeLit:
   133  		return 1 << nCompositeLit
   134  	case *ast.DeclStmt:
   135  		return 1 << nDeclStmt
   136  	case *ast.DeferStmt:
   137  		return 1 << nDeferStmt
   138  	case *ast.Ellipsis:
   139  		return 1 << nEllipsis
   140  	case *ast.EmptyStmt:
   141  		return 1 << nEmptyStmt
   142  	case *ast.ExprStmt:
   143  		return 1 << nExprStmt
   144  	case *ast.Field:
   145  		return 1 << nField
   146  	case *ast.FieldList:
   147  		return 1 << nFieldList
   148  	case *ast.File:
   149  		return 1 << nFile
   150  	case *ast.ForStmt:
   151  		return 1 << nForStmt
   152  	case *ast.FuncDecl:
   153  		return 1 << nFuncDecl
   154  	case *ast.FuncLit:
   155  		return 1 << nFuncLit
   156  	case *ast.FuncType:
   157  		return 1 << nFuncType
   158  	case *ast.GenDecl:
   159  		return 1 << nGenDecl
   160  	case *ast.GoStmt:
   161  		return 1 << nGoStmt
   162  	case *ast.Ident:
   163  		return 1 << nIdent
   164  	case *ast.IfStmt:
   165  		return 1 << nIfStmt
   166  	case *ast.ImportSpec:
   167  		return 1 << nImportSpec
   168  	case *ast.IncDecStmt:
   169  		return 1 << nIncDecStmt
   170  	case *ast.IndexExpr:
   171  		return 1 << nIndexExpr
   172  	case *typeparams.IndexListExpr:
   173  		return 1 << nIndexListExpr
   174  	case *ast.InterfaceType:
   175  		return 1 << nInterfaceType
   176  	case *ast.KeyValueExpr:
   177  		return 1 << nKeyValueExpr
   178  	case *ast.LabeledStmt:
   179  		return 1 << nLabeledStmt
   180  	case *ast.MapType:
   181  		return 1 << nMapType
   182  	case *ast.Package:
   183  		return 1 << nPackage
   184  	case *ast.ParenExpr:
   185  		return 1 << nParenExpr
   186  	case *ast.RangeStmt:
   187  		return 1 << nRangeStmt
   188  	case *ast.ReturnStmt:
   189  		return 1 << nReturnStmt
   190  	case *ast.SelectStmt:
   191  		return 1 << nSelectStmt
   192  	case *ast.SelectorExpr:
   193  		return 1 << nSelectorExpr
   194  	case *ast.SendStmt:
   195  		return 1 << nSendStmt
   196  	case *ast.SliceExpr:
   197  		return 1 << nSliceExpr
   198  	case *ast.StarExpr:
   199  		return 1 << nStarExpr
   200  	case *ast.StructType:
   201  		return 1 << nStructType
   202  	case *ast.SwitchStmt:
   203  		return 1 << nSwitchStmt
   204  	case *ast.TypeAssertExpr:
   205  		return 1 << nTypeAssertExpr
   206  	case *ast.TypeSpec:
   207  		return 1 << nTypeSpec
   208  	case *ast.TypeSwitchStmt:
   209  		return 1 << nTypeSwitchStmt
   210  	case *ast.UnaryExpr:
   211  		return 1 << nUnaryExpr
   212  	case *ast.ValueSpec:
   213  		return 1 << nValueSpec
   214  	}
   215  	return 0
   216  }
   217  
   218  func maskOf(nodes []ast.Node) uint64 {
   219  	if nodes == nil {
   220  		return 1<<64 - 1 // match all node types
   221  	}
   222  	var mask uint64
   223  	for _, n := range nodes {
   224  		mask |= typeOf(n)
   225  	}
   226  	return mask
   227  }