github.com/alecthomas/kong@v0.9.1-0.20240410131203-2ab5733f1179/visit.go (about)

     1  package kong
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  // Next should be called by Visitor to proceed with the walk.
     8  //
     9  // The walk will terminate if "err" is non-nil.
    10  type Next func(err error) error
    11  
    12  // Visitor can be used to walk all nodes in the model.
    13  type Visitor func(node Visitable, next Next) error
    14  
    15  // Visit all nodes.
    16  func Visit(node Visitable, visitor Visitor) error {
    17  	return visitor(node, func(err error) error {
    18  		if err != nil {
    19  			return err
    20  		}
    21  		switch node := node.(type) {
    22  		case *Application:
    23  			return visitNodeChildren(node.Node, visitor)
    24  		case *Node:
    25  			return visitNodeChildren(node, visitor)
    26  		case *Value:
    27  		case *Flag:
    28  			return Visit(node.Value, visitor)
    29  		default:
    30  			panic(fmt.Sprintf("unsupported node type %T", node))
    31  		}
    32  		return nil
    33  	})
    34  }
    35  
    36  func visitNodeChildren(node *Node, visitor Visitor) error {
    37  	if node.Argument != nil {
    38  		if err := Visit(node.Argument, visitor); err != nil {
    39  			return err
    40  		}
    41  	}
    42  	for _, flag := range node.Flags {
    43  		if err := Visit(flag, visitor); err != nil {
    44  			return err
    45  		}
    46  	}
    47  	for _, pos := range node.Positional {
    48  		if err := Visit(pos, visitor); err != nil {
    49  			return err
    50  		}
    51  	}
    52  	for _, child := range node.Children {
    53  		if err := Visit(child, visitor); err != nil {
    54  			return err
    55  		}
    56  	}
    57  	return nil
    58  }