@@ -27,36 +27,43 @@ func (s *SortableSpecs) Swap(i, j int) { s.Indexes[i], s.Indexes[j] = s.Indexes[
27
27
func (s * SortableSpecs ) Less (i , j int ) bool {
28
28
a , b := s.Specs [s.Indexes [i ]], s.Specs [s.Indexes [j ]]
29
29
30
- firstOrderedA := a .Nodes .FirstNodeMarkedOrdered ()
31
- firstOrderedB := b .Nodes .FirstNodeMarkedOrdered ()
32
- if firstOrderedA .ID == firstOrderedB .ID && ! firstOrderedA .IsZero () {
33
- // strictly preserve order in ordered containers. ID will track this as IDs are generated monotonically
34
- return a .FirstNodeWithType (types .NodeTypeIt ).ID < b .FirstNodeWithType (types .NodeTypeIt ).ID
30
+ aNodes , bNodes := a .Nodes .WithType (types .NodeTypesForContainerAndIt ), b .Nodes .WithType (types .NodeTypesForContainerAndIt )
31
+
32
+ firstOrderedAIdx , firstOrderedBIdx := aNodes .IndexOfFirstNodeMarkedOrdered (), bNodes .IndexOfFirstNodeMarkedOrdered ()
33
+ if firstOrderedAIdx > - 1 && firstOrderedBIdx > - 1 && aNodes [firstOrderedAIdx ].ID == bNodes [firstOrderedBIdx ].ID {
34
+ // strictly preserve order within an ordered containers. ID will track this as IDs are generated monotonically
35
+ return aNodes .FirstNodeWithType (types .NodeTypeIt ).ID < bNodes .FirstNodeWithType (types .NodeTypeIt ).ID
36
+ }
37
+
38
+ // if either spec is in an ordered container - only use the nodes up to the outermost ordered container
39
+ if firstOrderedAIdx > - 1 {
40
+ aNodes = aNodes [:firstOrderedAIdx + 1 ]
41
+ }
42
+ if firstOrderedBIdx > - 1 {
43
+ bNodes = bNodes [:firstOrderedBIdx + 1 ]
35
44
}
36
45
37
- aCLs := a .Nodes .WithType (types .NodeTypesForContainerAndIt ).CodeLocations ()
38
- bCLs := b .Nodes .WithType (types .NodeTypesForContainerAndIt ).CodeLocations ()
39
- for i := 0 ; i < len (aCLs ) && i < len (bCLs ); i ++ {
40
- aCL , bCL := aCLs [i ], bCLs [i ]
41
- if aCL .FileName < bCL .FileName {
42
- return true
43
- } else if aCL .FileName > bCL .FileName {
44
- return false
46
+ for i := 0 ; i < len (aNodes ) && i < len (bNodes ); i ++ {
47
+ aCL , bCL := aNodes [i ].CodeLocation , bNodes [i ].CodeLocation
48
+ if aCL .FileName != bCL .FileName {
49
+ return aCL .FileName < bCL .FileName
45
50
}
46
- if aCL .LineNumber < bCL .LineNumber {
47
- return true
48
- } else if aCL .LineNumber > bCL .LineNumber {
49
- return false
51
+ if aCL .LineNumber != bCL .LineNumber {
52
+ return aCL .LineNumber < bCL .LineNumber
50
53
}
51
54
}
52
55
// either everything is equal or we have different lengths of CLs
53
- if len (aCLs ) < len (bCLs ) {
54
- return true
55
- } else if len (aCLs ) > len (bCLs ) {
56
- return false
56
+ if len (aNodes ) != len (bNodes ) {
57
+ return len (aNodes ) < len (bNodes )
57
58
}
58
59
// ok, now we are sure everything was equal. so we use the spec text to break ties
59
- return a .Text () < b .Text ()
60
+ for i := 0 ; i < len (aNodes ); i ++ {
61
+ if aNodes [i ].Text != bNodes [i ].Text {
62
+ return aNodes [i ].Text < bNodes [i ].Text
63
+ }
64
+ }
65
+ // ok, all those texts were equal. we'll use the ID of the most deeply nested node as a last resort
66
+ return aNodes [len (aNodes )- 1 ].ID < bNodes [len (bNodes )- 1 ].ID
60
67
}
61
68
62
69
type GroupedSpecIndices []SpecIndices
0 commit comments