From 26f53e55e363727209a7a97854306b54b71cb3a5 Mon Sep 17 00:00:00 2001 From: Matt <85322+mattmassicotte@users.noreply.github.com> Date: Fri, 10 May 2024 10:30:10 -0400 Subject: [PATCH] RangeMutation adjustments needed for #44 --- Package.resolved | 2 +- Sources/RangeState/RangeProcessor.swift | 33 ++++++++++--- .../RangeStateTests/RangeProcessorTests.swift | 49 +++++++++++++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/Package.resolved b/Package.resolved index 3e9cf0f..af2dfba 100644 --- a/Package.resolved +++ b/Package.resolved @@ -14,7 +14,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/ChimeHQ/SwiftTreeSitter", "state" : { - "revision" : "7ccb58219c3e928bf1938dd43d33fd349dc71808" + "revision" : "b01904a3737649c1d8520106bbb285724fe5b0bb" } } ], diff --git a/Sources/RangeState/RangeProcessor.swift b/Sources/RangeState/RangeProcessor.swift index 92937c2..e05dd18 100644 --- a/Sources/RangeState/RangeProcessor.swift +++ b/Sources/RangeState/RangeProcessor.swift @@ -184,19 +184,40 @@ extension RangeProcessor { } public func didChangeContent(_ mutation: RangeMutation) { - guard processed(mutation.range) else { return } - - processMutation(mutation) + didChangeContent(in: mutation.range, delta: mutation.delta) } public func didChangeContent(in range: NSRange, delta: Int) { - let limit = maximumProcessedLocation ?? 0 + if processed(range.location) == false { + return + } + + guard let limit = maximumProcessedLocation else { + return + } precondition(limit >= 0) - let mutation = RangeMutation(range: range, delta: delta, limit: limit) + let visibleRange = range.clamped(to: limit) + let effectiveLimit = limit + let clampLength = range.upperBound - visibleRange.upperBound - didChangeContent(mutation) + precondition(clampLength >= 0) + + // The logic to adjust the delta is pretty tricky. + let visibleDelta: Int + + if clampLength == 0 { + visibleDelta = delta + } else if delta < 0 { + visibleDelta = max(delta + clampLength, 0) + } else { + visibleDelta = 0 + } + + let mutation = RangeMutation(range: visibleRange, delta: visibleDelta, limit: effectiveLimit) + + processMutation(mutation) } private func processMutation(_ mutation: RangeMutation) { diff --git a/Tests/RangeStateTests/RangeProcessorTests.swift b/Tests/RangeStateTests/RangeProcessorTests.swift index 890d17f..4f9a06f 100644 --- a/Tests/RangeStateTests/RangeProcessorTests.swift +++ b/Tests/RangeStateTests/RangeProcessorTests.swift @@ -176,4 +176,53 @@ final class RangeProcessorTests: XCTestCase { XCTAssertEqual(handler.mutations, expected) } + + @MainActor + func testInsertWithNothingProcessed() { + let processor = RangeProcessor( + configuration: .init( + lengthProvider: { 10 }, + changeHandler: { _, _ in fatalError() } + ) + ) + + processor.didChangeContent(in: NSRange(0..<10), delta: 10) + } + + @MainActor + func testChangeThatOverlapsUnprocessedRegion() { + let exp = expectation(description: "mutation") + exp.expectedFulfillmentCount = 2 + + let handler = MockChangeHandler() + + handler.changeCompleted = { + exp.fulfill() + } + + let content = StringContent(string: "abcdefghij") + + let processor = RangeProcessor( + configuration: .init( + lengthProvider: { content.currentLength }, + changeHandler: handler.handleChange + ) + ) + + // process half + XCTAssertTrue(processor.processLocation(5, mode: .required)) + XCTAssertTrue(processor.processed(5)) + + // change everything + processor.didChangeContent(in: NSRange(0..<10), delta: 0) + + wait(for: [exp], enforceOrder: true) + + let expected = [ + RangeMutation(range: NSRange(0..<0), delta: 5, limit: nil), + RangeMutation(range: NSRange(0..<5), delta: 0, limit: 5), + ] + + XCTAssertEqual(handler.mutations, expected) + } }