Skip to content

Commit bf3169f

Browse files
committed
Fix splitToSingleLineRanges
Previously, subsequent newlines would cause positions computed by splitToSingleLineRanges to become incorrect if omittingEmptyRanges was set. Additionally, add a test case for multi-line range splitting
1 parent 685944d commit bf3169f

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

Sources/SourceKitLSP/Swift/SyntaxHighlightingTokenParser.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,14 @@ extension Range where Bound == Position {
207207
/// Splits a potentially multi-line range to multiple single-line ranges.
208208
fileprivate func splitToSingleLineRanges(
209209
in snapshot: DocumentSnapshot,
210-
omittingEmptyRanges: Bool = true
210+
omittingEmptyRange: Bool = true
211211
) -> [Self] {
212+
if omittingEmptyRange && isEmpty {
213+
return []
214+
}
215+
212216
if lowerBound.line == upperBound.line {
213-
return omittingEmptyRanges && isEmpty ? [] : [self]
217+
return [self]
214218
}
215219

216220
guard let startIndex = snapshot.index(of: lowerBound),
@@ -219,7 +223,7 @@ extension Range where Bound == Position {
219223
}
220224

221225
let text = snapshot.text[startIndex..<endIndex]
222-
let lines = text.split(separator: "\n", omittingEmptySubsequences: omittingEmptyRanges)
226+
let lines = text.split(separator: "\n", omittingEmptySubsequences: false)
223227

224228
return lines
225229
.enumerated()
@@ -235,4 +239,12 @@ extension Range where Bound == Position {
235239
return start..<end
236240
}
237241
}
242+
243+
/// **Public for testing**
244+
public func _splitToSingleLineRanges(
245+
in snapshot: DocumentSnapshot,
246+
omittingEmptyRange: Bool = true
247+
) -> [Self] {
248+
splitToSingleLineRanges(in: snapshot, omittingEmptyRange: omittingEmptyRange)
249+
}
238250
}

Tests/SourceKitLSPTests/SemanticTokensTests.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,42 @@ final class SemanticTokensTests: XCTestCase {
188188
XCTAssertEqual(decoded, tokens)
189189
}
190190

191+
func testRangeSplitting() {
192+
let text = """
193+
struct X {
194+
let x: Int
195+
let y: String
196+
197+
198+
}
199+
"""
200+
openDocument(text: text)
201+
202+
guard let snapshot = connection.server?.workspace?.documentManager.latestSnapshot(uri) else {
203+
fatalError("Could not fetch document snapshot for \(#function)")
204+
}
205+
206+
let empty = Position(line: 0, utf16index: 1)..<Position(line: 0, utf16index: 1)
207+
XCTAssertEqual(empty._splitToSingleLineRanges(in: snapshot, omittingEmptyRange: true), [])
208+
XCTAssertEqual(empty._splitToSingleLineRanges(in: snapshot, omittingEmptyRange: false), [empty])
209+
210+
for omittingEmptyRange in [false, true] {
211+
let multiLine = Position(line: 1, utf16index: 6)..<Position(line: 2, utf16index: 7)
212+
XCTAssertEqual(multiLine._splitToSingleLineRanges(in: snapshot, omittingEmptyRange: omittingEmptyRange), [
213+
Position(line: 1, utf16index: 6)..<Position(line: 1, utf16index: 12),
214+
Position(line: 2, utf16index: 0)..<Position(line: 2, utf16index: 7),
215+
])
216+
217+
let emptyLines = Position(line: 2, utf16index: 14)..<Position(line: 5, utf16index: 1)
218+
XCTAssertEqual(emptyLines._splitToSingleLineRanges(in: snapshot, omittingEmptyRange: omittingEmptyRange), [
219+
Position(line: 2, utf16index: 14)..<Position(line: 2, utf16index: 15),
220+
Position(line: 3, utf16index: 0)..<Position(line: 3, utf16index: 0),
221+
Position(line: 4, utf16index: 0)..<Position(line: 4, utf16index: 0),
222+
Position(line: 5, utf16index: 0)..<Position(line: 5, utf16index: 1),
223+
])
224+
}
225+
}
226+
191227
func testEmpty() {
192228
let text = ""
193229
let tokens = openAndPerformSemanticTokensRequest(text: text)

Tests/SourceKitLSPTests/XCTestManifests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ extension SemanticTokensTests {
166166
("testInsertSpaceBeforeToken", testInsertSpaceBeforeToken),
167167
("testIntArrayCoding", testIntArrayCoding),
168168
("testRanged", testRanged),
169+
("testRangeSplitting", testRangeSplitting),
169170
("testRemoveNewline", testRemoveNewline),
170171
("testReplaceUntilEndOfToken", testReplaceUntilEndOfToken),
171172
("testReplaceUntilMiddleOfToken", testReplaceUntilMiddleOfToken),

0 commit comments

Comments
 (0)