Source file src/cmd/vendor/golang.org/x/tools/go/ast/edge/edge.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 edge defines identifiers for each field of an ast.Node
     6  // struct type that refers to another Node.
     7  package edge
     8  
     9  import (
    10  	"fmt"
    11  	"go/ast"
    12  	"reflect"
    13  )
    14  
    15  // A Kind describes a field of an [ast.Node] struct.
    16  type Kind uint8
    17  
    18  // String returns a description of the edge kind.
    19  func (k Kind) String() string {
    20  	if k == Invalid {
    21  		return "<invalid>"
    22  	}
    23  	info := fieldInfos[k]
    24  	return fmt.Sprintf("%v.%s", info.nodeType.Elem().Name(), info.name)
    25  }
    26  
    27  // NodeType returns the pointer-to-struct type of the ast.Node implementation.
    28  func (k Kind) NodeType() reflect.Type { return fieldInfos[k].nodeType }
    29  
    30  // FieldName returns the name of the field.
    31  func (k Kind) FieldName() string { return fieldInfos[k].name }
    32  
    33  // FieldType returns the declared type of the field.
    34  func (k Kind) FieldType() reflect.Type { return fieldInfos[k].fieldType }
    35  
    36  // Get returns the direct child of n identified by (k, idx).
    37  // n's type must match k.NodeType().
    38  // idx must be a valid slice index, or -1 for a non-slice.
    39  func (k Kind) Get(n ast.Node, idx int) ast.Node {
    40  	if k.NodeType() != reflect.TypeOf(n) {
    41  		panic(fmt.Sprintf("%v.Get(%T): invalid node type", k, n))
    42  	}
    43  	v := reflect.ValueOf(n).Elem().Field(fieldInfos[k].index)
    44  
    45  	if v.Kind() == reflect.Slice {
    46  		v = v.Index(idx) // asserts valid idx
    47  	} else if idx != -1 {
    48  		panic(fmt.Sprintf("%v, Get(%T, %d): cannot index non-slice", v, n, idx))
    49  	}
    50  
    51  	out, _ := v.Interface().(ast.Node) // may be nil
    52  	return out
    53  }
    54  
    55  // Each [Kind] is named Type_Field, where Type is the
    56  // [ast.Node] struct type and Field is the name of the field
    57  const (
    58  	Invalid Kind = iota // for nodes at the root of the traversal
    59  
    60  	// As of Go1.26 these kinds are sorted alphabetically, but
    61  	// numbering must be stable, so any new addition of const should
    62  	// use a new value (be added at the end of the list).
    63  
    64  	ArrayType_Elt
    65  	ArrayType_Len
    66  	AssignStmt_Lhs
    67  	AssignStmt_Rhs
    68  	BinaryExpr_X
    69  	BinaryExpr_Y
    70  	BlockStmt_List
    71  	BranchStmt_Label
    72  	CallExpr_Args
    73  	CallExpr_Fun
    74  	CaseClause_Body
    75  	CaseClause_List
    76  	ChanType_Value
    77  	CommClause_Body
    78  	CommClause_Comm
    79  	CommentGroup_List
    80  	CompositeLit_Elts
    81  	CompositeLit_Type
    82  	DeclStmt_Decl
    83  	DeferStmt_Call
    84  	Ellipsis_Elt
    85  	ExprStmt_X
    86  	FieldList_List
    87  	Field_Comment
    88  	Field_Doc
    89  	Field_Names
    90  	Field_Tag
    91  	Field_Type
    92  	File_Decls
    93  	File_Doc
    94  	File_Name
    95  	ForStmt_Body
    96  	ForStmt_Cond
    97  	ForStmt_Init
    98  	ForStmt_Post
    99  	FuncDecl_Body
   100  	FuncDecl_Doc
   101  	FuncDecl_Name
   102  	FuncDecl_Recv
   103  	FuncDecl_Type
   104  	FuncLit_Body
   105  	FuncLit_Type
   106  	FuncType_Params
   107  	FuncType_Results
   108  	FuncType_TypeParams
   109  	GenDecl_Doc
   110  	GenDecl_Specs
   111  	GoStmt_Call
   112  	IfStmt_Body
   113  	IfStmt_Cond
   114  	IfStmt_Else
   115  	IfStmt_Init
   116  	ImportSpec_Comment
   117  	ImportSpec_Doc
   118  	ImportSpec_Name
   119  	ImportSpec_Path
   120  	IncDecStmt_X
   121  	IndexExpr_Index
   122  	IndexExpr_X
   123  	IndexListExpr_Indices
   124  	IndexListExpr_X
   125  	InterfaceType_Methods
   126  	KeyValueExpr_Key
   127  	KeyValueExpr_Value
   128  	LabeledStmt_Label
   129  	LabeledStmt_Stmt
   130  	MapType_Key
   131  	MapType_Value
   132  	ParenExpr_X
   133  	RangeStmt_Body
   134  	RangeStmt_Key
   135  	RangeStmt_Value
   136  	RangeStmt_X
   137  	ReturnStmt_Results
   138  	SelectStmt_Body
   139  	SelectorExpr_Sel
   140  	SelectorExpr_X
   141  	SendStmt_Chan
   142  	SendStmt_Value
   143  	SliceExpr_High
   144  	SliceExpr_Low
   145  	SliceExpr_Max
   146  	SliceExpr_X
   147  	StarExpr_X
   148  	StructType_Fields
   149  	SwitchStmt_Body
   150  	SwitchStmt_Init
   151  	SwitchStmt_Tag
   152  	TypeAssertExpr_Type
   153  	TypeAssertExpr_X
   154  	TypeSpec_Comment
   155  	TypeSpec_Doc
   156  	TypeSpec_Name
   157  	TypeSpec_Type
   158  	TypeSpec_TypeParams
   159  	TypeSwitchStmt_Assign
   160  	TypeSwitchStmt_Body
   161  	TypeSwitchStmt_Init
   162  	UnaryExpr_X
   163  	ValueSpec_Comment
   164  	ValueSpec_Doc
   165  	ValueSpec_Names
   166  	ValueSpec_Type
   167  	ValueSpec_Values
   168  
   169  	maxKind
   170  )
   171  
   172  // Assert that the encoding fits in 7 bits,
   173  // as the inspector relies on this.
   174  // (We are currently at 104.)
   175  var _ = [1 << 7]struct{}{}[maxKind]
   176  
   177  type fieldInfo struct {
   178  	nodeType  reflect.Type // pointer-to-struct type of ast.Node implementation
   179  	name      string
   180  	index     int
   181  	fieldType reflect.Type
   182  }
   183  
   184  func info[N ast.Node](fieldName string) fieldInfo {
   185  	nodePtrType := reflect.TypeFor[N]()
   186  	f, ok := nodePtrType.Elem().FieldByName(fieldName)
   187  	if !ok {
   188  		panic(fieldName)
   189  	}
   190  	return fieldInfo{nodePtrType, fieldName, f.Index[0], f.Type}
   191  }
   192  
   193  var fieldInfos = [...]fieldInfo{
   194  	Invalid:               {},
   195  	ArrayType_Elt:         info[*ast.ArrayType]("Elt"),
   196  	ArrayType_Len:         info[*ast.ArrayType]("Len"),
   197  	AssignStmt_Lhs:        info[*ast.AssignStmt]("Lhs"),
   198  	AssignStmt_Rhs:        info[*ast.AssignStmt]("Rhs"),
   199  	BinaryExpr_X:          info[*ast.BinaryExpr]("X"),
   200  	BinaryExpr_Y:          info[*ast.BinaryExpr]("Y"),
   201  	BlockStmt_List:        info[*ast.BlockStmt]("List"),
   202  	BranchStmt_Label:      info[*ast.BranchStmt]("Label"),
   203  	CallExpr_Args:         info[*ast.CallExpr]("Args"),
   204  	CallExpr_Fun:          info[*ast.CallExpr]("Fun"),
   205  	CaseClause_Body:       info[*ast.CaseClause]("Body"),
   206  	CaseClause_List:       info[*ast.CaseClause]("List"),
   207  	ChanType_Value:        info[*ast.ChanType]("Value"),
   208  	CommClause_Body:       info[*ast.CommClause]("Body"),
   209  	CommClause_Comm:       info[*ast.CommClause]("Comm"),
   210  	CommentGroup_List:     info[*ast.CommentGroup]("List"),
   211  	CompositeLit_Elts:     info[*ast.CompositeLit]("Elts"),
   212  	CompositeLit_Type:     info[*ast.CompositeLit]("Type"),
   213  	DeclStmt_Decl:         info[*ast.DeclStmt]("Decl"),
   214  	DeferStmt_Call:        info[*ast.DeferStmt]("Call"),
   215  	Ellipsis_Elt:          info[*ast.Ellipsis]("Elt"),
   216  	ExprStmt_X:            info[*ast.ExprStmt]("X"),
   217  	FieldList_List:        info[*ast.FieldList]("List"),
   218  	Field_Comment:         info[*ast.Field]("Comment"),
   219  	Field_Doc:             info[*ast.Field]("Doc"),
   220  	Field_Names:           info[*ast.Field]("Names"),
   221  	Field_Tag:             info[*ast.Field]("Tag"),
   222  	Field_Type:            info[*ast.Field]("Type"),
   223  	File_Decls:            info[*ast.File]("Decls"),
   224  	File_Doc:              info[*ast.File]("Doc"),
   225  	File_Name:             info[*ast.File]("Name"),
   226  	ForStmt_Body:          info[*ast.ForStmt]("Body"),
   227  	ForStmt_Cond:          info[*ast.ForStmt]("Cond"),
   228  	ForStmt_Init:          info[*ast.ForStmt]("Init"),
   229  	ForStmt_Post:          info[*ast.ForStmt]("Post"),
   230  	FuncDecl_Body:         info[*ast.FuncDecl]("Body"),
   231  	FuncDecl_Doc:          info[*ast.FuncDecl]("Doc"),
   232  	FuncDecl_Name:         info[*ast.FuncDecl]("Name"),
   233  	FuncDecl_Recv:         info[*ast.FuncDecl]("Recv"),
   234  	FuncDecl_Type:         info[*ast.FuncDecl]("Type"),
   235  	FuncLit_Body:          info[*ast.FuncLit]("Body"),
   236  	FuncLit_Type:          info[*ast.FuncLit]("Type"),
   237  	FuncType_Params:       info[*ast.FuncType]("Params"),
   238  	FuncType_Results:      info[*ast.FuncType]("Results"),
   239  	FuncType_TypeParams:   info[*ast.FuncType]("TypeParams"),
   240  	GenDecl_Doc:           info[*ast.GenDecl]("Doc"),
   241  	GenDecl_Specs:         info[*ast.GenDecl]("Specs"),
   242  	GoStmt_Call:           info[*ast.GoStmt]("Call"),
   243  	IfStmt_Body:           info[*ast.IfStmt]("Body"),
   244  	IfStmt_Cond:           info[*ast.IfStmt]("Cond"),
   245  	IfStmt_Else:           info[*ast.IfStmt]("Else"),
   246  	IfStmt_Init:           info[*ast.IfStmt]("Init"),
   247  	ImportSpec_Comment:    info[*ast.ImportSpec]("Comment"),
   248  	ImportSpec_Doc:        info[*ast.ImportSpec]("Doc"),
   249  	ImportSpec_Name:       info[*ast.ImportSpec]("Name"),
   250  	ImportSpec_Path:       info[*ast.ImportSpec]("Path"),
   251  	IncDecStmt_X:          info[*ast.IncDecStmt]("X"),
   252  	IndexExpr_Index:       info[*ast.IndexExpr]("Index"),
   253  	IndexExpr_X:           info[*ast.IndexExpr]("X"),
   254  	IndexListExpr_Indices: info[*ast.IndexListExpr]("Indices"),
   255  	IndexListExpr_X:       info[*ast.IndexListExpr]("X"),
   256  	InterfaceType_Methods: info[*ast.InterfaceType]("Methods"),
   257  	KeyValueExpr_Key:      info[*ast.KeyValueExpr]("Key"),
   258  	KeyValueExpr_Value:    info[*ast.KeyValueExpr]("Value"),
   259  	LabeledStmt_Label:     info[*ast.LabeledStmt]("Label"),
   260  	LabeledStmt_Stmt:      info[*ast.LabeledStmt]("Stmt"),
   261  	MapType_Key:           info[*ast.MapType]("Key"),
   262  	MapType_Value:         info[*ast.MapType]("Value"),
   263  	ParenExpr_X:           info[*ast.ParenExpr]("X"),
   264  	RangeStmt_Body:        info[*ast.RangeStmt]("Body"),
   265  	RangeStmt_Key:         info[*ast.RangeStmt]("Key"),
   266  	RangeStmt_Value:       info[*ast.RangeStmt]("Value"),
   267  	RangeStmt_X:           info[*ast.RangeStmt]("X"),
   268  	ReturnStmt_Results:    info[*ast.ReturnStmt]("Results"),
   269  	SelectStmt_Body:       info[*ast.SelectStmt]("Body"),
   270  	SelectorExpr_Sel:      info[*ast.SelectorExpr]("Sel"),
   271  	SelectorExpr_X:        info[*ast.SelectorExpr]("X"),
   272  	SendStmt_Chan:         info[*ast.SendStmt]("Chan"),
   273  	SendStmt_Value:        info[*ast.SendStmt]("Value"),
   274  	SliceExpr_High:        info[*ast.SliceExpr]("High"),
   275  	SliceExpr_Low:         info[*ast.SliceExpr]("Low"),
   276  	SliceExpr_Max:         info[*ast.SliceExpr]("Max"),
   277  	SliceExpr_X:           info[*ast.SliceExpr]("X"),
   278  	StarExpr_X:            info[*ast.StarExpr]("X"),
   279  	StructType_Fields:     info[*ast.StructType]("Fields"),
   280  	SwitchStmt_Body:       info[*ast.SwitchStmt]("Body"),
   281  	SwitchStmt_Init:       info[*ast.SwitchStmt]("Init"),
   282  	SwitchStmt_Tag:        info[*ast.SwitchStmt]("Tag"),
   283  	TypeAssertExpr_Type:   info[*ast.TypeAssertExpr]("Type"),
   284  	TypeAssertExpr_X:      info[*ast.TypeAssertExpr]("X"),
   285  	TypeSpec_Comment:      info[*ast.TypeSpec]("Comment"),
   286  	TypeSpec_Doc:          info[*ast.TypeSpec]("Doc"),
   287  	TypeSpec_Name:         info[*ast.TypeSpec]("Name"),
   288  	TypeSpec_Type:         info[*ast.TypeSpec]("Type"),
   289  	TypeSpec_TypeParams:   info[*ast.TypeSpec]("TypeParams"),
   290  	TypeSwitchStmt_Assign: info[*ast.TypeSwitchStmt]("Assign"),
   291  	TypeSwitchStmt_Body:   info[*ast.TypeSwitchStmt]("Body"),
   292  	TypeSwitchStmt_Init:   info[*ast.TypeSwitchStmt]("Init"),
   293  	UnaryExpr_X:           info[*ast.UnaryExpr]("X"),
   294  	ValueSpec_Comment:     info[*ast.ValueSpec]("Comment"),
   295  	ValueSpec_Doc:         info[*ast.ValueSpec]("Doc"),
   296  	ValueSpec_Names:       info[*ast.ValueSpec]("Names"),
   297  	ValueSpec_Type:        info[*ast.ValueSpec]("Type"),
   298  	ValueSpec_Values:      info[*ast.ValueSpec]("Values"),
   299  }
   300  

View as plain text