// Copyright 2024 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.

//go:build go1.23

package inspector

import (
	
	
)

// PreorderSeq returns an iterator that visits all the
// nodes of the files supplied to [New] in depth-first order.
// It visits each node n before n's children.
// The complete traversal sequence is determined by ast.Inspect.
//
// The types argument, if non-empty, enables type-based filtering:
// only nodes whose type matches an element of the types slice are
// included in the sequence.
//
// Example:
//
//	for call := range in.PreorderSeq((*ast.CallExpr)(nil)) { ... }
//
// The [All] function is more convenient if there is exactly one node type:
//
//	for call := range All[*ast.CallExpr](in) { ... }
//
// See also the newer and more flexible [Cursor] API, which lets you
// start the traversal at an arbitrary node, and reports each matching
// node by its Cursor, enabling easier navigation.
// The above example would be written thus:
//
//	for curCall := range in.Root().Preorder((*ast.CallExpr)(nil)) {
//		call := curCall.Node().(*ast.CallExpr)
//		...
//	}
func ( *Inspector) ( ...ast.Node) iter.Seq[ast.Node] {

	// This implementation is identical to Preorder,
	// except that it supports breaking out of the loop.

	return func( func(ast.Node) bool) {
		 := maskOf()
		for  := int32(0);  < int32(len(.events)); {
			 := .events[]
			if .index >  {
				// push
				if .typ& != 0 {
					if !(.node) {
						break
					}
				}
				 := .index
				if .events[].typ& == 0 {
					// Subtrees do not contain types: skip them and pop.
					 =  + 1
					continue
				}
			}
			++
		}
	}
}

// All[N] returns an iterator over all the nodes of type N.
// N must be a pointer-to-struct type that implements ast.Node.
//
// Example:
//
//	for call := range All[*ast.CallExpr](in) { ... }
//
// See also the newer and more flexible [Cursor] API, which lets you
// start the traversal at an arbitrary node, and reports each matching
// node by its Cursor, enabling easier navigation.
// The above example would be written thus:
//
//	for curCall := range in.Root().Preorder((*ast.CallExpr)(nil)) {
//		call := curCall.Node().(*ast.CallExpr)
//		...
//	}
func [ interface {
	*
	ast.Node
},  any]( *Inspector) iter.Seq[] {

	// To avoid additional dynamic call overheads,
	// we duplicate rather than call the logic of PreorderSeq.

	 := typeOf(()(nil))
	return func( func() bool) {
		for  := int32(0);  < int32(len(.events)); {
			 := .events[]
			if .index >  {
				// push
				if .typ& != 0 {
					if !(.node.()) {
						break
					}
				}
				 := .index
				if .events[].typ& == 0 {
					// Subtrees do not contain types: skip them and pop.
					 =  + 1
					continue
				}
			}
			++
		}
	}
}