container_node.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package containernode
  2. import (
  3. "math/rand"
  4. "sort"
  5. "github.com/onsi/ginkgo/internal/leafnodes"
  6. "github.com/onsi/ginkgo/types"
  7. )
  8. type subjectOrContainerNode struct {
  9. containerNode *ContainerNode
  10. subjectNode leafnodes.SubjectNode
  11. }
  12. func (n subjectOrContainerNode) text() string {
  13. if n.containerNode != nil {
  14. return n.containerNode.Text()
  15. } else {
  16. return n.subjectNode.Text()
  17. }
  18. }
  19. type CollatedNodes struct {
  20. Containers []*ContainerNode
  21. Subject leafnodes.SubjectNode
  22. }
  23. type ContainerNode struct {
  24. text string
  25. flag types.FlagType
  26. codeLocation types.CodeLocation
  27. setupNodes []leafnodes.BasicNode
  28. subjectAndContainerNodes []subjectOrContainerNode
  29. }
  30. func New(text string, flag types.FlagType, codeLocation types.CodeLocation) *ContainerNode {
  31. return &ContainerNode{
  32. text: text,
  33. flag: flag,
  34. codeLocation: codeLocation,
  35. }
  36. }
  37. func (container *ContainerNode) Shuffle(r *rand.Rand) {
  38. sort.Sort(container)
  39. permutation := r.Perm(len(container.subjectAndContainerNodes))
  40. shuffledNodes := make([]subjectOrContainerNode, len(container.subjectAndContainerNodes))
  41. for i, j := range permutation {
  42. shuffledNodes[i] = container.subjectAndContainerNodes[j]
  43. }
  44. container.subjectAndContainerNodes = shuffledNodes
  45. }
  46. func (node *ContainerNode) BackPropagateProgrammaticFocus() bool {
  47. if node.flag == types.FlagTypePending {
  48. return false
  49. }
  50. shouldUnfocus := false
  51. for _, subjectOrContainerNode := range node.subjectAndContainerNodes {
  52. if subjectOrContainerNode.containerNode != nil {
  53. shouldUnfocus = subjectOrContainerNode.containerNode.BackPropagateProgrammaticFocus() || shouldUnfocus
  54. } else {
  55. shouldUnfocus = (subjectOrContainerNode.subjectNode.Flag() == types.FlagTypeFocused) || shouldUnfocus
  56. }
  57. }
  58. if shouldUnfocus {
  59. if node.flag == types.FlagTypeFocused {
  60. node.flag = types.FlagTypeNone
  61. }
  62. return true
  63. }
  64. return node.flag == types.FlagTypeFocused
  65. }
  66. func (node *ContainerNode) Collate() []CollatedNodes {
  67. return node.collate([]*ContainerNode{})
  68. }
  69. func (node *ContainerNode) collate(enclosingContainers []*ContainerNode) []CollatedNodes {
  70. collated := make([]CollatedNodes, 0)
  71. containers := make([]*ContainerNode, len(enclosingContainers))
  72. copy(containers, enclosingContainers)
  73. containers = append(containers, node)
  74. for _, subjectOrContainer := range node.subjectAndContainerNodes {
  75. if subjectOrContainer.containerNode != nil {
  76. collated = append(collated, subjectOrContainer.containerNode.collate(containers)...)
  77. } else {
  78. collated = append(collated, CollatedNodes{
  79. Containers: containers,
  80. Subject: subjectOrContainer.subjectNode,
  81. })
  82. }
  83. }
  84. return collated
  85. }
  86. func (node *ContainerNode) PushContainerNode(container *ContainerNode) {
  87. node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{containerNode: container})
  88. }
  89. func (node *ContainerNode) PushSubjectNode(subject leafnodes.SubjectNode) {
  90. node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{subjectNode: subject})
  91. }
  92. func (node *ContainerNode) PushSetupNode(setupNode leafnodes.BasicNode) {
  93. node.setupNodes = append(node.setupNodes, setupNode)
  94. }
  95. func (node *ContainerNode) SetupNodesOfType(nodeType types.SpecComponentType) []leafnodes.BasicNode {
  96. nodes := []leafnodes.BasicNode{}
  97. for _, setupNode := range node.setupNodes {
  98. if setupNode.Type() == nodeType {
  99. nodes = append(nodes, setupNode)
  100. }
  101. }
  102. return nodes
  103. }
  104. func (node *ContainerNode) Text() string {
  105. return node.text
  106. }
  107. func (node *ContainerNode) CodeLocation() types.CodeLocation {
  108. return node.codeLocation
  109. }
  110. func (node *ContainerNode) Flag() types.FlagType {
  111. return node.flag
  112. }
  113. //sort.Interface
  114. func (node *ContainerNode) Len() int {
  115. return len(node.subjectAndContainerNodes)
  116. }
  117. func (node *ContainerNode) Less(i, j int) bool {
  118. return node.subjectAndContainerNodes[i].text() < node.subjectAndContainerNodes[j].text()
  119. }
  120. func (node *ContainerNode) Swap(i, j int) {
  121. node.subjectAndContainerNodes[i], node.subjectAndContainerNodes[j] = node.subjectAndContainerNodes[j], node.subjectAndContainerNodes[i]
  122. }