@@ -87,17 +87,35 @@ extension TreeSitterClient {
87
87
cursor: QueryCursor ,
88
88
includedRange: NSRange
89
89
) -> [ HighlightRange ] {
90
+ guard let readCallback else { return [ ] }
91
+ var ranges : [ NSRange : Int ] = [ : ]
90
92
return cursor
93
+ . resolve ( with: . init( textProvider: readCallback) ) // Resolve our cursor against the query
91
94
. flatMap { $0. captures }
92
- . compactMap {
93
- // Sometimes `cursor.setRange` just doesn't work :( so we have to do a redundant check for a valid range
94
- // in the included range
95
- let intersectionRange = $0. range. intersection ( includedRange) ?? . zero
96
- // Check that the capture name is one CESE can parse. If not, ignore it completely.
97
- if intersectionRange. length > 0 , let captureName = CaptureName . fromString ( $0. name) {
98
- return HighlightRange ( range: intersectionRange, capture: captureName)
95
+ . reversed ( ) // SwiftTreeSitter returns captures in the reverse order of what we need to filter with.
96
+ . compactMap { capture in
97
+ let range = capture. range
98
+ let index = capture. index
99
+
100
+ // Lower indexed captures are favored over higher, this is why we reverse it above
101
+ if let existingLevel = ranges [ range] , existingLevel <= index {
102
+ return nil
103
+ }
104
+
105
+ guard let captureName = CaptureName . fromString ( capture. name) else {
106
+ return nil
99
107
}
100
- return nil
108
+
109
+ // Update the filter level to the current index since it's lower and a 'valid' capture
110
+ ranges [ range] = index
111
+
112
+ // Validate range and capture name
113
+ let intersectionRange = range. intersection ( includedRange) ?? . zero
114
+ guard intersectionRange. length > 0 else {
115
+ return nil
116
+ }
117
+
118
+ return HighlightRange ( range: intersectionRange, capture: captureName)
101
119
}
102
120
}
103
121
}
0 commit comments