Skip to content

Commit 0f2cbbb

Browse files
committed
Fix End Of Doc Invalidation Bug
1 parent 214f2a2 commit 0f2cbbb

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

Sources/CodeEditTextView/TextLayoutManager/TextLayoutManager+Invalidation.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ extension TextLayoutManager {
2525
linePosition.data.setNeedsLayout()
2626
}
2727

28+
// Special case where we've deleted from the very end, `linesInRange` correctly does not return any lines
29+
// So we need to invalidate the last line specifically.
30+
if range.location == textStorage?.length, !lineStorage.isEmpty {
31+
lineStorage.last?.data.setNeedsLayout()
32+
}
33+
2834
layoutView?.needsLayout = true
2935
}
3036

Tests/CodeEditTextViewTests/LayoutManager/TextLayoutManagerTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,20 @@ struct TextLayoutManagerTests {
250250
}
251251
}
252252
}
253+
254+
@Test
255+
func editingEndOfDocumentInvalidatesLastLine() throws {
256+
// Setup a slightly longer final line
257+
textStorage.replaceCharacters(in: NSRange(location: 7, length: 0), with: "EFGH")
258+
layoutManager.layoutLines(in: NSRect(x: 0, y: 0, width: 1000, height: 1000))
259+
260+
textStorage.replaceCharacters(in: NSRange(location: 10, length: 1), with: "")
261+
let invalidatedLineIds = layoutManager.layoutLines(in: NSRect(x: 0, y: 0, width: 1000, height: 1000))
262+
263+
let expectedLineIds = Array(
264+
layoutManager.lineStorage.linesInRange(NSRange(location: 6, length: 0))
265+
).map { $0.data.id }
266+
267+
#expect(invalidatedLineIds.isSuperset(of: Set(expectedLineIds)))
268+
}
253269
}

0 commit comments

Comments
 (0)