Source file src/cmd/vendor/golang.org/x/tools/go/ast/inspector/walk.go

     1  // Copyright 2025 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 is a fork of ast.Inspect to reduce unnecessary dynamic
     8  // calls and to gather edge information.
     9  //
    10  // Consistency with the original is ensured by TestInspectAllNodes.
    11  
    12  import (
    13  	"fmt"
    14  	"go/ast"
    15  
    16  	"golang.org/x/tools/go/ast/edge"
    17  )
    18  
    19  func walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) {
    20  	for i, node := range list {
    21  		walk(v, ek, i, node)
    22  	}
    23  }
    24  
    25  func walk(v *visitor, ek edge.Kind, index int, node ast.Node) {
    26  	v.push(ek, index, node)
    27  
    28  	// walk children
    29  	// (the order of the cases matches the order
    30  	// of the corresponding node types in ast.go)
    31  	switch n := node.(type) {
    32  	// Comments and fields
    33  	case *ast.Comment:
    34  		// nothing to do
    35  
    36  	case *ast.CommentGroup:
    37  		walkList(v, edge.CommentGroup_List, n.List)
    38  
    39  	case *ast.Field:
    40  		if n.Doc != nil {
    41  			walk(v, edge.Field_Doc, -1, n.Doc)
    42  		}
    43  		walkList(v, edge.Field_Names, n.Names)
    44  		if n.Type != nil {
    45  			walk(v, edge.Field_Type, -1, n.Type)
    46  		}
    47  		if n.Tag != nil {
    48  			walk(v, edge.Field_Tag, -1, n.Tag)
    49  		}
    50  		if n.Comment != nil {
    51  			walk(v, edge.Field_Comment, -1, n.Comment)
    52  		}
    53  
    54  	case *ast.FieldList:
    55  		walkList(v, edge.FieldList_List, n.List)
    56  
    57  	// Expressions
    58  	case *ast.BadExpr, *ast.Ident, *ast.BasicLit:
    59  		// nothing to do
    60  
    61  	case *ast.Ellipsis:
    62  		if n.Elt != nil {
    63  			walk(v, edge.Ellipsis_Elt, -1, n.Elt)
    64  		}
    65  
    66  	case *ast.FuncLit:
    67  		walk(v, edge.FuncLit_Type, -1, n.Type)
    68  		walk(v, edge.FuncLit_Body, -1, n.Body)
    69  
    70  	case *ast.CompositeLit:
    71  		if n.Type != nil {
    72  			walk(v, edge.CompositeLit_Type, -1, n.Type)
    73  		}
    74  		walkList(v, edge.CompositeLit_Elts, n.Elts)
    75  
    76  	case *ast.ParenExpr:
    77  		walk(v, edge.ParenExpr_X, -1, n.X)
    78  
    79  	case *ast.SelectorExpr:
    80  		walk(v, edge.SelectorExpr_X, -1, n.X)
    81  		walk(v, edge.SelectorExpr_Sel, -1, n.Sel)
    82  
    83  	case *ast.IndexExpr:
    84  		walk(v, edge.IndexExpr_X, -1, n.X)
    85  		walk(v, edge.IndexExpr_Index, -1, n.Index)
    86  
    87  	case *ast.IndexListExpr:
    88  		walk(v, edge.IndexListExpr_X, -1, n.X)
    89  		walkList(v, edge.IndexListExpr_Indices, n.Indices)
    90  
    91  	case *ast.SliceExpr:
    92  		walk(v, edge.SliceExpr_X, -1, n.X)
    93  		if n.Low != nil {
    94  			walk(v, edge.SliceExpr_Low, -1, n.Low)
    95  		}
    96  		if n.High != nil {
    97  			walk(v, edge.SliceExpr_High, -1, n.High)
    98  		}
    99  		if n.Max != nil {
   100  			walk(v, edge.SliceExpr_Max, -1, n.Max)
   101  		}
   102  
   103  	case *ast.TypeAssertExpr:
   104  		walk(v, edge.TypeAssertExpr_X, -1, n.X)
   105  		if n.Type != nil {
   106  			walk(v, edge.TypeAssertExpr_Type, -1, n.Type)
   107  		}
   108  
   109  	case *ast.CallExpr:
   110  		walk(v, edge.CallExpr_Fun, -1, n.Fun)
   111  		walkList(v, edge.CallExpr_Args, n.Args)
   112  
   113  	case *ast.StarExpr:
   114  		walk(v, edge.StarExpr_X, -1, n.X)
   115  
   116  	case *ast.UnaryExpr:
   117  		walk(v, edge.UnaryExpr_X, -1, n.X)
   118  
   119  	case *ast.BinaryExpr:
   120  		walk(v, edge.BinaryExpr_X, -1, n.X)
   121  		walk(v, edge.BinaryExpr_Y, -1, n.Y)
   122  
   123  	case *ast.KeyValueExpr:
   124  		walk(v, edge.KeyValueExpr_Key, -1, n.Key)
   125  		walk(v, edge.KeyValueExpr_Value, -1, n.Value)
   126  
   127  	// Types
   128  	case *ast.ArrayType:
   129  		if n.Len != nil {
   130  			walk(v, edge.ArrayType_Len, -1, n.Len)
   131  		}
   132  		walk(v, edge.ArrayType_Elt, -1, n.Elt)
   133  
   134  	case *ast.StructType:
   135  		walk(v, edge.StructType_Fields, -1, n.Fields)
   136  
   137  	case *ast.FuncType:
   138  		if n.TypeParams != nil {
   139  			walk(v, edge.FuncType_TypeParams, -1, n.TypeParams)
   140  		}
   141  		if n.Params != nil {
   142  			walk(v, edge.FuncType_Params, -1, n.Params)
   143  		}
   144  		if n.Results != nil {
   145  			walk(v, edge.FuncType_Results, -1, n.Results)
   146  		}
   147  
   148  	case *ast.InterfaceType:
   149  		walk(v, edge.InterfaceType_Methods, -1, n.Methods)
   150  
   151  	case *ast.MapType:
   152  		walk(v, edge.MapType_Key, -1, n.Key)
   153  		walk(v, edge.MapType_Value, -1, n.Value)
   154  
   155  	case *ast.ChanType:
   156  		walk(v, edge.ChanType_Value, -1, n.Value)
   157  
   158  	// Statements
   159  	case *ast.BadStmt:
   160  		// nothing to do
   161  
   162  	case *ast.DeclStmt:
   163  		walk(v, edge.DeclStmt_Decl, -1, n.Decl)
   164  
   165  	case *ast.EmptyStmt:
   166  		// nothing to do
   167  
   168  	case *ast.LabeledStmt:
   169  		walk(v, edge.LabeledStmt_Label, -1, n.Label)
   170  		walk(v, edge.LabeledStmt_Stmt, -1, n.Stmt)
   171  
   172  	case *ast.ExprStmt:
   173  		walk(v, edge.ExprStmt_X, -1, n.X)
   174  
   175  	case *ast.SendStmt:
   176  		walk(v, edge.SendStmt_Chan, -1, n.Chan)
   177  		walk(v, edge.SendStmt_Value, -1, n.Value)
   178  
   179  	case *ast.IncDecStmt:
   180  		walk(v, edge.IncDecStmt_X, -1, n.X)
   181  
   182  	case *ast.AssignStmt:
   183  		walkList(v, edge.AssignStmt_Lhs, n.Lhs)
   184  		walkList(v, edge.AssignStmt_Rhs, n.Rhs)
   185  
   186  	case *ast.GoStmt:
   187  		walk(v, edge.GoStmt_Call, -1, n.Call)
   188  
   189  	case *ast.DeferStmt:
   190  		walk(v, edge.DeferStmt_Call, -1, n.Call)
   191  
   192  	case *ast.ReturnStmt:
   193  		walkList(v, edge.ReturnStmt_Results, n.Results)
   194  
   195  	case *ast.BranchStmt:
   196  		if n.Label != nil {
   197  			walk(v, edge.BranchStmt_Label, -1, n.Label)
   198  		}
   199  
   200  	case *ast.BlockStmt:
   201  		walkList(v, edge.BlockStmt_List, n.List)
   202  
   203  	case *ast.IfStmt:
   204  		if n.Init != nil {
   205  			walk(v, edge.IfStmt_Init, -1, n.Init)
   206  		}
   207  		walk(v, edge.IfStmt_Cond, -1, n.Cond)
   208  		walk(v, edge.IfStmt_Body, -1, n.Body)
   209  		if n.Else != nil {
   210  			walk(v, edge.IfStmt_Else, -1, n.Else)
   211  		}
   212  
   213  	case *ast.CaseClause:
   214  		walkList(v, edge.CaseClause_List, n.List)
   215  		walkList(v, edge.CaseClause_Body, n.Body)
   216  
   217  	case *ast.SwitchStmt:
   218  		if n.Init != nil {
   219  			walk(v, edge.SwitchStmt_Init, -1, n.Init)
   220  		}
   221  		if n.Tag != nil {
   222  			walk(v, edge.SwitchStmt_Tag, -1, n.Tag)
   223  		}
   224  		walk(v, edge.SwitchStmt_Body, -1, n.Body)
   225  
   226  	case *ast.TypeSwitchStmt:
   227  		if n.Init != nil {
   228  			walk(v, edge.TypeSwitchStmt_Init, -1, n.Init)
   229  		}
   230  		walk(v, edge.TypeSwitchStmt_Assign, -1, n.Assign)
   231  		walk(v, edge.TypeSwitchStmt_Body, -1, n.Body)
   232  
   233  	case *ast.CommClause:
   234  		if n.Comm != nil {
   235  			walk(v, edge.CommClause_Comm, -1, n.Comm)
   236  		}
   237  		walkList(v, edge.CommClause_Body, n.Body)
   238  
   239  	case *ast.SelectStmt:
   240  		walk(v, edge.SelectStmt_Body, -1, n.Body)
   241  
   242  	case *ast.ForStmt:
   243  		if n.Init != nil {
   244  			walk(v, edge.ForStmt_Init, -1, n.Init)
   245  		}
   246  		if n.Cond != nil {
   247  			walk(v, edge.ForStmt_Cond, -1, n.Cond)
   248  		}
   249  		if n.Post != nil {
   250  			walk(v, edge.ForStmt_Post, -1, n.Post)
   251  		}
   252  		walk(v, edge.ForStmt_Body, -1, n.Body)
   253  
   254  	case *ast.RangeStmt:
   255  		if n.Key != nil {
   256  			walk(v, edge.RangeStmt_Key, -1, n.Key)
   257  		}
   258  		if n.Value != nil {
   259  			walk(v, edge.RangeStmt_Value, -1, n.Value)
   260  		}
   261  		walk(v, edge.RangeStmt_X, -1, n.X)
   262  		walk(v, edge.RangeStmt_Body, -1, n.Body)
   263  
   264  	// Declarations
   265  	case *ast.ImportSpec:
   266  		if n.Doc != nil {
   267  			walk(v, edge.ImportSpec_Doc, -1, n.Doc)
   268  		}
   269  		if n.Name != nil {
   270  			walk(v, edge.ImportSpec_Name, -1, n.Name)
   271  		}
   272  		walk(v, edge.ImportSpec_Path, -1, n.Path)
   273  		if n.Comment != nil {
   274  			walk(v, edge.ImportSpec_Comment, -1, n.Comment)
   275  		}
   276  
   277  	case *ast.ValueSpec:
   278  		if n.Doc != nil {
   279  			walk(v, edge.ValueSpec_Doc, -1, n.Doc)
   280  		}
   281  		walkList(v, edge.ValueSpec_Names, n.Names)
   282  		if n.Type != nil {
   283  			walk(v, edge.ValueSpec_Type, -1, n.Type)
   284  		}
   285  		walkList(v, edge.ValueSpec_Values, n.Values)
   286  		if n.Comment != nil {
   287  			walk(v, edge.ValueSpec_Comment, -1, n.Comment)
   288  		}
   289  
   290  	case *ast.TypeSpec:
   291  		if n.Doc != nil {
   292  			walk(v, edge.TypeSpec_Doc, -1, n.Doc)
   293  		}
   294  		walk(v, edge.TypeSpec_Name, -1, n.Name)
   295  		if n.TypeParams != nil {
   296  			walk(v, edge.TypeSpec_TypeParams, -1, n.TypeParams)
   297  		}
   298  		walk(v, edge.TypeSpec_Type, -1, n.Type)
   299  		if n.Comment != nil {
   300  			walk(v, edge.TypeSpec_Comment, -1, n.Comment)
   301  		}
   302  
   303  	case *ast.BadDecl:
   304  		// nothing to do
   305  
   306  	case *ast.GenDecl:
   307  		if n.Doc != nil {
   308  			walk(v, edge.GenDecl_Doc, -1, n.Doc)
   309  		}
   310  		walkList(v, edge.GenDecl_Specs, n.Specs)
   311  
   312  	case *ast.FuncDecl:
   313  		if n.Doc != nil {
   314  			walk(v, edge.FuncDecl_Doc, -1, n.Doc)
   315  		}
   316  		if n.Recv != nil {
   317  			walk(v, edge.FuncDecl_Recv, -1, n.Recv)
   318  		}
   319  		walk(v, edge.FuncDecl_Name, -1, n.Name)
   320  		walk(v, edge.FuncDecl_Type, -1, n.Type)
   321  		if n.Body != nil {
   322  			walk(v, edge.FuncDecl_Body, -1, n.Body)
   323  		}
   324  
   325  	case *ast.File:
   326  		if n.Doc != nil {
   327  			walk(v, edge.File_Doc, -1, n.Doc)
   328  		}
   329  		walk(v, edge.File_Name, -1, n.Name)
   330  		walkList(v, edge.File_Decls, n.Decls)
   331  		// don't walk n.Comments - they have been
   332  		// visited already through the individual
   333  		// nodes
   334  
   335  	default:
   336  		// (includes *ast.Package)
   337  		panic(fmt.Sprintf("Walk: unexpected node type %T", n))
   338  	}
   339  
   340  	v.pop(node)
   341  }
   342  

View as plain text