| package containernode |
| |
| import ( |
| "math/rand" |
| "sort" |
| |
| "github.com/onsi/ginkgo/internal/leafnodes" |
| "github.com/onsi/ginkgo/types" |
| ) |
| |
| type subjectOrContainerNode struct { |
| containerNode *ContainerNode |
| subjectNode leafnodes.SubjectNode |
| } |
| |
| func (n subjectOrContainerNode) text() string { |
| if n.containerNode != nil { |
| return n.containerNode.Text() |
| } else { |
| return n.subjectNode.Text() |
| } |
| } |
| |
| type CollatedNodes struct { |
| Containers []*ContainerNode |
| Subject leafnodes.SubjectNode |
| } |
| |
| type ContainerNode struct { |
| text string |
| flag types.FlagType |
| codeLocation types.CodeLocation |
| |
| setupNodes []leafnodes.BasicNode |
| subjectAndContainerNodes []subjectOrContainerNode |
| } |
| |
| func New(text string, flag types.FlagType, codeLocation types.CodeLocation) *ContainerNode { |
| return &ContainerNode{ |
| text: text, |
| flag: flag, |
| codeLocation: codeLocation, |
| } |
| } |
| |
| func (container *ContainerNode) Shuffle(r *rand.Rand) { |
| sort.Sort(container) |
| permutation := r.Perm(len(container.subjectAndContainerNodes)) |
| shuffledNodes := make([]subjectOrContainerNode, len(container.subjectAndContainerNodes)) |
| for i, j := range permutation { |
| shuffledNodes[i] = container.subjectAndContainerNodes[j] |
| } |
| container.subjectAndContainerNodes = shuffledNodes |
| } |
| |
| func (node *ContainerNode) BackPropagateProgrammaticFocus() bool { |
| if node.flag == types.FlagTypePending { |
| return false |
| } |
| |
| shouldUnfocus := false |
| for _, subjectOrContainerNode := range node.subjectAndContainerNodes { |
| if subjectOrContainerNode.containerNode != nil { |
| shouldUnfocus = subjectOrContainerNode.containerNode.BackPropagateProgrammaticFocus() || shouldUnfocus |
| } else { |
| shouldUnfocus = (subjectOrContainerNode.subjectNode.Flag() == types.FlagTypeFocused) || shouldUnfocus |
| } |
| } |
| |
| if shouldUnfocus { |
| if node.flag == types.FlagTypeFocused { |
| node.flag = types.FlagTypeNone |
| } |
| return true |
| } |
| |
| return node.flag == types.FlagTypeFocused |
| } |
| |
| func (node *ContainerNode) Collate() []CollatedNodes { |
| return node.collate([]*ContainerNode{}) |
| } |
| |
| func (node *ContainerNode) collate(enclosingContainers []*ContainerNode) []CollatedNodes { |
| collated := make([]CollatedNodes, 0) |
| |
| containers := make([]*ContainerNode, len(enclosingContainers)) |
| copy(containers, enclosingContainers) |
| containers = append(containers, node) |
| |
| for _, subjectOrContainer := range node.subjectAndContainerNodes { |
| if subjectOrContainer.containerNode != nil { |
| collated = append(collated, subjectOrContainer.containerNode.collate(containers)...) |
| } else { |
| collated = append(collated, CollatedNodes{ |
| Containers: containers, |
| Subject: subjectOrContainer.subjectNode, |
| }) |
| } |
| } |
| |
| return collated |
| } |
| |
| func (node *ContainerNode) PushContainerNode(container *ContainerNode) { |
| node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{containerNode: container}) |
| } |
| |
| func (node *ContainerNode) PushSubjectNode(subject leafnodes.SubjectNode) { |
| node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{subjectNode: subject}) |
| } |
| |
| func (node *ContainerNode) PushSetupNode(setupNode leafnodes.BasicNode) { |
| node.setupNodes = append(node.setupNodes, setupNode) |
| } |
| |
| func (node *ContainerNode) SetupNodesOfType(nodeType types.SpecComponentType) []leafnodes.BasicNode { |
| nodes := []leafnodes.BasicNode{} |
| for _, setupNode := range node.setupNodes { |
| if setupNode.Type() == nodeType { |
| nodes = append(nodes, setupNode) |
| } |
| } |
| return nodes |
| } |
| |
| func (node *ContainerNode) Text() string { |
| return node.text |
| } |
| |
| func (node *ContainerNode) CodeLocation() types.CodeLocation { |
| return node.codeLocation |
| } |
| |
| func (node *ContainerNode) Flag() types.FlagType { |
| return node.flag |
| } |
| |
| //sort.Interface |
| |
| func (node *ContainerNode) Len() int { |
| return len(node.subjectAndContainerNodes) |
| } |
| |
| func (node *ContainerNode) Less(i, j int) bool { |
| return node.subjectAndContainerNodes[i].text() < node.subjectAndContainerNodes[j].text() |
| } |
| |
| func (node *ContainerNode) Swap(i, j int) { |
| node.subjectAndContainerNodes[i], node.subjectAndContainerNodes[j] = node.subjectAndContainerNodes[j], node.subjectAndContainerNodes[i] |
| } |