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

View as plain text