// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package inspector

// This file is a fork of ast.Inspect to reduce unnecessary dynamic
// calls and to gather edge information.
//
// Consistency with the original is ensured by TestInspectAllNodes.

import (
	
	

	
)

func [ ast.Node]( *visitor,  edge.Kind,  []) {
	for ,  := range  {
		walk(, , , )
	}
}

func ( *visitor,  edge.Kind,  int,  ast.Node) {
	.push(, , )

	// walk children
	// (the order of the cases matches the order
	// of the corresponding node types in ast.go)
	switch n := .(type) {
	// Comments and fields
	case *ast.Comment:
		// nothing to do

	case *ast.CommentGroup:
		walkList(, edge.CommentGroup_List, .List)

	case *ast.Field:
		if .Doc != nil {
			(, edge.Field_Doc, -1, .Doc)
		}
		walkList(, edge.Field_Names, .Names)
		if .Type != nil {
			(, edge.Field_Type, -1, .Type)
		}
		if .Tag != nil {
			(, edge.Field_Tag, -1, .Tag)
		}
		if .Comment != nil {
			(, edge.Field_Comment, -1, .Comment)
		}

	case *ast.FieldList:
		walkList(, edge.FieldList_List, .List)

	// Expressions
	case *ast.BadExpr, *ast.Ident, *ast.BasicLit:
		// nothing to do

	case *ast.Ellipsis:
		if .Elt != nil {
			(, edge.Ellipsis_Elt, -1, .Elt)
		}

	case *ast.FuncLit:
		(, edge.FuncLit_Type, -1, .Type)
		(, edge.FuncLit_Body, -1, .Body)

	case *ast.CompositeLit:
		if .Type != nil {
			(, edge.CompositeLit_Type, -1, .Type)
		}
		walkList(, edge.CompositeLit_Elts, .Elts)

	case *ast.ParenExpr:
		(, edge.ParenExpr_X, -1, .X)

	case *ast.SelectorExpr:
		(, edge.SelectorExpr_X, -1, .X)
		(, edge.SelectorExpr_Sel, -1, .Sel)

	case *ast.IndexExpr:
		(, edge.IndexExpr_X, -1, .X)
		(, edge.IndexExpr_Index, -1, .Index)

	case *ast.IndexListExpr:
		(, edge.IndexListExpr_X, -1, .X)
		walkList(, edge.IndexListExpr_Indices, .Indices)

	case *ast.SliceExpr:
		(, edge.SliceExpr_X, -1, .X)
		if .Low != nil {
			(, edge.SliceExpr_Low, -1, .Low)
		}
		if .High != nil {
			(, edge.SliceExpr_High, -1, .High)
		}
		if .Max != nil {
			(, edge.SliceExpr_Max, -1, .Max)
		}

	case *ast.TypeAssertExpr:
		(, edge.TypeAssertExpr_X, -1, .X)
		if .Type != nil {
			(, edge.TypeAssertExpr_Type, -1, .Type)
		}

	case *ast.CallExpr:
		(, edge.CallExpr_Fun, -1, .Fun)
		walkList(, edge.CallExpr_Args, .Args)

	case *ast.StarExpr:
		(, edge.StarExpr_X, -1, .X)

	case *ast.UnaryExpr:
		(, edge.UnaryExpr_X, -1, .X)

	case *ast.BinaryExpr:
		(, edge.BinaryExpr_X, -1, .X)
		(, edge.BinaryExpr_Y, -1, .Y)

	case *ast.KeyValueExpr:
		(, edge.KeyValueExpr_Key, -1, .Key)
		(, edge.KeyValueExpr_Value, -1, .Value)

	// Types
	case *ast.ArrayType:
		if .Len != nil {
			(, edge.ArrayType_Len, -1, .Len)
		}
		(, edge.ArrayType_Elt, -1, .Elt)

	case *ast.StructType:
		(, edge.StructType_Fields, -1, .Fields)

	case *ast.FuncType:
		if .TypeParams != nil {
			(, edge.FuncType_TypeParams, -1, .TypeParams)
		}
		if .Params != nil {
			(, edge.FuncType_Params, -1, .Params)
		}
		if .Results != nil {
			(, edge.FuncType_Results, -1, .Results)
		}

	case *ast.InterfaceType:
		(, edge.InterfaceType_Methods, -1, .Methods)

	case *ast.MapType:
		(, edge.MapType_Key, -1, .Key)
		(, edge.MapType_Value, -1, .Value)

	case *ast.ChanType:
		(, edge.ChanType_Value, -1, .Value)

	// Statements
	case *ast.BadStmt:
		// nothing to do

	case *ast.DeclStmt:
		(, edge.DeclStmt_Decl, -1, .Decl)

	case *ast.EmptyStmt:
		// nothing to do

	case *ast.LabeledStmt:
		(, edge.LabeledStmt_Label, -1, .Label)
		(, edge.LabeledStmt_Stmt, -1, .Stmt)

	case *ast.ExprStmt:
		(, edge.ExprStmt_X, -1, .X)

	case *ast.SendStmt:
		(, edge.SendStmt_Chan, -1, .Chan)
		(, edge.SendStmt_Value, -1, .Value)

	case *ast.IncDecStmt:
		(, edge.IncDecStmt_X, -1, .X)

	case *ast.AssignStmt:
		walkList(, edge.AssignStmt_Lhs, .Lhs)
		walkList(, edge.AssignStmt_Rhs, .Rhs)

	case *ast.GoStmt:
		(, edge.GoStmt_Call, -1, .Call)

	case *ast.DeferStmt:
		(, edge.DeferStmt_Call, -1, .Call)

	case *ast.ReturnStmt:
		walkList(, edge.ReturnStmt_Results, .Results)

	case *ast.BranchStmt:
		if .Label != nil {
			(, edge.BranchStmt_Label, -1, .Label)
		}

	case *ast.BlockStmt:
		walkList(, edge.BlockStmt_List, .List)

	case *ast.IfStmt:
		if .Init != nil {
			(, edge.IfStmt_Init, -1, .Init)
		}
		(, edge.IfStmt_Cond, -1, .Cond)
		(, edge.IfStmt_Body, -1, .Body)
		if .Else != nil {
			(, edge.IfStmt_Else, -1, .Else)
		}

	case *ast.CaseClause:
		walkList(, edge.CaseClause_List, .List)
		walkList(, edge.CaseClause_Body, .Body)

	case *ast.SwitchStmt:
		if .Init != nil {
			(, edge.SwitchStmt_Init, -1, .Init)
		}
		if .Tag != nil {
			(, edge.SwitchStmt_Tag, -1, .Tag)
		}
		(, edge.SwitchStmt_Body, -1, .Body)

	case *ast.TypeSwitchStmt:
		if .Init != nil {
			(, edge.TypeSwitchStmt_Init, -1, .Init)
		}
		(, edge.TypeSwitchStmt_Assign, -1, .Assign)
		(, edge.TypeSwitchStmt_Body, -1, .Body)

	case *ast.CommClause:
		if .Comm != nil {
			(, edge.CommClause_Comm, -1, .Comm)
		}
		walkList(, edge.CommClause_Body, .Body)

	case *ast.SelectStmt:
		(, edge.SelectStmt_Body, -1, .Body)

	case *ast.ForStmt:
		if .Init != nil {
			(, edge.ForStmt_Init, -1, .Init)
		}
		if .Cond != nil {
			(, edge.ForStmt_Cond, -1, .Cond)
		}
		if .Post != nil {
			(, edge.ForStmt_Post, -1, .Post)
		}
		(, edge.ForStmt_Body, -1, .Body)

	case *ast.RangeStmt:
		if .Key != nil {
			(, edge.RangeStmt_Key, -1, .Key)
		}
		if .Value != nil {
			(, edge.RangeStmt_Value, -1, .Value)
		}
		(, edge.RangeStmt_X, -1, .X)
		(, edge.RangeStmt_Body, -1, .Body)

	// Declarations
	case *ast.ImportSpec:
		if .Doc != nil {
			(, edge.ImportSpec_Doc, -1, .Doc)
		}
		if .Name != nil {
			(, edge.ImportSpec_Name, -1, .Name)
		}
		(, edge.ImportSpec_Path, -1, .Path)
		if .Comment != nil {
			(, edge.ImportSpec_Comment, -1, .Comment)
		}

	case *ast.ValueSpec:
		if .Doc != nil {
			(, edge.ValueSpec_Doc, -1, .Doc)
		}
		walkList(, edge.ValueSpec_Names, .Names)
		if .Type != nil {
			(, edge.ValueSpec_Type, -1, .Type)
		}
		walkList(, edge.ValueSpec_Values, .Values)
		if .Comment != nil {
			(, edge.ValueSpec_Comment, -1, .Comment)
		}

	case *ast.TypeSpec:
		if .Doc != nil {
			(, edge.TypeSpec_Doc, -1, .Doc)
		}
		(, edge.TypeSpec_Name, -1, .Name)
		if .TypeParams != nil {
			(, edge.TypeSpec_TypeParams, -1, .TypeParams)
		}
		(, edge.TypeSpec_Type, -1, .Type)
		if .Comment != nil {
			(, edge.TypeSpec_Comment, -1, .Comment)
		}

	case *ast.BadDecl:
		// nothing to do

	case *ast.GenDecl:
		if .Doc != nil {
			(, edge.GenDecl_Doc, -1, .Doc)
		}
		walkList(, edge.GenDecl_Specs, .Specs)

	case *ast.FuncDecl:
		if .Doc != nil {
			(, edge.FuncDecl_Doc, -1, .Doc)
		}
		if .Recv != nil {
			(, edge.FuncDecl_Recv, -1, .Recv)
		}
		(, edge.FuncDecl_Name, -1, .Name)
		(, edge.FuncDecl_Type, -1, .Type)
		if .Body != nil {
			(, edge.FuncDecl_Body, -1, .Body)
		}

	case *ast.File:
		if .Doc != nil {
			(, edge.File_Doc, -1, .Doc)
		}
		(, edge.File_Name, -1, .Name)
		walkList(, edge.File_Decls, .Decls)
		// don't walk n.Comments - they have been
		// visited already through the individual
		// nodes

	default:
		// (includes *ast.Package)
		panic(fmt.Sprintf("Walk: unexpected node type %T", ))
	}

	.pop()
}