package internal import "github.com/onsi/ginkgo/v2/types" type TreeNode struct { Node Node Parent *TreeNode Children TreeNodes } func (tn *TreeNode) AppendChild(child *TreeNode) { tn.Children = append(tn.Children, child) child.Parent = tn } func (tn *TreeNode) AncestorNodeChain() Nodes { if tn.Parent == nil || tn.Parent.Node.IsZero() { return Nodes{tn.Node} } return append(tn.Parent.AncestorNodeChain(), tn.Node) } type TreeNodes []*TreeNode func (tn TreeNodes) Nodes() Nodes { out := make(Nodes, len(tn)) for i := range tn { out[i] = tn[i].Node } return out } func (tn TreeNodes) WithID(id uint) *TreeNode { for i := range tn { if tn[i].Node.ID == id { return tn[i] } } return nil } func GenerateSpecsFromTreeRoot(tree *TreeNode) Specs { var walkTree func(nestingLevel int, lNodes Nodes, rNodes Nodes, trees TreeNodes) Specs walkTree = func(nestingLevel int, lNodes Nodes, rNodes Nodes, trees TreeNodes) Specs { tests := Specs{} nodes := make(Nodes, len(trees)) for i := range trees { nodes[i] = trees[i].Node nodes[i].NestingLevel = nestingLevel } for i := range nodes { if !nodes[i].NodeType.Is(types.NodeTypesForContainerAndIt) { continue } leftNodes, rightNodes := nodes.SplitAround(nodes[i]) leftNodes = leftNodes.WithoutType(types.NodeTypesForContainerAndIt) rightNodes = rightNodes.WithoutType(types.NodeTypesForContainerAndIt) leftNodes = lNodes.CopyAppend(leftNodes...) rightNodes = rightNodes.CopyAppend(rNodes...) if nodes[i].NodeType.Is(types.NodeTypeIt) { tests = append(tests, Spec{Nodes: leftNodes.CopyAppend(nodes[i]).CopyAppend(rightNodes...)}) } else { treeNode := trees.WithID(nodes[i].ID) tests = append(tests, walkTree(nestingLevel+1, leftNodes.CopyAppend(nodes[i]), rightNodes, treeNode.Children)...) } } return tests } return walkTree(0, Nodes{}, Nodes{}, tree.Children) }